using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Data;
using VBNET = Microsoft.VisualBasic;
using gmRTL.Core;
using Microsoft.VisualBasic.CompilerServices;
using System.Linq;
using System.Collections.Generic;

namespace Vb3DDefine
{
   public partial class Form1 : System.Windows.Forms.Form
   {
      private bool _disposed = false;
      public Form1()
      {
         //
         // Required for Windows Form Designer support
         //
         InitializeComponent();

         //
         // TODO: Add any constructor code after InitializeComponent call
         //
         if (DesignMode) return;
         cmdControls = new System.Collections.Generic.SortedList<int, 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<int, System.Windows.Forms.ToolStripMenuItem>();
         mnuChangeRisolution.Add(1, _mnuChangeRisolution_1);
         mnuChangeRisolution.Add(2, _mnuChangeRisolution_2);
         mnuSetPoint = new System.Collections.Generic.SortedList<int, System.Windows.Forms.ToolStripMenuItem>();
         mnuSetPoint.Add(1, _mnuSetPoint_1);
         mnuSetPoint.Add(2, _mnuSetPoint_2);
         mnuChangeView = new System.Collections.Generic.SortedList<int, 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<int, System.Windows.Forms.ToolStripMenuItem>();
         mnuDrawPlane.Add(1, _mnuDrawPlane_1);
         mnuDrawPlane.Add(2, _mnuDrawPlane_2);
         mnuDrawPlane.Add(3, _mnuDrawPlane_3);
         Form_Load(null, null);
         Form_Resize(null, null);
      }

      /// <summary>
      /// Clean up any resources being used.
      /// </summary>
      /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
      protected override void Dispose(bool disposing)
      {
         if (_disposed)
         {
            return;
         }
         if (disposing)
         {
            if (components != null)
            {
               components.Dispose();
            }
         }
         _disposed = true;
         base.Dispose(disposing);
      }

      double dx = 0.0;
      double dy = 0.0;
      double lx = 0.0;
      double j = 0.0;
      double rs = 0.0;
      int rsbase = 0;
      double p = 0.0;
      double xmx = 0.0;
      double ymx = 0.0;
      double xc = 0.0;
      double yc = 0.0;
      double y = 0.0;
      double xj = 0.0;
      double yj = 0.0;
      double zj = 0.0;
      double xx = 0.0;
      double yy = 0.0;
      float zz = 0.0F;
      double xpj = 0.0;
      double ypj = 0.0;
      double xp1j = 0.0;
      double yp1j = 0.0;
      double a = 0.0;
      double b = 0.0;
      double cosa = 0.0;
      double sina = 0.0;
      double cosp = 0.0;
      double sinp = 0.0;
      double x = 0.0;
      double z = 0.0;
      double zl = 0.0;
      double xp = 0.0;
      double xpl = 0.0;
      double yp = 0.0;
      double ypl = 0.0;
      double xl = 0.0;
      double yl = 0.0;
      double xlx = 0.0;
      double yly = 0.0;
      double xl1 = 0.0;
      double yl1 = 0.0;
      double xlx1 = 0.0;
      double yly1 = 0.0;
      double ycosa = 0.0;
      double ysina = 0.0;
      double ycosp = 0.0;
      double ysinp = 0.0;
      double xp1 = 0.0;
      double yp1 = 0.0;
      // math constants
      private const double e = 2.718281828;
      private const double pg = 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 string func = "";
      public void AddFunction()
      {
         // add function defined in the TextBox to the VBcode with the MS ScriptControl
         string strFunction = "";
         strFunction = "Function f(x, y)" + "\r\n" + "  f = " + txtFunction.Text + "\r\n" + "End Function";
         ScriptControl.ExecuteCommand(strFunction);

      }
      private void Axis()
      {
         // cancel the Form
         gmRTL.GUI.ControlHelper.FormCls(this);
         gmRTL.GUI.ControlHelper.ScaleForm(this);
         this.ForeColor = System.Drawing.Color.FromArgb(255,255,255);
         // print in the upperleft corner the angles from the axis
         gmRTL.GUI.ControlHelper.SetCurrentX(this,0);
         gmRTL.GUI.ControlHelper.SetCurrentY(this,0);
         gmRTL.GUI.ControlHelper.PicturePrint(this,"a=",((int)Math.Floor(a * 180 / pg)),"°");
         gmRTL.GUI.ControlHelper.PicturePrint(this,"b=",((int)Math.Floor(180 - b * 180 / pg)),"°");

         // draw the 3D Axis in the Form
         // ymx = scale the height of the Form
         ymx = 3F / 4F * xmx;
         // (xc,yc) = center of the form
         xc = xmx / 2F + dx;
         yc = ymx / 2F + dy;
         // scale the form from (xmx,ymx)=upperleft corner to (0,0)=downright corner
         gmRTL.GUI.ControlHelper.Scale(this,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(this,xc,yc,xc,ymx,gmRTL.GUI.ControlHelper.QBColor(12));
         gmRTL.GUI.ControlHelper.Line(this,xc,yc,xc - xmx * cosa,yc - xmx * sina,gmRTL.GUI.ControlHelper.QBColor(12));
         gmRTL.GUI.ControlHelper.Line(this,xc,yc,xc + xmx * cosp,yc - xmx * sinp,gmRTL.GUI.ControlHelper.QBColor(12));
         // set the color of the axis label
         this.ForeColor = System.Drawing.ColorTranslator.FromOle(gmRTL.GUI.ControlHelper.QBColor(15));
         // print the axis label near the axis
         for(j = 1.ToDbl(); j <= ymx; j += 1)
         {
            gmRTL.GUI.ControlHelper.PSet(this,xc - j * cosa,yc - j * sina,System.Drawing.ColorTranslator.FromOle(gmRTL.GUI.ControlHelper.QBColor(9)));
            gmRTL.GUI.ControlHelper.PicturePrint(this,j);
            gmRTL.GUI.ControlHelper.PSet(this,xc + j * cosp,yc - j * sinp,System.Drawing.ColorTranslator.FromOle(gmRTL.GUI.ControlHelper.QBColor(9)));
            gmRTL.GUI.ControlHelper.PicturePrint(this,j);
            gmRTL.GUI.ControlHelper.PSet(this,xc,yc + j,System.Drawing.ColorTranslator.FromOle(gmRTL.GUI.ControlHelper.QBColor(9)));
            gmRTL.GUI.ControlHelper.PicturePrint(this,j);
         }
         DrawFunction();
      }
      private void DrawFunction()
      {
         // draw the function in the Form
         double x = 0.0;
         double y = 0.0;
         try
         {
            // 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 = (float)(-lx); y <= (float)(lx); y += 0.5F)
            {
               ycosp = xc + y * cosp;
               ycosa = xc - y * cosa;
               ysinp = yc - y * sinp;
               ysina = yc - y * sina;
               for(x = -lx; x <= lx; x += p)
               {
                  xp = -x * cosa + ycosp;
                  xp1 = -(x + p) * cosa + ycosp;
                  yp = -x * sina + ysinp + ((object)ScriptControl.Script.f(x,y)).ToDbl();
                  yp1 = -(x + p) * sina + ysinp + ((object)ScriptControl.Script.f(x + p,y)).ToDbl();
                  xl = ycosa + x * cosp;
                  xl1 = ycosa + (x + p) * cosp;
                  yl = ysina - x * sinp + ((object)ScriptControl.Script.f(y,x)).ToDbl();
                  yl1 = ysina - (x + p) * sinp + ((object)ScriptControl.Script.f(y,x + p)).ToDbl();
                  // draw line from the previous point to the point evaluated now
                  gmRTL.GUI.ControlHelper.Line(this,xp,yp,xp1,yp1,gmRTL.GUI.ControlHelper.QBColor(10));
                  gmRTL.GUI.ControlHelper.Line(this,xl,yl,xl1,yl1,gmRTL.GUI.ControlHelper.QBColor(10));
               }
            }
            return;
         }
         catch(System.Exception exc)
         {
            gmRTL.Core.GlobalException.Initialize(exc);
            // if there is an error evaluating the function (as a division by 0)...
            // UPGRADE_TODO Resume Next;
         }
      }
      private void mnuInterval_Click(object sender, EventArgs e)
      {
         // increase or decrease the drawing interval
         lx = gmRTL.GUI.ControlHelper.InputBox("lx < (x,y) < lx","Drawing interval","1",200,67).ToDbl();
         Axis();
      }
      private void cmdControls_Click(object sender, EventArgs e)
      {
         System.Windows.Forms.Button cmdControls;
         cmdControls = (System.Windows.Forms.Button)sender;
         int Index = this.cmdControls.Keys[this.cmdControls.IndexOfValue(cmdControls)];
         // control the drawing view
         switch(Index)
         {
         case 1:
            // move to the Left
            dx = dx - xmx / 8;
            break;
         case 2:
            // move to the Right
            dx = dx + xmx / 8;
            break;
         case 3:
            // move up
            dy = dy - xmx / 8;
            break;
         case 4:
            // move down
            dy = dy + xmx / 8;
            break;
         case 5:
            // expand the angle between the X-axis an Y-axis
            b = b - pg / 12;
            break;
         case 6:
            // tight the angle between the X-axis an Y-axis
            b = b + pg / 12;
            break;
         case 7:
            // rotate to the Left
            a = a - pg / 12;
            break;
         case 8:
            // rotate to the Right
            a = a + pg / 12;
            break;
         case 9:
            // zoom In
            xmx = xmx / 1.5;
            break;
         case 10:
            // zoom Out
            xmx = xmx * 1.5;
            break;
         }
         // restore normal resolution
         rs = rsbase;
         // draw Axis
         Axis();
      }
      private void Form_Load(object sender, EventArgs e)
      {
         gmRTL.GUI.ControlHelper.SetAutoRedraw(this,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();
      }
      private void Form_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
      {
         int Button;
         Button = (int)e.Button / 0x100000;
         // show the Popup menů when the right mouse button is clicked
         if (Button == 2)
         {
            gmRTL.GUI.ControlHelper.PopupMenu(mnuGeneral,this);
         }
      }
      private void Form_Resize(object sender, EventArgs e)
      {
         // located the controls in the Form
         int i = 0;
         // rescale the form to the initial value to locate controls
         gmRTL.GUI.ControlHelper.ScaleForm(this);
         // center all controls in the Form
         lblFunction.Left = (this.ClientRectangle.Width - (txtFunction.Width + lblFunction.Width)) / 2;
         txtFunction.Left = lblFunction.Left + lblFunction.Width;
         _cmdControls_4.Left = ((int)((this.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 = this.ClientRectangle.Height - _cmdControls_4.Height;
         _cmdControls_3.Top = _cmdControls_4.Top - _cmdControls_3.Height;
         for(i = 1; i <= 10; i += 1)
         {
            switch(i)
            {
            case 7:
            case 8:
            case 9:
            case 10:
               cmdControls[i].Top = this.ClientRectangle.Height - _cmdControls_9.Height;
               break;
            case 1:
            case 2:
            case 5:
            case 6:
               cmdControls[i].Top = ((int)(this.ClientRectangle.Height - 2.0F * _cmdControls_9.Height));
               break;
            }
         }
         // draw Axis
         Axis();
      }
      private void mnuChangeRisolution_Click(object sender, EventArgs e)
      {
         System.Windows.Forms.ToolStripMenuItem mnuChangeRisolution;
         mnuChangeRisolution = (System.Windows.Forms.ToolStripMenuItem)sender;
         int Index = this.mnuChangeRisolution.Keys[this.mnuChangeRisolution.IndexOfValue(mnuChangeRisolution)];
         // increase or decrease drawing resolution
         if (Index == 1)
         {
            // increase the resolution if it isn't so big (rs=500)
            if (rs < 500)
            {
               rs = rs * 2;
            }
         }
         else
         {
            // decrease the resolution if it isn't so small (rs=10)
            if (rs > 10)
            {
               rs = rs / 2;
            }
         }
         Axis();
      }
      private void mnuDrawPlane_Click(object sender, EventArgs e)
      {
         System.Windows.Forms.ToolStripMenuItem mnuDrawPlane;
         mnuDrawPlane = (System.Windows.Forms.ToolStripMenuItem)sender;
         int Index = this.mnuDrawPlane.Keys[this.mnuDrawPlane.IndexOfValue(mnuDrawPlane)];
         // draw some reference planes
         switch(Index)
         {
         case 1:
            // draw a XY plane
            zz = gmRTL.GUI.ControlHelper.InputBox("Z=","Plane XY","0",200,133).ToSng();
            for(y = -lx; y <= lx; y += 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(this,xl,yl,xl1,yl1,gmRTL.GUI.ControlHelper.QBColor(13));
               gmRTL.GUI.ControlHelper.Line(this,xlx,yly,xlx1,yly1,gmRTL.GUI.ControlHelper.QBColor(13));
            }
            break;
         case 2:
            // draw a ZX plane
            yy = gmRTL.GUI.ControlHelper.InputBox("Y=","Plane ZX","0",200,133).ToDbl();
            for(j = lx; j >= -lx; j += -0.5)
            {
               xl = xc - yy * cosa + j * cosp;
               yl = yc - yy * sina - j * sinp + lx;
               yl1 = yl - 2 * lx;
               gmRTL.GUI.ControlHelper.Line(this,xl,yl,xl,yl1,gmRTL.GUI.ControlHelper.QBColor(13));
            }
            break;
         case 3:
            // draw a ZY plane
            xx = gmRTL.GUI.ControlHelper.InputBox("X=","Plane ZY","0",200,133).ToDbl();
            xl = xc - lx * cosa + xx * cosp;
            xl1 = xl + 2 * lx * cosa;
            for(z = lx; z >= -lx; z += -0.5)
            {
               yl = yc - lx * sina - xx * sinp + z;
               yl1 = yl + 2 * lx * sina;
               gmRTL.GUI.ControlHelper.Line(this,xl,yl,xl1,yl1,gmRTL.GUI.ControlHelper.QBColor(13));
            }
            for(y = lx; y >= -lx; y += -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(this,xl,yl,xl1,yl1,gmRTL.GUI.ControlHelper.QBColor(13));
            }
            break;
         }
      }
      private void mnuSetPoint_Click(object sender, EventArgs e)
      {
         System.Windows.Forms.ToolStripMenuItem mnuSetPoint;
         mnuSetPoint = (System.Windows.Forms.ToolStripMenuItem)sender;
         int Index = this.mnuSetPoint.Keys[this.mnuSetPoint.IndexOfValue(mnuSetPoint)];
         // draw or evaluate a point of the function
         try
         {
            if (Index == 1)
            {
               // draw a point in the Form
               xj = gmRTL.GUI.ControlHelper.InputBox("X=","Draw point","0",200,67).ToDbl();
               yj = gmRTL.GUI.ControlHelper.InputBox("Y=","Draw point","0",200,67).ToDbl();
               zj = gmRTL.GUI.ControlHelper.InputBox("Z=","Draw point","0",200,67).ToDbl();
               xpj = xc - yj * cosa;
               xp1j = xpj + xj * cosp;
               ypj = yc - yj * sina;
               yp1j = ypj - xj * sinp;
               gmRTL.GUI.ControlHelper.Line(this,xpj,ypj,xp1j,yp1j,gmRTL.GUI.ControlHelper.QBColor(11));
               gmRTL.GUI.ControlHelper.Line(this,xp1j,yp1j,xp1j,yp1j + zj,gmRTL.GUI.ControlHelper.QBColor(11));
            }
            else
            {
               // evaluate a point of function
               xj = gmRTL.GUI.ControlHelper.InputBox("X=","Evaluate point","0",200,67).ToDbl();
               yj = gmRTL.GUI.ControlHelper.InputBox("Y=","Evaluate point","0",200,67).ToDbl();
               zj = ((object)ScriptControl.Script.f(xj,yj)).ToDbl();
               System.Windows.Forms.MessageBox.Show("Z(" + xj.ToStr() + "," + yj.ToStr() + ")=" + zj.ToStr(), "Evaluate point", MessageBoxButtons.OK);
            }
            return;
         }
         catch(System.Exception exc)
         {
            gmRTL.Core.GlobalException.Initialize(exc);
            // if the function causes a error (as a division by 0....)
            System.Windows.Forms.MessageBox.Show("Evaluating error", "Attention!", MessageBoxButtons.OK);
         }
      }
      private void mnuRefresh_Click(object sender, EventArgs e)
      {
         // refresh the draw
         Axis();
      }
      private void mnuChangeView_Click(object sender, EventArgs e)
      {
         System.Windows.Forms.ToolStripMenuItem mnuChangeView;
         mnuChangeView = (System.Windows.Forms.ToolStripMenuItem)sender;
         int Index = this.mnuChangeView.Keys[this.mnuChangeView.IndexOfValue(mnuChangeView)];
         // change the view of draw: from Left, Right...
         switch(Index)
         {
         case 1:
            // view from Left
            a = pg;
            b = pg;
            break;
         case 2:
            // view from Right
            a = 0;
            b = pg;
            break;
         case 3:
            // restore the initial view
            dx = 0;
            dy = 0;
            Form_Load(null,new EventArgs());
            break;
         }
         // draw Axis
         Axis();
      }
      private void txtFunction_GotFocus(object sender, EventArgs e)
      {
         // select the text in the TextBox when it receives the focus
         txtFunction.SelectionStart = 0;
         txtFunction.SelectionLength = txtFunction.Text.Len();
      }
      private void txtFunction_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
      {
         int KeyAscii;
         KeyAscii = (int)e.KeyChar;
         // draw the function if "Enter" is pressed in the TextBox
         if (KeyAscii == 13)
         {
            AddFunction();
            Axis();
         }
      }
   }
}
