Problem calculation points in pentagon

BlitzMax Forums/BlitzMax Programming/Problem calculation points in pentagon

Sokurah(Posted 2008) [#1]
I hope someone can help me with this - I can't figure it out.

First a picture for reference;


The code below will draw a 5 sided tube - a pentagon (the mesh shown in white in the picture, is the output from the code below).

Just a pentagon is pretty easily done, as the corners of the shapes are really just the points where the other sections join up.

What I would really like to do, is to have "free-floating plates" instead of a big connected mesh, but I can't quite figure out how to do it
(see picture - I've drawn in red how I'd like it to look)

It's easy to do for each "ring" as I can just add a little extra space between them - try to press F1 and you'll see what I mean.

...but I can't figure out how to do the calculations so it works the way I'd like it to, with the cells to the sides.

And I need it to be able to zoom and rotate. The sample already rotates - use arrowkeys left/right.
Can anyone help?




Emmett(Posted 2008) [#2]
This is a unique problem that I have been experimenting with all week. I do not know how to implement the math to solve this however here are my thoughts. Maybe you can do the math.
You are solving for 5 points about a circle. Try solving for 10 points about a circle.
1st point at 1 degrees, 2nd point at 71 degrees, 3rd point at 73 degrees, 4th point at 143 degrees, 5th point at 145 degrees, 6th point at 215 degrees, 7th point at 217 degrees, 8th point at 287 degrees, 9th point at 289 degrees, 10th point at 359 degrees.
Thats 70 degrees for each line segment and 2 degrees of space between each.
If keydown(key_up) Then zoom3:+2 'not working corrently
Why do you say "not working corrently"? It appears to work OK.
Your labeling of points is a little confusing, why not just use a,b,c,d or 1,2,3,4?
As in: x1,y1; x2,y2; x3,y3; x4,y4 or xa,ya; xb,yb; xc,yc; xd,yd.
I hope my post will stimulate your "cells" and get you to try different approaches to this.
Maybe someone who really knows what they are doing will take a little time to help you on this too.


Bremer(Posted 2008) [#3]
Not quite what you need, but this was what I had so far. Lets hope someone else comes along and help you out.

SuperStrict

Graphics 800,600

Local sine:Int = 0
Local angle:Int = 0
Local update:Int = MilliSecs()

While Not KeyHit(KEY_ESCAPE)
	Cls
	drawCells(5,100,5,100+Sin(sine)*50,angle)
	drawCells(5,100,5,200+Sin(sine)*50,angle)
	drawCells(5,100,5,300+Sin(sine)*50,angle)
	drawCells(5,100,5,400+Sin(sine)*50,angle)
	Flip

	sine :+ 5
	If sine > 360 Then sine :- 360
	angle :+ 2
	If angle > 360 Then angle :- 360

	While MilliSecs()<update+(1000/30)
	Wend
	update=MilliSecs() 

Wend
End

Function drawCells(cellCount:Int,cellHeight:Int,cellSpace:Int,cellDistance:Int,cellAngle:Int)
	Local x1:Int,x2:Int,x3:Int,x4:Int,y1:Int,y2:Int,y3:Int,y4:Int
	Local cellHalfHeight:Int = (cellHeight / 2) - cellSpace
	Local cellHalfAngle:Int = ((360/cellCount)/2) - cellSpace
	Local cellAngleAdd:Int = 360 / cellCount

	For Local i:Int = 0 To cellCount-1
		' buttom points
		x1 = 400+Sin(cellAngle-cellHalfAngle)*(cellDistance-cellHalfHeight)
		y1 = 300+Cos(cellAngle-cellHalfAngle)*(cellDistance-cellHalfHeight)
		x2 = 400+Sin(cellAngle+cellHalfAngle)*(cellDistance-cellHalfHeight)
		y2 = 300+Cos(cellAngle+cellHalfAngle)*(cellDistance-cellHalfHeight)
		' top points
		x3 = 400+Sin(cellAngle-cellHalfAngle)*(cellDistance+cellHalfHeight)
		y3 = 300+Cos(cellAngle-cellHalfAngle)*(cellDistance+cellHalfHeight)
		x4 = 400+Sin(cellAngle+cellHalfAngle)*(cellDistance+cellHalfHeight)
		y4 = 300+Cos(cellAngle+cellHalfAngle)*(cellDistance+cellHalfHeight)
		' buttom line
		DrawLine x1,y1,x2,y2
		' top line
		DrawLine x3,y3,x4,y4
		' left line
		DrawLine x1,y1,x3,y3
		' right line
		DrawLine x2,y2,x4,y4
		cellAngle:+ cellAngleAdd
	Next
End Function



sswift(Posted 2008) [#4]
What you need, is normals!

If you can make the white outlined version, then you're halfway there.

To make the red version, what you need to do is calculate the 2D normal of the two lines adjacent to that point.

How do you do that?

I'm glad you asked!

; -----------------------------------------------------------------------------------------------------------------------------------
; This function calculates the equation of a 2D line.
;
; The equation of a 2D line is the same as the equation of a plane, except that the C component (Normal Z) is assumed to be 0.
; If facing down the line from point 1 to point 2, the line's normal will point left.
; In other words, if the line is an edge of a triangle wound clockwise, the resulting edge normals will point outwards.
;
; Function assumes positive Y is up, unlike screen coordinates.
; -----------------------------------------------------------------------------------------------------------------------------------
Function CLIP_Calculate2DLine(X1#, Y1#, X2#, Y2#)

	Local Nx#, Ny#, Nl#

	; Calculate the normal of the line, (A = Nx, B = Ny) and the distance of the line (D) from the origin (0,0,0).
	Nx# = Y2# - Y1# 
	Ny# = X1# - X2#

	; Normalize the normal.
	Nl# = Sqr(Nx#*Nx# + Ny#*Ny#)
	
	CLIP_A# = Nx# / Nl#
	CLIP_B# = Ny# / Nl#
	CLIP_D# = -(CLIP_A#*X1# + CLIP_B#*Y1#)
	
End Function



This code will calculate a normal for a line which points perpendicular to the line in 2D space.

If you go clockwise around your shape, you will get a bunch of normals which point outwards. So either go counterclockwise, or invert the order you pass the points to the function to get normals which point inwards.

Once you've done that, multiply the components of the normals for the two lines adjacent to each vertex. Ie, Nx# = N1x#*N2x#, Ny# = N1y#*N2y#

Then calculate the length of that normal, and normalize it just like I did in the code above with the normal I calculated for the line.

Once you've done that, you now have a vector which tells you which way you need to move that particular vertex. Decide how far you want to move it, multiply the components of the normal by that amount, and then add the normal's X and Y to the X and Y of the vertex. This is your new position for the vertex.

And voila, you have space between the polygons!


This is really just an inverse 2D version of what you do when you want to create an outline around a 3D mesh. We're just using 2D normals instead of 3D normals, and calculating the vertex normals with the normals of lines instead of the normals of planes, and we're moving the vertices inward instead of outward.


sswift(Posted 2008) [#5]
Um, I should specify that to do the above you should be creating these shapes as three and four sided 2D polygons. Ie, for each one you specify three or four vertices, and then draw lines between those. Then you can use the method I described to adjust the position of those vertices for each polygon to make the space between them.


Sokurah(Posted 2008) [#6]
Holy cow. No answer for a few days so I haven't checked this thread until now, and suddenly there's lots of answers. I have managed to solve the problem in the meantime though.

The solution to the problem was actually quite simple once I thought a little more about it. Instead of eg. angles at 0,72,144 (and so on) degrees, I would just add 1 degree on one side and subtract one from the other side, so it works perfect now.

So it's basically what you suggest Emmett, only I'm still only calculating 5 points. And...ehrm...the reasoning behind my labeling of points is basically that...I can be a bit of a slob sometimes.
I really should change the variablenames before the code becomes too unreadable. :)

...actually, the result of my code looks very close to your example zawran. :)
Thank you for that example. Not that I have any use for it now, but I appreciate you taking the time to help me...and you can be proud of the code - I like it when people include example code so you can se the result right aways. Hey, I like instant gratification. ;)

sswift; I must admit that I didn't really understand much of what you said. :D Normals, polygons (is that what I'm doing?), vertexes...damn, I'm glad I've already figured it out. :)
But thanks - I'll keep re-reading it until I understand it. :)

Thanks for the help guys.