求解均匀分布/均匀间隙螺旋点的算法?

big*_*igp 7 algorithm math pseudocode spiral actionscript-3

首先,只是为了直观地了解我所追求的内容,这是我发现的最接近的结果(但不完全是我所追求的):

在此输入图像描述

以下是整个网站的参考:http://www.mathematische-basteleien.de/spiral.htm

但是,它并没有完全解决我所追求的问题.我想存储一个非常具体的螺旋算法的点数组.

  • 积分均匀分布
  • 360度周期有一个均匀的差距

如果我没弄错的话,前两点将是:

  • point [0] = new Point(0,0);
  • point [1] = new Point(1,0);

但是从哪里开始呢?

我想提供的唯一论据是:

  • 我希望解决的点数(数组的长度).
  • 每个点之间的距离(像素间隙).
  • 周期之间的距离.

对我来说,几乎听起来我必须计算" 螺旋周长 "(如果有这样一个术语),以便沿着螺旋线绘制均匀分布的点.

2*PI*半径可靠地使用这种计算你觉得呢?

如果之前已经完成,请显示一些代码示例!

Geo*_*nza 18

有趣的小问题:)

如果您仔细查看图表,则会明确说明顺序:

螺旋图

绘制这些可能有很多解决方案,也许更优雅,但这是我的:

您知道斜边是当前分段计数的平方根+ 1,而三角形的另一侧始终为1.

你也知道角度的正弦(Math.sin)等于相反的一边除以斜边.来自旧的mnenonic SOH(正弦,对面,斜面), - CAH-TOA.

Math.sin(angle) = opp/hyp
Run Code Online (Sandbox Code Playgroud)

你知道角度的正弦值,你知道两边,但你还不知道角度,但你可以使用弧正弦函数(Math.asin)

angle = Math.asin(opp/hyp)
Run Code Online (Sandbox Code Playgroud)

现在您知道每个段的角度,并注意它随每行递增.

既然您有一个角度和一个半径(斜边),您可以使用极坐标笛卡尔公式将该角度,半径对转换为x,y对.

x = Math.cos(angle) * radius;
y = Math.sin(angle) * radius;
Run Code Online (Sandbox Code Playgroud)

既然你要求一个动作脚本解决方案,那么Point类已经通过polar()方法为你提供了这个功能.您传递半径和角度,它返回Point对象中的x和y.

这是一个绘制螺旋线的小片段.您可以通过在Y轴上移动鼠标来控制分段数.

var sw:Number = stage.stageWidth,sh:Number = stage.stageHeight;
this.addEventListener(Event.ENTER_FRAME,update);
function update(event:Event):void{
    drawTheodorus(144*(mouseY/sh),sw*.5,sh*.5,20);
}
//draw points
function drawTheodorus(segments:int,x:Number,y:Number,scale:Number):void{
    graphics.clear();
    var points:Array = getTheodorus(segments,scale);
    for(var i:int = 0 ; i < segments; i++){
        points[i].offset(x,y);
        graphics.lineStyle(1,0x990000,1.05-(.05+i/segments));
        graphics.moveTo(x,y);//move to centre
        graphics.lineTo(points[i].x,points[i].y);//draw hypotenuse
        graphics.lineStyle(1+(i*(i/segments)*.05),0,(.05+i/segments));
        if(i > 0) graphics.lineTo(points[i-1].x,points[i-1].y);//draw opposite
    }
}
//calculate points
function getTheodorus(segments:int = 1,scale:Number = 10):Array{
    var result = [];
    var radius:Number = 0;
    var angle:Number = 0;
    for(var i:int = 0 ; i < segments ; i++){
        radius = Math.sqrt(i+1);
        angle += Math.asin(1/radius);//sin(angle) = opposite/hypothenuse => used asin to get angle
        result[i] = Point.polar(radius*scale,angle);//same as new Point(Math.cos(angle)*radius.scale,Math.sin(angle)*radius.scale)
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

这可能是用较少的行编写的,但我想把它分成两个函数:一个只处理数字计算,另一个处理绘制线条.

以下是一些截图:

螺旋1

螺旋2

螺旋3

为了好玩,我在这里使用ProcessingJS添加了一个版本.运行有点慢,所以我建议使用Chromium/Chrome.

现在你可以在这里实际运行这段代码(上下移动鼠标):

var totalSegments = 850,hw = 320,hh = 240,segments;
var len = 10;
points = [];
function setup(){
  createCanvas(640,480);
  smooth();
  colorMode(HSB,255,100,100);
  stroke(0);
  noFill();
  //println("move cursor vertically");
}
function draw(){
  background(0);
  translate(hw,hh);
  segments = floor(totalSegments*(mouseY/height));
  points = getTheodorus(segments,len);
  for(var i = 0 ; i < segments ; i++){
    strokeWeight(1);
    stroke(255-((i/segments) * 255),100,100,260-((i/segments) * 255));
    line(0,0,points[i].x,points[i].y);
    // strokeWeight(1+(i*(i/segments)*.01));
    strokeWeight(2);
    stroke(0,0,100,(20+i/segments));
    if(i > 0) line(points[i].x,points[i].y,points[i-1].x,points[i-1].y);
  }
}
function getTheodorus(segments,len){
  var result = [];
  var radius = 0;
  var angle = 0;
  for(var i = 0 ; i < segments ; i++){
    radius = sqrt(i+1);
    angle += asin(1/radius);
    result[i] = new p5.Vector(cos(angle) * radius*len,sin(angle) * radius*len);
  }
  return result;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.4.4/p5.min.js"></script>
Run Code Online (Sandbox Code Playgroud)