Pregunta

En primer lugar, sólo para dar una idea visual de lo que busco, aquí está el resultado más cercano (todavía no es exactamente lo que busco) imagen que he encontrado:

introducir descripción de la imagen aquí

Aquí está todo el sitio de referencia: http://www.mathematische-basteleien.de/ spiral.htm

Pero, no resuelve el problema exactamente lo que busco. Me gustaría almacenar una matriz de puntos de un algoritmo de caracol muy específico.

  • Los puntos se distribuyen uniformemente
  • Los ciclos de 360 ??grados tienen una brecha aún

Si no me equivoco, los dos primeros puntos serían:

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

Pero, ¿dónde ir desde aquí?

Los únicos argumentos que me gustaría ofrecer son:

  • la cantidad de puntos deseo de resolver (longitud de array).
  • la distancia entre cada (GAP píxeles) puntos.
  • la distancia entre los ciclos.

Casi suena, a mí, que tengo que calcular el " espiral circunferencia " (si hay tal término a) con el fin de representar los puntos uniformemente distribuidos a lo largo de la espiral.

puede 2 * pi * radio puede utilizarse de manera fiable para este cálculo te parece?

Si se ha hecho antes, por favor mostrar algún ejemplo de código!

¿Fue útil?

Solución

Diversión pequeño problema:)

Si nos fijamos en el diagrama más cerca, la secuencia se afirma claramente:

diagrama espiral

Probablemente hay muchas soluciones a dibujar estos, tal vez más elegante, pero aquí está la mía:

Usted sabe que la hipotenusa es la raíz cuadrada de la cantidad actual de segmento + 1 y el lado opuesto del triángulo es siempre 1.

También se sabe que Sine (Math.sin) del ángulo es igual al lado opuesto dividido por la hipotenusa. desde el antiguo SOH mnenonic (Sine, enfrente, la hipotenusa), -. CAH-TOA

Math.sin(angle) = opp/hyp

Usted sabe que el valor del seno del ángulo, ya sabes los dos lados, pero no se sabe aún el ángulo, pero se puede utilizar la función arco seno (Math.asin) para que

angle = Math.asin(opp/hyp)

Ahora usted sabe el ángulo para cada segmento, y el aviso se incrementa con cada línea.

Ahora que tiene un ángulo y un radio (la hipotenusa) se puede utilizar para polar a cartesiano fórmula para convertir que ángulo, radio par a un x, y par.

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

Desde que solicitó una solución ActionScript, hay clase Point ya proporciona esta función para usted a través de la polar método (). Se le pasa un radio y el ángulo y devuelve su xey en un objeto Point.

Aquí hay un pequeño fragmento que traza la espiral. Se puede controlar el número de segmentos moviendo el ratón en el eje 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;
}

Esto podría haber sido escrito en menos líneas, pero quería dividirla en dos funciones: una que se ocupa sólo de calcular los números, y el otro que se ocupa de la elaboración de las líneas.

Estas son algunas capturas de pantalla:

espiral 1

espiral 2

espiral 3

Para la diversión que añade una versión de este ProcessingJS usando aquí . Corre un poco lento, por lo que recomiendo cromo / cromo para esto.

Ahora en realidad se puede ejecutar este código aquí (mover el ratón hacia arriba y hacia abajo):

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>

Otros consejos

La respuesta de George fue excelente! Yo estaba buscando la solución durante bastante tiempo.

Este es el mismo código ajustado para PHP, en caso de que ayuda a alguien. Yo uso la secuencia de comandos para dibujar puntos (= ciudades) para un mapa con las coordenadas X, Y. X se inicia desde la izquierda, Y comienza desde la parte inferior izquierda.

<?
/**
 * Initialize variables
 **/

// MAXIMUM width & height of canvas (X: 0->400, Y: 0->400)
$width = 400;

// For loop iteration amount, adjust this manually
$segments = 10000;

// Scale for radius
$radiusScale = 2;

// Draw dot (e.g. a city in a game) for every N'th drawn point
$cityForEveryNthDot = 14; 

/**
 * Private variables
 **/
$radius = 0;
$angle = 0;
$centerPoint = $width/2;

/**
 * Container print
 **/
print("<div style=\"width: ${width}px; height: ${width}px; background: #cdcdcd; z-index: 1; position: absolute; left: 0; top: 0;\"></div>");

/**
 * Looper
 **/
for($i=0;$i<$segments;$i++) {
    // calculate radius and angle
    $radius = sqrt($i+1) * $radiusScale;
    $angle += asin(1/$radius);

    // skip this point, if city won't be created here
    if($i % $cityForEveryNthDot != 0) {
        continue;
    }   

    // calculate X & Y (from top left) for this point
    $x = cos($angle) * $radius;
    $y = sin($angle) * $radius;

    // print dot
    print("<div style=\"width: 1px; height: 1px; background: black; position: absolute; z-index: 2; left: " . round($x+$centerPoint) . "; top: " . round($y+$centerPoint) . ";\"></div>");

    // calculate rounded X & Y (from bottom left)
    $xNew = round($x+$centerPoint);
    $yNew = round($width - ($y+$centerPoint));

    // just some internal checks
    if($xNew > 1 && $yNew > 1 && $xNew < $width && $yNew < $width) {
        /**
         * do something (e.g. store to database). Use xNew and yNew
         **/
    }   
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top