Drawing Arcs
Drawing Arcs
I tried this question earlier in the GDI+ post under Tips & Tricks to no avail.  So now I'm making it a little more generic.
How can I draw an elliptical arc at any angle of my choosing? Anti-aliased would be nice but I can live without if I have to. Also, when I say "at any angle" I mean to rotate the theoretical ellipse before tracing it's arc. I do not mean to just start the arc angle at some degree followed by a different end angle.
Hope that makes sense and that someone out there can help.
			
			
									
									
						How can I draw an elliptical arc at any angle of my choosing? Anti-aliased would be nice but I can live without if I have to. Also, when I say "at any angle" I mean to rotate the theoretical ellipse before tracing it's arc. I do not mean to just start the arc angle at some degree followed by a different end angle.
Hope that makes sense and that someone out there can help.
- Kaeru Gaman
 - Addict

 - Posts: 4826
 - Joined: Sun Mar 19, 2006 1:57 pm
 - Location: Germany
 
(And to accelerate the execution of your algo)
(To explain what you wanna create, I put a convention : ^a = vector a)
In a classical plane (orthonormal or 'carthesian plane') named (O;^i;^j)
But these values are the result of trigo calcul like that:
Zéro is the angle of your draw (ellipse) in the plane (Z rotation)
So you replace 0 by a variable 'Zr'
Now, when you have a point p(x, y), you know that:
Examples:
>> Zr = 0 (no rotation)
>> Zr = Pi/2 (90° left rotation)
To begin a 3D engine, I wrote this code:
			
			
									
									
						(To explain what you wanna create, I put a convention : ^a = vector a)
In a classical plane (orthonormal or 'carthesian plane') named (O;^i;^j)
Code: Select all
>>O is the origin
>>^i is a horizontal vector (1;0) (x axial)
>>^j is a vertical vector (0;1) (y axial)Code: Select all
>> ^i [Cos(0); Sin(0) ]
>> ^j [Cos((Pi/2)+0); Sin((Pi/2)+0) ]     }} (Results are above)So you replace 0 by a variable 'Zr'
Code: Select all
>> ^i [Cos(Zr); Sin(Zr) ]
>> ^j [Cos(Pi/2+Zr); Sin(Pi/2+Zr) ]Now, when you have a point p(x, y), you know that:
Code: Select all
^p = x^i + y^j    (syntax: x^i = x*^i)
^p = x^[Cos(Zr); Sin(Zr) ] + y^[Cos((Pi/2)+Zr); Sin((Pi/2)+Zr) ]
^p = x^[A; B] + y^[C; D]
= ^p[xA + yC; xB + yD]   (Sum of 2 vectors)
= ^p[ xCos(Zr) + yCos((Pi/2)+Zr)  ;   xSin(Zr) + ySin((Pi/2)+Zr) ]>> Zr = 0 (no rotation)
Code: Select all
^p1[ xCos(0) + yCos((Pi/2)+0)  ;   xSin(0) + ySin((Pi/2)+0) ]
^p1[ x*1 + y*0)  ;   x*0 + y*1]
^p1[ x ; y ]Code: Select all
^p2[ xCos(Pi/2) + yCos((Pi/2)+Pi/2)  ;   xSin(Pi/2) + ySin((Pi/2)+Pi/2) ]
^p2[ xCos(Pi/2) + yCos(Pi)  ;   xSin(Pi/2) + ySin(Pi) ]
^p2[ x*0 + y*-1  ;   x*1 + y*0 ]
^p2[ -y ; x ]Code: Select all
 InitSprite() 
  InitKeyboard() 
  OpenScreen(1024, 768, 32, "x") 
  ;*********** 
  R.F = 100.0 
  Xtheta.F = 0.0 
  Ytheta.F = 0.0 
  Ztheta.F = 0.0      
  Ttheta.F = 0.0      
  ;*********** 
  Repeat 
    StartDrawing(ScreenOutput() ) 
      Box(0, 0, 1024, 768, #Black) 
      Vxx.F = Cos(Ztheta) 
      Vxy.F = -Sin(Ztheta) 
      Vyx.F = Cos(Ztheta + #PI / 2.0) 
      Vyy.F = -Sin(Ztheta + #PI / 2.0) 
      Line(512, 384, Vxx * 20.0, Vxy * 20.0, #Blue) 
      Line(512, 384, Vyx * 20.0, Vyy * 20.0, #Blue) 
      For i = 0 To 359 
        ; MaJ référentiel Vecteur x et Vecteur y 
        X.F = #PI * i / 180.0 
        
        Tx.F = Cos(X) * Cos(Ytheta) * 100.0 
        Ty.F = Sin(X) * 100.0 
      
        Ex.F = Vxx * Tx + Vxy * Ty 
        Ey.F = Vxy * Tx + Vyy * Ty 
        ;Trace vecteur E 
        Plot(512 + Ex, 384 + Ey, #Blue) 
        If Abs(X - Xtheta) < 0.01 
          Line(512, 384, Ex, Ey, #White) 
          Box(511 + Ex, 383 + Ey, 3, 3, #White) 
        EndIf 
        
      Next    
    Xtmp = Xtheta * 180 / #PI 
    Xtmp % 180 
    DrawText(0, 0, Str(Xtmp), #White, #Black) 
    Ytmp = Ytheta * 180 / #PI 
    Ytmp % 180 
    DrawText(0, 16, Str(Ytmp), #White, #Black) 
    ZTmp = (Ztheta * 180 / #PI) 
    Ztmp % 180 
    DrawText(0, 32, Str(Ztmp), #White, #Black) 
    DrawText(0, 48, "ARROW KEYS PageUp PageDown to change x, y, et z values") 
    StopDrawing() 
    FlipBuffers() 
    ExamineKeyboard() 
    If KeyboardPushed(#PB_Key_PageUp) 
      Ztheta + 0.04      
    EndIf 
    If KeyboardPushed(#PB_Key_PageDown) 
      Ztheta - 0.04 
    EndIf 
    If KeyboardPushed(#PB_Key_Up) 
      Xtheta + 0.04 
      If Xtheta > 2.0 * #PI 
        Xtheta - 2.0 * #PI 
      EndIf 
    EndIf 
    If KeyboardPushed(#PB_Key_Down) 
      Xtheta - 0.04 
      If Xtheta < 0.0 
        Xtheta + 2.0 * #PI 
      EndIf 
    EndIf 
    If KeyboardPushed(#PB_Key_Left) 
      Ytheta + 0.04 
    EndIf 
    If KeyboardPushed(#PB_Key_Right) 
      Ytheta - 0.04 
    EndIf 
  Until KeyboardPushed(#PB_Key_Escape)Thanks, Kaeru Gaman and Ollivier.
Your code is really nifty, Ollivier (I especially like the 3D view) but way beyond my means. I only need a simple 2d elliptical arc that can be rotated about it's ... Y? axis.
And I'm afraid I don't quite follow your example, Kaeru Gaman. I'm afraid I'm just not a mathematician =/
Would I be able to beg an algorithm or a link to an algorithm in any language that would allow me to draw an elliptical arc rotated an arbitrary amount?
Sorry for being greedy but I tried digging around with Google and came up short. Lines and rectangles are more my speed
			
			
									
									
						Your code is really nifty, Ollivier (I especially like the 3D view) but way beyond my means. I only need a simple 2d elliptical arc that can be rotated about it's ... Y? axis.
And I'm afraid I don't quite follow your example, Kaeru Gaman. I'm afraid I'm just not a mathematician =/
Would I be able to beg an algorithm or a link to an algorithm in any language that would allow me to draw an elliptical arc rotated an arbitrary amount?
Sorry for being greedy but I tried digging around with Google and came up short. Lines and rectangles are more my speed
- Kaeru Gaman
 - Addict

 - Posts: 4826
 - Joined: Sun Mar 19, 2006 1:57 pm
 - Location: Germany
 
my point was, when you can draw a horizontal ellipse, you can work the rotation out.
- you calculate an x/y for a point on the horizontal ellipse.
- from this x/y, you take the radius and angle, to interprete it as a point on a circle.
- you turn the angle of this radius along your desired rotation angle.
- you plot the point.
- repeat all these steps for each desired point of the ellipse.
you will get different radiuses each calculation.
the result will be a rotated ellipse.
this is just the theory behind it.
sorry, I'm too lazy to work it out as code right now.
and I think, understanding this basic concept will help you more than a complete routine.
			
			
									
									- you calculate an x/y for a point on the horizontal ellipse.
- from this x/y, you take the radius and angle, to interprete it as a point on a circle.
- you turn the angle of this radius along your desired rotation angle.
- you plot the point.
- repeat all these steps for each desired point of the ellipse.
you will get different radiuses each calculation.
the result will be a rotated ellipse.
this is just the theory behind it.
sorry, I'm too lazy to work it out as code right now.
and I think, understanding this basic concept will help you more than a complete routine.
oh... and have a nice day.
						Is this too simple?
Gruss
Helle
			
			
									
									
						Code: Select all
 Width  = 500
  Height = 300
  If OpenWindow(0, 0, 0, Width, Height+1, "Rotations-Ellipse", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    If StartDrawing(WindowOutput(0))
      i = 1
      x = Width/2
      y = Height/2
      
       For w = 0 To 360
         If w <= 90 Or w>=270
           col = 1234
          Else
           col = 123456
         EndIf 
          Ellipse(x, y, x*Cos(w*#PI/180), y, col+i)
          FillArea(0, 0, col+i, RGB(212, 208, 200))
         
          i = ~i
          Delay(10)
      
       Next
      StopDrawing()
    EndIf
    
    Repeat : Event = WaitWindowEvent() : Until  Event = #PB_Event_CloseWindow
  EndIf
Helle
Code: Select all
xCenter FLOAT (pixel)
yCenter FLOAT (pixel)
xRadius FLOAT (pixel)
yRadius FLOAT (pixel)
zRotation FLOAT (rad)
StartAngle FLOAT (rad)
FinishAngle FLOAT (rad)Code: Select all
Procedure EllipseWithRotation(xCenter.F, yCenter.F, xRadius.F, yRadius.F, zRotation.F, StartAngle.F, FinishAngle.F, Color.L)
    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
    NewList DrawX.POINT()
    Angle = StartAngle
    Repeat        
        X.F = Cos(Angle) * xRadius                           ; Draw an ellipse...
        Y.F = -Sin(Angle) * yRadius
        DisplayX.F = X * Cos(zRotation) - Y * Sin(zRotation) ; Rotation...
        DisplayY.F = X * Sin(zRotation) + Y * Cos(zRotation)        
        AddElement(DrawX() )                                 ; Record...
        DrawX()\X = xCenter + DisplayX
        DrawX()\Y = yCenter + DisplayY        
        Angle + AngleStep        
    Until Angle > FinishAngle
    ResetList(DrawX() )                                      ; Draw...
    For i = 1 To CountList(DrawX() ) - 1        
        SelectElement(DrawX(), i - 1)
        x1 = DrawX()\X
        y1 = DrawX()\Y
        SelectElement(DrawX(), i)
        x2 = DrawX()\X
        y2 = DrawX()\Y
        LineXY(x1, y1, x2, y2, Color)        
    Next
    ClearList(DrawX() )
EndProcedure- 
				dell_jockey
 - Enthusiast

 - Posts: 767
 - Joined: Sat Jan 24, 2004 6:56 pm
 
- 
				dell_jockey
 - Enthusiast

 - Posts: 767
 - Joined: Sat Jan 24, 2004 6:56 pm
 
Ollivier,
check out: http://en.wikipedia.org/wiki/Xiaolin_Wu ... _algorithm
Xiaolin Wu's algorithm is one of many anti-aliassing techniques.
bye
Hans
			
			
									
									
						check out: http://en.wikipedia.org/wiki/Xiaolin_Wu ... _algorithm
Xiaolin Wu's algorithm is one of many anti-aliassing techniques.
bye
Hans
