Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ideas for algorithm to generate random flower

Can anyone suggest any links, ideas or algorithms to generate flowers randomly like the one as my profile pic? The profile pic flower has only a 10 x 10 grid and the algorithm is not truly random. I would also prefer that the new algorithm use a grid of about 500 x 500 or even better, allow the user to pick the size of the grid.

[Plant[][] is declared as int plant[10][10];]

public void generateSimpleSky(){

    for(int w2=0;w2<10;w2++)
        for(int w3=0;w3<10;w3++)
            plant[w2][w3]=5;

}

public void generateSimpleSoil(){

    for(int q=0;q<10;q++)
        plant[q][9]=1;

}

public void generateSimpleStem(){

    int ry=rand.nextInt(4);
    plant[3+ry][8]=4;
    xr=3+ry;

    for(int u=7;u>1;u--){

        int yu=rand.nextInt(3);
        plant[xr-1+yu][u]=4;
        xr=xr-1+yu;

    }

}

public void generateSimpleFlower(){

    plant[xr][2]=3;

    for(int q2=1;q2<4;q2++)
        if((2-q2)!=0)
            plant[xr][q2]=2;

    for(int q3=xr-1;q3<=xr+1;q3++)
        if((xr-q3)!=0)
            plant[q3][2]=2;

}
like image 604
Hele Avatar asked Jan 02 '13 03:01

Hele


1 Answers

It sounds like a reasonably simple problem where you just generate 1 parameter at a time, possibly based on the output of the previous variables.

My model of a flower will be: It has just a reasonably upright stem, a perfectly round center, some amount of leaves on the stem on alternating sides, petals perfectly distributed around the center.

random() is just a random number within some chosen bounds, the bounds may be unique for each variable. random(x1, x2, ..., xn) generates a random number within some bounds dependent on the variables x1, x2, ..., xn (as in stemWidth < stemHeight/2, a reasonable assumption).

The Stem

stemXPosition = width / 2
stemHeight = random()
stemWidth = random(stemHeight)
stemColour = randomColour()
stemWidthVariationMax = random(stemWidth, stemHeight)
stemWidthVariationPerPixel = random(stemWidth, stemHeight)

stemWidthVariationMax/-PerPixel are for generating a stem that isn't perfectly straight (if you want to do something that complicated, a low PerPixel is for smoothness). Generate the stem using these as follows:

pixelRelative[y-position][0] := left x-position at that y-position relative to the stem
pixelRelative[y-position][1] := right x-position at that y-position relative to the stem

pixelRelative[0][0] = randomInRange(-stemWidthVariationMax, stemWidthVariationMax)
for each y > 0:
  pixelRelative[y-1][0] = max(min(randomInRange(pixel[y] - stemWidthVariationPerPixel,
                                        pixel[y] + stemWidthVariationPerPixel),
                          -stemWidthVariationMax),
                      stemWidthVariationMax)
//pixelRelative[0][1] and pixelRelative[y-1][1] generated same as pixelRelative[y-1][i]
for each y:
  pixelAbsolute[y][0] = width / 2 - stemWidth / 2 + pixelRelative[y][0]
  pixelAbsolute[y][1] = width / 2 + stemWidth / 2 + pixelRelative[y][1]

You can also use arcs to simplify things and go more than 1 pixel at a time.

The Top

centerRadius = random(stemHeight)
petalCount = random() // probably >= 3
petalSize = random(centerRadius, petalCount)

It's not too easy to generate the petals, you need to step from 0 to 2*PI with step-size of 2*PI/petalCount and generate arcs around the circle. It requires either a good graphics API or some decent maths.

Here's some nicely generated tops of flowers, though seemingly not open-source. Note that they don't have a center at all. (or centerRadius = 0)

The Leaves

You could probably write an entire paper on this, (like this one) but a simple idea would just be to generate a 1/2 circle and extend lines outward from there to meet at 2*the radius of the circle and to draw parallel lines on the flower.

Once you have a leaf generation algorithm:

leafSize = random(stemHeight) // either all leaves are the same size or generate the size for each randomly
leafStemLength = random(leafSize) // either all leaves have the same stem length or generate for each randomly
leafStemWidth = random(leafStemLength)
leaf[0].YPosition = random(stemHeight)
leaf[0].XSide = randomly either left or right
leaf[0].rotation = random between say 0 and 80 degrees
for each leaf i:
  leaf[i].YPosition = random(stemHeight, leaf[i-1]) // only generate new leaves above previous leaves
  leaf[i].XSide = opposite of leaf[i].XSide

Last words

The way to determine the bounds of each random would be either to argue it out, or give it some fixed value, generate everything else randomly a few times, keep increasing / decreasing it until it starts to look weird.

10 x 10 versus 500 x 500 would probably require greatly different algorithms, I wouldn't recommend the above for below 100 x 100, maybe generate a bigger image and simply shrink it using averaging or something.

Code

I started writing some Java code, when I realised it may take a bit longer than I would like to spend on this, so I'll show you what I have so far.

  // some other code, including these functions to generate random numbers:
  float nextFloat(float rangeStart, float rangeEnd);
  int nextInt(int rangeStart, int rangeEnd);

  ...

  // generates a color somewhere between green and brown
  Color stemColor = Color.getHSBColor(nextFloat(0.1, 0.2), nextFloat(0.5, 1), nextFloat(0.2, 0.8));
  int stemHeight = nextInt(height/2, 3*height/4);
  int stemWidth = nextInt(height/20, height/20 + height/5);
  Color flowerColor = ??? // I just couldn't use the same method as above to generate bright colors, but I'm sure it's not too difficult
  int flowerRadius = nextInt(Math.min(stemHeight, height - stemHeight)/4, 3*Math.min(stemHeight, height - stemHeight)/4);
like image 69
Bernhard Barker Avatar answered Oct 23 '22 10:10

Bernhard Barker