弧通过特定方向的3个点

时间:2014-06-12 07:07:44

标签: javascript opengl canvas geometry

我被困在8级几何问题=( 我需要从特定方向的3个点绘制弧线。 假设我有3个vec2点P1,P2,P3; 我一直设法找到弧形中心:

circleCenter: function (b, c, d) {
    var temp = Math.pow(c.x, 2) + Math.pow(c.y, 2);
    var bc = (Math.pow(b.x, 2) + Math.pow(b.y, 2) - temp) / 2.;
    var cd = (temp - Math.pow(d.x, 2) - Math.pow(d.y, 2)) / 2.;
    var det = (b.x - c.x) * (c.y - d.y) - (c.x - d.x) * (b.y - c.y);

    if (Math.abs(det) < 1e-14)
        return false;

    var circ = new THREE.Vector2((bc * (c.y - d.y) - cd * (b.y - c.y)) / det,
    ((b.x - c.x) * cd - (c.x - d.x) * bc) / det
    );

    return circ;
},

和半径......

    var startPoint = P1;
    var endPoint = P3;
    var centerPoint = P2;

    var centerPoint = this.circle(startPoint, centerPoint, endPoint);

    var r = Math.sqrt((startPoint.x - centerPoint.x) * (startPoint.x - centerPoint.x) + (startPoint.y - centerPoint.y) * (startPoint.y - centerPoint.y));
第三步是找到我被卡住的角度。 我正在以这种方式为每个点计算角度:

angleFromOrigin: function (c, p) {
    var x = p.x - c.x;
    var y = p.y - c.y;
    var theta = (180 / Math.PI * Math.atan2(y, x));
    return theta;
},

但是这种方法并没有给我a)方向,b)它并不总是包括第3点(在圆圈上显示相反的弧)

因此我需要使用旋转方向(顺时针,逆时针)和3rth角度来修正我所拥有的角度,我需要包含在弧形中。 这部分给了我堆栈溢出在我脑海中...谷歌中的所有链接成为一个,导致编写问题页面。我不能开箱即用......帮助我,集体思想))

2 个答案:

答案 0 :(得分:0)

在将一些特定的矢量数据椭圆弧转换为SVG时,heh也在那里......

如果应该这样做,很少。我看到你的情况是这样的:

arc

尝试这个角度修正:

if (a2-a1>+180.0) a2-=360.0;
if (a2-a1<-180.0) a2+=360.0;
if (a3-a2>+180.0) a3-=360.0;
if (a3-a2<-180.0) a3+=360.0;

之后方向很容易:

if (a2-a1< 0) dir = CW;
if (a2-a1> 0) dir = CCW;
if (a2-a1==0) dir = none;

唯一的问题是当你的弧线覆盖整个360度圆圈或更多时......

  • 那么这还不够

绘画可以这样做:

for (i=0,a=a1;i<100;i++,a+=(a3-a1)/99.0) // 100 lines per arc or use GDI arc ...
 {
 x=C.x + R*cos(a*PI/180.0);
 y=C.y + R*sin(a*PI/180.0); // or - R*...  if your render device has opposite Y direction
 if (!i) ...->Canvas->MoveTo(x,y);
 else    ...->Canvas->LineTo(x,y);
 }
  • R = | P1-C |

答案 1 :(得分:0)

我正在解决一个类似的问题,看起来您可以通过比较您计算出的角度来计算方向和扫掠角。如果你必须从终止角向后走更远才能到达起始角而不是到达中间角,那么你是顺时针方向。您可以使用模运算符 (%) 将角度进行正则化以进行比较,从而解决了 360 度交叉的问题。类似这样:

function determineDirection(start, middle, end) {
    endToStart = (end - start + 360) % 360;
    endToMiddle = (end - middle + 360) % 360;
    if (endToMiddle < endToStart) {
        return {direction: 'cw', sweepAngle: endToStart};
    } else {
        return {direction: 'ccw', sweepAngle: (360 - endToStart)};
    }
}

angleStart = angleFromOrigin(centerOfCircle, P1);
angleMiddle = angleFromOrigin(centerOfCircle, P2);
angleEnd = angleFromOrigin(centerOfCircle, P3);

direction = determineDirection(angleStart, angleMiddle, angleEnd);

请注意,此函数假设角度在顺时针方向增加。如果您将它用于角度在逆时针方向增加的典型情况,请交换“cw”和“ccw”的位置。

尝试一下:

determineDirection(0, 1, 2)
> {direction: "cw", sweepAngle: 2}

determineDirection(2, 1, 0)
> {direction: "ccw", sweepAngle: 2}

determineDirection(0, 2, 1)
> {direction: "ccw", sweepAngle: 359}

determineDirection(1, 2, 0)
> {direction: "cw", sweepAngle: 359}

determineDirection(359, 0, 1)
> {direction: "cw", sweepAngle: 2}

determineDirection(359, 1, 0)
> {direction: "ccw", sweepAngle: 359}

determineDirection(0, 1, 359)
> {direction: "cw", sweepAngle: 359}

determineDirection(1, 0, 359)
> {direction: "ccw", sweepAngle: 2}

determineDirection(0, 359, 1)
> {direction: "ccw", sweepAngle: 359}

determineDirection(1, 359, 0)
> {direction: "cw", sweepAngle: 359}

determineDirection(0, 90, 180)
> {direction: "cw", sweepAngle: 180}

determineDirection(180, 90, 0)
> {direction: "ccw", sweepAngle: 180}

determineDirection(180, 0, 90)
> {direction: "cw", sweepAngle: 270}

我注意到您在圆心和圆弧中点都使用了“centerPoint”,因此我更改了变量名称以避免混淆。