Получение плоского изображения из 3D тела с помощью .NET.

Автор Тема: Получение плоского изображения из 3D тела с помощью .NET.  (Прочитано 9970 раз)

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

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

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Здравствуйте!
Кто-нибудь пробовал получать программно плоские виды 3D тела? Есть ли какие-то инструменты в API для этого?

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Конечно. Через создание секущей плоскости

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Код - C# [Выбрать]
  1.           // Делаем снимок с помощью секущей плоскости
  2.       using (Transaction tr = db.TransactionManager.StartTransaction())
  3.       {
  4.         SectionType st = SectionType.Section2d;
  5.         Extents3d ext = source.GeometricExtents;
  6.         Point3dCollection pts = new Point3dCollection();
  7.  
  8.         double planeElev = Round(ext.MaxPoint.Z + 5, 0);
  9.         pts.Add(new Point3d(ext.MaxPoint.X, ext.MaxPoint.Y, planeElev));
  10.         pts.Add(new Point3d(ext.MinPoint.X, ext.MinPoint.Y, planeElev));
  11.  
  12.         BlockTableRecord model = db.GetModel(tr);
  13.         if (model == null) return false;
  14.  
  15.         Section sec = new Section(pts, Vector3d.YAxis, Vector3d.ZAxis.Negate());
  16.         sec.State = SectionState.Plane;
  17.         model.AppendEntity(sec);
  18.         tr.AddNewlyCreatedDBObject(sec, true);
  19.  
  20.         sec.SetHeight(SectionHeight.HeightAboveSectionLine, 3.0);
  21.         sec.SetHeight(SectionHeight.HeightBelowSectionLine, 1.0);
  22.         SectionSettings ss = (SectionSettings)tr.GetObject(sec.Settings, OpenMode.ForWrite);
  23.         ss.CurrentSectionType = st;
  24.         ObjectIdCollection oic = new ObjectIdCollection();
  25.         oic.Add(source.ObjectId);
  26.         ss.SetSourceObjects(st, oic);
  27.         ss.SetVisibility(st, SectionGeometry.BackgroundGeometry, true);
  28.         ss.SetHiddenLine(st, SectionGeometry.BackgroundGeometry, false);
  29.         ss.SetGenerationOptions(st, SectionGeneration.SourceSelectedObjects | SectionGeneration.DestinationFile);
  30.  
  31.         sec.GenerateSectionGeometry(source, out Array flEnts, out Array bgEnts, out Array foregEntities, out Array ftEnts, out Array ctEnts);
  32.  
  33.         foreach (Entity e in flEnts)
  34.           e.Dispose();
  35.         foreach (Entity e in bgEnts)
  36.           e.Dispose();
  37.         foreach (Entity e in ftEnts)
  38.           e.Dispose();
  39.         foreach (Entity e in ctEnts)
  40.           e.Dispose();
  41.  
  42.         foreground = foregEntities.Cast<Entity>().ToList();
  43.         foreach (Entity fore in foreground)
  44.           fore.TransformBy(Matrix3d.Displacement(new Vector3d(0, 0, 0 - planeElev)));
  45.  
  46.         ss.SetVisibility(st, SectionGeometry.BackgroundGeometry, false);
  47.         ss.SetVisibility(st, SectionGeometry.CurveTangencyLines, false);
  48.         ss.SetHiddenLine(st, SectionGeometry.BackgroundGeometry, true);
  49.  
  50.         sec.GenerateSectionGeometry(source, out flEnts, out bgEnts, out foregEntities, out ftEnts, out ctEnts);
  51.  
  52.         foreach (Entity e in flEnts)
  53.           e.Dispose();
  54.         foreach (Entity e in bgEnts)
  55.           e.Dispose();
  56.         foreach (Entity e in ftEnts)
  57.           e.Dispose();
  58.         foreach (Entity e in ctEnts)
  59.           e.Dispose();
  60.  
  61.         background = foregEntities.Cast<Entity>().ToList();
  62.         foreach (Entity back in background)
  63.           back.TransformBy(Matrix3d.Displacement(new Vector3d(0, 0, 0 - planeElev)));
  64.  
  65.         tr.Abort(); // сотрем из БД сечения
  66.       }
  67.  

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
В этом коде половина - непонятное шаманство с непонятными параметрами этой самой секущей плоскости. Поэтому если не волнуют невидимые линии, то я предпочитаю спроецировать на плоскость все ребра из BRep.

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Я, кажется, нашёл первоисточник: https://through-the-interface.typepad.com/through_the_interface/2008/05/sectioning-an-a.html
Всё круто! Но мне бы получить сечение солида, которого нет в базе данных чертежа...

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Поэтому если не волнуют невидимые линии, то я предпочитаю спроецировать на плоскость все ребра из BRep.
А это как?

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Как вариант так (даже без brep)
Код - C# [Выбрать]
  1.     public static List<Curve> ExplodeToCurves(this Entity ent)
  2.     {
  3.       List<Curve> ret = new List<Curve>();
  4.       if (ent == null || ent.IsErased)
  5.         return ret;
  6.       DBObjectCollection col = new DBObjectCollection();
  7.       try { ent.Explode(col); }
  8.       catch { return ret; }
  9.       if (col == null) return ret;
  10.       foreach(DBObject obj in col)
  11.       {
  12.         if (obj is Curve cur) ret.Add(cur);
  13.         else if (obj is Entity sub) ret.AddRange(sub.ExplodeToCurves());
  14.       }
  15.       return ret;
  16.     }
Ну и потом проецирование кривых на плоскость. Невидимые выловить невозможно. Зато работает с сетями. Да и вообще со всеми объектами без разбора. Жалко тексты не взрываются...

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Да это, похоже, как раз то что нужно! Спасибо! Что-то я не догадался, что можно просто взорвать солид :)
Единственное что смущает в коде примера - объект sub не диспозится и не добавляется в выходную коллекцию.

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
объект sub не диспозится
sub==obj, а obj приписан в коллекцию col и по идее диспозится вместе с ней. Не? Я никогда не вызываю диспоз объектов из коллекций. Я не прав?

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Но мне бы получить сечение солида
С сечением глухо - только сохранять в БД, создавать секущую и все отменять, абортить транзакцию. И, кстати, секущие работают ТОЛЬКО в Автокад, универсальный плагин не получится.

Отмечено как Решение Дмитрий Загорулькин 17-12-2018, 20:17:11

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Хотя.... можно попробовать Slice. Потом взорвать отрезанный кусок солида и выбрать кривые на плоскости сечения. Получим именно сечение (не разрез)

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Но со Slice будьте осторожны - промахнетесь плоскостью мимо солида - получите фатал. Приходится сначала пробовать вычитать тоненький солид.

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
sub==obj, а obj приписан в коллекцию col и по идее диспозится вместе с ней. Не? Я никогда не вызываю диспоз объектов из коллекций. Я не прав?
Хороший вопрос... Наверное прав. Только col тоже нигде не диспозится вроде. Надо её, наверное, в using завернуть.
С сечением глухо - только сохранять в БД, создавать секущую и все отменять, абортить транзакцию. И, кстати, секущие работают ТОЛЬКО в Автокад, универсальный плагин не получится.
Неправильно выразился, мне не сечение надо, а именно вид сбоку.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
sub==obj, а obj приписан в коллекцию col и по идее диспозится вместе с ней. Не? Я никогда не вызываю диспоз объектов из коллекций. Я не прав?
С какой стати? В коллекции хранятся ссылки на объекты. Диспоз коллекции диспозит коллекцию, но не объекты, ссылки на которые хранятся в ней. Я специально поизучал класс DBObjectCollection и не нашёл нигде чтобы выполнялся Dispose для его элементов.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Ну и потом проецирование кривых на плоскость. Невидимые выловить невозможно. Зато работает с сетями. Да и вообще со всеми объектами без разбора. Жалко тексты не взрываются...
Бегло проверил. Похоже, что такой метод "в лоб" мне не поможет. В чём проблема: этим способом хорошо обрабатывать тела с выраженными гранями. Но если есть скругления, то при взрыве они теряются. Остаются только окружности оснований, по которым их не восстановить.
« Последнее редактирование: 17-12-2018, 19:39:21 от Дмитрий Загорулькин »