Page 2 of 3

Posted: Sun Sep 02, 2007 9:05 am
by Trond
Is there any reason you don't use the API function Arc_()?

Posted: Sun Sep 02, 2007 9:38 pm
by Xombie
@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!

Posted: Sun Sep 02, 2007 9:43 pm
by Trond
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 ^_^
Did you try RotateDC_()?

Posted: Tue Sep 04, 2007 1:14 am
by Xombie
I haven't heard of RotateDC_() and it doesn't seem to show up on MSDN.

Do you have links to any more information?

Thanks!

Posted: Tue Sep 04, 2007 4:51 pm
by Trond
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

Posted: Tue Sep 04, 2007 5:30 pm
by Ollivier
2Trond

Have you got an example of using RotateDC() ?

What is XFORM structure?

Posted: Tue Sep 04, 2007 6:32 pm
by Trond

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




Posted: Tue Sep 04, 2007 8:15 pm
by Ollivier
To run your code, I replaced the 2 lines

Code: Select all

    \eDx = x0 - Cos(Radians)*x0 + Sin(Radians)*y0 
    \eDy = y0 - Cos(Radians)*y0 - Sin(Radians)*x0 
 
with

Code: Select all

    \ex = x0 - Cos(Radians)*x0 + Sin(Radians)*y0 
    \ey = y0 - Cos(Radians)*y0 - Sin(Radians)*x0 
 
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?

Posted: Tue Sep 04, 2007 9:20 pm
by Trond
I also had ex and ey, but in the beta version of PB they are changed into eDx and eDy for some reason. It's possible to do things like shearing and scaling instead of rotation by setting the variables to different values, but how exactly I've got no idea.

Posted: Tue Sep 04, 2007 9:30 pm
by Ollivier
Okay it's settings for transformations...

Posted: Fri Sep 07, 2007 8:04 pm
by Xombie
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 ^_^

Posted: Sat Sep 08, 2007 10:38 am
by Trond
The x and y is the point you want to rotate around. Usually it makes sense to put this in the middle of the image, but in your case you could use the middle of the selection (or the middle of the arc, should be the same if I understood your correctly).

Posted: Sat Sep 08, 2007 1:38 pm
by dell_jockey
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 ^_^
what are you into, Xombie? CFD, FEA or something?

Posted: Wed Oct 03, 2007 2:35 pm
by #NULL
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.

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


Posted: Sat Jul 12, 2008 4:03 am
by zxtunes.com
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.

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)