Модуль обмена данными C3D Converter, работая с деревом модели, оперирует двумя основными сущностями — компонентом, который в свою очередь может быть деталью или сборкой, и вставкой одного компонента в другой. Возможны разные интерпретации, что считать компонентом: в C3D ему соответствует файл САПР, содержащий в разной комбинации собственные элементы (тела, кривые) и ссылки на другие компоненты. Кроме того, у компонента есть идентификатор, имя, сведения об авторе и организации.
Один из наиболее популярных вопросов — что делать с моделями, импортированными из файлов обменных форматов? Как извлечь компоненты, из которых состоит модель, с учетом вложенности?
C3D Converter умеет отображать дерево модели на объекты ядра C3D Modeler — наследники класса MbItem. Этот функционал, в частности, используется функциями семейства ImportFrom, которые работают с объектами C3D. Одну из них можно вызвать, например, таким образом:
#include <conv_i_converter.h> c3d::ItemSPtr rootItem; c3d::string_t importPath;//=... const MbeConvResType importResult = c3d::ImportFromFile( rootItem, importPath, C3D_NULL_PTR, C3D_NULL_PTR );
Алгоритм формирования модели нацелен на то, чтобы представить дерево модели, по возможности, наименьшим количеством объектов, необходимым для описания формы изделия и соотношения между его частями.
В том случае, если компонент нельзя отождествить с элементом, который он содержит, формируется объект типа MbAssembly. В него включаются как собственные компоненты, так и ссылки на другие элементы. Ссылки при этом также, по возможности, сводятся к вставке компонента без использования MbInstance.
Структуру модели можно вывести на консоль следующей функцией:
//------------------------------------------------------------------------------ // Вывести структуру документа в стандартный поток // --- void PrintItemsInfoFromContent( const MbItem* item, const std::string& preStr ) { if ( item != C3D_NULL_PTR ) return; std::cout << preStr; PrintProductAttributes( *item ); switch (item->IsA()) { case st_Solid: std::cout << "Тело " << ( static_cast<const MbSolid&>(*item).IsClosed() ? "замкнутое " : "открытое " ) << std::setbase(16) << item << std::setbase(10) << std::endl; break; case st_Mesh: std::cout << "Полигональный объект" << std::setbase(16) << item << std::setbase(10) << std::endl; break; case st_WireFrame: std::cout << "Проволочный каркас" << std::setbase(16) << item << std::setbase(10) << std::endl; break; case st_Instance: { const MbInstance& inst = static_cast<const MbInstance&>(*item); std::cout << "Вставка " << std::setbase(16) << inst.GetItem() << std::setbase(10) << std::endl; PrintItemsInfoFromContent( inst.GetItem(), preStr + " " ); } break; case st_Assembly: { std::cout << "Составной элемент " << std::setbase(16) << item << std::setbase(10) << std::endl; const MbAssembly& assm = static_cast<const MbAssembly&>(*item); for (size_t ind = 0, sz = assm.ItemsCount(); ind < sz; ind++) { PrintItemsInfoFromContent(assm.GetItem(ind), preStr + " " ); } } break; default: std::cout << "Нереализованный случай " << std::setbase(16) << item << std::setbase(10) << std::endl; break; } }
По-хорошему, для каждого компонента должен быть определен, по крайней мере, его алфавитно-числовой идентификатор, чтобы пользователи могли однозначно различать их между собой. Для хранения информации, специфической для компонентов, в ядре C3D Modeler есть специальные объекты — атрибуты изделия.
Ниже приведен пример работы с двумя атрибутами изделия — обязательным MbProductInfo и опциональным MbPersonOrganizationInfo.
#include <attr_product.h> //------------------------------------------------------------------------------ // Вывести атрибуты изделия в стандартный поток // --- void PrintProductAttributes( const MbItem& item ) { AttrVector productAttr; item.GetAttributes( productAttr, at_ProductAttribute, at_ProductInfo ); if ( (!productAttr.empty()) && (productAttr.front() != C3D_NULL_PTR) ) { const MbProductInfo& prod = *(static_cast<MbProductInfo*>(productAttr.front())); string_t id, name, descr; std::cout << "* MbProductInfo * " << (prod.IsAssembly() ? "Сборка" : "Деталь") << ToSTDstring( prod.GetId() ) << " : " << ToSTDstring( prod.GetName() ) << '\t'; } productAttr.clear(); item.GetAttributes( productAttr, at_ProductAttribute, at_PersonOrganizationInfo ); if ( (!productAttr.empty()) && (productAttr.front() != C3D_NULL_PTR) ) { const MbPersonOrganizationInfo& persOrg = *(static_cast<MbPersonOrganizationInfo*>(productAttr.front())); std::cout << "* MbPersonOrganizationInfo * " << ToSTDstring( persOrg.NameOneLine() ) << '\t'; } }
Отметим, что возможны ситуации, когда объект, являющийся потомком MbItem, не несет атрибутов изделия, но таких случаев лучше избегать. Подобные модели, как правило, построены при недостатке исходных данных в условиях, когда нужно сохранить форму изделия и его структуру.
Автор:
Александр Спиваков
Руководитель разработки C3D Converter