Топология полигонального объекта MbPolymeshTopo

Полигональный объект MbPolymesh является наследником MbItem и содержит внутри топологию MbPolymeshTopo (по аналогии с MbSolid, который содержит внутри MbFaceShell). Топология включает в себя все методы для работы как с сеткой, так и с сегментацией. Далее будут рассмотрены более подробные описания методов данного класса.

Методы общего назначения

Метод

static MbPolymeshTopo * Create();

создаёт пустой экземпляр класса.

Метод

static MbPolymeshTopo * Create( const MbMesh & mesh,
                                      double   toleranceSew );

создаёт экземпляр класса по экземпляру MbMesh. Точность сшивки toleranceSew используется для объединения почти совпадающих вершин в одну.

Метод

bool GetMesh( MbMesh & mesh ) const;

создаёт экземпляр MbMesh с потерей топологической информации, где каждому подрегиону соответствует отдельный объект MbGrid. При этом внутри этого экземпляра создаётся (в виде MapPolymeshToMbMesh) отображение между индексами MbGrid и индексами подрегионов, так как в общем случае они будут иметь различную нумерацию.

Метод

MbPolymeshTopo * Clone() const;

создаёт копию топологии.

Метод

void CalculateGabarit( const MbMatrix3D & matrInto,
                             MbCube &     bb ) const;

рассчитывает габарит объекта.

Метод

void Invert();

инвертирует всю топологию, включая разворот циклов вокруг фасетов.

Методы трансформации

void Transform( const MbMatrix3D & matr );
void Move     ( const MbVector3D & to   );
void Rotate   ( const MbAxis3D   & axis, double angle );

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

Метод

void DeleteInactive();

удаляет все неактивные элементы, уменьшая тем самым размер полигонального объекта (рёбра, вершины, фасеты сетки, рёбра сегментации, вершины сегментации, регионы, подрегионы и циклы сегментации).

Метод

double FindNearest( const MbCartPoint3D & pnt,
                          MbCartPoint3D & pntProj,
                          size_t &        iFacet ) const;

находит ближайшую к указанной точку и индекс фасета, на который она попала. Возвращает расстояние от указанной точки до ближайшей на полигональном объекте.

Метод

bool FindLineIntersection( const MbAxis3D &      ray,
                                 MbCartPoint3D & pntCross,
                                 double &        tRes,
                                 size_t &        iFacet ) const;

находит ближайшее пересечение с прямой. Выходными параметрами являются точка пересечения, параметр луча и индекс фасета, с которым это пересечение произошло.

Метод

const MbFaceShell * GetSubstrateShell() const;

обеспечивает доступ к оболочке-подложке (если она существует), из которой полигональный объект был создан.

Метод

void DeleteSubstrateShell();

удаляет оболочку-подложку, из которой полигональный объект был создан, а также все сохранённые данные, обеспечивающие отображение от регионов и рёбер сегментации к граням и рёбрам оболочки.

Методы для работы с сеткой

Метод

const MbHalfedge & GetMeshTopo() const;

возвращает топологию сетки в виде объекта MbHalfedge. Это нужно, например, для конструирования сеточных итераторов.

Метод

void Reserve( size_t nVx,
              size_t nEd,
              size_t nF );

резервирует память под вершины, рёбра и фасеты для сетки и всех атрибутов, которые она содержит.

Метод

size_t CloneVertex( size_t iVx );

клонирует вершину сетки и возвращает индекс склонированной вершины.

Методы добавления элементов

size_t AddVertex();
size_t AddEdge();
size_t AddFacet();

добавляют активный элемент сетки и возвращают его индекс. Если в сетке есть неактивные элементы, один из них переводится в активное состояние и возвращается его индекс.

Методы деактивации элементов

void MakeVertexInactive( size_t iVx );
void MakeEdgeInactive   ( size_t iEd );
void MakeFacetInactive  ( size_t iF  );

переводят элемент сетки в неактивное состояние. Использование должно быть крайне осторожным, так как без дополнительных действий эти методы приведут к невалидности топологии сетки.

Метод

void SewEdges( size_t iEd0,
               size_t iEd1 );

делает два указанных рёбра сетки близнецами.

Метод

size_t AddFacet( const c3d::IndicesVector & vertices );

конструирует структуру фасета по указанным вершинам и возвращает его индекс. Вершины на момент вызова должны уже существовать. Метод создаёт фасет, все необходимые рёбра и устанавливает между ними (кроме близнецов) все нужные ссылки.

Метод

void SewByVertices();

устанавливает ссылки на близнецов для всех рёбер сетки, используя вершины, из которых исходят рёбра. Используется для окончательного формирования топологии при ручном конструировании, после того как все нужные фасеты были добавлены методом AddFacet().

Метод

void DeleteFacets( const c3d::IndicesVector & facets );

удаляет указанные фасеты и обеспечивает валидность топологии после этой операции. Удаление неактивных элементов не производится. Пример действий, необходимых для поддержания валидности топологии, показан на рис. 1: в исходном состоянии вершина A одна и та же для всех рёбер веера. После удаления выделенных фасетов веер оказывается разрывным, что не допускается в структуре Halfedge. Поэтому вершина будет склонирована, и части оставшегося веера будет соответствовать вершина A, а другой части её клон B. В этом месте топологически будет разрыв сетки, хотя геометрически эти две вершины совпадают.

../../../_images/P.2.4.2.1.png

Рис. 1

Метод

bool FlipEdge( size_t iEd );

делает переброску ребра в триангуляции. Нельзя перебрасывать открытые рёбра и рёбра, принадлежащие рёбрам сегментации. Пример работы метода показан на рис. 2:

../../../_images/P.2.4.2.2.png

Рис. 2

Метод

size_t SplitEdge( size_t iEd,
                  double prm );

разрезает ребро в указанном параметре, значение которого должно быть в интервале от 0 до 1. Возвращает индекс созданной в этом месте двухвалентной вершины. Количество рёбер для смежных фасетов увеличится на единицу. На рис. 3 показан результат после триангуляции двух четырёхугольных смежных фасетов:

../../../_images/P.2.4.2.3.png

Рис. 3

Метод

void SplitFacet( size_t              eVx0,
                 size_t              eVx1,
                 c3d::IndicesPair  & eNew );

разрезает фасет на два путём вставки пары рёбер между вершинами v0 и v1, из которых исходят указанные рёбра eVx0, eVx1, и возвращает индексы этих вставленных рёбер. Входные рёбра должны принадлежать одному фасету, который и будет разрезаться. Пример работы показан на рис. 4:

../../../_images/P.2.4.2.4.png

Рис. 4

Метод

bool JoinEdgeFacets( size_t iEd );

объединяет два фасета, смежных ребру, в один. Это операция, обратная методу SplitFacet(). Нельзя объединить фасеты, если в результате получится фасет, касающийся сам себя ребром или вершиной.

Метод

bool RemoveVertexValence2( size_t iVx );

удаляет двухвалентную вершину сетки. Операция, обратная методу SplitEdge().

Метод

size_t InsertVertexTriangle( size_t iTr,
                             double u,
                             double v );

вставляет новую вершину в треугольник и разрезает его на три. Возвращает индекс вставленной вершины. Параметры u и v – барицентрические координаты, которые определяют новую вершину внутри треугольника. Значения атрибутов для новой вершины (3D точка, 2D параметр, нормаль, кривизна и т.д.) рассчитываются как линейная комбинация из величин в вершинах треугольника согласно барицентрическим координатам.

Метод

size_t InsertVertexFacet( const c3d::IndicesVector &     edgesSplit,
                          const std::array<size_t, 3> &  edgesInterpolate,
                                double                   u,
                                double                   v );

вставляет новую вершину в фасет и разрезает его на несколько новых фасетов путём соединения рёбрами вставленной вершины с вершинами, из которых исходят рёбра из массива edgesSplit. Рёбра из этого массива должны принадлежать одному фасету. Массив edgesInterpolate определяет «виртуальный» треугольник из вершин фасета, относительно которого задаются барицентрические координаты u и v.

Пример использования показан на рисунке: на рисунке a) чёрным показан фасет, который нужно разбить синей вершиной и фиолетовыми рёбрами; на рисунке b) зелёным цветом показаны рёбра фасета, индексы которых должны быть указаны в массиве edgesSplit (они должны быть расположены в порядке следования внутри фасета); на рисунке c) зелёным цветом показан «виртуальный» треугольник, относительно которого задаются барицентрические координаты, а красным – индексы рёбер, которые нужно поместить в массив edgesInterpolate. Расчёт значений атрибутов для новой вершины делается аналогично методу InsertVertexTriangle().

../../../_images/P.2.4.2.5.png

Рис. 5

Методы для работы с сегментацией

Метод

bool IsSegmented() const;

проверяет, инициализирована ли сегментация. Рекомендуется всегда инициализировать сегментацию.

Метод

void Initialize( const MbHalfedgeBoundaryCriterionBase & crit );

инициализирует сегментацию согласно указанному критерию границы. Критерий должен быть реализован пользователем как наследник базового класса MbHalfedgeBoundaryCriterionBase, в котором должна быть заложена логика того, считать ли ребро сетки разделительным или нет. Например, можно предварительно посчитать двугранные углы для рёбер сетки, а в критерии проверять, превышает ли угол заданный порог или нет. Тогда получится сегментация сетки по острым сломам.

Метод

void Initialize();

инициализирует сегментацию из одного региона. Сетка разбивается на связные части, каждой из которых назначается подрегион. Сегментационные рёбра образуются из открытых рёбер сетки, если таковые имеются. Рекомендуется всегда инициализировать так сегментацию при ручном создании полигонального объекта.

Метод

const MbHalfedge & GetSegmTopo() const;

открывает доступ к константной топологии сегментации в виде Halfedge. Нужен для конструирования некоторых сегментационных итераторов.

Метод

size_t LoopsCount() const;

возвращает количество циклов в сегментации (включая неактивные).

Метод

const MbSegmentationLoop & Loop( size_t iLoop ) const;

получает цикл сегментации по его индексу.

Метод

size_t RegionCount() const;

возвращает количество регионов в сегментации (включая неактивные).

Метод

bool IsRegionActive( size_t iRegion ) const;

проверяет, является ли регион активным. То же самое можно сделать с помощью метода IsFacetActive() с тем же индексом для топологии сегментации, возвращаемой методом GetSegmTopo().

Метод

size_t SubRegionsCount() const;

возвращает количество подрегионов в сегментации (включая неактивные).

Метод

size_t SubRegionsCount( size_t iRegion ) const;

возвращает количество подрегионов, входящих в указанный регион.

Метод

const MbSegmentationSubRegion & SubRegion( size_t iSub ) const;

возвращает подрегион сегментации по его индексу.

Метод

size_t EdgeSegmCount() const;

возвращает количество рёбер в сегментации (включая неактивные).

Метод

const MbHalfedgeEdge & EdgeSegm( size_t iEdSegm ) const;

возвращает ребро сегментации по его индексу.

Метод

bool IsInnerEdge( size_t iEdSegm ) const;

проверяет, является ли ребро сегментации внутренним.

Метод

size_t GetSegmEdgeId( size_t iEdTopo ) const;

возвращает индекс сегментационного ребра, которому принадлежит указанное сеточное ребро.

Метод

void GetFacetRegionId( size_t iFacet,
                       size_t & iRegion,
                       size_t & iSubRegion ) const;

возвращает индексы региона и подрегиона, которым принадлежит указанный фасет сетки.

Метод

size_t VertexSegmCount() const;

получает количество вершин в сегментации (включая неактивные).

Метод

const MbHalfedgeVertex & VertexSegm( size_t iVxSegm ) const;

возвращает вершину сегментации по её индексу.

Метод

void GetRegion( size_t               r,
                c3d::IndicesVector & facets ) const;

возвращает индексы всех фасетов сетки, входящих в указанный регион.

Метод

void GetSubRegion( size_t               iSub,
                   c3d::IndicesVector & facets,
                   bool                 bAdd = false ) const;

возвращает индексы всех фасетов сетки, входящих в указанный подрегион.

Метод

void DeleteRegion( size_t iRegion );

удаляет указанный регион. При этом поддерживается валидность топологии и сетки, и сегментации, аналогично удалению фасетов.

Метод

void SplitByEdgesTopo( const c3d::IndicesVector & splitSet,
                             bool                 bKeepRegions );

разбивает существующую сегментацию набором рёбер сетки. Это может привести к появлению новых связанных групп фасетов. Для каждого из них создаётся новый подрегион. По флагу bKeepRegions эти подрегионы либо остаются в составе старого региона, либо из каждого из них будет создан новый регион. Также эта операция может привести к появлению внутренних рёбер сегментации.

Метод

void MergeRegions( const c3d::IndicesVector & regions,
                         bool                 bRemoveValence2 );

объединяет указанные регионы в один. Его индекс равен первому индексу из массива regions. При этом могут образоваться последовательности рёбер сегментации, разделённые двухвалентными сегментационными вершинами. По флагу bRemoveValence2 эти последовательности объединяются в рёбра сегментации.

Метод

void SplitByFacetsTopo( const c3d::IndicesVector & splitSet,
                              bool                 bMakeOneRegion,
                              bool                 bKeepRegions );

разбивает существующую сегментацию набором фасетов сетки. Этому набору соответствует один или несколько связных групп фасетов, относящихся к старым регионам и каждой из которых назначается новый подрегион. Комбинация этих групп в новые регионы и подрегионы зависит от двух управляющих флагов bMakeOneRegion и bKeepRegions. Пример показан на рис. 6, пусть сегментация состоит из четырёх простых регионов, которые нужно разбить выделенными ярко зелёным фасетами:

../../../_images/P.2.4.3.1.png

Рис. 6

  1. bMakeOneRegion = true, bKeepRegions = true.

Выделенные фасеты образовали один новый регион (жёлтый). Старые регионы остались, но разделились каждый на два подрегиона. Теперь в сегментации 5 регионов (рис. 7).

../../../_images/P.2.4.3.2.png

Рис. 7

  1. bMakeOneRegion = true, bKeepRegions = false.

Выделенные фасеты образовали один новый регион (жёлтый). Каждый из старых регионов распался на две несвязные части, каждая из которых образовала новый отдельный регион. Всего теперь в сегментации 9 регионов (рис. 8).

../../../_images/P.2.4.3.3.png

Рис. 8

  1. bMakeOneRegion = false, bKeepRegions = true.

Выделенные фасеты разбили каждый из старых регионов на 3 части. Регионов в сегментации по-прежнему 4, но каждый из них теперь состоит из трёх подрегионов (рис. 9).

../../../_images/P.2.4.3.4.png

Рис. 9

  1. bMakeOneRegion = false, bKeepRegions = false.

Выделенные фасеты разбили каждый из старых регионов на 3 части. Каждой такой части назначен новый регион. Всего теперь в сегментации 12 регионов, состоящих из одного подрегиона (рис. 10).

../../../_images/P.2.4.3.5.png

Рис. 10

Метод

void SplitRegionBySubregions( size_t iReg );

выделяет подрегионы региона как отдельные регионы.

Метод

c3d::IndicesPair SplitSegmentationEdge( size_t iEdSegm,
                                        size_t iEdTopo,
                                        size_t iVxSegmSplit = SYS_MAX_T );

разрезает ребро сегментации с индексом iEdSegm (и его близнеца) в вершине сетки, из которой исходит сеточное ребро iEdTopo. Ребро iEdTopo должно принадлежать сегментационному ребру и не должно совпадать с самым первым сеточным ребром для сегментационного ребра. В этом месте возникнет двухвалентная вершина сегментации, существующая с индексом iVxSegmSplit, если он задан, либо будет добавлена новая. Возвращает индексы новых рёбер сегментации, на которые распалось старое ребро сегментации и его близнец (если он существует). Топологию сетки метод не изменяет. Новые рёбра сегментации наследуют атрибуты от старых, из которых они были получены.

Метод

bool ExtractSubRegionAsRegion( size_t iSub );

выделяет указанный подрегион в отдельный регион. Если старый регион состоял только из указанного подрегиона, никаких действий выполнено не будет.

Метод

void RemoveSegmVertexValence2( size_t iVx );

удаляет вершину сегментации с валентностью 2. Метод, обратный к SplitSegmentationEdge().

Метод

size_t GetTopoVertex( size_t iVxSegm ) const;

возвращает индекс вершины сетки, в которой находится указанная вершина сегментации.

Метод

size_t GetSegmEdgeRegionId( size_t iEdSegm ) const;

возвращает индекс региона, которому принадлежит ребро сегментации.

Метод

size_t GetSegmEdgeSubRegionId( size_t iEdSegm ) const;

возвращает индекс подрегиона, которому принадлежит ребро сегментации.

Метод

size_t GetLoopRegionId( size_t iLoop ) const;

возвращает индекс региона, которому принадлежит цикл.

Метод

size_t GetLoopSubRegionId( size_t iLoop ) const;

возвращает индекс подрегиона, которому принадлежит цикл.

Метод

size_t GetNeighborRegionId( size_t iEdSegm ) const;

возвращает индекс региона с другой стороны ребра сегментации.

Метод

size_t GetNeighborSubRegionId( size_t iEdSegm ) const;

возвращает индекс подрегиона с другой стороны ребра сегментации.

Методы для работы с атрибутами сетки и сегментации

Метод

size_t MeshHalfedgeAttributeCount() const;

возвращает количество сеточных атрибутов.

Метод

size_t SegmHalfedgeAttributeCount() const;

возвращает количество сегментационных атрибутов.

Метод

template <class T>
T * AddMeshHalfedgeAttribute();

создаёт сеточный атрибут указанного типа и возвращает указатель на него.

Метод

template <class T>
T * AddSegmHalfedgeAttribute();

добавляет сегментационный атрибут указанного типа и возвращает указатель на него.

Метод

template <class T>
T * GetMeshHalfedgeAttribute();

и константный вариант

template <class T>
const T * GetMeshHalfedgeAttribute() const;

находят в полигональном объекте сеточный атрибут указанного типа (первый подходящий в массиве атрибутов) и возвращают указатель на него.

Метод

template <class T>
T * GetSegmHalfedgeAttribute();

и константный вариант

template <class T>
const T * GetSegmHalfedgeAttribute() const;

находят в полигональном объекте сегментационный атрибут указанного типа (первый подходящий в массиве атрибутов) и возвращают указатель на него.

Метод

template <class T>
void DeleteMeshHalfedgeAttribute();

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

Метод

template <class T>
void DeleteSegmHalfedgeAttribute();

удаляет сегментационный атрибут указанного типа (первый подходящий в массиве атрибутов).

Методы

MbHalfedgeAttrBase * GetMeshHalfedgeAttributeByIndex( size_t ind );

const MbHalfedgeAttrBase * GetMeshHalfedgeAttributeByIndex( size_t ind ) const;

возвращают указатель на сеточный атрибут с заданным индексом в массиве атрибутов.

Методы

MbHalfedgeAttrBase * GetSegmHalfedgeAttributeByIndex( size_t ind );

const MbHalfedgeAttrBase * GetSegmHalfedgeAttributeByIndex( size_t ind ) const;

возвращают указатель на сегментационный атрибут с заданным индексом в массиве атрибутов.

Метод

void DeleteMeshHalfedgeAttribute( MbHalfedgeAttrBase * pAttr );

удаляет указанный сеточный атрибут.

Метод

void DeleteSegmHalfedgeAttribute( MbHalfedgeAttrBase * pAttr );

удаляет указанный сегментационный атрибут.

Метод

MbAttributeContainer * GetSegmRegionModelAttributes( size_t iRegion,
                                                     bool   bCreate );

возвращает контейнер атрибутов объекта геометрического ядра для региона. Если он отсутствует, то по флагу bCreate будет создан, иначе возвращается нулевой указатель.

Метод

const MbAttributeContainer * GetSegmRegionModelAttributes( size_t iRegion ) const;

возвращает контейнер атрибутов объекта геометрического ядра для региона.

Метод

MbAttributeContainer * GetSegmEdgeModelAttributes( size_t iEdSegm,
                                                   bool   bCreate );

возвращает контейнер атрибутов объекта геометрического ядра для ребра сегментации. Если он отсутствует, то по флагу bCreate будет создан, иначе возвращается нулевой указатель.

Метод

const MbAttributeContainer * GetSegmEdgeModelAttributes( size_t iEdSegm ) const;

возвращает контейнер атрибутов объекта геометрического ядра для ребра сегментации.

Метод

MbAttributeContainer * GetSegmVertexModelAttributes( size_t iVxSegm,
                                                     bool   bCreate );

возвращает контейнер атрибутов объекта геометрического ядра для вершины сегментации. Если он отсутствует, то по флагу bCreate будет создан, иначе возвращается нулевой указатель.

Метод

const MbAttributeContainer * GetSegmVertexModelAttributes( size_t iVxSegm ) const;

возвращает контейнер атрибутов объекта геометрического ядра для вершины сегментации.