繁体   English   中英

在JavaScript中挑战矢量数学

[英]Challenging vector maths in JavaScript

我有一个有趣的开发/数学问题,我无法解决问题。

请参见下图。

最终结果

我有两个圆点; 一个小而一个大。

我想要:

  • 从外圆中的任何给定点绘制一条直线到内圆中的任意给定点(完成)
  • 线应该是弧形,不应该越过内圈的边界或外圈的边界。 (我需要你的帮助!)

小提琴!

我创建了一个用RaphaelJS编写的jsFiddle,我在其中创建点和绘制线条。 见这里, http://jsfiddle.net/KATT/xZVnx/9/

它基本上在drawLine函数中我需要你的帮助,以绘制一个漂亮的弧,而不是一条直线。

我添加了一些辅助工具来处理矢量,se MathHelpers.Vector

请继续分叉并尝试实施一个解决方案,其中线条围绕着。 使用实际看起来很好的Béziers的解决方案也非常受欢迎。

是的,我猜矢量几何最适合计算。

非常非常非常感谢任何帮助。 我花了很多时间试图解决它,但我生锈的高中数学技能还不够。

简单地通过绘制分段螺旋来开始。

螺旋半径从起始角到终止角,螺旋半径从内圆半径到外圆半径。

为了让你知道我的意思,选择一些件(n)

var n = 20, // The number of lines in the spiral
    rStep = (outerRadius - innerRadius)/n, // the radius increase between points
    aStep = (outerAngle - innerAngle)/n,  // the angle change between points
    points = [];

// compute the cartesian coordinates (x, y) from polar coordinates (r, a)
function cartesian(r, a) {
    return [
        r * Math.cos(a),
        r * Math.sin(a)
    ];
}

for (i = 0; i <= n; i += 1) {
   points.push(cartesian(innerRadius + (i * rStep), innerAngle + (i * aStep));
}

我用极坐标演示了一个基本的分段螺旋:

http://jsfiddle.net/xmDx8/

尝试更改n以查看碎片是如何构建的。

drawLine(innerCircleIndex, outerCircleIndex, 1); // This is what you did

drawLine(innerCircleIndex, outerCircleIndex, 100); // 100 lines in the example

drawLine(innerCircleIndex, outerCircleIndex, n); // Choose n to see how it grows

一种选择是使用椭圆弧。 这看起来并不太令人敬畏,但满足了约束条件,我认为可以通过仔细选择圆半径来改进(这里我使用的是固定的)。

var angleDiff = MathHelpers.getAngleInCircle(innerCircleIndex, numberOfDotsInInnerCircle) - MathHelpers.getAngleInCircle(outerCircleIndex, numberOfDotsInOuterCircle);
while (angleDiff > Math.PI) {
    angleDiff -= 2 * Math.PI;
}
while (angleDiff < -Math.PI) {
    angleDiff += 2 * Math.PI;
}

from = addOffsetAndRound(from);
to = addOffsetAndRound(to);
r = (0.5 * innerCircleRadius + 0.5 * outerCircleRadius);

var pathStr = "";
pathStr += "M" + [from.x, from.y].join(' '); // MOVE to
pathStr += "A" + [r, r, 0, 0, angleDiff >= 0 ? 1 : 0, to.x, to.y].join(' '); // Draw line to
var path = paper.path(pathStr);

PS当然,应该记住,真正的螺旋不是椭圆弧。

如果你真的想要避免使用数学,那么你可以使用一系列简单的线段来近似螺旋,除了连接的两个点的坐标以及它们各自相对于原点或原点坐标的角度之外没有任何信息。显然可以从另一个推断出一个)。 给定(ix,iy,i_angle)描述内点的坐标和相对角度以及描述外点坐标和相对角度的(ox,oy,o_angle),

        var generatePath = function( ix, iy, i_angle, ox, oy, o_angle )
        {
            var path = [ "M", ox, oy ];
            var slices = 100;

            var cur_angle = o_angle;
            var cur_r = cr_outer;
            var delta_r = ( cr_inner - cr_outer ) / slices;
            var delta_angle = ( i_angle - o_angle );
            if ( delta_angle > Math.PI )
                delta_angle -= Math.PI * 2;
            else if ( delta_angle < Math.PI * -1 )
                delta_angle += Math.PI * 2;
            delta_angle = delta_angle / slices;

            for ( var i = 0; i < slices; i++ )
            {
                cur_angle += delta_angle;
                cur_r += delta_r;
                path.push( "L", cx + Math.cos( cur_angle ) * cur_r, cy + Math.sin( cur_angle ) * cur_r );
            }
            return path;
        }

逻辑很简单,即使在高分辨率下看起来也很好,并且可能比“真正的”弧段或一系列二次贝塞尔曲线更具性能。 每段的切片数量可能会根据长度和大小进行调整,以平衡性能与美学效果。

我有这个功能(带控制点计算)在这里上演。

尝试一种没有花哨数学的方法:

  • 找到连接点之间的中心点和内点。
  • 找到由这些中间点形成的段的中间。

绘制通过此点的曲线。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM