2D polygon generation
Blitz3D Forums/Blitz3D Beginners Area/2D polygon generation
| ||
I first created this function to give myself some extra polys to play with. So far Iv'e just used it in a screen saver. THE PROBLEM IS, the octogon, decagon,dodecagon have gaps between some of the corners. And the 11 gon(whatever thats called) has an uneven side. I originally thought that it was due to coordinates not being floating point numbers, but it's mostly the even numbers giving me problem. Any help would be greatly appreciated. Graphics 320,240,16,2 AutoMidHandle(True) size = 3 Print "Press mouse button to change polygons......" WaitMouse While Not KeyDown(1) Cls polygon = PolyImage(size,100,0,255,255,255) DrawImage polygon,320/2,240/2 FreeImage polygon Text 320/2,240/2,size + " sides",1,1 WaitMouse size = size + 1 If size > 12 Then size = 3 Wend End ;Creates an image of a polygon and returns it to specified handle ;**************************************************************** Function PolyImage(numSides,size,rotation,r,g,b) Color r,g,b polygon = CreateImage(size*2,size*2) SetBuffer ImageBuffer(polygon) Origin size,size rotationSolver = rotation + 90 sides= 360/numSides degrees = 0-rotationSolver a = 0 ;Generate coordinates of the polygon corners with polar coordinate system based on sin/cos ;***************************************************************************************** Repeat y = Sin(degrees)*size x = Cos(degrees)*size ;Plot x,y a = a + 1 Select a Case 1 px1 = x py1 = y Case 2 px2 = x py2 = y Case 3 px3 = x py3 = y Case 4 px4 = x py4 = y Case 5 px5 = x py5 = y Case 6 px6 = x py6 = y Case 7 px7 = x py7 = y Case 8 px8 = x py8 = y Case 9 px9 = x py9 = y Case 10 px10 = x py10 = y Case 11 px11 = x py11 = y Case 12 px12 = x py12 = y End Select degrees = degrees + sides Until degrees > 360 ;draw sides of polygons based on corners coordinates Select numSides Case 3 Line px1,py1,px2,py2 Line px2,py2,px3,py3 Line px3,py3,px1,py1 Case 4 Line px1,py1,px2,py2 Line px2,py2,px3,py3 Line px3,py3,px4,py4 Line px4,py4,px1,py1 Case 5 Line px1,py1,px2,py2 Line px2,py2,px3,py3 Line px3,py3,px4,py4 Line px4,py4,px5,py5 Line px5,py5,px1,py1 Case 6 Line px1,py1,px2,py2 Line px2,py2,px3,py3 Line px3,py3,px4,py4 Line px4,py4,px5,py5 Line px5,py5,px6,py6 Line px6,py6,px1,py1 Case 7 Line px1,py1,px2,py2 Line px2,py2,px3,py3 Line px3,py3,px4,py4 Line px4,py4,px5,py5 Line px5,py5,px6,py6 Line px6,py6,px7,py7 Line px7,py7,px1,py1 Case 8 Line px1,py1,px2,py2 Line px2,py2,px3,py3 Line px3,py3,px4,py4 Line px4,py4,px5,py5 Line px5,py5,px6,py6 Line px6,py6,px7,py7 Line px7,py7,px8,py8 Line px8,py8,px1,py1 Case 9 Line px1,py1,px2,py2 Line px2,py2,px3,py3 Line px3,py3,px4,py4 Line px4,py4,px5,py5 Line px5,py5,px6,py6 Line px6,py6,px7,py7 Line px7,py7,px8,py8 Line px8,py8,px9,py9 Line px9,py9,px1,py1 Case 10 Line px1,py1,px2,py2 Line px2,py2,px3,py3 Line px3,py3,px4,py4 Line px4,py4,px5,py5 Line px5,py5,px6,py6 Line px6,py6,px7,py7 Line px7,py7,px8,py8 Line px8,py8,px9,py9 Line px9,py9,px10,py10 Line px10,py10,px1,py1 Case 11 Line px1,py1,px2,py2 Line px2,py2,px3,py3 Line px3,py3,px4,py4 Line px4,py4,px5,py5 Line px5,py5,px6,py6 Line px6,py6,px7,py7 Line px7,py7,px8,py8 Line px8,py8,px9,py9 Line px9,py9,px10,py10 Line px10,py10,px11,py11 Line px11,py11,px1,py1 Case 12 Line px1,py1,px2,py2 Line px2,py2,px3,py3 Line px3,py3,px4,py4 Line px4,py4,px5,py5 Line px5,py5,px6,py6 Line px6,py6,px7,py7 Line px7,py7,px8,py8 Line px8,py8,px9,py9 Line px9,py9,px10,py10 Line px10,py10,px11,py11 Line px11,py11,px12,py12 Line px12,py12,px1,py1 End Select SetBuffer FrontBuffer() Return polygon End Function ;PolyImage() |
| ||
Well, first of all, I would change all of your position variables to floating point numbers. You actually only have to do this the first time the variable is used in the code if you don't feel like changing all of them. 11 sided polygons do not have angles that are integers. 360/11 = 32.727272727272727272727272727273 This is why your last side is shorter. |
| ||
Thanx for the reply WolRon. Unfortunatly, that doesn't work. Although I agree with you on 11. 8,10,and 12 give me even results. The math problem has to be somewhere else. |
| ||
And on another note. Can coordinates be other than whole numbers? |
| ||
change polygon = CreateImage(size*2,size*2) to polygon = CreateImage(size*2+1,size*2+1) or change y = Sin(degrees)*size and x = cos(degrees)*size to y = Sin(degrees)*(size - 1) and x = Cos(degrees)*(size - 1) Edit: reason for the gaps is that your plotting off the edge of the image by 1 pixel. |
| ||
Tom....good eyes. I knew it was something stupid, I just could not see it. Thanks. |
| ||
Well, not really. Noticed you put in a function to rotate the ploygons. Thought I'd make use of it and see if the problem was caused by the angle of the lines. Then I noticed that all the gaps appeared either at the very bottom or at the very right edge, that's when I realized that it must be drawing off the edge of the image buffer. So I changed DrawImage to DrawBlock (so it wouldn't draw transparent) then colored the background of the screen red. Then it was easy to notice the lines drawing off the rectangle. Had you not put in that rotation function, I might still be trying to figure out your problem. |
| ||
Thats kinda funny. If I never put in the rotation, I might have figured it out. Putting in the rotation allowed you to fix it. Cool nun the less. Thanks again. |
| ||
That is a strange and not very good way to do the loop. what if you want say 37 sides ? How about this: Const ScreenWidth = 640 Const ScreenHeight = 480 Const CentreX = ScreenWidth / 2 Const CentreY = ScreenHeight / 2 Graphics ScreenWidth, ScreenHeight, 16, 2 AutoMidHandle(True) Sides = 3 Print "Press mouse button to change polygons......" WaitMouse While True If KeyHit(1) Exit EndIf X = MouseX() - CentreX Y = MouseY() - CentreY Size# = Sqr(X * X + Y * Y) Rot# = ATan2(Y, X) Polygon = PolyImage2(Sides, Size, Rot, 255, 255, 255) SetBuffer BackBuffer() Cls TileImage Polygon, CentreX, CentreY FreeImage Polygon Text CentreX, CentreY, "Sides = " + Sides + " Rot = " + Rot, 1, 1 Flip True If MouseHit(1) Sides = Sides + 1 If Sides > 12 Then Sides = 3 EndIf Wend End ;Creates an image of a polygon and returns it to specified handle ;**************************************************************** Function PolyImage2(numSides, size, rotation, r, g, b) Color r, g, b polygon = CreateImage(size * 2 + 1, size * 2 + 1) SetBuffer ImageBuffer(polygon) Origin size,size Local OldX#, OldY# Local NewX#, NewY# Local AngleStep# = 360 / numSides Local Angle# For i = 0 To numSides Angle = i * AngleStep + rotation OldX = NewX OldY = NewY NewX = size * Cos(Angle) NewY = size * Sin(Angle) If (i <> 0) Line OldX, OldY, NewX, NewY EndIf Next Return polygon End Function The function is not only a lot shorter but more flexible as numSides can be anything with no need to add code. I also added a bit more functionality in the mainline like rotating the polygon according to the mouse position and tiling the image for a cool but cheap effect. Hence the switch to continuous drawing and flip etc. |
| ||
That is alot shorter. And better for equilateral shapes. In fact that is very similar to how i was originally writing it. I chose this method because it allowed me to more easily prototype other shapes based on the same numbers like pentangles and hexangles. It also gives me more direct control over the individual coordinates for non equilateral shapes, instead of effecting each pair equally. Eventually it will all be much more economical. And as for the amount of sides.....I definitely agree , But I also figured once you get past 15 or so, you would be better off using the oval command. I DO VERY MUCH APPRECIATE THE IMPROVEMENT TO MY CODE. Thanks PGF. |