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 = bezierparameterize
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.
Код: Выделить всё
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