Inkscape's bezmisc.py improvements English version
Добавлено: 16 мар 2010, 16:11
While developing Gcode tools extension found that bezmisc.py needs some improvements:
1. bezierparameterize function
This corrections have effect if one or more tangents are zeros.
If one tangent equals 0 Bezier's cubic path becomes Bezier quadratic path if both tangents are zeros it will become a straight line. Without this correction bezierslopeatt will give a 0 near the end with 0 tangent.
2. Here's remade linebezierintersect to csp_line_intersection wit a cubic solver
It's not exact line and bezier intersect but line and cubic super path, which are in fact almost the same. And additional cubic solver.
1. bezierparameterize function
This corrections have effect if one or more tangents are zeros.
If one tangent equals 0 Bezier's cubic path becomes Bezier quadratic path if both tangents are zeros it will become a straight line. Without this correction bezierslopeatt will give a 0 near the end with 0 tangent.
Код: Выделить всё
def bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))):
#parametric bezier
ax,ay,bx,by,cx,cy,x0,y0 = 0, 0, 0, 0, 0, 0, 0, 0
if (bx0,by0)==(bx1,by1) and (bx2,by2)==(bx3,by3):
x0=bx0
cx=bx3-bx0
y0=by0
cy=by3-by0
elif (bx2,by2)==(bx3,by3) :
x0=bx0
cx = (bx1-bx0)*2
bx = bx0-2*bx1+bx2
y0=by0
cy = (by1-by0)*2
by = by0-2*by1+by2
elif (bx0,by0)==(bx1,by1) :
x0=bx1
cx = (bx2-bx1)*2
bx = bx1-2*bx2+bx3
y0=by1
cy = (by2-by1)*2
by = by1-2*by2+by3
else:
x0=bx0
y0=by0
cx=3*(bx1-x0)
bx=3*(bx2-bx1)-cx
ax=bx3-x0-cx-bx
cy=3*(by1-y0)
by=3*(by2-by1)-cy
ay=by3-y0-cy-by
return ax,ay,bx,by,cx,cy,x0,y0
bezmisc.bezierparameterize = bezierparameterizeIt's not exact line and bezier intersect but line and cubic super path, which are in fact almost the same. And additional cubic solver.
Код: Выделить всё
def cubic_solver(a,b,c,d):
if a!=0:
# Monics formula see http://en.wikipedia.org/wiki/Cubic_function#Monic_formula_of_roots
a,b,c = (b/a, c/a, d/a)
m = 2*a**3 - 9*a*b + 27*c
k = a**2 - 3*b
n = m**2 - 4*k**3
w1 = -.5 + .5*cmath.sqrt(3)*1j
w2 = -.5 - .5*cmath.sqrt(3)*1j
m1 = pow(complex((m+cmath.sqrt(n))/2),1./3)
n1 = pow(complex((m-cmath.sqrt(n))/2),1./3)
x1 = -1./3 * (a + m1 + n1)
x2 = -1./3 * (a + w1*m1 + w2*n1)
x3 = -1./3 * (a + w2*m1 + w1*n1)
return [x1,x2,x3]
elif b!=0:
det = c**2-4*b*d
if det>0 :
return [(-c+math.sqrt(det))/(2*b),(-c-math.sqrt(det))/(2*b)]
elif d == 0 :
return [-c/(b*b)]
else :
return [(-c+cmath.sqrt(det))/(2*b),(-c-cmath.sqrt(det))/(2*b)]
elif c!=0 :
return [-d/c]
else : return []
def csp_line_intersection(l1,l2,sp1,sp2):
dd=l1[0]
cc=l2[0]-l1[0]
bb=l1[1]
aa=l2[1]-l1[1]
if aa==cc==0 : return []
if aa:
coef1=cc/aa
coef2=1
else:
coef1=1
coef2=aa/cc
bez = (sp1[1][:],sp1[2][:],sp2[0][:],sp2[1][:])
ax,ay,bx,by,cx,cy,x0,y0=bezmisc.bezierparameterize(bez)
a=coef1*ay-coef2*ax
b=coef1*by-coef2*bx
c=coef1*cy-coef2*cx
d=coef1*(y0-bb)-coef2*(x0-dd)
roots = cubic_solver(a,b,c,d)
retval = []
for i in roots :
if type(i) is complex and i.imag==0:
i = i.real
if type(i) is not complex and 0<=i<=1:
retval.append(i)
return retval