Drawing Arcs
@Trond - because GDI+ and the Arc_() command are both bound by a rectangle which means the ellipse is either elongated on the x or y axis.  I need to set the elongated edge around the z axis, if that makes sense.  It's for a silly little program that I'm working on on the side ^_^
@Ollivier - it works although I had to scare up a quick old memory on coordinate systems to vaguely remember something about degrees and radians
I especially like being able to have points available as I was hoping to color different parts different colors.
Thanks so much!
			
			
									
									
						@Ollivier - it works although I had to scare up a quick old memory on coordinate systems to vaguely remember something about degrees and radians
I especially like being able to have points available as I was hoping to color different parts different colors.
Thanks so much!
Did you try RotateDC_()?Xombie wrote:@Trond - because GDI+ and the Arc_() command are both bound by a rectangle which means the ellipse is either elongated on the x or y axis. I need to set the elongated edge around the z axis, if that makes sense. It's for a silly little program that I'm working on on the side ^_^
Sorry, RotateDC() was I function I had written myself. I meant SetWorldTransform_().
			
			
									
									
						Code: Select all
Procedure RotateDC(hDC.l, x0.l, y0.l, Degrees.d)
  Static XFORM.XFORM
  Protected Radians.d = Degrees*(#PI/180)
  With XFORM
    \eM11 = Cos(Radians)
    \eM12 = Sin(Radians)
    \eM21 = -\eM12
    \eM22 = \eM11
    \ex = x0 - Cos(Radians)*x0 + Sin(Radians)*y0
    \ey = y0 - Cos(Radians)*y0 - Sin(Radians)*x0
  EndWith
  SetGraphicsMode_(hDC, #GM_ADVANCED)
  SetWorldTransform_(hDC, XFORM)
EndProcedureCode: Select all
Procedure RotateDC(hDC.l, x0.l, y0.l, Degrees.d) 
  Static XFORM.XFORM 
  Protected Radians.d = Degrees*(#PI/180) 
  With XFORM 
    \eM11 = Cos(Radians) 
    \eM12 = Sin(Radians) 
    \eM21 = -\eM12 
    \eM22 = \eM11 
    \eDx = x0 - Cos(Radians)*x0 + Sin(Radians)*y0 
    \eDy = y0 - Cos(Radians)*y0 - Sin(Radians)*x0 
  EndWith 
  SetGraphicsMode_(hDC, #GM_ADVANCED) 
  SetWorldTransform_(hDC, XFORM) 
EndProcedure
OpenWindow(0, 0, 0, 384, 384, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
CreateGadgetList(WindowID(0))
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Repaint
      hDC = StartDrawing(WindowOutput(0))
        Line(100, 100, 200, 0, #Red)
        RotateDC(hDC, WindowWidth(0)/2, WindowHeight(0)/2, 90)
        Line(100, 100, 200, 0, #Blue)
        RotateDC(hDC, WindowWidth(0)/2, WindowHeight(0)/2, 180)
        Line(100, 100, 200, 0, #Green)
      StopDrawing()
    Case #PB_Event_CloseWindow
      Break
  EndSelect
ForEver
To run your code, I replaced the 2 lines
with
It's exactly what Xombie could use with the API Ellipse drawing function!
But I ignore the XFORM structure. Has it other variables. Its variables are they in function of the functions using it, or do they have a independant mean?
			
			
									
									
						Code: Select all
    \eDx = x0 - Cos(Radians)*x0 + Sin(Radians)*y0 
    \eDy = y0 - Cos(Radians)*y0 - Sin(Radians)*x0 
 Code: Select all
    \ex = x0 - Cos(Radians)*x0 + Sin(Radians)*y0 
    \ey = y0 - Cos(Radians)*y0 - Sin(Radians)*x0 
 But I ignore the XFORM structure. Has it other variables. Its variables are they in function of the functions using it, or do they have a independant mean?
Trond - thanks a lot for that code.  It's very useful.  Now I have a question about the passed x & y variables.  If I'm drawing an arc at (10, 10) with an image size of 200x300 and I want to rotate about it's begin point (10, 10) would I pass 10 as the parameter for x & y or is it something else?  I've tried that but it looks like it didn't work.  However, I would not be surprised if I messed it up.
A small background on what I'll be doing. I'll have an image of random size and allow the user to mark a section of the image. I would then want to draw a lot of arcs about some slightly random angle but all within that marked section. The angle could possibly change for each arc and there will be many thousand arcs (more likely tens of thousands and more) within the area. I would be randomly choosing a beginning location within the area for each arc and then drawing them around a random angle. The angle is determined by the user but then a 1-10% (or more depending on the user) random amount is added to that base angle. So I'll have the defined area, the starting x & y location of the arc and the angle of the arc. Sigh. I'm rambling. Does any of that mess I just said make sense? If not, I'll take a deep breath and try again.
Once again - thanks to both of you. This looks like it'll be what I need once I work out a few things ^_^
			
			
									
									
						A small background on what I'll be doing. I'll have an image of random size and allow the user to mark a section of the image. I would then want to draw a lot of arcs about some slightly random angle but all within that marked section. The angle could possibly change for each arc and there will be many thousand arcs (more likely tens of thousands and more) within the area. I would be randomly choosing a beginning location within the area for each arc and then drawing them around a random angle. The angle is determined by the user but then a 1-10% (or more depending on the user) random amount is added to that base angle. So I'll have the defined area, the starting x & y location of the arc and the angle of the arc. Sigh. I'm rambling. Does any of that mess I just said make sense? If not, I'll take a deep breath and try again.
Once again - thanks to both of you. This looks like it'll be what I need once I work out a few things ^_^
- 
				dell_jockey
 - Enthusiast

 - Posts: 767
 - Joined: Sat Jan 24, 2004 6:56 pm
 
what are you into, Xombie? CFD, FEA or something?Xombie wrote:Trond - thanks a lot for that code. It's very useful. Now I have a question about the passed x & y variables. If I'm drawing an arc at (10, 10) with an image size of 200x300 and I want to rotate about it's begin point (10, 10) would I pass 10 as the parameter for x & y or is it something else? I've tried that but it looks like it didn't work. However, I would not be surprised if I messed it up.
A small background on what I'll be doing. I'll have an image of random size and allow the user to mark a section of the image. I would then want to draw a lot of arcs about some slightly random angle but all within that marked section. The angle could possibly change for each arc and there will be many thousand arcs (more likely tens of thousands and more) within the area. I would be randomly choosing a beginning location within the area for each arc and then drawing them around a random angle. The angle is determined by the user but then a 1-10% (or more depending on the user) random amount is added to that base angle. So I'll have the defined area, the starting x & y location of the arc and the angle of the arc. Sigh. I'm rambling. Does any of that mess I just said make sense? If not, I'll take a deep breath and try again.
Once again - thanks to both of you. This looks like it'll be what I need once I work out a few things ^_^
here is how i managed to draw ellipses in any rotation, clippin or size, using some polygon-macros of mine.
but for the rotation i didn't find a way else than to calculate back the angle and radius of each point, to add the rotation-angle, and then to re-calculate the new position (as Kaeru Gaman explained). so i'm using an getAngle()-function and also Sqrt() for each point.
the code is a bit bigger, because the parts come from a generall drawing context, not for ellipses in particular.
			
			
									
									
						but for the rotation i didn't find a way else than to calculate back the angle and radius of each point, to add the rotation-angle, and then to re-calculate the new position (as Kaeru Gaman explained). so i'm using an getAngle()-function and also Sqrt() for each point.
the code is a bit bigger, because the parts come from a generall drawing context, not for ellipses in particular.
Code: Select all
Procedure.f getAngle(mx,my, px,py, mode.l=1)
; returns the angle of a line going from point
; [mx,my] to point [px,py] in radian
; mode=1 (default):
; pointing to the right means 0 degrees
; pointing to the top means 90 degrees, ect
; [math y-axis]
; mode=-1:
; pointing to the right means 0 degrees
; pointing to the bottom means 90 degrees, ect
; [screen y-axis.]
  Protected xd=px-mx
  Protected yd=py-my
  Protected alpha.f
  
  If xd>0
    If     yd<0 :: alpha=         ATan(-yd / xd )
    ElseIf yd>=0 :: alpha= 2*#PI - ATan( yd / xd )
    EndIf
  ElseIf xd<0
    If     yd<0 :: alpha=   #PI - ATan(-yd /-xd )
    ElseIf yd>=0 :: alpha=   #PI + ATan( yd /-xd )
    EndIf
  ElseIf xd=0
    If     yd>0 : alpha=   #PI*1.5
    ElseIf yd<0 : alpha=   #PI*0.5
    EndIf
  EndIf
  If mode=-1
    alpha = 2*#PI-alpha
  EndIf
  ProcedureReturn alpha
EndProcedure
Structure _S_poly
  p0.POINT
  p.POINT
  go.POINT
  center.POINT
  radius.l
  angle.f
  color.l
  relative.l
  temp.f
EndStructure
Global _poly._S_poly
Macro initRadialPoly(xCenter_, yCenter_, x_, y_, a_, color_=$ffffff, relative_=#True)
  _poly\center\x = xCenter_
  _poly\center\y = yCenter_
  _poly\angle = a_
  _poly\temp = getAngle(_poly\center\x, _poly\center\y, _poly\center\x + (x_), _poly\center\y + (y_),-1)
  _poly\radius = Sqr( (x_)*(x_)+(y_)*(y_) )
  _poly\p0\x = _poly\center\x + _poly\radius * Cos(_poly\angle + _poly\temp)
  _poly\p0\y = _poly\center\y + _poly\radius * Sin(_poly\angle + _poly\temp)
  _poly\p\x  = _poly\p0\x
  _poly\p\y  = _poly\p0\y
  _poly\color = color_
  _poly\relative = relative_
EndMacro
Macro setRadialPoly(x_, y_, color_=_poly\color)
  _poly\temp = getAngle(_poly\center\x, _poly\center\y, _poly\center\x + (x_), _poly\center\y + (y_),-1)
  _poly\radius = Sqr( (x_)*(x_)+(y_)*(y_) )
  _poly\go\x = _poly\center\x + _poly\radius * Cos(_poly\angle + _poly\temp)
  _poly\go\y = _poly\center\y + _poly\radius * Sin(_poly\angle + _poly\temp)
  LineXY( _poly\p\x, _poly\p\y, _poly\go\x, _poly\go\y, color_)
  _poly\p\x = _poly\go\x
  _poly\p\y = _poly\go\y
EndMacro
Macro closePoly(color_=_poly\color)
  LineXY(_poly\p\x, _poly\p\y, _poly\p0\x, _poly\p0\y, color_)
EndMacro
Macro rad(_deg_)
  ((_deg_)*0.017453292519943295) ; _deg_ * #PI / 180
EndMacro
InitSprite()
ww=800
wh=600
hWin=OpenWindow(0, 50,50,ww,wh, "")
OpenWindowedScreen( hWin, 0,0,ww,wh, 0,0,0)
Repeat
  event=WaitWindowEvent()
  Select event
    Case #PB_Event_CloseWindow
      quit=1
  EndSelect
  StartDrawing(ScreenOutput())
    
    ;an angled ellipse
    
    centerX = 300 ; mid
    centerY = 200
    r1    = 200   ; radius
    r2    = 100
    angle = DesktopMouseY() ; rotation
    min   = DesktopMouseX() ; starting angle (in unrotated ellipse)
    max   = min+356-45      ; end angle      (in unrotated ellipse)
    Circle(200,600,3,$0000ff)
    initRadialPoly(centerX,centerY, r1*Cos(rad(min)), r2*Sin(rad(min)), rad(angle), $0000ff)
    For i=min To max ;Step 20
      setRadialPoly(r1*Cos(rad(i)),r2*Sin(rad(i)))
    Next
    ;closePoly()
    
  StopDrawing()
  FlipBuffers()
  ClearScreen($333333)
Until quit
- zxtunes.com
 - Enthusiast

 - Posts: 375
 - Joined: Wed Apr 23, 2008 7:51 am
 - Location: Saint-Petersburg, Russia
 - Contact:
 
Some modification Ollivier code:
Now arc have point "StartAngle" - start position and any moving about this point (Are adhered to it).
This useful for me current game, may be anymody too.
			
			
									
									
						Now arc have point "StartAngle" - start position and any moving about this point (Are adhered to it).
This useful for me current game, may be anymody too.
Code: Select all
Global x_pos.l, y_pos.l
Procedure EllipseWithRotation(xCenter.f, yCenter.f, xRadius.f, yRadius.f, zRotation.f, StartAngle.f, put) 
    Protected angle.f 
    Protected AngleStep.f    
    Protected x.f 
    Protected y.f 
    Protected DisplayX.f 
    Protected DisplayY.f 
    Protected GreatestRadius.f
  
    If xRadius > yRadius 
        GreatestRadius.f = xRadius 
    Else 
        GreatestRadius = yRadius 
    EndIf 
    AngleStep.f = #PI / GreatestRadius
    angle = StartAngle 
    f = 1
    For a=0 To GreatestRadius * 2     
        x.f = Cos(angle) * xRadius                           
        y.f = -Sin(angle) * yRadius 
        DisplayX.f = x * Cos(zRotation) - y * Sin(zRotation) + xCenter
        DisplayY.f = x * Sin(zRotation) + y * Cos(zRotation) + yCenter       
        
        If put: Plot(DisplayX, DisplayY, 255): EndIf
    
        If f And put=0: 
            x_pos = DisplayX: y_pos = DisplayY: f=0: Break
        EndIf
        
        angle + AngleStep       
     Next a   
EndProcedure
InitSprite() 
  InitKeyboard() 
  OpenScreen(1024, 768, 32, "x") 
   
  xr.f = 128
  yr.f = 64
  zr.f = 0
  fr.f = -#PI
  Repeat 
    ClearScreen(0)
    StartDrawing(ScreenOutput() ) 
    
    EllipseWithRotation(512,384, xr, yr, zr, fr, 0)
    
    EllipseWithRotation(512 + (x_pos-512), 384 + (y_pos-384), xr, yr, zr, fr, 1)
    Box(512-1, 384-1, 3, 3, 65535):
    
    StopDrawing() 
    FlipBuffers() 
    ExamineKeyboard() 
    
    If KeyboardPushed(#PB_Key_PageUp): zr + 0.04: EndIf 
    If KeyboardPushed(#PB_Key_PageDown): zr - 0.04: EndIf 
    If KeyboardPushed(#PB_Key_Up): yr - 1: EndIf 
    If KeyboardPushed(#PB_Key_Down) : yr + 1: EndIf
    If KeyboardPushed(#PB_Key_Left): xr - 1: EndIf 
    If KeyboardPushed(#PB_Key_Right): xr + 1: EndIf
    If KeyboardPushed(#PB_Key_Q): fr + 0.1: EndIf
    If KeyboardPushed(#PB_Key_A): fr - 0.1: EndIf
    
  Until KeyboardPushed(#PB_Key_Escape)
