C# 求解贝塞尔曲线

C# 求解贝塞尔曲线,c#,bezier,C#,Bezier,我正在为相机的运动控制器编写代码,贝塞尔曲线方程用于使运动平滑 由于我的数学能力不是很强,我使用了这个“stackoverflow”答案上的代码,这要感谢成员“Daniel Wolf” 使用系统; 公共课点{ 公共点(双x,双y) { X=X; Y=Y; } 公共双X{get;私有集;} 公共双Y{get;私有集;} } 公共类贝塞尔曲线{ 公共贝塞尔曲线(点p0、点p1、点p2、点p3){ P0=P0; P1=P1; P2=P2; P3=P3; } 公共点P0{get;私有集;} 公共点P1{

我正在为相机的运动控制器编写代码,贝塞尔曲线方程用于使运动平滑

由于我的数学能力不是很强,我使用了这个“stackoverflow”答案上的代码,这要感谢成员“Daniel Wolf”

使用系统;
公共课点{
公共点(双x,双y)
{
X=X;
Y=Y;
}
公共双X{get;私有集;}
公共双Y{get;私有集;}
}
公共类贝塞尔曲线{
公共贝塞尔曲线(点p0、点p1、点p2、点p3){
P0=P0;
P1=P1;
P2=P2;
P3=P3;
}
公共点P0{get;私有集;}
公共点P1{get;private set;}
公共点P2{get;private set;}
公共点P3{get;private set;}
公共双人间(双人间){
//确定t
双t;
如果(x==P0.x){
//明确处理角点情况以防止舍入错误
t=0;
}else如果(x==P3.x){
t=1;
}否则{
//计算t
双a=-P0.X+3*P1.X-3*P2.X+P3.X;
双b=3*P0.X-6*P1.X+3*P2.X;
双c=-3*P0.X+3*P1.X;
双d=P0.X-X;
双?tTemp=立方(a、b、c、d);
if(tTemp==null)返回null;
t=tTemp.值;
}
//从t计算y
返回立方(1-t)*P0.Y
+3*t*平方(1-t)*P1.Y
+3*平方(t)*(1-t)*P2.Y
+立方(t)*P3.Y;
}
//求解xϵ的方程ax³+bx²+cx+d=0ℝ
//并返回[0,1]中的第一个结果或null。
专用静态双精度(双精度a、双精度b、双精度c、双精度d){
如果(a==0)返回(b,c,d);
如果(d==0)返回0;
b/=a;
c/=a;
d/=a;
双q=(3.0*c-平方(b))/9.0;
双r=(-27.0*d+b*(9.0*c-2.0*平方(b)))/54.0;
双圆盘=立方(q)+平方(r);
双端1=b/3.0;
如果(光盘>0){
双s=r+Math.Sqrt(圆盘);
s=(s<0)?-立方英尺(-s):立方英尺(s);
双t=r-数学Sqrt(disc);
t=(t<0)?-立方英尺(-t):立方英尺(t);
双结果=-term1+s+t;

如果(result>=0&&result=0&&result=0&&result=0&&result=0&&result=0&&result=0&&result=0&&result如果你解决了这个问题,请发布一个答案,如果你认为这个问题是其他人也会遇到的问题,或者删除你的帖子,这样人们就不会在将来遇到这个问题,而只是为了发现“存在”一个解决方案,但没有人费心说它是什么。鉴于这个问题有投票权,写解决方案而不是删除可能是正确的方式。如果你解决了问题,请发布一个答案,因为你认为这个问题也会遇到,或者删除你的帖子,让人们寻找他们问题的答案em不会在将来遇到它,只是发现“有”一个解决方案,但没有人愿意说它是什么。考虑到这个问题有投票权,编写解决方案而不是删除可能是正确的方法。
using System;
public class Point {
public Point(double x, double y) 
{
    X = x;
    Y = y;
}
public double X { get; private set; }
public double Y { get; private set; }
}

public class BezierCurve {
public BezierCurve(Point p0, Point p1, Point p2, Point p3) {
    P0 = p0;
    P1 = p1;
    P2 = p2;
    P3 = p3;
}

public Point P0 { get; private set; }
public Point P1 { get; private set; }
public Point P2 { get; private set; }
public Point P3 { get; private set; }

public double? GetY(double x) {
    // Determine t
    double t;
    if (x == P0.X) {
        // Handle corner cases explicitly to prevent rounding errors
        t = 0;
    } else if (x == P3.X) {
        t = 1;
    } else {
        // Calculate t
        double a = -P0.X + 3 * P1.X - 3 * P2.X + P3.X;
        double b = 3 * P0.X - 6 * P1.X + 3 * P2.X;
        double c = -3 * P0.X + 3 * P1.X;
        double d = P0.X - x;
        double? tTemp = SolveCubic(a, b, c, d);
        if (tTemp == null) return null;
        t = tTemp.Value;
    }

    // Calculate y from t
    return Cubed(1 - t) * P0.Y
        + 3 * t * Squared(1 - t) * P1.Y
        + 3 * Squared(t) * (1 - t) * P2.Y
        + Cubed(t) * P3.Y;
}

// Solves the equation ax³+bx²+cx+d = 0 for x ϵ ℝ
// and returns the first result in [0, 1] or null.
private static double? SolveCubic(double a, double b, double c, double d) {
    if (a == 0) return SolveQuadratic(b, c, d);
    if (d == 0) return 0;

    b /= a;
    c /= a;
    d /= a;
    double q = (3.0 * c - Squared(b)) / 9.0;
    double r = (-27.0 * d + b * (9.0 * c - 2.0 * Squared(b))) / 54.0;
    double disc = Cubed(q) + Squared(r);
    double term1 = b / 3.0;

    if (disc > 0) {
        double s = r + Math.Sqrt(disc);
        s = (s < 0) ? -CubicRoot(-s) : CubicRoot(s);
        double t = r - Math.Sqrt(disc);
        t = (t < 0) ? -CubicRoot(-t) : CubicRoot(t);

        double result = -term1 + s + t;
        if (result >= 0 && result <= 1) return result;
    } else if (disc == 0) {
        double r13 = (r < 0) ? -CubicRoot(-r) : CubicRoot(r);

        double result = -term1 + 2.0 * r13;
        if (result >= 0 && result <= 1) return result;

        result = -(r13 + term1);
        if (result >= 0 && result <= 1) return result;
    } else {
        q = -q;
        double dum1 = q * q * q;
        dum1 = Math.Acos(r / Math.Sqrt(dum1));
        double r13 = 2.0 * Math.Sqrt(q);

        double result = -term1 + r13 * Math.Cos(dum1 / 3.0);
        if (result >= 0 && result <= 1) return result;

        result = -term1 + r13 * Math.Cos((dum1 + 2.0 * Math.PI) / 3.0);
        if (result >= 0 && result <= 1) return result;

        result = -term1 + r13 * Math.Cos((dum1 + 4.0 * Math.PI) / 3.0);
        if (result >= 0 && result <= 1) return result;
    }

    return null;
}

// Solves the equation ax² + bx + c = 0 for x ϵ ℝ
// and returns the first result in [0, 1] or null.
private static double? SolveQuadratic(double a, double b, double c) {
    double result = (-b + Math.Sqrt(Squared(b) - 4 * a * c)) / (2 * a);
    if (result >= 0 && result <= 1) return result;

    result = (-b - Math.Sqrt(Squared(b) - 4 * a * c)) / (2 * a);
    if (result >= 0 && result <= 1) return result;

    return null;
}

private static double Squared(double f) { return f * f; }

private static double Cubed(double f) { return f * f * f; }

private static double CubicRoot(double f) { return Math.Pow(f, 1.0 / 3.0); }
}