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
-
- Enthusiast
- Posts: 767
- Joined: Sat Jan 24, 2004 6:56 pm
-
- 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