Создание 3DSolid из PolyfaceMesh

Автор Тема: Создание 3DSolid из PolyfaceMesh  (Прочитано 4107 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 806
  • Карма: 166
    • Мои плагины к Автокаду
Создание 3DSolid из PolyfaceMesh
« : 08-04-2017, 18:21:27 »
Выделено из http://adn-cis.org/forum/index.php?topic=316.0 /* Александр Ривилис */

А нет ли где примеров решения обратной задачи: из PolyfaceMesh сделать солид. При экспорте из 3DMax в dwg вылезают эти убогие PolyfaceMesh и ничего с ними нельзя сделать, ни во что нельзя преобразовать и даже взорвать до линий нельзя. Очень было бы полезно создать конвертер
« Последнее редактирование: 08-04-2017, 20:57:39 от avc »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Создание 3DSolid из PolyfaceMesh
« Ответ #1 : 08-04-2017, 20:03:06 »
Есть команда _CONVTOSOLID. Можешь попробовать её.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Создание 3DSolid из PolyfaceMesh
« Ответ #2 : 08-04-2017, 20:27:04 »
Ну и есть такая статья (на ObjectARX, но думаю что можно переделать и на AutoCAD .NET API):
How to Convert Polyfacemesh to 3dSolid - AutoCAD DevBlog
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 806
  • Карма: 166
    • Мои плагины к Автокаду
Re: Создание 3DSolid из PolyfaceMesh
« Ответ #3 : 08-04-2017, 20:36:28 »
100 случаях из 100 команда CONVTOSOLID выводит "Object cannot be converted." Предполагаю она для Mesh, а не для PolyFaceMesh. У Mesh и в контекстном меню есть конвертация, и многие команды Автокада с ней работают. А вот PolyFaceMesh - это тупиковая ветвь эволюции :)
А за статью спасибо! На первый взгляд вполне переводимо на .Net . Попробую

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Создание 3DSolid из PolyfaceMesh
« Ответ #4 : 08-04-2017, 20:47:48 »
А вот PolyFaceMesh - это тупиковая ветвь эволюции :)
Это самая первая сеть, которая появилась в AutoCAD. Так что не удивляйся.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Александр Ривилис 10-04-2017, 17:45:26

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 806
  • Карма: 166
    • Мои плагины к Автокаду
Re: Создание 3DSolid из PolyfaceMesh
« Ответ #5 : 10-04-2017, 14:56:49 »
Все получилось. Сети можно конвертировать в солиды! Главное не пытаться сглаживать.
Перевод на .Net получился такой:
Код - C# [Выбрать]
  1.     [CommandMethod("PFSolid", CommandFlags.NoPaperSpace | CommandFlags.UsePickSet | CommandFlags.Redraw)]
  2.     public static void PFSolid()
  3.     {
  4.         Document doc = Application.DocumentManager.MdiActiveDocument;
  5.         if (doc == null) return;
  6.         ObjectId[] selection = ....; // Список выбраных заранее объектов или запрос
  7.         if (selection == null)
  8.           return;
  9.        using (Transaction tr = doc.Database.TransactionManager.StartTransaction())
  10.         {
  11.           BlockTable bt = (BlockTable)tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead);
  12.           BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
  13.           int count = 0;
  14.  
  15.           foreach (ObjectId entId in selection)
  16.           {
  17.             if (entId.IsNull || entId.IsErased || !entId.IsValid || entId.ObjectClass != dbPolyFaceMesh) continue;
  18.             PolyFaceMesh pfm = (PolyFaceMesh)tr.GetObject(entId, OpenMode.ForRead);
  19.             if (pfm == null) continue;
  20.             count++;
  21.  
  22.             Point3dCollection vertexArray;
  23.             Int32Collection faceArray;
  24.             if (!GetPolyFaceMeshData(pfm, out vertexArray, out faceArray))
  25.               return;
  26.  
  27.             /*We create an in-memory mesh and convert mesh to solid*/
  28.             SubDMesh subDMesh = new SubDMesh();
  29.  
  30.               subDMesh.SetSubDMesh(vertexArray, faceArray, 0);
  31.               /*Now convert to Solid using CONVTOSOLID  API*/
  32.               /*We will restrict to polygonal solid, we set false for smoothness, so not to abuse CPU*/
  33.               Solid3d solid = subDMesh.ConvertToSolid(false, true);
  34.               solid.SetPropertiesFrom(pfm);
  35.               ms.AppendEntity(solid);
  36.               tr.AddNewlyCreatedDBObject(solid, true);
  37.  
  38.             /*Delete pfm*/
  39.             pfm.UpgradeOpen();
  40.             pfm.Erase();
  41.           }
  42.  
  43.           tr.Commit();
  44.           .... отчет о проделанной работе по count
  45.         }
  46.     }
  47.  
  48.     /*Get the Mesh data, not accounted for Color and Material of Faces*/
  49.     static bool GetPolyFaceMeshData(PolyFaceMesh mesh, out Point3dCollection vertexArray, out Int32Collection faceArray)
  50.     {
  51.       vertexArray = new Point3dCollection();
  52.       faceArray = new Int32Collection();
  53.       if (mesh == null || mesh.IsErased || mesh.Database == null) return false;
  54.       Transaction tr = mesh.Database.TransactionManager.TopTransaction;
  55.       if (tr == null) return false;
  56.  
  57.       foreach (ObjectId id in mesh)
  58.       {
  59.         if (id.IsNull || id.IsErased || !id.IsValid) continue;
  60.         DBObject obj = tr.GetObject(id, OpenMode.ForRead);
  61.         if (obj is PolyFaceMeshVertex)
  62.         {
  63.           PolyFaceMeshVertex vertex = (PolyFaceMeshVertex)obj;
  64.           vertexArray.Add(vertex.Position);
  65.         }
  66.         else if (obj is FaceRecord)
  67.         {
  68.           FaceRecord face = (FaceRecord)obj;
  69.           int count = 0;
  70.           short[] indices = new short[4];
  71.           for (short i = 0; i < 4; i++)
  72.           {
  73.             indices[i] = face.GetVertexAt(i);
  74.             if (indices[i] == 0)
  75.               break;
  76.             count++;
  77.           }
  78.           // Quick triangle test by checking if the first vertex
  79.           // is the same as the last vertex
  80.           if (count == 4 && (Math.Abs(indices[0]) == Math.Abs(indices[3])))
  81.             count = 3;
  82.  
  83.           // Per face record can be a triangle or quad
  84.           if (count > 2)
  85.           {
  86.             faceArray.Add(count);
  87.             for (int i = 0; i < count; i++)
  88.               faceArray.Add((short)(Math.Abs(indices[i]) - 1));
  89.           }
  90.         }
  91.       }
  92.       return true;
  93.     }
  94.  

Шаманства с системными переменными я убрал, т.к. SetSubDMesh работет адекватно только с smoothLevel = 0. А вот в ConvertToSolid я включил optimize - это не замедляет работу, но устраняет часть мусора из солида (Портированные из Макса сети всегда состоят из треугольников, оптимизация часть из них объединяет в прямоугольники).
Мою cпецифическую обработку исключений я из кода стер, она там конечно нужна.
И обязательно добавлю solid.SeparateBody()
« Последнее редактирование: 10-04-2017, 18:06:06 от avc »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Создание 3DSolid из PolyfaceMesh
« Ответ #6 : 10-04-2017, 17:46:19 »
Отлично! Скоро станешь специалистом по ObjectARX/C++ :)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение