Option Explicit On
Imports System.Linq
Imports System.Collections.Generic
Namespace Vb3DDefine
   Public Class Form1 : Inherits System.Windows.Forms.Form
      Private Dim _disposed As Boolean = False
      <System.Diagnostics.DebuggerNonUserCode()> _
      Public Sub New()
         MyBase.New()
         'This call is required by the Windows Form Designer.
         InitializeComponent()
         'Add any initialization after the InitializeComponent() call
         If (DesignMode) Then Exit Sub
         cmdControls = New System.Collections.Generic.SortedList(Of Integer, System.Windows.Forms.Button)
         cmdControls.Add(1, _cmdControls_1)
         cmdControls.Add(8, _cmdControls_8)
         cmdControls.Add(6, _cmdControls_6)
         cmdControls.Add(10, _cmdControls_10)
         cmdControls.Add(4, _cmdControls_4)
         cmdControls.Add(7, _cmdControls_7)
         cmdControls.Add(2, _cmdControls_2)
         cmdControls.Add(5, _cmdControls_5)
         cmdControls.Add(9, _cmdControls_9)
         cmdControls.Add(3, _cmdControls_3)
         mnuChangeRisolution = New System.Collections.Generic.SortedList(Of Integer, System.Windows.Forms.ToolStripMenuItem)
         mnuChangeRisolution.Add(1, _mnuChangeRisolution_1)
         mnuChangeRisolution.Add(2, _mnuChangeRisolution_2)
         mnuSetPoint = New System.Collections.Generic.SortedList(Of Integer, System.Windows.Forms.ToolStripMenuItem)
         mnuSetPoint.Add(1, _mnuSetPoint_1)
         mnuSetPoint.Add(2, _mnuSetPoint_2)
         mnuChangeView = New System.Collections.Generic.SortedList(Of Integer, System.Windows.Forms.ToolStripMenuItem)
         mnuChangeView.Add(1, _mnuChangeView_1)
         mnuChangeView.Add(2, _mnuChangeView_2)
         mnuChangeView.Add(3, _mnuChangeView_3)
         mnuDrawPlane = New System.Collections.Generic.SortedList(Of Integer, System.Windows.Forms.ToolStripMenuItem)
         mnuDrawPlane.Add(1, _mnuDrawPlane_1)
         mnuDrawPlane.Add(2, _mnuDrawPlane_2)
         mnuDrawPlane.Add(3, _mnuDrawPlane_3)
         Form_Load(Nothing, Nothing)
         Form_Resize(Nothing, Nothing)

      End Sub
      'Form overrides dispose to clean up the component list.
      <System.Diagnostics.DebuggerNonUserCode()> _
      Protected Overloads Overrides Sub Dispose(ByVal Disposing As Boolean)
         If _disposed Then
            Return
         End If
         If Disposing Then
            If Not components Is Nothing Then
               components.Dispose()
            End If
         End If
         _disposed = True
         MyBase.Dispose(Disposing)
      End Sub
      Dim dx As Double = 0.0
      Dim dy As Double = 0.0
      Dim lx As Double = 0.0
      Dim j As Double = 0.0
      Dim rs As Double = 0.0
      Dim rsbase As Integer = 0
      Dim p As Double = 0.0
      Dim xmx As Double = 0.0
      Dim ymx As Double = 0.0
      Dim xc As Double = 0.0
      Dim yc As Double = 0.0
      Dim y As Double = 0.0
      Dim xj As Double = 0.0
      Dim yj As Double = 0.0
      Dim zj As Double = 0.0
      Dim xx As Double = 0.0
      Dim yy As Double = 0.0
      Dim zz As Single = 0.0F
      Dim xpj As Double = 0.0
      Dim ypj As Double = 0.0
      Dim xp1j As Double = 0.0
      Dim yp1j As Double = 0.0
      Dim a As Double = 0.0
      Dim b As Double = 0.0
      Dim cosa As Double = 0.0
      Dim sina As Double = 0.0
      Dim cosp As Double = 0.0
      Dim sinp As Double = 0.0
      Dim x As Double = 0.0
      Dim z As Double = 0.0
      Dim zl As Double = 0.0
      Dim xp As Double = 0.0
      Dim xpl As Double = 0.0
      Dim yp As Double = 0.0
      Dim ypl As Double = 0.0
      Dim xl As Double = 0.0
      Dim yl As Double = 0.0
      Dim xlx As Double = 0.0
      Dim yly As Double = 0.0
      Dim xl1 As Double = 0.0
      Dim yl1 As Double = 0.0
      Dim xlx1 As Double = 0.0
      Dim yly1 As Double = 0.0
      Dim ycosa As Double = 0.0
      Dim ysina As Double = 0.0
      Dim ycosp As Double = 0.0
      Dim ysinp As Double = 0.0
      Dim xp1 As Double = 0.0
      Dim yp1 As Double = 0.0
      'math constants
      Private Const e As Double = 2.718281828
      Private Const pg As Double = 3.14159265358979
      '******************************************************************************
      '*     Name: 3Ddefine (compiled on Visual Basic 6)                           *
      '*  Version: 1.0 (4 June 2002)                                                *
      '*  Project: 3Ddefine.vbp (Visual Basic Project)                             *
      '*           3Ddefine.frm (Visual Basic Form)                                *
      '*           3ddefline.exe (Exe file)                                         *
      '*  Purpose: This program allow you to study the 3D functions of the          *
      '*           type z = f(x,y); the draw can be rotated and moved.              *
      '*           You can also draw some section plans, increase the drawing       *
      '*           precision and expand or decrease the function area.              *
      '*     Type: Freeware (if you use this code or part of this, please           *
      '*           mention the author: this is the only restriction)                *
      '*   Author: Picinotti Duccio (Duke)                                          *
      '*           Loc.Poggio di Sopra, 23 Subbiano (AR) Italy                      *
      '*           If you want some explanation of this code please contact me at:  *
      '*   E-mail: picinotti.duccio@tin.it                                          *
      '* Homepage: http://www.catenaia.cjb.net                                      *
      '******************************************************************************
      Public func As String = ""
      Public Sub AddFunction()
         'add function defined in the TextBox to the VBcode with the MS ScriptControl
         Dim strFunction As String = ""
         strFunction = "Function f(x, y)" & Environment.NewLine & "  f = " & txtFunction.Text & Environment.NewLine & "End Function"
         ScriptControl.ExecuteCommand(strFunction)

      End Sub
      Private Sub Axis()
         'cancel the Form
         gmRTL.GUI.ControlHelper.FormCls(Me)
         gmRTL.GUI.ControlHelper.ScaleForm(Me)
         Me.ForeColor = System.Drawing.Color.FromArgb(255,255,255)
         'print in the upperleft corner the angles from the axis
         gmRTL.GUI.ControlHelper.SetCurrentX(Me,0)
         gmRTL.GUI.ControlHelper.SetCurrentY(Me,0)
         gmRTL.GUI.ControlHelper.PicturePrint(Me,"a=",Conversion.Int(a * 180 / pg),"°")
         gmRTL.GUI.ControlHelper.PicturePrint(Me,"b=",Conversion.Int(180 - b * 180 / pg),"°")

         'draw the 3D Axis in the Form
         'ymx = scale the height of the Form
         ymx = 3! / 4! * xmx
         '(xc,yc) = center of the form
         xc = xmx / 2! + dx
         yc = ymx / 2! + dy
         'scale the form from (xmx,ymx)=upperleft corner to (0,0)=downright corner
         gmRTL.GUI.ControlHelper.Scale(Me,xmx,ymx,0.0,0.0)
         'define some value used forward
         cosa = Math.Cos(a)
         sina = Math.Sin(a)
         cosp = Math.Cos(b - a)
         sinp = Math.Sin(b - a)
         'draw the 3D-axis
         gmRTL.GUI.ControlHelper.Line(Me,xc,yc,xc,ymx,QBColor(12))
         gmRTL.GUI.ControlHelper.Line(Me,xc,yc,xc - xmx * cosa,yc - xmx * sina,QBColor(12))
         gmRTL.GUI.ControlHelper.Line(Me,xc,yc,xc + xmx * cosp,yc - xmx * sinp,QBColor(12))
         'set the color of the axis label
         Me.ForeColor = System.Drawing.ColorTranslator.FromOle(QBColor(15))
         'print the axis label near the axis
         For j = CDbl(1) To ymx Step 1
            gmRTL.GUI.ControlHelper.PSet(Me,xc - j * cosa,yc - j * sina,System.Drawing.ColorTranslator.FromOle(QBColor(9)))
            gmRTL.GUI.ControlHelper.PicturePrint(Me,j)
            gmRTL.GUI.ControlHelper.PSet(Me,xc + j * cosp,yc - j * sinp,System.Drawing.ColorTranslator.FromOle(QBColor(9)))
            gmRTL.GUI.ControlHelper.PicturePrint(Me,j)
            gmRTL.GUI.ControlHelper.PSet(Me,xc,yc + j,System.Drawing.ColorTranslator.FromOle(QBColor(9)))
            gmRTL.GUI.ControlHelper.PicturePrint(Me,j)
         Next
         DrawFunction()
      End Sub
      Private Sub DrawFunction()
         'draw the function in the Form
         On Error Goto Errore
         Dim x As Double = 0.0
         Dim y As Double = 0.0
         'p = precision, distance from two lines
         p = lx / rs
         'draw the iso-level lines: it draws line from the previous point to the
         'point evaluated at the moment
         'it use ScriptControl.Run for evaluate the function added before
         For y = -lx To lx Step 0.5!
            ycosp = xc + y * cosp
            ycosa = xc - y * cosa
            ysinp = yc - y * sinp
            ysina = yc - y * sina
            For x = -lx To lx Step p
               xp = -x * cosa + ycosp
               xp1 = -(x + p) * cosa + ycosp
               yp = CDbl(-x * sina + ysinp + (ScriptControl.Evaluate(String.Format("f({0}, {1})",x,y))))
               yp1 = CDbl(-(x + p) * sina + ysinp + (ScriptControl.Evaluate(String.Format("f({0}, {1})",x + p,y))))
               xl = ycosa + x * cosp
               xl1 = ycosa + (x + p) * cosp
               yl = CDbl(ysina - x * sinp + (ScriptControl.Evaluate(String.Format("f({0}, {1})",y,x))))
               yl1 = CDbl(ysina - (x + p) * sinp + (ScriptControl.Evaluate(String.Format("f({0}, {1})",y,x + p))))
               'draw line from the previous point to the point evaluated now
               gmRTL.GUI.ControlHelper.Line(Me,xp,yp,xp1,yp1,QBColor(10))
               gmRTL.GUI.ControlHelper.Line(Me,xl,yl,xl1,yl1,QBColor(10))
            Next
         Next
         Exit Sub
      Errore:
         'if there is an error evaluating the function (as a division by 0)...
         Resume Next
      End Sub
      Private Sub mnuInterval_Click(ByVal sender As Object, ByVal e As EventArgs)
         'increase or decrease the drawing interval
         lx = CDbl(Interaction.InputBox("lx < (x,y) < lx","Drawing interval","1",200,67))
         Axis()
      End Sub
      Private Sub cmdControls_Click(ByVal sender As Object, ByVal e As EventArgs)
         Dim cmdControls As System.Windows.Forms.Button
         cmdControls = CType(sender,System.Windows.Forms.Button)
         Dim Index As Integer = Me.cmdControls.Keys(Me.cmdControls.IndexOfValue(cmdControls))
         'control the drawing view
         Select Case Index
            Case 1
               'move to the Left
               dx = dx - xmx / 8
            Case 2
               'move to the Right
               dx = dx + xmx / 8
            Case 3
               'move up
               dy = dy - xmx / 8
            Case 4
               'move down
               dy = dy + xmx / 8
            Case 5
               'expand the angle between the X-axis an Y-axis
               b = b - pg / 12
            Case 6
               'tight the angle between the X-axis an Y-axis
               b = b + pg / 12
            Case 7
               'rotate to the Left
               a = a - pg / 12
            Case 8
               'rotate to the Right
               a = a + pg / 12
            Case 9
               'zoom In
               xmx = xmx / 1.5
            Case 10
               'zoom Out
               xmx = xmx * 1.5
         End Select
         'restore normal resolution
         rs = rsbase
         'draw Axis
         Axis()
      End Sub
      Private Sub Form_Load(ByVal sender As Object, ByVal e As EventArgs)
         gmRTL.GUI.ControlHelper.SetAutoRedraw(Me,True)
         'initialize variables
         'xmx = scale the Width of the Form
         xmx = 16
         'a = angle (in degrees) from the Horizontal line to the X-axis
         a = 30
         'angle in radiants
         a = a * pg / 180
         'b = 180° - [angle (in degrees) from the X-axis to the Y-axis]
         b = 60
         'angle in radiants
         b = b * pg / 180
         'lx = interval of the drawing
         lx = 4
         'rs = resolution of drawing
         rs = 100
         'rsbase = normal resolution of drawing
         rsbase = 20
         'write the function specificated in the TextBox with MS ScriptControl
         AddFunction()
      End Sub
      Private Sub Form_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
         Dim Button As Integer
         Button = e.Button \ &H100000
         'show the Popup menů when the right mouse button is clicked
         If (Button = 2) Then
            gmRTL.GUI.ControlHelper.PopupMenu(mnuGeneral,Me)
         End If
      End Sub
      Private Sub Form_Resize(ByVal sender As Object, ByVal e As EventArgs)
         'located the controls in the Form
         Dim i As Integer = 0
         'rescale the form to the initial value to locate controls
         gmRTL.GUI.ControlHelper.ScaleForm(Me)
         'center all controls in the Form
         lblFunction.Left = (Me.ClientRectangle.Width - (txtFunction.Width + lblFunction.Width)) / 2
         txtFunction.Left = lblFunction.Left + lblFunction.Width
         _cmdControls_4.Left = (Me.ClientRectangle.Width - _cmdControls_4.Width) / 2
         _cmdControls_3.Left = _cmdControls_4.Left
         _cmdControls_7.Left = _cmdControls_4.Left - _cmdControls_7.Width
         _cmdControls_1.Left = _cmdControls_7.Left
         _cmdControls_8.Left = _cmdControls_4.Left + _cmdControls_4.Width
         _cmdControls_2.Left = _cmdControls_8.Left
         _cmdControls_9.Left = _cmdControls_7.Left - _cmdControls_9.Width
         _cmdControls_5.Left = _cmdControls_9.Left
         _cmdControls_10.Left = _cmdControls_8.Left + _cmdControls_8.Width
         _cmdControls_6.Left = _cmdControls_10.Left
         'locate all controls to the down of the Form
         _cmdControls_4.Top = Me.ClientRectangle.Height - _cmdControls_4.Height
         _cmdControls_3.Top = _cmdControls_4.Top - _cmdControls_3.Height
         For i = 1 To 10 Step 1
            Select Case i
               Case 7,8,9,10
                  cmdControls(i).Top = Me.ClientRectangle.Height - _cmdControls_9.Height
               Case 1,2,5,6
                  cmdControls(i).Top = Me.ClientRectangle.Height - 2.0! * _cmdControls_9.Height
            End Select
         Next
         'draw Axis
         Axis()
      End Sub
      Private Sub mnuChangeRisolution_Click(ByVal sender As Object, ByVal e As EventArgs)
         Dim mnuChangeRisolution As System.Windows.Forms.ToolStripMenuItem
         mnuChangeRisolution = CType(sender,System.Windows.Forms.ToolStripMenuItem)
         Dim Index As Integer = Me.mnuChangeRisolution.Keys(Me.mnuChangeRisolution.IndexOfValue(mnuChangeRisolution))
         'increase or decrease drawing resolution
         If (Index = 1) Then
            'increase the resolution if it isn't so big (rs=500)
            If (rs < 500) Then
               rs = rs * 2
            End If
         Else
            'decrease the resolution if it isn't so small (rs=10)
            If (rs > 10) Then
               rs = rs / 2
            End If
         End If
         Axis()
      End Sub
      Private Sub mnuDrawPlane_Click(ByVal sender As Object, ByVal e As EventArgs)
         Dim mnuDrawPlane As System.Windows.Forms.ToolStripMenuItem
         mnuDrawPlane = CType(sender,System.Windows.Forms.ToolStripMenuItem)
         Dim Index As Integer = Me.mnuDrawPlane.Keys(Me.mnuDrawPlane.IndexOfValue(mnuDrawPlane))
         'draw some reference planes
         Select Case Index
            Case 1
               'draw a XY plane
               zz = CSng(Interaction.InputBox("Z=","Plane XY","0",200,133))
               For y = -lx To lx Step 0.5
                  xl = xc + y * cosp + lx * cosa
                  xl1 = xl - 2 * lx * cosa
                  xlx = xc - y * cosa - lx * cosp
                  xlx1 = xlx + 2 * lx * cosp
                  yl = yc - y * sinp + zz + lx * sina
                  yl1 = yl - 2 * lx * sina
                  yly = yc - y * sina + zz + lx * sinp
                  yly1 = yly - 2 * lx * sinp
                  gmRTL.GUI.ControlHelper.Line(Me,xl,yl,xl1,yl1,QBColor(13))
                  gmRTL.GUI.ControlHelper.Line(Me,xlx,yly,xlx1,yly1,QBColor(13))
               Next
            Case 2
               'draw a ZX plane
               yy = CDbl(Interaction.InputBox("Y=","Plane ZX","0",200,133))
               For j = lx To -lx Step -0.5
                  xl = xc - yy * cosa + j * cosp
                  yl = yc - yy * sina - j * sinp + lx
                  yl1 = yl - 2 * lx
                  gmRTL.GUI.ControlHelper.Line(Me,xl,yl,xl,yl1,QBColor(13))
               Next
            Case 3
               'draw a ZY plane
               xx = CDbl(Interaction.InputBox("X=","Plane ZY","0",200,133))
               xl = xc - lx * cosa + xx * cosp
               xl1 = xl + 2 * lx * cosa
               For z = lx To -lx Step -0.5
                  yl = yc - lx * sina - xx * sinp + z
                  yl1 = yl + 2 * lx * sina
                  gmRTL.GUI.ControlHelper.Line(Me,xl,yl,xl1,yl1,QBColor(13))
               Next
               For y = lx To -lx Step -0.5
                  xl = xc - y * cosa + xx * cosp
                  xl1 = xl
                  yl = yc - y * sina + xx * sinp + lx
                  yl1 = yl - 2 * lx
                  gmRTL.GUI.ControlHelper.Line(Me,xl,yl,xl1,yl1,QBColor(13))
               Next
         End Select
      End Sub
      Private Sub mnuSetPoint_Click(ByVal sender As Object, ByVal e As EventArgs)
         Dim mnuSetPoint As System.Windows.Forms.ToolStripMenuItem
         mnuSetPoint = CType(sender,System.Windows.Forms.ToolStripMenuItem)
         Dim Index As Integer = Me.mnuSetPoint.Keys(Me.mnuSetPoint.IndexOfValue(mnuSetPoint))
         'draw or evaluate a point of the function
         On Error Goto Errors
         If (Index = 1) Then
            'draw a point in the Form
            xj = CDbl(Interaction.InputBox("X=","Draw point","0",200,67))
            yj = CDbl(Interaction.InputBox("Y=","Draw point","0",200,67))
            zj = CDbl(Interaction.InputBox("Z=","Draw point","0",200,67))
            xpj = xc - yj * cosa
            xp1j = xpj + xj * cosp
            ypj = yc - yj * sina
            yp1j = ypj - xj * sinp
            gmRTL.GUI.ControlHelper.Line(Me,xpj,ypj,xp1j,yp1j,QBColor(11))
            gmRTL.GUI.ControlHelper.Line(Me,xp1j,yp1j,xp1j,yp1j + zj,QBColor(11))
         Else
            'evaluate a point of function
            xj = CDbl(Interaction.InputBox("X=","Evaluate point","0",200,67))
            yj = CDbl(Interaction.InputBox("Y=","Evaluate point","0",200,67))
            zj = CDbl((ScriptControl.Evaluate(String.Format("f({0}, {1})",xj,yj))))
            System.Windows.Forms.MessageBox.Show("Z(" & xj & "," & yj & ")=" & zj, "Evaluate point", MessageBoxButtons.OK)
         End If
         Exit Sub
      Errors:
         'if the function causes a error (as a division by 0....)
         System.Windows.Forms.MessageBox.Show("Evaluating error", "Attention!", MessageBoxButtons.OK)
      End Sub
      Private Sub mnuRefresh_Click(ByVal sender As Object, ByVal e As EventArgs)
         'refresh the draw
         Axis()
      End Sub
      Private Sub mnuChangeView_Click(ByVal sender As Object, ByVal e As EventArgs)
         Dim mnuChangeView As System.Windows.Forms.ToolStripMenuItem
         mnuChangeView = CType(sender,System.Windows.Forms.ToolStripMenuItem)
         Dim Index As Integer = Me.mnuChangeView.Keys(Me.mnuChangeView.IndexOfValue(mnuChangeView))
         'change the view of draw: from Left, Right...
         Select Case Index
            Case 1
               'view from Left
               a = pg
               b = pg
            Case 2
               'view from Right
               a = 0
               b = pg
            Case 3
               'restore the initial view
               dx = 0
               dy = 0
               Form_Load(Nothing,New EventArgs())
         End Select
         'draw Axis
         Axis()
      End Sub
      Private Sub txtFunction_GotFocus(ByVal sender As Object, ByVal e As EventArgs)
         'select the text in the TextBox when it receives the focus
         txtFunction.SelectionStart = 0
         txtFunction.SelectionLength = Strings.Len(txtFunction.Text)
      End Sub
      Private Sub txtFunction_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
         Dim KeyAscii As Integer
         KeyAscii = Asc(e.KeyChar)
         'draw the function if "Enter" is pressed in the TextBox
         If (KeyAscii = 13) Then
            AddFunction()
            Axis()
         End If
      End Sub
   End Class
End Namespace
