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

Как выполнить сечение CAD-модели

Вопрос от нашего читателя Дмитрия:

Как создать вид сечения (2d) по модели (3d)?

Искомое сечение CAD-модели.

У меня есть исходная модель TopoDS_Shape (baseModel). Для того чтобы получить вид сечения я должен:

  1. Создать усеченную модель TopoDS_Shape (sectionModel) с помощью BRepAlgoAPI_Common или BRepAlgoAPI_Cut;
  2. Создать проекцию на плоскость усеченной модели с помощью HLRBRep_Algo и HLRAlgo_Projector.

Я пробовал использовать BRepAlgoAPI_Section, но он предоставляет контур пересечения плоскости и тела, т.е. нет остальных граней, которые должны быть видны. Я приложил картинку с демонстрацией. Верны ли мои рассуждения? Или есть другие средства?

Ваши рассуждения верны. Пакет HLR (Hidden Line Removal) библиотеки OpenCascade позволяет получить проекцию видимых очертаний детали на некоторую плоскость. На самом деле есть два алгоритма: HLRBRep_Algo и HLRBRep_PolyAlgo. Первый работает на криволинейном представлении детали, второй — на ее полигонах. Ходят слухи (сам не проверял), что полигональная версия надежнее.

Работа с HLR требует привлечения трех классов:

  • HLRBRep_PolyAlgo — собственно алгоритм HLR.
  • HLRAlgo_Projector — описывает плоскость проекции.
  • HLRBRep_PolyHLRToShape — позволяет извлечь результат как топологическую структуру данных (TopoDS).

Код, приведенный ниже, демонстрирует использование алгоритма в C++.

// Inputs:
TopoDS_Shape partShape = ...; // Your TopoDS_Shape.
gp_Ax2 axes = ...; // Your projection plane.
  
// Prepare projector.
HLRAlgo_Projector projector(axes);
  
// Prepare polygonal HLR algorithm which is known to be more reliable than
// the "curved" version of HLR.
Handle(HLRBRep_PolyAlgo) polyAlgo = new HLRBRep_PolyAlgo;
// 
polyAlgo->Projector(projector);
polyAlgo->Load(partShape);
polyAlgo->Update();
  
// Create topological entities.
HLRBRep_PolyHLRToShape HLRToShape;
HLRToShape.Update(polyAlgo);
  
// Prepare one compound shape to store HLR results.
TopoDS_Compound hlrShape;
BRep_Builder().MakeCompound(hlrShape);
  
// Add visible edges to the result.
TopoDS_Shape vcompound = HLRToShape.VCompound();
if ( !vcompound.IsNull() )
  BRep_Builder().Add(hlrShape, vcompound);
//
vcompound = HLRToShape.OutLineVCompound();
if ( !vcompound.IsNull() )
  BRep_Builder().Add(hlrShape, vcompound);

Переменная hlrShape хранит результат в виде неупорядоченного набора ребер. Эти ребра представлены двумерными параметрическими прямыми, определенными в плоскости проекции.

Сечение CAD-модели и вычисление проекции при помощи алгоритма HLR.

Ниже приведен сценарий построения плоского сечения в программе «Анализ Положения» (начиная с версии 0.2.6) для тестовой модели ANC101:

# Load sample part.
set dir [pwd]
clear
load-brep $dir/data/cad/ANC101.brep
fit
  
# Cut with Boolean operation.
set-as-var body
make-box tool -25 -25 -25 500 125 250
cut clipped body tool
donly clipped
set-as-part clipped
  
# Compute HLR.
hlr proj 0 0 0 0 -1 0

Инструменты OpenCascade решают чисто геометрическую задачу о нахождении видимых ребер. Алгоритм HLR не наносит штриховок и не рисует осевые линии. Его следует рассматривать только как часть решения проблемы построения чертежей.

Пример сечения сборки.

В случае, если вы режете не одиночную деталь, а сборку, желательно использовать булеву операцию на каждом твердотельном объекте отдельно. Например, вот так:

explode -solid
erase-all
for {set i 1} {$i <= 39} {incr i} {cut res$i "SOLID $i" tool}
make-compound comp
for {set i 1} {$i <= 39} {incr i} {add-subshape comp res$i}
set-as-part comp
hlr res 0 0 -300 0 0 -1

Здесь 'tool' представляет «режущий инструмент» (параллелепипед), а исходное тело содержит 39 деталей. Заметьте, что в конце разрезанные детали собираются в одну, чтобы обеспечить ожидаемый вход для команды 'hlr'.

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

Добрый день! По какому принципу можно сделать проекцию нескольких объектов так, чтобы иметь возможность понять какому объекту принадлежат спроецированные элементы?

Я думал, что нужно сделать проекцию каждого объекта в отдельности, но столкнулся с проблемой. При пообъектном проецировании не учитывается то, что проецируемое тело может перекрываться другим, как будто в сцене находится только один объект. Если же проецировать все интересующие тела разом, то не ясно как потом определить какому объекту принадлежат линии. Вот картинка демонстрирующая эти два подхода - https://i.ibb.co/3sHkZtw/pic.png

Я нашел способ, как проецировать объекты по отдельности, чтобы знать какому объекту принадлежат линии проекции.

1) В polyAlgo необходимо добавить все объекты (напр. box и sphere):

Handle(HLRBRep_PolyAlgo) polyAlgo = new HLRBRep_PolyAlgo;

polyAlgo->Projector(projector);

polyAlgo->Load(sphere);

polyAlgo->Load(box);

polyAlgo->Update();

2) Для каждого тела (по отдельности) произвести получение геометрии, передовая в методы VCompound и OutLineVCompound нужные объекты. Ниже я получаю все линии проекция принадлежащие объекту sphere:

TopoDS_Shape vcompound;

vcompound = HLRToShape.VCompound(sphere);

if (!vcompound.IsNull())

BRep_Builder().Add(hlrShape, vcompound);

vcompound = HLRToShape.OutLineVCompound(sphere);

if (!vcompound.IsNull())

BRep_Builder().Add(hlrShape, vcompound);

3) Результат проекции для тела sphere: https://i.ibb.co/P1gyMrC/pic2.png (https://ibb.co/zPZgFmf)

Я все делаю верно или есть более хорошее решение?

Дмитрий, признаюсь, не имею об этом ни малейшего понятия :) Но вопрос хороший, можно повесить вместе с найденным вами решением отдельным постом. Я начал смотреть исходники HLRTest.cxx, и мое внимание привлекла структура HLRTopoBRep_OutLiner, но я не успел с ней поэкспериментировать. Если HLR работает, то хорошо. Производительность там неоптимальная, в любом случае, но для одиночных деталей и маленьких сборок сгодится.

Было бы здорово найти оптимальное решение этой задачи. Я пытался найти, что-то на просторах сети на эту тему, но безрезультатно. Может стоит создать тему на официальном форуме?

Вы ищите какие-то зацепки непосредственно в исходниках? Я использую документацию, но к сожалению она скудна на описания и не ясно, что из себя представляет HLRTopoBRep_OutLiner.