算法解决的均匀分布/偶空白点螺旋? [英] Algorithm to solve the points of a evenly-distributed / even-gaps spiral?

查看:369
本文介绍了算法解决的均匀分布/偶空白点螺旋?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,只给了我后一个视觉的想法,这里是最接近的结果(但不完全是我后),我发现图像:

下面是整个网站参考: http://www.mathematische-basteleien.de/spiral热媒

但,它不完全解决林后问题。我想存储一个非常特殊的螺旋算法的点组成的数组。

  • 在这些点分布均匀
  • 360度周期有一个更缺口

如果我没有记错,前两点是:

  • 点[0] =新的点(0,0);
  • 点[1] =新的点(1,0);

不过,从哪里走?

唯一的参数,我想提供的是:

  • 点预祝量来解决(数组的长度)。
  • 在每个点(像素间隙)之间的距离。
  • 周期之间的距离。

这听起来,对我来说,我要计算的螺旋周长的(如果有这样一个名词),以绘制沿螺旋均匀分布点。

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

如果它已经做过,请出示一些code例子!

解决方案

有趣的小问题:)

如果你看一下图近,序列明确规定:

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

您知道斜边是当前的段数+ 1的平方根 和三角形的相对侧始终为1

另外你知道,角度的正弦(Math.sin)等于另一侧由斜边划分。 从旧mnenonic SOH(正弦,相反,斜边), - CAH-TOA

  Math.sin(角度)= OPP / HYP
 

您知道正弦的角度值,你知道双方,但你不知道的角度,但你可以使用反正弦函数(Math.asin)为

 角= Math.asin(OPP / HYP)
 

现在你知道的角度对每个段,并注意到它与每行递增。

现在你有一个角度,半径(斜边),你可以使用极性直角公式将其转换成角度,半径对一个 X,Y 对。

  X = Math.cos(角)*半径;
Y = Math.sin(角度)*半径;
 

既然你问了一个动作的解决方案,还有点类已通过的极性()方法。你传递一个半径,角度,它返回的x和y的Point对象。

下面是一个小片段而绘制的螺旋。可以通过移动鼠标在Y轴控制段的数量。

 变种SW:数= stage.stageWidth,SH:数= stage.stageHeight;
this.addEventListener(Event.ENTER_FRAME,更新);
功能更新(事件:事件):无效{
    drawTheodorus(144 *(mouseY的/ SH),SW * 5,SH * .5,20);
}
//画点
功能drawTheodorus(段:INT,X:数x,y:数量,规模:编号):无效{
    graphics.clear();
    VAR要点:阵列= getTheodorus(段比例);
    对于(VAR我:= 0; I<段;我++){
        点[I] .offset(X,Y​​);
        graphics.lineStyle(1,0x990000,1.05  - (05 + I /段)。);
        graphics.moveTo(X,Y); //移动到中心
        graphics.lineTo(分[I] .X,点[I] .Y); //画出斜边
        graphics.lineStyle(1+(I *(ⅰ/段)* 05),0,(05 + I /段)。);
        如果(ⅰ大于0)graphics.lineTo(点[I-1] .X,分〔I-1] .Y); //绘制相对
    }
}
//计算点
功能getTheodorus(段:INT = 1,规模:数= 10):数组{
    VAR的结果= [];
    VAR半径:数= 0;
    VAR角度:数= 0;
    对于(VAR我:= 0; I<段;我++){
        半径=的Math.sqrt第(i + 1);
        角+ = Math.asin(1 /半径); //罪(角)=对边/斜边=>用ASIN获得角
        结果[I] = Point.polar(半径*规模,角度); //同新点(Math.cos(角)* radius.scale,Math.sin(角度)* radius.scale)
    }
    返回结果;
}
 

这可能已经被写入少行,但我想分成两个功能: 一个只处理计算的数字,而另一个涉及绘制线条

下面是一些截屏:

为了好玩我加了一个版本使用ProcessingJS 这里。 运行的速度有点慢,所以我会建议铬/铬这一点。

现在,你可以实际运行此code就在这里(移动鼠标上下):

VAR totalSegments = 850,HW = 320,HH = 240段; 变种的len = 10; 分= []; 功能设置(){   createCanvas(640,480);   光滑();   colorMode(HSB,255100100);   中风(0);   NOFILL();   //的println(移动光标垂直); } 功能平局(){   背景(0);   翻译(HW,HH);   段=地板(totalSegments *(mouseY的/高));   点= getTheodorus(段的len);   对于(VAR I = 0; I<段;我++){     strokeWeight(1);     中风(255 - ((I /段)* 255),100100260 - ((I /段)* 255));     线路(0,0,点[I] .X,点[I] .Y);     // strokeWeight(1+(I *(I /段)* 01));     strokeWeight(2);     中风(0,0,100,(20 + I /段));     如果(ⅰ大于0)线(点[I] .X,点[I] .Y,分〔I-1] .X,分〔I-1] .Y);   } } 功能getTheodorus(段的len){   VAR的结果= [];   变种半径= 0;   变种角度= 0;   对于(VAR I = 0; I<段;我++){     半径= SQRT第(i + 1);     角+ = ASIN(1 /半径);     结果[I] =新p5.Vector(COS(角)*半径* LEN,罪(角)*半径* LEN);   }   返回结果; }

&LT;脚本SRC =htt​​ps://cdnjs.cloudflare.com/ajax /libs/p5.js/0.4.4/p5.min.js"></script>

First, just to give a visual idea of what I'm after, here's the closest result (yet not exactly what I'm after) image that I've found:

Here's the entire site-reference: http://www.mathematische-basteleien.de/spiral.htm

BUT, it doesn't exactly solve the problem I'm after. I would like to store an array of points of a very specific spiral algorithm.

  • The points are evenly distributed
  • The 360 degree cycles have an even gap

If I'm not mistaken, the first two points would be:

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

But where to go from here?

The only arguments I'd like to provide are:

  • the quantity of points I wish to resolve (length of array).
  • the distance between each points (pixels gap).
  • the distance between cycles.

It almost sounds, to me, that I have to calculate the "spiral-circumference" (if there's such a term) in order to plot the evenly distributed points along the spiral.

Can 2*PI*radius be reliably used for this calculation you think?

If it's been done before, please show some code example!

解决方案

Fun little problem :)

If you look at the diagram closer, the sequence is clearly stated:

There are probably many solutions to drawing these, maybe more elegant, but here's mine:

You know the hypotenuse is square root of the current segment count+1 and the opposite side of the triangle is always 1.

Also you know that Sine(Math.sin) of the angle is equal to the opposite side divided by the hypotenuse. from the old mnenonic SOH(Sine,Opposite,Hypotenuse),-CAH-TOA.

Math.sin(angle) = opp/hyp

You know the value of the sine for the angle, you know the two sides, but you don't know the angle yet, but you can use the arc sine function(Math.asin) for that

angle = Math.asin(opp/hyp)

Now you know the angle for each segment, and notice it increments with each line.

Now that you have an angle and a radius(the hypotenuse) you can use for polar to cartesian formula to convert that angle,radius pair to a x,y pair.

x = Math.cos(angle) * radius;
y = Math.sin(angle) * radius;

Since you asked for an actionscript solution, there Point class already provides this function for you through the polar() method. You pass it a radius and angle and it returns your x and y in a Point object.

Here's a little snippet which plots the spiral. You can control the number of segments by moving the mouse on the Y axis.

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;
}

This could've been written in less lines, but I wanted to split this into two functions: one that deals only with computing the numbers, and the other which deals with drawing the lines.

Here are some screenshots:

For fun I added a version of this using ProcessingJS here. Runs a bit slow, so I would recommend Chromium/Chrome for this.

Now you can actually run this code right here (move the mouse up and down):

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;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.4.4/p5.min.js"></script>

这篇关于算法解决的均匀分布/偶空白点螺旋?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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