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

ADN Club => Forge: Data Management API => Тема начата: Александр Пекшев aka Modis от 27-09-2021, 12:34:37

Название: BIM360 Issue pushpin - в каких координатах?
Отправлено: Александр Пекшев aka Modis от 27-09-2021, 12:34:37
Если из BIM360 Docs получать Issues, "привязанные" к файлам (в основном это файлы Navisworks), то у Issue будут данные по булавке (pushpin):
(https://i.postimg.cc/LYZxb80r/Screenshot-4.png) (https://postimg.cc/LYZxb80r)

Булавку, в свою очередь, можно "прикрепить" только к элементу модели. Например, используя плагин Coordination Issues for Autodesk® Navisworks® (https://apps.autodesk.com/NAVIS/en/Detail/Index?id=5155805354033590972)

Возникла задача - найти элемент в модели Navisworks по координатам pushpin. Но никакой справочной информации я не смог найти. Главный вопрос - что это за координаты location и как перевести их в координаты модели?
Название: Re: BIM360 Issue pushpin - в каких координатах?
Отправлено: Александр Игнатович от 27-09-2021, 13:06:44
На вскидку, нужно учесть globalOffset, как вот здесь:
https://adn-cis.org/map-forge-viewer-camera-back-to-navisworks.html
Название: Re: BIM360 Issue pushpin - в каких координатах?
Отправлено: Александр Игнатович от 27-09-2021, 13:09:16
Я бы ещё посмотрел вот в эту сторону на всякий случай
Код - Javascript [Выбрать]
  1. NOP_VIEWER.model.getModelToViewerTransform()
Название: Re: BIM360 Issue pushpin - в каких координатах?
Отправлено: Александр Пекшев aka Modis от 27-09-2021, 14:33:17
Спасибо за ссылки, но вопрос-то в другом.
Из плагина я "вынул" кусок, который восстанавливает точку обзора:
Код - C# [Выбрать]
  1. public static void RestorePushPinViewpoint(Autodesk.Navisworks.Api.View view, PushPinData data)
  2. {
  3.     if (view == null)
  4.         return;
  5.  
  6.     var viewpoint = view.CreateViewpointCopy();
  7.     if (data.Target != null)
  8.     {
  9.         viewpoint.Position = LinearUtils.ArrayToPoint3D(data.Eye);
  10.         viewpoint.AspectRatio = data.AspectRatio;
  11.         viewpoint.WorldUpVector = new UnitVector3D(Autodesk.Navisworks.Api.Application.ActiveDocument.UpVector);
  12.         viewpoint.PointAt(LinearUtils.ArrayToPoint3D(data.Target));
  13.         viewpoint.AlignUp(LinearUtils.ArrayToVector3D(data.Up));
  14.         viewpoint.Projection = data.IsOrthographic ? ViewpointProjection.Orthographic : ViewpointProjection.Perspective;
  15.         if (data.IsOrthographic)
  16.         {
  17.             if (!data.OrthographicHeight.HasValue)
  18.             {
  19.                 throw new ArgumentException(
  20.                     @"Invalid viewpoint. Is orthographic but no orthographicHeight specified.",
  21.                     nameof(data.OrthographicHeight));
  22.             }
  23.            
  24.             viewpoint.HeightField = data.OrthographicHeight.Value;
  25.         }
  26.         else
  27.         {
  28.             if (!data.FieldOfView.HasValue)
  29.             {
  30.                 throw new ArgumentException(
  31.                     @"Invalid viewpoint. Is perspective but no fieldOfView specified.",
  32.                     nameof(data.FieldOfView));
  33.             }
  34.            
  35.             viewpoint.HeightField = LinearUtils.DegreesToRadians(data.FieldOfView.Value);
  36.         }
  37.     }
  38.     else
  39.     {
  40.         viewpoint.ZoomBox(Autodesk.Navisworks.Api.Application.MainDocument.GetBoundingBox(true));
  41.     }
  42.    
  43.     view.CopyViewpointFrom(viewpoint, ViewChange.JumpCut);
  44.     view.RequestDelayedRedraw(ViewRedrawRequests.OverlayRender);
  45. }

И перед этим еще производится трансформ:
Код - C# [Выбрать]
  1. public static bool TryTransformPushPinData(Pushpin data, Model model, out PushPinData transformedData)
  2. {
  3.     if (model != null)
  4.     {
  5.         transformedData = new PushPinData(data);
  6.        
  7.         if (!Path.GetExtension(new Uri(model.FileName).LocalPath)
  8.             .Equals(".nwd", StringComparison.OrdinalIgnoreCase))
  9.         {
  10.             Transform3D modelToWorldTransform = GetModelToWorldTransform(model);
  11.             transformedData.Location = TransformPoint(data.Location, modelToWorldTransform);
  12.             transformedData.Eye = TransformPoint(data.Eye, modelToWorldTransform);
  13.             transformedData.Target = TransformPoint(data.Target, modelToWorldTransform);
  14.         }
  15.  
  16.         if (transformedData.IsOrthographic && transformedData.OrthographicHeight.HasValue)
  17.         {
  18.             double num = Autodesk.Navisworks.Api.Interop.LcOaUnit.ScaleFactor(model.Units,
  19.                 Autodesk.Navisworks.Api.Application.MainDocument.Models.First.Units);
  20.             transformedData.OrthographicHeight *= num;
  21.         }
  22.        
  23.         return true;
  24.     }
  25.  
  26.     transformedData = null;
  27.     return false;
  28. }
  29.  
  30. private static Transform3D GetModelToWorldTransform(Model model)
  31. {
  32.     double value = Autodesk.Navisworks.Api.Interop.LcOaUnit.ScaleFactor(
  33.         model.Units,
  34.         Autodesk.Navisworks.Api.Application.MainDocument.Models.First.Units);
  35.     Transform3DComponents transform3DComponents = model.Transform.Factor();
  36.     transform3DComponents.Scale = transform3DComponents.Scale.Multiply(value);
  37.     return transform3DComponents.Combine();
  38. }
  39.  
  40. private static double[] TransformPoint(double[] pnt, Transform3D transform)
  41. {
  42.     return LinearUtils.Vector3DToArray(new Vector3D(pnt[0], pnt[1], pnt[2]).Multiply(transform.Linear).Add(transform.Translation));
  43. }
  44.  


Там есть некоторые неясные моменты, но в тестовом файле все работает - точка обзора восстанавливается как надо.
При создании булавок используется метод View.PickItemFromPoint (https://apidocs.co/apps/navisworks/2018/M_Autodesk_Navisworks_Api_View_PickItemFromPoint_2_22dcb54d.htm). Как я понял - эта точка - PickItemResult.Point - это и есть точка location. Но скорее всего я ошибаюсь

А вопрос в том - как имея location найти элемент в модели? Какие обратные процедуры произвести?
Название: Re: BIM360 Issue pushpin - в каких координатах?
Отправлено: Александр Игнатович от 27-09-2021, 15:21:25
А вопрос в том - как имея location найти элемент в модели? Какие обратные процедуры произвести?

Где ты ищешь элемент? В Navisworks или Forge Viewer?

Если в Navisworks, тогда нужно преобразовать координаты, pushpin имеет координаты в системе координат Viewer-а (логично, вроде), есть матрица перехода model-to-viewer, можно получить обратную viewer-to-model. Ну или ещё проще, вряд ли при трансформации модели будет назначен какой-то поворот или масштабирование, взять global offset как в статье предложено. С API Navisworks-а мало имел и совсем давно, возможно, там есть что-то для пространственного поиска.

Если речь про поиск в Forge Viewer, то преобразовывать координаты не нужно. Сам поиск можно реализовывать по разному в зависимости от задачи. Если одноразово, то можно простым перебором, если многоразово, то, наверное, стоит по boundingbox-ам построить R-Tree, искать уже в нём

Название: Re: BIM360 Issue pushpin - в каких координатах?
Отправлено: Александр Пекшев aka Modis от 27-09-2021, 15:44:42
Где ты ищешь элемент? В Navisworks или Forge Viewer?
В Navisworks

можно получить обратную viewer-to-model
Как? Я не понимаю

В модели вот примерно такие координаты (центры BB):
Цитировать
Element 802034 bb center: (9952,5384326613802841, 70816,2968044955487130, 522,9658793952521592)
Element 802423 bb center: (10204,6086616059928929, 70569,3836395785911009, 523,2939633847535106)
Element 1340572 bb center: (9834,1697264512931724, 70497,0170252555108164, 520,3412074942601748)

Булавки вот с такими координатами:
Цитировать
Issue 495 pushpin: -168,621583508413, -100,020605428304, 7,31800306525327
Issue 494 pushpin: 201,793944775753, -27,6070030396659, 9,06755644286818
Issue 493 pushpin: -50,2509445499618, 220,224071918055, 15,971968234686

Видно, что координаты не особо коррелируют, что указывает на правдивость высказывания
Цитировать
pushpin имеет координаты в системе координат Viewer-а (логично, вроде)

Но что и как преобразовывать - я не понимаю
Название: Re: BIM360 Issue pushpin - в каких координатах?
Отправлено: Александр Игнатович от 27-09-2021, 17:49:19
Набросал чуток кода:
Код - Javascript [Выбрать]
  1. function getLeafFragIds (model, leafId) {
  2.         const instanceTree = model.getInstanceTree();
  3.        
  4.         const fragIds = [];
  5.        
  6.         instanceTree.enumNodeFragments(leafId, (fragId) => {fragIds.push(fragId)});
  7.        
  8.         return fragIds;
  9. }
  10.  
  11. function getBoundingBox(fragIds, fragList) {
  12.     const fragbBox = new THREE.Box3();
  13.     const nodebBox = new THREE.Box3();
  14.     fragIds.forEach(function(fragId) {
  15.         fragList.getWorldBounds(fragId, fragbBox);
  16.         nodebBox.union(fragbBox);
  17.     });
  18.  
  19.     return nodebBox;
  20. }
  21.  
  22. const box = getBoundingBox(getLeafFragIds(NOP_VIEWER.model, NOP_VIEWER.getSelection()[0]), NOP_VIEWER.model.getFragmentList())
  23.  
  24. const offset = NOP_VIEWER.model.getGlobalOffset();
  25. console.log(new THREE.Vector3().copy(box.min).add(offset))
  26. console.log(new THREE.Vector3().copy(box.max).add(offset))

Revit:
(https://i.postimg.cc/XGVCmbGx/Revit.png) (https://postimg.cc/XGVCmbGx)
Forge:

(https://i.postimg.cc/v188dHh1/Forge.png) (https://postimg.cc/v188dHh1)
Название: Re: BIM360 Issue pushpin - в каких координатах?
Отправлено: Александр Пекшев aka Modis от 27-09-2021, 18:01:40
А как код для форджа поможет мне решить проблему в нэвисе? При том, что с форждом я вообще не работаю
Название: Re: BIM360 Issue pushpin - в каких координатах?
Отправлено: Александр Игнатович от 27-09-2021, 18:58:21
При том, что с форждом я вообще не работаю
Ну сорри, не понял, что Forge viewer не при делах.

Смотри, global offset - это центр bounding box-а всей модели, вот ссылка на дискуссию, где это обсуждается: https://stackoverflow.com/questions/42148538/aligning-coordinate-systems-in-autodesk-forge-viewer

Цитировать
What is this offset? the difference between (0,0,0) and where the model was placed originally?
Цитировать
Correct. The viewer will load the model by placing the center of its bounding box at the origin, so depending on the original file, this may add an offset which is returned by the property discussed above.

Philippe доверять можно :-)

А дальше по аналогии переходить от координат во вьювере к модельными координатам
Название: Re: BIM360 Issue pushpin - в каких координатах?
Отправлено: Александр Пекшев aka Modis от 28-09-2021, 10:28:54
Ну нет в нэвисе Viewer'а! И нет там свойства GlobalOffset...
Название: Re: BIM360 Issue pushpin - в каких координатах?
Отправлено: Александр Игнатович от 28-09-2021, 10:41:13
И? я и не говорил, что тебе нужен viewer в navis. Я как бы показал, как считается GlobalOffset
Название: Re: BIM360 Issue pushpin - в каких координатах?
Отправлено: Александр Пекшев aka Modis от 28-09-2021, 10:57:43
Вот как работает плагин автодеска:
Юзер тыкает в элемент модели и плагин получает PickItemResult (https://apidocs.co/apps/navisworks/2018/T_Autodesk_Navisworks_Api_PickItemResult.htm). У этого результат есть свойство Point, которое:
Цитировать
The picked point on the surface of the picked model item (in world space).
В мировой системе координат!

Дальше плагин делает вот так:

(https://i.postimg.cc/DJYgPSQV/Screenshot-7.png) (https://postimg.cc/DJYgPSQV)

Если это nwd (а именно на таком случае я тестирую), то просто отправляет эту точку.

Значит, логично предположить, что из BIM360 я получаю эту точку в мировой системе координат и мне нужно трансформировать её в систему координат модели. В том-же плагине есть такие методы:

(https://i.postimg.cc/dL07KWK9/Screenshot-8.png) (https://postimg.cc/dL07KWK9)

Я попробовал их оба (на всякий случай):
Код - C# [Выбрать]
  1. Transform3D modelToWorldTransform = GetModelToWorldTransform(model);
  2. var worldToModelTransform = GetWorldToModelTransform(model);
  3. Debug.Print($"Issue origin location: {data.Location[0]}, {data.Location[1]}, {data.Location[2]}");
  4. var d = TransformPoint(data.Location, modelToWorldTransform);
  5. Debug.Print($"Issue transformed model to world location: {d[0]}, {d[1]}, {d[2]}");
  6. d = TransformPoint(data.Location, worldToModelTransform);
  7. Debug.Print($"Issue transformed world to model location: {d[0]}, {d[1]}, {d[2]}");

и получил такой результат:
Цитировать
Issue origin location: 201,793944775753, -27,6070030396659, 9,06755644286818
Issue transformed model to world location: 201,793944775753, -27,6070030396659, 9,06755644286818
Issue transformed world to model location: 201,793944775753, -27,6070030396659, 9,06755644286818

А вот как выглядят свойства модели:
(https://i.postimg.cc/f3dCfz2k/Screenshot-9.png) (https://postimg.cc/f3dCfz2k)

т.е. там нет никакого трансформа

Так что это за координаты и как их трансформировать? Где и как я тут могу использовать GlobalOffset?

Название: Re: BIM360 Issue pushpin - в каких координатах?
Отправлено: Александр Игнатович от 28-09-2021, 11:40:05
GlobalOffset - это вектор в центр bounding box-а модели
Название: Re: BIM360 Issue pushpin - в каких координатах?
Отправлено: Александр Пекшев aka Modis от 28-09-2021, 16:40:22
Александр Игнатович, да, ты был прав с самого начала. Я не заметил, что GlobalOffset тоже можно получить из Issue. Если банально сложить координаты булавки с координатами GlobalOffset, то получаются вроде нужные значения.
Правда, оказалось, что к Issue можно привязать несколько элементов, поэтому задачу реализовывать не стали и решили пойти другим путем. Спасибо за участие
Название: Re: BIM360 Issue pushpin - в каких координатах?
Отправлено: Александр Игнатович от 28-09-2021, 16:42:55
You are welcome