DrawingArea PAINT.ROTATE(RAD(x))

Post

Posted
Rating:
#1 (In Topic #862)
Avatar
Regular
Askjerry is in the usergroup ‘Regular’
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

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

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

'------------------------------------------------------------------------------------------
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.  :|
Online now: No Back to the top

Post

Posted
Rating:
#2
Avatar
Guru
cogier is in the usergroup ‘Guru’
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: -

Code (gambas)

  1. ' Gambas class file
  2.  
  3. ''USE gb.gui.qt for best results
  4.  
  5. DrawingArea1 As DrawingArea
  6. Slider1 As Slider
  7.  
  8. Public Sub Form_Open()
  9.  
  10.   With Me
  11.     .Height = 300
  12.     .Width = 300
  13.     .Padding = 5
  14.     .Arrangement = Arrange.Vertical
  15.     .Center
  16.  
  17.   With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
  18.     .Cached = True
  19.     .Expand = True
  20.  
  21.   With Slider1 = New Slider(Me) As "Slider1"
  22.     .Height = 28
  23.     .MaxValue = 630
  24.  
  25.   DrawingArea1.Refresh
  26.   Wait 0.1
  27.  
  28.  
  29. Public Sub Form_Arrange()
  30.  
  31.   Slider1.value = 314
  32.  
  33.  
  34. Public Sub Slider1_Change()
  35.  
  36.   Dim cx As Integer = DrawingArea1.W / 2  'Horizontal Center
  37.   Dim cy As Integer = DrawingArea1.h / 2  'Vertical Center
  38.  
  39.   DrawingArea1.Clear
  40.  
  41.   With Paint
  42.     ' The drawing area is 200 x 200 pixels
  43.     '-- Make Text --
  44.     .Begin(DrawingArea1)
  45.     .Translate(cx, cy)
  46.     .Rotate(-Slider1.value / 100)                       ''Slider1 value from 0 to 630
  47.     .Translate(-cx, -cy)
  48.     .MoveTo(cx, cy)
  49.     .Brush = Paint.Color(&H00000000)
  50.     .Font.Bold = True
  51.     .Font.Size = 20
  52.     .Text("Drawing Area 1", cx, cy + 80, 0, 0, 3)
  53.  
  54.     '-- Make Filled Area --
  55.     '.Brush = Paint.Color(&H006666ff)
  56.     .Brush = Paint.Color(&H00FF0000)
  57.     .MoveTo(CX, CY - 80)
  58.     .LineTo(cx + 10, cy)
  59.     .LineTo(cx, cy + 20)
  60.     .LineTo(cx - 10, cy)
  61.     .LineTo(cx, cy - 80)
  62.     .fill
  63.  
  64.     ' -- Make Outline --
  65.     .Brush = Paint.Color(&H00000000)
  66.     .MoveTo(CX, CY - 80)
  67.     .LineTo(cx + 10, cy)
  68.     .LineTo(cx, cy + 20)
  69.     .LineTo(cx - 10, cy)
  70.     .LineTo(cx, cy - 80)
  71.     .lineto(cx, cy + 20)
  72.     .stroke
  73.     .end
  74.  
  75.  
  76.  
Online now: No Back to the top

Post

Posted
Rating:
#3
Avatar
Regular
Askjerry is in the usergroup ‘Regular’
I created a new file in QT, pasted in the code and attempted to run it…
<COLOR color="#BF0000">NULL OBJECT in FMAIN 36</COLOR>

Image

(Click to enlarge)


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.

<IMG src="https://forum.gambas.one/download/file.php?id=1067"> </IMG>

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

' 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
Online now: No Back to the top

Post

Posted
Rating:
#4
Guru
BruceSteers is in the usergroup ‘Guru’
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…

Code (gambas)

  1.   Dim fa As Float = ValueToAngle($iValue)
  2.   If fa <> fAmount Then RotateImage(fa)
  3.  

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.

Code (gambas)

  1.  
  2. Public Sub ValueToAngle(Value As Integer) As Float
  3.  
  4.   Dim f As Float
  5.   Dim p As Float = Value / If($iMaxValue > 1, $iMaxValue, Rad(360) * 10)
  6.  
  7.   f = (Rad($iCircle) * p)
  8.   Return -f
  9.  
  10.  
  11. Public Sub AngleToValue(Angle As Float) As Integer
  12.  
  13.   Dim f As Float = Angle / Rad($iCircle)
  14.   Dim v As Integer = $iMinValue - ($iMaxValue * f)
  15.   Return v
  16.  
  17.  
  18. Public Sub RotateImage(Optional SetAmount As Float)
  19.  
  20.   If SetAmount Then fAmount = SetAmount
  21.  
  22.   Dim i As Image
  23.   i = If($iValue = $iMinValue, $pPicture.Image, $pPicture.Image.Rotate(fAmount))
  24.  
  25.   $iImage = i.Copy(((i.W - Me.W) / 2) + 1, ((i.H - Me.H) / 2) + 1, Me.W, Me.H)
  26.   $hView.Refresh
  27.  
  28.  
  29.  

Can post the whole ImageSpinner project if you wanna gander?
Online now: No Back to the top

Post

Posted
Rating:
#5
Avatar
Guru
cogier is in the usergroup ‘Guru’
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.
Online now: No Back to the top

Post

Posted
Rating:
#6
Avatar
Regular
Askjerry is in the usergroup ‘Regular’
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  :)
Online now: No Back to the top

Post

Posted
Rating:
#7
Avatar
Guru
cogier is in the usergroup ‘Guru’
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

Code (gambas)

  1. ' Gambas class file
  2.  
  3. ''USE gb.gui.qt for best results
  4.  
  5. DrawingArea1 As DrawingArea
  6. Slider1 As Slider
  7.  
  8. Public Sub Form_Open()
  9.  
  10.   With Me
  11.     .Height = 300
  12.     .Width = 300
  13.     .Padding = 5
  14.     .Arrangement = Arrange.Vertical
  15.     .Center
  16.  
  17.   With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
  18.     .Cached = True
  19.     .Expand = True
  20.  
  21.   With Slider1 = New Slider(Me) As "Slider1"
  22.     .Height = 28
  23.     .MaxValue = 630
  24.  
  25.   DrawingArea1.Refresh
  26.   Wait 0.1
  27.  
  28.  
  29. Public Sub Form_Arrange()
  30.  
  31.   Slider1.value = 1
  32.  
  33.  
  34. Public Sub Slider1_Change()
  35.  
  36.   Dim cx As Integer = DrawingArea1.W / 2  'Horizontal Center
  37.   Dim cy As Integer = DrawingArea1.h / 2  'Vertical Center
  38.  
  39.   DrawingArea1.Clear
  40.  
  41.   With Paint
  42.     ' The drawing area is 200 x 200 pixels
  43.     '-- Make Text --
  44.     .Begin(DrawingArea1)
  45.     .MoveTo(cx, cy)
  46.     .Brush = Paint.Color(&H00000000)
  47.     .Font.Bold = True
  48.     .Font.Size = 18
  49.     .Text("Drawing Area 1", cx, cy + 80, 0, 0, 3)
  50.     .Fill
  51.     .Stroke
  52.  
  53.     '-- Make Filled Area --
  54.     '.Brush = Paint.Color(&H006666ff)
  55.     .Translate(cx, cy)
  56.     .Rotate(-Slider1.value / 100)                       ''Slider1 value from 0 to 630
  57.     .Translate(-cx, -cy)
  58.     .Brush = Paint.Color(&H00FF0000)
  59.     .MoveTo(CX, CY - 80)
  60.     .LineTo(cx + 10, cy)
  61.     .LineTo(cx, cy + 20)
  62.     .LineTo(cx - 10, cy)
  63.     .LineTo(cx, cy - 80)
  64.     .fill
  65.  
  66.     ' -- Make Outline --
  67.     .Brush = Paint.Color(&H00000000)
  68.     .MoveTo(CX, CY - 80)
  69.     .LineTo(cx + 10, cy)
  70.     .LineTo(cx, cy + 20)
  71.     .LineTo(cx - 10, cy)
  72.     .LineTo(cx, cy - 80)
  73.     .lineto(cx, cy + 20)
  74.     .stroke
  75.     .end
  76.  
  77.  
  78.  
Online now: No Back to the top

Post

Posted
Rating:
#8
Avatar
Regular
Askjerry is in the usergroup ‘Regular’
I'm trying to revisit this and try it out… but I'm getting an error n line 62.

<COLOR color="#BF0000">Ambiguous Expression. Please use brackets in FMain.class : 62</COLOR>

I think this is close… certainly less than all the math I was using to locate every graphics point.

I also just started another thread because I think there is a way to define a shape or polygon… then just tell it, put it here and at this angle.

Thanks for your help.
Jerry
Online now: No Back to the top

Post

Posted
Rating:
#9
Avatar
Regular
Askjerry is in the usergroup ‘Regular’
I've got it now… just took getting my head around it.

Code

' Gambas class file

Public Sub DRW_1_Draw()
Dim x, y As Integer
' DEFINE CENTER OF ROTATION
x = DRW_1.Width / 2
y = DRW_1.Height / 2

  With Paint
    ' SET CENTER POINT
    .Translate(x, y)
    ' ROTATE THE WHOLE DRAWING ENVIONMENT
    .rotate(Rad(Slider3.value))
    ' Draw Filled Pointer with pivot point at (0,0)
    .brush = Paint.Color(&hffff00)
    .MoveTo(0, -80)
    .LineTo(-20, 0)
    .LineTo(0, 20)
    .LineTo(20, 0)
    .LineTo(0, -80)
    .fill
    ' Draw Outlined Pointer with pivot point at (0,0)
    .brush = Paint.Color(&h0000FF)
    .MoveTo(0, -80)
    .LineTo(-20, 0)
    .LineTo(0, 20)
    .LineTo(20, 0)
    .LineTo(0, -80)
    .stroke
    ' Finish Drawing
    .End
  End With
End

' SLIDER SET to -360 to +360 for data to test rotation
Public Sub Slider3_Change()
TextLabel3.Text = Format(Slider3.Value, "000") & " DEG"
DRW_1.Refresh
End

' SLIDER REST TO ZERO BUTTON
Public Sub Button1_Click()
  Slider3.Value = 0
End

'EXIT THE PROGRAM BUTTON
Public Sub BTN_EXIT_Click()
  FMain.Close
End

I had BORDER ON - PLAIN for the drawing area… I noticed that the whole square was rotating inside the "window" where I had originally placed the DrawingArea…

It wasn't until I saw your TRANSLATE(x,y) function that I figured it out… draw the thing around the (0,0) point… then shift and rotate it where you want it.

Thanks for the help!!!!!!!!!!!!!

Jerry

<COLOR color="#0040FF">UPDATE: </COLOR>I have a newer version that is just beautiful… I am attaching the file for your enjoyment.

Attachment

GAMBAS Sample Gauge Fully Documented.


This gauge is made in layers…
<LIST>
  • <LI>On the bottom - Gauge Image - A very detailed colorful gauge.</LI>
</LIST>
<LIST>
  • <LI>Next up is a transparent drawing area to hold the pointer which is redrawn each time.</LI>
</LIST>
<LIST>
  • <LI>Over that is a lable to hold the display text which shows the speed in kp/h fully formatted.</LI>
</LIST>
<LIST>
  • <LI>At the top of the stack is a transparent PNG which contains the pointer cover, a gradient circle. It can also contain a lens flare if you like.</LI>
</LIST>
Online now: No Back to the top
1 guest and 0 members have just viewed this.