ADN Open CIS
Сообщество программистов Autodesk в СНГ

11/11/2013

Создание PolyfaceMesh из 3D Solid

Это пример кода, создающего многогранную сеть из твердого тела. Большая часть в этом коде из статьи в блоге Kean Walmsleyна похожую тему с некоторыми дополнениями создающую многогранную сеть. Как и в оригинальной статье, я тестировал код со сферой, так что для более сложных тел возможно потребуется настройка параметров.

Код - C#: [Выделить]
  1. using Autodesk.AutoCAD.BoundaryRepresentation;
  2. [CommandMethod("SOL2POLYFACEMESH")]
  3. static public void PolyfaceMeshFromSolid()
  4. {
  5.     Document doc =
  6.     Application.DocumentManager.MdiActiveDocument;
  7.     Database db = doc.Database;
  8.     Editor ed = doc.Editor;
  9.  
  10.     PromptEntityOptions peo =
  11.     new PromptEntityOptions("\nВыберите твердое тело: ");
  12.     peo.SetRejectMessage("\nТолько твердое тело! ");
  13.     peo.AddAllowedClass(typeof(Solid3d), true);
  14.     PromptEntityResult per = ed.GetEntity(peo);
  15.  
  16.     if (per.Status != PromptStatus.OK)
  17.         return;
  18.  
  19.     Transaction tr = db.TransactionManager.StartTransaction();
  20.     using (tr)
  21.     {
  22.         BlockTable bt = (BlockTable)tr.GetObject
  23.             (
  24.                 db.BlockTableId,
  25.                 OpenMode.ForRead,
  26.                 false
  27.             );
  28.  
  29.         BlockTableRecord btr = (BlockTableRecord)
  30.                 tr.GetObject(
  31.                                 bt[BlockTableRecord.ModelSpace],
  32.                                 OpenMode.ForWrite, false
  33.                             );
  34.  
  35.         Solid3d sol = tr.GetObject(
  36.                                     per.ObjectId,
  37.                                     OpenMode.ForRead
  38.                                   ) as Solid3d;
  39.  
  40.         // Вычислим приблизительный размер нашего тела
  41.         double length = sol.GeometricExtents.MinPoint.GetVectorTo
  42.                         (sol.GeometricExtents.MaxPoint).Length;
  43.  
  44.         using (Brep brp = new Brep(sol))
  45.         {
  46.             // Создадим и установим параметры элемента управления сетью
  47.  
  48.             using (Mesh2dControl mc = new Mesh2dControl())
  49.             {
  50.                 // Эти установки могут показаться завышенными, но они
  51.                 // приводят к ~500 граням для сферы (во всяком случае,
  52.                 // в моих тестах).
  53.  
  54.                 mc.MaxNodeSpacing = length / 10000;
  55.                 mc.MaxSubdivisions = 100000000;
  56.  
  57.                 // Создадим элемент фильтра сети
  58.  
  59.                 using (Mesh2dFilter mf = new Mesh2dFilter())
  60.                 {
  61.                     // Используем его для отображения настроек управления
  62.                     // в Brep
  63.  
  64.                     mf.Insert(brp, mc);
  65.  
  66.                     // Генерируем сеть при помощи фильтра
  67.  
  68.                     PolyFaceMesh pfm = new PolyFaceMesh();
  69.                     pfm.SetDatabaseDefaults();
  70.                     pfm.ColorIndex = 2;
  71.                     btr.AppendEntity(pfm);
  72.  
  73.                     short v0 = 0;
  74.                     short v1 = 0;
  75.                     short v2 = 0;
  76.                     short v3 = 0;
  77.                     short v = 0;
  78.  
  79.                     Dictionary<Point3d, short> vertexLookup
  80.                             = new Dictionary<Point3d, short>();
  81.  
  82.                     using (Mesh2d m = new Mesh2d(mf))
  83.                     {
  84.                         // Получаем отдельные грани
  85.                         // из данных сети
  86.  
  87.                         foreach (Element2d e in m.Element2ds)
  88.                         {
  89.                             foreach (Node n in e.Nodes)
  90.                             {
  91.                                 if (! vertexLookup.ContainsKey(n.Point))
  92.                                 {
  93.                                     PolyFaceMeshVertex pfmVertex
  94.                                         = new PolyFaceMeshVertex(n.Point);
  95.  
  96.                                     pfm.AppendVertex(pfmVertex);
  97.                                     vertexLookup.Add(n.Point, ++v);
  98.  
  99.                                     tr.AddNewlyCreatedDBObject
  100.                                             (pfmVertex, true);
  101.                                 }
  102.  
  103.                                 n.Dispose();
  104.                             }
  105.                         }
  106.  
  107.                         foreach (Element2d e in m.Element2ds)
  108.                         {
  109.                             Point3dCollection pts
  110.                                     = new Point3dCollection();
  111.                             foreach (Node n in e.Nodes)
  112.                             {
  113.                                 pts.Add(n.Point);
  114.  
  115.                                 n.Dispose();
  116.                             }
  117.  
  118.                             e.Dispose();
  119.  
  120.                             v0 = 0;
  121.                             if (vertexLookup.ContainsKey(pts[0]))
  122.                                 v0 = vertexLookup[pts[0]];
  123.  
  124.                             v1 = 0;
  125.                             if (vertexLookup.ContainsKey(pts[1]))
  126.                                 v1 = vertexLookup[pts[1]];
  127.  
  128.                             v2 = 0;
  129.                             if (vertexLookup.ContainsKey(pts[2]))
  130.                                 v2 = vertexLookup[pts[2]];
  131.  
  132.                             v3 = 0;
  133.                             if (pts.Count == 4)
  134.                             {
  135.                                 if (vertexLookup.ContainsKey(pts[3]))
  136.                                     v3 = vertexLookup[pts[3]];
  137.                             }
  138.  
  139.                             FaceRecord fr
  140.                                = new FaceRecord(v0, v1, v2, v3);
  141.                             pfm.AppendFaceRecord(fr);
  142.                             tr.AddNewlyCreatedDBObject(fr, true);
  143.                         }
  144.                     }
  145.  
  146.                     tr.AddNewlyCreatedDBObject(pfm, true);
  147.  
  148.                     vertexLookup.Clear();
  149.                 }
  150.             }
  151.         }
  152.         tr.Commit();
  153.     }
  154. }

А это скриншот многогранной сети, полученной из твердого тела - сферы :

 

 

Источник: http://adndevblog.typepad.com/autocad/2013/10/creating-polyfacemesh-from-a-3d-solid.html

Обсуждение: http://adn-cis.org/forum/index.php?topic=316

Опубликовано 11.11.2013