CAD System Web Site - Computer Aided Design Software
i NET1000.COM
by Makoto Honda
ast Update: 2012-January-16                                                 Update Info     Site Index     Licensing     Copyright Notice     Privacy Policy     Contact Us  
 

 

HOME

                                   
G-System . CAD
Computer-Aided Design Software
__________________________________________________________________________

C# / WPF / WPF3D / DirectX
Visual Studio 2010 Express / .NET / Windows 7
__________________________________________________________________________

  Progress Note / Screen Shots               C# Note             WPF Note             WPF3D Note           .NET Note

 

The WPF/C# conversion effort of the current G-System (VC++/MFC/OpenGL) has officially begun on March 10, 2011. 
Below is my working document for this endeavor.

    WPF CAD SYSTEM  -  NEW SCREEN SHOT                

 

 2011-June-27
* Porting CFD grid generation commands into this C#/WPF project.
* Took some time to straighten out arrays and pointers in C++ for this grid generation algorithm.

 

    SUMMARY                                              2011-March-05

     The G-System is a desktop CAD software written in roughly 50K lines of C++ code.
      It is based on MFC (Microsoft Foundation Class) utilizing MDI (Multiple Document Interface) architecture.
     Graphics rendering is done by OpenGL.
     The current version is based on Visual Studio 2008 (VC++) on Windows 7.

     Now, I am going to port the system into C# / WPF / DirectX on .Net platform.
     The IDE is Visual Studio 2010 Express (free) using WPF/C# on Windows 7.

     OLD SYSTEM:: VC++ / MFC / OpenGL  (~50K lines of C++ code)
     NEW SYSTEM:: C# / WPF / WPF 3D (DirectX)

     Roughly speaking, GUI changes from MFC to WPF. Rendering changes from OpenGL to WPF 3D (or DirectX).
     The rest, after C# porting is done, should work like a charm - maybe.

    ISSUES / CONSIDERATION                                 2011-March-05

     Document/View Architecture :  Doc class / View class
                
MFC Document/View architecture paradigm must be handled by WPF paradigm. 
     View (viewport) creation & management :  Create - Resize/Move - Delete
                
CView + MdiChild: OnInitialUpdate (MFC), ...
     Event-handling / routing mechanism :  L-button / R-button / Mouse Move / Keyin
                
Menu event, Mouse event, Keyboard event, ....  Event handling by WPF
     Real-time view rotation :  O
     Selection - Hit Test :  O
     Project (DLL) Dependency :  O
     FM Programming Paradigm :  O
     Permanent/Temporary FM :  O
     Prompt message :  O
     OnDraw :  Invalidate()
     Draw on all viewports :  O
     Persistent Data :  m_elemList <>
     Desktop design :  Menu creation, Toolbar creation, Icons,.....
     MDI windows :  WPF MdiChild windows

     Graphics Rendering :  WPF 3D - GenerateVertices/CreateGLcalls
                                 
OpenGL calls must be converted to WPF 3D/DirectX calls
     OpenGL display list :  O
     Current Plane :  O
     CDialog boxes :  Replaced by WPF user controls
    

   VS Project Structure / Old VC++ System::  VC++ / MFC / OpenGL      2011-March-10

     Solution "GS" / 12 projects --- Visual Studio 2008 Professional / VC++  (~50K lines of VC++/MFC code)  

     GDoc (2100) / GDoc_1
          GFK_viewing  (1980)
          GFK_linking   (300)
          GFK_base_doc

          GElemLink  (500)
          GElemLight  (400)

          DialogBoxes..... (xxxx)

     GView - graphic (4700)
     GView2 - text info
     GView3 - text info

     GData -  (2000) --- goes to Doc?

     GElement - base class (1100)
     GElem1 - general elements (1900 + 560)
     GElemCfd - cfd (5300)
     GElemPipe - piping (2800) --- delete

     GFK_base (750)
     GFK_element - creation (3600)
     GFK_editing - edit (4500)
          Dialogs...
     GFK_cfd - meshing (5000)
     GFK_piping (3000) --- delete

     GUtil - math utility (1800)

   VS Project Structure / New C# System::  C# / WPF / WPF 3D / DirectX     2011-June-10

      Solution "G-CS" / 9 projects --- Visual Studio 2010 Express / C# / WPF

      GProject_Main
/ exe  
(WPF Application)
          
Control   
ns_Main                           ........ *ns_ for name space
                TutorialControl1.xaml / cs
                TutorialControl2.xaml / cs
                TutorialControl3.xaml / cs
                - - - - -  
                GView.xaml / cs  
ns_Main  class CView .........  Keep this here for now

           MainWindow.xaml / cs  
class MainWindow   ns_Main
           GDoc.cs ns_Main class CDoc

          
GFM_viewing.cs   
ns_Main   class CFM_viewing
           GFM_linking.cs   
ns_Main   class CFM_linking
           GFM_base_doc.cs    ns_Main   class CFM_base_doc

           GElemLink.cs   
ns_Main   class CElemLink
           GElemLight.cs   
ns_Main   class CElemLight

      GProject_View
/ dll   (WPF User Control)
          
Control
                GView.xaml / cs 
class CView..... Kept in GProject_Main for now
                GView2.xaml / cs 
class CView2

      GProject_Dialog
/ dll   (WPF User control)
          
Control
                GDialog1.xaml / cs
                GDialog2.xaml / cs
                - - - - -

      GProject_FM_command
/ dll (Class Library)
          
GFM_base.cs   
ns_FM_command   class CFM_base
           GFM_element.cs
           GFM_editing.cs
           GFM_cfd.cs

      GProject_Data
/ dll   (Class Library)
          
GData.cs  
ns_Data  class CData

      GProject_Element
/ dll   (Class Library)
          
GElement.cs  
ns_Element  class CElemBase, CElemBase1D/2D/3D, ...Elbow3D..

      GProject_Utility
/ dll   (Class Library)
          
GUtility.cs  
ns_Utility  class CPoint2D, CPoint3D, CViewMatrix, ...

      GProject_Global / dll   (Class Library)
          
GGlobal.cs  
ns_Global  class G

      WPF.MDI
/ dll
          
MdiChild.cs   WPF.MDI  
           MdiContainer.cs  
WPF.MDI  

    
 ------------------------------------------------ future consideration
      GProject_DB2 / exe
          
GMySQL.cs   ns_DB2  

      GProject_Controller
/ exe
          
GController.cs   ns_Controller

   MENU STRUCTURE OF G-C# SYSTEM         2011-June-03     

   

 File  Edit  View  Geometry  CFD Mesh  Current
 Plane
 Light  Tools  Window  Help  

  New
  Open
  Close
  -----
  Save
  Save As...
  -----
  Document Name...
  -----
  Exit

 

  Undo
  Redo
  -----
  Cut
  Copy
  Paste
  -----
  FM Delete
  FM Hide
  Show All
  -----
  FM Translate
  FM Rotate
  FM Scale
  FM Mirror
  FM Jump
  -----
  Copy Mode
  -----
  FM Modify
  -----
  Color
  Line Width
  Material
  Layer
  -----
  FM Group
  -----
  FM Change Color
  FM Change Layer
  -----
  FM Copy Window
  FM Paste Window

 

  Perspective Projection
  -----
  Display
       Shaded
       Wireframe
  Clipping Planes
       Near Plane
       Far Plane
  -----
  Preset Views
       Ortho XY
       Ortho XZ
       Ortho YZ
       Iso X
       Iso Y
       Iso Z
  View Setting
       Snap to Current Plane
       Define by 3 Points
  Pan Mode
       Same Camera Orientation
       Turn Camera Head
  Rotate
       Rotate XYZ Axis
       Rotate Screen
       Rotate Arbitrary Axis
  Lens Angle
  Zoom
       By Lens Angle
       By Camera Move
       Zoom Box
  Fit All
  -----
  Toolbar
  -----
  Properties...

  FM Point
  FM Line
  FM Rectangle
  FM Circle
  FM Box / Pyramid
  FM Cylinder / Cone
  FM Elbow
  -----
  FM Revolve
  FM Extrude 
  FM Sweep / Transverse
  FM Transit
  -----
  FM Text

 

  FM Domain
  FM Multi-Box Domain
  FM Multi-Cylinder Domain
  -----
  FM Line Edge
  FM Arc Edge
  -----
  Structure Domain
  -----
  FM Slice
  FM Insert
  -----
  FM Grid Generation
  -----
  Output Domain File
  Output Grid File

 

  Preset Planes
       XY Plane
       XZ Plane
       YZ Plane
  Plane Setting
       Move Origin
       Set Normal
       On Element
       Define by 3 Points
       Rotate
  -----
  Grid Snap
  -----
  Properties...

 

  New Light
  Move Light
  Delete Light
  Named Light
  -----
  Properties...

 

  Coordinate Key-in Mode
       Rectangular
       Cylindrical
       Spherical
  -----
  Global
  Current Plane
  -----
  Absolute
  Relative
  -----
  FM Analysis
  -----
  Setting
  Customize...
  Options...
  New Viewport
  -----
  Tile
  Cascade
  -----
  2-Viewport Layout
  3-Viewport Layout
  4-Viewport Layout
  -----
  Window Theme
       Aero
       Luna
       Generic

  Help
  User Guide
  Documentation
  -----
  About G-System
  -----
  Tutorial Examples...

 

 

 

  

   Critical Data Flow and Organization        2011-March-22

     -----------------------------------------------------------------------------------------
     MainWindow.xaml.cs - Main WPF application window

     <Member data>
          public CDoc pDoc;

     <Constructor>
          pDoc = new CDoc (this);

     <View creation - Menu: New Window>
        
 private void miNewWindow_Click (object sender, RoutedEventArgs e)
          {
               CView pV = new CView (pDoc, pDoc.m_pData);
               pDoc.m_viewList.Add (pV);

               MdiChild mdiView = new MdiChild()
               {
                    Title = "WPF 3D - CView",
                    Content = pV,
                    Width = 400, Height = 400,
               };
               Canvas.SetLeft (mdiView, 400);
               Canvas.SetTop (mdiView, 250);
               Container.Children.Add (mdiView);    
// (1) Save in container
               pDoc.m_mdiViewList.Add (mdiView);
 // (2) Save in view list

               m_mdiViewList.Add (mdiView;
               m_viewList.Add (pV);
               this.cameraControl2 = pV;
          }

     <FM command initiation>
        
 private void miFMPoint_Click(object sender, RoutedEventArgs e)
          {
             
 // FM Point...
          }

    
-----------------------------------------------------------------------------------------
     GDoc.cs - Document class

     <Member data>
          public CData m_pData;
          public CView m_pVptCur = new CView(); // viewport currency

          public List<MdiChild> m_mdiViewList = new List<MdiChild>();
          public List<CView> m_viewList = new List<CView>();
// not needed?

          public CFM_base m_pFM;
          public CFM_base m_pFMT;

          public CView m_pViewEvent = new CView();
// view of event-origin

     <Constructor>
        
  public CDoc (Window window)
          {
               this.window = window;
               m_pData = new CData();

               // Create default view -- cannot ??
               // vw.Owner = this;
               // window.Show();
          }

     <FM command - default FM is Point creation>
          m_pFM = m_pFKM = null; // This will be deleted unless null
          m_pFM = new CFM_createPoint (m_pData);

    
-----------------------------------------------------------------------------------------
     CView.xaml.cs - View class

     <Member data>
          public CData m_pData;
          public CDoc m_pDoc;

    
<Constructor>
          InitializeComponent();  // WPF
          this.m_pDoc = pDoc;
          this.m_pData = pData;
          InitialViewDefault();

   
 <Event generation>
         
private void UserControl_PreviewMouseLeftButtonDown (object sender, MouseButtonEventArgs e)
          {
              
// This is where an event is issued to the active FM command
               CFM_base m_pFM = m_pDoc.GetActiveFK();
               m_pFM.EventForSEL(1, null);
               m_pFM.EventForDEFPT(1, null);
               m_pFM.EventForIND(1, null);
               m_pFM.EventForKY1(1, null);
               m_pFM.EventForKY2(1, null);
               m_pFM.EventForKY3(1, null);
               m_pFM.EventForLBD(1, null);
               m_pFM.EventForLBU(1, null);
               m_pFM.EventForLB2(1, null);
          }

          private void UserControl_PreviewMouseRightButtonDown (object sender, MouseButtonEventArgs e)
          {
              
// Real-time view manipulation.... no event issued to FM commands
              
this.myCamera.Position = new Point3D(cameraPosX, cameraPosY, cameraPosZ);
          }

    
-----------------------------------------------------------------------------------------
     CData.cs - Data class - primary repository of Doc's data

     <Member data>
         
public List<object> m_elemList = new List<object>();
          public List<object> m_lightList = new List<object>();
          public List<object> m_viewMatrixList = new List<object>();
// View Matrix
          public List<object> m_curPlaneList = new List<object>();
// Current Planes


    
-----------------------------------------------------------------------------------------
     CFM_Command.cs - FM commands...

     <Member data>
          public CDoc pDoc;xxxxxxxxxxx

     <Constructor>
          pDoc = new CDoc (this);xxxxxxxxxxxxxxxx

     <View creation - Menu: New Window>
        
 private void miNewWindow_Click (objectxxxxxxxxxxxxxxx sender, RoutedEventArgs e)
          {
               CView pV = new CView (pDoc, pDoc.m_pData);xxxxxxxxxxxxxxxxx
               pDoc.m_viewList.Add (pV);

   How to add a New Project to my G_CS Solution      2011-March-12

     How to add a new project - Class Library (GUtility) - Visual Studio 2010 / Visual C# Express

     1.  R-click Add > New Project > Class Library, Name GUtility
     2.  Replace a newly provided xxx.cs with your own GUtility.cs code. Add namespace GUtility.
     3.  R-click References folder of Main project. Click Add References. Select Project tab. Select GUtility project and OK.
     4.  Use "using GUtility" in Main.cs.

     How to add a new project - WPF project (GView)
- Visual Studio 2010 / Visual C# Express

     1.  R-click Add > New Project > WPF Application, Name GProjectView
     2.  Remove App.xaml & MainWindow.xaml - we don't need them.
     3.  Add "Controls" folder under this project.
     4.  R-click the project and select Properties.
Application Tab-->Output type: Class library.
          This will set this project as DLL (Choosing Window Application will set it as EXE). 

     How to add a UserControl in Controls folder of a project - Visual Studio 2010 / Visual C# Express

     1.  R-click the Controls folder of a project.  Add > User Control...  Select UserControl (WPF). Enter name GView
     2.  Replace a newly provided xaml.cs with your own GView.cs code. Add namespace GView.

     How to add references to a project - in order to use "using xxx"
- Visual Studio 2010 / Visual C# Express

     1.  R-click References folder of the Project and click Add Reference... In the Project tab, select all projects this project is dependent on OK.

     Note on "cyclic" dependency of Projects - Visual Studio 2010 / Visual C# Express

     1.  You must not create a cyclic dependency on other projects when "adding references" on Reference folder of the project.
     2.  If two entities (files) depend on each other (cyclically), they must be placed in the same namespace (project).

 

   How to Integrate 3DTools to theSolution           2012-Jan-06

 

  1. In VS2010 Solution Explorer, R-click 3DTools(unavailable), and removed it from the solution first.

  2. In Windows Explorer, copy 3DTools folder (that contains 3DTools.csproj) to the same folder that contains my.solution file as well as all the Project folders.

  3. In VS2010 Solution Explorer, R-click Solution and Add--> Existing Project... Select 3DTools.csproj that was copied above.

  4. Then for all Projects that need this 3DTools, R-click and Add Reference... and select 3DTools & OK.


 

   C# GElement Hierarchy            2011-March-15

  -----------------------------------------------------------------------------------------
  abstract class CELemBase
  {
       public abstract CElemBase Clone();
       public abstract void GenerateVertices();
       public abstract int CreateGLcalls();

       public virtual CPoint3D GetMxOrigin();
       public virtual CPoint3D GetMxAxisX();
       public virtual CPoint3D oid GetMxAxisY();
       public virtual CPoint3D GetMxAxisZ();

       public virtual void SetMatrix(CViewMatrix mx) { }
       public virtual CViewMatrix GetMatrix() { return new CViewMatrix(); }

       public virtual void SetMxOrigin(double x, double y, double z) { }
       public virtual void SetMxAxisX(double x, double y, double z) { }
       public virtual void SetMxAxisY(double x, double y, double z) { }
       public virtual void SetMxAxisZ(double x, double y, double z) { }

       public virtual void Translate();
       public virtual void Rotate();
       public virtual void Scale();
       public virtual void Mirror();
       public virtual void Jump();

       public virtual void ApplyMatrixToModelMx();
       public virtual void GetModelMxAs3x4();
       public virtual void GetMinMaxForAbsoluteXYZ();
       public virtual void HighlightVolumeColor()
  }

 
-----------------------------------------------------------------------------------------
  public abstract class CELemBase1D : CElemBase
  {
       // - public override CElemBase Clone();
       // - public override void GenerateVertices();
       // - public override int CreateGLcalls();

       public override void GetMxOrigin();
       public override void SetMxOrigin(double x, double y, double z) { }

       public override void Translate();
       public override void Rotate();
       public override void Scale();
       public override void Mirror();
       public override void Jump();

       public override void ApplyMatrixToModelMx();
       public override void GetModelMxAs3x4();
       public override void GetMinMaxForAbsoluteXYZ();

       public virtual void MakeHomegeneousMatrix16();
  }

 
-----------------------------------------------------------------------------------------
  public abstract class CELemBase2D : CElemBase1D
  {
       public override CElemBase Clone();
       public override void GenerateVertices();
       public override void CreateGLcalls();
       public override void GetMxOrigin();
       public override void GetMxAxisX();
       public override void GetMxAxisY();
       public override void GetMxAxisZ();
       public override void Translate();
       public override void Rotate();
       public override void Scale();
       public override void Mirror();
       public override void Jump();
       public override void ApplyMatrixToModelMx();
       public override void GetModelMxAs3x4();
  }

 
-----------------------------------------------------------------------------------------
  public abstract class CELemBase3D : CElemBase2D
  {
       public override CElemBase Clone();
       public override int GenerateVertices();
       public override void CreateGLcalls();
  }

 
-----------------------------------------------------------------------------------------
  public class CELemElbow3D : CElemBase3D
  {
       public override CElemBase Clone();
       public override int GenerateVertices();
       public override void CreateGLcalls();
  }

    Simple Scenario to Kick Off This Conversion        2011-March-24

     Scenario
     (1) Start Application
          MainWindow::constructor
          pDoc = new CDoc(this);
          // Create a default view - same as New Window
          miNewWindow_Click(null, null);

     (2) Enter FM-command: CreateBox
          MainWindow::miFMbox_Click
    
     pDoc.OnFMCreateBox()
          ===>     GDoc::OnFMCreateBox()
                       m_pFM = new CFM_createBox (m_pData)
                       InitializeFM()

     (3) In FM_createBox, click Viewport --> This "creates" a new box
          GView::UserControl_PrevMouseLeftButtonDown
          CFM_base pFM = m_pdoc.GetActiveFM()
          pFM.EventForDEFPT (1, null) ------------------- CREATE BOX
          (A)==>
  GFM_createBox::EventForDEFPT ()
         
            CElemBase pE = new CElemBox()
                      m_pData.m_elemList.Add (pE)
                      InvalidateAllVpts()??
          m_pDoc.OnDraw_WPF (this.myViewport, allVpts)  ------> (C) ON DRAW 

     (4) In FM_createBox, click model --> This "modifies" the box
         
GView::Model_PrevMouseLeftButtonDown
    
     CFM_base pFM = m_pdoc.GetActiveFM()
          pFM.EventForSEL (1, null) -------------------- MODIFY BOX
          (B)==> GFM_createBox::EventForSEL ()
                     
///////////// - test of MODIFY box  
                      CElemBox pE = m_pData.m_elemList[0] as CElemBox;
                      // Modify some elem attributes...
                      pE.m_width *= 2;
          m_pDoc.OnDraw_WPF (this.myViewport, allVpts)  ------> (C) ON DRAW

     (C) GDoc::OnDraw_WPF (vpt, allVpts)
    
     foreach (CView pV in m_viewList)
          foreach (CElem pE in m_pData.m_elemList)
               pE.DrawElemOneVpt (out n3, out vec3) ------> (D) DRAW ELEM ONE VPT
               (D)==> GElem::DrawElemOneVpt (out n3, out vec3, ...)
                    
      // Elem's own ViewMatrix...
                           CreateVertices()  // -- no change needed
                           CreateGLcalls_WPF (out n3, out vec3)
               MesgGeometry3D mesh = new...
                    mesh.TriangleINDEX
               pV.MyViewport.Children.Add (model)

     (5) R-click the viewport --> Real-time View rotation
          GView::UserControl_PrevMouseRightButtonDown
    
     myCamera.Position
          myCamera.LookDirection
          myCamera.FieldOfView

     (6) R-click the model --> Just a Test to add geometry   
          GView::Model_PrevMouseRightButtonDown
          m_pDoc.OnDraw_WPF_TEST  (this.myViewport, allVpts) 

   How to create a new element        2011-March-27

   CElemBox::  example
   /////////////////////////////////////////////////////////////////////////////
   public CElemBox(G.COLORREF color, int layer, CPoint3D pt, CPoint3D dir,
   CPoint3D ori, double height, double width) : base(color, layer, 1, pt, dir, ori, height, width)
   {
        m_elemType = G.ELEM_TYPE.ET_BOX;
        m_totalVertex = 4;
   }
   /////////////////////////////////////////////////////////////////////////////
   public override int GenerateVertices() // public virtual???????
   {
        double w = m_width / 2.0f;
        double h = m_height / 2.0f;

        m_pVertex2D = new CPoint2D [m_totalVertex ];
        CPoint2D pt0 = new CPoint2D(w, h); m_pVertex2D[0] = pt0;
        CPoint2D pt1 = new CPoint2D(w, -h); m_pVertex2D[1] = pt1;
        CPoint2D pt2 = new CPoint2D(-w, -h); m_pVertex2D[2] = pt2;
        CPoint2D pt3 = new CPoint2D(-w, h); m_pVertex2D[3] = pt3;
        return 4; // ?
   }
   /////////////////////////////////////////////////////////////////////////////
   public override void CreateGLcalls_WPF(out int n3, out CPoint3D[,] vec3)
   {
        // Create calls to OpenGL using vertices in m_generatedPts[i] qaz
        n3 = 2; // 2 triangles
        vec3 = new CPoint3D[3, 100];

        vec3[0, 0] = new CPoint3D(m_pVertex2D[0].x, m_pVertex2D[0].y, 0.0f);
        vec3[0, 1] = new CPoint3D(m_pVertex2D[1].x, m_pVertex2D[1].y, 0.0f);
        vec3[0, 2] = new CPoint3D(m_pVertex2D[2].x, m_pVertex2D[2].y, 0.0f);

        vec3[1, 0] = new CPoint3D(m_pVertex2D[2].x, m_pVertex2D[2].y, 0.0f);
        vec3[1, 1] = new CPoint3D(m_pVertex2D[3].x, m_pVertex2D[3].y, 0.0f);
        vec3[1, 2] = new CPoint3D(m_pVertex2D[0].x, m_pVertex2D[0].y, 0.0f);

        ApplyMatrixToVec(n3, ref vec3);

        //2011-3-14 was CreatePolygonWithNormal (4, vertex, 3,2,1,0);
   }

   CElemBase2D::
  
/////////////////////////////////////////////////////////////////////////////
   public void ApplyMatrixToVec(int n3, ref CPoint3D[,] vec3)
   {
        // Apply elem's matrix to each vertex... m_matrix
        for (int i = 0; i < n3; i++)
        {
             vec3[0, i] = m_matrix.TransformPoint(vec3[0, i]);
             vec3[1, i] = m_matrix.TransformPoint(vec3[1, i]);
             vec3[2, i] = m_matrix.TransformPoint(vec3[2, i]);
        }
   }

  
CElemBase::
  
/////////////////////////////////////////////////////////////////////////////
   public void DrawElemOneVpt_WPF(out int n3, out CPoint3D[,] vec3)
   {
        GenerateVertices();
        CreateGLcalls_WPF(out n3, out vec3); // Apply Elem's own matrix, etc.....
   }

   CDoc::
   /////////////////////////////////////////////////////////////////////////////
   public void OnDraw_WPF(Viewport3D vpt, bool bOneVptOnly = false) // 2011-3-22
   {
        // In the VC++ G system, CView::OnDraw drew everything:
        // - DrawAllElems
        // - DrawCurPlane
        // - DrawAllTempElems
        // - DrawRubberband3D
        // - DrawZoomBox
        // - DrawRubberband2D
        // So, we have to do the same here....
        ///////////////////////////////////////////////////////
        //---------- DrawAllElems -------------------
        ///////////////////////////////////////////////////////
        // Most cases require all viewports to be updated
        foreach (CView pV in m_viewList)
        {
             foreach (CElemBase1D pE in m_pData.m_elemList)
             {
                  Colors color;
                  int n3 = 0;
                  CPoint3D[,] vec3 = new CPoint3D[3, 100];
                  pE.DrawElemOneVpt_WPF(out n3, out vec3);
                  ///////////////////////////////////////// Create model
                   MeshGeometry3D mesh = new MeshGeometry3D();
                  ///////////////////////////////////////// Create model
                  for (int i = 0; i < n3; i++)
                  {
                       int ii = i * 3;
                       Point3D pp0 = new Point3D(vec3[0, i].x, vec3[0, i].y, vec3[0, i].z);
                       Point3D pp1 = new Point3D(vec3[1, i].x, vec3[1, i].y, vec3[1, i].z);
                       Point3D pp2 = new Point3D(vec3[2, i].x, vec3[2, i].y, vec3[2, i].z);
                       mesh.Positions.Add(pp0);
                       mesh.Positions.Add(pp1);
                       mesh.Positions.Add(pp2);
                       mesh.TriangleIndices.Add(ii);
                       mesh.TriangleIndices.Add(ii + 2);
                       mesh.TriangleIndices.Add(ii + 1);
                       Vector3D norml = CalculateNormal(pp2, pp1, pp0); // bad - (pp0, pp1, pp2);
                       mesh.Normals.Add(norml);
                       mesh.Normals.Add(norml);
                       mesh.Normals.Add(norml);
                  }
                  Material matl = new DiffuseMaterial(new SolidColorBrush(Colors.Yellow));
                  GeometryModel3D geo = new GeometryModel3D(mesh, matl);
                  ModelVisual3D model = new ModelVisual3D();
                  model.Content = geo;
                  ///////////////////////////////// Add model to viewport
                  if (bOneVptOnly)
                  {
                       vpt.Children.Add(model); // This vpt only
                       //-------------------------------------------------- Lihgt
                       // vpt.Children.Add(model4light); // add light
                       break;
                  }
                  pV.myViewport.Children.Add(model);
                  ///////////////////////////////// Add model to viewport
             }
             //--------------------------------------------------------------- Lihgt
             ModelVisual3D model4light = new ModelVisual3D();
             DirectionalLight light = new DirectionalLight();
             light.Color = Colors.White; // Green; // White;
             light.Direction = new Vector3D(11, -21, -111);//(-1, 1, -5);
             model4light.Content = light;
             pV.myViewport.Children.Add(model4light); // add light
             //--------------------------------------------------------------- Lihgt
        }

   VIew Creation / Initialization / OnSize()         2011-May-26

  
   /////////////////////////////////////////////////////////////////////////////
   Main :: miNewWindow_Click (object sender, RoutedEventArgs e)
   {
        //-------------------------------------------------  A NEW VIEWPORT
        CView pV = new CView(pDoc, pDoc.m_pData);
        pDoc.m_viewList.Add(pV);

        //------------------------------------------------- MDI Creation
        MdiCild mdiView = new MdiChild()

        //------------------------------------------------- OnInitialUpdate
        pV.OnInitialUpdate ();
        // In MFC's Doc/View architecture, OnInitialUpdate is called immediately after the view is attached
        // to the document. This is where the view's initialization should be done.

  
   /////////////////////////////////////////////////////////////////////////////
   CView :: constructor
   {
        //-------------- mainly member data initialization

  
   /////////////////////////////////////////////////////////////////////////////
   CView :: OnInitialUpdate ()
   {
       //-------------- initialization
       OnSize (mdi.Width, mdi.Height)
       Setup2Projection ()
       Setup2UpVector ()
       Setup3Light ()

  

   /////////////////////////////////////////////////////////////////////////////
   CView :: OnSize (x, y)
   {
        //-------------------------------------------------  A NEW VIEWPORT
        m_pixSizeX, Y
        UpdateOrthoSizeGivenNewPerspectiveSetting ()
        --->   Setup1ViewAspectRatio ()

   Menu: Window --> New Window (viewport)        2011-March-29

   New Viewport Creation - MainWindow::
   /////////////////////////////////////////////////////////////////////////////
   private void miNewWindow_Click(object sender, RoutedEventArgs e)
   {
        //------------------------------------------------- CREATE A NEW VIEWPORT
        // (1) Create a CView instance...
        CView pV = new CView(pDoc, pDoc.m_pData);
        pDoc.m_viewList.Add(pV);

        // (2) Create an Mdi instance...
        MdiCild mdiView = new MdiChild()
        { Title = "WPF 3D - CView",
          Content = pV,
          Width = 600, MinWidth = 150,
          Height = 400, MinHeight = 150,
          MinimizeBox = true, MaximizeBox = true,
        };
        Canvas.SetLeft(mdiView, 600);
        Canvas.SetTop(mdiView, 150);
        // Save in 2 places: (1) Mdi Container (2) data member
        Container.Children.Add(mdiView);
        pDoc.m_mdiViewList.Add(mdiView);
        pDoc.m_viewList.Add(pV);

        // (3) Initialize view attributes...
        pV.OnInitialUpdate(600, 400);
        // In MFC's Doc/View architecture, OnInitialUpdate is called immediately after the view is attached
        // to the document. This is where the view's initialization should be done.

        // (4) Camera setup...
        pV.Setup2Projection();
        pV.Setup2UpVector();
        -- pV.myCamera.Position = new Point3D(-20, 0, 0);
        -- pV.myCamera.LookDirection = new System.Windows.Media.Media3D.Vector3D(1, 0, 0);
        -- pV.myCamera.UpDirection = new System.Windows.Media.Media3D.Vector3D(0, 0, 1);
        -- pV.myCamera.FieldOfView = 30;
        -- pV.myCamera.NearPlaneDistance = 0.1;
        -- pV.myCamera.FarPlaneDistance = 200;

        // (5) Lighting...
        ModelVisual3D model4light = new ModelVisual3D();
        DirectionalLight light = new DirectionalLight();
        light.Color = Colors.White; // Green;
        light.Direction = new Vector3D(1, -21, -111);
        model4light.Content = light;
        pV.myViewport.Children.Add(model4light); // add light to vpt
        //------------------------------------------------- CREATE A NEW VIEWPORT
  }

   WPF Rendering Flow : OnDraw_WPF         2011-May-26

   (A) Create a New Element
   /////////////////////////////////////////////////////////////////////////////
   CView::UserControl_PreviewMouseLeftButtonDown (object sender, MouseButtonEventArgs e)
   {
        CFM_base pFM = m_pDoc.GetActiveFM ();

        pFM.EventForIND ();

        m_pDoc.OnDraw_WPF (m_pData.m_OnDrawFlag, this);
   }
   /////////////////////////////////////////////////////////////////////////////
   CFM_createBox3d::EventForIND ()
   {
        //------------------------------------------------- CREATE A NEW ELEMENT
        // Clear this list every time
        m_pData.m_elemNewlyCreatedList.Clear ();

        CElemBase pE1 = new CElemBox3d(G.COLORREF.A, layer, m_ptIND, new CPoint3D(1, 0, 0), new CPoint3D(1, 0, 1), 0.1, 0.1, 0.5);
        m_pData.m_elemList.Add (pE1);
        m_pData.m_elemNewlyCreatedList.Add (pE1);
        CElemBase pE2 = new CElemBox3d(G.COLORREF.A, layer, m_ptIND, new CPoint3D(-1, 0, 0), new CPoint3D(1, 0, 1), 0.1, 0.1, 0.5);
        m_pData.m_elemList.Add (pE2);
       
m_pData.m_elemNewlyCreatedList.Add (pE2);

        m_pData.m_OnDraw_flag = 1; // Draw only newly created elements on all vpts
   }
   /////////////////////////////////////////////////////////////////////////////
   CDoc::OnDraw_WPF (int flag, CView pVOnlyOne = null)
   {
        ------------------------------------------------------------
        // flag = 1: Draw only newly created elems in all vpts
        {
             foreach (CView pV in m_viewList)
             {
                  DrawNewlyCreatedElems (pV);
                  //------------------ Draw Axis axes
                  //------------------ Draw Current plane
             }
        ------------------------------------------------------------
        // flag = 2: Undraw an elem in all vpts
        {
             foreach (CView pV in m_viewList)
             {
                  UndrawThisElem (pV, m_pData.m_pElemUndraw);
             }
        ------------------------------------------------------------
        // flag = 3: Draw all elems in only one vpt
        {
             DrawAllElems (pVOnlyOne);
             //------------------ Draw Axis axes
             //------------------ Draw Current plane
   }
   /////////////////////////////////////////////////////////////////////////////
   CDoc::DrawAllElems (CView pV)
   {
        foreach (CElemBase1D pE in m_pData.m_elemList)
        {
             DrawElemOneVpt (pE, pV);
        }
    }
   /////////////////////////////////////////////////////////////////////////////
   CDoc::DrawNewlyCreatedElems (CView pV)
   {
        foreach (CElemBase1D pE in m_pData.m_elemNewlyCreatedList)
        {
             DrawElemOneVpt (pE, pV);
        }
    }
   /////////////////////////////////////////////////////////////////////////////
   CDoc::UndrawThisElem (CView pV, CElemBase pElemToDelete)
   {
        int index = 0;
        foreach (CElemBase pE in pV.m_elemList)
        {
             if (pE == pElemToDelete)
             {
                  index = 1;
                  ModelVisual3D model = pV.m_modelVisual3DList (index);
                  pV.myViewport.Children.Remove (model);
                  break;
              }
         }
   }
   /////////////////////////////////////////////////////////////////////////////
   CDoc::DrawElemOneVpt (CElemBase pE, CView pV)
   {

        Colors color;
        int n3 = 0;
        CPoint3D[,] vec3 = new CPoint3D[3, 100];
        pE.GenerateVerticesAndCreateWPFcalls (out n3, out vec3);

        MeshGeometry3D mesh = new MeshGeometry3D();
        for (int i = 0; i < n3; i++)
        {
             Point3D pp0 = new Point3D(vec3[0, i].x, vec3[0, i].y, vec3[0, i].z);
             mesh.Positions.Add (pp0,,,,);
             mesh.TriangleIndices.Add (ii,,,,);
             Vector3D norml = CalculateNormal(pp0, pp1, pp2);
             mesh.Normals.Add (norml,,,,);
        }
        Material mat = new DiffuseMaterial(new SolidColorBrush(Colors.LightBlue));
        GeometryModel3D geo = new GeometryModel3D(mesh, mat);
        ModelVisual3D model = new ModelVisual3D ();
        model.Content = geo;
        pV.myViewport.Children.Add (model); // Add model to viewport

        // Save for future delete...
        pV.m_modelVisual3DList.Add (model);
        pV.m_elemList.Add (pE);
   }

   (B) Delete an Element
   /////////////////////////////////////////////////////////////////////////////
   CView::UserControl_PreviewMouseLeftButtonDown (object sender, MouseButtonEventArgs e)
   {
        //------------------------------------------------- GET CURRENT FM
        CFM_base pFM = m_pDoc.GetActiveFM ();

        pFM.EventForIND ();

        m_pDoc.OnDraw_WPF (m_pData.m_OnDrawFlag, this);
   }
   /////////////////////////////////////////////////////////////////////////////
   CFM_createBox3d::EventForIND ()
   {
        // ---- Identify the element to be deleted

        //------------------------------------------------- REMOVE THIS ELEM FROM ELEM LIST
        m_pData.m_elemList.Remove (pElemToDelete);

        m_pData.m_OnDraw_flag = 2; // Undraw an element on all vpts

        m_pData.m_pElemUndraw = pElemToDelete;
   }
   /////////////////////////////////////////////////////////////////////////////
   CDoc::OnDraw_WPF (int flag, CView pVOnlyOne = null)
   {
        // flag = 1: Draw only newly created elems in all vpts
        {
             foreach (CView pV in m_viewList)
             {
                  DrawNewlyCreatedElems (pV);
                  //------------------ Draw Axis axes
                  //------------------ Draw Current plane
             }
        }
        // flag = 2: Undraw an elem in all vpts
        {
             foreach (CView pV in m_viewList)
             {
                  UndrawThisElem (pV, m_pData.m_pElemUndraw);
             }
        }
        // flag = 3: Draw all elems in only one vpt
        {
             DrawAllElems (pVOnlyOne);
             //------------------ Draw Axis axes
             //------------------ Draw Current plane
        }
   }
   /////////////////////////////////////////////////////////////////////////////
   CDoc::UndrawThisElem (CView pV, CElemBase pElemToDelete)
   {
        int index = 0;
        foreach (CElemBase pE in pV.m_elemList)
        {
             if (pE == pElemToDelete)
             {
                  index = 1;
                  ModelVisual3D model = pV.m_modelVisual3DList (index);
                  pV.myViewport.Children.Remove (model);
                  break;
              }
         }
   }

   (C) When a New Viewport Popped
   /////////////////////////////////////////////////////////////////////////////
   MainWindow::miNewViewport_Click(object sender, RoutedEventArgs e)
   {
        //------------------------------------------------- GET CURRENT FM
        // (1) Create a CView instance ---------------------- CREATE NEW VIEWPORT
        CView pV = new CView (pDoc, pDoc.m_pData);
        pDoc.m_viewList.Add (pV);

        // (2) Create an Mdi instance ------------------------ CREATE MDI INSTANCE
        MdiChild mdiChd = new MdiChild()
        Canvas.SetLeft(mdiChd, 600);
        Canvas.SetTop(mdiChd, 150);

        // Save in 2 places: (1) Mdi Container (2) data member
        Container.Children.Add(mdiChd);
        pDoc.m_mdiViewList.Add(mdiChd);
        pV.m_mdiChild = mdiChd;

        // (3) Initialize view attributes...
        pV.OnInitialUpdate(); // ((int)mdiWidth, (int)mdiHeight);

        // (4) Camera setup ------------------------------------ CAMERA
        pV.Setup2Projection();
        pV.Setup2UpVector();

        // (5) Lighting ----------------------------------------- LIGHT
        ModelVisual3D model = new ModelVisual3D();
        DirectionalLight lightDir = new DirectionalLight();
        AmbientLight lightAmb = new AmbientLight();
        PointLight lightPnt = new PointLight();
        pV.myViewport.Children.Add(model); // add light to vpt

        // (6) Draw all elements -------------------------- DRAW ELEMENTS
        pDoc.OnDraw_WPF (3, pV); // Draw all elemes in one vpt
   }
   /////////////////////////////////////////////////////////////////////////////
   CDoc::OnDraw_WPF (int flag, CView pVOnlyOne = null)
   {
        // flag = 1: Draw only newly created elems in all vpts
        {
             foreach (CView pV in m_viewList)
             {
                  DrawNewlyCreatedElems (pV);
                  //------------------ Draw Axis axes
                  //------------------ Draw Current plane
             }
        }
        // flag = 2: Undraw an elem in all vpts
        {
             foreach (CView pV in m_viewList)
             {
                  UndrawThisElem (pV, m_pData.m_pElemUndraw);
             }
        }
        // flag = 3: Draw all elems in only one vpt
        {
             DrawAllElems (pVOnlyOne);
             //------------------ Draw Axis axes
             //------------------ Draw Current plane
        }
   }
   /////////////////////////////////////////////////////////////////////////////
   CDoc::DrawAllElems (CView pV)
   {
        foreach (CElemBase1D pE in m_pData.m_elemList)
        {
             DrawElemOneVpt (pE, pV);
        }
    }
   /////////////////////////////////////////////////////////////////////////////
   CDoc::DrawElemOneVpt (CElemBase pE, CView pV)
   {

        Colors color;
        int n3 = 0;
        CPoint3D[,] vec3 = new CPoint3D[3, 100];
        pE.GenerateVerticesAndCreateWPFcalls (out n3, out vec3);

        MeshGeometry3D mesh = new MeshGeometry3D();
        for (int i = 0; i < n3; i++)
        {
             Point3D pp0 = new Point3D(vec3[0, i].x, vec3[0, i].y, vec3[0, i].z);
             mesh.Positions.Add (pp0,,,,);
             mesh.TriangleIndices.Add (ii,,,,);
             Vector3D norml = CalculateNormal(pp0, pp1, pp2);
             mesh.Normals.Add (norml,,,,);
        }
        Material mat = new DiffuseMaterial(new SolidColorBrush(Colors.LightBlue));
        GeometryModel3D geo = new GeometryModel3D(mesh, mat);
        ModelVisual3D model = new ModelVisual3D ();
        model.Content = geo;
        pV.myViewport.Children.Add (model); // Add model to viewport

        // Save for future delete...
        pV.m_modelVisual3DList.Add (model);
        pV.m_elemList.Add (pE);
   }

   Function Mode (FM) Messages Printing Mechanism         2011-June-04

   I decided to use a delegate to pass FMPrintMessages() down to Class FM_command
   to handle FM prompt message display on the G-System desktop.

   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  
MainWindow::
   ------------------------------------------------------------------------------------
   public void FMPrintMessages ()   // to be sent as Delegate to -> Doc -> FM base
   {
        if (pDoc != null)
        {
             lblFMcommand.Content = pDoc.m_pData.FM_command;
             lblFMprompt.Content = pDoc.m_pData.FM_prompt;
             lblSystemFeedback.Content = pDoc.m_pData.FM_systemFeedback;
             lblKeyinEcho.Content = pDoc.m_pData.FM_keyinEcho;
             // clear each time
             pDoc.m_pData.FM_prompt = "";
             pDoc.m_pData.FM_systemFeedback = "";
             pDoc.m_pData.FM_keyinEcho = "";
        }
   }
   ------------------------------------------------------------------------------------
   pDoc = new CDoc (this, FMPrintMessages);

   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  
CDoc::
   ------------------------------------------------------------------------------------
   public FMPrintMessagesDelegate
FMPrintMessages;
   ------------------------------------------------------------------------------------
   public CDoc (Window window, FMPrintMessagesDelegate d)
   {
        this.window = window;
        this.
FMPrintMessages = d;
        m_pFM = new CFM_createPoint (m_pData,
FMPrintMessages);
        OnNewDocument();
   }
   ------------------------------------------------------------------------------------
   public void OnCreatePoint()
   { m_pFM = new CFM_createPoint (m_pData,
FMPrintMessages); InitializeFM(); }


   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  
CFM_base::
   ------------------------------------------------------------------------------------
   public delegate void FMPrintMessagesDelegate ();  // delegate declaration
   ------------------------------------------------------------------------------------
   public int pxs;
   public int cxs;
   public FMPrintMessagesDelegate
FMPrintMessages;   // save as data member
   public string
m_promptMessage;
   ------------------------------------------------------------------------------------
   public CFM_base (CData pData, FMPrintMessagesDelegate d)
   {
        m_pData = pData;
        this.
FMPrintMessages = d;
        pxs = 0;
        cxs = 1;
   }
   ------------------------------------------------------------------------------------
   public virtual void NXS ( int nxs = 0 )
   {
        int n = ( 0 == nxs ) ? cxs : nxs;
        pxs = cxs; cxs = n;
       
// Invoke delegate
        this.
FMPrintMessages ();
        CommonTaskForNXS ( nxs );
   }
   ------------------------------------------------------------------------------------
   public void FM_command (string s)
   {  m_pData.FM_command = s; }
   public void SystemFeedbackMessage (string s)
   {  m_pData.FM_systemFeedback = s; }
   public void PromptMessage (string s)
   {  m_pData.FM_prompt = s; }
   public void KeyinEchoMessage (string s)
   {  m_pData.FM_keyinEcho = s; }
   ------------------------------------------------------------------------------------
   public CFM_baseP (CData pData, FMPrintMessagesDelegate d) : base (pData, d)
   public CFM_baseT (CData pData, FMPrintMessagesDelegate d) : base (pData, d)


   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  
CFM_createPoint::     -- example --
   ------------------------------------------------------------------------------------
   public CFM_createPoint (CData pData, FMPrintMessagesDelegate d)
// constructor
             : base (pData, d)
   {
        
FM_command ( "FM Create Point" );
        NXS (1);
        SetSubmenu();
   }
   ------------------------------------------------------------------------------------
   public override void InitializeFM ()
   {
   }
   ------------------------------------------------------------------------------------
   public override void NXS (int nxs)
   {
        switch (nxs)
        {
             case 1:
                 
PromptMessage ( "Indicate to create a point" );
                  break;
             case 2:
                 
PromptMessage ( "Indicate to create another point" );
                  break;
             case 3:
                 
PromptMessage ( "Indicate to create yet another point )";
                  break;
         }
         base.NXS (nxs);  
// Call base function at the end
   }
   ------------------------------------------------------------------------------------
   public override void EventForIND ()
   {
        m_pData.m_elemNewlyCreatedList.Clear ();
        switch (nxs)
        {
             case 1:
                  CElemBase pE1 = new CElemBox3d ( . . . , m_ptIND, . . . );
                  m_pData.m_elemList.Add (pE1);
                  m_pData.m_elemNewlyCreatedList.Add (pE1);
                 
SystemFeedbackMessage ( "Box 3D created successfully" );
                  NXS (2);
                  break;
             case 2:
                  . . . . .
                 
break;
             case 3:
                  . . . . .
                 
break;
        }
        m_pData.m_OnDraw_flag = 1;  
// 1 = DrawAllElems, 2 = UndrawThisElem
   }

   Element Creation Paradigm         2011-June-10

   In this WPF system, the following element creation paradigm has been established.
  Whenever a new element is to be created, this paradigm must be followed:

   /////////////////////////////////////////////////////////////////////////////
   CView::UserControl_PreviewMouseLeftButtonDown (object sender, MouseButtonEventArgs e)
   {
        CFM_base pFM = m_pDoc.GetActiveFM ();
        pFM.EventForIND ();
        m_pDoc.OnDraw_WPF (m_pData.m_OnDrawFlag, this);
   }

   /////////////////////////////////////////////////////////////////////////////
   CFM_createElbow::EventForIND ()
   {
       
m_pData.CreateElbow (m_ptIND, 3, 5);
        NXS (2);
        InvalidateAllVpts_WPF (1);
 // Draw newly created elems in all viewports
    }

   /////////////////////////////////////////////////////////////////////////////
   CData::CreateElbow (pt, a, b)
   {
       
m_feedbackMessage = 1;
        FactoryForElemOnCP (ET_ELBOW, pt, a, b);
    }

   /////////////////////////////////////////////////////////////////////////////
   CData::FactoryForElemOnCP  / FactoryForCloneElem / FactoryForDittoElem
   {
       
pE = NewElem (type, pt, CurPlane.X, CurPlane.Y, a, b, c, d)
        RegisterNewElem (pE);
    }

   /////////////////////////////////////////////////////////////////////////////
   CData::NewElem  (type, pt, CurPlane.X, CurPlane.Y, a, b, c, d)
   {
       
switch (type)
        {
                case ET_POINT:
                         pE =
new CElemPoint (---);
                case ET_ELBOW:
                         pE =
new CElemElbow (---);
                case ET_BOX:
                         pE =
new CElemBox (---);
         }
    }

   /////////////////////////////////////////////////////////////////////////////
   CData::RegisterNewElem (pE)     /      RegisterNewDitto (pE))
   {
        m_pElemCur
= pE;
        m_elemList.Add (pE);
        m_elemNewlyCreatedList.Add (pE); 
// Cleared in OnDraw_WPF
    }

   /////////////////////////////////////////////////////////////////////////////
   CFM_base::InvalidateAllVpts_WPF (flag)
   {
        m_pData.m_OnDraw_flag = flag;
// 1 = DrawAllElems, 2 = UndrawThisElem
   }

   /////////////////////////////////////////////////////////////////////////////

 

   Visual Cue Display Scheme (1) --- Temporary Element / Lines        2011-June-19

   Temp elem (lines) are used in FM command for visual cues...

   /////////////////////////////////////////////////////////////////////////////
   CDoc::OnDraw_WPF
   {
         DrawAllElems (pV);
         DrawAbsoluteAxes (pV);
         DrawCurPlane (pV);
         DrawTempElem (pV);

      
 // Clear this list everytime
        m_pData.m_elemNewlyCreatedList.Clear();
   }
   CDoc::DrawTempElem (CView pV)
   {
        // Make sure to remove first...
        ScreenSpaceLines3D line1 = pV.m_tempLineWPF1;
        line1.Points.Clear ();
// importnt to clear
        pV.myViewport.Children.Remove(line1);

        ScreenSpaceLines3D line2 = pV.m_tempLineWPF2;
        line2.Points.Clear ();
// importnt to clear
        pV.myViewport.Children.Remove(line2);

      
 //----------------------------------------------------------- Line 1
        foreach (CPoint3D p in m_pData.m_tempLineWPFArraySingle1)
        {
             line1.Points.Add(pp1);
             line1.Points.Add(pp2);
        }
        foreach (CPoint3D p in m_pData.m_tempLineWPFArrayMulti1)
        {
             line1.Points.Add(pp1);
             line1.Points.Add(pp2);
        }
        line1.Thickness = m_pData.m_tempLineWPFThickness1;
        line1.Color = Colors.BlueViolet;
        pV.myViewport.Children.Add(line1);
       
//----------------------------------------------------------- Line 2
        //----------------------------------------------------------- Line 3

   }

   /////////////////////////////////////////////////////////////////////////////
   CView::
   {
         // IMPORTANT NOTE: These have to be declared here in View; cannot be in Doc
         // (nor in Data, for Data has no scope for Lines3D). If declared in Doc,
         // an exception is raised when there are more than one viewport, because
         // one instance of ScreenSpaceLines3D cannot be added to myViewport
         // of multiple Views. < 2011-6-19>

       
 // Temporary lines used by FM commands...
         public ScreenSpaceLines3D m_tempLineWPF1 = new ScreenSpaceLines3D();
         public ScreenSpaceLines3D m_tempLineWPF2 = new ScreenSpaceLines3D();
         public ScreenSpaceLines3D m_tempLineWPF3 = new ScreenSpaceLines3D();

       
 // Current plane & Keyin coordinnates...
         public ScreenSpaceLines3D m_visualCueCurPlane = new ScreenSpaceLines3D();
         public ScreenSpaceLines3D m_visualCueCoordRCS = new ScreenSpaceLines3D();

        
// Absolute axes (RGB)...
         public ScreenSpaceLines3D m_visualCueAbsAxisR = new ScreenSpaceLines3D();
         public ScreenSpaceLines3D m_visualCueAbsAxisG = new ScreenSpaceLines3D();
         public ScreenSpaceLines3D m_visualCueAbsAxisB = new ScreenSpaceLines3D();

       
 // Visual cues for real-time viewing...
         public ScreenSpaceLines3D m_visualCueViewing1 = new ScreenSpaceLines3D();
         public ScreenSpaceLines3D m_visualCueViewing2 = new ScreenSpaceLines3D();
         public ScreenSpaceLines3D m_visualCueViewing3 = new ScreenSpaceLines3D();
         public ScreenSpaceLines3D m_visualCueViewing4 = new ScreenSpaceLines3D();
         public ScreenSpaceLines3D m_visualCueViewing5 = new ScreenSpaceLines3D();
   }

   /////////////////////////////////////////////////////////////////////////////
   CData::
   {
      
 
//--------------------------------------- temp line 1
        public List<CPoint3D> m_tempLineWPFArraySingle1 = new List<CPoint3D>();
        public List<CPoint3D> m_tempLineWPFArrayMulti1 = new List<CPoint3D>();
        public int m_tempLineWPFColor1 = 1;
        public int m_tempLineWPFThickness1 = 1;
       
//--------------------------------------- temp line 2
        public List<CPoint3D> m_tempLineWPFArraySingle2 = new List<CPoint3D>();
        public List<CPoint3D> m_tempLineWPFArrayMulti2 = new List<CPoint3D>();
        public int m_tempLineWPFColor2 = 1;
        public int m_tempLineWPFThickness2 = 1;

   /////////////////////////////////////////////////////////////////////////////
   CFM_base::
TempLineWPFClear1, 2, 3 ()
   {
 
      m_pData.m_tempLineWPFArraySingle1.Clear ();
        m_pData.m_tempLineWPFArrayMulti1.Clear ();
   }
   CFM_base::
TempLineWPFStart1, 2, 3 (color, thickness)
   {
     
  m_pData.m_tempLineWPFColor1 = color;
        m_pData.m_tempLineWPFThickness1 = color;
   }
   CFM_base::
TempLineWPF1, 2, 3 (p1, p2)
   {
 
      m_pData.m_tempLineWPFArraySingle1.Add (p1);
        m_pData.m_tempLineWPFArraySingle1.Add (p2);
   }
   CFM_base::
TempLineWPFArray1, 2, 3 (int flag, CPoint3D[] pArray)
   {
 
      foreach (CPoint3D p in pArray) m_pData.m_tempLineWPFArrayMulti1.Add (p);
        if (flag == 1) m_pData.m_tempLineWPFArrayMulti1.Add(pArray[0]);
   }

   /////////////////////////////////////////////////////////////////////////////
   CFM_createBox::EventForIND ()
   {
 
      case 1:
            
TempLineWPFClearAll();
             // TempLineWPFClear1();
             // TempLineWPFClear2();

             m_pData.CreateBox(m_ptIND, 1.0, 0.5);
             SystemFeedbackMessage("Box created by IND");

             int color = 1;
             int thickness = 5;
            
TempLineWPFStart1 (color, thickness);

            
TempLineWPF1 (p1, m_ptIND);
            
TempLineWPF1 (p2, m_ptIND);

             CPoint3D[] pArray = {new CPoint3D(0, -1, -1),new CPoint3D(0, -1, -3),new CPoint3D(0, -2, -5) };
            
TempLineWPFArray1 (1, pArray); // flag = 1 : close loop

             NXS(2);
             break;

        InvalidateAllVpts_WPF (1);
    }

   Visual Cue Display Scheme (2) --- Viewing Free Rot/Pan/Zoom        2011-June-19

   Users: View::BeginRealTimeFreeRotation / FreePan / FreeZoom
              View::UserControl_PrevMouseRightButtonUp()

   /////////////////////////////////////////////////////////////////////////////
   CView::
  
{
         public ScreenSpaceLines3D m_visualCueViewing1 = new ScreenSpaceLines3D();
         public ScreenSpaceLines3D m_visualCueViewing2 = new ScreenSpaceLines3D();
         public ScreenSpaceLines3D m_visualCueViewing3 = new ScreenSpaceLines3D();
         public ScreenSpaceLines3D m_visualCueViewing4 = new ScreenSpaceLines3D();
         public ScreenSpaceLines3D m_visualCueViewing5 = new ScreenSpaceLines3D();
   }
   CView:: VisualCueViewingClear1()
  
{
        this.myViewport.Children.Remove (m_visualCueViewing1);
        m_visualCueViewing1.Points.Clear ();
   }
   CView:: VisualCueViewingStart1 (Color color, int thickness)
   {
        m_visualCueViewing1.Color = color;
        m_visualCueViewing1.Thickness = thickness;
   }
   CView:: VisualCueViewingPoint1 (p1, p2)
   {
        ViewingVisCuePoint1 (pp1, pp2);
   }
   CView:: VisualCueViewingEnd1 ()
   {
        this.myViewport.Children.Add (m_visualCueViewing1);
   }

   Visual Cue Display Scheme (3) --- Key-in Coordinate Rect/Cyl/Sph        2011-June-20

   Visual cue for the key-in coordinate is issued by Main:: txtKeyinPad_TextChanged(

   /////////////////////////////////////////////////////////////////////////////
   CView::
  
{
        public ScreenSpaceLines3D m_visualCueCoordRCS = new ScreenSpaceLines3D();
   }
   /////////////////////////////////////////////////////////////////////////////
   CDoc:: DrawCoordinateRCS (CView pV)
   {
       
// Clear first....
       
ClearCoordianteRCS ()
        ScreenSpaceLines3D line= pV.m_visualCueCoordRCS;

        line.Thickness = width;
        line.Color = c;

        line.Points.Add(p0);
        line.Points.Add(p1);

        pV.myViewport.Children.Add (line);
   }
   CDoc:: ClearCoordianteRCS(CView pV)
// One viewport
   {
        pV.myViewport.Children.Remove (pV.m_visualCueCoordRCS);
        m_visualCueCurPlane.Points.Clear ();
// importnt to clear
   }
   /////////////////////////////////////////////////////////////////////////////
   Main:: txtKeyinPad_TextChanged(object sender, TextChangedEventArgs e)
   {
        try
        {
            
// Clear temp display... only after ENTER
             m_pDoc.ClearCoordianteRCS();
// All vpts
             m_pDoc.m_pFM.m_ptKEY3 = m_pDoc.GetKeyCoordinate(); 

   /////////////////////////////////////////////////////////////////////////////
   CDoc:: GetKeyCoordinate()
   {
         DrawCoordinateRCS();
// All vpts
         return ptAbs;
   }

   Visual Cue Display Scheme (4) --- Current Plane        2011-June-20

   Current plane must be redrawn every time....

   /////////////////////////////////////////////////////////////////////////////
   CView::
  
{
        public ScreenSpaceLines3D m_visualCueCurPlane = new ScreenSpaceLines3D();
   }
   /////////////////////////////////////////////////////////////////////////////
   CDoc:: OnDraw_WPF
   {
        DrawAllElems (pV);
        DrawAbsoluteAxes (pV);
        DrawCurPlane (pV);
        DrawTempElem (pV);
   }
   CDoc:: DrawCurPlane (CView pV)
   {
        // Clear first....
   
    ClearCurPlane(pV);

        ScreenSpaceLines3D line= pV.m_visualCueCurPlane;
        line.Thickness = width;
        line.Color = c;

        line.Points.Add(p0);
        line.Points.Add(p1);

        pV.myViewport.Children.Add (line);
   }
   CDoc:: ClearCurPlane(CView pV)
// One viewport
   {
        pV.myViewport.Children.Remove(pV.m_visualCueCurPlane);
        pV.m_visualCueCurPlane.Points.Clear();
   }
   /////////////////////////////////////////////////////////////////////////////
   CDoc:: OnCurPlaneXy/Xz/Zy()
   {
        m_pData.m_pCurPlane.SetPresetPlaneXY();
        DrawCurPlane();
// All vpts
   }

   Event Generation Sites       2011-June-21

   Events are generated from two places: MainWindow and CView.

 
Main Window
   /////////////////////////////////////////////////////////////////////////////
   1.  Menu Event

        Main:: miOrthoXY_Click ()
          
        ----------> Doc:: OnOrthoUtilityXY ()
        Main:: miOrthoXZ_Click ()
          
        ----------> Doc:: OnOrthoUtilityXZ ()
        Main:: miCreateBox_Click ()
          
        ----------> Doc:: OnFMCreateBox () ---> m_pFM = new CFM_createBox
        Main:: miElemRotate ()
          
        ----------> Doc:: OnFMElemRotate () --->  m_pFM = new CFM_elemRotate

   /////////////////////////////////////////////////////////////////////////////
   2.  Key Event

        Main:: Window_PreviewKeyDown ()

                  
BEFORE_EventForInitialize ()
                   ----------> View:: OnMMZoomLensAngle (delta);
                   ----------> View:: OnMMPanTurnHead (delta);
                   ----------> View:: OnMMZoomMoveCamera (delta);
                   ----------> FM::
EventForESC ()
                   ----------> FM::
EventForDEL ()
                   ----------> FM::
EventForTAB ()
                   ----------> FM::
EventForSPACE ()
                   ----------> FM::
EventForARROW
                  
AFTER_EventForOnDraw ()

   /////////////////////////////////////////////////////////////////////////////
   3.  Coordinate Key-in Event

        Main:: txtKeyinPad_TextChanged (txtKeyinPad_PreviewKeyDown)

                  
BEFORE_EventForInitialize ()
                   ----------> FM::
EventForKEY3 ()
                   ----------> FM::
EventForKEY2 ()
                   ----------> FM::
EventForKEY1 ()
                   ----------> FM::
EventForDEFPT ()
                  
AFTER_EventForOnDraw ()

   /////////////////////////////////////////////////////////////////////////////
   Main:: private CView
BEFORE_EventForInitialize()
   {
        m_pDoc.m_pData.m_OnDraw_flag = 0;
        CView pV = GetActiveViewport (); 
// Initialize flag to 0 before EventForXXX
        m_pDoc.m_pViewEvent = pV; 
// view pointer of event-origin
        return pV;
   }
   Main:: private void
AFTER_EventForOnDraw()
   {
        m_pDoc.OnDraw_WPF ();  // All vpts
        txtKeyinPad.Focus();
   }


 
CView
   /////////////////////////////////////////////////////////////////////////////
   1.  Mouse Button Down / Up Event

        View:: UserControl_PreviewMouseLeftButtonDown
                  
BEFORE_EventForInitialize ()
                   BeginRealTimeFreeRotation (p)
                   ----------> FM::
EventForLBD ()
                   ----------> FM::
EventForDEFPT ()
                  
AFTER_EventForOnDraw ()
        View:: UserControl_PreviewMouseLeftButtonUp
                   BeginRealTimeFreePan (p)
                   BeginRealTimeFreeZoom (p)
                   ----------> FM::
EventForLBU ()
        View:: UserControl_PreviewMouseRightButtonDown
                  
BEFORE_EventForInitialize ()
                   ----------> FM::
EventForRBD ()
                  
AFTER_EventForOnDraw ()
        View:: UserControl_PreviewMouseRightButtonUp
                 
 ----------> FM::
EventForRBU ()
        View:: UserControl_PreviewMouseDoubleClick
                 
 ----------> FM::
EventForLB2 ()
                   ----------> FM::
EventForRB2 ()

   /////////////////////////////////////////////////////////////////////////////
   2.  Mouse Move Event

        View:: UserControl_PreviewMouseMove
                 
 ----------> FM::
EventForMMV ()
                   ----------> OnMMPanSameOrien ()
                   ----------> OnMMPanTurnHead ()
                   ----------> OnMMZoomLensAngle ()
                   ----------> OnMMZoomMoveCamera ()

   /////////////////////////////////////////////////////////////////////////////
   3.  Viewport Size Changed Event

       View:: UserControl_SizeChanged
                      
SetVptPixelSizeXYandRatio();
                       Setup2Projection();
                       Setup2UpVector();
                       UpdateVptExtentAndSizes();

   /////////////////////////////////////////////////////////////////////////////
   View:: private void BEFORE_EventForInitialize ()
   {
  
     m_pDoc.m_pData.m_OnDraw_flag = 0;  // Initialize flag to 0 before EventForXXX
        m_pDoc.m_pViewEvent = this; 
// view pointer of event-origin
   }
   View:: private void
AFTER_EventForOnDraw ()
   {
        m_pDoc.OnDraw_WPF (this);
        lblViewCaption2.Content = DateTime.Now.ToString();
   }

   WPF 3D Rendering Scheme Revisited         2011-December-30

-----------------------------------------------------------------

    public void OnDraw_WPF(CView pVOnlyOne = null)
    {
        // This is always called after EventForXXX. FM processing the EventForXXX
        // sets the flag via ....

        if (bAllElems)
        { //------------------(1)----------------------- All elems
            foreach (CElemBase1D pE in m_pData.m_elemList)
            {
                // Check each elem's render capability...
                SetRenderFlags(flag, pE, out nWire, out nShade);
                if (nShade > 0) geo = CreateGeometryModel3D(pE); // Common for Draw & Modify
                if (nWire > 0) pE.GenerateVerticesAndCreateWPFcalls(out n2, out vec2, out n3, out vec3, out segArray);
                if (bAllVpts)
                { // ------------------------------ All vpts
                    foreach (CView pV in m_viewList)
                    {
                         Render(pE, pV, geo, n2, vec2, n3, vec3, segArray, nShade, nWire, bModify, bDelete);
                         DrawTempElemOneVpt(pV);

-----------------------------------------------------------------

    public GeometryModel3D CreateGeometryModel3D(CElemBase pE)
    {
-----------------------------------------------------------------

    public void Render(CElemBase pE, CView pV,
    GeometryModel3D geo, int n2, CPoint3D[,] vec2, int n3, CPoint3D[,] vec3, int[] segArray,
    uint nShade, uint nWire, bool bModify, bool bDelete = false)
    {
        // This is the low-level WPF3D renderer. The value of nShade and nWire controls
        // the rendering. 1 for single-render-object, 2 for multi-render-objects. Either 1 or 2
-----------------------------------------------------------------

    /////////////////////////////////////////////////////////////////77//////////
    public void CREATE_SINGLE_SHADE(CElemBase pE, CView pV, GeometryModel3D geo)
    {
        ModelVisual3DG model = new ModelVisual3DG();
        model.Content = geo;
        //----------------------------- Apply "Transform" property
        CViewMatrix m = pE.GetMatrix(); // elem's own matrix
        Matrix3D mx = new Matrix3D(m.Xx, m.Xy, m.Xz, 0, m.Yx, m.Yy, m.Yz, 0, m.Zx, m.Zy, m.Zz, 0, m.Ox, m.Oy, m.Oz, 1);
        MatrixTransform3D tran = new MatrixTransform3D(mx);
        //----------------------------- Apply "Transform" property
        model.Transform = tran;
        pV.myViewport.Children.Add(model);
        model.m_pElem = pE; // save "data structure" pointer in "render"
        pE.m_singleShadeDict.Add(pV, model); // save "render" side pointer
    }
    public void MODIFY_SINGLE_SHADE(CElemBase pE, CView pV)
    {
        ModelVisual3D model = pE.m_singleShadeDict[pV];
        //--- GeometryModel3D geo = CreateGeometryModel3D(pE);
        //--- model.Content = geo;
        // This modify only works for "Transform" property change...
        CViewMatrix m = pE.GetMatrix(); // elem's own matrix
        Matrix3D mx = new Matrix3D(m.Xx, m.Xy, m.Xz, 0, m.Yx, m.Yy, m.Yz, 0, m.Zx, m.Zy, m.Zz, 0, m.Ox, m.Oy, m.Oz, 1);
        MatrixTransform3D tran = new MatrixTransform3D(mx);
        model.Transform = tran;
    }
    public void DELETE_SINGLE_SHADE(CElemBase pE, CView pV)
    {
        ModelVisual3D model = pE.m_singleShadeDict[pV];
        pV.myViewport.Children.Remove(model);
    }
    public void HIDE_SINGLE_SHADE(CElemBase pE, CView pV)
    public void UNHIDE_SINGLE_SHADE(CElemBase pE, CView pV)
    /////////////////////////////////////////////////////////////////77//////////
    public void CREATE_MULTI_SHADE(CElemBase pE, CView pV, int[] segArray, CPoint3D[,] vec2)
    public void MODIFY_MULTI_SHADE(CElemBase pE, CView pV)
    public void DELETE_MULTI_SHADE(CElemBase pE, CView pV)
    public void HIDE_MULTI_SHADE(CElemBase pE, CView pV)
    public void UNHIDE_MULTI_SHADE(CElemBase pE, CView pV)
    /////////////////////////////////////////////////////////////////77//////////
    public void CREATE_SINGLE_WIRE(CElemBase pE, CView pV, int n2, CPoint3D[,] vec2)
    public void MODIFY_SINGLE_WIRE(CElemBase pE, CView pV)
    public void DELETE_SINGLE_WIRE(CElemBase pE, CView pV)
    public void HIDE_SINGLE_WIRE(CElemBase pE, CView pV)
    public void UNHIDE_SINGLE_WIRE(CElemBase pE, CView pV)
    /////////////////////////////////////////////////////////////////77//////////
    public void CREATE_MULTI_WIRE(CElemBase pE, CView pV, int[] segArray, CPoint3D[,] vec2)
    public void MODIFY_MULTI_WIRE(CElemBase pE, CView pV)
    public void DELETE_MULTI_WIRE(CElemBase pE, CView pV)
    public void HIDE_MULTI_WIRE(CElemBase pE, CView pV)
    public void UNHIDE_MULTI_WIRE(CElemBase pE, CView pV)

   Free View Rotation Schemes        2012-February-02

   1.  Delta Rotation
   /////////////////////////////////////////////////////////////////////////////
   Use cursor's X Y delta. Location-transparent. Always 3D rotation.

   2.  Trackball
   /////////////////////////////////////////////////////////////////////////////
   If Pt.1 is within CircleA, initiate 3D rotation. If outside, initiate 2D rotation. CircleA is 90% of the screen.
   Once initiated, the rotation mode remains in effect until the mouse button is released.

   3.  Trackball
   /////////////////////////////////////////////////////////////////////////////
   If Pt.1 is within CircleA, initiate 3D rotation. If outside, see if Vector1-2 goes through CircleB. If it does, 3D, else 2D.
   CircleA is 50% of the screen. CircleB is the same as CircleA or smaller.
   Once initiated, the rotation mode remains in effect until the mouse button is released.

  

 

 

CAD System Web Site - Computer Aided Design Software:  Copyright 2010-2013 Makoto Honda. All Rights Reserved.  

 

   

Copyright 2010-2013 Makoto Honda. All Rights Reserved.                                       www.iNET1000.com