Java 立方Bé;返回错误结果的zier公式

Java 立方Bé;返回错误结果的zier公式,java,bezier,curve,Java,Bezier,Curve,我在Java中创建了一个非常简单的三次Bézier形式,以便在给定时间(t)的情况下检索点的Y值。在我的实现中,我的第一个(P1)点和最后一个(P4)点总是分别为(0,0)和(1,1),我将只处理P1和P2。这样做的目的是创建一条可修改的曲线,用于检索一个值,该值将用于乘法和操纵其他值,如视频游戏中的难度渐变 我已经使用P2=(0.1,0.1)和P3=(0.9,0.9)测试了我的实现,因此曲线实际上应该是一条直线,无论我的输入值(t)是什么,输出都应该模拟: 这是我的CubicBezier课程

我在Java中创建了一个非常简单的三次Bézier形式,以便在给定时间(t)的情况下检索点的Y值。在我的实现中,我的第一个(P1)点和最后一个(P4)点总是分别为(0,0)和(1,1),我将只处理P1和P2。这样做的目的是创建一条可修改的曲线,用于检索一个值,该值将用于乘法和操纵其他值,如视频游戏中的难度渐变

我已经使用P2=(0.1,0.1)和P3=(0.9,0.9)测试了我的实现,因此曲线实际上应该是一条直线,无论我的输入值(t)是什么,输出都应该模拟:

这是我的CubicBezier课程:

@AllArgsConstructor
public class CubicBezier {

    private static final Point P1 = new Point(0, 0);
    private static final Point P4 = new Point(1, 1);

    private Point p2;
    private Point p3;

    public double getValue(double t) {
        double dt = 1d - t;
        double dt2 = dt*dt;
        double t2 = t*t;

        Point temp = p2.copy();

        return P1.copy()
                 .scale(dt2 * dt)
                 .add(temp.scale(3 * dt2 * t))
                 .add(temp.set(p3).scale(3 * dt * t2))
                 .add(temp.set(P4).scale(t2 * t))
                 .getY();
    }
}
我的观点是:

@Data
@AllArgsConstructor
public class Point {
    private double x;
    private double y;

    public Point(Point point) {
        this.x = point.x;
        this.y = point.y;
    }

    public Point copy() {
        return new Point(this);
    }

    public Point set(Point point) {
        this.x = point.x;
        this.y = point.y;
        return this;
    }

    public Point add(double scalar) {
        this.x += scalar;
        this.y += scalar;
        return this;
    }

    public Point add(double x, double y) {
        this.x += x;
        this.y += y;
        return this;
    }

    public Point add(Point point) {
        return add(point.x, point.y);
    }

    public Point scale(double scalar) {
        this.x *= scalar;
        this.y *= scalar;
        return this;
    }

    public Point scale(double x, double y) {
        this.x *= x;
        this.y *= y;
        return this;
    }

    public Point scale(Point point) {
        return scale(point.x, point.y);
    }

}
我的主要方法是:

public static void main(String[] args) {
    CubicBezier bezier = new CubicBezier(new Point(0.1d, 0.1d), new Point(0.9d, 0.9d));

    double value = 0.4;
    System.out.println(value + ": " + bezier.getValue(value));
}
预期产出应为:

0.4: 0.4
但是,我收到的输出是:

0.4: 0.36640000000000006
我不明白为什么。我的
getValue
方法是使用。我错过什么了吗

注意:我正在使用Lombok删除一些样板文件。如有必要,我可以指定此样板

编辑:


因此,看起来我的贝塞尔曲线实际工作正常,我一直误认为
t
x
轴上的值,假设计算出的贝塞尔曲线的
y
值将与
x
轴相关。我想要的功能是,对于生成的曲线,给定一个值
x
,返回与之相关的
y
值。所以在上面的截图中,曲线是一条直线,
x
应该等于
y

我找到了问题的答案。我的代码从来没有任何错误,错误是缺乏理解。我曾假设,因为
P1
p2
p3
P4
都是位于x轴和y轴上0和1之间的直线上的点,所以无论它们位于该直线上的何处,时间都会以相同的方式反映进程,即
x
将等于
y

然而,由于
p2
p3
分别更接近
P0
P4
,因此沿着曲线的进程相对于时间被拉伸

为了使三次贝塞尔曲线的级数(
y
)值与时间(
t
)值相同,其中
P1=(0,0)
P4=(1,1)
,两个内点必须沿曲线在两个轴上均匀分布。因此,
p2
必须是
(0.33333,0.33333)
p3
必须是
(0.66666,0.666666)


此问题的示例如所示。当这些点分散开来时,结果值会受到影响。

请看这是否解释了我在实际输出中所经历的0.0336的巨大损失?不一定。我看到了p2的声明位置,但在调用p2.copy()之前,我看不到在哪里给它赋值;那是龙目巨人的@AllArgsConstructor。请参见
new CubicBezier(新点(0.1d,0.1d),新点(0.9d,0.9d))
其中p2=
(0.1d,0.1d)
而您仍然不在那里:单个
t
值定义了
x
y
值。P2和P3根本不必是1/3和2/3,但是如果你没有选择那些精确的间隔,那么需要做的是,如果你有一个
x
值,你需要找到产生
x
t
值,然后使用找到的
t
值来计算相关的
y
:这是我无法找到的黄金信息。非常感谢。