Drawing Arcs

Everything else that doesn't fall into one of the other PB categories.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Is there any reason you don't use the API function Arc_()?
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Post 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!
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post 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_()?
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Post 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!
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post 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
Ollivier
Enthusiast
Enthusiast
Posts: 281
Joined: Mon Jul 23, 2007 8:30 pm
Location: FR

Post by Ollivier »

2Trond

Have you got an example of using RotateDC() ?

What is XFORM structure?
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post 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



Ollivier
Enthusiast
Enthusiast
Posts: 281
Joined: Mon Jul 23, 2007 8:30 pm
Location: FR

Post 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?
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post 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.
Ollivier
Enthusiast
Enthusiast
Posts: 281
Joined: Mon Jul 23, 2007 8:30 pm
Location: FR

Post by Ollivier »

Okay it's settings for transformations...
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Post 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 ^_^
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

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

Post 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?
cheers,
dell_jockey
________
http://blog.forex-trading-ideas.com
#NULL
Addict
Addict
Posts: 1497
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Post 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

User avatar
zxtunes.com
Enthusiast
Enthusiast
Posts: 375
Joined: Wed Apr 23, 2008 7:51 am
Location: Saint-Petersburg, Russia
Contact:

Post 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)
Post Reply