Android Question Plotting like a geometric lathe.

Chris Salonikas

Member
Licensed User
Longtime User
Hi All, my first post (question) I hope I followed the guide properly.
I want to simulate a geometric lathe. I want the curve to show the plotting of DrawPoint (x, y, color) on the canvas as it is being calculated like in the old IBM-PC PSET (X, Y), also need to control the speed it plots, this way children can follow how the geometric function is being generated. The code below plots the final curve after the loop ends. Appreciate any suggestion on how to simulate this plotting with a controlled speed.

B4X:
Sub Button1_Click
    Private a As Double
    Private x, y,r,s,n As Int
    r = 275
    s = 125
    n = 10   
    For a = 0.1 To 20 * 3.141596 Step 0.001
        x = Round2((r) * Cos(a) + (s) * Cos(n * a) + 610, 0)
        y = Round2((r) * Sin(a) + (s) * Sin(n * a) + 710, 0)
        cvsActivity.DrawPoint(x, y, Colors.Yellow)
    Next
End Sub
 

Attachments

  • GeometricLathe.zip
    9.3 KB · Views: 186

Chris Salonikas

Member
Licensed User
Longtime User
Thank you all for the suggestions
Sleep() does slow down the loop but but only plots the coordinates only if you keep pressing the action button (Plot) and it does it very slowly even if you use Sleep(1).
Same problem if a Timer is used. I will experiment with B4XTurtle.
 
Upvote 0

roumei

Active Member
Licensed User
Please notice that you need to invalidate a canvas in order to redraw it. The behavior you described is caused by the missing invalidate call.
- Add a panel to your layout (Panel1)
- Initialize the canvas with Panel1 instead of the activity.
- Call Panel1.Invalidate when you're done with your drawings for this frame.
- Add a sleep() like agraham suggested.

B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    Private cvsActivity As Canvas
    Private Panel1 As Panel
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    cvsActivity.Initialize (Panel1)
End Sub

Sub Button1_Click
    Private a As Double
    Private x, y,r,s,n As Int
    r = 275
    s = 125
    n = 10   
    For a = 0 To 20 * 3.141596 Step 0.001
        x = Round2((r) * Cos(a) + (s) * Cos(n * a) + 610, 0)
        y = Round2((r) * Sin(a) + (s) * Sin(n * a) + 710, 0)
        cvsActivity.DrawPoint(x, y, Colors.Yellow)
        Panel1.Invalidate
        Sleep(20)
    Next
End Sub
 
Upvote 0

Chris Salonikas

Member
Licensed User
Longtime User
Thank you roumei, I should read the B4X Graphics guide more carefully.
It works as I need it to except it plots very slow and too long to complete even with Sleep(1).
If I reduce the Step in the for loop it becomes faint and granular. I only used a simple example here. For more complex geometric shapes it may be unbearably long.
for now I appreciate this quick solution until I get to know B4XTurtle and see if it can do it any faster.
 
Upvote 0

roumei

Active Member
Licensed User
You can increase the step if you draw lines instead of points. No need to draw every millisecond. A sleep(16) gives you 60fps.
B4X:
Sub Button1_Click
    Private a As Double
    Private x, y,r,s,n As Int
    Private lastx, lasty As Int
    r = 275
    s = 125
    n = 10   
    For a = 0 To 20 * 3.141596 Step 0.01
        x = Round2((r) * Cos(a) + (s) * Cos(n * a) + 610, 0)
        y = Round2((r) * Sin(a) + (s) * Sin(n * a) + 710, 0)
        If a = 0 Then
            lastx = x
            lasty = y   
        End If
        cvsActivity.DrawLine(lastx, lasty, x, y, Colors.Yellow, 2dip)
        Panel1.Invalidate
        Sleep(20)
        lastx = x
        lasty = y
    Next
End Sub
 
Upvote 0

Chris Salonikas

Member
Licensed User
Longtime User
You have made my day roumei, thank you. Now I can have some fun with other shapes.
For those following this post, one can get a variety of shapes by changing the values of r, s and n.
Try r=350, s=100 and n =20 Enjoy.
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
one can get a variety of shapes by changing the values of r, s and n.
Try r=350, s=100 and n =20 Enjoy.
If you like to experiment with different shapes, you can randomize the 3 variables:
B4X:
r=Rnd(275, 351)
    s=Rnd(100, 126)
    n=Rnd(10, 21)
You can also get a a not too slow plot even if you stay with points instead of lines. I would change this line:
B4X:
For a = 0 To 20 * 3.141596 Step 0.001
to this line:
B4X:
For a = 0 To 2 * cPI Step 0.002
you do not need to go with 0 to 20 *. If you use: 0 to 2 * it will be sufficient, because you were redrawing the same geometric shape 10 times instead of once. It would be interesting to see how Turtle lib does it. I never used it.
 
Upvote 0

Chris Salonikas

Member
Licensed User
Longtime User
Thank you Mahares, you are right, it is 2pi not 20. I was trying different values and forgot to change it back before posting.
This may explain the unusual very slow behavior when I stop and restart the app in debug mode with different values thinking it has finished.
Correct me if I am wrong in thinking that the plotting may be continuing in the background.
If anyone is interested I am getting these functions from a book I bought in 1985, "microcomputer art" by Ross Edwords. The book is full with variety of these functions and is available at amazon Microcomputer Art: Edwards, Ross: 9780135802182: Amazon.com: Books is only just over $900. Also available in the National Library of Australia.
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Correct me if I am wrong in thinking that the plotting may be continuing in the background.
If you place a line: Log("done") after the Next outside the loop, you will be able to tell when it is finished plotting. I have made a few changes to your code and Roumei's . It is the full project basically. You can modify it any way you want

B4X:
Sub Globals
    Private cvsActivity As Canvas
    Private Panel1 As Panel
    Private w, h As Int
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")  'has Panel1 and button1
    cvsActivity.Initialize (Panel1)
    w=Panel1.Width/2   'to bring the plot more inward
    h=Panel1.Height/2    'to bring the plot more inward
End Sub

Sub Button1_Click
    Dim Rect1 As Rect
    Rect1.Initialize(0, 0, 100%x, 100%y)
    cvsActivity.DrawRect(Rect1, Colors.black, True, 1dip)
    Panel1.Invalidate
    
    Private a As Double
    Private x, y,r,s,n As Int
    Private lastx, lasty As Int
    r=Rnd(275, 351)
    s=Rnd(100, 126)
    n=Rnd(10, 21)
    For a = 0 To 2 * cPI Step 0.01
        x = r * Cos(a) + s * Cos(n * a) + w
        y = r * Sin(a) + s * Sin(n * a) + h
        If a = 0 Then
            lastx = x
            lasty = y
        End If
        If a <= 3  Then
            cvsActivity.DrawLine(lastx, lasty, x, y, Colors.Yellow, 2dip)
        Else if a>3 And a < = 10 Then
            cvsActivity.DrawLine(lastx, lasty, x, y, Colors.Red, 2dip)
        Else
            cvsActivity.DrawLine(lastx, lasty, x, y, Colors.cyan, 2dip)
        End If
        Panel1.Invalidate
        Sleep(0)  'change to suit
        lastx = x
        lasty = y
    Next
    Log($"r: ${r},   s: ${s},   n: ${n},"$)
    Log("done")
End Sub
:
 

Attachments

  • lathe.png
    lathe.png
    18.2 KB · Views: 187
Upvote 0

Chris Salonikas

Member
Licensed User
Longtime User
Mahares, you must have read my mind with changing the color, thank you. It is 2am here and I am hoping for a power failure so I can go to bed.
Thank you and roumei once again and hope many other followers enjoy this.
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Thank you roumei, I should read the B4X Graphics guide more carefully.
It works as I need it to except it plots very slow and too long to complete even with Sleep(1).
If I reduce the Step in the for loop it becomes faint and granular. I only used a simple example here. For more complex geometric shapes it may be unbearably long.
for now I appreciate this quick solution until I get to know B4XTurtle and see if it can do it any faster.
Here it is by making use of Turtle

1611466943257.png


B4X:
#Region Project Attributes
    #MainFormWidth: 700
    #MainFormHeight: 700
#End Region

#Region Form Preperation
'Template version 1.00
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private xui As XUI 'ignore
    Private Turtle As B4XTurtle
    Private MenuBar1 As MenuBar
    Private w, h As Float
End Sub


Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Main")
    MainForm.Show
    
    w = Turtle.Width/2
    h = Turtle.Height/2
    
    
End Sub

Sub MenuBar1_Action
    Dim Mi As MenuItem = Sender
    Select Mi.Tag
        Case "Restart"
            Turtle.Stop.ClearScreen.Home
            Turtle_Start
        Case "Exit"
            MainForm.Close
    End Select
End Sub
#End Region

'B4XTurtle examples: https://www.b4x.com/android/forum/threads/examples-for-teachers-and-parents.116979
Sub Turtle_Start

    Turtle.SetPenSize(0.5)
    Turtle.SetPenColor(xui.Color_Black)
    Turtle.SetX(0)
    Turtle.SetY(h)
    Turtle.MoveTo(Turtle.Width, h)
    
    Turtle.SetX(w)
    Turtle.SetY(0)
    Turtle.MoveTo(w, Turtle.Height)
    
    
    Turtle.SetPenSize(1)
    Dim lastx As Float
    Dim lasty As Float
    Dim a As Double
    Dim x, y,r,s,n As Int
    lastx = w
    lasty = h
    r=Rnd(150, 175)
    s=Rnd(50, 100)
    n=Rnd(20, 40)

    For a = 0 To 2 * cPI Step 0.01
        x = r * Cos(a) + s * Cos(n * a) + w
        y = r * Sin(a) + s * Sin(n * a) + h
        If a = 0 Then
            Turtle.SetX(x)
            Turtle.SetY(y)
        End If
        If a = 0 Then
            lastx = x
            lasty = y
        End If
        If a <= 2 * cPI / 3  Then                              '0 to 1/3 of the way
            Turtle.SetPenColor(xui.Color_Yellow)
            Turtle.MoveTo(x, y)
        Else if a > 2 * cPI / 3 And a < = 2 * 2 * cPI / 3 Then '1/3 of the way to 2/3's of the way
            Turtle.SetPenColor(xui.Color_Red)
            Turtle.MoveTo(x, y)
        Else
            Turtle.SetPenColor(xui.Color_Cyan)                 '2/3's of the way up to the end
            Turtle.MoveTo(x, y)
        End If

        lastx = x
        lasty = y
    Next
    Log($"r: ${r},   s: ${s},   n: ${n},"$)
    Log("done")


End Sub
 

Attachments

  • TurtleFormula.zip
    3.8 KB · Views: 171
Last edited:
Upvote 0

Chris Salonikas

Member
Licensed User
Longtime User
Thank you Johan for the example, makes my learning B4XTurtle a lot easier.
Below is another interesting more complex formula. It can easily replace the above one with one additional variable.

Geometric Formula2:
'Example Formula 2
r = 320
s = 160
t = 120
n = -8
m = -26

For a = 0 To 2 * cPI + 0.01 Step 0.01
        x = Round2((r) * Cos(a) + (s) * Cos(n * a) + (t) * Cos(m * a)+ 720, 0)
        y = Round2((r) * Sin(a) + (s) * Sin(n * a) + (t) * Sin(m * a)+ 720, 0)
        If a = 0 Then
            lastx = x
            lasty = y
        End If
        cvsActivity.DrawLine(lastx, lasty, x, y, Colors.Yellow, 1dip)
        Panel2.Invalidate
        Sleep(10)
        lastx = x
        lasty = y
Next

Enjoy
 
Last edited:
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Thank you Johan for the example, makes my learning B4XTurtle a lot easier.
Below is another interesting for complex formula. It can easily replace the above one with one additional variable.

Enjoy

It looks like this with the values that I have set for r = 160, s = 80, t = 40, m = -26, n = -8

1611499625663.png


B4X:
Sub Turtle_Start

    Turtle.SetSpeedFactor(5)
    Turtle.SetPenSize(0.5)
    Turtle.SetPenColor(xui.Color_Black)
    Turtle.SetX(0)
    Turtle.SetY(h)
    Turtle.MoveTo(Turtle.Width, h)
    
    Turtle.SetX(w)
    Turtle.SetY(0)
    Turtle.MoveTo(w, Turtle.Height)
    

    Turtle.SetPenSize(1)
    Dim lastx As Float
    Dim lasty As Float
    Dim a As Double
'    Dim x, y,r,s,n As Int
    lastx = w
    lasty = h
'    r=150
'    s=75
'    n=30

    Dim x, y, r, s, t, m, n As Int
    r = 160
    s = 80
    t = 40
    n = -8
    m = -26

    For a = 0 To 2 * cPI Step 0.01
'        x = r * Cos(a) + s * Cos(n * a) + w
'        y = r * Sin(a) + s * Sin(n * a) + h
        x = Round2((r) * Cos(a) + (s) * Cos(n * a) + (t) * Cos(m * a)+ w, 0)
        y = Round2((r) * Sin(a) + (s) * Sin(n * a) + (t) * Sin(m * a)+ h, 0)
        If a = 0 Then
            lastx = x
            lasty = y
            Turtle.SetX(x)
            Turtle.SetY(y)
        End If
        If a <= 2 * cPI / 3  Then                              '0 to 1/3 of the way
            Turtle.SetPenColor(xui.Color_Green)
            Turtle.MoveTo(x, y)
        Else if a > 2 * cPI / 3 And a < = 2 * 2 * cPI / 3 Then '1/3 of the way to 2/3's of the way
            Turtle.SetPenColor(xui.Color_Red)
            Turtle.MoveTo(x, y)
        Else
            Turtle.SetPenColor(xui.Color_Blue)                 '2/3's of the way up to the end
            Turtle.MoveTo(x, y)
        End If

        lastx = x
        lasty = y
    Next
    
    a = 0
'    x = r * Cos(a) + s * Cos(n * a) + w
'    y = r * Sin(a) + s * Sin(n * a) + h
    x = Round2((r) * Cos(a) + (s) * Cos(n * a) + (t) * Cos(m * a)+ w, 0)
    y = Round2((r) * Sin(a) + (s) * Sin(n * a) + (t) * Sin(m * a)+ h, 0)
    Turtle.MoveTo(x, y)
    Turtle.SetTurtleVisible(False)
    
    Log($"r: ${r},   s: ${s},   n: ${n},"$)
    Log("done")


End Sub
 
Upvote 0

Chris Salonikas

Member
Licensed User
Longtime User
Thank you Johan. If you change the "m" and "n" variables you can get interesting illustrations.
I am not making a making any private app and all this is intended for fun and education.

Erel:
Would it be of any benefit if these examples are put in the education section?
With time more formulas and examples can be added for teachers and students to play with both ways of plotting (B4XTurtles and Basic).
Because of the many views, I assume there is an interest and hate to enjoy it by my self.
 
Upvote 0
Top