I had to shorten this a bit. there seems to be a limit about 8k of what a post can hold.
Run this in full screen mode:
background(0)# try to make size match the main displaytry:
import Foundation, AppKit
s = AppKit.NSScreen.mainScreen()
X,Y = s.frame().sizeexceptImportError:
# duh...
X = 1024.0
Y = 768.0size(X, Y)importmathimportrandomimporttimeimportpprint
dbg_frame = True# sceen mid
x_half = X / 2
y_half = Y / 2
roffset = (X - Y) / 2speed(0.2)class FGPoint(object):
def__init__(self, *args):
iflen(args) == 2:
try:
self.x = float(args[0])self.y = float(args[1])except:
raiseTypeError, "Wrong initializer for FGPoint object"else:
self.x = self.y = 0.0def__repr__(self):
return"FGPoint(%f, %f)" % (self.x, self.y)def__eq__(self, other):
if checkpoint(other):
returnself.x == other.xandself.y == other.yelse:
returnFalsedef__ne__(self, other):
returnnotself.__eq__(other)def__gt__(self, other):
if checkpoint(other):
return((self.x > other.x)and(self.y > other.y))else:
returnFalsedef__lt__(self, other):
returnnotself.__gt__(other)def__le__(self, other):
return(self.__eq__(other)orself.__lt__(other))def__ge__(self, other):
return(self.__eq__(other)orself.__gt__(other))def__add__(self, other):
t = type(other)if t == FGPoint:
return FGPoint(self.x + other.x, self.y + other.y)elif t in(tuple, list)andlen(other) == 2:
return FGPoint(self.x + other[0], self.y + other[1])elif t in(long, int, float):
# a numeric scalar
v = float(other)return FGPoint(self.x + v, self.y + v)else:
raiseValueError, "FGPoint addition error; value must be Point, FGPoint or number-like"def__sub__(self, other):
returnself.__add__(other.__neg__())def__mul__(self, other):
t = type(other)if t == intor t == float:
return FGPoint(self.x * other, self.y * other)elif t == FGPoint:
return FGPoint(self.x * other.x, self.y * other.y)else:
raiseValueError, "FGPoint multiplication error; value must be FGPoint or number-like"def__div__(self, other):
t = type(other)if t == FGPoint:
if other.x == 0.0:
x = 0.0else:
x = self.x / other.xif other.y == 0.0:
y = 0.0else:
y = self.y / other.yreturn FGPoint(x, y)elif t == floator t == int:
other = float(other)if other != 0.0:
return FGPoint(self.x / other, self.y / other)else:
return FGPoint(0.0, 0.0)else:
raiseValueError, "FGPoint multiplication error; value must be FGPoint or number-like"def__neg__(self):
return FGPoint(-self.x, -self.y)defas_list(self):
return[self.x, self.y]defas_tuple(self):
return(self.x, self.y)class FGHexagon(object):
"""Hexagon class"""def__init__(self, p, r):
"""p center point, r radius"""
r30 = math.radians(30)
c30 = math.cos( r30 )
s30 = math.sin( r30 )
t = type(p)if t == FGPoint:
self.p = p
elif t in(tuple, list)andlen(p) == 2:
self.p = FGPoint(p[0], p[1])else:
raiseValueError, "FGHexagon initialisation error."self.r = r
self.s = r * c30
self.points = [self.p + (self.r, 0),
self.p + (self.r / 2, -self.s),
self.p + (-self.r / 2, -self.s),
self.p + (-self.r, 0),
self.p + (-self.r / 2, self.s),
self.p + (self.r / 2, self.s)]defas_tuples(self):
p = self.points
l = [ pt.as_tuple()for pt in p]returntuple(l)defas_triangles(self):
return[(self.p, self.points[0], self.points[1]),
(self.p, self.points[1], self.points[2]),
(self.p, self.points[2], self.points[3]),
(self.p, self.points[3], self.points[4]),
(self.p, self.points[4], self.points[5]),
(self.p, self.points[5], self.points[0])]def__repr__(self):
s = "FGHexagon(p=%s, r=%.2f)"return s % (sepf.p, self.r)defcalculatePoints(points, smallerscale, steps):
"""Create a mousecurve from a list of points
Iterate steps times and each point moves with smallerscale
to he next point.
"""
result = []# work with a copy because it's overwritten in the loop
pointList = points[:]
n = len(pointList)for k inrange(steps):
# a new polygon type thingy# this should change; return a list of point list# that None stopmark made drawPoints() messy
result.append(None)
nextLevel = []for i,p inenumerate(pointList):
# cyclic nextPoint# if it's the last point, next one is first pointif0 <= i < n-1:
nextPoint = pointList[ i+1]elif i == n-1:
nextPoint = pointList[0]else:
# should never happenprint"BOGEY",i,n
# line curPoint, nextPoint
result.append( nextPoint )# FGPoint made this very nice...
scaledPoint = p + ((nextPoint - p) * smallerscale)
nextLevel.append( scaledPoint )# copy the calculated points as input for next iteration
pointList = nextLevel[:]return result
defdrawPoints(points):
"""Draw a list of points which has None interspersed as a stopmark
for different polygons.
"""
start = False
during = False
firstpoint = Falsebeginpath()for p in points:
ifnot p:
# it's a None stopmarkif firstpoint:
lineto( firstpoint.x, firstpoint.y)
firstpoint = False
start = Trueelse:
if start:
# print "start MOVETO", pmoveto( p.x, p.y)
firstpoint = p
start = Falseelse:
lineto( p.x, p.y)endpath()defhexagonCurve(x, y, size_, smallerscale, steps, shuffle):
"""make a hexagon mousecurve
"""
h = FGHexagon((x, y), size_)
p = h.pointsif shuffle:
random.shuffle(p)# the "reverse" points
q = p[::-1]# the mousecurves
r = calculatePoints(p, smallerscale, steps)
s = calculatePoints(q, smallerscale, steps)return(r, s)defhexagonTriangleCurve(x, y, size_, smallerscale, steps, shuffle):
"""make a hexagon consisting of triangle mousecurves
The orientation of the mousecurve is randomized per triangle.
"""
h = FGHexagon((x, y), size_)
p = h.as_triangles()
result = []for t in p:
q = t[::-1]ifrandom.random() > 0.5:
r = calculatePoints(t, smallerscale, steps)else:
r = calculatePoints(q, smallerscale, steps)
result.extend(r)return result
# the framedefdbgframe(angle=0):
push()reset()stroke(0.665,0.665,0.665)strokewidth(0.14142 * 4)nofill()oval(roffset, 0, Y, Y)rect(roffset, 0, Y, Y)transform(CORNER)translate(x_half, y_half)rotate(angle)for i inrange(6):
rotate(60)line(0,0, y_half, 0)pop()defdrawIt(angle=0):
"""Not really necessary. Is a randomisation of the next two functions."""ifrandom.random() > 0.5:
r, s = hexagonCurve(0, 0, y_half, 0.0066, 266, True)
r.extend(s)else:
r = hexagonTriangleCurve(0, 0, y_half, 0.0166, 166, True)reset()transform(CENTER)if angle == -361:
angle = random.random() * 60 - 30reset()translate(x_half, y_half)rotate(angle)nofill()stroke(0.665,0.665,0)strokewidth(0.14142 * 2)
drawPoints(r)defmakeHex(angle=0):
"""Create and draw a hexagonal mousecurve, centered at the screen
screen.y/2 in size."""
r, s = hexagonCurve(0, 0, y_half, 0.0066, 266, True)reset()transform(CENTER)reset()translate(x_half, y_half)rotate(angle)nofill()stroke(0.665,0.665,0)strokewidth(0.14142 * 2)
drawPoints(r)# drawing the oppsite curve in a different color make as nice effectstroke(0.0, 0.332, 0.332)
drawPoints(s)defmakeTri(angle=0):
# hexagon of triangles
r = hexagonTriangleCurve(0, 0, y_half, 0.0166, 166, True)reset()transform(CENTER)reset()stroke(0.665,0.665,0)translate(x_half, y_half)rotate(angle)nofill()strokewidth(0.14142 * 2)
drawPoints(r)
g_angle = 0defsetup():
# draw one since speed is 1/5 fpsglobal g_angle
g_angle += 1background(0)if dbg_frame:
dbgframe(g_angle)
makeHex(g_angle)
makeTri(g_angle)defdraw():
global g_angle
g_angle += 1
a = g_angle # random.random() * 360background(0)# fun loving folks should reverse this switchifTrue:
if dbg_frame:
dbgframe(a)
makeHex(a)else:
for i inrange(2):
if dbg_frame:
dbgframe(a)
makeHex(a)
drawIt(a)ifrandom.random() > 0.5:
makeHex(a)ifrandom.random() > 0.5:
makeTri(a)
Hexagonal mousecurves
Posted by Karsten Wolf on Jun 19, 2010I had to shorten this a bit. there seems to be a limit about 8k of what a post can hold.
Run this in full screen mode: