23#ifndef VCL_ALGORITHMS_MESH_FACE_TOPOLOGY_H
24#define VCL_ALGORITHMS_MESH_FACE_TOPOLOGY_H
26#include <vclib/algorithms/core/polygon/ear_cut.h>
27#include <vclib/concepts/mesh.h>
28#include <vclib/exceptions/mesh.h>
29#include <vclib/mesh/iterators/face/edge_adj_face_iterator.h>
30#include <vclib/misc/comparators.h>
31#include <vclib/space/complex/mesh_pos.h>
32#include <vclib/space/core/polygon.h>
33#include <vclib/views/mesh.h>
65template<FaceMeshConcept MeshType, FaceConcept FaceType>
66void addTriangleFacesFromPolygon(
69 const std::vector<uint>& polygon)
71 using VertexType = MeshType::VertexType;
72 using CoordType = VertexType::CoordType;
75 std::vector<CoordType> polCoords(polygon.size());
76 for (uint i = 0; i < polygon.size(); ++i) {
77 if (polygon[i] >= m.vertexContainerSize()) {
78 throw BadVertexIndexException(
79 "Index " + std::to_string(polygon[i]) +
80 " is out of range in Vertex Container.");
82 if (m.vertex(polygon[i]).deleted()) {
83 throw BadVertexIndexException(
84 "Vertex " + std::to_string(polygon[i]) +
" is deleted.");
86 polCoords[i] = m.vertex(polygon[i]).coord();
90 std::vector<uint> tris =
earCut(polCoords);
95 std::set<std::pair<uint, uint>, UnorderedPairComparator<uint>>
97 for (uint i = 0; i < polygon.size(); ++i)
98 unorderedEdges.emplace(i, (i + 1) % (uint) polygon.size());
100 if constexpr (FaceType::VERTEX_NUMBER < 0) {
105 for (uint i = 0; i < f.vertexNumber(); ++i) {
106 f.setVertex(i, polygon[tris[i]]);
109 if constexpr (face::HasFaceBitFlags<FaceType>) {
110 if (unorderedEdges.find(std::make_pair(tris[0], tris[1])) ==
111 unorderedEdges.end())
112 f.edgeFaux(0) =
true;
113 if (unorderedEdges.find(std::make_pair(tris[1], tris[2])) ==
114 unorderedEdges.end())
115 f.edgeFaux(1) =
true;
116 if (unorderedEdges.find(std::make_pair(tris[2], tris[0])) ==
117 unorderedEdges.end())
118 f.edgeFaux(2) =
true;
122 for (uint i = 3; i < tris.size(); i += 3) {
123 uint ff = m.addFace();
125 if constexpr (FaceType::VERTEX_NUMBER < 0) {
126 m.face(ff).resizeVertices(3);
129 for (uint j = 0; j < m.face(ff).vertexNumber(); ++j) {
130 m.face(ff).setVertex(j, polygon[tris[i + j]]);
133 if constexpr (face::HasFaceBitFlags<FaceType>) {
134 if (unorderedEdges.find(std::make_pair(tris[i], tris[i + 1])) ==
135 unorderedEdges.end())
136 m.face(ff).edgeFaux(0) =
true;
137 if (unorderedEdges.find(std::make_pair(tris[i + 1], tris[i + 2])) ==
138 unorderedEdges.end())
139 m.face(ff).edgeFaux(1) =
true;
140 if (unorderedEdges.find(std::make_pair(tris[i + 2], tris[i + 0])) ==
141 unorderedEdges.end())
142 m.face(ff).edgeFaux(2) =
true;
162template<FaceMeshConcept MeshType>
163uint addTriangleFacesFromPolygon(MeshType& m,
const std::vector<uint>& polygon)
165 uint fid = m.addFace();
166 addTriangleFacesFromPolygon(m, m.face(fid), polygon);
186template<FaceConcept FaceType>
187bool isFaceManifoldOnEdge(
const FaceType& f, uint edge)
188 requires comp::HasAdjacentFaces<FaceType>
191 if (!comp::isAdjacentFacesAvailableOn(f)) {
192 throw MissingComponentException(
193 "Face has no Adjacent Faces component.");
197 if (f.adjFace(edge) ==
nullptr) {
201 return f.adjFace(edge)->indexOfAdjFace(&f) !=
UINT_NULL;
221template<FaceConcept FaceType>
222bool isFaceEdgeOnBorder(
const FaceType& f, uint edge)
223 requires comp::HasAdjacentFaces<FaceType>
225 if (!comp::isAdjacentFacesAvailableOn(f)) {
226 throw MissingComponentException(
227 "Face has no Adjacent Faces component.");
230 return f->adjFace(edge) ==
nullptr;
267template<FaceConcept FaceType>
268bool checkFlipEdge(
const FaceType& f, uint edge)
269 requires comp::HasAdjacentFaces<FaceType>
271 if (!comp::isAdjacentFacesAvailableOn(f)) {
272 throw MissingComponentException(
273 "Face has no Adjacent Faces component.");
276 using VertexType = FaceType::VertexType;
278 if (f.vertexNumber() > 3)
281 if (isFaceEdgeOnBorder(f, edge))
284 const VertexType* v0 = f.vertex(edge);
285 const VertexType* v1 = f.vertexMod(edge + 1);
287 const FaceType* of = f.adjFace(edge);
288 uint oe = of->indexOfAdjFace(&f);
293 if (of->vertex(oe) != v1 || of->vertexMod(oe + 1) != v0)
298 const VertexType* f_v2 = f.vertexMod(edge + 2);
299 const VertexType* of_v2 = of->vertexMod(oe + 2);
301 MeshPos<FaceType> pos(&f, f_v2);
302 MeshPos<FaceType> startPos = pos;
305 pos.nextEdgeAdjacentToV();
306 if (pos.adjVertex() == of_v2)
308 }
while (pos != startPos);
333template<FaceConcept FaceType>
334uint edgeAdjacentFacesNumber(
const FaceType& f, uint edge)
335 requires comp::HasAdjacentFaces<FaceType>
337 if (!comp::isAdjacentFacesAvailableOn(f)) {
338 throw MissingComponentException(
339 "Face has no Adjacent Faces component.");
342 ConstEdgeAdjFaceIterator<FaceType> begin(f, edge), end;
344 for (
auto it = begin; it != end; ++it) {
366template<FaceConcept FaceType>
367uint faceEdgesOnBorderNumber(
const FaceType& f)
368 requires comp::HasAdjacentFaces<FaceType>
370 if (!comp::isAdjacentFacesAvailableOn(f)) {
371 throw MissingComponentException(
372 "Face has no Adjacent Faces component.");
376 for (uint i = 0; i < f.vertexNumber(); ++i)
377 if (isFaceEdgeOnBorder(f, i))
402template<FaceConcept FaceType>
403auto faceDihedralAngleOnEdge(
const FaceType& f, uint e)
404 requires comp::HasAdjacentFaces<FaceType>
406 if (!comp::isAdjacentFacesAvailableOn(f)) {
407 throw MissingComponentException(
408 "Face has no Adjacent Faces component.");
422 assert(f.adjFace(e) !=
nullptr);
423 const FaceType& f1 = *(f.adjFace(e));
425 uint e1 = f1.indexOfAdjFace(&f);
428 const auto& vf0 = *(f.vertexMod((
int) e - 1));
429 const auto& vf1 = *(f1.vertexMod(e1 - 1));
434 auto off0 = n0 * vf0.coord();
435 auto off1 = n1 * vf1.coord();
437 auto dist01 = off0 - n0 * vf1.coord();
438 auto dist10 = off1 - n1 * vf0.coord();
440 auto sign = std::abs(dist01) > std::abs(dist10) ? dist01 : dist10;
442 auto angleRad = n0.angle(n1);
443 return sign > 0 ? angleRad : -angleRad;
471template<FaceConcept FaceType>
472void detachAdjacentFacesOnEdge(FaceType& f, uint edge)
473 requires comp::HasAdjacentFaces<FaceType>
475 if (!comp::isAdjacentFacesAvailableOn(f)) {
476 throw MissingComponentException(
477 "Face has no Adjacent Faces component.");
480 FaceType* nextFace = f.adjFace(edge);
484 if (nextFace !=
nullptr) {
486 ConstEdgeAdjFaceIterator<FaceType> begin(f, edge), end;
487 for (
auto it = begin; it != end; ++it) {
491 if (nextFace == prevFace) {
492 uint en = nextFace->indexOfAdjFace(&f);
494 nextFace->setAdjFace(en,
nullptr);
499 uint pn = prevFace->indexOfAdjFace(&f);
501 prevFace->setAdjFace(pn, nextFace);
503 f.setAdjFace(edge,
nullptr);
528template<FaceConcept FaceType>
529void detachFace(FaceType& f)
requires comp::HasAdjacentFaces<FaceType>
531 if (!comp::isAdjacentFacesAvailableOn(f)) {
532 throw MissingComponentException(
533 "Face has no Adjacent Faces component.");
536 using VertexType = FaceType::VertexType;
538 for (uint e = 0; e < f.vertexNumber(); ++e) {
539 detachAdjacentFacesOnEdge(f, e);
542 if constexpr (comp::HasAdjacentFaces<VertexType>) {
543 if (comp::isAdjacentFacesAvailableOn(f.vertex(e))) {
544 VertexType* v = f.vertex(e);
545 uint vpos = v->indexOfAdjFace(&f);
548 v->eraseAdjFace(vpos);
569template<FaceConcept FaceType>
570std::set<const FaceType*> floodFacePatch(
571 const FaceType& seed,
574 if (!comp::isAdjacentFacesAvailableOn(seed)) {
575 throw MissingComponentException(
576 "Face has no Adjacent Faces component.");
579 std::set<const FaceType*>
faces;
581 std::vector<const FaceType*> stackFaces;
583 if (!faceSelector(seed))
588 for (
const FaceType* adjacent : seed.
adjFaces()) {
590 if (adjacent && faceSelector(*adjacent))
591 stackFaces.push_back(adjacent);
595 while (stackFaces.size() > 0) {
596 const FaceType* fi = stackFaces[stackFaces.size() - 1];
597 stackFaces.pop_back();
599 for (
const FaceType* adjacent : fi->
adjFaces()) {
600 if (adjacent && faceSelector(*adjacent)) {
602 stackFaces.push_back(adjacent);
FaceType::VertexType::CoordType faceNormal(const FaceType &f)
Computes the normal of a face, without modifying the face. Works both for triangle and polygonal face...
Definition geometry.h:45
std::vector< uint > earCut(Iterator begin, Iterator end)
Triangulates a simple polygon with no holes using the ear-cutting algorithm.
Definition ear_cut.h:92
constexpr uint UINT_NULL
The UINT_NULL value represent a null value of uint that is the maximum value that can be represented ...
Definition base.h:48
constexpr detail::FacesView faces
A view that allows to iterate overt the Face elements of an object.
Definition face.h:52
constexpr detail::AdjFacesView adjFaces
The adjFaces view allows to obtain a view that access to the adjacent faces of the object that has be...
Definition adj_faces.h:65