简体   繁体   English

在JavaScript中挑战矢量数学

[英]Challenging vector maths in JavaScript

I have a fun dev/math's problem that I can't get my head around solving. 我有一个有趣的开发/数学问题,我无法解决问题。

See the illustration below. 请参见下图。

最终结果

I have two circles of dots; 我有两个圆点; one small and one big. 一个小而一个大。

I want to: 我想要:

  • Draw a line from any given point in the outer circle to any given point in the inner circle (done) 从外圆中的任何给定点绘制一条直线到内圆中的任意给定点(完成)
  • The lines should be arcs and shouldn't cross the inner circle's boundries or the outer circle's boundries. 线应该是弧形,不应该越过内圈的边界或外圈的边界。 (I need your help!) (我需要你的帮助!)

fiddle! 小提琴!

I've created a jsFiddle written with RaphaelJS where i create dots and draw lines between them. 我创建了一个用RaphaelJS编写的jsFiddle,我在其中创建点和绘制线条。 See here, http://jsfiddle.net/KATT/xZVnx/9/ . 见这里, http://jsfiddle.net/KATT/xZVnx/9/

It's basically in the drawLine function I need your help, in order to draw a nice arc, instead of a straight line. 它基本上在drawLine函数中我需要你的帮助,以绘制一个漂亮的弧,而不是一条直线。

I added some helpers for working with vectors as well, se MathHelpers.Vector . 我添加了一些辅助工具来处理矢量,se MathHelpers.Vector

Please have a go on forking and try implementing a solution where the lines bend around the. 请继续分叉并尝试实施一个解决方案,其中线条围绕着。 Solutions using Béziers that actually look good is also much appreciated. 使用实际看起来很好的Béziers的解决方案也非常受欢迎。

And yeah, I guess vector geometry is best suited for the calculations. 是的,我猜矢量几何最适合计算。

Very, very, very thankful for any help. 非常非常非常感谢任何帮助。 I've spent a lot of time trying to solve it, but my rusty highschool math skills just aren't enough. 我花了很多时间试图解决它,但我生锈的高中数学技能还不够。

Start simply by drawing a piecewise a spiral. 简单地通过绘制分段螺旋来开始。

The spiral radius goes from start angle to end angle and the spiral radius goes from inner circle radius to outer circle radius. 螺旋半径从起始角到终止角,螺旋半径从内圆半径到外圆半径。

To give you an idea of what I mean, choose a number of pieces (n) 为了让你知道我的意思,选择一些件(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));
}

I have demonstrated a basic piecewise spiral using polar coordinates: 我用极坐标演示了一个基本的分段螺旋:

http://jsfiddle.net/xmDx8/ http://jsfiddle.net/xmDx8/

Try changing n to see how the pieces build up. 尝试更改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

One option is to use elliptical arcs. 一种选择是使用椭圆弧。 This doesn't look too awesome, but satisfies the constraints, and I think it can be improved by careful choice of the circle radius (here I used a fixed one). 这看起来并不太令人敬畏,但满足了约束条件,我认为可以通过仔细选择圆半径来改进(这里我使用的是固定的)。

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 Of course, one should keep in mind that the real spiral isn't an elliptical arc. PS当然,应该记住,真正的螺旋不是椭圆弧。

If you really did want to avoid teh fancy maths, you could approximate a spiral using a series of simple line segments given no information other than the coordinates of the two points being connected and either their respective angles relative to the origin or the origin's coordinates (obviously one can be inferred from the other). 如果你真的想要避免使用数学,那么你可以使用一系列简单的线段来近似螺旋,除了连接的两个点的坐标以及它们各自相对于原点或原点坐标的角度之外没有任何信息。显然可以从另一个推断出一个)。 Given (ix,iy,i_angle) describing the coordinates and relative angle of the interior point and (ox,oy,o_angle) describing the coordinates and relative angle of the exterior point, 给定(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;
        }

The logic is stupid-simple, looks good even at high resolutions, and is possibly more performant than a "genuine" arc segment or series of quadratic bezier curve. 逻辑很简单,即使在高分辨率下看起来也很好,并且可能比“真正的”弧段或一系列二次贝塞尔曲线更具性能。 The number of slices per segment could probably be tuned based on length and size to balance performance against aesthetics. 每段的切片数量可能会根据长度和大小进行调整,以平衡性能与美学效果。

I have this function (with control point calculations) staged here . 我有这个功能(带控制点计算)在这里上演。

Trying an approach without fancy maths: 尝试一种没有花哨数学的方法:

  • find the outter dot and the inner dot that are halfway between the dots to connect. 找到连接点之间的中心点和内点。
  • find the middle of the segment formed by these halfway dots. 找到由这些中间点形成的段的中间。

Draw your curve passing by this point. 绘制通过此点的曲线。

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

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