DrawingArea PAINT.ROTATE(RAD(x))

Ask about the individual Gambas components here.
Post Reply
User avatar
Askjerry
Posts: 50
Joined: Saturday 18th August 2018 9:06pm
Location: Kyle, Texas, USA
Contact:

DrawingArea PAINT.ROTATE(RAD(x))

Post by Askjerry » Wednesday 22nd June 2022 12:49am

I have become pretty good at making gauges for GAMBAS, I drop in an SVG image, then overlay it with a DRAWINGAREA and draw a gauge with .stroke and .fill which look great.

Code: Select all

Public Sub drawingarea1_Draw()
  Dim cx As Integer = DrawingArea1.W / 2  'Horizontal Center
  Dim cy As Integer = DrawingArea1.h / 2  'Vertical Center

  With Paint
    ' The drawing area is 200 x 200 pixels
    '-- Make Text --
    .Brush = Paint.Color(&H00000000)
    .Text("Drawing Area 1", cx, cy + 80, 000, 000, 3)
    .fill
 
    '-- Make Filled Area --
    .Brush = Paint.Color(&H006666ff)
    .MoveTo(CX, CY - 80)
    .LineTo(cx + 10, cy)
    .LineTo(cx, cy + 20)
    .LineTo(cx - 10, cy)
    .LineTo(cx, cy - 80)
    .fill
    
    ' -- Make Outline --
    .Brush = Paint.Color(&H00000000)
    .MoveTo(CX, CY - 80)
    .LineTo(cx + 10, cy)
    .LineTo(cx, cy + 20)
    .LineTo(cx - 10, cy)
    .LineTo(cx, cy - 80)
    .lineto(cx, cy + 20)
    .stroke  

    ' Finish the process
    .end
  End With
End
I see there is a ROTATE command that uses RADIANS... so the command it's self would be .ROTATE(RAD(A)) where "A" would be the angle in degrees.

The issue is... HOW do I use it???

My thinking is that you would define your "stuff" in the drawing area and rotate it... like this...

Code: Select all

Public Sub drawingarea1_Draw()
  Dim cx As Integer = DrawingArea1.W / 2  'Horizontal Center
  Dim cy As Integer = DrawingArea1.h / 2  'Vertical Center

    ' -- Make Outline --
    .Brush = Paint.Color(&H00000000)
    .MoveTo(CX, CY - 80)
    .LineTo(cx + 10, cy)
    .LineTo(cx, cy + 20)
    .LineTo(cx - 10, cy)
    .LineTo(cx, cy - 80)
    .lineto(cx, cy + 20)
    
    .Rotate(Rad(45))
    .stroke  
   
    ' Finish the process
    .end
  End With
End
But no... it doesn't work. And the documentation is underwhelming... really needs samples. Seriously.
Modifies the current transformation matrix (CTM) by rotating the user-space axes by angle radians. The rotation of the axes takes places after any existing transformation of user space. The rotation direction for positive angles is from the positive X axis toward the positive Y axis.

Angle : angle (in radians) by which the user-space axes will be rotated.
Can someone show me how to use this???

I mean for now, I'm using math that would be hard for my students to comprehend...

Code: Select all

'------------------------------------------------------------------------------------------
Public Sub Form_Open()

End

Public Sub DrawingArea1_Draw()
  Dim cx As Integer = DrawingArea1.W / 2  'Horizontal Center
  Dim cy As Integer = DrawingArea1.h / 2  'Vertical Center
  Dim ca As Integer = Slider1.Value       'Active Angle Movement
  Dim co As Integer = 0                   'Angular Offset -> Adjust starting point
  Dim x1 As Integer = 0                   'X Draw Point
  Dim y1 As Integer = 0                   'Y Draw Point
  With Paint
    ' The drawing area is 200 x 200 pixels
    '-- Make Text --
    .Brush = Paint.Color(&H00000000)
    .Text("Angle: " & ca, cx, cy + 80, 000, 000, 3)
    .fill
    
    ' -- Make Fill --
    .Brush = Paint.Color(&H0066FF66)
    x1 = Cos(Rad(ca - 90 - co)) * 80 + cx
    y1 = Sin(Rad(ca - 90 - co)) * 80 + cy
    .MoveTo(x1, y1)
    x1 = Cos(Rad(ca - 0 - co)) * 10 + cx
    y1 = Sin(Rad(ca - 0 - co)) * 10 + cy
    .LineTo(x1, y1)
    x1 = Cos(Rad(ca + 90 - co)) * 20 + cx
    y1 = Sin(Rad(ca + 90 - co)) * 20 + cy
    .LineTo(x1, y1)
    x1 = Cos(Rad(ca + 180 - co)) * 10 + cx
    y1 = Sin(Rad(ca + 180 - co)) * 10 + cy
    .LineTo(x1, y1)
    x1 = Cos(Rad(ca - 90 - co)) * 80 + cx
    y1 = Sin(Rad(ca - 90 - co)) * 80 + cy
    .LineTo(x1, y1)
    ' Center line - Not Required
    .fill 

    ' -- Make Outline --
    .Brush = Paint.Color(&H00000000)
    x1 = Cos(Rad(ca - 90 - co)) * 80 + cx
    y1 = Sin(Rad(ca - 90 - co)) * 80 + cy
    .MoveTo(x1, y1)
    x1 = Cos(Rad(ca - 0 - co)) * 10 + cx
    y1 = Sin(Rad(ca - 0 - co)) * 10 + cy
    .LineTo(x1, y1)
    x1 = Cos(Rad(ca + 90 - co)) * 20 + cx
    y1 = Sin(Rad(ca + 90 - co)) * 20 + cy
    .LineTo(x1, y1)
    x1 = Cos(Rad(ca + 180 - co)) * 10 + cx
    y1 = Sin(Rad(ca + 180 - co)) * 10 + cy
    .LineTo(x1, y1)
    x1 = Cos(Rad(ca - 90 - co)) * 80 + cx
    y1 = Sin(Rad(ca - 90 - co)) * 80 + cy
    .LineTo(x1, y1)
    x1 = Cos(Rad(ca + 90 - co)) * 20 + cx
    y1 = Sin(Rad(ca + 90 - co)) * 20 + cy
    .LineTo(x1, y1)
    .stroke  

    ' Finish the process
    .end
  End With
End

Public Sub Slider1_Change()
  drawingarea1.refresh
End
Just make a 200x200 drawingarea and add a slider set 0 to 360. But yeah... I'd love to use the ROTATE command. :|

User avatar
cogier
Site Admin
Posts: 883
Joined: Wednesday 21st September 2016 2:22pm
Location: Guernsey, Channel Islands

Re: DrawingArea PAINT.ROTATE(RAD(x))

Post by cogier » Thursday 23rd June 2022 3:35pm

I think what you want is below, but I worry when I know your maths is so much better than mine. Run this in a new graphical program: -
' Gambas class file

''USE gb.gui.qt for best results

DrawingArea1 As DrawingArea
Slider1 As Slider

Public Sub Form_Open()

  With Me
    .Height = 300
    .Width = 300
    .Padding = 5
    .Arrangement = Arrange.Vertical
    .Center
  End With

  With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
    .Cached = True
    .Expand = True
  End With

  With Slider1 = New Slider(Me) As "Slider1"
    .Height = 28
    .MaxValue = 630
  End With

  DrawingArea1.Refresh
  Wait 0.1

End

Public Sub Form_Arrange()

  Slider1.value = 314

End

Public Sub Slider1_Change()

  Dim cx As Integer = DrawingArea1.W / 2  'Horizontal Center
  Dim cy As Integer = DrawingArea1.h / 2  'Vertical Center

  DrawingArea1.Clear

  With Paint
    ' The drawing area is 200 x 200 pixels
    '-- Make Text --
    .Begin(DrawingArea1)
    .Translate(cx, cy)
    .Rotate(-Slider1.value / 100)                       ''Slider1 value from 0 to 630
    .Translate(-cx, -cy)
    .MoveTo(cx, cy)
    .Brush = Paint.Color(&H00000000)
    .Font.Bold = True
    .Font.Size = 20
    .Text("Drawing Area 1", cx, cy + 80, 0, 0, 3)

    '-- Make Filled Area --
    '.Brush = Paint.Color(&H006666ff)
    .Brush = Paint.Color(&H00FF0000)
    .MoveTo(CX, CY - 80)
    .LineTo(cx + 10, cy)
    .LineTo(cx, cy + 20)
    .LineTo(cx - 10, cy)
    .LineTo(cx, cy - 80)
    .fill

    ' -- Make Outline --
    .Brush = Paint.Color(&H00000000)
    .MoveTo(CX, CY - 80)
    .LineTo(cx + 10, cy)
    .LineTo(cx, cy + 20)
    .LineTo(cx - 10, cy)
    .LineTo(cx, cy - 80)
    .lineto(cx, cy + 20)
    .stroke
    .end

  End With

End

User avatar
Askjerry
Posts: 50
Joined: Saturday 18th August 2018 9:06pm
Location: Kyle, Texas, USA
Contact:

Re: DrawingArea PAINT.ROTATE(RAD(x))

Post by Askjerry » Saturday 25th June 2022 12:42am

I created a new file in QT, pasted in the code and attempted to run it...
NULL OBJECT in FMAIN 36
TEMP-ERROR.png
TEMP-ERROR.png (21.93 KiB) Viewed 49 times
Bummer. :( I do appreciate the effort... maybe I'm just missing something small. :roll:

It also appears as if your code is rotating the entire drawingarea... (I could be wrong) my method only alters the data for 5 points as it draws the shape... an order of magnitude less calculations.

Not sure why it failed, nor why you are creating the slider and drawing area within the program instead of placing and scaling on the form where you want them, setting all parameters, then just drawing the simple lines. I suppose I have much to learn.

My method does work... I was hoping for a more simple way of doing it... but it looks like my method and yours are equally complex.

Image

The results are pretty good however... once you overlay it on another graphic.

If you create a QT project, then set the form up with

drawingarea1 200x200 pixels
drawingarea2 200x200 pixels
slider1 0 to 360

Then paste in this code...

Code: Select all

' Gambas class file
'------------------------------------------------------------------------------------------
Public Sub Form_Open()


End

Public Sub drawingarea1_Draw()
  Dim cx As Integer = DrawingArea1.W / 2  'Horizontal Center
  Dim cy As Integer = DrawingArea1.h / 2  'Vertical Center
  Dim ca As Integer = 0                   'Angle Offset
  With Paint
    ' The drawing area is 200 x 200 pixels
    '-- Make Text --
    .Brush = Paint.Color(&H00000000)
    .Text("Drawing Area 1", cx, cy + 80, 000, 000, 3)
    .fill
 
    '-- Make Filled Area --
    .Brush = Paint.Color(&H006666ff)
    .MoveTo(CX, CY - 80)
    .LineTo(cx + 10, cy)
    .LineTo(cx, cy + 20)
    .LineTo(cx - 10, cy)
    .LineTo(cx, cy - 80)
    .fill
    
    ' -- Make Outline --
    .Brush = Paint.Color(&H00000000)
    .MoveTo(CX, CY - 80)
    .LineTo(cx + 10, cy)
    .LineTo(cx, cy + 20)
    .LineTo(cx - 10, cy)
    .LineTo(cx, cy - 80)
    .lineto(cx, cy + 20)
    .stroke  

    ' Finish the process
    .end
  End With
End

Public Sub DrawingArea2_Draw()
  Dim cx As Integer = DrawingArea2.W / 2  'Horizontal Center
  Dim cy As Integer = DrawingArea2.h / 2  'Vertical Center
  Dim ca As Integer = Slider1.Value       'Active Angle Movement
  Dim co As Integer = 0                   'Angular Offset -> Adjust starting point
  Dim x1 As Integer = 0                   'X Draw Point
  Dim y1 As Integer = 0                   'Y Draw Point
  With Paint
    ' The drawing area is 200 x 200 pixels
    '-- Make Text --
    .Brush = Paint.Color(&H00000000)
    .Text("Angle: " & ca, cx, cy + 80, 000, 000, 3)
    .fill
    
    ' -- Make Fill --
    .Brush = Paint.Color(&H0066FF66)
    x1 = Cos(Rad(ca - 90 - co)) * 80 + cx
    y1 = Sin(Rad(ca - 90 - co)) * 80 + cy
    .MoveTo(x1, y1)
    x1 = Cos(Rad(ca - 0 - co)) * 10 + cx
    y1 = Sin(Rad(ca - 0 - co)) * 10 + cy
    .LineTo(x1, y1)
    x1 = Cos(Rad(ca + 90 - co)) * 20 + cx
    y1 = Sin(Rad(ca + 90 - co)) * 20 + cy
    .LineTo(x1, y1)
    x1 = Cos(Rad(ca + 180 - co)) * 10 + cx
    y1 = Sin(Rad(ca + 180 - co)) * 10 + cy
    .LineTo(x1, y1)
    x1 = Cos(Rad(ca - 90 - co)) * 80 + cx
    y1 = Sin(Rad(ca - 90 - co)) * 80 + cy
    .LineTo(x1, y1)
    ' Center line - Not Required
    .fill 

    ' -- Make Outline --
    .Brush = Paint.Color(&H00000000)
    x1 = Cos(Rad(ca - 90 - co)) * 80 + cx
    y1 = Sin(Rad(ca - 90 - co)) * 80 + cy
    .MoveTo(x1, y1)
    x1 = Cos(Rad(ca - 0 - co)) * 10 + cx
    y1 = Sin(Rad(ca - 0 - co)) * 10 + cy
    .LineTo(x1, y1)
    x1 = Cos(Rad(ca + 90 - co)) * 20 + cx
    y1 = Sin(Rad(ca + 90 - co)) * 20 + cy
    .LineTo(x1, y1)
    x1 = Cos(Rad(ca + 180 - co)) * 10 + cx
    y1 = Sin(Rad(ca + 180 - co)) * 10 + cy
    .LineTo(x1, y1)
    x1 = Cos(Rad(ca - 90 - co)) * 80 + cx
    y1 = Sin(Rad(ca - 90 - co)) * 80 + cy
    .LineTo(x1, y1)
    x1 = Cos(Rad(ca + 90 - co)) * 20 + cx
    y1 = Sin(Rad(ca + 90 - co)) * 20 + cy
    .LineTo(x1, y1)
    .stroke  

    ' Finish the process
    .end
  End With
End

Public Sub Slider1_Change()
  drawingarea2.refresh
End
You can tinker with it.
Once set up there is only 1 other thing to update/change as needed...
Dim co As Integer = 0 'Angular Offset -> Adjust starting point

So if you wanted a range of 0 to 120 for example... you could offset by -60 and the pointer would be adjusted in rotation... like this...
Dim co As Integer = -60 'Angular Offset -> Adjust starting point

I'll be building on the graphics in my video series... eventually with a single large drawing area... and all the pointers and "stuff" laid out where needed. Or... I dunno... might leave them separate so I can tweak on them individually. Only time will tell. :D

Thanks,
Jerry

BruceSteers
Posts: 788
Joined: Thursday 23rd July 2020 5:20pm

Re: DrawingArea PAINT.ROTATE(RAD(x))

Post by BruceSteers » Saturday 25th June 2022 9:19am

I know nothing about that sort of math but after reading the situation i think it would be easier using Image.class instead of DrawingArea.

So create a new Image to overlay instead, use your routine to paint the needle, then simply use the image rotation features.

Also is your conversion from value to degree correct?
Here is how i convert a slider value into an angle and back again for a program i made that uses an image of a rotational knob as a slider...
Maybe the code will help?

Note. $iCircle is 360 by default and defines how big the circle is.

It's used like this...
  Dim fa As Float = ValueToAngle($iValue)
  If fa <> fAmount Then RotateImage(fa)
RotateImage() makes a copy of the image rotated and extracts the original size from center.

watch out for rotate shrinking the image. an image is square and if rotated and painted normally it will shrink so the corners still fit inside the square.
you can get over it by copying the image as i do in the RotateImage() method, make a copy of it rotated then extract the original area size (Me.W,Me.H) from the center point.

Public Sub ValueToAngle(Value As Integer) As Float

  Dim f As Float
  Dim p As Float = Value / If($iMaxValue > 1, $iMaxValue, Rad(360) * 10)

  f = (Rad($iCircle) * p)
  Return -f

End

Public Sub AngleToValue(Angle As Float) As Integer

  Dim f As Float = Angle / Rad($iCircle)
  Dim v As Integer = $iMinValue - ($iMaxValue * f)
  Return v

End

Public Sub RotateImage(Optional SetAmount As Float)

  If SetAmount Then fAmount = SetAmount

  Dim i As Image 
  i = If($iValue = $iMinValue, $pPicture.Image, $pPicture.Image.Rotate(fAmount))

  $iImage = i.Copy(((i.W - Me.W) / 2) + 1, ((i.H - Me.H) / 2) + 1, Me.W, Me.H)
  $hView.Refresh

End

Can post the whole ImageSpinner project if you wanna gander?

User avatar
cogier
Site Admin
Posts: 883
Joined: Wednesday 21st September 2016 2:22pm
Location: Guernsey, Channel Islands

Re: DrawingArea PAINT.ROTATE(RAD(x))

Post by cogier » Saturday 25th June 2022 2:46pm

I created a new file in QT, pasted in the code and attempted to run it...
NULL OBJECT in FMAIN 36
I have tried the code again and it works for me. See here.

It should still work without the Public Sub Form_Arrange() routine if that helps.

User avatar
Askjerry
Posts: 50
Joined: Saturday 18th August 2018 9:06pm
Location: Kyle, Texas, USA
Contact:

Re: DrawingArea PAINT.ROTATE(RAD(x))

Post by Askjerry » Saturday 25th June 2022 6:34pm

BruceSteers - I'll play with your code and do some experimenting.

Cogier - Not sure what went on... but as I thought... yours rotates the entire image.

With my method... I can have the overlay (drawingarea) do multiple pointers, text, and even "fluid levels" (working on that) all on ONE image if I like. I'm just going to need to use my current math and at least for now abandon the ROTATE command. So now I need to learn the rectangle and ellipse commands for my next steps.

And if I don't use your method (at least for this project) it does not mean that I don't appreciate your help!

I may use it in another project which has different graphic requirements.

Thank you,
Jerry :)

User avatar
cogier
Site Admin
Posts: 883
Joined: Wednesday 21st September 2016 2:22pm
Location: Guernsey, Channel Islands

Re: DrawingArea PAINT.ROTATE(RAD(x))

Post by cogier » Sunday 26th June 2022 2:27pm

Cogier - Not sure what went on... but as I thought... yours rotates the entire image.
A minor change to the program, and I think this is what you want:-

Video here
' Gambas class file

''USE gb.gui.qt for best results

DrawingArea1 As DrawingArea
Slider1 As Slider

Public Sub Form_Open()

  With Me
    .Height = 300
    .Width = 300
    .Padding = 5
    .Arrangement = Arrange.Vertical
    .Center
  End With

  With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
    .Cached = True
    .Expand = True
  End With

  With Slider1 = New Slider(Me) As "Slider1"
    .Height = 28
    .MaxValue = 630
  End With

  DrawingArea1.Refresh
  Wait 0.1

End

Public Sub Form_Arrange()

  Slider1.value = 1

End

Public Sub Slider1_Change()

  Dim cx As Integer = DrawingArea1.W / 2  'Horizontal Center
  Dim cy As Integer = DrawingArea1.h / 2  'Vertical Center

  DrawingArea1.Clear

  With Paint
    ' The drawing area is 200 x 200 pixels
    '-- Make Text --
    .Begin(DrawingArea1)
    .MoveTo(cx, cy)
    .Brush = Paint.Color(&H00000000)
    .Font.Bold = True
    .Font.Size = 18
    .Text("Drawing Area 1", cx, cy + 80, 0, 0, 3)
    .Fill
    .Stroke

    '-- Make Filled Area --
    '.Brush = Paint.Color(&H006666ff)
    .Translate(cx, cy)
    .Rotate(-Slider1.value / 100)                       ''Slider1 value from 0 to 630
    .Translate(-cx, -cy)
    .Brush = Paint.Color(&H00FF0000)
    .MoveTo(CX, CY - 80)
    .LineTo(cx + 10, cy)
    .LineTo(cx, cy + 20)
    .LineTo(cx - 10, cy)
    .LineTo(cx, cy - 80)
    .fill

    ' -- Make Outline --
    .Brush = Paint.Color(&H00000000)
    .MoveTo(CX, CY - 80)
    .LineTo(cx + 10, cy)
    .LineTo(cx, cy + 20)
    .LineTo(cx - 10, cy)
    .LineTo(cx, cy - 80)
    .lineto(cx, cy + 20)
    .stroke
    .end

  End With

End

Post Reply