Author Topic: Polyface Mesh to 3dFace in .net  (Read 6060 times)

0 Members and 1 Guest are viewing this topic.

AARYAN

  • Newt
  • Posts: 72
Polyface Mesh to 3dFace in .net
« on: December 12, 2014, 06:12:50 AM »
Hello All,

Please Help.

I have found this code from the google search for Triangulation of Points.

http://through-the-interface.typepad.com/through_the_interface/2009/04/triangulating-an-autocad-polyface-mesh-from-a-set-of-points-using-net.html

But It only works with limited points because of the restrictions with Polyface mesh.

Can anyone PLEASE update the code to draw 3d Faces rather than the Polyface mesh.

Thanks in Advance.

Regards

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Polyface Mesh to 3dFace in .net
« Reply #1 on: December 12, 2014, 07:57:39 AM »
Hi,

Largely inspired by this later thread from Kean, here's what I use to create either a Polyface, a SubDmesh, a 3d Solid or 3d Faces.

Code - C#: [Select]
  1. using System;
  2. using System.Linq;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.Geometry;
  5. using Autodesk.AutoCAD.Runtime;
  6. using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
  7.  
  8. namespace DelaunayTriangulation
  9. {
  10.     class Triangulation
  11.     {
  12.         private int npts, ntri, nouted;
  13.         private int[] pt1, pt2, pt3, ed1, ed2, outed1;
  14.         private double[] ptx, pty, ptz;
  15.         private bool createSolid;
  16.         private double zref;
  17.  
  18.         public Triangulation(ObjectId[] ids, bool createSolid, double zref)
  19.         {
  20.             this.createSolid = createSolid;
  21.             this.zref = zref;
  22.             Triangulate(ids);
  23.             Count = ntri;
  24.         }
  25.  
  26.         public Triangulation(ObjectId[] ids)
  27.             : this(ids, false, 0.0) { }
  28.  
  29.         public int Count { get; private set; }
  30.  
  31.         public int MakeFaces()
  32.         {
  33.             Database db = HostApplicationServices.WorkingDatabase;
  34.             using (Transaction tr = db.TransactionManager.StartTransaction())
  35.             {
  36.                 BlockTableRecord btr =
  37.                     (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite);
  38.                 for (int i = 0; i < ntri; i++)
  39.                 {
  40.                     using (Face face = new Face(
  41.                         new Point3d(ptx[pt1[i]], pty[pt1[i]], ptz[pt1[i]]),
  42.                         new Point3d(ptx[pt2[i]], pty[pt2[i]], ptz[pt2[i]]),
  43.                         new Point3d(ptx[pt3[i]], pty[pt3[i]], ptz[pt3[i]]),
  44.                         true, true, true, true))
  45.                     {
  46.                         btr.AppendEntity(face);
  47.                         tr.AddNewlyCreatedDBObject(face, true);
  48.                     }
  49.                 }
  50.                 tr.Commit();
  51.             }
  52.             return ntri;
  53.         }
  54.  
  55.         public void MakePolyFaceMesh()
  56.         {
  57.             Database db = HostApplicationServices.WorkingDatabase;
  58.             using (Transaction tr = db.TransactionManager.StartTransaction())
  59.             {
  60.                 BlockTableRecord btr =
  61.                     (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite);
  62.                 using (PolyFaceMesh pfm = new PolyFaceMesh())
  63.                 {
  64.                     btr.AppendEntity(pfm);
  65.                     tr.AddNewlyCreatedDBObject(pfm, true);
  66.                     for (int i = 0; i < npts; i++)
  67.                     {
  68.                         using (PolyFaceMeshVertex vert =
  69.                             new PolyFaceMeshVertex(new Point3d(ptx[i], pty[i], ptz[i])))
  70.                         {
  71.                             pfm.AppendVertex(vert);
  72.                         }
  73.                     }
  74.                     for (int i = 0; i < ntri; i++)
  75.                     {
  76.                         using (FaceRecord face =
  77.                             new FaceRecord((short)(pt1[i] + 1), (short)(pt2[i] + 1), (short)(pt3[i] + 1), 0))
  78.                         {
  79.                             pfm.AppendFaceRecord(face);
  80.                         }
  81.                     }
  82.                 }
  83.                 tr.Commit();
  84.             }
  85.         }
  86.  
  87.         public void MakeSubDMesh()
  88.         {
  89.             Point3dCollection vertices = new Point3dCollection();
  90.             Int32Collection faces = new Int32Collection();
  91.  
  92.             for (int i = 0; i < npts; i++)
  93.                 vertices.Add(new Point3d(ptx[i], pty[i], ptz[i]));
  94.  
  95.             for (int i = 0; i < ntri; i++)
  96.             {
  97.                 faces.Add(3);
  98.                 faces.Add(pt1[i]);
  99.                 faces.Add(pt2[i]);
  100.                 faces.Add(pt3[i]);
  101.             }
  102.  
  103.             Database db = HostApplicationServices.WorkingDatabase;
  104.             using (Transaction tr = db.TransactionManager.StartTransaction())
  105.             {
  106.                 BlockTableRecord btr =
  107.                     (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite);
  108.                 using (SubDMesh sdm = new SubDMesh())
  109.                 {
  110.                     sdm.SetDatabaseDefaults();
  111.                     sdm.SetSubDMesh(vertices, faces, 0);
  112.                     btr.AppendEntity(sdm);
  113.                     tr.AddNewlyCreatedDBObject(sdm, true);
  114.                 }
  115.                 tr.Commit();
  116.             }
  117.         }
  118.  
  119.         public void MakeSolid3d()
  120.         {
  121.             Point3dCollection vertices = new Point3dCollection();
  122.             Int32Collection faces = new Int32Collection();
  123.  
  124.             for (int i = 0; i < npts; i++)
  125.                 vertices.Add(new Point3d(ptx[i], pty[i], ptz[i]));
  126.  
  127.             for (int i = 0; i < nouted; i++)
  128.                 vertices.Add(new Point3d(ptx[ed1[outed1[i]]], pty[ed1[outed1[i]]], zref));
  129.  
  130.             for (int i = 0; i < ntri; i++)
  131.             {
  132.                 faces.Add(3);
  133.                 faces.Add(pt1[i]);
  134.                 faces.Add(pt2[i]);
  135.                 faces.Add(pt3[i]);
  136.             }
  137.  
  138.             for (int i = 0; i < nouted; i++)
  139.             {
  140.                 faces.Add(4);
  141.                 int k = outed1[i];
  142.                 faces.Add(ed1[k]);
  143.                 faces.Add(ed2[k]);
  144.                 if (i == nouted - 1)
  145.                 {
  146.                     faces.Add(npts);
  147.                 }
  148.                 else
  149.                 {
  150.                     faces.Add(npts + i + 1);
  151.                 }
  152.                 faces.Add(npts + i);
  153.             }
  154.             faces.Add(nouted);
  155.             for (int i = 0; i < nouted; i++)
  156.                 faces.Add(npts + i);
  157.             Database db = HostApplicationServices.WorkingDatabase;
  158.             using (Transaction tr = db.TransactionManager.StartTransaction())
  159.             {
  160.                 BlockTableRecord btr =
  161.                     (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite);
  162.                 using (SubDMesh sdm = new SubDMesh())
  163.                 {
  164.                     sdm.SetDatabaseDefaults();
  165.                     sdm.SetSubDMesh(vertices, faces, 0);
  166.                     btr.AppendEntity(sdm);
  167.                     tr.AddNewlyCreatedDBObject(sdm, true);
  168.                     try
  169.                     {
  170.                         using (Solid3d sol = sdm.ConvertToSolid(false, false))
  171.                         {
  172.                             btr.AppendEntity(sol);
  173.                             tr.AddNewlyCreatedDBObject(sol, true);
  174.                         }
  175.                     }
  176.                     catch
  177.                     {
  178.                         AcAp.DocumentManager.MdiActiveDocument.Editor.WriteMessage(
  179.                             "\nMesh was too complex to turn into a solid.");
  180.                     }
  181.                     sdm.Erase();
  182.                 }
  183.                 tr.Commit();
  184.             }
  185.         }
  186.  
  187.         private bool circum(double x1, double y1, double x2, double y2, double x3, double y3, ref double xc, ref double yc, ref double r)
  188.         {
  189.             const double eps = 1e-6;
  190.             const double big = 1e12;
  191.             bool result = true;
  192.             double m1, m2, mx1, mx2, my1, my2, dx, dy;
  193.  
  194.             if ((Math.Abs(y1 - y2) < eps) && (Math.Abs(y2 - y3) < eps))
  195.             {
  196.                 result = false;
  197.                 xc = x1; yc = y1; r = big;
  198.             }
  199.             else
  200.             {
  201.                 if (Math.Abs(y2 - y1) < eps)
  202.                 {
  203.                     m2 = -(x3 - x2) / (y3 - y2);
  204.                     mx2 = (x2 + x3) / 2;
  205.                     my2 = (y2 + y3) / 2;
  206.                     xc = (x2 + x1) / 2;
  207.                     yc = m2 * (xc - mx2) + my2;
  208.                 }
  209.                 else if (Math.Abs(y3 - y2) < eps)
  210.                 {
  211.                     m1 = -(x2 - x1) / (y2 - y1);
  212.                     mx1 = (x1 + x2) / 2;
  213.                     my1 = (y1 + y2) / 2;
  214.                     xc = (x3 + x2) / 2;
  215.                     yc = m1 * (xc - mx1) + my1;
  216.                 }
  217.                 else
  218.                 {
  219.                     m1 = -(x2 - x1) / (y2 - y1);
  220.                     m2 = -(x3 - x2) / (y3 - y2);
  221.                     if (Math.Abs(m1 - m2) < eps)
  222.                     {
  223.                         result = false;
  224.                         xc = x1;
  225.                         yc = y1;
  226.                         r = big;
  227.                     }
  228.                     else
  229.                     {
  230.                         mx1 = (x1 + x2) / 2;
  231.                         mx2 = (x2 + x3) / 2;
  232.                         my1 = (y1 + y2) / 2;
  233.                         my2 = (y2 + y3) / 2;
  234.                         xc = (m1 * mx1 - m2 * mx2 + my2 - my1) / (m1 - m2);
  235.                         yc = m1 * (xc - mx1) + my1;
  236.                     }
  237.                 }
  238.             }
  239.             dx = x2 - xc;
  240.             dy = y2 - yc;
  241.             r = dx * dx + dy * dy;
  242.             return result;
  243.         }
  244.  
  245.         private void Triangulate(ObjectId[] ids)
  246.         {
  247.             Point3d[] pts = new Point3d[ids.Length];
  248.             Database db = HostApplicationServices.WorkingDatabase;
  249.             using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
  250.             {
  251.                 pts = ids
  252.                     .Select(id => ((DBPoint)tr.GetObject(id, OpenMode.ForRead)).Position)
  253.                     .Distinct()
  254.                     .ToArray();
  255.             }
  256.  
  257.             npts = ids.Length;
  258.  
  259.             if (npts < 3)
  260.                 throw new ArgumentException("Minimum of 3 points must be selected!");
  261.  
  262.             ProgressMeter progress = new ProgressMeter();
  263.             progress.SetLimit(npts);
  264.             progress.Start("Triangulation...");
  265.             progress.SetLimit(npts);
  266.  
  267.             int i, j, k, ned, status1 = 0;
  268.             bool status;
  269.  
  270.             // Point coordinates
  271.             ptx = new double[npts + 3];
  272.             pty = new double[npts + 3];
  273.             ptz = new double[npts + 3];
  274.  
  275.             // Triangle definitions
  276.             pt1 = new int[npts * 2 + 1];
  277.             pt2 = new int[npts * 2 + 1];
  278.             pt3 = new int[npts * 2 + 1];
  279.  
  280.             // Circumscribed circle
  281.             double[] cex = new double[npts * 2 + 1];
  282.             double[] cey = new double[npts * 2 + 1];
  283.             double[] rad = new double[npts * 2 + 1];
  284.             double xmin, ymin, xmax, ymax, dx, dy, xmid, ymid, dmax;
  285.             ed1 = new int[npts * 2 + 1];
  286.             ed2 = new int[npts * 2 + 1];
  287.             if (createSolid)
  288.                 outed1 = new int[npts + 1];
  289.  
  290.             k = 0;
  291.             for (i = 0; i < npts; i++)
  292.             {
  293.                 Point3d pt = pts[i];
  294.                 ptx[i] = pt.X;
  295.                 pty[i] = pt.Y;
  296.                 ptz[i] = pt.Z;
  297.                 k++;
  298.             }
  299.  
  300.             // Supertriangle
  301.             xmin = ptx[0]; xmax = xmin;
  302.             ymin = pty[0]; ymax = ymin;
  303.             for (i = 0; i < npts; i++)
  304.             {
  305.                 if (ptx[i] < xmin) xmin = ptx[i];
  306.                 if (ptx[i] > xmax) xmax = ptx[i];
  307.                 if (pty[i] < xmin) ymin = pty[i];
  308.                 if (pty[i] > xmin) ymax = pty[i];
  309.             }
  310.  
  311.             dx = xmax - xmin;
  312.             dy = ymax - ymin;
  313.             dmax = dx < dy ? dy : dx;
  314.             xmid = (xmin + xmax) / 2; ymid = (ymin + ymax) / 2;
  315.             i = npts;
  316.             ptx[i] = xmid - 2 * dmax;
  317.             pty[i] = ymid - dmax;
  318.             ptz[i] = 0;
  319.             pt1[0] = i;
  320.             i++;
  321.             ptx[i] = xmid + 2 * dmax;
  322.             pty[i] = ymid - dmax;
  323.             ptz[i] = 0;
  324.             pt2[0] = i;
  325.             i++;
  326.             ptx[i] = xmid;
  327.             pty[i] = ymid + 2 * dmax;
  328.             ptz[i] = 0;
  329.             pt3[0] = i;
  330.             ntri = 1;
  331.             circum(
  332.                 ptx[pt1[0]], pty[pt1[0]], ptx[pt2[0]],
  333.                 pty[pt2[0]], ptx[pt3[0]], pty[pt3[0]],
  334.                 ref cex[0], ref cey[0], ref rad[0]
  335.                 );
  336.  
  337.             // Main loop
  338.             for (i = 0; i < npts; i++)
  339.             {
  340.                 progress.MeterProgress();
  341.  
  342.                 ned = 0;
  343.                 xmin = ptx[i]; ymin = pty[i];
  344.                 j = 0;
  345.                 while (j < ntri)
  346.                 {
  347.                     dx = cex[j] - xmin; dy = cey[j] - ymin;
  348.                     if (((dx * dx) + (dy * dy)) < rad[j])
  349.                     {
  350.                         ed1[ned] = pt1[j]; ed2[ned] = pt2[j];
  351.                         ned++;
  352.                         ed1[ned] = pt2[j]; ed2[ned] = pt3[j];
  353.                         ned++;
  354.                         ed1[ned] = pt3[j]; ed2[ned] = pt1[j];
  355.                         ned++;
  356.                         ntri--;
  357.                         pt1[j] = pt1[ntri];
  358.                         pt2[j] = pt2[ntri];
  359.                         pt3[j] = pt3[ntri];
  360.                         cex[j] = cex[ntri];
  361.                         cey[j] = cey[ntri];
  362.                         rad[j] = rad[ntri];
  363.                         j--;
  364.                     }
  365.                     j++;
  366.                 }
  367.  
  368.                 for (j = 0; j < ned - 1; j++)
  369.                     for (k = j + 1; k < ned; k++)
  370.                         if ((ed1[j] == ed2[k]) && (ed2[j] == ed1[k]))
  371.                         {
  372.                             ed1[j] = -1;
  373.                             ed2[j] = -1;
  374.                             ed1[k] = -1;
  375.                             ed2[k] = -1;
  376.                         }
  377.  
  378.                 for (j = 0; j < ned; j++)
  379.                     if ((ed1[j] >= 0) && (ed2[j] >= 0))
  380.                     {
  381.                         pt1[ntri] = ed1[j];
  382.                         pt2[ntri] = ed2[j];
  383.                         pt3[ntri] = i;
  384.                         status = circum(
  385.                             ptx[pt1[ntri]], pty[pt1[ntri]], ptx[pt2[ntri]],
  386.                             pty[pt2[ntri]], ptx[pt3[ntri]], pty[pt3[ntri]],
  387.                             ref cex[ntri], ref cey[ntri], ref rad[ntri]
  388.                             );
  389.                         if (!status)
  390.                         {
  391.                             status1++;
  392.                         }
  393.                         ntri++;
  394.                     }
  395.             }
  396.  
  397.             // Removal of outer triangles
  398.             i = 0;
  399.             nouted = 0;
  400.             while (i < ntri)
  401.             {
  402.                 if ((pt1[i] >= npts) || (pt2[i] >= npts) || (pt3[i] >= npts))
  403.                 {
  404.                     if (createSolid)
  405.                     {
  406.                         if ((pt1[i] >= npts) && (pt2[i] < npts) && (pt3[i] < npts))
  407.                         {
  408.                             ed1[nouted] = pt2[i];
  409.                             ed2[nouted] = pt3[i];
  410.                             nouted++;
  411.                         }
  412.                         if ((pt2[i] >= npts) && (pt1[i] < npts) && (pt3[i] < npts))
  413.                         {
  414.                             ed1[nouted] = pt3[i];
  415.                             ed2[nouted] = pt1[i];
  416.                             nouted++;
  417.                         }
  418.                         if ((pt3[i] >= npts) && (pt1[i] < npts) && (pt2[i] < npts))
  419.                         {
  420.                             ed1[nouted] = pt1[i];
  421.                             ed2[nouted] = pt2[i];
  422.                             nouted++;
  423.                         }
  424.                     }
  425.                     ntri--;
  426.                     pt1[i] = pt1[ntri];
  427.                     pt2[i] = pt2[ntri];
  428.                     pt3[i] = pt3[ntri];
  429.                     cex[i] = cex[ntri];
  430.                     cey[i] = cey[ntri];
  431.                     rad[i] = rad[ntri];
  432.                     i--;
  433.                 }
  434.                 i++;
  435.             }
  436.  
  437.             if (createSolid)
  438.             {
  439.                 outed1[0] = 0;
  440.                 for (i = 1; i < nouted; i++)
  441.                     for (j = 1; j < nouted; j++)
  442.                         if (ed2[outed1[i - 1]] == ed1[j])
  443.                         {
  444.                             outed1[i] = j;
  445.                             j = nouted;
  446.                         }
  447.                 outed1[nouted] = 0;
  448.             }
  449.  
  450.             progress.Stop();
  451.         }
  452.     }
  453. }

<Edit: replaced ObjectId.Open() with Transaction.GetObject()>
« Last Edit: December 15, 2014, 01:39:06 AM by gile »
Speaking English as a French Frog

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Polyface Mesh to 3dFace in .net
« Reply #2 on: December 12, 2014, 07:58:24 AM »
And here're some testing commands

Code - C#: [Select]
  1. // (C) Copyright 2012 by Gilles Chanteau
  2. //
  3. using System;
  4. using Autodesk.AutoCAD.ApplicationServices;
  5. using Autodesk.AutoCAD.DatabaseServices;
  6. using Autodesk.AutoCAD.EditorInput;
  7. using Autodesk.AutoCAD.Geometry;
  8. using Autodesk.AutoCAD.Runtime;
  9. using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
  10.  
  11. [assembly: CommandClass(typeof(DelaunayTriangulation.CommandMethods))]
  12.  
  13. namespace DelaunayTriangulation
  14. {
  15.     public class CommandMethods
  16.     {
  17.         Editor ed = AcAp.DocumentManager.MdiActiveDocument.Editor;
  18.  
  19.         [CommandMethod("TRIANG_FACE3D", CommandFlags.Modal | CommandFlags.UsePickSet)]
  20.         public void ToFace3d()
  21.         {
  22.             ObjectId[] ids = SelectPoints();
  23.             if (ids == null)
  24.                 return;
  25.  
  26.             try
  27.             {
  28.                 Triangulation triangles = new Triangulation(ids);
  29.                 triangles.MakeFaces();
  30.             }
  31.             catch (System.Exception ex)
  32.             {
  33.                 ed.WriteMessage(ex.Message + ex.StackTrace);
  34.             }
  35.         }
  36.  
  37.         [CommandMethod("TRIANG_POLYFACE", CommandFlags.Modal | CommandFlags.UsePickSet)]
  38.         public void ToPolyFaceMesh()
  39.         {
  40.             ObjectId[] ids = SelectPoints();
  41.             if (ids == null)
  42.                 return;
  43.  
  44.             if (ids.Length > 32767)
  45.             {
  46.                 AcAp.ShowAlertDialog("Maximum number of points (32767) exceeded!");
  47.                 return;
  48.             }
  49.  
  50.             try
  51.             {
  52.                 Triangulation triangles = new Triangulation(ids);
  53.                 triangles.MakePolyFaceMesh();
  54.             }
  55.             catch (System.Exception ex)
  56.             {
  57.                 ed.WriteMessage(ex.Message + ex.StackTrace);
  58.             }
  59.         }
  60.  
  61.         [CommandMethod("TRIANG_SUBDMESH", CommandFlags.Modal | CommandFlags.UsePickSet)]
  62.         public void ToSubDMesh()
  63.         {
  64.             ObjectId[] ids = SelectPoints();
  65.             if (ids == null)
  66.                 return;
  67.  
  68.             try
  69.             {
  70.                 Triangulation triangles = new Triangulation(ids);
  71.                 triangles.MakeSubDMesh();
  72.             }
  73.             catch (System.Exception ex)
  74.             {
  75.                 ed.WriteMessage(ex.Message + ex.StackTrace);
  76.             }
  77.         }
  78.  
  79.         [CommandMethod("TRIANG_SOLID3D", CommandFlags.Modal | CommandFlags.UsePickSet)]
  80.         public void ToSolid3d()
  81.         {
  82.             ObjectId[] ids = SelectPoints();
  83.             if (ids == null)
  84.                 return;
  85.  
  86.             PromptDoubleOptions pdo = new PromptDoubleOptions(
  87.                 "\nEnter Z coordinate of reference plane: ");
  88.             pdo.AllowZero = true;
  89.             pdo.DefaultValue = 0.0;
  90.             pdo.UseDefaultValue = true;
  91.             PromptDoubleResult pdr = ed.GetDouble(pdo);
  92.             if (pdr.Status != PromptStatus.OK)
  93.                 return;
  94.  
  95.             try
  96.             {
  97.                 Triangulation triangles = new Triangulation(ids, true, pdr.Value);
  98.                 triangles.MakeSolid3d();
  99.             }
  100.             catch (System.Exception ex)
  101.             {
  102.                 ed.WriteMessage(ex.Message + ex.StackTrace);
  103.             }
  104.         }
  105.  
  106.         private ObjectId[] SelectPoints()
  107.         {
  108.             PromptSelectionOptions pso = new PromptSelectionOptions();
  109.             pso.MessageForAdding = "\nSelect points (or Enter for all): ";
  110.             SelectionFilter filter = new SelectionFilter(
  111.                 new TypedValue[2] { new TypedValue(0, "POINT"), new TypedValue(410, "Model") });
  112.             PromptSelectionResult psr = ed.GetSelection(pso, filter);
  113.             if (psr.Status == PromptStatus.Error)
  114.                 psr = ed.SelectAll(filter);
  115.             if (psr.Status == PromptStatus.OK)
  116.                 return psr.Value.GetObjectIds();
  117.             return null;
  118.         }
  119.     }
  120. }
  121.  
Speaking English as a French Frog

AARYAN

  • Newt
  • Posts: 72
Re: Polyface Mesh to 3dFace in .net
« Reply #3 on: December 14, 2014, 11:45:38 PM »
Thank You So Much Mr.Gile.

But I am getting one error.

Autodesk.......Open is obsolete. Use GetObject instead. at Line no. 253.
« Last Edit: December 15, 2014, 12:01:56 AM by AARYAN »

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Polyface Mesh to 3dFace in .net
« Reply #4 on: December 15, 2014, 01:48:34 AM »
Hi,

As far I know, using the 'obsolete' ObjectId.Open() do not raise an error, just a warning which message is: "For advanced use only. Use GetObject instead".
As shown here, the Open/Close way may improve performances.
Anyway, I edited the upper code tu use StartOpenCloseTransaction() instead.
Speaking English as a French Frog

AARYAN

  • Newt
  • Posts: 72
Re: Polyface Mesh to 3dFace in .net
« Reply #5 on: December 15, 2014, 03:56:06 AM »
Thank You Mr.Gile. You are really Helpful. :-)

AARYAN

  • Newt
  • Posts: 72
Re: Polyface Mesh to 3dFace in .net
« Reply #6 on: December 16, 2014, 04:45:15 AM »
Hello Mr.Gile.

I am trying to call the above function through lisp (only for 3dfaces). I have removed some variables which are not used by Triang_face3d function and also added some code to suite to call from lisp but being a beginner and self learner I am unable to succeed and getting and error.

System.MissingMethodException: No parameterless constructor defined for this object.

Not sure what does it mean.

Please help.

Code: [Select]
namespace DelaunayTriangulation
{
class Triangulation
    {
        private int npts, ntri;
        private int[] pt1, pt2, pt3, ed1, ed2;
        private double[] ptx, pty, ptz;
        private double zref;

        public Triangulation(ObjectId[] ids, double zref)
        {
            this.zref = zref;
            Triangulate(ids);
            Count = ntri;
        }

        public Triangulation(ObjectId[] ids)
            : this(ids, 0.0) { }

        public int Count { get; private set; }

        public int MakeFaces()
        {
            Database db = HostApplicationServices.WorkingDatabase;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTableRecord btr =
                    (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite);
                for (int i = 0; i < ntri; i++)
                {
                    using (Face face = new Face(
                        new Point3d(ptx[pt1[i]], pty[pt1[i]], ptz[pt1[i]]),
                        new Point3d(ptx[pt2[i]], pty[pt2[i]], ptz[pt2[i]]),
                        new Point3d(ptx[pt3[i]], pty[pt3[i]], ptz[pt3[i]]),
                        true, true, true, true))
                    {
                        btr.AppendEntity(face);
                        tr.AddNewlyCreatedDBObject(face, true);
                    }
                }
                tr.Commit();
            }
            return ntri;
        }

        private bool circum(double x1, double y1, double x2, double y2, double x3, double y3, ref double xc, ref

double yc, ref double r)
        {
            const double eps = 1e-6;
            const double big = 1e12;
            bool result = true;
            double m1, m2, mx1, mx2, my1, my2, dx, dy;
            if ((Math.Abs(y1 - y2) < eps) && (Math.Abs(y2 - y3) < eps))
            {
                result = false;
                xc = x1; yc = y1; r = big;
            }
            else
            {
                if (Math.Abs(y2 - y1) < eps)
                {
                    m2 = -(x3 - x2) / (y3 - y2);
                    mx2 = (x2 + x3) / 2;
                    my2 = (y2 + y3) / 2;
                    xc = (x2 + x1) / 2;
                    yc = m2 * (xc - mx2) + my2;
                }
                else if (Math.Abs(y3 - y2) < eps)
                {
                    m1 = -(x2 - x1) / (y2 - y1);
                    mx1 = (x1 + x2) / 2;
                    my1 = (y1 + y2) / 2;
                    xc = (x3 + x2) / 2;
                    yc = m1 * (xc - mx1) + my1;
                }
                else
                {
                    m1 = -(x2 - x1) / (y2 - y1);
                    m2 = -(x3 - x2) / (y3 - y2);
                    if (Math.Abs(m1 - m2) < eps)
                    {
                        result = false;
                        xc = x1;
                        yc = y1;
                        r = big;
                    }
                    else
                    {
                        mx1 = (x1 + x2) / 2;
                        mx2 = (x2 + x3) / 2;
                        my1 = (y1 + y2) / 2;
                        my2 = (y2 + y3) / 2;
                        xc = (m1 * mx1 - m2 * mx2 + my2 - my1) / (m1 - m2);
                        yc = m1 * (xc - mx1) + my1;
                    }
                }
            }
            dx = x2 - xc;
            dy = y2 - yc;
            r = dx * dx + dy * dy;
            return result;
        }
        private void Triangulate(ObjectId[] ids)
        {
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            sw.Start();
            Point3d[] pts = ids
                .Select(id =>
                {
                    using (DBPoint point = (DBPoint)id.Open(OpenMode.ForRead))
                    {
                        return point.Position;
                    }
                })
                .Distinct()
                .ToArray();
            npts = ids.Length;
            ProgressMeter progress = new ProgressMeter();
            progress.SetLimit(npts);
            progress.Start("Creating Triangles...");
            progress.SetLimit(npts);
            int i, j, k, ned, status1 = 0;
            bool status;
            // Point coordinates
            ptx = new double[npts + 3];
            pty = new double[npts + 3];
            ptz = new double[npts + 3];
            // Triangle definitions
            pt1 = new int[npts * 2 + 1];
            pt2 = new int[npts * 2 + 1];
            pt3 = new int[npts * 2 + 1];
            // Circumscribed circle
            double[] cex = new double[npts * 2 + 1];
            double[] cey = new double[npts * 2 + 1];
            double[] rad = new double[npts * 2 + 1];
            double xmin, ymin, xmax, ymax, dx, dy, xmid, ymid, dmax;
            ed1 = new int[npts * 2 + 1];
            ed2 = new int[npts * 2 + 1];
            k = 0;
            for (i = 0; i < npts; i++)
            {
                Point3d pt = pts[i];
                ptx[i] = pt.X;
                pty[i] = pt.Y;
                ptz[i] = pt.Z;
                k++;
            }
            // Supertriangle
            xmin = ptx[0]; xmax = xmin;
            ymin = pty[0]; ymax = ymin;
            for (i = 0; i < npts; i++)
            {
                if (ptx[i] < xmin) xmin = ptx[i];
                if (ptx[i] > xmax) xmax = ptx[i];
                if (pty[i] < xmin) ymin = pty[i];
                if (pty[i] > xmin) ymax = pty[i];
            }
            dx = xmax - xmin;
            dy = ymax - ymin;
            dmax = dx < dy ? dy : dx;
            xmid = (xmin + xmax) / 2; ymid = (ymin + ymax) / 2;
            i = npts;
            ptx[i] = xmid - 2 * dmax;
            pty[i] = ymid - dmax;
            ptz[i] = 0;
            pt1[0] = i;
            i++;
            ptx[i] = xmid + 2 * dmax;
            pty[i] = ymid - dmax;
            ptz[i] = 0;
            pt2[0] = i;
            i++;
            ptx[i] = xmid;
            pty[i] = ymid + 2 * dmax;
            ptz[i] = 0;
            pt3[0] = i;
            ntri = 1;
            circum(
                ptx[pt1[0]], pty[pt1[0]], ptx[pt2[0]],
                pty[pt2[0]], ptx[pt3[0]], pty[pt3[0]],
                ref cex[0], ref cey[0], ref rad[0]
                );
            // Main loop
            for (i = 0; i < npts; i++)
            {
                progress.MeterProgress();
                ned = 0;
                xmin = ptx[i]; ymin = pty[i];
                j = 0;
                while (j < ntri)
                {
                    dx = cex[j] - xmin; dy = cey[j] - ymin;
                    if (((dx * dx) + (dy * dy)) < rad[j])
                    {
                        ed1[ned] = pt1[j]; ed2[ned] = pt2[j];
                        ned++;
                        ed1[ned] = pt2[j]; ed2[ned] = pt3[j];
                        ned++;
                        ed1[ned] = pt3[j]; ed2[ned] = pt1[j];
                        ned++;
                        ntri--;
                        pt1[j] = pt1[ntri];
                        pt2[j] = pt2[ntri];
                        pt3[j] = pt3[ntri];
                        cex[j] = cex[ntri];
                        cey[j] = cey[ntri];
                        rad[j] = rad[ntri];
                        j--;
                    }
                    j++;
                }
                for (j = 0; j < ned - 1; j++)
                    for (k = j + 1; k < ned; k++)
                        if ((ed1[j] == ed2[k]) && (ed2[j] == ed1[k]))
                        {
                            ed1[j] = -1;
                            ed2[j] = -1;
                            ed1[k] = -1;
                            ed2[k] = -1;
                        }
                for (j = 0; j < ned; j++)
                    if ((ed1[j] >= 0) && (ed2[j] >= 0))
                    {
                        pt1[ntri] = ed1[j];
                        pt2[ntri] = ed2[j];
                        pt3[ntri] = i;
                        status = circum(
                            ptx[pt1[ntri]], pty[pt1[ntri]], ptx[pt2[ntri]],
                            pty[pt2[ntri]], ptx[pt3[ntri]], pty[pt3[ntri]],
                            ref cex[ntri], ref cey[ntri], ref rad[ntri]
                            );
                        if (!status)
                        {
                            status1++;
                        }
                        ntri++;
                    }
            }
            // Removal of outer triangles
            i = 0;
            while (i < ntri)
            {
                if ((pt1[i] >= npts) || (pt2[i] >= npts) || (pt3[i] >= npts))
                {
                    ntri--;
                    pt1[i] = pt1[ntri];
                    pt2[i] = pt2[ntri];
                    pt3[i] = pt3[ntri];
                    cex[i] = cex[ntri];
                    cey[i] = cey[ntri];
                    rad[i] = rad[ntri];
                    i--;
                }
                i++;
            }
            progress.Stop();
        }
        [LispFunction("MakeTriangles")]
        public object MakeTriangles(ResultBuffer resbuf)
        {
            TypedValue[] args = resbuf.AsArray();
            SelectionSet ss = (SelectionSet)args[0].Value;
            ObjectId[] ids = ss.GetObjectIds();
            try
            {
                Triangulation triangles = new Triangulation(ids);
                triangles.MakeFaces();
            }
            catch (System.Exception ex)
            {
                AcAp.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.Message + ex.StackTrace);
            }
            return null;
        }
    }
}

Regards

AARYAN

  • Newt
  • Posts: 72
Re: Polyface Mesh to 3dFace in .net
« Reply #7 on: December 17, 2014, 12:35:43 AM »
I have got the solution just by changing

public object MakeTriangles

to

public static void MakeTriangles


Thank You.

AARYAN

  • Newt
  • Posts: 72
Re: Polyface Mesh to 3dFace in .net
« Reply #8 on: December 18, 2014, 01:32:11 AM »
Sorry Gurus,

Come up with an another issue. My colleague has AutoCAD 2010 installed and .Net Framework 3.0, so tried building the dll using .net 3.0 framework but I get an error

'The type of namespace 'Linq' does not exist in the namespace 'System'.

and also I 'System.Xml.Linq' missing from the reference.

Please help me if there is any substitute of it or can anyone please update the code to support 3.0 framework.

I have downloaded the LinqBridge.dll and the error goes away but In the target machine AutoCAD error comes up saying
"LinqBridge.dll  is missing" Where can I include this dll in the target machine.

Hope to see any reply soon.

Thanks
« Last Edit: December 18, 2014, 01:45:24 AM by AARYAN »

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Polyface Mesh to 3dFace in .net
« Reply #9 on: December 18, 2014, 02:11:00 AM »
Hi,

IMO, your collegue should download and install .NET Framework 3.5 so that it would be able to use System.Linq, extension methods and some others interesting features.

An other way would be replacing the piece of code which uses Linq:
Code - C#: [Select]
  1.             Point3d[] pts;
  2.             Database db = HostApplicationServices.WorkingDatabase;
  3.             using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
  4.             {
  5.                 pts = ids
  6.                     .Select(id => ((DBPoint)tr.GetObject(id, OpenMode.ForRead)).Position)
  7.                     .Distinct()
  8.                     .ToArray();
  9.             }
  10.             npts = pts.Length;
with the 'traditional' equivalent code:
Code - C#: [Select]
  1.             List<Point3d> lst = new List<Point3d>();
  2.             Database db = HostApplicationServices.WorkingDatabase;
  3.             using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
  4.             {
  5.                 foreach (ObjectId id in ids)
  6.                 {
  7.                     Point3d pt = ((DBPoint)tr.GetObject(id, OpenMode.ForRead)).Position;
  8.                     if (!lst.Contains(pt))
  9.                         lst.Add(pt);
  10.                 }
  11.             }
  12.             npts = lst.Count;
  13.             Point3d[] pts = new Point3d[npts];
  14.             lst.CopyTo(pts);
Speaking English as a French Frog

AARYAN

  • Newt
  • Posts: 72
Re: Polyface Mesh to 3dFace in .net
« Reply #10 on: December 18, 2014, 05:43:15 AM »
Thanks Mr. Gile.

Your code works properly but it decreases the speed of the program too much.

Other option of installing the 3.5 framework seems better.

Regards