Manifold Geometry // Многообразная Геометрия

Сборки в OpenCascade

/ Просмотров: 4644
Выражаю благодарность инженерам с форума САПР-2000 за прояснение терминологических вопросов.

Глоссарий

Assembly Сборка Иерархия узлов сложного изделия.
Subassembly Подсборка Узел Сборки, не являющийся Деталью.
Part Деталь Атомарный элемент Сборки.
Original Оригинал Деталь или Подсборка.
Instance (occurrence) Вхождение Вхождение Оригинала (Детали или Подсборки) с заданной локальной трансформацией (placement).
Component Компонент Вхождение в составе Сборки. Компонент — это всегда Вхождение. Но Вхождение может не быть Компонентом, если оно не вложено в Сборку.
Assembly constraint Сопряжение Тип взамного расположения деталей в сборке (совпадение, соосность).
Assembly item Сборочная единица Любой узел иерархии сборки (корень, Вхождение Детали или Подсборки).

Рис. 1. Принятые термины иллюстрируются через сценарии Part Design и Assembly Design. Part — это геометрическая модель детали, которая вкладывается в сборку путем привязки к соседним узлам. Деталь, вложенная в сборку, — это вхождение (instance). Вхождения группируются в подсборках, после чего могут быть вложены как целое в другие узлы сборки.

Пожалуй, наиболее туманным терминологическим вопросом остается различие между ДЕТАЛЬЮ и ее ВХОЖДЕНИЕМ в сборку. Инженер не говорит «вхождение» (instance), инженер говорит «деталь» (part). Термин ВХОЖДЕНИЕ применяется тогда, когда нужно подчеркнуть, что данная конкретная деталь в сборке есть передвинутая копия другой детали. Обе такие детали ссылаются на одну и ту же геометрию части изделия (еще говорят «позицию»), которая проектируется отдельно и ничего не знает о сборках. Мы будем говорить, что сборка набирается из вхождений деталей, чтобы подчеркнуть это различие между сортаментом и его использованием (usage occurrence). Это немного корявый, но достаточно точный язык для разговора о вещах на том техническом уровне, который нам здесь нужен.

Введение

Библиотека OpenCascade умеет читать и писать разнообразные форматы САПР-данных. Самые востребованные — это нейтральные STEP и IGES. Наряду с геометрией, CAD-файл чаще всего содержит некоторые мета-данные, такие как имена объектов, их цвета, материалы, размерности и допуски (dimensions and tolerances), сопряжения и прочее. Модель без ассоциативных данных ничего не сообщает о способе производства и не несет никакой информации для технолога. Это не более чем кусок геометрии в пространстве, где намерения проектировщика, если и сохранились, то не иначе как в виде топологии модели.

Записать геометрию в формате STEP можно очень по-разному, и обилие вариантов привело к появлению так называемых «рекомендованных практик», то есть советов из разряда «делай так». Неоднозначность представления геометрии, обилие всевозможных мета-данных, попытка объять необъятное в самом формате — все это делает процесс написания собственного STEP-транслятора похожим на затяжной эволюционный процесс. К счастью, в открытой библиотеке OpenCascade плодами этого процесса может воспользоваться кто угодно. Посмотрим на что похоже чтение STEP-файла при наличии мета-данных.

Код, приведенные в данной заметке, справедлив для версии билиотеки OpenCascade 7.1.

Начем с кода для чтения STEP:

bool xde_STEP::Read(const TCollection_AsciiString& filename,
                    Handle(TDocStd_Document)&      result_document)
{
  STEPCAFControl_Reader Reader;
  Handle(XSControl_WorkSession) WS = Reader.Reader().WS();
  
  // Read CAD and associated data from file
  try
  {
    if ( !Reader.ReadFile( filename.ToCString() ) )
    {
      std::cout << "Cannot read STEP file" << std::endl;
      return false;
    }
    
    // Translate model into document
    if ( !Reader.Transfer(result_document) )
    {
      std::cout << "Cannot transfer CAD data from STEP file to XDE" << std::endl;
      return false;
    }
  }
  catch ( ... )
  {
    std::cout << "Exception on reading STEP file" << std::endl;
    return false;
  }
  return true;
}

В библиотеке OpenCascade все пользовательские атрибуты хранятся в структурах OCAF, и мета-данные не исключение. OCAF — отдельная тема, которой мы пока не будем касаться подробно. Упрощенно говоря, OCAF — это инструментарий OpenCascade, позволяющий связать геометрию с произвольными пользовательскими данными. Соответствующие пользовательские структуры данных не встраиваются в геометрию на уровне B-Rep, но оборачивают ее. Иными словами, геометрия в OpenCascade ничего не знает о своих мета-данных.

Двумя важнейшими понятиями OCAF являются метка и атрибут. Метка — это адрес кусочка данных в общей иерархической структуре. С меткой связаны атрибуты — реальные носители данных. Если метки задают «скелет» метагеометрической модели, то атрибуты — это ее «мягкие ткани». Ниже мы рассмотрим как задача обмена инженерными данными решена в библиотеке OpenCascade при помощи модуля OCAF.

Структура сборки

Общие сведения

Возьмем в качестве примера несложную сборку, состоящую из 18 изолированных твердых тел (рис. 2). Это одна из тестовых моделей, доступных на сайте CAx-IF.

Рис. 2. Сборка.

В том, что эти тела изолированы, можно убедиться, рассмотрев, например, граф смежности граней сборки (рис. 3). Мы видим 18 плавающих молекул, отвечающих каждому твердому телу.

Рис. 3. Граф смежности граней.

В действительности же модель содержит всего лишь 5 принципиально различных твердотельных объектов. Остальные тела можно получить путем добавления некоторой трансформации к основному геометрическому описанию (обратите внимание, что геометрия уголков и болтов идентична на рис. 2). Такой подход — не более чем оптимизация, ведь повторящиеся детали можно хранить в единственном экземпляре, тем самым экономя память и ускоряя запись / чтение. Иными словами, у нас есть 5 деталей и 18 вхождений этих деталей, а также их логических групп. Посмотрим, как выглядит модель с мета-данными в структуре OCAF (рис. 4).

Рис. 4. Внутренняя структура модели с мета-данными.

На рис. 4 показан один из способов разложить геометрию модели и ее мета-данные при помощи OCAF. Это одна из бесконечного множества допустимых схем хранения данных, причем уже реализованная в OpenCascade и доступная в стандартной поставке. Данная схема имеет собственное название — XDE (eXtended Data Exchange). Посмотрим теперь на структуру XDE более пристально.

XDE использует довольно запутанный формат хранения данных. OCAF — это не просто иерархия меток и простейших атрибутов типа «строка» или «число». Атрибут умеет ссылаться на другой атрибут или другую метку, создавая тем самым косвенные графы отношений между данными. В одном дереве может сидеть произвольное количество невидимых на первый взгляд деревьев, и понимание такого рода переплетенных структур перестает быть интуитивным. Это похоже на голографическое изображение: смотрим с разных ракурсов и видим разные картинки. Такой механизм предоставляет неограниченные возможности по проектированнию метагеометрической модели, поэтому будьте бдительны и старайтесь выбирать максимально простые способы организации данных. Или используйте проверенные универсальные схемы, такие как TObj или Active Data. В указанных библиотеках полет фантазии программиста ограничен без ущерба для гибкости.

Ветка Shapes (идентификатор 0:1:1) содержит в качестве дочерних элементов все детали и вхождения. Этот уровень структуры XDE можно назвать уровнем объявлений. Здесь мы найдем все геометрические или логические объекты, из которых компонуется модель. Следующий уровень — это уровень вхождений. Здесь каждая объявленная деталь или сборка связывается со своими дочерними деталями или сборками. Если дочерний объект — это сборка, то ее объявление следует искать на первом уровне. То есть при работе с физической организацией документа XDE важно иметь в виду, что вложения на уровне меток — всегда двухуровневые.

Действительная геометрия содержится в объектах уровня объявлений. На уровне вхождений мы имеем, очевидно, вхождения т.е. легковесные объекты, содержащие ссылку на уникальную деталь и матрицу трансформации (rigid body transformation). Для работы с веткой Shapes используется инструментальный класс XCAFDoc_ShapeTool. Информация о том, является ли объект уровня объявлений логическим контейнером (сборкой) представлена специальным атрибутом TDataStd_UAttribute. Если этот атрибут есть, значит сборка. Если нет — значит геометрическое тело. Данная проверка реализована методом IsAssembly() класса XCAFDoc_ShapeTool.

Связь вхождения детали (instance) и ее геометрии реализована атрибутом TDataStd_TreeNode. Этот атрибут создает косвенное дерево отношений между объектами. Если у нашего объекта в данном косвенном дереве есть родитель, то такой объект является чьим-то вхождением. На практике это означает, что его геометрическое описание следует искать в другом месте, и вообще всю геометрическую работу вести с оригиналом. Узнать, является ли объект вхождением можно при помощи метода IsReference() класса XCAFDoc_ShapeTool.

Если у объекта нет вхождений, то он называется СВОБОДНЫМ объектом. Эта проверка реализуется методом XCAFDoc_ShapeTool::IsFree(), который проверяет, что атрибут TDataStd_TreeNode либо не задан, либо не имеет дочерних.

Рис. 5. Структура атрибута TDataStd_TreeNode.

Итак, вхождение держит за хвост оригинал. Оригинал также в курсе, что у него есть вхождение. Механика настройки такого двойного отношения полностью скрыта в атрибуте TDataStd_TreeNode (рис. 5). Для вхождения в нем содержится родитель, а для родителя доступен точно такой же атрибут со ссылкой на ПЕРВОЕ вхождение. Кроме того, вхождение содержит ссылки на следующее и предыдущее вхождения, если они есть. Это довольно интересная топология связей, когда родительский элемент держит ссылку только на ПЕРВЫЙ дочерний, а дочерние знают своих непосредственных соседей.

Любители OCAF должны навострить в этом месте уши. Получается, что атрибут TDataStd_TreeNode реализует как прямую, так обратную ссылки между объектами ("reference" и "back reference" в одном флаконе). Хотя такая структура несколько усложняет понимание формата XDE, это позволяет нам меньше заботиться о поддержании целостности данных. Действительно, в случае, если прямая и обратная ссылки содержатся отдельно (например, при помощи атрибута TDF_Reference), то их установка и удаление должны всегда быть парными. Можно сказать, что гомеостаз модели, построенной на TDataStd_TreeNode лучше гипотетического аналога, опирающегося на TDF_Reference.

Пример

Следует твердо усвоить разницу между понятиями Сборки, Детали и Вхождения. Проиллюстрируем эту разницу на примере. Возьмем животное класса «Выпь» и скомпонуем ее глаза как подсборки механического изделия.

Изделие «Выпь» (схематично).

В упрощенном виде будем говорить, что глаз — это подсборка из трех компонент: стекловидного тела (vitreous body), хрусталика (lens) и сетчатки (retina).

Глаз как подсборка из трех компонент (стекловидное тело, хрусталик и сетчатка).

Таким образом мы группируем три детали (стекловидное тело, хрусталик и сетчатку) в один объект. Получается простейшая иерархия.

Три компоненты, составляющие подсборку «глаз».

Выше мы оговорились, что сборки набираются из ВХОЖДЕНИЙ, то есть ссылок на детали с привязанным положением. С точки зрения XDE, это означает, что компоненты глаза Vitreous body, Lens и Retina используются не непосредственно, а через механизм ссылок на уровне вхождений. Таким образом, группа Eye содержит не сами детали, но ссылки на них: по одной на каждую деталь.

Содержатся не сами детали, а ссылки на них.

Далее нужно заметить, что изделие «Выпь» содержит сразу два глаза. Чтобы выразить это, сам глаз, как подсборка, включается через вхождение. Заметим, что внутренняя структура глаза от этого не изменяется: вхождения стекловидного тела, хрусталика и сетчатки переиспользуются полностью, то есть новых вхождений для них не создается.

Глаз, как вхождение подсборки.

Переиспользование вхождений, конечно, экономит память. Но происходит это ценой усложнения структуры и операций над ней. Что если мы желаем удалить хрусталик только из левого глаза животного? Увы, сделать это будет непросто, так как изъятие вхождения Lens [1] из одного глаза неминуемо приведет к точно такому же изъятию из другого, ведь оба глаза ссылаются на одну и ту же подсборку.

Модификация компоненты сборки

До сих пор мы говорили об XDE с позиций «только для чтения», что, понятное дело, существенно ограничивает круг адресуемых проблем. Положим, что та или иная компонента сборки должна быть модифицирована. Скажем, в конструкторской модели мы желаем удалить все «отверстия под болты», получив тем самым, упрощенную модель для дальшейшего расчета. Казалось бы, надо всего-лишь заменить B-Rep геометрию соответствующей компоненты в XDE, но не тут-то было. Сборка XDE не так прозрачна, как хотелось бы. Это не просто дерево меток с геометрическими листьями. Каждая промежуточная подсборка тоже хранит B-Rep геометрию в виде чисто топологического контейнера TopoDS_Compound! По всей видимости, такая огранизация данных упрощает некоторые процессы на уровне ядра OpenCascade, но с точки зрения пользователя эта «топологическая кожа», обтягивающая дерево OCAF, вносит дополнительные трудности.

С учетом сказанного, очевидно, что для модификации геометрии части сборки недостаточно выполнить локальное изменение в структурах OCAF. Нужно еще перестроить те компаунды (TopoDS_Compound), которые содержали оригинальную геометрию, иначе можно получить неприятные отложенные побочные эффекты, например, при записи из XDE обратно в STEP. В OCAF для хранения геометрии используется атрибут TNaming_NamedShape. Его следует искать во всех компонентах сборки на уровне объявлений (рис. 6).

Рис. 6. Внутренние топологические структуры XDE выделены красным фоном. Уровень объявлений обведен фиолетовым маркером.

Два раздела ниже промаркированы звездочкой. Их можно пропустить без ущебра для понимания XDE.

* Обновление снизу-вверх

Оказывается, для обновления сборки в XDE существует метод UpdateAssembly() класса XCAFDoc_ShapeTool. Этот метод как раз и перестраивает компаунды, заново вкладывая низлежащую геометрию в вышестоящую топологическую коллекцию. И здесь снова тонкость. Метод UpdateAssembly() не идет дальше первого уровня вложенности, то есть никаких адских рекурсий! Можно, наверное, отнести такое поведение к достоинствам метода, так как он сваливает на пользователя всю ответственность за глобальность совершаемых изменений... Впрочем, достаточно прочитать вслух данный тезис, чтобы возмутиться в сердце своем...

Итак, чтобы сбросить старую топологическую кожу и отрастить новую, нам потребуется некоторый итератор дерева. Вспомним, что дерево имеет не более чем два уровня вложенности, поэтому все «прыжки» с уровня вхождений на уровень объявлений придется совершать вручную (рис. 7).

Рис. 7. Схема итерации по сборке от изменяемого тела (TopoDS_Solid) к корню иерархии. Итерируемся «снизу-вверх».

Такое обновление совершает код, приведенный ниже (обратите внимание на рекурсию):

void UpdateOwnerAssemblies(const TDF_Label& partLabel)
{
  // Get shape tool
  Handle(XCAFDoc_ShapeTool) ShapeTool = XCAFDoc_DocumentTool::ShapeTool(partLabel);
  
  // Get all insertions of the part to assemblies
  TDF_LabelSequence insertions;
  ShapeTool->GetUsers(partLabel, insertions);
  
  // Update all owning assemblies
  for ( int l = 1; l <= insertions.Length(); ++l )
  {
    const TDF_Label& insertion_L = insertions(l);
    TDF_Label        owner_L     = insertion_L.Father();
  
    // Update owner
    ShapeTool->UpdateAssembly(owner_L);
  
    // Now notice that the owner can be inserted in some top-level
    // assembly, so let's do the same process on it
    UpdateOwnerAssemblies(owner_L);
  }
}

* Обновление сверху-вниз

Обсуждаемая здесь функция зарегистрирована в официальном багтрекере.

Код, приведенный выше, совершает локальное обновление сборки. Это удобно, если модификация совершалась на единственной компоненте, родительские элементы которой можно пройти один раз снизу-вверх. Рассмотрим теперь ситуацию, когда выполняется некоторая сложная модификация сборки, в частности, изменение нескольких компонент в рамках одной транзакции. Можно, конечно, использовать код, приведенный выше. Однако ясно, что такой способ обновления перестанет быть эффективным, поскольку некоторые родители вероятно будут обновлены несколько раз. В таких условиях существенно удобнее оказывается глобальное обновление сборки от корневого узла до всех компонент. Обновление начинается с вхождений верхнего уровня, доступных как результат вызова XCAFDoc_ShapeTool::GetFreeShapes():

//! Performs top-down update of all assemblies in the XDE document.
void UpdateAssemblies()
{
  // Get shape tool
  Handle(XCAFDoc_ShapeTool) shapeTool = ...
  
  // We start from those shapes which are "free" in terms of XDE
  TDF_LabelSequence roots;
  shapeTool->GetFreeShapes(roots);
  
  // Iterate over the free shapes
  for ( TDF_LabelSequence::Iterator it(roots); it.More(); it.Next() )
  {
    const TDF_Label& rootLab = it.Value();
    
    TopoDS_Shape assemblyShape;
    updateComponent(rootLab, assemblyShape);
  }
}

Итератор посещает каждый сборочный узел верхнего уровня и инициирует его обновление вызовом функции updateComponent(). Функция updateComponent(), в свою очередь, организована так:

//! Checks recursively if the given assembly item is modified. If so, its
//! associated compound is updated.
//! param itemLabel    assembly item label.
//! param updatedShape updated shape.
//! eturn true if the assembly item is modified, false -- otherwise.
bool updateComponent(const TDF_Label& itemLabel,
                     TopoDS_Shape&    updatedShape) const
{
  Handle(XCAFDoc_ShapeTool) shapeTool = this->GetShapeTool();
  
  if ( !shapeTool->IsAssembly(itemLabel) )
    return false; // Do nothing for non-assemblies
  
  // Get the currently stored compound for the assembly
  TopoDS_Shape currentRootShape;
  shapeTool->GetShape(itemLabel, currentRootShape);
  
  // Get components of the assembly
  TDF_LabelSequence componentLabs;
  shapeTool->GetComponents(itemLabel, componentLabs);
  
  // This flag indicates whether to update the compound of the assembly
  bool isModified = false;
  
  // Compare the number of components. A component may happen to be removed,
  // so we have to update the assembly compound
  int numTopoComponents = 0;
  for ( TopoDS_Iterator topoRootIt(currentRootShape); topoRootIt.More(); topoRootIt.Next() )
    numTopoComponents++;
  //
  if ( numTopoComponents != componentLabs.Length() )
    isModified = true;
  
  // Iterate over the assembly components. If at least one component is
  // modified (this is the recursive check), then the actually stored
  // compound has to be updated
  TopTools_ListOfShape componentShapes;
  //
  for ( TDF_LabelSequence::Iterator cit(componentLabs); cit.More(); cit.Next() )
  {
    const TDF_Label& componentLab = cit.Value();
    
    // Take the referred assembly item (ultimately, a part for an instance)
    TDF_Label componentRefLab;
    shapeTool->GetReferredShape(componentLab, componentRefLab);
    
    // Shape comes with some placement transformation here
    TopoDS_Shape componentShape;
    shapeTool->GetShape(componentLab, componentShape);
    TopLoc_Location componentLoc = componentShape.Location();
    
    // If the component is a sub-assembly, then its associated compound
    // has to be processed in the same manner
    if ( shapeTool->IsAssembly(componentRefLab) )
    {
      // Recursive call
      if ( this->updateComponent(componentRefLab, componentShape) )
      {
        if ( !isModified )
          isModified = true;
        
        componentShape.Location(componentLoc); // Apply placement
      }
    }
    else
    {
      // Search for a part in the actual compound of the ultimate assembly.
      // If the part is there, then the compound is up-to-date, so it does
      // not require rebuilding
      bool isPartFound = false;
      for ( TopoDS_Iterator topoIt(currentRootShape); topoIt.More(); topoIt.Next() )
      {
        if ( topoIt.Value() == componentShape )
        {
          isPartFound = true;
          break;
        }
      }
      
      if ( !isPartFound && !isModified )
        isModified = true; // Part has been modified somewhere, so the compound
                           // has to be rebuilt
    }
    
    // Fill the list of shapes composing a new compound for the assembly
    componentShapes.Append(componentShape);
  }
  
  // If any component is modified, we update the currently stored shape
  if ( isModified )
  {
    TopoDS_Compound updatedCompound;
    BRep_Builder BB;
    BB.MakeCompound(updatedCompound);
    
    // Compose new compound
    for ( TopTools_ListIteratorOfListOfShape sit(componentShapes); sit.More(); sit.Next() )
    {
      BB.Add( updatedCompound, sit.Value() );
    }
    
    // Store the updated shape as an output
    updatedShape = updatedCompound;
    
    // Use topological naming services to store the updated shape in XDE
    TNaming_Builder NB(itemLabel);
    NB.Generated(updatedShape);
  }
  
  return isModified;
}

Метод работает только на сборках и подсборках, о чем свидетельствует барьерное условие IsAssembly() в начале. Если наша сборка содержит в качестве объектов верхнего уровня вхождения деталей без подсборок, то никакое обновление ей не требуется и метод возвращает false. Если же на верхнем уровне мы имеем подсборку, то ее топология должна быть обновлена. Текущую топологию сборки позволяет получить вызов XCAFDoc_ShapeTool::GetShape(). Дальнейшая работа состоит в следующем. Из данной сборки выбираются все ее дочерние компоненты. Если компонент сам является сборкой, то вызов updateComponent() повторяется рекурсивно. В соответствии с принятой логикой метода, перед рекурсивным погружением мы обязаны перейти от объекта уровня вхождений к объекту уровня объявлений, чему служит вызов XCAFDoc_ShapeTool::GetReferredShape(). Кроме того, с данного компонента снимается его топологическое представление с трансформацией, определяющей положение компонента в текущем узле сборки. Эта трансформация будет применена к перестроенной топологии, если рекурсивный метод возвращает true.

Рекурсия завершается, когда итератор «спускается» до вхождений деталей. В этом случае компонента сборки больше не является подсборкой и текущий компаунд содержит непосредственно геометрические модели деталей. Это ядро метода. Здесь мы выясняем, актуален ли текущий компаунд сборки, разыскивая в нем геометрию детали. Сравнение выполняется тривиально через оператор ==, поскольку свидетельством модификации детали является ее измененный адрес. Здесь мы напрямую пользуемся тем фактом, что OpenCascade не позволяет менять топологию, а только ее перестраивать.

Мета-данные

Цвета

Посмотрим теперь, как к геометрии привязываются цвета (рис. 8). Это делается косвенно, то есть путем настройки отношения «иметь цвет» между объектом Деталь и объектом Цвет.

Рис. 8. Коллекция цветов в XDE.

Интересно, что отношение «иметь цвет» опять-таки задается при помощи атрибута TDataStd_TreeNode (рис. 9). Это ЕЩЕ ОДНО дерево, в котором родителем является цвет, а дочерними элементами — геометрические объекты или подсборки. Похоже на то, что цвета всегда привязываются к элементам первого уровня, то есть уровня объявлений. Все вхождения будут подкрашены соответственно тем же цветом. Дерево здесь нужно для того, чтобы назначить один цвет нескольким объектам.

Рис. 9. Цветовые отношения (красные дуги) и отношения реплика-оригинал (черные дуги).

Допустим теперь, что некоторое тело сборки должно иметь один цвет, а грани этого тела другой. Например, если на фюзеляже самолета выбито название фирмы-производителя, то в CAD-модели мы чаще всего увидим контурный импринт, подкрашенный индивидуальным цветом. С точки зрения XDE схема работы со цветами не изменяется и при таком уровне детализации. Нужно только, чтобы метка тела содержала дочерние метки для граней, на которые уже, в свою очередь, настраивается отношение «иметь цвет». Таким образом цветовая детализация находит отражение в структуре сборки (рис. 10), хотя на уровне объявлений грани не появляются.

Рис. 10. Привязка индивидуальных цветов к граням.

Материалы

Материалы обрабатываются подобно цветам (рис. 11). Каждому материалу отвечает метка в группе Materials, связанная с геометрическим телом посредством атрибута TDataStd_TreeNode.

Рис. 11. Коллекция материалов в XDE.

Слои

Ситуация несколько сложнее со слоями. Здесь не только один слой может содержать несколько объектов, но и один объект — принадлежать сразу нескольким слоям. Такое отношение есть граф с отвечающим ему атрибутом XCAFDoc_GraphNode.

Заключение

Сложно? Пожалуй. Почему бы не забыть про XDE как про страшный сон и не реализовать свою схему хранения геометрии и мета-данных? Во-первых, в схеме XDE можно разобраться, она внутренне непротиворечива, хотя и сложна. Во-вторых, в этой схеме уже реализованы трансляторы STEP и IGES, а именно пакеты STEPCAFControl и IGESCAFControl, которые не могут работать ни с каким другим форматом OCAF, кроме XDE.

Итак, для того, чтобы размотать клубок XDE, требуется учитывать множество отношений между элементами данных. Вот НЕКОТОРЫЕ из них:

Иерархия меток [Shapes] Метки образуют уровень объявлений и уровень вхождений. Таким образом выражается структура сборки.
Реплика-Оригинал [Shapes] Отношение Реплика-Оригинал моделируется при помощи косвенного дерева атрибутом TDataStd_TreeNode.
Цвет-Деталь [Colors][Shapes] Отношение Цвет-Деталь моделируется при помощи косвенного дерева атрибутом TDataStd_TreeNode.
Материал-Деталь [Materials][Shapes] Отношение Материал-Деталь моделируется при помощи косвенного дерева атрибутом TDataStd_TreeNode.
Слой-Деталь [Colors][Shapes] Отношение Слой-Деталь моделируется при помощи косвенного графа атрибутом XCAFDoc_GraphNode.

Среди неназванных мета-данных следует отметить также PMI (Product Manufacturing Information). Они поступают в XDE при чтении STEP-файла протокола AP242, привнося в паутину зависимостей новые нити. Однако, ознакомившись с принципом организации данных, не составляет большого труда проследить эти зависимости самостоятельно, обратившись к исходным кодам каскейда.

Комментариев: 2 RSS

Можно ли в Open CASCADE оптимизировать большую модель (*.step), которая содержит большое количество деталей и подсборок? Например, сделать из всех подсборок монолитные детали? Такой подход (combine) применяется в игровых движках к трехмерным моделям для уменьшения большого количества отдельных объектов в сцене с целью повышения производительности. Будет ли работать такой подход в OCC?

Для работы с JT нужно покупать отдельный модуль?

Софт на базе OpenCascade для упрощения больших сборок существует, но это уже коммерческое приложение.