5
5
# You can download Raph's curve editor from http://www.levien.com/spiro/.
6
6
7
7
from math import *
8
+ from plotdevice .lib import register
9
+ _ctx = register (__name__ )
8
10
9
11
### CORNU ############################################################################################
10
12
@@ -44,7 +46,7 @@ def boundary_ths(path, ths, closed):
44
46
ths [0 ] = first_th
45
47
last_th = 2 * atan2 (path [- 1 ][1 ] - path [- 2 ][1 ], path [- 1 ][0 ] - path [- 2 ][0 ]) - ths [- 2 ]
46
48
ths [- 1 ] = last_th
47
-
49
+
48
50
# implementation adapted from cephes
49
51
def polevl (x , coef ):
50
52
ans = coef [- 1 ]
@@ -271,10 +273,10 @@ def draw_cornu(path, ths, closed, flat=False):
271
273
#print 'stroke'
272
274
273
275
def draw_cornu_flat (x0 , y0 , t0 , t1 , s0 , c0 , flip , cs , ss , cmd ):
274
-
276
+
275
277
""" Raph Levien's code draws fast LINETO segments.
276
278
"""
277
-
279
+
278
280
for j in range (0 , 100 ):
279
281
t = j * .01
280
282
s , c = eval_cornu (t0 + t * (t1 - t0 ))
@@ -287,7 +289,7 @@ def draw_cornu_flat(x0, y0, t0, t1, s0, c0, flip, cs, ss, cmd):
287
289
print_pt (x0 + x , y0 + y , cmd )
288
290
cmd = 'lineto'
289
291
return cmd
290
-
292
+
291
293
def draw_cornu_bezier (x0 , y0 , t0 , t1 , s0 , c0 , flip , cs , ss , cmd , scale , rot ):
292
294
293
295
""" Mark Meyer's code draws elegant CURVETO segments.
@@ -301,11 +303,11 @@ def draw_cornu_bezier(x0, y0, t0, t1, s0, c0, flip, cs, ss, cmd, scale, rot):
301
303
# becomes the new first point
302
304
t = j * .2
303
305
t2 = t + .2
304
-
306
+
305
307
curvetime = t0 + t * (t1 - t0 )
306
308
curvetime2 = t0 + t2 * (t1 - t0 )
307
309
Dt = (curvetime2 - curvetime ) * scale
308
-
310
+
309
311
if not s :
310
312
# get first point
311
313
# avoid calling this again: the next time though x,y will equal x3, y3
@@ -315,40 +317,40 @@ def draw_cornu_bezier(x0, y0, t0, t1, s0, c0, flip, cs, ss, cmd, scale, rot):
315
317
c -= c0
316
318
# calculate derivative of fresnel function at point to get tangent slope
317
319
# just take the integrand of the fresnel function
318
- dx1 = cos (pow (curvetime , 2 ) + (flip * rot ))
320
+ dx1 = cos (pow (curvetime , 2 ) + (flip * rot ))
319
321
dy1 = flip * sin (pow (curvetime , 2 ) + (flip * rot ))
320
322
# x,y = first point on function
321
323
x = ((c * cs - s * ss ) + x0 )
322
324
y = ((s * cs + c * ss ) + y0 )
323
325
324
326
#evaluate the fresnel further along the function to look ahead to the next point
325
- s2 ,c2 = eval_cornu (curvetime2 )
327
+ s2 ,c2 = eval_cornu (curvetime2 )
326
328
s2 *= flip
327
329
s2 -= s0
328
330
c2 -= c0
329
331
330
- dx2 = cos (pow (curvetime2 , 2 ) + (flip * rot ))
332
+ dx2 = cos (pow (curvetime2 , 2 ) + (flip * rot ))
331
333
dy2 = flip * sin (pow (curvetime2 , 2 ) + (flip * rot ))
332
334
# x3, y3 = second point on function
333
335
x3 = ((c2 * cs - s2 * ss )+ x0 )
334
336
y3 = ((s2 * cs + c2 * ss )+ y0 )
335
337
336
338
# calculate control points
337
339
x1 = (x + ((Dt / 3.0 ) * dx1 ))
338
- y1 = (y + ((Dt / 3.0 ) * dy1 ))
340
+ y1 = (y + ((Dt / 3.0 ) * dy1 ))
339
341
x2 = (x3 - ((Dt / 3.0 ) * dx2 ))
340
342
y2 = (y3 - ((Dt / 3.0 ) * dy2 ))
341
343
342
344
if cmd == 'moveto' :
343
345
print_pt (x , y , cmd )
344
346
cmd = 'curveto'
345
347
print_crv (x1 , y1 , x2 , y2 , x3 , y3 )
346
-
348
+
347
349
dx1 , dy1 = dx2 , dy2
348
350
x ,y = x3 , y3
349
-
351
+
350
352
return cmd
351
-
353
+
352
354
# update thetas based on cornu splines
353
355
def tweak_ths (path , ths , closed ):
354
356
dks = []
@@ -430,7 +432,7 @@ def draw_cspline(path, ths):
430
432
def print_pt (x , y , cmd ):
431
433
x = 100 * x
432
434
y = 100 * y
433
- if (cmd == 'moveto' ):
435
+ if (cmd == 'moveto' ):
434
436
_ctx .moveto (x , y )
435
437
elif (cmd == 'lineto' ):
436
438
_ctx .lineto (x , y )
@@ -447,34 +449,34 @@ def print_crv(x1, y1, x2, y2, x3, y3):
447
449
_ctx .curveto (x1 , y1 , x2 , y2 , x3 , y3 )
448
450
449
451
def dot_pt (x , y ):
450
- _ctx .oval (x - 3 ,y - 3 , 6 , 6 )
452
+ _ctx .oval (x - 3 ,y - 3 , 6 , 6 )
451
453
452
454
def relativise (path ):
453
455
454
456
for i in range (len (path )):
455
457
x , y = path [i ]
456
458
x *= 0.01 * _ctx .WIDTH
457
459
y *= 0.01 * _ctx .HEIGHT
458
-
460
+
459
461
#Points on the path that have identical coordinates
460
462
#generate a ZeroDivisionError
461
463
for point in path :
462
464
if (x ,y ) == point :
463
465
x += 0.0000000001
464
466
y += 0.0000000001
465
-
467
+
466
468
path [i ] = (x ,y )
467
-
469
+
468
470
return path
469
-
471
+
470
472
def path (points , close = False , tweaks = 20 , flat = False , draw = False , helper = False ):
471
473
472
- # To make sure we don't change the original, make a copy of the
474
+ # To make sure we don't change the original, make a copy of the
473
475
# given points
474
476
points = list (points )
475
477
476
478
points = relativise (points )
477
-
479
+
478
480
ths = local_ths (points , close )
479
481
for i in range (tweaks ):
480
482
boundary_ths (points , ths , close )
@@ -498,20 +500,20 @@ def path(points, close=False, tweaks=20, flat=False, draw=False, helper=False):
498
500
_ctx .endpath ()
499
501
for x ,y in points :
500
502
dot_pt (x * 100 ,y * 100 )
501
-
503
+
502
504
return p
503
-
505
+
504
506
def drawpath (p , close = False , tweaks = 20 , points = False , flat = False ):
505
-
507
+
506
508
path (p , close , tweaks , flat , draw = True , helper = points )
507
509
508
510
### PSYCO SPECIALIZATION #############################################################################
509
511
510
512
try :
511
513
import psyco
512
514
for f in [
513
- fit_arc , local_ths , boundary_ths , polevl , fresnel , eval_cornu ,
514
- mod_2pi , fit_cornu_half , fit_cornu , draw_tan , draw_cornu ,
515
+ fit_arc , local_ths , boundary_ths , polevl , fresnel , eval_cornu ,
516
+ mod_2pi , fit_cornu_half , fit_cornu , draw_tan , draw_cornu ,
515
517
draw_cornu_flat , draw_cornu_bezier ,
516
518
tweak_ths , csinterp , draw_cspline , print_pt , relativise
517
519
]:
0 commit comments