GameApi 28
Library used by GameApi Builder tool
Loading...
Searching...
No Matches
mesh_connected_components.h
Go to the documentation of this file.
1// Copyright 2016 The Draco Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15#ifndef DRACO_MESH_MESH_CONNECTED_COMPONENTS_H_
16#define DRACO_MESH_MESH_CONNECTED_COMPONENTS_H_
17
18#include <vector>
19
21
22namespace draco {
23
24// Class for detecting connected components on an input mesh defined by a
25// corner table. Degenerated faces and their vertices are not assigned to any
26// component.
28 public:
30
31 // Initializes the class with the component data of the input mesh. No other
32 // method should be called before this one.
33 template <class CornerTableT = CornerTable>
34 void FindConnectedComponents(const CornerTableT *corner_table);
35 int NumConnectedComponents() const { return components_.size(); }
36
38 std::vector<int> vertices;
39 std::vector<int> faces;
40 std::vector<int> boundary_edges;
41 };
42
43 const ConnectedComponent &GetConnectedComponent(int index) const {
44 return components_[index];
45 }
46
47 // Returns the id of an component attached to a given vertex. Returns -1 when
48 // the vertex was not assigned to any component.
49 int GetConnectedComponentIdAtVertex(int vertex_id) const {
50 return vertex_to_component_map_[vertex_id];
51 }
52
53 // Returns the number of vertices that belong to the input component.
54 int NumConnectedComponentVertices(int component_id) const {
55 return components_[component_id].vertices.size();
56 }
57
58 // Returns the i-th vertex of the input component.
59 int GetConnectedComponentVertex(int component_id, int i) const {
60 return components_[component_id].vertices[i];
61 }
62
63 // Returns the id of an component attached to a given face. Returns -1 when
64 // the face was not assigned to any component.
65 int GetConnectedComponentIdAtFace(int face_id) const {
66 return face_to_component_map_[face_id];
67 }
68
69 // Returns the number of faces that belong to the input component.
70 int NumConnectedComponentFaces(int component_id) const {
71 return components_[component_id].faces.size();
72 }
73
74 // Returns the i-th face of the input component.
75 int GetConnectedComponentFace(int component_id, int i) const {
76 return components_[component_id].faces[i];
77 }
78
79 // Returns the number of boundary edges that belong to the input component.
80 int NumConnectedComponentBoundaryEdges(int component_id) const {
81 return components_[component_id].boundary_edges.size();
82 }
83
84 // Returns the i-th boundary edge of the input component.
85 int GetConnectedComponentBoundaryEdge(int component_id, int i) const {
86 return components_[component_id].boundary_edges[i];
87 }
88
89 private:
90 std::vector<int> vertex_to_component_map_;
91 std::vector<int> face_to_component_map_;
92 std::vector<int> boundary_corner_to_component_map_;
93 std::vector<ConnectedComponent> components_;
94};
95
96template <class CornerTableT>
98 const CornerTableT *corner_table) {
99 components_.clear();
100 vertex_to_component_map_.assign(corner_table->num_vertices(), -1);
101 face_to_component_map_.assign(corner_table->num_faces(), -1);
102 boundary_corner_to_component_map_.assign(corner_table->num_corners(), -1);
103 std::vector<int> is_face_visited(corner_table->num_faces(), false);
104 std::vector<int> face_stack;
105 // Go over all faces of the mesh and for each unvisited face, recursively
106 // traverse its neighborhood and mark all traversed faces as visited. All
107 // faces visited during one traversal belong to one mesh component.
108 for (int face_id = 0; face_id < corner_table->num_faces(); ++face_id) {
109 if (is_face_visited[face_id]) {
110 continue;
111 }
112 if (corner_table->IsDegenerated(FaceIndex(face_id))) {
113 continue;
114 }
115 const int component_id = components_.size();
116 components_.push_back(ConnectedComponent());
117 face_stack.push_back(face_id);
118 is_face_visited[face_id] = true;
119 while (!face_stack.empty()) {
120 const int act_face_id = face_stack.back();
121 if (face_to_component_map_[act_face_id] == -1) {
122 face_to_component_map_[act_face_id] = component_id;
123 components_[component_id].faces.push_back(act_face_id);
124 }
125 face_stack.pop_back();
126 // Gather all neighboring faces.
127 std::array<CornerIndex, 3> corners =
128 corner_table->AllCorners(FaceIndex(act_face_id));
129 for (int c = 0; c < 3; ++c) {
130 // Update vertex to component mapping.
131 const int vertex_id = corner_table->Vertex(corners[c]).value();
132 if (vertex_to_component_map_[vertex_id] == -1) {
133 vertex_to_component_map_[vertex_id] = component_id;
134 components_[component_id].vertices.push_back(vertex_id);
135 }
136 // Traverse component to neighboring faces (add the faces to the stack).
137 const CornerIndex opp_corner = corner_table->Opposite(corners[c]);
138 if (opp_corner == kInvalidCornerIndex) {
139 if (boundary_corner_to_component_map_[corners[c].value()] == -1) {
140 boundary_corner_to_component_map_[corners[c].value()] =
141 component_id;
142 components_[component_id].boundary_edges.push_back(
143 corners[c].value());
144 }
145 continue; // Invalid corner (mesh boundary).
146 }
147
148 const int opp_face_id = corner_table->Face(opp_corner).value();
149 if (is_face_visited[opp_face_id]) {
150 continue; // Opposite face has been already reached.
151 }
152 is_face_visited[opp_face_id] = true;
153 face_stack.push_back(opp_face_id);
154 }
155 }
156 }
157}
158
159} // namespace draco
160
161#endif // DRACO_MESH_MESH_CONNECTED_COMPONENTS_H_
int NumConnectedComponentBoundaryEdges(int component_id) const
Definition mesh_connected_components.h:80
int GetConnectedComponentIdAtVertex(int vertex_id) const
Definition mesh_connected_components.h:49
int NumConnectedComponentVertices(int component_id) const
Definition mesh_connected_components.h:54
const ConnectedComponent & GetConnectedComponent(int index) const
Definition mesh_connected_components.h:43
int NumConnectedComponents() const
Definition mesh_connected_components.h:35
int GetConnectedComponentIdAtFace(int face_id) const
Definition mesh_connected_components.h:65
int GetConnectedComponentBoundaryEdge(int component_id, int i) const
Definition mesh_connected_components.h:85
int GetConnectedComponentVertex(int component_id, int i) const
Definition mesh_connected_components.h:59
int GetConnectedComponentFace(int component_id, int i) const
Definition mesh_connected_components.h:75
void FindConnectedComponents(const CornerTableT *corner_table)
Definition mesh_connected_components.h:97
int NumConnectedComponentFaces(int component_id) const
Definition mesh_connected_components.h:70
Definition attribute_octahedron_transform.cc:21
CornerIndex CornerIndex
Definition mesh_edgebreaker_encoder_impl.cc:35
FaceIndex FaceIndex
Definition mesh_edgebreaker_encoder_impl.cc:36
Definition mesh_connected_components.h:37
std::vector< int > boundary_edges
Definition mesh_connected_components.h:40
std::vector< int > faces
Definition mesh_connected_components.h:39
std::vector< int > vertices
Definition mesh_connected_components.h:38