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

ADN Club => AutoCAD .NET API => Тема начата: Georg от 30-12-2021, 17:24:28

Название: Хранение идентификаторов объектов в строчном виде
Отправлено: Georg от 30-12-2021, 17:24:28
Добрый день!
Вопрос заключается в необходимости хранить идентификаторы объектов, которые являются вложенными в данный; к примеру -- грани солида (Faces).
Зачем это надо? Объясняю - есть необходимость обрабатывать данные чертежа в другом ПО и вернуть их же + доп. параметры, которые потом назначить этим элементам. В настоящем примере - материалы для граней тела.

У них [дочерних элементов] отсутствует ObjectId, у которого можно было бы получить Handle, а наличествующий SubentityId не имеет нужного представления.
Вариант с генерацией FullSubentityPath https://adn-cis.org/podsvetka-segmenta-polilinii.html (https://adn-cis.org/podsvetka-segmenta-polilinii.html) тоже не совсем подходит, так как для этого придется создавать дополнительную структуру типа словаря/дерева во время нового перебора граней солидов (во время которого заново находить этот FullSubentityPath, преобразовать в строку и искать по ключу в созданной коллекции). С позиции работы с памятью не очень хорошо .... хоть наверное так пока и поступлю.
Аналогично вместо FullSubentityPath могу использовать "строковый кортеж" типа $"{Solid.Handle}_{Face.Index}".
Также я намеревался использовать в качестве идентификатора грани её центроид (усредненную сумму координат по X,Y,Z) - то есть в целом 3 варианта решения всё равно сводятся к необходимости создания коллекции с сопоставлением ключ:доп. параметры солида, а хотелось бы имея некое строчное представления идентификатора как Handle получать его представление в БД чертежа и производить с ним манипуляции без необходимости сопоставления с чем-либо вспомогательным.

Надеюсь, мысль донёс корректно ....
P.S. Хотя вот что интересно - а этот набор будет упорядочен всегда в рамках текущего состояния солида (не изменяя его) и после перезапуска чертежа (solid_id - это ObjectId солида)
Код - C# [Выбрать]
  1. List < Autodesk.AutoCAD.BoundaryRepresentation.Face > faces = new Brep(new FullSubentityPath(new ObjectId[1] { solid_id }, new SubentityId(SubentityType.Null, IntPtr.Zero))).Faces.ToList();
Название: Re: Хранение идентификаторов объектов в строчном виде
Отправлено: Александр Ривилис от 31-12-2021, 14:38:01
Вариант с генерацией FullSubentityPath https://adn-cis.org/podsvetka-segmenta-polilinii.html тоже не совсем подходит, так как для этого придется создавать дополнительную структуру типа словаря/дерева во время нового перебора граней солидов (во время которого заново находить этот FullSubentityPath, преобразовать в строку и искать по ключу в созданной коллекции).
Не понял зачем перебирать грани солида вторично, если ты знаешь Handle этого солида (и соответственно его ObjectId) и номер грани. По этим критериям и создается FullSubentityPath.
Название: Re: Хранение идентификаторов объектов в строчном виде
Отправлено: Georg от 31-12-2021, 15:05:21
А номер грани это и есть его "номер" в списке Brep.Faces()? Я среди методов не нашел вроде явного номера.
P.S. и да, я чего-то не подумал что перебирать повторно не надо, раз есть явный идентификатор
Название: Re: Хранение идентификаторов объектов в строчном виде
Отправлено: Александр Ривилис от 31-12-2021, 17:28:58
А номер грани это и есть его "номер" в списке Brep.Faces()? Я среди методов не нашел вроде явного номера.
P.S. и да, я чего-то не подумал что перебирать повторно не надо, раз есть явный идентификатор
Глянь этот код: https://adn-cis.org/forum/index.php?topic=7169.msg21059#msg21059
Название: Re: Хранение идентификаторов объектов в строчном виде
Отправлено: Georg от 31-12-2021, 17:50:04
Да, спасибо, это примерно то и есть!.
Только вот очень расстраивает скорость ... у меня порядка 67000 граней и процесс замены материала/цвета занял аж полчаса выполнения (это делалось в рамках одной транзакции).... ускорить никак невозможно для интереса? (хотя сам понимаю что средств никаких нет ... это так безумно плохо видимо внутренняя сортировка организована в AutoCAD)
Название: Re: Хранение идентификаторов объектов в строчном виде
Отправлено: Александр Ривилис от 31-12-2021, 17:52:21
у меня порядка 67000 граней и процесс замены материала/цвета занял аж полчаса выполнения
Нужно смотреть код. Возможно достаточно отключить историю изменений Solid3d и это ускорит процесс (Solid3d.RecordHistory)
Название: Re: Хранение идентификаторов объектов в строчном виде
Отправлено: Georg от 31-12-2021, 18:10:15
Нужно смотреть код
Ну .... пусть будет так:https://github.com/GeorgGrebenyuk/Civil3D.CustomNodes/blob/a890fe6995f766faba93b313b0b7bc655d549dc8/Code/Main/Solids.cs#L143 (https://github.com/GeorgGrebenyuk/Civil3D.CustomNodes/blob/a890fe6995f766faba93b313b0b7bc655d549dc8/Code/Main/Solids.cs#L143) . Я делаю методы под Dynamo (сейчас речь идет про пункт 5 ниже)
Логика ниже описана (статью пишу типа параллельно*)

Теперь наметим алгоритм действий:
1. Получаем набор граней тел как коллекцию центроидов (сразу вычисляем центроид как полусумму координат треугольной грани и фиксируем идентификатор каждой грани - родительское тело и порядковый номер в списке граней).
2. Создаем на базе полученных центроидов точки AutoCAD, назначаем им атрибутику в виде ObjectData
3. Экспортируем полученные точки с атрибутикой в SHP-файл;
4. В среде QGIS проводим операцию определения попадания точек в полигоны инструментом Join attributes by location и экспортируем точки с новым атрибутом типа полигона обратно в Civil 3D. При этом заменяем null на другое значение (для территории суши).
5. Загружаем точки mapimport'ом и запускаем второй скрипт, который сперва отсортирует массив точек по спискам (применимо к солиду) и для грани каждого присвоит материал\цвет в зависимости от условия (чтобы не "запрашивать" для произвольной точки свой солид и его внутрянку -- сразу делаем в рамках 1 солида все действия).
Название: Re: Хранение идентификаторов объектов в строчном виде
Отправлено: Александр Ривилис от 31-12-2021, 18:11:14
А номер грани это и есть его "номер" в списке Brep.Faces()?
Номер грани это face.SubentityPath.SubentId.IndexPtr
Название: Re: Хранение идентификаторов объектов в строчном виде
Отправлено: Александр Ривилис от 31-12-2021, 18:17:08
Georg,
А теперь посмотри на чем происходит основная потеря времени.
Название: Re: Хранение идентификаторов объектов в строчном виде
Отправлено: Georg от 31-12-2021, 18:20:35
А теперь посмотри на чем происходит основная потеря времени
А как это отлавливать (инструментом)? Я пока не пробовал такое в отношении кода. В отношении программ как-то пользовался Windows Performance Analyzer но тут другое ...
Название: Re: Хранение идентификаторов объектов в строчном виде
Отправлено: Александр Ривилис от 31-12-2021, 18:58:55
А теперь посмотри на чем происходит основная потеря времени
А как это отлавливать (инструментом)? Я пока не пробовал такое в отношении кода. В отношении программ как-то пользовался Windows Performance Analyzer но тут другое ...
Не инструментом, а через Windows API.
Вот эта строка мне подозрительна на предмет быстродействия:
Код - C# [Выбрать]
  1. List<Autodesk.AutoCAD.BoundaryRepresentation.Face> solid_faces = brep.Faces.ToList();
Фактически это итерация по всем граням солида, а это имеет смысл только в том случае если ты собираешься менять цвет/материал всем граням, а не только некоторым.
Название: Re: Хранение идентификаторов объектов в строчном виде
Отправлено: Georg от 31-12-2021, 19:23:31
сли ты собираешься менять цвет/материал всем граням
Всем "поверхностным" вообще-то и собираюсь ... другой вопрос, я так и не понял, как ограничить коллекцию граней только теми, которые относятся к верхней кромке (минуя нижнюю плоскость тела и боковые грани).
Но насчет списка я согласен - заменил это на идентификатор типа 
Код - C# [Выбрать]
  1. string Face_Id = $"{OneSolidId.Handle}_{face.SubentityPath.SubentId.IndexPtr.ToInt64()}";

А инициализирую грань вот так:
Код - C# [Выбрать]
  1. foreach (KeyValuePair<string, string> face_info in faces_info)
  2.                             {
  3.                                 long FaceNumber = Convert.ToInt64(face_info.Key.Split('_')[1]);
  4.                                 IntPtr face_IntPtr = (IntPtr)FaceNumber;
  5.                                 FullSubentityPath path2 = new FullSubentityPath(new ObjectId[1] { OneSolidId }, new SubentityId(SubentityType.Null, face_IntPtr));
  6.                                 using (Brep frep_face = new Brep(path2))
  7.                                 {
  8.                                     Autodesk.AutoCAD.BoundaryRepresentation.Face face = frep_face.Faces.First();

Потом запущу так для интереса ... но тут смущает необходимость программного обращения к этим граням - мб и тут тоже будет тормоза. Я проверял без этого метода - точки сортируются п словарям и прочие действия что на "вход" подаются выполняются до 2 минут.
Название: Re: Хранение идентификаторов объектов в строчном виде
Отправлено: Александр Ривилис от 31-12-2021, 20:24:27
Georg,
Что-то мне кажется, что вместо:
Код - C# [Выбрать]
  1. FullSubentityPath path2 = new FullSubentityPath(new ObjectId[1] { OneSolidId }, new SubentityId(SubentityType.Null, face_IntPtr));
должно быть:
Код - C# [Выбрать]
  1. FullSubentityPath path2 = new FullSubentityPath(new ObjectId[1] { OneSolidId }, new SubentityId(SubentityType.Face, face_IntPtr));
Название: Re: Хранение идентификаторов объектов в строчном виде
Отправлено: Georg от 31-12-2021, 23:26:52
должно быть:
Не совсем правда понимаю где именно это вводить -- на этапе первичной выборки или когда ищу грань по номеру в теле? Во втором случае оно итак грань (по номеру), думаю смысла не будет. А в первом не уверен как это поможет ...

Результаты тестов - если раньше с тем List() выполнялось за 32 минуты, то сейчас  без него с обращением к грани по номеру выходит аж 54 минут. Вообще конечно результаты убивающие, не понимаю почему так медленно. На поверхности из 2100 граней отрабатывает почти мгновенно. Сам файл приложу позже ... авось кто разберется. Так что откатываюсь на момент списка, где хоть как-то работало.

Вообще, так как это тело нельзя экспортировать в IFC (не передается ни цвет ни материал) эта задача мне не нужна ... нет так нет. Интересно больше почему так.
P.S. Взамен можно было бы делать с МПолигонами с нужным цветом по граням тела, а их там уже и как ГИС-примитивы можно передавать со свойством цвета ...
Название: Re: Хранение идентификаторов объектов в строчном виде
Отправлено: Georg от 01-01-2022, 02:59:08
Наконец-то получилась стабильная версия  ;D, не вылетающая и на большом солиде.
https://github.com/GeorgGrebenyuk/Civil3D.CustomNodes/blob/cb422bcff7c0081fa8b9d1735f4fe82d59c3dab1/Code/Main/Solids.cs#L152 (https://github.com/GeorgGrebenyuk/Civil3D.CustomNodes/blob/cb422bcff7c0081fa8b9d1735f4fe82d59c3dab1/Code/Main/Solids.cs#L152)
Транзакцию перевел в Solid.ObjectId.Open() и тогда вылетать перестало (на моменте tr.Commit()).
Кстати если в методе по назначению материала сделать вместо этого (стабильно работает на этапе получения граней тела для поиска центроида):
Код - C# [Выбрать]
  1. FullSubentityPath path = new FullSubentityPath(new ObjectId[1] { OneSolidId }, new SubentityId(SubentityType.Null, IntPtr.Zero));
вот так:
Код - C# [Выбрать]
  1. FullSubentityPath path = new FullSubentityPath(new ObjectId[1] { OneSolidId }, new SubentityId(SubentityType.Face, IntPtr.Zero));
То выбьется такое исключение.
(https://i.postimg.cc/ZCY5L7JH/image.png) (https://postimg.cc/ZCY5L7JH)
По скорости вообще не заметил особо преимущества, что с ним что без него.
Отмечу как решение тот ваш пост, так как по сути в нём и ответ - оборачивание метода в Open без транзакции и получение идентификатора грани солида.


P.S. Ищу тег материала, как запрос ключа словаря строки типа "Solid.Handle_Face.Id"
Более подробно всю методику расписал в статье.
https://zen.yandex.ru/media/id/5d0dba97ecd5cf00afaf2938/autocad-3d-api-i-osm-naznachaem-materialy-graniam-3dtel-61cd4b2205c49671f55b07af (https://zen.yandex.ru/media/id/5d0dba97ecd5cf00afaf2938/autocad-3d-api-i-osm-naznachaem-materialy-graniam-3dtel-61cd4b2205c49671f55b07af)

Не инструментом, а через Windows API.
P.P.S. Буду также благодарен за направление где посмотреть примеры такой отладки ... а то в процессе настройки текущих он вылетал вообще без каких-либо Exception
Название: Re: Хранение идентификаторов объектов в строчном виде
Отправлено: Александр Ривилис от 01-01-2022, 17:19:22
Цитата: Александр Ривилис от 31-12-2021, 17:58:55

    Не инструментом, а через Windows API.

P.P.S. Буду также благодарен за направление где посмотреть примеры такой отладки ... а то в процессе настройки текущих он вылетал вообще без каких-либо Exception
А причем здесь отладка? Речь шла про получение времени выполнения участков кода. Посмотри здесь одну из возможностей: https://docs.microsoft.com/ru-ru/dotnet/api/system.diagnostics.stopwatch?view=net-6.0