1

I need to be able to find x, y coordinates at any length down an Archimedean spiral arm, given a specific distance between each loop of the arm.

I have researched previous questions on Stackoverflow, and across the Internet, and I have found three methods, which are each different, and each plot me a spiral. (I call them the first, second and third method, here.)

The first method, does plot equidistant points, with the pointdist variable = 1, but as this is increased, there is also an aberration of point distances (supposed to be equidistant) near the center of the spiral.

The third method and second method, do not correctly plot equidistant points near the center of the spiral. (See graphs below)

The third method, though, allows me to input any length down the arm and obtain x, y coordinates.

The first and second methods plot equidistant points by a process where they additively sum a variable, each cycle of a loop to plot the equidistant points. Because of how this value is built up instead of calculated from scratch using only the distance along the spiral arm variable, I can't use these two methods to find coordinates at any arbitrary length along the arm [Proofreading this, I just thought, perhaps if I initialize the length to calculate one point each time. However, all three methods have problems even with equidistant points.]

Here is output from the third method:

Equidistant points - inaccurate near center - 3rd method

Here is the code of the "third method". This method uses what an answer to another sprial-related question on Stackoverflow (Placing points equidistantly along an Archimedean spiral) calls the "Clackson scroll formula", which is said to be possibly inaccurate in some ranges.

double thetamax = 10 * Math.PI;
double b = armbandwidth / (2 * Math.PI); 
// "armbandwidth” value influences distance between the spiral arms, usually kept between 1 and 20

AddPoint(0,0);               //  Mark the origin of the spiral

// “pointdist” is the length between points to plot along the spiral, I use 0.1 to 2+  
//  but it doesn't reveal spiral shape with increasing values
for (double s = pointdist; s < spirallength; s += pointdist)  
{
      double thetai = Math.Sqrt(2 * s / b);
      double xx = b * thetai * Math.Cos(thetai);
      double yy = b * thetai * Math.Sin(thetai);
      AddPoint(xx, yy);                               
}

I need to both:

  1. Use a method that does not have aberrations in the equidistance of points along the spiral arm, given equally spaced values of lengths down the spiral arms.
  2. Use a method that allows me to specify the width between the spiral arms (in terms of the same units used for the length along spiral arm between the points, as well).

In case it helps, and to be clear about what I've tried, here are the code and output from the other methods I've found and tested (here called "second method" and "first method") for calculating the coordinates of equidistant points along an Archimedean spiral:

Here is output from the second method (note the uneven distanced points near center):

Equidistant points - inaccurate near center - 2nd method

Here is the code for the second method:

AddPoint(0,0);               //  Mark the origin of the spiral

double arclength = 0.8;      // This value (kept between 0.1 and 20 or so) sets the distance between points to calculate coordinates for along the spiral curve
double r = arclength; 
double b = armbandwidth / (2 * Math.PI);     // "armbandwidth" value influences distance between the spiral arms, usually kept between 3.5 to 10
double phi = r / b;

double xx = r * Math.Cos(phi);
double yy = r * Math.Sin(phi);
AddPoint(xx, yy);

while( r <= spirallength )   // spirallength determines roughly how many iterations of points to draw
{
      phi += arclength / r;
      r = b * phi;
      xx = r * Math.Cos(phi);
      yy = r * Math.Sin(phi);
      AddPoint(xx, yy);
}

Because the variable phi is additively increased each iteration, I can't pass in any length down the spiral arm to find coordinates for. (Maybe if I initialized the whole method only to a single arclength each time. - In any case, the points near center are not evenly spaced.)

Here is output from the first method (Equidistant points throughout with pointdist = 1):

Equidistant points - 1st method - pointdist = 1

Here is the code of the first method:

double separation = 4;   // Value influences distance between the spiral arms, usually kept 3.5 to 10+
double angle = 0;
double r;

AddPoint(0,0);              //  Mark the origin of the spiral

for (double i=0; i <= spirallength; i+=pointdist)   // spirallength determines pointdist spaced points to plot
{
      r = Math.Sqrt(i+1);
      angle += Math.Asin(1/r);
      double xx = Math.Cos(angle) * r*separation;
      double yy = Math.Sin(angle) * r*separation;
      AddPoint(xx, yy);
}

However, when "pointdist" is increased above 1, there are aberrations in equidistance between points near the center of the spiral, even by this method. Here is the output of a graph using the "first method" and pointdist = 9:

Equidistant points - 1st method - inaccurate with pointdist = 9

Can anyone help me calculate x, y coordinates for any length down the spiral arm from center, for an Archimedes spiral defined by a specified width between loops of the arm?

(It should be able to have equidistant points, accurate even near the center, and be able to take a width between loops of the arm in units the same scale as those used for the distance to a point along the arm passed to the coordinates equation.)

Much appreciated!

GoldenAxe
  • 36
  • 4

1 Answers1

0

I believe this last piece of code is the best (most simple and straightforward) approach:

  • constant angle variation
  • For a given angle
  • calculate the radius
  • convert Polar coordinates to Cartesian.

However, I understand the Archimedean spiral is defined by the formula: r = a + b * angle (where a=0 to simplify, and b controls the distance between loops. In short, the position of particle is proportional to the angle θ as time elapses.

So what's up with that? That's not linear at all!

  r = Math.Sqrt(i+1);
  angle += Math.Asin(1/r);

Here's a simple way to make it.

It's not a running code. But I believe it's very easy to understand.

So just understand the logic and then code it with your own variables:

for (some incrementing t)
{
      radius = t/100; //Start at radius = 0. When t = 100, radius=1.
      angle = t*2*Pi/200; //It takes 200 points to make a full 360 (2Pi) turn

      //Now converting from polar coordinates (r,angle) to (x,y):
      x = cos(angle) * r;
      y = sin(angle) * r;
      AddPoint(x, y);
}

This code generates the following image:

Archimedean Spiral

This generates the right trajectory. However, as noticed, this does not produce equidistant points, because each angle increment is multiplied by the radius. So I suggest you to find a correction function and apply it to t. Like so:

function correction(i)
{
 // I actually don't know the exact relationship between t and i
 t = 1/i 
 // But I think it converges to t=1/i for very small increments
 return t
 }
 
for (some incrementing i)
{
      t = correction(i)
      ...
}
Andre Goulart
  • 528
  • 2
  • 20
  • I ran this code, and it drew a nice spiral. Unfortunately, when t was incremented evenly, the points were further apart in the outer arm swirls, closer together in the inner swirls, not equidistant as I would expect by evenly incrementing t. Here's a picture of this: ![Output of Andre's method](https://imgur.com/uO4v0YN). In this image, the points on different bands of the arm happen to align along angles outward from the origin, with the parameters used for the image, but they don't always with this method. But this underscores that the points are more distanced in the outer arm bands. – GoldenAxe Aug 11 '21 at 09:23
  • Oh, that is true! They are equidistant in polar coordinates (the sequence has a fixed angle and radius increment), but not on Cartesian, because each angle increment represents a larger cartesian distance when the radius is large. To fix that, I suggest you to increment some i (instead of t) and use a function to map i into t. I'll edit it on the post. – Andre Goulart Aug 11 '21 at 20:20