I was looking for a way to put a four petal flower shape on my Python-POV-ray generated egg. As it turns out, this shape is a common geometric one called

Pascal's Rose.

For expediency rather than efficiency's sake, I opted to generate the shape using individual x, y points (actually x, z in POV-ray):

def getcoords(theta, factorr, factortheta, trigfunc):

"""

Returns two tuple of x and y values for

the equation in the form

factorr * r * r = trigfunc(factortheta * theta)

"""

r = math.sqrt((trigfunc(factortheta * theta)) ** 2 / factorr)

x = r * math.cos(theta)

y = r * math.sin(theta)

if abs(x) < ZEROLIMIT:

x = 0.0

if abs(y) < ZEROLIMIT:

y = 0.0

print x, y, theta

return x, y

def cycleequation(step, start, stop, trigfunc, factorr, factortheta):

"""

Returns list of x, y coordinates that correspond

to the equation of the form

factorr * r * r = trigfunc(factortheta * theta)

theta will be incremented by step.

start is the first value of theta.

stop is the last value of theta.

"""

coords = []

theta = start

while theta < stop:

coords.append(getcoords(theta, factorr, factortheta, trigfunc))

theta += step

coords.append(getcoords(stop, factorr, factortheta, trigfunc))

return coords

math.cos creates Pascal's Rose for this equation. I had to add a Prism object to the

POV-ray recipe I am using.

class Prism(Item):

def __init__(self, base, top, numpts, *opts, **kwargs):

Item.__init__(self,"prism",(base, top, numpts),opts,**kwargs)

For me it was easiest to just translate the points of the prism into POV-ray SDL language prior to feeding them to Python:

def translatetopovray(pts):

"""

Returns string in povray format of list

of points pts.

"""

stringpoints = []

for pt in pts:

stringpoints.append('<%.8f, %.8f>' % pt)

return string.join(stringpoints, ',')

This allowed for generation of a prism:

This is just a rough representation of what I wanted. The scene I was creating required a two colored flower, the outside as gold and the inside as orange. Further, the outside edge needed to appear to be of constant width, as one would achieve by applying wax to an egg with the pysanky drawing tool, the kistka.

To get this effect I used a rough offset algorithm - get the centerpoint of the line segment on the outside edge of the "flower", offset a set distance along the normal to the outside line segment, then connect all the inner points.

def gettan(pt1, pt2):

"""

Returns the tangent of the directional

angle formed by line segment pt1-pt2.

"""

return (pt2[1] - pt1[1])/(pt2[0] - pt1[0])

def getmidpoint(pt1, pt2):

"""

Get the midpoint of the line segment

pt1-pt2.

"""

x = pt1[0] + (pt2[0] - pt1[0])/2.0

y = pt1[1] + (pt2[1] - pt1[1])/2.0

return x, y

def calcoffsetpoint(pt1, pt2, offset):

"""

Get point offset distance offset

from the midpoint of line segment

pt1-pt2 to the left.

"""

midpoint = getmidpoint(pt1, pt2)

# get normal

# quadrant I

if pt2[0] >= pt1[0] and pt2[1] >= pt1[1]:

theta = math.atan(gettan(pt1, pt2)) + math.pi/2.0

x = midpoint[0] + math.cos(theta) * offset

y = midpoint[1] + math.sin(theta) * offset

# quadrant II

elif pt2[0] <= pt1[0] and pt2[1] >= pt1[1]:

theta = math.atan(gettan(pt1, pt2)) + math.pi/2.0

x = midpoint[0] - math.cos(theta) * offset

y = midpoint[1] - math.sin(theta) * offset

# quadrant III

elif pt2[0] <= pt1[0] and pt2[1] <= pt1[1]:

theta = 3.0 * math.pi/2.0 + math.atan(gettan(pt1, pt2))

x = midpoint[0] + math.cos(theta) * offset

y = midpoint[1] + math.sin(theta) * offset

# quadrant IV

elif pt2[0] >= pt1[0] and pt2[1] <= pt1[1]:

theta = 3.0 * math.pi/2.0 + math.atan(gettan(pt1, pt2))

x = midpoint[0] - math.cos(theta) * offset

y = midpoint[1] - math.sin(theta) * offset

else:

print pt1, pt2

print 'error - theta undefined'

theta = 0.0

return x, y

def getmiddle(step, start, stop, trigfunc, factorr, factortheta, offset):

"""

Return list of points for middle of 'petal'.

"""

startend = (0.0, 0.0)

pts = [startend]

# need to offset by fixed distance along

# normal to each line segment

# need to get pts along original flower

# but not near 0.0, 0.0 where they will

# overlap

outsidepts = cycleequation(step, start, stop,

trigfunc, factorr, factortheta)

counter = 0

maxcounter = len(outsidepts)

while (counter + 1) < (maxcounter - 1):

pts.append(calcoffsetpoint(outsidepts[counter],

outsidepts[counter + 1], offset))

counter += 1

pts.append(startend)

return pts

My analytical geometry is a bit rough, but this works well enough for what I was trying to accomplish.

Through some intersecting and positioning, I was able to get the effect I wanted. This egg design, according to the Sixty Score of Easter Eggs book by Elyjiw, is from the Odessa region of the Ukraine.

Thanks for having a look.