数学解贝塞尔曲线和直线相交在咖啡脚本(或任何语言我懂)



我发现了一个关于…的论坛问题

Function intersectBezier3Line(x1#,y1#,vx1#,vy1#,x2#,y2#,vx2#,vy2#,L1x#,L1y#,L2x#,L2y#)
        Local A#,B#,C#,E#,F#,G#,La#,Lb#,Lc#,Solution#
                A=3*vx1+x2-(3*vx2)-x1
        B=3*x1-(6*vx1)+(3*vx2)
        C=3*vx1-(3*x1)
                E=3*vy1+y2-(3*vy2)-y1
        F=3*y1-(6*vy1)+(3*vy2)
        G=3*vy1-(3*y1)
        La=L2y-L1y
        Lb=L1x-L2x
        Lc=L1y*(L2x-L1x) + L1x*(L1y-L2y)

                ax(4)=La*x1 + Lb*y1 + Lc
        ax(3)=La*C  + Lb*G
        ax(2)=La*B  + Lb*F
        ax(1)=La*A  + Lb*E
       FindRootsPoly3(ax(4),ax(3),ax(2),ax(1)) 
End Function
Function  FindRootsPoly3(A3#,A2#,A1#,A0#)
    Local fc2#,gc2#,hc2#,Rc2#,Sc2#,Tc2#,Uc2#,ic2#,jc2#,kc2#,Lc2#,Mc2#,Nc2#,Pc2#
    fc2 =( (3*A1/A3) - ((A2^2)/(A3^2) ))/ 3
    gc2=(( (2*A2^3)/(A3^3)) - (9*A2*A1/(A3^2)) + (27*A0/A3)) / 27
    hc2 = ((gc2^2)/4) + ((fc2^3)/27)
    If hc2>0 Then
                Rc2 = -(gc2/2) + (Sqr(hc2))
                If Rc2<0 Then 
                    Sc2 = -(Abs(Rc2)^0.333333)
                Else
                    Sc2 = ((Rc2))^0.333333
                EndIf
                Tc2 = -(gc2/2) -( Sqr(hc2))
                If Tc2<0 Then 
                    Uc2 = -(Abs(Tc2)^0.333333)
                Else
                    Uc2 = (Tc2)^0.333333
                EndIf
                Rx(0) = (Sc2 + Uc2) - (A2/(3*A3))
                Else
                If hc2=0 And gc2=0 And fc2=0 Then
                    Rx(0) =-((A0/A3)^0.3333333 )
                Else
                    If hc2<0 Or hc2=0 Then
                        ic2= Sqr(((gc2^2)/4) - hc2)
                        jc2 = (ic2)^0.333333
                        kc2 = ACos (- (gc2 / (2*ic2)))
                        Lc2 = -jc2
                        Mc2 = Cos (kc2/3)
                        Nc2 = Sqr( 3) * Sin (kc2/3)
                        Pc2 = -(A2/(3*A3))
                        Rx(0) = 2*jc2 * Cos(kc2/3) -(A2/(3*A3))
                        Rx(1) = Lc2 * (Mc2 + Nc2) + Pc2
                        Rx(2) = Lc2 * (Mc2 - Nc2) + Pc2
                   EndIf        
              EndIf
    EndIf
End Function

我期望以某种方式输出一条直线和贝塞尔曲线之间的交点。我翻译成咖啡文字

intersectBezier3Line = (x1,y1,vx1,vy1,x2,y2,vx2,vy2,L1x,L1y,L2x,L2y)->
  A=3*vx1+x2-(3*vx2)-x1
  B=3*x1-(6*vx1)+(3*vx2)
  C=3*vx1-(3*x1)
  E=3*vy1+y2-(3*vy2)-y1
  F=3*y1-(6*vy1)+(3*vy2)
  G=3*vy1-(3*y1)
  La=L2y-L1y
  Lb=L1x-L2x
  Lc=L1y*(L2x-L1x) + L1x*(L1y-L2y)
  ax = [
    La*x1 + Lb*y1 + Lc
    La*C  + Lb*G
    La*B  + Lb*F
    La*A  + Lb*E
  ]
  FindRootsPoly3 ax[3],ax[2],ax[1],ax[0]
pow = (x,y)-> Math.pow x,y
sqr = (x)-> x*x 
FindRootsPoly3 = (A3,A2,A1,A0)->
  fc2 = ((3*A1 / A3) - ( pow(A2,2) / pow(A3,2) ))/ 3
  gc2 = (( (2*pow(A2,3)) / pow(A3,3)) - (9*A2*A1 / pow(A3,2)) + (27*A0 / A3)) / 27
  hc2 = (pow(gc2,2)/4) + (pow(fc2,3)/27)
  Rx = []
  if hc2>0
    Rc2 = -(gc2/2) + (sqr(hc2))
    if Rc2<0
      Sc2 = -(pow(Math.abs(Rc2),0.333333))
    else
      Sc2 = pow(((Rc2)),0.333333)
    Tc2 = -(gc2/2) - ( sqr(hc2))
    if Tc2<0
      Uc2 = -pow(Math.abs(Tc2),0.333333)
    else
      Uc2 = pow((Tc2),0.333333)
    Rx[0] = (Sc2 + Uc2) - (A2/(3*A3))
  else
    if hc2==0 and gc2==0 and fc2==0
      Rx[0] = -pow((A0/A3),0.3333333 )
    else
      if hc2<0 or hc2==0
        ic2 = sqr((pow(gc2,2)/4) - hc2)
        jc2 = pow((ic2),0.333333)
        kc2 = Math.acos( -(gc2 / (2*ic2)))
        Lc2 = -jc2
        Mc2 = Math.cos(kc2/3)
        Nc2 = sqr( 3) * Math.sin(kc2/3)
        Pc2 = -(A2/(3*A3))
        Rx[0] = 2*jc2 * Math.cos(kc2 / 3) - (A2/(3*A3))
        Rx[1] = Lc2 * (Mc2 + Nc2) + Pc2
        Rx[2] = Lc2 * (Mc2 - Nc2) + Pc2
  Rx

有时(有一些输入)它输出一些东西,但主要是NaNundefined。我不知道它到底应该输出什么,它是初始贝塞尔曲线上t的值吗?

而且,它显然不能正常工作。有人能看出我的翻译或初始代码有什么问题吗?

我真的希望能够在数学上与javascript/coffeescript中的一条线相交贝塞尔曲线!

你最大的错误是在vbscript Sqr不是"平方",它是"平方根"

编辑:(不介意之前在这里的评论)

编辑二:你的翻译没有问题,但似乎原始代码在定义要解决的多项式时有一些错误:

bezier4poly = (A,B,C,D) ->
    [
        -A + 3*B + -3*C + D 
        3*A - 6*B + 3*C
        -3*A + 3*B
        A 
    ]
intersectBezier3Line2 = (Px0,Py0,Px1,Py1,Px2,Py2,Px3,Py3,Lx0,Ly0,Lx1,Ly1)->
    ### (x_2 - x_1)(y - y_1)=(y_2 - y_1)(x - x_1) =>  ### 
    ###(y_1 - y_2)x + (x_2 - x_1)y   + (x_1(y_2 - y_1) + - y_1(x_2 - x_1)) =>  Ax + By + C = 0  ###
    A=Ly0-Ly1
    B=Lx1-Lx0
    C=Lx0*(Ly1-Ly0) + -Ly0*(Lx1-Lx0)
    ax = bezier4poly(Px0,Px1,Px2,Px3)
    ay = bezier4poly(Py0,Py1,Py2,Py3)
    p = [
        A*ax[0] + B*ay[0]
        A*ax[1] + B*ay[1]
        A*ax[2] + B*ay[2]
        A*ax[3] + B*ay[3]  + C
    ]
    findRootsPoly3 p[0],p[1],p[2],p[3]

使用this,取this的结果并对

排序
intersectBezier3Line2(0,0,1,0,0,1,1,1,0,0,1,1)

[-6.212270483585414e-7, 0.49999999999999994, 1.0000006212270485]

这接近于我直觉上的t值,t的贝塞尔曲线在(0,0),(1,1)定义的直线旁边,但我并没有接近于称这个错误没有,它只是"似乎有效"。

如果你知道Obj-C我张贴了一个关于创建贝塞尔曲线的问题。有了正确的答案,这是一个有效的功能。

objective-c中的贝塞尔曲线算法需要调整

最新更新