About Monkey 2 › Forums › Monkey 2 Programming Help › need help solving a logic problem.
This topic contains 8 replies, has 3 voices, and was last updated by
Jesse
2 years, 4 months ago.
-
AuthorPosts
-
November 20, 2016 at 5:32 pm #5278
I have a logic problem I can’t figure out. I an trying to create a shape editor program. but I ran into problems when trying to create an arc while using the mouse. the Arc end points are handles that can be moved to increase or decrease the size of it’s circumference. and thats exactly where the problem is. I can move the handles to a certain point after that it draws the arc in reverse. it has to do with the way ATan2 Works.
I am posting and extract from my program in hope someone can help me figure this out. Use the mouse on the handles to edit the shape:
[/crayon]Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274[crayon-5cba8c882c8e9562581391 inline="true" ]Namespace shapeEditor#Import "<std>"#Import "<mojo>"Using std..Using mojo..Const Size:=New Vec2i( 640,480 )Class MyWindow Extends WindowField arc:ArcMethod New()Super.New( "My Window",640,480,WindowFlags.Resizable )Layout = "letterbox"arc = New Arc(100,100,100)EndMethod OnRender( canvas:Canvas ) OverrideApp.RequestRender()arc.Update()canvas.DrawText(arc.startAngle,10,10)canvas.DrawText(arc.endAngle,10,30)canvas.Color = New Color(.8,.1,.1)arc.Render(canvas)EndMethod OnKeyEvent( event:KeyEvent ) OverrideIf event.Type=EventType.KeyDown And event.Key=Key.Enter And event.Modifiers & Modifier.AltFullscreen=Not FullscreenEndifEndMethod OnMeasure:Vec2i() OverrideReturn SizeEndEndFunction Main()New AppInstanceNew MyWindowApp.Run()EndClass HandleField pos:Vec2dField location:Vec2iField radius:FloatMethod New(pos:Vec2d,radius:Float = 4)Self.pos = posEnd MethodMethod SetLocation(p:Vec2i)End MethodEnd ClassClass EntityField pos:Vec2dField color:ColorMethod New()pos = New Vec2dcolor = New Color(1,1,1,1)End MethodEnd ClassClass Arc Extends EntityField radius:FloatField startAngle:FloatField endAngle:FloatField angleSteps:FloatField stepSize:FloatField angleStep:FloatField lineWidth:FloatField arcCenter:Vec2dField prevs:FloatField preve:FloatField tpos:Vec2dField trad:Vec2dField tstart:Vec2dField teend:Vec2dField temp:Vec2dConst HANDLE_SIZE:Int = 4Method New(x:Float,y:Float,radius:Float=10,startAngle:Float=0,endAngle:Float=Pi/2.0,lineWidth:Int = 6)Self.pos =New Vec2d(x,y)Self.radius = radiusSelf.startAngle = startAngleSelf.endAngle = endAngleSelf.lineWidth = lineWidthSelf.arcCenter = New Vec2dSelf.prevs = Self.startAngleSelf.preve = Self.endAngleSelf.Init()End MethodMethod Init()Self.stepSize = 1.0/Pi*radiusSelf.angleStep = (endAngle-startAngle)/stepSizeLocal mid:Float = (endAngle-startAngle)/2.0arcCenter.Set(Cos(startAngle+mid)*radius,Sin(startAngle+mid)*radius)temp = New Vec2dEnd MethodMethod MouseInHandle:Bool()Local vx:Float = Mouse.X - pos.xLocal vy:Float = Mouse.Y - pos.yReturn Sqrt(vx*vx+vy*vy) <= HANDLE_SIZEEnd MethodMethod MouseInRadius:Bool()Local vx:Float = Mouse.X - (pos.x+arcCenter.x)Local vy:Float = Mouse.Y - (pos.y+arcCenter.y)Return Sqrt(vx*vx+vy*vy) <= HANDLE_SIZEEnd MethodMethod MouseInStart:Bool()Local x:Float = pos.x+Cos(startAngle)*radiusLocal y:Float = pos.y+Sin(startAngle)*radiusLocal vx:Float = Mouse.X - xLocal vy:Float = Mouse.Y - yReturn Sqrt(vx*vx+vy*vy) <=HANDLE_SIZEEnd MethodMethod MouseAtEnd:Bool()Local x:Float = pos.x+Cos(endAngle)*radiusLocal y:Float = pos.y+Sin(endAngle)*radiusLocal vx:Float = Mouse.X - xLocal vy:Float = Mouse.Y - yReturn Sqrt(vx*vx+vy*vy) <= HANDLE_SIZEEnd methodMethod Update()If Mouse.ButtonPressed(MouseButton.Left)If MouseInHandle()tpos = posElseif MouseInRadius()trad = arcCenterElseif MouseInStart()tstart = tempElseif MouseAtEnd()teend = tempEndifElseif Mouse.ButtonReleased(MouseButton.Left)tpos = Nulltrad = Nulltstart = Nullteend = NullEndifIf tpostpos.x = Mouse.Xtpos.y = Mouse.YElseif tradtrad.x = Mouse.X - pos.xtrad.y = Mouse.Y - pos.yLocal vx:Float = pos.x - (pos.x+trad.x)Local vy:Float = pos.y - (pos.y+trad.y)radius = Sqrt(vx*vx+vy*vy)Init()Elseif tstartLocal vx:Float = Mouse.X - pos.xLocal vy:Float = Mouse.Y - pos.yLocal cAngle:Float = ATan2(vy,vx)startAngle = (cAngle + TwoPi) Mod TwoPiangleStep = (endAngle-startAngle)/stepSizeInit()Elseif teendLocal vx:Float = Mouse.X - pos.xLocal vy:Float = Mouse.Y - pos.yendAngle = (ATan2(vy,vx)+ TwoPi) Mod TwoPiIf endAngle < startAngleLocal len:Float = startAngle - endAngleIf len > TwoPiendAngle += TwoPiEndifEndifangleStep = (endAngle-startAngle)/stepSizeInit()EndifEnd MethodMethod Render(canvas:Canvas)canvas.LineWidth = lineWidth' Determine coordinates of first point using basic circle math.Local xx:Float = Cos(startAngle) * radiusLocal yy:Float = Sin(startAngle) * radiusLocal px:Float = pos.x+xxLocal py:Float = pos.y+yycanvas.DrawCircle(px,py,HANDLE_SIZE)For Local i:Int = 1 To stepSize'' Increment the angle by "angleStep".Local angle:Float = startAngle + i * angleStep'' Determine Next point's coordinates using basic circle math.xx = pos.x + Cos(angle) * radiusyy = pos.y + Sin(angle) * radiuscanvas.DrawCircle(pos.x,pos.y,HANDLE_SIZE)'' Draw a line To the Next point.canvas.DrawLine(px,py,xx, yy)px = xxpy = yyNextLocal ex := Cos(endAngle) * radiusLocal ey := Sin(endAngle) * radiuscanvas.DrawLine(px,py,pos.x+ex,pos.y+ey)canvas.DrawCircle(pos.x+arcCenter.x,pos.y+arcCenter.y,HANDLE_SIZE)canvas.LineWidth = 1canvas.DrawLine(pos.x,pos.y,pos.x+arcCenter.x,pos.y+arcCenter.y)canvas.DrawCircle(pos.x+ex,pos.y+ey,HANDLE_SIZE)End MethodEnd ClassClass Vec2dField x:FloatField y:FloatMethod New()End MethodMethod New(x:Float,y:Float)Set(x,y)End MethodMethod New(x1:Float,y1:Float,x2:Float,y2:Float)Set(x2-x1,y2-y1)End MethodMethod New(v:Vec2d)Set(v)End MethodMethod Set:Vec2d(v:Vec2d)x = v.xy = v.yReturn SelfEnd MethodMethod Set:Vec2d(x:Float,y:Float)Self.x = xSelf.y = yReturn SelfEnd MethodEnd ClassI have tried several different ways of doing it but I can’t seem to figure out how to solve it.
November 20, 2016 at 5:35 pm #5279it would be easier to test with this #Import “vec2d.monkey2”
jplib?
can you reduce it to a minimal example that can be run on the defaul modules ?
November 20, 2016 at 5:48 pm #5280sorry I forgot about that. Corrected source code!
November 21, 2016 at 7:59 am #5298nice…. thats a proper pain!
I had a quick fiddle but no joy and speaking of joy http://gamedev.stackexchange.com/questions/46552/360-degree-rotation-skips-back-to-0-degrees-when-using-math-atan2y-x
interested to see how you get on….
November 21, 2016 at 3:33 pm #5312I’m going to have to scrap that idea somewhat and use vector sequence instead. It’ll help me freshen up on my vector math.
November 21, 2016 at 9:05 pm #5324here is some working example with starting and ending point, so if you invert the handles to arc will flip.
May be you don’t want it to flip when the angle is small. EDIT:If so just invert start and end when the switch occurs.Won’t work “just” like that…
You should have used Vec2f instead of redefine a vec2. Monkey is full of little gentle things like that..[/crayon]Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284[crayon-5cba8c88474b6994688729 inline="true" ]Namespace shapeEditor#Import "<std>"#Import "<mojo>"Using std..Using mojo..Const Size:=New Vec2i( 640,480 )Class MyWindow Extends WindowField arc:ArcMethod New()Super.New( "My Window",640,480,WindowFlags.Resizable )Layout = "letterbox"arc = New Arc(100,100,100)EndMethod OnRender( canvas:Canvas ) OverrideApp.RequestRender()arc.Update()canvas.DrawText(arc.startAngle,10,10)canvas.DrawText(arc.endAngle,10,30)canvas.DrawText(arc.stepSize,10,50)canvas.DrawText(arc.angleStep,10,70)canvas.Color = New Color(.8,.1,.1)arc.Render(canvas)EndMethod OnKeyEvent( event:KeyEvent ) OverrideIf event.Type=EventType.KeyDown And event.Key=Key.Enter And event.Modifiers & Modifier.Alt'Fullscreen=Not Fullscreen Returned an error..EndifEndMethod OnMeasure:Vec2i() OverrideReturn SizeEndEndFunction Main()New AppInstanceNew MyWindowApp.Run()EndClass HandleField pos:Vec2dField location:Vec2iField radius:FloatMethod New(pos:Vec2d,radius:Float = 4)Self.pos = posEnd MethodMethod SetLocation(p:Vec2i)End MethodEnd ClassClass EntityField pos:Vec2dField color:ColorMethod New()pos = New Vec2dcolor = New Color(1,1,1,1)End MethodEnd ClassClass Arc Extends EntityField radius:FloatField startAngle:FloatField endAngle:FloatField angleSteps:FloatField stepSize:FloatField angleStep:FloatField lineWidth:FloatField arcCenter:Vec2dField prevs:FloatField preve:FloatField tpos:Vec2dField trad:Vec2dField tstart:Vec2dField teend:Vec2dField temp:Vec2dConst HANDLE_SIZE:Int = 4Method New(x:Float,y:Float,radius:Float=10,startAngle:Float=0,endAngle:Float=Pi/2.0,lineWidth:Int = 6)Self.pos =New Vec2d(x,y)Self.radius = radiusSelf.startAngle = startAngleSelf.endAngle = endAngleSelf.lineWidth = lineWidthSelf.arcCenter = New Vec2dSelf.prevs = Self.startAngleSelf.preve = Self.endAngleSelf.Init()End MethodMethod Init()Self.stepSize = 1.0/Pi*radius'-------modified from hereLocal angleWidth:FloatIf startAngle<=endAngleangleWidth=(endAngle-startAngle)ElseangleWidth=(TwoPi+endAngle-startAngle)EndSelf.angleStep = angleWidth/stepSizeLocal mid:Float = angleWidth/2.0'-------to herearcCenter.Set(Cos(startAngle+mid)*radius,Sin(startAngle+mid)*radius)temp = New Vec2dEnd MethodMethod MouseInHandle:Bool()Local vx:Float = Mouse.X - pos.xLocal vy:Float = Mouse.Y - pos.yReturn Sqrt(vx*vx+vy*vy) <= HANDLE_SIZEEnd MethodMethod MouseInRadius:Bool()Local vx:Float = Mouse.X - (pos.x+arcCenter.x)Local vy:Float = Mouse.Y - (pos.y+arcCenter.y)Return Sqrt(vx*vx+vy*vy) <= HANDLE_SIZEEnd MethodMethod MouseInStart:Bool()Local x:Float = pos.x+Cos(startAngle)*radiusLocal y:Float = pos.y+Sin(startAngle)*radiusLocal vx:Float = Mouse.X - xLocal vy:Float = Mouse.Y - yReturn Sqrt(vx*vx+vy*vy) <=HANDLE_SIZEEnd MethodMethod MouseAtEnd:Bool()Local x:Float = pos.x+Cos(endAngle)*radiusLocal y:Float = pos.y+Sin(endAngle)*radiusLocal vx:Float = Mouse.X - xLocal vy:Float = Mouse.Y - yReturn Sqrt(vx*vx+vy*vy) <= HANDLE_SIZEEnd methodMethod Update()If Mouse.ButtonPressed(MouseButton.Left)If MouseInHandle()tpos = posElseif MouseInRadius()trad = arcCenterElseif MouseInStart()tstart = tempElseif MouseAtEnd()teend = tempEndifElseif Mouse.ButtonReleased(MouseButton.Left)tpos = Nulltrad = Nulltstart = Nullteend = NullEndifIf tpostpos.x = Mouse.Xtpos.y = Mouse.YElseif tradtrad.x = Mouse.X - pos.xtrad.y = Mouse.Y - pos.yLocal vx:Float = pos.x - (pos.x+trad.x)Local vy:Float = pos.y - (pos.y+trad.y)radius = Sqrt(vx*vx+vy*vy)Init()Elseif tstartLocal vx:Float = Mouse.X - pos.xLocal vy:Float = Mouse.Y - pos.ystartAngle = ATan2(vy,vx) '-------modfied this line for unusefull calculus'-------removed things hereInit()Elseif teendLocal vx:Float = Mouse.X - pos.xLocal vy:Float = Mouse.Y - pos.yendAngle = ATan2(vy,vx) '--------modfied this line for unusefull calculus'-------removed things hereInit()EndifEnd MethodMethod Render(canvas:Canvas)canvas.LineWidth = lineWidth' Determine coordinates of first point using basic circle math.Local xx:Float = Cos(startAngle) * radiusLocal yy:Float = Sin(startAngle) * radiusLocal px:Float = pos.x+xxLocal py:Float = pos.y+yycanvas.DrawCircle(px,py,HANDLE_SIZE)For Local i:Int = 1 To stepSize'' Increment the angle by "angleStep".Local angle:Float = startAngle + i * angleStep'' Determine Next point's coordinates using basic circle math.xx = pos.x + Cos(angle) * radiusyy = pos.y + Sin(angle) * radiuscanvas.DrawCircle(pos.x,pos.y,HANDLE_SIZE)'' Draw a line To the Next point.canvas.DrawLine(px,py,xx, yy)px = xxpy = yyNextLocal ex := Cos(endAngle) * radiusLocal ey := Sin(endAngle) * radiuscanvas.DrawLine(px,py,pos.x+ex,pos.y+ey)canvas.DrawCircle(pos.x+arcCenter.x,pos.y+arcCenter.y,HANDLE_SIZE)canvas.LineWidth = 1canvas.DrawLine(pos.x,pos.y,pos.x+arcCenter.x,pos.y+arcCenter.y)canvas.DrawCircle(pos.x+ex,pos.y+ey,HANDLE_SIZE)End MethodEnd ClassClass Vec2dField x:FloatField y:FloatMethod New()End MethodMethod New(x:Float,y:Float)Set(x,y)End MethodMethod New(x1:Float,y1:Float,x2:Float,y2:Float)Set(x2-x1,y2-y1)End MethodMethod New(v:Vec2d)Set(v)End MethodMethod Set:Vec2d(v:Vec2d)x = v.xy = v.yReturn SelfEnd MethodMethod Set:Vec2d(x:Float,y:Float)Self.x = xSelf.y = yReturn SelfEnd MethodEnd ClassNovember 21, 2016 at 10:09 pm #5325Oh, this is good! Thanks abakobo. that did it. I haven’t gone trough the code to see how you did it but it works so Thank you.
>You should have used Vec2f instead of redefine a vec2. Monkey is full of little gentle things like that..
I had several reasons for using my own Vector class. the #1 reason I had for using it was that I have some functionality on it that the default module does not have and I will be needing it in the long run. Another is that since I am using pointers to determine where the if statements take action and a null is needed and since the default vector is a structure it is really never Null, You don’t even have to create an instance of the structure for it to have a value or access its fields, so It was no use for this program.
November 21, 2016 at 10:52 pm #5326Structs goes on the stack and classes on the heap… So structs are theoretically faster.. if you’ll use your vects in very iterative process it will slowdown your app. In some very hungry loops it’s even interresting to use x and y with no structs at all!
November 22, 2016 at 12:07 am #5327I know how they work, but I wasn’t looking for speed. I just needed it to work. I know there are other ways I could have done it to make it even faster but it served it’s purpose so I am fine with it. Thanks for the advice anyway.
-
AuthorPosts
You must be logged in to reply to this topic.