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)
EndProcedure
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
\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 ^_^
-
- 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)