Domanda

Per prima cosa, giusto per dare un'idea visiva di quello che sto cercando, ecco il risultato più vicino (ma non è esattamente quello che sto cercando) un'immagine che ho trovato:

entrare descrizione dell'immagine qui

Ecco l'intero sito-di riferimento: http://www.mathematische-basteleien.de/ spiral.htm

MA, non esattamente a risolvere il problema che sto cercando. Vorrei memorizzare una serie di punti di un ben preciso algoritmo di spirale.

  • I punti sono distribuiti uniformemente
  • I cicli 360 gradi hanno un divario ancora

Se non sbaglio, i primi due punti sarebbero:

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

Ma dove andare da qui?

Gli unici argomenti che vorrei fornire sono:

  • la quantità di punti desidero risolvere (lunghezza di array).
  • la distanza tra ciascun pixel (gap) punti.
  • la distanza tra i cicli.

Sembra quasi, a me, che devo calcolare il " spirale-circonferenza " (se c'è tale termine a) al fine di tracciare i punti uniformemente distribuiti lungo la spirale.

possono 2 PI * * Raggio essere usata in modo affidabile per questo calcolo si pensa?

Se è stato fatto prima, si prega di mostrare qualche esempio di codice!

È stato utile?

Soluzione

Divertimento piccolo problema:)

Se si guarda lo schema più vicino, la sequenza è chiaramente indicato:

Schema spirale

Ci sono probabilmente molte soluzioni a disegnare questi, forse più elegante, ma ecco la mia:

Non si sa l'ipotenusa è radice quadrata della corrente conteggio dei segmenti + 1 e il lato opposto del triangolo è sempre 1.

Inoltre si sa che Sine (Math.sin) dell'angolo è uguale al lato opposto diviso per l'ipotenusa. dal vecchio SOH mnenonic (Sine, di fronte, Hypotenuse), -. CAH-TOA

Math.sin(angle) = opp/hyp

Si conosce il valore del seno per l'angolo, si sa le due parti, ma non si conosce ancora l'angolo, ma è possibile utilizzare la funzione arcoseno (Math.asin) per quel

angle = Math.asin(opp/hyp)

Ora si sa l'angolo per ogni segmento, e l'avviso incrementa con ogni riga.

Ora che avete un angolo e un raggio (l'ipotenusa) è possibile utilizzare per polar a cartesiano formula per convertire che angolo, raggio accoppiamento ad un x, y pair.

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

Poiché hai chiesto una soluzione ActionScript, c'è classe Point offre già questa funzione per l'utente attraverso il polar () metodo . Si passa un raggio e l'angolo e restituisce il tuo xey in un oggetto Point.

Ecco un piccolo frammento che traccia la spirale. È possibile controllare il numero di segmenti spostando il mouse sull'asse 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;
}

Questo potrebbe essere stato scritto in meno linee, ma ho voluto dividere questo in due funzioni: uno che si occupa solo di calcolare i numeri, e l'altra che si occupa di disegnare le linee.

Ecco alcuni screenshot:

spirale 1

spirale 2

spirale 3

Per divertimento ho aggiunto una versione di questo utilizzando ProcessingJS qui . Esegue un po 'lento, quindi vi consiglio di Chromium / Chrome per questo.

Ora si può effettivamente eseguire questo codice qui (spostare il mouse su e giù):

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>

Altri suggerimenti

risposta di George era eccellente! Ero alla ricerca di una soluzione per un bel po '.

Ecco lo stesso codice corretto per PHP, nel caso in cui aiuta qualcuno. Io uso lo script per disegnare punti (= città) per una mappa con le coordinate X, Y. X inizia da sinistra, Y inizia dal basso a sinistra.

<?
/**
 * 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
         **/
    }   
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top