Posted: Sun Sep 02, 2007 9:05 am
Is there any reason you don't use the API function Arc_()?
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 ^_^
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
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
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 ^_^
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
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)