Начинаем писать свой экспортёр IFC из AutoCAD Civil3D ввиду отвратительного базового и не подающего надежды нового (в рамках бета-тестирования) модуля по экспорту в IFC.
Срочность также связана с необходимостью решить задачу передачи в IFC труб и колодцев без промежуточного их экспорта в 3д-тела и необходимости повторения этой операции при проектных изменениях.
В данной статье я, наверное, впервые поступил иначе с логикой изложения - сперва разобрался с материалом, а потом уже его описал (а не как я делаю обычно - пишу и корректирую по мере апробации).
И еще одна особенность - я перестаю вставлять тонну картинок, их почти не будет - времени на писанину становится всё меньше .. да и пользы от них немного.
1. О чем пойдет речь?
Речь пойдет о библиотеке GeometryGym на .NET (C# ) для чтения(парсинга)/записи файлов IFC (и также STEP и тестово в IfcXml). Если по библиотекам XBim есть материал, то в отношении GeometryGym такого сказать нельзя - в профиле организации на GitHub есть несколько проектов по работе с геометрией, часть примеров есть на репозитории BuidingSmart, в то время как существенный пласт информации по работе со свойствами и прочим параметрами остается нераскрытым полностью.
Отметим, что GeometryGym распространяется под MIT-лицензией, что дает право на любое использование кода в том числе в коммерческих целях. Небольшой бонус - библиотека почти независима (в качестве внешней зависимости у неё болтается только Newtonsoft.Json, распространяемый к слову также под MIT-лицензией). Так как библиотека представляет собой фактически автономную сборку - её можно запросто скомпилировать самостоятельно (есть также и Nuget-версия).
2. Немного о Civil3D и его представлении геометрии и свойств.
Писать я буду под Civil3D на .NET. (как бы я ни хотел попробовать IfcPlusPlus, писать под Civil на C++ как я понял что-то между самоубийством и безумием; внятной инфы как это сделать я не нашёл, поэтому решил забить).
Так как Civil3D является вертикальным решением на базе AutoCAD, некоторые сущности у нас наследуются от AutoCAD, некоторые вовсе тянутся извне (типа "Наборов характеристик"). Я решил начать с простейшего с точки зрения геометрии элемента - с поверхностей. Про них к тому же я писал, при знакомстве с XBim-библиотекой. Там, правда выяснилось, что он не позволяет создавать некоторые IFC-классы, и я их создавал вручную (в режиме чтения они были).
В дополнение к поверхностям я решил разобраться с наборами характеристик - так как они применимы к любым объектам модели, и методика их получения никак не зависит от типа объекта. Собственно говоря, у объекта в Civil3D есть собственные свойства, свойственные его типу и дополнительные свойства - через наборы характеристик.
Подход с хранением и привязкой свойств в структуре IFC к объекту един. Един также подход с наборами характеристик. То есть нам потребуется лишь свести к единой схеме передачу собственных свойств объектов Civil3D чтобы не дублировать для каждого класса объектов логику присвоения свойств. Так, у поверхности есть 3 собственных набора свойств - General properties, Terrarian properties, Tin properties.
Я принял решения пока хранить свойства в таких громоздких конструкциях:
Dictionary<string, Dictionary<string, object>>, так как групп свойств может быть несколько. Под object пока поддерживаются строки (по умолчанию), целые числа, дробные числа, булевы значения.
Больное место в логике работы со свойства - это невозможность использовать ref-отсылку на объект (передавая методу ссылку на объект а не полное его представление). Это будет немного ухудшать производительность, но зато код не будет содержать лишнего дублирования информации.
Вариант с поиском в готовое базе IFC-файла сохраненного элемента по индексу я не нашел, хоть индекс и сохраняется.
3. Структура экспортера
Пока что я планирую писать модуль как классический командный метод, работающий в данной сессии модели (легко можно будет транслировать и на набор файлов, применив флаг CommandFlags.Session. Потом планирую сделать его с окошечками (для настройки типов объектов, включения панелей свойств; позже - с учетом файлов маппинга геометрии).
Сразу скажу, модуль доступен на GitHub по ссылке ниже:
Это библиотека классов на .NET Framework 4.8 (хотел сперва на 4.7, но на нее заругался GeometryGym).
В базовом классе Start.cs у нас при запуске командного метода "_ifc_export" происходит инициация текущего документа и базы данных, а также базы данных для IFC-файла. Так как мы говорим про работу в Civil3D - для нас базовой структурой в IfcDatabase будет IfcSite (по логике вещей).
Отсюда же, из ConvertToIfc() мы будем вызывать методы отдельных классов, преобразующих объекты и свойства объектов Civil3D в классы IFC.
4. Логика работы с файлом IFC в GeometryGym
Изюминка работы с классами IFC в GeometryGym заключается в автоматической фиксации всех новых классов и свойств классов в базу данных IFC-файла (элемент DatabaseIfc). Фактически, мы используем её как дефолтную для всех создаваемых элементов, а родительский объект (кому передавать свойства, или кого считать родителем - для иерархии в структуре модели) задаем, фиксируя его в соответствующих методах (как сущность IfcObject).
Заметим, что многие IFC классы в GeometryGym наследуют большое число других классов, а именно - все (ну, во всяком случае встречавшиеся) классы геометрических объектов наследуют сущность IfcObject, которая нам и нужна.
Вообще, справка к GeometryGym отсутствует - вместо этого разработчики предлагают ориентироваться на спецификацию формата IFC нужной версии от BuildingSmart, и действительно - ряд вещей я почерпнул оттуда, поскольку как уже упоминал в начале статьи, примеров работы со свойствами я не нашел вообще.
Для нашей первой части я работал с поверхностями - они у меня представлялись как отдельные объекты IfcSite, где IfcSite.Representation выражалась в структуре IfcProductDefinitionShape (конечный набор отдельных граней IfcFace триангуляции поверхности).
С цветом/материалом я решил пока не заморачиваться.
Если с геометрией всё боле-менее понятно, но вот на свойствах хотелось бы остановиться отдельно. Существует практика, когда объекту назначается группа свойств, и от этого я отталкивался. Здесь пока неважно, родные ли это свойства или дополнительные (через наборы характеристик).
Отдельные свойства - это запись IfcPropertySingleValue, принимающее на вход базу данных ifc (у нас const, имя свойства и значение свойства). Значение свойства может быть выражено строкой, дробным числом, целым числом, булевым значением. Чуть шире список у параметра IfcValue но он protected, а кто его наследует я пока не разбирался. Свойство IfcPropertySingleValue наследует во втором поколении класс IfcProperty, что позволяет нам представить набор свойств для объекта как элемент IfcPropertySet. Один из конструкторов для него (IfcPropertySet) включает зависимый объект, наименование (таблицы данных) и коллекцию свойств IfcProperty (у нас это IfcPropertySingleValue, которые наследуют IfcProperty). И всё - оному объекту можно назначить несколько наборов IfcPropertySet, что я и делал.
5. Сохранение данных
Объявление любого класса и поля с конструкцией "new ***" применимо к GeometryGym значит фиксацию элемента в DatabaseIfc, что делает необязательным для пользователя эту операцию.
То есть к моменту окончания обработки данных в чертеже мы вызываем метод DatabaseIfc.WriteFile() и у нас формируется IFC.
6. Ещё заметка
Для демонстрации возможностей, прикладываю также к репозиторию папку "demo" с простыми dwg-файлами, с объектами civil 3d для апробации возможностей модуля.
Не пропускайте публикации, подписывайтесь на Telegram-канал с тизерами статей.
#civil3d #autodesk #ifc #geometrygym