.. role:: blue :class: blue Сегментация и сегментационные итераторы ======================================= .. _Segmentation_and_Segmentation_Iterators: .. версия ядра: 118027 Сегментация над полигональной сеткой также организована в виде :blue:`Halfedge` структуры. Для её представления используются следующие элементы, которые находятся в заголовочном файле *halfedge_element.h*. Каждый из сегментационных элементов может быть в активном и неактивном статусе. **Подрегион** (:blue:`MbSegmentationSubRegion`) – связная группа фасетов. **Регион** – группа из нескольких подрегионов, как правило, из одного. Отдельного класса, описывающего регион, нет. **Ребро сегментации** – последовательность рёбер сетки, такая, что каждое следующее ребро исходит из вершины, в которую приходит предыдущее ребро. Ребро сегментации может быть замкнутым. Самопересечения рёбер не допускаются. Аналогично ребру сетки ребро сегментации имеет ссылки на следующее ребро сегментации, предыдущее ребро сегментации, ребро сегментации-близнеца и вершину, за счёт чего формируются циклы. Если ребро сегментации принадлежит открытой границе, ссылка на близнеца отсутствует. Сеточные рёбра, входящие в ребро сегментации и его близнеца, тоже являются близнецами (рис. 1): .. figure:: ../../pictures/P.2.3.1ru.png :width: 15cm :align: center Рис. 1 **Вершина сегментации** – соответствует вершине сетки, в которой сходятся несколько рёбер сегментации. **Цикл подрегиона** (:blue:`MbSegmentationLoop`), состоящий из последовательности рёбер сегментации. Подрегион может иметь сколько угодно циклов или вообще ни одного, если он представляет из себя замкнутую группу фасетов. Имеет такой же смысл, как цикл грани в граничном представлении, с некоторыми отличиями. Как правило, на сетке нельзя разделить циклы на внешний и внутренние, поэтому все циклы равноправны. Также цикл может иметь «внутренние» рёбра. Пример разделения сетки на четыре региона, каждый из которых состоит из одного подрегиона, показан на рис. 2: .. figure:: ../../pictures/P.2.3.2.png :width: 15cm :align: center Рис. 2 Пример для той же сетки, но теперь в сегментации два региона, один из которых состоит из одного подрегиона, а другой из трёх, показан на рис. 3: .. figure:: ../../pictures/P.2.3.3.png :width: 15cm :align: center Рис. 3 Пример подрегиона с двумя циклами показан на рис. 4. Зелёный цикл полностью состоит из внутренних рёбер, в красном внутренними являются рёбра 1, 2, 4–9. .. figure:: ../../pictures/P.2.3.4.png :width: 15cm :align: center Рис. 4 Для работы с топологией сегментации предназначены сегментационные итераторы, которые находятся в заголовочном файле *halfedge_segm_iterators.h*: - :blue:`EdgeLoopIterator` – итератор по рёбрам цикла подрегиона. В зависимости от флага :blue:`bExcludeInnerEdges` возвращает последовательность всех рёбер цикла либо только внешних. - :blue:`EdgeEdgesIterator` – итератор по сеточным рёбрам ребра сегментации. В зависимости от флага :blue:`bReverse` возвращает последовательность сеточных рёбер в прямом либо обратном порядке. - :blue:`SubregionRegionIterator` – итератор по подрегионам региона. - :blue:`LoopSubregionIterator` – итератор по циклам подрегиона. Для итерации по вееру вершин сегментации нужно использовать итератор :blue:`EdgeFanIterator`, как показано в примере ниже. Примеры использования сегментационных итераторов: .. code-block:: cpp MbPolymesh polymesh; const MbPolymeshTopo & topo = *polymesh->GetTopo(); const MbHalfedge & halfedge = topo.GetMeshTopo(); for( size_t r = 0; r < topo.RegionCount(); ++r ) { if( !topo.IsRegionActive( r ) ) continue; for( SubregionRegionIterator itSub( topo, r ); !itSub.Done(); ++itSub ) { for( LoopSubregionIterator itLoop( topo, itSub.Subregion() ); !itLoop.Done(); ++itLoop ) { for( EdgeLoopIterator itEdge( topo, itLoop.Loop() ); !itEdge.Done(); ++itEdge ) { for( EdgeEdgesIterator it( topo, itEdge.Edge() ); !it.Done(); ++it ) { const MbHalfedgeEdge & ed = halfedge.Edge( it.Edge() ); ... } } } } }, for( EdgeFanIterator it( topo.GetSegmTopo(), iVxSegm, true ); !it.Done(); ++it ) { const MbHalfedgeEdge & edSegm = topo.GetSegmTopo().Edge( it.Edge() ); }