rewrite the parallel deformer and its helper routines
[PyX/mjg.git] / test / functional / test_deformer.py
blob74fe4a657ea6a78abaccb1f26832dca05e32c145
1 #!/usr/bin/env python
2 import sys; sys.path[:0] = ["../.."]
3 import warnings
4 from pyx import *
5 from pyx.deformer import *
7 ##### helpers ##############################################################
9 def bboxrect(cmd):
10 return cmd.bbox().enlarged(5*unit.t_mm).rect()
12 def dotest(c, x, y, test):
13 c2 = c.insert(canvas.canvas([trafo.translate(x, y)]))
14 eval("%s(c2)" % test)
15 c.stroke(bboxrect(c2))
17 def drawpathwbbox(c, p):
18 c.stroke(p, [color.rgb.red])
19 np = p.normpath()
20 c.stroke(np, [color.rgb.green, style.linestyle.dashed])
21 c.stroke(bboxrect(p))
23 ##### tests ################################################################
25 def testcycloid(c):
27 # dependence on turnangle
28 p = path.line(0, 0, 3, 0)
29 c.stroke(p, [style.linewidth.THIN])
30 cyc = cycloid(halfloops=3, skipfirst=0.5, skiplast=0.5, curvesperhloop=2)
31 c.stroke(p, [cyc(turnangle=00)])
32 c.stroke(p, [cyc(turnangle=22), color.rgb.red])
33 c.stroke(p, [cyc(turnangle=45), color.rgb.green])
34 c.stroke(p, [cyc(turnangle=67), color.rgb.blue])
35 c.stroke(p, [cyc(turnangle=90), color.cmyk.Cyan])
37 # dependence on curvesperloop
38 p = path.curve(5, 0, 8, 0, 6, 4, 9, 4)
39 c.stroke(p)
40 cyc = cycloid(halfloops=16, skipfirst=0, skiplast=0, curvesperhloop=1)
41 c.stroke(p, [cyc(curvesperhloop=2)])
42 c.stroke(p, [cyc(curvesperhloop=3), color.rgb.red])
43 c.stroke(p, [cyc(curvesperhloop=4), color.rgb.green])
44 c.stroke(p, [cyc(curvesperhloop=10), color.rgb.blue])
46 # extremely curved path
47 p = path.curve(0,2, 0.5,5, 1,6, 2,2)
48 c.stroke(p)
49 cyc = cycloid(radius=0.7, halfloops=7, skipfirst=0, skiplast=0, curvesperhloop=1)
50 c.stroke(p, [cyc(curvesperhloop=2)])
51 c.stroke(p, [cyc(curvesperhloop=3), color.rgb.red])
52 c.stroke(p, [cyc(curvesperhloop=4), color.rgb.green])
53 c.stroke(p, [cyc(curvesperhloop=50), color.rgb.blue])
56 def testsmoothed(c):
57 p = path.path(
58 path.moveto(0,0),
59 path.lineto(3,0),
60 path.lineto(5,7),
61 path.curveto(0,10, -2,8, 0,6),
62 path.lineto(0,4),
63 # horrible overshooting with obeycurv=1
64 #path.lineto(-4,4), path.curveto(-7,5, -4,2, -5,2),
65 path.lineto(-4,3), path.curveto(-7,5, -4,2, -5,2),
66 #path.arct(-6,4, -5,1, 1.5),
67 #path.arc(-5, 3, 0.5, 0, 180),
68 path.lineto(-5,1),
69 path.lineto(-0.2,0.2),
70 path.closepath()
71 ) + path.circle(0,1,2)
73 c.stroke(p, [color.gray(0.8), style.linewidth.THICk])
74 c.stroke(p.normpath(), [color.gray(0.8), style.linewidth.THICk])
75 c.stroke(p, [smoothed(radius=0.85, softness=1, obeycurv=1), style.linewidth.Thin])
76 c.stroke(p, [smoothed(radius=0.85, softness=1, obeycurv=0), color.rgb.red])
77 c.stroke(p, [smoothed(radius=0.20, softness=1, obeycurv=0), color.rgb.green])
78 c.stroke(p, [smoothed(radius=1.20, softness=1, obeycurv=0), color.rgb.blue])
80 p = path.path(
81 path.moveto(0,10),
82 path.curveto(1,10, 4,12, 2,11),
83 path.curveto(4,8, 4,12, 0,11)
85 c.stroke(p, [color.gray(0.8), style.linewidth.THICk])
86 c.stroke(p.normpath(), [color.gray(0.8), style.linewidth.THICk])
87 c.stroke(p, [smoothed(radius=0.85, softness=1, obeycurv=1), style.linewidth.Thick])
88 c.stroke(p, [smoothed(radius=0.85, softness=1, obeycurv=0), color.rgb.red])
89 c.stroke(p, [smoothed(radius=0.20, softness=1, obeycurv=0), color.rgb.green])
90 c.stroke(p, [smoothed(radius=1.20, softness=1, obeycurv=0), color.rgb.blue])
93 def hard_test(c, p, dist, pardef, move=(0, 0), label=""):
94 print "hard test of: ", label
95 p = p.transformed(trafo.translate(*move))
96 c.text(move[0], move[1], label)
97 c.stroke(p)
98 pps = []
99 if 1:
100 p1 = pardef(distance=+dist).deform(p)
101 c.stroke(p1, [color.rgb.red])
102 pps.append(p1)
103 if 1:
104 p2 = pardef(distance=-dist).deform(p)
105 c.stroke(p2, [color.rgb.blue])
106 pps.append(p2)
107 return
108 for pp in pps:
109 for nsp in pp.normsubpaths:
110 beg, end = nsp.at_pt([0, len(nsp)])
111 begn, endn = nsp.rotation([0, len(nsp)])
112 if begn is normpath.invalid:
113 begn = (1, 0)
114 else:
115 begn = begn.apply_pt(0, 1)
116 if endn is normpath.invalid:
117 endn = (1, 0)
118 else:
119 endn = endn.apply_pt(0, 1)
120 l = 0.1
121 c.stroke(path.line_pt(beg[0]-l*begn[0], beg[1]-l*begn[1], beg[0]+l*begn[0], beg[1]+l*begn[1]), [color.rgb.green])
122 c.stroke(path.line_pt(end[0]-l*endn[0], end[1]-l*endn[1], end[0]+l*endn[0], end[1]+l*endn[1]), [color.rgb.green])
123 for nspitem in nsp.normsubpathitems:
124 if isinstance(nspitem, normpath.normcurve_pt):
125 c.fill(path.circle(nspitem.x1_pt*unit.u_pt, nspitem.y1_pt*unit.u_pt, 0.025), [color.rgb.green])
126 c.fill(path.circle(nspitem.x2_pt*unit.u_pt, nspitem.y2_pt*unit.u_pt, 0.025), [color.rgb.green])
127 c.fill(path.circle(nspitem.atbegin_pt()[0]*unit.u_pt, nspitem.atbegin_pt()[1]*unit.u_pt, 0.02))
128 c.fill(path.circle(nspitem.atend_pt()[0]*unit.u_pt, nspitem.atend_pt()[1]*unit.u_pt, 0.02))
130 for nsp in p.normpath().normsubpaths:
131 for nspitem in nsp.normsubpathitems:
132 c.fill(path.circle(nspitem.atbegin_pt()[0]*unit.u_pt, nspitem.atbegin_pt()[1]*unit.u_pt, 0.02), [color.rgb.red])
133 c.fill(path.circle(nspitem.atend_pt()[0]*unit.u_pt, nspitem.atend_pt()[1]*unit.u_pt, 0.02), [color.rgb.red])
136 def testparallel_1(c):
138 d = c
140 # HARD TESTS of elementary geometry:
142 # test for correct skipping of short ugly pieces:
143 move = (0, 0)
144 p = path.path(path.moveto(0, 1), path.lineto(10, 0.3), path.lineto(12, 0), path.lineto(0, 0))
145 p.append(path.closepath())
146 hard_test(c, p, -0.2, parallel(0.0), move, "A")
148 # test non-intersecting/too short neighbouring pathels
149 move = (0, 4)
150 p = path.curve(0,0, 0,1, 1,2, 2,0)
151 p.append(path.lineto(2.1, 0.1))
152 p.append(path.lineto(1.6, -2))
153 p.append(path.lineto(2.1, -2))
154 p.append(path.lineto(-0.15, 0))
155 p.append(path.closepath())
156 hard_test(c, p, 0.3, parallel(0.0), move, "B")
157 hard_test(c, p, 0.12, parallel(0.0), move, "B")
159 # test extremely sensitively:
160 move = (3.5, 2)
161 p = path.curve(0,0, 0,1, 1,1, 1,0)
162 p.append(path.closepath())
163 hard_test(c, p, -0.1, parallel(0.0), move, "C")
164 # takes quite long:
165 hard_test(c, p, -0.1, parallel(0.0, relerr=1e-15, checkdistanceparams=[0.5]), move, "C")
167 # test for numeric instabilities:
168 move = (6, 2)
169 p = path.curve(0,0, 1,1, 1,1, 2,0)
170 p.append(path.closepath())
171 hard_test(c, p, -0.1, parallel(0.0, relerr=0.15, checkdistanceparams=[0.5]), move, "D")
172 hard_test(c, p, -0.3, parallel(0.0), move, "D")
174 # test for an empty parallel path:
175 move = (5, 5)
176 p = path.circle(0, 0, 0.5)
177 hard_test(c, p, 0.55, parallel(0.0), move, "E")
178 hard_test(c, p, 0.499, parallel(0.0), move, "E")
179 hard_test(c, p, 0.499999, parallel(0.0), move, "E")
181 # a degenerate path:
182 move = (12, 3)
183 p = path.curve(0,0, 0,-5, 0,1, 0,0.5)
184 # hard_test(c, p, 0.1, parallel(0.0), move, "F")
186 # test for too big curvatures in the middle:
187 move = (9, 2.5)
188 p = path.curve(0,0, 1,1, 1,1, 2,0)
189 hard_test(c, p, -0.4, parallel(0.0, relerr=1.0e-2), move, "G")
190 hard_test(c, p, -0.6, parallel(0.0, relerr=1.0e-2), move, "G")
191 hard_test(c, p, -0.8, parallel(0.0, relerr=1.0e-2), move, "G")
192 hard_test(c, p, -1.2, parallel(0.0), move, "G")
194 # deformation of the deformation:
195 move = (9, 6)
196 p = path.curve(0,0, 1,1, 1,1, 2,0)
197 c.stroke(p, [trafo.translate(*move)])
198 p = parallel(-0.4, relerr=1.0e-2).deform(p)
199 hard_test(c, p, -0.39, parallel(0.0), move, "H")
201 # test for infinite curvature in the middle:
202 move = (9, 8)
203 p = path.curve(0,0, 1,1, 0,1, 1,0)
204 hard_test(c, p, -0.2, parallel(0.0), move, "I")
206 # test for infinite curvature at the end:
207 move = (5, 8)
208 p = path.curve(0,0, 1,1, 1,0, 1,0)
209 hard_test(c, p, -0.1, parallel(0.0), move, "J")
210 # test for infinite curvature when the path goes on
211 p.append(path.rlineto(1, 0))
212 hard_test(c, p, -0.22, parallel(0.0), move, "J")
215 def testparallel_2(c):
217 d = c
219 # a path of two subpaths:
220 move = (0, 0)
221 p = path.circle(-6, 0, 2)
222 p += path.path(path.moveto(0,0), path.curveto(0,16, -11,5, 5,5))
223 p += path.path(path.lineto(5,4), path.lineto(7,4), path.lineto(7,6), path.lineto(4,6),
224 path.lineto(4,7), path.lineto(5,7), path.lineto(3,1), path.closepath())
225 p = p.transformed(trafo.scale(0.5))
226 hard_test(c, p, 0.05, parallel(0.0), move, "K")
227 hard_test(c, p, 0.3, parallel(0.0), move, "K")
228 #hard_test(c, p, 0.6, parallel(0.0), move, "K")
231 c=canvas.canvas()
232 dotest(c, 13, 15, "testcycloid")
233 dotest(c, 20, 0, "testsmoothed")
234 dotest(c, 0, 0, "testparallel_1")
235 dotest(c, 6, 12, "testparallel_2")
236 c.writeEPSfile("test_deformer", paperformat=document.paperformat.A4, rotated=0, fittosize=1)
237 c.writePDFfile("test_deformer")