Logarithmic spiral

Blitz3D Forums/Blitz3D Programming/Logarithmic spiral

sswift(Posted 2004) [#1]
I was hoping someone could help me out with a math problem.

I'm trying to make a logartihmic spiral out of line segments.

To do this, I specify the initial line segment length, an angle to adjust each segment by relative to the last, and a taper value which is the percentage of the last line segment's length that the next segment should be.

For example,

If:
Length# = 16
Taper# = 0.5 (ie, 50% size change)
Angle# = 22.5

Then each loop I would go:
Length# = Length# * Taper#
CurrentAngle# = CurrentAngle# + Angle#

So if I had four segments their lengths would be:

16, 8, 4, 2

And each would be at a 22.5 degree angle to the last.


Now here's my problem. I want to allow the ability to subdivide the curve. So if a subidivision of 1 is specified, the curve will have just 4 segments, but if a subdivision level of 2 is specified, each will be divided in half.

My problem is that if I divide each segment in half I then don't know how much to angle each segment relative to the last, and how long to make each segment to maintain the shape of the spiral, but make it smoother.

I can't just cut the angle in half. I've already considered that, and it would not maintain the shape of the curve. It seems I have to cut it in quarters when I cut the number of segments in half... So maybe I need to divide angle by subdivisions^2. I'm not sure. And I still don't know what to do about the length of each segment and the percentage of change.

Anyone got any ideas?

Btw, here's some info form mathworld on logarithmic spirals. Maybe someoen who understand the math better than I can make some sense of it in this context.

http://mathworld.wolfram.com/LogarithmicSpiral.html


sswift(Posted 2004) [#2]
Here's a picture of my problem.

log

Note the blue line is the initial spiral, and the red one is my pathertic attempt to figure out how I should change angle and segment length to get a smoother spiral, but clearly they don't match up.


sswift(Posted 2004) [#3]
So isn't there anyone here mathematically up to this?

Here's another look at the problem:

I hate prohosting

I'm pretty sure I need to know how the angle between lines P1P4 and P1P3 ie, angle C - and B, relates to the angle B. If I know that then I can calculate the point P4.


Floyd(Posted 2004) [#4]
To summarize the MathWorld info, for a given central angle you have a point (x,y):

r = A*Exp( B*angle )
x = r*Cos( angle )
y = r*Sin( angle )

Where A,B are known constants.

This gives (x,y) on the curve in terms of the angle.
Going the other way, if you know (x,y) on the curve then use

r = Sqr( x*x + y*y )
angle = Log( r/A ) / B

to find the angle.

Finally, the key fact that arc length is given by

arc = C * Exp( B*angle )

where C = Sqr( 1 + B*B ) * A / B is a known constant.

This is arc length in terms of angle. Solving for angle gives

angle = Log( arc/C ) / B

This tells you how to find points at given 'distances' along the curve.
Say you have two points on the spiral and you want a point one third
of the way from the first to the second. Using the equations given above you
find the corresponding arc lengths arc1,arc2 for these points.
The point you seek has arc length

arc = arc1 + (arc2-arc1)/3

and you know how to find the angle for this point from its arc length.


sswift(Posted 2004) [#5]
Thanks Floyd. Not sure if that'll be a help to me yet or not... I'll have to go over it with a fine toothed comb to understand what you're talking about, but it looks like a promising direction to investigate.


sswift(Posted 2004) [#6]
Floyd, I think I understand what you're saying, but how do I calculate A and B from a given set of points known to lie on the arc? If I understood you correctly, you're implying that I should know A and B... have chosen values for them. The method I'm using goes against that. So I need to calcualte them from something. I know the location of three points on the curve and the angle between them. Can I calculate A and B from those?


Floyd(Posted 2004) [#7]
Given length, taper and angle the values A and B are forced.
Global length# = 16.0
Global  taper# =  0.95  ; 0.85 to 0.95 produce nice looking sprirals 
Global  angle# = 22.5

; Logarithmic spiral:   r = A * Exp( B * theta )

Global A# = length / Sqr( 1.0 + taper^2 - 2*taper*Cos(angle) )
Global B# = Log( taper ) / angle

Graphics 800, 600, 0, 1
Origin 300, 350

DrawSpiral
DrawTriangles

WaitKey : End 


Function DrawPixel( x#, y# )

	s# = 420.0 / A
	Plot x*s, -y*s

End Function

Function DrawLine( x1#,y1#, x2#,y2# )
	
	s# = 420.0 / A
	Line x1*s, -y1*s, x2*s, -y2*s

End Function

Function DrawSpiral()

	Color 150,150,0

	For theta# = 0 To 9*360 Step 0.1
		r# = A * Exp( B * theta )
		x# = r * Cos( theta )
		y# = r * Sin( theta )	
		DrawPixel x, y
	Next
	
End Function

Function DrawTriangles()

	x1# = A : y1# = 0.0
	Color 50,50,50
	drawline 0,0, x1,y1
	
	r# = A
	For n = 1 To 270 / angle
	
		theta# = n * angle
		r = r * taper
		x2# = r * Cos(theta)
		y2# = r * Sin(theta)
		
		Color 255,255,255
		Drawline x1,y1, x2,y2 
	
		x1 = x2
		y1 = y2
	
		Color 50,50,50
		drawline 0,0, x1,y1
		
	Next
	
End Function

This draws a sequence of triangles, each consisting of one white side and two gray sides.
The triangles are similar. Each is like its predecessor, but with all sides multiplied by taper#.

Each triangle has one vertex on the logarithmic spiral.

NOTE: I've just made a change to the equation for A, which I had copied incorrectly from my notes.

In the example program the value of A turns out to be irrelevant.
It is the length of the first (theta=0) edge of the first triangle.
But the code scales everything to fit on the screen.
The first edge is drawn as if A were 420, no matter what A really is.


sswift(Posted 2004) [#8]
Floyd I took a close look at your program, but it doesn't work in the way I need to calculate the spiral.

For one, length appears to have no effect on the spiral. Length should reduce the size of the individual segments.

Which brings me to the second problem. Angle. Angle, as you have defined it in your program defines the angle of each point around the spiral relative to 0,0. That's not the way in which I need angle to work.

Look at the right side of your spiral. See that first segment? I need that to go straight up. Then, I need to rotate each segment after that clockwise or counterclockwise by some angle the user defines.

The way I want it, a taper of 1.0 and an angle of 0 should result in a straight line going straight up, with no curvature and with all segments evenly spaced, with the spacing defined by length.


Floyd(Posted 2004) [#9]
Well, I see there is another message thread which may make this all unneeded.
But here are some comments.

First about the length. The points x,y do depend on length L.
But for plotting purposes everything is then scaled to fit the screen.
After all 16 pixels actual size doesn't look like much.

I have generated these using the 22.5 degree change in the 'central angle' rather than the edge which approximates the spiral. It may not be obvious but this is the same angle by which the edge rotates.

Try my code with the call to DrawSpiral commented out. Study the triangles.
Each succeeding triangle is exactly like the its predecessor, but with all sides scaled by the same amount.

It is also rotated, in this case by 22.5 degrees. That means all three sides are rotated by this same amount, including the white edge.

It starts at x=A, y=0 and is not in the direction you want.
But this easily fixed by subtracting an offset, just as Blitz's Origin command does.

If you have an equation y = f(x) and you want a point (p,q) to be the new origin then the new equation is (y-q) = f(x-p).

The same is true in the polar case. If you need to rotate the entire graph then simply replace theta with (theta-offset).