1 import sys
; sys
.path
.insert(0, "../..")
8 # I'm missing some basic functionality ...
9 def normpatheltrafo(normpathel
, param
):
10 tx
, ty
= normpathel
.at_pt(param
)
11 tdx
, tdy
= normpathel
.tangentvector_pt(param
)
12 return trafo
.translate_pt(tx
, ty
)*trafo
.rotate(math
.degrees(math
.atan2(tdy
, tdx
)))
14 def normpathelbegintrafo(normpathel
):
15 if isinstance(normpathel
, path
.normcurve
):
16 tx
, ty
= normpathel
.x0_pt
, normpathel
.y0_pt
17 tdx
, tdy
= normpathel
.x1_pt
- normpathel
.x0_pt
, normpathel
.y1_pt
- normpathel
.y0_pt
18 return trafo
.translate_pt(tx
, ty
)*trafo
.rotate(math
.degrees(math
.atan2(tdy
, tdx
)))
20 tx
, ty
= normpathel
.x0_pt
, normpathel
.y0_pt
21 tdx
, tdy
= normpathel
.x1_pt
- normpathel
.x0_pt
, normpathel
.y1_pt
- normpathel
.y0_pt
22 return trafo
.translate_pt(tx
, ty
)*trafo
.rotate(math
.degrees(math
.atan2(tdy
, tdx
)))
24 def normpathelendtrafo(normpathel
):
25 if isinstance(normpathel
, path
.normcurve
):
26 tx
, ty
= normpathel
.x3_pt
, normpathel
.y3_pt
27 tdx
, tdy
= normpathel
.x3_pt
- normpathel
.x2_pt
, normpathel
.y3_pt
- normpathel
.y2_pt
28 return trafo
.translate_pt(tx
, ty
)*trafo
.rotate(math
.degrees(math
.atan2(tdy
, tdx
)))
30 tx
, ty
= normpathel
.x1_pt
, normpathel
.y1_pt
31 tdx
, tdy
= normpathel
.x1_pt
- normpathel
.x0_pt
, normpathel
.y1_pt
- normpathel
.y0_pt
32 return trafo
.translate_pt(tx
, ty
)*trafo
.rotate(math
.degrees(math
.atan2(tdy
, tdx
)))
34 def connect(normpathel1
, normpathel2
, round):
35 "returns a list of normpathels connecting normpathel1 and normpathel2 either rounded or not"
36 # this is for corners, i.e. when there are jumps in the tangent vector
37 t1
= normpathelendtrafo(normpathel1
)
38 t2
= normpathelbegintrafo(normpathel2
)
39 xs
, ys
= t1
._apply(0, 0) # TODO: _apply -> apply_pt
40 xe
, ye
= t2
._apply(0, 0)
41 if (xs
-xe
)*(xs
-xe
) + (xs
-xe
)*(xs
-xe
) < 1e-5**2:
44 # calculate crossing point of normal
46 param
= ((t2
.matrix
[0][1]*(t1
.vector
[1]-t2
.vector
[1]) -
47 t2
.matrix
[1][1]*(t1
.vector
[0]-t2
.vector
[0])) /
48 (t2
.matrix
[1][1]*t1
.matrix
[0][1] -
49 t2
.matrix
[0][1]*t1
.matrix
[1][1]))
50 except ArithmeticError:
51 return [path
.normline(xs
, ys
, xe
, ye
)]
53 # since t1 is a translation + rotation, param is the radius
54 # hence, param should be equal to enlargeby_pt
56 x
, y
= t1
._apply(0, param
)
57 # c.fill(path.circle_pt(x, y, 1))
58 angle1
= math
.atan2(ys
-y
, xs
-x
)
59 angle2
= math
.atan2(ye
-y
, xe
-x
)
60 while angle2
< angle1
:
62 return [path
._arctobcurve
(x
, y
, param
, angle1
, angle2
)]
64 # calculate crossing point of tangents
66 param
= ((t2
.matrix
[0][0]*(t1
.vector
[1]-t2
.vector
[1]) -
67 t2
.matrix
[1][0]*(t1
.vector
[0]-t2
.vector
[0])) /
68 (t2
.matrix
[1][0]*t1
.matrix
[0][0] -
69 t2
.matrix
[0][0]*t1
.matrix
[1][0]))
70 except ArithmeticError:
71 return [path
.normline(xs
, ys
, xe
, ye
)]
73 x
, y
= t1
._apply(param
, 0)
74 return [path
.normline(xs
, ys
, x
, y
), path
.normline(x
, y
, xe
, ye
)]
77 def enlarged(normpath
, enlargeby_pt
, round):
79 for subpath
in normpath
.subpaths
:
80 splitnormpathels
= subpath
.normpathels
[:] # do splitting on a copy
82 while i
< len(splitnormpathels
):
83 if isinstance(splitnormpathels
[i
], path
.normcurve
) and splitnormpathels
[i
].arclen_pt() > 50:
84 splitnormpathels
[i
:i
+1] = splitnormpathels
[i
].midpointsplit()
88 for normpathel
in splitnormpathels
:
89 # get old and new start and end points
90 ts
= normpathelbegintrafo(normpathel
)
91 xs
, ys
= ts
._apply
(0, 0)
92 nxs
, nys
= ts
._apply
(0, -enlargeby_pt
)
93 te
= normpathelendtrafo(normpathel
)
94 xe
, ye
= te
._apply
(0, 0)
95 nxe
, nye
= te
._apply
(0, -enlargeby_pt
)
97 if isinstance(normpathel
, path
.normcurve
):
98 # We should do not alter the sign. Could we do any better here?
100 cs
= 1/(normpathel
.curvradius_pt(0) + enlargeby_pt
)
101 except ArithmeticError:
104 ce
= 1/(normpathel
.curvradius_pt(1) + enlargeby_pt
)
105 except ArithmeticError:
108 # this should be a function (in path?), not a method in a class
109 # the parameter convention is quite different from other places ...
110 bezierparams
= deco
.smoothed
.normal
._onebezierbetweentwopathels
((nxs
, nys
), (nxe
, nye
),
111 (ts
.matrix
[0][0], ts
.matrix
[1][0]),
112 (te
.matrix
[0][0], te
.matrix
[1][0]),
114 c
.fill(path
.circle_pt(bezierparams
[0][0], bezierparams
[0][1], 1), [color
.rgb
.blue
])
115 c
.fill(path
.circle_pt(bezierparams
[3][0], bezierparams
[3][1], 1), [color
.rgb
.blue
])
116 newnormpathel
= path
.normcurve(bezierparams
[0][0], bezierparams
[0][1],
117 bezierparams
[1][0], bezierparams
[1][1],
118 bezierparams
[2][0], bezierparams
[2][1],
119 bezierparams
[3][0], bezierparams
[3][1])
120 showtangent(newnormpathel
)
121 showcircle(newnormpathel
)
124 newnormpathel
= path
.normline(nxs
, nys
, nxe
, nye
)
126 if len(newnormpathels
):
127 newnormpathels
.extend(connect(newnormpathels
[-1], newnormpathel
, round=round))
128 newnormpathels
.append(newnormpathel
)
130 newnormpathels
.extend(connect(newnormpathels
[-1], newnormpathels
[0], round=round))
131 newnormsubpaths
.append(path
.normsubpath(newnormpathels
, subpath
.closed
))
132 return path
.normpath(newnormsubpaths
)
135 def showtangent(normcurve
):
139 cx
= 3*normcurve
.x1_pt
- 3*normcurve
.x0_pt
140 bx
= 3*normcurve
.x2_pt
- 6*normcurve
.x1_pt
+ 3*normcurve
.x0_pt
141 ax
= normcurve
.x3_pt
- 3*normcurve
.x2_pt
+ 3*normcurve
.x1_pt
- normcurve
.x0_pt
143 cy
= 3*normcurve
.y1_pt
- 3*normcurve
.y0_pt
144 by
= 3*normcurve
.y2_pt
- 6*normcurve
.y1_pt
+ 3*normcurve
.y0_pt
145 ay
= normcurve
.y3_pt
- 3*normcurve
.y2_pt
+ 3*normcurve
.y1_pt
- normcurve
.y0_pt
147 x
= - (dy
*bx
-dx
*by
)/(3.0*dy
*ax
-3.0*dx
*ay
)
148 s
= math
.sqrt(x
*x
-(dy
*cx
-dx
*cy
)/(3.0*dy
*ax
-3.0*dx
*ay
))
157 trafo
= normpatheltrafo(normcurve
, t
)
158 c
.stroke(path
.line_pt(*list(trafo
._apply
(-100, 0))+list(trafo
._apply
(100, 0))), [color
.rgb
.red
])
160 def showcircle(normcurve
):
165 cos
= dx
/math
.sqrt(dx
*dx
+dy
*dy
)
166 sin
= dy
/math
.sqrt(dx
*dx
+dy
*dy
)
170 cx
= 3*normcurve
.x1_pt
- 3*normcurve
.x0_pt
171 bx
= 3*normcurve
.x2_pt
- 6*normcurve
.x1_pt
+ 3*normcurve
.x0_pt
172 ax
= normcurve
.x3_pt
- 3*normcurve
.x2_pt
+ 3*normcurve
.x1_pt
- normcurve
.x0_pt
174 cy
= 3*normcurve
.y1_pt
- 3*normcurve
.y0_pt
175 by
= 3*normcurve
.y2_pt
- 6*normcurve
.y1_pt
+ 3*normcurve
.y0_pt
176 ay
= normcurve
.y3_pt
- 3*normcurve
.y2_pt
+ 3*normcurve
.y1_pt
- normcurve
.y0_pt
179 return ax
*t
*t
*t
+bx
*t
*t
+cx
*t
+normcurve
.x0_pt
181 return ay
*t
*t
*t
+by
*t
*t
+cy
*t
+normcurve
.y0_pt
183 return 3*ax
*t
*t
+2*bx
*t
+cx
185 return 3*ay
*t
*t
+2*by
*t
+cy
191 return cos
*(x(t
)-x0
)+sin
*(y(t
)-y0
)+sign
*math
.sqrt(r
*r
-(sin
*(x(t
)-x0
)-cos
*(y(t
)-y0
))**2)
193 return cos
*xdot(t
)+sin
*ydot(t
)-sign
*((sin
*(x(t
)-x0
)-cos
*(y(t
)-y0
))*
194 (sin
*xdot(t
)-cos
*ydot(t
))/
195 math
.sqrt(r
*r
-(sin
*(x(t
)-x0
)-cos
*(y(t
)-y0
))**2))
197 return (x(t
)-x0
-l(t
, sign
)*cos
)*xdot(t
)+(y(t
)-y0
-l(t
, sign
)*sin
)*ydot(t
)
199 return ((x(t
)-x0
-l(t
, sign
)*cos
)*xddot(t
)+(xdot(t
)-ldot(t
, sign
)*cos
)*xdot(t
)+
200 (y(t
)-y0
-l(t
, sign
)*sin
)*yddot(t
)+(ydot(t
)-ldot(t
, sign
)*sin
)*ydot(t
))
202 return sin
*(x(t
)-x0
)-cos
*(y(t
)-y0
)
204 return sin
*xdot(t
)-cos
*ydot(t
)
206 x
= - (sin
*bx
-cos
*by
)/(3.0*sin
*ax
-3.0*cos
*ay
)
207 s
= math
.sqrt(x
*x
-(sin
*cx
-cos
*cy
)/(3.0*sin
*ax
-3.0*cos
*ay
))
210 #print startdot(t1), startdot(t2), start(t1), start(t2)
211 startt1
, startt2
= start(t1
), start(t2
)
212 #print startt1, startt2
213 if startt1
*startt2
< 0:
214 while abs(startt1
)+abs(startt2
) > 1e-5:
217 if starttn
*startt1
< 0:
218 t2
, startt2
= tn
, starttn
220 t1
, startt1
= tn
, starttn
222 elif abs(startt1
) < abs(startt2
):
232 while abs(isz
) > 1e-5:
234 ist
-= 0.05*isz
/ zdot(ist
, sign
) # overshoots lead to nan-results ...
242 if ist
is not None and 0 < ist
< 1:
244 c
.fill(path
.circle_pt(x(ist
), y(ist
), 1), [color
.rgb
.green
])
245 c
.stroke(path
.circle_pt(x0
+isl
*cos
, y0
+isl
*sin
, r
), [color
.rgb
.green
])
248 # parameters for the enlargement:
250 round = 0 # a boolean to turn round corners on and off
253 for normpath
in [path
.normpath(path
.rect(0, 0, 5, 5)),
254 path
.normpath(path
.circle(10, 3, 3)),
255 path
.normpath(path
.path(path
.moveto(0, 8),
256 path
.curveto(1, 8, 1, 9, 2, 11),
257 path
.curveto(1, 12, 1, 12, 0, 11),
260 path
.normpath(path
.path(path
.moveto(5, 8),
261 path
.curveto(20, 8, 6, 9, 7, 11),
262 path
.curveto(6, 12, 6, 12, 5, 11),
265 path
.normpath(path
.path(path
.moveto(16, 0),
266 path
.curveto(18, 0, 18, 4, 20, 4),
268 path
.curveto(12, 12, 20, 8, 16, 8),
271 c
.stroke(enlarged(normpath
, enlargeby_pt
, round), [color
.rgb
.blue
])
273 c
.writeEPSfile("newbox")