Получение геометрии элементов

Автор Тема: Получение геометрии элементов  (Прочитано 13515 раз)

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

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

  • ADN OPEN
  • ***
  • Сообщений: 210
  • Карма: 0
Доброго времени суток.
Подскажите пожалуйста, как получить геометрию для элемента (набор треугольников, представляющих все поверхности).
Я могу получить ModelGeometry для каждого ModelItem. Но как из ModelGeometry получить треугольники, так и не разобрался.
Спасибо за информацию.

Отмечено как Решение Vladislav 27-03-2019, 14:19:57

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Получение геометрии элементов
« Ответ #2 : 26-03-2019, 22:56:02 »
Vladislav: Геометрию в Navisworks можно получать, к сожалению, только с использованием COM API. Посмотрите, там при установке Navisworks, насколько помню, можно установить SDK (на край, найти гуглом). Там расписаны разные виды API, доступные в Navis, их различия и области применения. Касательно вопроса про получение геометрии, Александр Ривилис подсказал статью в правильном направлении.

Вот часть кода из одного из моих проектов:

Код - C# [Выбрать]
  1. internal class GeometryObjectBuilder : InwSimplePrimitivesCB
  2.     {
  3.         ...
  4.         private double[] currentTransformMatrix;
  5.  
  6.         public IEnumerable<GeometryObject> Build(ModelItem modelItem)
  7.         {
  8.             var oSel = ComApiBridge.ToInwOpSelection(new ModelItemCollection {modelItem});
  9.  
  10.             foreach (InwOaPath3 path in oSel.Paths())
  11.             {
  12.                 InwOaPath3 path1 = path;
  13.                 var fragments = path.Fragments()
  14.                     .Cast<InwOaFragment3>()
  15.                     .Where(x => IsFragmentOnPath(path1, x))
  16.                     .ToList();
  17.  
  18.                 foreach (var fragment in fragments)
  19.                 {
  20.                     ...
  21.  
  22.                     currentTransformMatrix = fragment.GetLocalToWorldTransformMatrix();
  23.  
  24.                     fragment.GenerateSimplePrimitives(nwEVertexProperty.eNORMAL, this);
  25.  
  26.                    ...
  27.                 }
  28.             }
  29.         }
  30.        
  31.         public void Triangle(InwSimpleVertex v1, InwSimpleVertex v2, InwSimpleVertex v3)
  32.         {
  33.             // здесь можно получать координаты, например для первой точки
  34.             var p1 = v1.GetGeometryPoint(currentTransformMatrix);
  35.             // нормали
  36.             var n1 = v1.GetNormal();
  37.             // делать ещё что-либо полезное
  38.         }
  39.  
  40.         public void Line(InwSimpleVertex v1, InwSimpleVertex v2)
  41.         {
  42.            
  43.         }
  44.  
  45.         public void Point(InwSimpleVertex v1)
  46.         {
  47.            
  48.         }
  49.  
  50.         public void SnapPoint(InwSimpleVertex v1)
  51.         {
  52.            
  53.         }
  54.  
  55.  
  56.         /// <summary>
  57.         /// From http://adndevblog.typepad.com/aec/2012/08/geometry-fragment-returns-all-instances-when-a-multiply-instanced-node-is-selected.html
  58.         /// </summary>
  59.         /// <param name="path"></param>
  60.         /// <param name="fragment"></param>
  61.         /// <returns></returns>
  62.         private static bool IsFragmentOnPath(InwOaPath3 path, InwOaFragment3 fragment)
  63.         {
  64.             var a1 = (Array)(object)fragment.path.ArrayData;
  65.             var a2 = (Array)(object)path.ArrayData;
  66.  
  67.             if (a1.GetLength(0) == a2.GetLength(0) &&
  68.                 a1.GetLowerBound(0) == a2.GetLowerBound(0) &&
  69.                 a1.GetUpperBound(0) == a2.GetUpperBound(0))
  70.             {
  71.                 var i = a1.GetLowerBound(0);
  72.                 for (; i <= a1.GetLength(0); i++)
  73.                     if ((int)a1.GetValue(i) != (int)a2.GetValue(i))
  74.                         return false;
  75.             }
  76.             else
  77.                 return false;
  78.  
  79.             return true;
  80.         }
  81.     }

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Получение геометрии элементов
« Ответ #3 : 26-03-2019, 23:02:34 »
Посмотрите, там при установке Navisworks, насколько помню, можно установить SDK (на край, найти гуглом).
Все Navisworks SDK (в составе которой документация) здесь: https://www.autodesk.com/developer-network/platform-technologies/navisworks
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ***
  • Сообщений: 210
  • Карма: 0
Re: Получение геометрии элементов
« Ответ #4 : 27-03-2019, 14:20:38 »
Коллеги, большое спасибо за информацию. Буду разбираться.

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

  • ADN OPEN
  • ***
  • Сообщений: 210
  • Карма: 0
Re: Получение геометрии элементов
« Ответ #5 : 29-03-2019, 15:47:40 »
Доброго времени суток.
В продолжение темы возник еще один вопрос. Нет ли возможности выбирать уровень детализации получаемой геометрии.
Мне необходимо разработать конвертер из Navisworks в наш формат. А обработка геометрии (сетки треугольников), полученной по
указанной выше методике занимает очень много времени даже для относительно простой модели (снегоход из прилагаемых примеров Navisworks).

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Получение геометрии элементов
« Ответ #6 : 29-03-2019, 15:52:07 »
Насколько знаю, нет, раньше, по крайней мере, такой возможности точно не было (последний раз под Navisworks что-то делал года 3-4 назад), а, к сожалению, Navisworks практически не развивается, т.к. вместо него теперь сервисы Forge. Кстати, можете попробовать воспользоваться ими, если задача и ТЗ позволяют.

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

  • ADN OPEN
  • ***
  • Сообщений: 210
  • Карма: 0
Re: Получение геометрии элементов
« Ответ #7 : 01-04-2019, 11:56:06 »
Добрый день, Александр. Возник вопрос по приведенному Вами примеру кода.
А именно, как произвести преобразование координат, полученных методом Triangle, из локальных в глобальные.
В вашем примере метод fragment.GetLocalToWorldTransformMatrix() возвращает непосредственно одномерный массив double[] вместо InwLTransform3f.
Также в моем случае вершины InwSimpleVertex v1..v3 не имеют методов GetGeometryPoint() и GetNormal().
Спасибо за информацию. 

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Получение геометрии элементов
« Ответ #8 : 01-04-2019, 12:00:32 »
Пардон. Делал этот проект в далеком 2015. Вот Extension-ы:
Код - C# [Выбрать]
  1. public static class InwSimpleVertexExtensions
  2. {
  3.         public static GeometryPoint GetGeometryPoint(this InwSimpleVertex vector)
  4.         {
  5.                 return GetCoordinates(vector, x => (object)x.coord);
  6.         }
  7.  
  8.         public static GeometryPoint GetGeometryPoint(this InwSimpleVertex vector, double[] matrix)
  9.         {
  10.                 if (matrix.Length != 16)
  11.                         throw new ArgumentOutOfRangeException();
  12.  
  13.                 var arrayVector = (Array)(object)vector.coord;
  14.  
  15.                 var vertexes = arrayVector.Cast<float>().ToArray();
  16.  
  17.                 var x = vertexes[0] * matrix[0] + vertexes[1] * matrix[4] + vertexes[2] * matrix[8] + matrix[12];
  18.                 var y = vertexes[0] * matrix[1] + vertexes[1] * matrix[5] + vertexes[2] * matrix[9] + matrix[13];
  19.                 var z = vertexes[0] * matrix[2] + vertexes[1] * matrix[6] + vertexes[2] * matrix[10] + matrix[14];
  20.  
  21.                 return new GeometryPoint(x, y, z);
  22.         }
  23.  
  24.         public static GeometryPoint GetNormal(this InwSimpleVertex vertex)
  25.         {
  26.                 return GetCoordinates(vertex, x => (object) x.normal);
  27.         }
  28.  
  29.         private static GeometryPoint GetCoordinates(InwSimpleVertex vector, Func<InwSimpleVertex, object> getVertexParameter)
  30.         {
  31.                 var arrayVector = (Array)getVertexParameter(vector);
  32.  
  33.                 var vertexes = arrayVector.Cast<float>().ToArray();
  34.  
  35.                 return new GeometryPoint(vertexes[0], vertexes[1], vertexes[2]);
  36.         }
  37. }

Ну GeometryPoint, соответственно, простой, представляет собой точку в пространстве

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

  • ADN OPEN
  • ***
  • Сообщений: 210
  • Карма: 0
Re: Получение геометрии элементов
« Ответ #9 : 01-04-2019, 12:27:18 »
Спасибо большое. И еще такой вопрос.
Массив double[] получается из InwLTransform3f при обращении к свойству Matrix?
А то там возвращается значение типа dynamic и не совсем ясно, как его использовать.

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Получение геометрии элементов
« Ответ #10 : 01-04-2019, 12:30:46 »
Походу, да. Нашёл в том проекте такое:
Код - C# [Выбрать]
  1. public static class InwOaFragment3Extensions
  2. {
  3.         public static double[] GetLocalToWorldTransformMatrix(this InwOaFragment3 fragment)
  4.         {
  5.                 var localToWorld = (InwLTransform3f3)fragment.GetLocalToWorldMatrix();
  6.  
  7.                 var matrix = (Array)(object)localToWorld.Matrix;
  8.  
  9.                 return matrix.Cast<double>().ToArray();
  10.         }
  11. }

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

  • ADN OPEN
  • ***
  • Сообщений: 210
  • Карма: 0
Re: Получение геометрии элементов
« Ответ #11 : 01-04-2019, 13:18:19 »
Спасибо. А нет ли какой-либо информации по работе с цветом InwSimpleVertex?
Есть свойство color, но оно также dynamic. И неясно, как разложить его на ARGB-составляющие.
Благодарю за ответы.

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Получение геометрии элементов
« Ответ #12 : 01-04-2019, 13:42:39 »
Я брал из ModelItem.Geometry. Там есть свойства OriginalColor и OriginalTransparency

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

  • ADN OPEN
  • ***
  • Сообщений: 210
  • Карма: 0
Re: Получение геометрии элементов
« Ответ #13 : 02-04-2019, 14:08:50 »
Добрый день.
В продолжение вопроса об ускорении обработки графики, полученной из модели Navisworks.
У InwOaFragment3 есть свойство Geometry. Оно имеет тип dynamic. Оно аналогично одноименному свойству у ModelItem или несет что-то еще?
Нельзя ли с его помощью (или как-то иначе) получить готовые примитивы, используемые визуализатором Navisworks,
вместо генерирования их для каждого элемента модели?
Насколько я помню, в Inventor есть метод GetExistingFacets() для этой цели.
Благодарю за ответы.

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Получение геометрии элементов
« Ответ #14 : 02-04-2019, 14:17:24 »
У InwOaFragment3 есть свойство Geometry. Оно имеет тип dynamic. Оно аналогично одноименному свойству у ModelItem или несет что-то еще?

Насколько помню, нет, но это не точно. Посмотрите в отладчике.

Нельзя ли с его помощью (или как-то иначе) получить готовые примитивы, используемые визуализатором Navisworks,
вместо генерирования их для каждого элемента модели?
Насколько я помню, в Inventor есть метод GetExistingFacets() для этой цели.

Нет.

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

  • ADN OPEN
  • ***
  • Сообщений: 210
  • Карма: 0
Re: Получение геометрии элементов
« Ответ #15 : 02-04-2019, 16:38:14 »
А в каких единицах представлены возвращаемые координаты в Navisworks? Для Revit это футы, для Inventor - сантиметры. А в данном случае не совсем ясно.
Спасибо.

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc

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

  • ADN OPEN
  • ***
  • Сообщений: 210
  • Карма: 0
Re: Получение геометрии элементов
« Ответ #17 : 05-04-2019, 17:57:26 »
Добрый вечер.
При конвертации графики из модели Naviwsorks возникла проблема. Нормали некоторых объектов направлены не в ту сторону.
Соответственно, объекты не видны. В связи с этим возник вопрос. В метод Triangle вершины треугольника v1, v2 и v3 всегда приходят в одном порядке?
То есть по или против часовой стрелке. И правильно ли я получаю координаты нормали из вершин?
Вот мой код:
           
Код - C# [Выбрать]
  1. Array array_n1 = (Array)(object)v1.normal;
  2. n1.x = (float)array_n1.GetValue(1);
  3. n1.y = (float)array_n1.GetValue(2);
  4. n1.z = (float)array_n1.GetValue(3);
Спасибо за ответы.
« Последнее редактирование: 05-04-2019, 18:18:45 от Александр Ривилис »

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

  • ADN OPEN
  • ***
  • Сообщений: 210
  • Карма: 0
Re: Получение геометрии элементов
« Ответ #18 : 08-04-2019, 14:24:26 »
Видимо, предыдущий вопрос пометился как прочитанный и его никто не увидел(

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Получение геометрии элементов
« Ответ #19 : 08-04-2019, 20:17:48 »
В метод Triangle вершины треугольника v1, v2 и v3 всегда приходят в одном порядке?
Сомневаюсь. Во всяком случае об этом нигде не сказано.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ***
  • Сообщений: 210
  • Карма: 0
Re: Получение геометрии элементов
« Ответ #20 : 20-03-2020, 13:35:40 »
Александр, добрый день!
Вопрос к Вам, как к автору кода по получению геометрии элементов.
А можно ли как-то, на Ваш взгляд, ускорить процесс получения геометрии?
Просто код выполняется оооочень долго (если для всех элементов модели).
Для модели размером 1.6 гБ, порядка 3х часов на intel Core i5-3450 c 8гб оперативной памяти.
Сейчас совместно с Александром Ривилисом рассматриваем вопрос по распараллеливанию.

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Получение геометрии элементов
« Ответ #21 : 20-03-2020, 14:45:25 »
К сожалению, нет. COM API медленный по умолчанию. Autodesk, видимо, не имеет особых планов развивать Navis с появлением Forge viewer, функционала BIM 360 (не помню, в каком там продукте у них clash detection). Там, кстати, подобная задача будет очень быстрой...

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

  • ADN OPEN
  • ***
  • Сообщений: 210
  • Карма: 0
Re: Получение геометрии элементов
« Ответ #22 : 30-04-2020, 21:09:29 »
Есть набор элементов ModelItem (это трубы и кабели) для которых modelItem.Geometry.PrimitiveTypes == PrimitiveTypes.Lines.
В Нэвисе они отображаются соответственно цилиндрами. Могу ли я как-то получить их геометрию через API?
Использую класс GeometryBuilder, приведенный Вами выше. Метод Lines там не переопределен, но в него передаются только две точки.
Благодарю за ответы.