Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java bezier裁剪中距离函数计算的难点_Java_Graphics_Geometry_Processing_Bezier - Fatal编程技术网

Java bezier裁剪中距离函数计算的难点

Java bezier裁剪中距离函数计算的难点,java,graphics,geometry,processing,bezier,Java,Graphics,Geometry,Processing,Bezier,我正在尝试实现一种称为bezier裁剪的曲线兴趣分割算法,该算法在文章末尾的一节中进行了描述(尽管本文称之为“胖线裁剪”)。我已经看完了本文和示例的源代码(可用) 注:其他来源包括。如果我能找到他们,更多的将被张贴 该算法的核心部分是计算曲线1和曲线2的“基线”(即从曲线2的一个端点到另一个端点的直线)之间的“距离函数”。所以我有一些东西来比较我的结果,我使用了第一个例子的源代码中的曲线。我成功地复制了示例中距离函数的形状,但函数的距离位置已关闭。在尝试另一条曲线时,距离函数与其他两条曲线并不接

我正在尝试实现一种称为bezier裁剪的曲线兴趣分割算法,该算法在文章末尾的一节中进行了描述(尽管本文称之为“胖线裁剪”)。我已经看完了本文和示例的源代码(可用)

注:其他来源包括。如果我能找到他们,更多的将被张贴

该算法的核心部分是计算曲线1和曲线2的“基线”(即从曲线2的一个端点到另一个端点的直线)之间的“距离函数”。所以我有一些东西来比较我的结果,我使用了第一个例子的源代码中的曲线。我成功地复制了示例中距离函数的形状,但函数的距离位置已关闭。在尝试另一条曲线时,距离函数与其他两条曲线并不接近,尽管它们明显相交。我可能对这个算法的工作原理很幼稚,但我认为这会导致没有检测到交叉点

根据我的理解(这很可能是错误的),定义距离函数的过程涉及以xa+yb+c=0的形式表示曲线2的基线,其中a2+b2=1。系数是通过将线的项重新排列成y=ux+v的形式获得的,其中u等于斜率,x和y是基线上的任意点。该公式可以重新排列,得到vv=y-ux。重新排列公式,我们得到-u*x+1*y-v=0,其中a=-ub=1,和c=-v。为确保条件a2+b2=1,将系数除以Math.sqrt(uu+1)的标量。然后将该线的表示替换为另一条曲线(基线未关联的曲线)的函数,以获得距离函数。该距离函数用贝塞尔曲线表示,其中yi=aPi x+b*Pi y+cxi=(1-t)x1+tx2,其中t等于0,1/3,2/3,3mx1x2是基线的端点,和Pi是曲线1的控制点

下面是计算距离函数的示例程序(用语言处理编写)的一些源代码片段,奇怪的是,该程序使用了与上段稍有不同的方法来计算基线的替代表示形式

/**
 * Set up four points, to form a cubic curve, and a static curve that is used for intersection checks
 */
void setupPoints()
{
points = new Point[4];
points[0] = new Point(85,30);
points[1] = new Point(180,50);
points[2] = new Point(30,155);
points[3] = new Point(130,160);

curve = new Bezier3(175,25,  55,40,  140,140,  85,210);
curve.setShowControlPoints(false);
}

...

flcurve = new Bezier3(points[0].getX(), points[0].getY(),
                                        points[1].getX(), points[1].getY(),
                                        points[2].getX(), points[2].getY(),
                                        points[3].getX(), points[3].getY());

...

void drawClipping()
{
    double[] bounds = flcurve.getBoundingBox();

    // get the distances from C1's baseline to the two other lines
    Point p0 = flcurve.points[0];
    // offset distances from baseline
    double dx = p0.x - bounds[0];
    double dy = p0.y - bounds[1];
    double d1 = sqrt(dx*dx+dy*dy);
    dx = p0.x - bounds[2];
    dy = p0.y - bounds[3];
    double d2 = sqrt(dx*dx+dy*dy);

    ...

    double a, b, c;
a = dy / dx;
b = -1;
c = -(a * flcurve.points[0].x - flcurve.points[0].y);
// normalize so that a² + b² = 1
double scale = sqrt(a*a+b*b);
a /= scale; b /= scale; c /= scale;     

// set up the coefficients for the Bernstein polynomial that
// describes the distance from curve 2 to curve 1's baseline
double[] coeff = new double[4];
for(int i=0; i<4; i++) { coeff[i] = a*curve.points[i].x + b*curve.points[i].y + c; }
double[] vals = new double[4];
for(int i=0; i<4; i++) { vals[i] = computeCubicBaseValue(i*(1/3), coeff[0], coeff[1], coeff[2], coeff[3]); }

translate(0,100);

...

// draw the distance Bezier function
double range = 200;
for(float t = 0; t<1.0; t+=1.0/range) {
    double y = computeCubicBaseValue(t, coeff[0], coeff[1], coeff[2], coeff[3]);
    params.drawPoint(t*range, y, 0,0,0,255); }

...

translate(0,-100);
}

...

/**
 * compute the value for the cubic bezier function at time=t
 */
double computeCubicBaseValue(double t, double a, double b, double c, double d) {
double mt = 1-t;
return mt*mt*mt*a + 3*mt*mt*t*b + 3*mt*t*t*c + t*t*t*d; }
/**
*设置四个点,以形成三次曲线和用于交点检查的静态曲线
*/
无效设置点()
{
点=新点[4];
点[0]=新点(85,30);
点[1]=新点(180,50);
点[2]=新点(30155);
点[3]=新点(130160);
曲线=新贝塞尔3(175,25,55,4014085210);
曲线。设置显示控制点(假);
}
...
flcurve=new Bezier3(点[0].getX(),点[0].getY(),
点[1]。getX(),点[1]。getY(),
点[2]。getX(),点[2]。getY(),
点[3].getX(),点[3].getY();
...
void drawClipping()
{
double[]bounds=flcurve.getBoundingBox();
//获取C1基线到其他两条线的距离
点p0=FL曲线。点[0];
//距基线的偏移距离
双dx=p0.x-界[0];
双dy=p0.y-界[1];
双d1=sqrt(dx*dx+dy*dy);
dx=p0.x-界[2];
dy=p0.y-界[3];
双d2=sqrt(dx*dx+dy*dy);
...
双a、b、c;
a=dy/dx;
b=-1;
c=-(a*flcurve.points[0].x-flcurve.points[0].y);
//正常化,使a²+b²=1
双刻度=sqrt(a*a+b*b);
a/=刻度;b/=刻度;c/=刻度;
//设置Bernstein多项式的系数
//描述从曲线2到曲线1基线的距离
双[]系数=新双[4];

对于(int i=0;i您的距离函数不一定在两条原始曲线附近:它使用完全不同的坐标系,即t vs D,而不是使用x和y的原始曲线。[编辑]也就是说,t只上升到1.0,测量你沿着曲线的距离,作为总长度的一个比率,D测量你的曲线2到曲线1基线的距离

/**
 * Set up four points, to form a cubic curve, and a static curve that is used for intersection checks
 */
void setupPoints()
{
points = new Point[4];
points[0] = new Point(85,30);
points[1] = new Point(180,50);
points[2] = new Point(30,155);
points[3] = new Point(130,160);

curve = new Bezier3(175,25,  55,40,  140,140,  85,210);
curve.setShowControlPoints(false);
}

...

flcurve = new Bezier3(points[0].getX(), points[0].getY(),
                                        points[1].getX(), points[1].getY(),
                                        points[2].getX(), points[2].getY(),
                                        points[3].getX(), points[3].getY());

...

void drawClipping()
{
    double[] bounds = flcurve.getBoundingBox();

    // get the distances from C1's baseline to the two other lines
    Point p0 = flcurve.points[0];
    // offset distances from baseline
    double dx = p0.x - bounds[0];
    double dy = p0.y - bounds[1];
    double d1 = sqrt(dx*dx+dy*dy);
    dx = p0.x - bounds[2];
    dy = p0.y - bounds[3];
    double d2 = sqrt(dx*dx+dy*dy);

    ...

    double a, b, c;
a = dy / dx;
b = -1;
c = -(a * flcurve.points[0].x - flcurve.points[0].y);
// normalize so that a² + b² = 1
double scale = sqrt(a*a+b*b);
a /= scale; b /= scale; c /= scale;     

// set up the coefficients for the Bernstein polynomial that
// describes the distance from curve 2 to curve 1's baseline
double[] coeff = new double[4];
for(int i=0; i<4; i++) { coeff[i] = a*curve.points[i].x + b*curve.points[i].y + c; }
double[] vals = new double[4];
for(int i=0; i<4; i++) { vals[i] = computeCubicBaseValue(i*(1/3), coeff[0], coeff[1], coeff[2], coeff[3]); }

translate(0,100);

...

// draw the distance Bezier function
double range = 200;
for(float t = 0; t<1.0; t+=1.0/range) {
    double y = computeCubicBaseValue(t, coeff[0], coeff[1], coeff[2], coeff[3]);
    params.drawPoint(t*range, y, 0,0,0,255); }

...

translate(0,-100);
}

...

/**
 * compute the value for the cubic bezier function at time=t
 */
double computeCubicBaseValue(double t, double a, double b, double c, double d) {
double mt = 1-t;
return mt*mt*mt*a + 3*mt*mt*t*b + 3*mt*t*t*c + t*t*t*d; }
另外,当你说curve1和curve2的“基线”之间的“距离函数”时,“我认为你在这里混淆了curve1和curve2,因为在你的代码中,你显然使用了curve1的基线

此外,该算法假设“每个贝塞尔曲线都完全包含在连接所有起点/控制点/终点的多边形中,称为其“凸包”,在curve1的例子中,[编辑]它是一个三角形,其中第二个起点的控制点不是顶点。但我不确定这对算法有何影响

否则,您的距离计算看起来很好(尽管您确实可以做一些优化:)