- negative parameters are no longer supported in path and normpath methods
[PyX/mjg.git] / test / functional / test_path.py
blobeca34efb2962d5329db2f712b18b0effc917bd5b
1 #!/usr/bin/env python
2 import sys; sys.path[:0] = ["../.."]
4 from pyx import *
5 from pyx.path import *
7 def bboxrect(cmd):
8 # bbox=cmd.bbox()
9 # return rect("%f t pt" % bbox.llx, "%f t pt" % bbox.lly,
10 # "%f t pt" % (bbox.urx-bbox.llx), "%f t pt" % (bbox.ury-bbox.lly))
11 return cmd.bbox().rect()
14 def dotest(c, x, y, test):
15 c2 = c.insert(canvas.canvas(trafo.translate(x, y)))
16 eval("%s(c2)" % test)
17 c.stroke(bboxrect(c2))
20 class cross(path):
21 def __init__(self, x, y):
22 self.path=[moveto(x,y),
23 rmoveto(-0.1, -0.1),
24 rlineto(0.2, 0.2),
25 rmoveto(-0.1, -0.1),
26 rmoveto(-0.1, +0.1),
27 rlineto(0.2, -0.2)]
30 def drawpathwbbox(c, p):
31 c.stroke(p, [color.rgb.red])
32 np=normpath(p)
33 c.stroke(np, [color.rgb.green, style.linestyle.dashed])
34 c.stroke(bboxrect(p))
37 def testarcs(c):
38 def testarc(c, x, y, phi1, phi2):
39 p=path(arc(x,y, 0.5, phi1, phi2))
40 np=normpath(p)
41 c.stroke(p, [color.rgb.red])
42 c.stroke(np, [color.rgb.green, style.linestyle.dashed])
44 def testarcn(c, x, y, phi1, phi2):
45 p=path(arcn(x,y, 0.5, phi1, phi2))
46 np=normpath(p)
47 c.stroke(p, [color.rgb.red])
48 c.stroke(np, [color.rgb.green, style.linestyle.dashed])
50 def testarct(c, r, x0, y0, dx1, dy1, dx2, dy2):
51 p=path(moveto(x0,y0), arct(x0+dx1,y0+dy1, x0+dx2, y0+dy2, r), rlineto(dx2-dx1, dy2-dy1), closepath())
52 np=normpath(p)
53 c.stroke(p, [color.rgb.red, style.linewidth.Thick])
54 c.stroke(np, [color.rgb.green, style.linewidth.THin, deco.filled([color.rgb.green])])
56 testarc(c, 1, 2, 0, 90)
57 testarc(c, 2, 2, -90, 90)
58 testarc(c, 3, 2, 270, 90)
59 testarc(c, 4, 2, 90, -90)
60 testarc(c, 5, 2, 90, 270)
61 testarc(c, 4, 3, 45, -90)
62 testarc(c, 2, 3, 45, -90-2*360)
63 testarc(c, 1, 3, 45, +90+2*360)
65 testarcn(c, 1, 5, 0, 90)
66 testarcn(c, 2, 5, -90, 90)
67 testarcn(c, 3, 5, 270, 90)
68 testarcn(c, 4, 5, 90, -90)
69 testarcn(c, 5, 5, 90, 270)
70 testarcn(c, 4, 6, 45, -90)
71 testarcn(c, 2, 6, 45, -90-360)
72 testarcn(c, 1, 6, 45, -90+360)
74 testarct(c, 0.5, 1, 8, 0, 1, 1, 1)
75 testarct(c, 0.5, 3, 8, 1, 1, 1, 2)
76 testarct(c, 0.5, 5, 8, 1, 0, 2, 1)
77 testarct(c, 0.5, 7, 8, 1, 0, 2, 0)
78 testarct(c, 0.0, 9, 8, 0, 1, 1, 1)
80 # testarct(c, 0.5, 11, 8, 0, 1, 0, 0) # not allowed
83 def testmidpointsplit(c):
84 p=path(moveto(1,1), rlineto(2,2), arc(5,2,1,30,300), closepath())
85 bpsplit=p.bpath().MidPointSplit()
86 c.stroke(p, [color.rgb.red])
87 c.stroke(bpsplit, [color.rgb.green, style.linestyle.dashed])
90 def testintersectbezier(c):
91 p=normpath(path(moveto(0,0), curveto(2,6,4,5,2,9)), epsilon=1e-4)
92 q=normpath(path(moveto(2,0), curveto(2,6,4,12,1,6)), epsilon=1e-4)
94 c.stroke(q, [style.linewidth.THIN])
95 c.stroke(p, [style.linewidth.THIN])
97 isect = p.intersect(q)
99 for i in isect[0]:
100 x, y = p.at(i)
101 c.stroke(cross(x, y), [style.linewidth.THIN])
103 def testintersectcircle(c):
104 k=circle(0, 0, 2)
105 l=line(0,0, 3, 0)
106 c.stroke(k, [style.linewidth.THIN])
107 c.stroke(l, [style.linewidth.THIN])
109 isect = k.intersect(l)
110 assert len(isect[0])==1, "double count of intersections"
112 for i in isect[0]:
113 x, y = k.at(i)
114 c.stroke(cross(x, y), [style.linewidth.THIN])
116 def testintersectline(c):
117 l1=line(0, 0, 1, 1)
118 l2=line(0, 1, 1, 0)
119 c.stroke(l1, [style.linewidth.THIN])
120 c.stroke(l2, [style.linewidth.THIN])
122 isect = l1.intersect(l2)
124 for i in isect[0]:
125 x, y = l1.at(i)
126 c.stroke(circle(x, y, 0.1), [style.linewidth.THIN])
129 def testnormpathtrafo(c):
130 p = path(moveto(0, 5),
131 curveto(2, 1, 4, 0, 2, 4),
132 rcurveto(-3, 2, 1, 2, 3, 6),
133 rlineto(0, 3),
134 closepath())
136 c.stroke(p)
137 c.stroke(normpath(p), [color.rgb.green, style.linestyle.dashed])
138 c.stroke(p.transformed(trafo.translate(3,1)), [color.rgb.red])
139 c.insert(canvas.canvas(trafo.translate(3,1))).stroke(p,
140 [color.rgb.green,
141 style.linestyle.dashed])
143 c.stroke(p.reversed(), [color.rgb.blue, style.linestyle.dotted, style.linewidth.THick])
145 c.stroke(cross(*(p.at(0))))
146 c.stroke(cross(*(p.reversed().at(0))))
148 p1, p2 = p.split([1.0, 2.1])
149 c.stroke(p1, [color.rgb.red, style.linestyle.dashed])
150 c.stroke(p2, [color.rgb.green, style.linestyle.dashed])
152 circ1 = circle(0, 10, 1)
153 circ2 = circle(1.7, 10, 1)
155 c.stroke(circ1)
156 c.stroke(circ2)
158 isectcirc1, isectcirc2 = circ1.intersect(circ2)
159 segment1 = circ1.split(isectcirc1)[0]
160 segment2 = circ2.split(isectcirc2)[1]
162 segment = segment1 << segment2
163 segment.append(closepath())
165 c.stroke(segment, [style.linewidth.THick, deco.filled([color.rgb.green])])
167 def testtangent(c):
168 p=path(moveto(0,5),
169 curveto(2,1,4,0,2,4),
170 rcurveto(-3,2,1,2,3,6),
171 rlineto(2,3))+circle(5,5,1)
172 c.stroke(p, [style.linewidth.THick])
173 for i in range(int(p.range())*2):
174 c.stroke(p.tangent(i/2.0, length="20 t pt"), [color.rgb.blue, deco.earrow.normal])
175 c.stroke(line(0, 0, 1, 0).transformed(p.trafo(i/2.0)), [color.rgb.green, deco.earrow.normal])
176 c.stroke(line(0, 0, 0, 1).transformed(p.trafo(i/2.0)), [color.rgb.red, deco.earrow.normal])
178 # test the curvature
179 cc = canvas.canvas()
180 for i in range(int(p.range())*2):
181 radius = p.curvradius(i/2.0)
182 radius = unit.tocm(radius)
183 if radius < 10000:
184 pos = p.trafo(i/2.0).apply(0,radius*radius/abs(radius))
185 cc.stroke(circle(0,0,abs(radius)), [color.grey(0.5), trafo.translate(*pos)])
187 c.insert(cc)#, [canvas.clip(c.bbox().enlarge(1).rect())])
190 def testarcbbox(c):
191 for phi in range(0,360,30):
192 drawpathwbbox(c,path(arc(phi*0.1, phi*0.1, 1, 0, phi)))
194 for phi in range(0,360,30):
195 drawpathwbbox(c,path(arc(phi*0.1, 5+phi*0.1, 1, phi, 360)))
197 for phi in range(0,360,30):
198 drawpathwbbox(c,path(arc(phi*0.1, 10+phi*0.1, 1, phi, phi+30)))
200 for phi in range(0,360,30):
201 drawpathwbbox(c,path(arc(phi*0.1, 15+phi*0.1, 1, phi, phi+120)))
203 for phi in range(0,360,30):
204 drawpathwbbox(c,path(arc(phi*0.1, 20+phi*0.1, 1, phi, phi+210)))
206 for phi in range(0,360,30):
207 drawpathwbbox(c,path(arc(phi*0.1, 25+phi*0.1, 1, phi, phi+300)))
209 for phi in range(0,360,30):
210 drawpathwbbox(c,path(arc(phi*0.1, 30+phi*0.1, 1, phi, phi+390)))
213 for phi in range(0,360,30):
214 drawpathwbbox(c,path(moveto(20+phi*0.1, phi*0.09),
215 arc(20+phi*0.1, phi*0.1, 1, 0, phi)))
217 for phi in range(0,360,30):
218 drawpathwbbox(c,path(moveto(20+phi*0.1, 5+phi*0.11),
219 arc(20+phi*0.1, 5+phi*0.1, 1, 0, phi)))
221 for phi in range(0,360,30):
222 drawpathwbbox(c,path(moveto(20+phi*0.1, 10+phi*0.09),
223 arcn(20+phi*0.1, 10+phi*0.1, 1, 0, phi)))
225 for phi in range(0,360,30):
226 drawpathwbbox(c,path(moveto(20+phi*0.1, 15+phi*0.11),
227 arcn(20+phi*0.1, 15+phi*0.1, 1, 0, phi)))
229 for phi in range(0,360,30):
230 drawpathwbbox(c,path(moveto(50+phi*0.1, phi*0.09),
231 arc(50+phi*0.1, phi*0.1, 1, 0, phi),
232 rlineto(1,1)))
234 for phi in range(0,360,30):
235 drawpathwbbox(c,path(moveto(50+phi*0.1, 5+phi*0.11),
236 arc(50+phi*0.1, 5+phi*0.1, 1, 0, phi),
237 rlineto(1,1)))
239 for phi in range(0,360,30):
240 drawpathwbbox(c,path(moveto(50+phi*0.1, 10+phi*0.09),
241 arcn(50+phi*0.1, 10+phi*0.1, 1, 0, phi),
242 rlineto(1,1)))
244 for phi in range(0,360,30):
245 drawpathwbbox(c,path(moveto(50+phi*0.1, 15+phi*0.11),
246 arcn(50+phi*0.1, 15+phi*0.1, 1, 0, phi),
247 rlineto(1,1)))
250 def testcurvetobbox(c):
251 drawpathwbbox(c,path(moveto(10,60), curveto(12,66,14,65,12,69)))
254 def testtrafobbox(c):
255 sc=c.insert(canvas.canvas(trafo.translate(0,40).rotated(10)))
257 p=path(moveto(10,10), curveto(12,16,14,15,12,19)); drawpathwbbox(sc,p)
258 p=path(moveto(5,17), curveto(6,18, 5,16, 7,15)); drawpathwbbox(sc,p)
261 def testclipbbox(c):
262 clip=canvas.clip(rect(11,11,10,5))
264 p1=path(moveto(10,10), curveto(12,16,14,15,12,19));
265 p2=path(moveto(12,12), curveto(6,18, 5,16, 7,15));
267 # just a simple test for clipping
268 sc=c.insert(canvas.canvas(clip))
269 drawpathwbbox(sc,p1)
270 drawpathwbbox(sc,p2)
272 # more complicated operations
274 # 1. transformation followed by clipping:
275 # in this case, the clipping path will be evaluated in the
276 # context of the already transformed canvas, so that the
277 # actually displayed portion of the path should be the same
279 sc=c.insert(canvas.canvas(trafo.translate(5,0), clip))
280 drawpathwbbox(sc,p1)
281 drawpathwbbox(sc,p2)
283 # 2. clipping followed by transformation
284 # in this case, the clipping path will not be transformed, so
285 # that the display portionof the path should change
287 sc=c.insert(canvas.canvas(clip, trafo.translate(1,1)))
288 drawpathwbbox(sc,p1)
289 drawpathwbbox(sc,p2)
291 def testarclentoparam(c):
292 curve=path(moveto(0,0), lineto(0,5), curveto(5,0,0,10,5,5), closepath(),
293 moveto(5,0), lineto(10,5))
294 ll = curve.arclen()
295 # l=[-0.8*ll, -0.6*ll, -0.4*ll, -0.2*ll, 0, 0.1*ll, 0.3*ll, 0.5*ll, 0.7*ll, 0.9*ll]
296 l=[0, 0.1*ll, 0.2*ll, 0.3*ll, 0.4*ll, 0.5*ll, 0.6*ll, 0.7*ll, 0.8*ll, 0.9*ll]
297 cols=[color.gray.black, color.gray(0.3), color.gray(0.7), color.rgb.red,
298 color.rgb.green, color.rgb.blue, color.cmyk(1,0,0,0),
299 color.cmyk(0,1,0,0), color.cmyk(0,0,1,0), color.gray.black]
300 t=curve.arclentoparam(l)
301 c.stroke(curve)
302 for i in range(len(t)):
303 c.draw(path(circle(curve.at(t[i])[0], curve.at(t[i])[1], 0.1)), [deco.filled([cols[i]]), deco.stroked()])
306 c=canvas.canvas()
307 dotest(c, 0, 0, "testarcs")
308 #dotest(c, 12, 3, "testmidpointsplit")
309 dotest(c, 2, 12, "testintersectbezier")
310 dotest(c, 10,11, "testnormpathtrafo")
311 dotest(c, 12, -4, "testtangent")
312 dotest(c, 5, -4, "testintersectcircle")
313 dotest(c, 9, -4, "testintersectline")
314 dotest(c, 21, 12, "testarclentoparam")
315 c.writeEPSfile("test_path", paperformat="a4", rotated=0, fittosize=1)
317 c=canvas.canvas()
318 testarcbbox(c)
319 testcurvetobbox(c)
320 testtrafobbox(c)
321 testclipbbox(c)
322 c.writeEPSfile("test_bbox", paperformat="a4", rotated=1, fittosize=1)
323 #c.writeEPSfile("test_bbox")