allow empty return value for realpolyroots
[PyX/mjg.git] / test / functional / test_deformer.py
blob61d2e2f06f897706facde725e415aca486c00ce9
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.Thin])
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 p = p.transformed(trafo.translate(*move))
95 c.text(move[0], move[1], label)
96 c.stroke(p)
97 pps = []
98 if 1:
99 p1 = pardef(distance=+dist).deform(p)
100 c.stroke(p1, [color.rgb.red])
101 pps.append(p1)
102 if 1:
103 p2 = pardef(distance=-dist).deform(p)
104 c.stroke(p2, [color.rgb.blue])
105 pps.append(p2)
106 for pp in pps:
107 for nsp in pp.normsubpaths:
108 for nspitem in nsp.normsubpathitems:
109 if isinstance(nspitem, normpath.normcurve_pt):
110 c.fill(path.circle(nspitem.x1_pt*unit.u_pt, nspitem.y1_pt*unit.u_pt, 0.025), [color.rgb.green])
111 c.fill(path.circle(nspitem.x2_pt*unit.u_pt, nspitem.y2_pt*unit.u_pt, 0.025), [color.rgb.green])
112 c.fill(path.circle(nspitem.atbegin_pt()[0]*unit.u_pt, nspitem.atbegin_pt()[1]*unit.u_pt, 0.02))
113 c.fill(path.circle(nspitem.atend_pt()[0]*unit.u_pt, nspitem.atend_pt()[1]*unit.u_pt, 0.02))
115 for nsp in p.normpath().normsubpaths:
116 for nspitem in nsp.normsubpathitems:
117 c.fill(path.circle(nspitem.atbegin_pt()[0]*unit.u_pt, nspitem.atbegin_pt()[1]*unit.u_pt, 0.02), [color.rgb.red])
118 c.fill(path.circle(nspitem.atend_pt()[0]*unit.u_pt, nspitem.atend_pt()[1]*unit.u_pt, 0.02), [color.rgb.red])
119 #if isinstance(nspitem, normpath.normcurve_pt):
120 # c.fill(path.circle(nspitem.x1_pt*unit.u_pt, nspitem.y1_pt*unit.u_pt, 0.025), [color.rgb.green])
121 # c.fill(path.circle(nspitem.x2_pt*unit.u_pt, nspitem.y2_pt*unit.u_pt, 0.025), [color.rgb.green])
124 def testparallel_1(c):
126 # HARD TESTS of elementary geometry:
128 # test for correct skipping of short ugly pieces:
129 move = (0, 0)
130 p = path.path(path.moveto(0, 1), path.lineto(10, 0.3), path.lineto(12, 0), path.lineto(0, 0))
131 p.append(path.closepath())
132 hard_test(c, p, -0.2, parallel(0.0), move, "A")
134 # test non-intersecting/too short neighbouring pathels
135 move = (0, 4)
136 p = path.curve(0,0, 0,1, 1,2, 2,0)
137 p.append(path.lineto(2.1, 0.1))
138 p.append(path.lineto(1.6, -2))
139 p.append(path.lineto(2.1, -2))
140 p.append(path.lineto(-0.15, 0))
141 p.append(path.closepath())
142 hard_test(c, p, 0.3, parallel(0.0), move, "B")
144 # test extremely sensitively:
145 move = (3.5, 2)
146 p = path.curve(0,0, 0,1, 1,1, 1,0)
147 p.append(path.closepath())
148 hard_test(c, p, -0.1, parallel(0.0), move, "C")
149 # hard_test(c, p, -0.1, parallel(0.0, relerr=1e-15, checkdistance=1), move, "C")
151 # test for numeric instabilities:
152 move = (6, 2)
153 # unsymmetric outcome: see fallback in controldists_from_endgeometry_pt
154 # this fails is root-polishing is used in realpolyroots
155 p = path.curve(0,0, 1,1, 1,1, 2,0)
156 p.append(path.closepath())
157 hard_test(c, p, -0.1, parallel(0.0, relerr=0.15, checkdistance=1), move, "D")
158 hard_test(c, p, -0.3, parallel(0.0), move, "D")
160 # test for an empty parallel path:
161 move = (5, 5)
162 p = path.circle(0, 0, 0.5)
163 hard_test(c, p, 0.55, parallel(0.0), move, "E")
164 #hard_test(c, p, 0.499, parallel(0.0), move, "E")
165 hard_test(c, p, 0.499999, parallel(0.0), move, "E")
167 # a degenerate path:
168 move = (12, 3)
169 # XXX this is killed with a ZeroDivisionError that does not react on except:
170 p = path.curve(0,0, 0,-5, 0,1, 0,0.5)
171 # hard_test(c, p, 0.1, parallel(0.0), move, "F")
173 # test for too big curvatures in the middle:
174 move = (9, 2.5)
175 p = path.curve(0,0, 1,1, 1,1, 2,0)
176 hard_test(c, p, -0.4, parallel(0.0, relerr=1.0e-2), move, "G")
177 hard_test(c, p, -0.6, parallel(0.0, relerr=1.0e-2), move, "G")
178 hard_test(c, p, -0.8, parallel(0.0, relerr=1.0e-2), move, "G")
179 # this fails in _intersect_and_concatenate at the modifiedbegin
180 # TODO: improve the recursion in normpath.intersect...
181 hard_test(c, p, -1.2, parallel(0.0), move, "G")
183 # deformation of the deformation:
184 move = (9, 6)
185 p = path.curve(0,0, 1,1, 1,1, 2,0)
186 c.stroke(p, [trafo.translate(*move)])
187 p = parallel(-0.4, relerr=1.0e-2).deform(p)
188 hard_test(c, p, -0.39, parallel(0.0), move, "H")
190 # test for infinite curvature in the middle:
191 move = (9, 8)
192 p = path.curve(0,0, 1,1, 0,1, 1,0)
193 hard_test(c, p, -0.2, parallel(0.0), move, "I")
195 # test for infinite curvature at the end:
196 move = (5, 8)
197 p = path.curve(0,0, 1,1, 1,0, 1,0)
198 hard_test(c, p, -0.1, parallel(0.0), move, "J")
199 # test for infinite curvature when the path goes on
200 # XXX this is killed by the non-defined tangents at the end
201 p.append(path.rlineto(1, 0))
202 hard_test(c, p, -0.22, parallel(0.0), move, "J")
205 def testparallel_2(c):
207 # a path of two subpaths:
208 move = (0, 0)
209 p = path.circle(-6, 0, 2)
210 p += path.path(path.moveto(0,0), path.curveto(0,16, -11,5, 5,5))
211 p += path.path(path.lineto(5,4), path.lineto(6,4), path.lineto(6,6), path.lineto(4,6),
212 path.lineto(4,7), path.lineto(5,7), path.lineto(3,1), path.closepath())
213 p = p.transformed(trafo.scale(0.5))
214 hard_test(c, p, 0.05, parallel(0.0), move, "K")
215 hard_test(c, p, 0.7, parallel(0.0), move, "K")
218 c=canvas.canvas()
219 dotest(c, 13, 15, "testcycloid")
220 dotest(c, 20, 0, "testsmoothed")
221 #dotest(c, 0, 0, "testparallel_1")
222 #dotest(c, 6, 12, "testparallel_2")
223 c.writeEPSfile("test_deformer", paperformat=document.paperformat.A4, rotated=0, fittosize=1)
224 c.writePDFfile("test_deformer")