Question

Tout d'abord, juste pour donner une idée visuelle de ce que je suis après, voici le résultat le plus proche (mais pas exactement ce que je suis après) l'image que j'ai trouvé:

entrer image description ici

Voici l'ensemble de référence du site: http://www.mathematische-basteleien.de/ spiral.htm

Mais, il ne résout pas exactement le problème que je suis après. Je voudrais stocker un tableau de points d'un algorithme spirale très spécifique.

  • Les points sont répartis uniformément
  • Les 360 cycles degré ont un écart encore

Si je ne me trompe pas, les deux premiers points seraient:

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

Mais où aller d'ici?

Les seuls arguments que je voudrais fournir sont:

  • la quantité de points que je souhaite résoudre (longueur du tableau).
  • la distance entre chaque points (écart de pixels).
  • la distance entre les cycles.

Il presque sons, pour moi, que je dois calculer la « circonférence spirale » (s'il y a un tel terme) afin de tracer les points uniformément répartis le long de la spirale.

Can 2 * PI * rayon être utilisé de manière fiable pour ce calcul que vous pensez?

Si cela a été fait avant, s'il vous plaît montrer quelques exemples de code!

Était-ce utile?

La solution

Fun petit problème:)

Si vous regardez le schéma plus proche, la séquence est clairement indiqué:

diagramme spirale

Il y a probablement de nombreuses solutions pour tirer ceux-ci, peut-être plus élégant, mais voici le mien:

Vous savez que l'hypoténuse est la racine carrée du nombre actuel de la secteur + 1 et le côté opposé du triangle est toujours 1.

vous savez aussi que Sine (Math.sin) de l'angle est égal au côté opposé, divisé par l'hypoténuse. de l'ancien mnenonic SOH (Sine, face, hypoténuse), -. CAH-TOA

Math.sin(angle) = opp/hyp

Vous savez que la valeur du sinus de l'angle, vous connaissez les deux côtés, mais vous ne savez pas encore l'angle, mais vous pouvez utiliser la fonction arc sinus (Math.asin) pour que

angle = Math.asin(opp/hyp)

Maintenant, vous savez l'angle pour chaque segment, et l'avis incrémente à chaque ligne.

Maintenant que vous avez un angle et un rayon (l'hypoténuse), vous pouvez utiliser pour polaire cartésienne formule pour convertir que angle, rayon une paire de x, y paire.

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

Depuis que vous avez demandé une solution actionscript, il classe point fournit déjà cette fonction pour vous par la polaire () méthode . Vous passez un rayon et l'angle et renvoie votre x et y dans un objet Point.

Voici un petit extrait qui trace la spirale. Vous pouvez contrôler le nombre de segments en déplaçant la souris sur l'axe 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;
}

aurait pu être écrit en moins de lignes, mais je voulais partager cela en deux fonctions: une qui ne traite que de calculer les nombres, et l'autre qui traite de tracer les lignes.

Voici quelques captures d'écran:

spirale 1

spirale 2

spirale 3

Pour le plaisir, j'ai ajouté une version de ce en utilisant processing.js . Lance un peu lent, donc je recommande Chrome / Chrome pour cela.

Maintenant, vous pouvez réellement exécuter ce code ici (déplacez la souris vers le haut et vers le bas):

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>

Autres conseils

La réponse de George était excellent! Je cherchais la solution pendant un certain temps.

Voici le même code pour PHP ajusté, au cas où il aide quelqu'un. J'utilise le script pour établir des points (= villes) pour une carte avec des coordonnées X, Y. X commence à partir de la gauche, Y commence à en bas à gauche.

<?
/**
 * 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
         **/
    }   
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top