在贝塞尔曲线内获得一个点 [英] Get a point inside bezier curve

查看:132
本文介绍了在贝塞尔曲线内获得一个点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用KineticJS绘制徽标,顶部和底部都是bezierCurveTo.

I' using KineticJS to drawing a logo, both top an bottom lines are bezierCurveTo.

我需要在它们之间画线,所以我需要在两条曲线内定位点.

I need to draw lines between them and so I need to locate the points inside both curves.

我想使用的是获取X坐标和获取Y坐标. 使用方法bezierCurveTo可以找到位置. 问题是bezierCurveTo使用第一个参数作为百分比,而我的两个berzier不相等,因此不是我的解决方案.

What I thought to use was get the X coordinate and get the Y coordinate. Using method bezierCurveTo I can find the position. The problem is bezierCurveTo use the first parameter as percent and my two berzier are not equivalent, so is not a solution for me.

有没有给定树点且X返回Y的函数?

Is there any function that given tree points and X returns the Y ?

已编辑

我将在下一个示例中尝试更好地解释它 我有C点.我需要A点和B点,它们是C点和贝塞尔曲线给出的垂直线的交点,但是贝塞尔不是函数.

I'll try to explain it better with the next example I have the point C. I need the point A and B which are the intersection of the vertical line given by the point C and the bezier curves, but beziers are not functions.

推荐答案

给出X坐标:如何获取2条垂直堆叠的贝塞尔曲线的Y坐标.

我可以想到两种方式,都使用蛮力".

I can think of 2 ways, both use "brute force".

第一种方法:检查像素:

First method: examine pixels:

  • 在单独的画布上绘制两个贝塞尔曲线.
  • 使用context.getImageData获取画布上坐标X处所有垂直像素的数组.
  • 在所需的X坐标处遍历每个垂直Y像素
  • 如果找到不透明的像素,则说明您已经命中Bezier(它是Y)
  • 从顶部到底部进行迭代,直到找到顶部的贝塞尔曲线Y.
  • 从底部进行迭代,直到找到底部的Bezier Y.

以下是第一种方法的代码和提琴手: http://jsfiddle.net/m1erickson/uRDYf/

Here is code and Fiddle for the first method: http://jsfiddle.net/m1erickson/uRDYf/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    #canvas{border:1px solid red;}
</style>

<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    // draw a top bezier
    ctx.beginPath();
    ctx.moveTo(50,50);
    ctx.bezierCurveTo(125,0,150,100,250,75);
    ctx.lineWidth=3;
    ctx.strokeStyle="black";
    ctx.stroke();

    // draw a bottom bezier
    ctx.beginPath();
    ctx.moveTo(50,150);
    ctx.bezierCurveTo(125,0,150,100,250,175);
    ctx.lineWidth=3;
    ctx.strokeStyle="blue";
    ctx.stroke();

    // get an array of all the pixels in the canvas
    var x=100;  // put your X coordinate value here
    var iData = ctx.getImageData(x,0,1,canvas.height);
    var data = iData.data;
    var w=canvas.width;
    var h=canvas.height;
    var theY1=-999;  // your top result
    var theY2=-999;  // your bottom result


    // iterate through each Y at your vertical X coordinate
    // Examine the opacity value at the XY
    // if the pixel is not transparent, you have found your Y
    for(var y=0; y<h; y++) {
        if(data[y*4+3]>10){
            theY1=y;
            break;
      }
    }

    // now iterate backwards to get the Y of the bottom curve
    for(var y=0; y<h; y++) {
        if(data[(h-y)*4+3]>10){
            theY2=(h-y);
            break;
      }
    }


    // testing -- display the results

    ctx.beginPath();
    ctx.moveTo(x,0);
    ctx.lineTo(x,h);
    ctx.strokeStyle="lightgray";
    ctx.stroke();

    ctx.beginPath();
    ctx.arc(x,theY1,4,Math.PI*2,false);
    ctx.closePath();
    ctx.arc(x,theY2,4,Math.PI*2,false);
    ctx.closePath();
    ctx.fillStyle="red";
    ctx.fill();

}); // end $(function(){});
</script>

</head>

<body>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

第二种方法:使用Bezier曲线公式反复猜测" Y坐标.

Second method: use the Bezier curve formula to repeatedly "guess" the Y coordinate.

仅供参考,三次贝塞尔曲线确实有一个公式

// where ABCD are the control points and T is an interval along that curve

function CubicN(T, a,b,c,d) {
    var t2 = T*T;
    var t3 = t2*T;
    return a + (-a * 3 + T * (3 * a - a * T)) * T
    + (3 * b + T * (-6 * b + b * 3 * T)) * T
    + (c * 3 - c * 3 * T) * t2
    + d * t3;
}

您可以按照以下公式计算XY点:

And you can calculate XY points along that formula like this:

// cubic bezier T is 0-1
// When T==0.00, you are at the beginning of the Curve
// When T==1.00, you are at the ending of the Curve
function getCubicBezierXYatT(startPt,controlPt1,controlPt2,endPt,T){
    var x=CubicN(T,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
    var y=CubicN(T,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
    return({x:x,y:y});
}

第二种方法是使用getCubicBezierXYatT沿曲线重复猜测" T值.

So the second method is to repeatedly "guess" T values along your curve using getCubicBezierXYatT.

当返回的X是所需的X时,您也将具有所需的Y.

When the returned X is your desired X, you also have your desired Y.

我还没有尝试过,但是这篇SO帖子使用了一种称为Newton-Raphson改进的方法,它比随机的猜测要好:

I haven't tried it, but this SO post uses something called the Newton-Raphson refinement to make better than random guesses:

获得三次贝塞尔曲线的x坐标中的y,是快速的牛顿-拉夫森法

这篇关于在贝塞尔曲线内获得一个点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆