DHART
Loading...
Searching...
No Matches
meshinfo.cpp
Go to the documentation of this file.
1
7
8#include <meshinfo.h>
9#include <Geometry>
10#include <HFExceptions.h>
11#include <math.h>
12#include <corecrt_math_defines.h>
13#include <iostream>
14#include <robin_hood.h>
15
16
17#define _USE_MATH_DEFINES
18
19using std::array;
20using std::vector;
21namespace HF::Geometry {
22 template <typename T>
23 MeshInfo<T>::MeshInfo(const vector<array<T, 3>>& vertices, int id, std::string name)
24 {
25 // Throw if the input array has no values in it.
26 const size_t n = vertices.size();
27 if (vertices.size() < 1) throw HF::Exceptions::InvalidOBJ(); // Doesn't have any valid geometry
28
29 //AddVerts(vertices);
30 VectorsToBuffers(vertices);
31
32 // Throw if a NAN was placed into the mesh.
33 if (verts.hasNaN()) throw HF::Exceptions::InvalidOBJ();
34
35 meshid = id;
36 this->name = name;
37 }
38
39 template <typename T>
40 inline void MeshInfo<T>::SetVert(int index, T x, T y, T z)
41 {
42 // the () operator is overloaded for eigen to index the array
43 // For example array(row, col) will index the value at row, col.
44 verts(0, index) = x;
45 verts(1, index) = y;
46 verts(2, index) = z;
47 }
48
49
72 template <typename T>
74 const vector<array<T, 3>>& vertices,
75 vector<int>& mapped_indexes,
76 vector<T>& mapped_vertices
77 ) {
78 // Create a hashmap to map vertices to indices.
79 robin_hood::unordered_map <array<T, 3>, int> index_map;
80 int next_id = 0;
81
82 int vertsize = vertices.size();
83
84 // Iterate through every 3 vertexes in vertices
85 for (int i = 0; i < vertsize; i += 3) {
86 array<int, 3> ids;
87
88 // Iterate through every 3 vertexes in vertices.
89 for (int k = 0; k < 3; k++)
90 {
91 // Get the vertex at this position
92 const auto& vert = vertices[i + k];
93 int current_id;
94
95 // Get ID from index map, or create a new ID if one doesn't exist
96 if (index_map.count(vert) > 0)
97 current_id = index_map[vert];
98 else {
99
100 // store the id in the hashmap for this vertex.
101 index_map[vert] = next_id;
102 current_id = next_id;
103
104 // If this is a new vertex, add it the mapped_vertices vector
105 mapped_vertices.push_back(vert[0]);
106 mapped_vertices.push_back(vert[1]);
107 mapped_vertices.push_back(vert[2]);
108 next_id++;
109 }
110 // Store this new ID in the array.
111 ids[k] = current_id;
112 }
113
114 // Push the indexes back into the triangle array
115 mapped_indexes.push_back(ids[0]);
116 mapped_indexes.push_back(ids[1]);
117 mapped_indexes.push_back(ids[2]);
118 }
119 }
120
121 template <typename T>
122 void MeshInfo<T>::VectorsToBuffers(const vector<array<T, 3>>& vertices)
123 {
124 // Create and fill vectors
125 vector<int> mapped_indexes; vector<T> mapped_vertices;
126 IndexRawVertices(vertices, mapped_indexes, mapped_vertices);
127
128 // This OBJ isn't valid if the following doesn't hold
129 if (!(mapped_indexes.size() % 3 == 0))
131
132 // Copy contents into index and vertex vectors into matrices.
133 verts.resize(3, mapped_vertices.size() / 3);
134 indices.resize(3, mapped_indexes.size() / 3);
135 std::move(mapped_vertices.begin(), mapped_vertices.end(), verts.data());
136 std::move(mapped_indexes.begin(), mapped_indexes.end(), indices.data());
137 }
138
139 template <typename T>
141 const vector<T>& in_vertices,
142 const vector<int>& in_indexes,
143 int id,
144 std::string name
145 ) {
146 // If the size of vertices or the size of indexes aren't multiples of 3
147 // then we can easily rule this out as an invalid mesh
148 if (in_vertices.size() % 3 != 0 || in_indexes.size() % 3 != 0)
150
151 // Resize verts and indices, then std::move valuees into them.
152 verts.resize(3, in_vertices.size() / 3);
153 indices.resize(3, in_indexes.size() / 3);
154 std::move(in_vertices.begin(), in_vertices.end(), verts.data());
155 std::move(in_indexes.begin(), in_indexes.end(), indices.data());
156
157 meshid = id;
158 this->name = name;
159 }
160
161 template <typename T>
162 void MeshInfo<T>::AddVerts(const vector<array<T, 3>>& in_vertices)
163 {
164 if (in_vertices.size() % 3 != 0) throw HF::Exceptions::InvalidOBJ(); // Incomplete triangle
165
166 verts.resize(3, (static_cast<size_t>(verts.cols()) + in_vertices.size()));
167
168 for (int i = 0; i < in_vertices.size(); i++) {
169 auto& vertex = in_vertices[i];
170 verts(0, i) = vertex[0];
171 verts(1, i) = vertex[1];
172 verts(2, i) = vertex[2];
173 }
174 if (verts.hasNaN()) throw std::exception("Creation of mesh info failed");
175 }
176
177 template <typename T>
178 int MeshInfo<T>::NumVerts() const { return static_cast<int>(verts.cols()); }
179
180 template <typename T>
181 int MeshInfo<T>::NumTris() const { return static_cast<int>(indices.cols()); }
182
183 template <typename T>
185 {
186 Eigen::AngleAxis<T> yrot(0.5f * static_cast<T>(M_PI), Eigen::Vector3<T>::UnitX());
187 Eigen::Quaternion<T> quat;
188 quat = yrot;
189 quat.normalize();
190 verts = yrot.toRotationMatrix() * verts;
191 //auto newer_matrix = new_matrix.eval();
192 if (!verts.allFinite()) throw std::exception("Verts has NAN");
193 }
194
195 template <typename T>
197 {
198 Eigen::AngleAxis<T> yrot(-0.5f * static_cast<T>(M_PI), Eigen::Vector3<T>::UnitX());
199 Eigen::Quaternion<T> quat;
200 quat = yrot;
201 quat.normalize();
202 Eigen::Matrix3<T> rotation_matrix = yrot.toRotationMatrix();
203 assert(!rotation_matrix.hasNaN());
204 verts = (rotation_matrix * verts);
205 assert(!verts.hasNaN());
206 }
207
208 template <typename T>
209 void MeshInfo<T>::PerformRotation(T rx, T ry, T rz)
210 {
211 // Convert to radians
212 T radian_ratio = static_cast<T>(M_PI) / 180.00f;
213 rx *= radian_ratio; ry *= radian_ratio; rz *= radian_ratio;
214
215 // Implementation based on
216 // https://stackoverflow.com/questions/21412169/creating-a-rotation-matrix-with-pitch-yaw-roll-using-eigen
217 Eigen::AngleAxis<T> rollAngle(rz, Eigen::Vector3<T>::UnitZ());
218 Eigen::AngleAxis<T> yawAngle(ry, Eigen::Vector3<T>::UnitY());
219 Eigen::AngleAxis<T> pitchAngle(rx, Eigen::Vector3<T>::UnitX());
220
221
222 // Create a quaternion from the angles, normalize it, then
223 // convert it to a rotation matrix.
224 Eigen::Quaternion<T> q = (rollAngle * yawAngle * pitchAngle);
225 q.normalize();
226 Eigen::Matrix3<T> rotation_matrix = q.toRotationMatrix();
227
229 // Assert that we didn't create any NANS or infinite values
230 assert(rotation_matrix.allFinite());
231
232 // Apply the rotation matrix to verts
233 verts = (rotation_matrix * verts);
234
235 // Once again assert that we didn't create any nans or infinite numbers.
236 assert(verts.allFinite());
238 }
239
240 template <typename T>
241 int MeshInfo<T>::GetMeshID() const { return meshid; }
242
243 template <typename T>
245 {
246 // Preallocate space for all vertices
247 vector<T> out_array(verts.size());
248
249 // Copy verts into it
250 std::copy(verts.data(), verts.data() + verts.size(), out_array.begin());
251
252 return out_array;
253 }
254
255 template <typename T>
256 vector<int> MeshInfo<T>::getRawIndices() const
257 {
258 vector<int> out_array(indices.size());
259 std::copy(indices.data(), indices.data() + indices.size(), out_array.begin());
260 return out_array;
261 }
262
263 template <typename T>
264 vector<std::array<T,3>> MeshInfo<T>::GetUnindexedVertices() const
265 {
266 // Preallocate an array 3x the size of the triangle matrix
267 int tri_count = NumTris();
268 vector<array<T, 3>>out_array(tri_count * 3);
269
270 // Fill arrays with values of vertices
271 for (int i = 0; i < tri_count; i++)
272 {
273 const int offset = i * 3;
274 out_array[offset] = (*this)[indices(0, i)];
275 out_array[offset + 1] = (*this)[indices(1, i)];
276 out_array[offset + 2] = (*this)[indices(2, i)];
277 }
278 return out_array;
279 }
280
281 template <typename T>
282 void MeshInfo<T>::SetMeshID(int new_id) { meshid = new_id; }
283
284 template <typename T>
285 array<T, 3> MeshInfo<T>::operator[](int i) const
286 {
287 // Throw if going beyond the array bounds
288 if (i < 0 || i > NumVerts()) throw std::exception("Out of range on index");
289
290 // Create and return out array.
291 array<T, 3> out_array;
292 out_array[0] = verts(0, i);
293 out_array[1] = verts(1, i);
294 out_array[2] = verts(2, i);
295 return out_array;
296 }
297
305 template <typename T>
306 T arrayDist(const array<T, 3> from, const array<T, 3>& to) {
307 return sqrtf(powf(from[0] - to[0], 2) + powf(from[1] - to[1], 2) + powf(from[2] - to[2], 2));
308 }
309 template <typename T>
310 bool MeshInfo<T>::operator==(const MeshInfo& M2) const
311 {
312 // Get out quickly if the number of vertices do not match
313 if (NumVerts() != M2.NumVerts()) return false;
314
315 for (int i = 0; i < NumVerts(); i++) {
316 auto this_array = (*this)[i];
317 auto that_array = M2[i];
318
319 if (!(arrayDist(this_array, that_array) < 0.001))
320 return false;
321 }
322 return true;
323 }
324
325 template <typename T>
327 array_and_size<int> ret_array;
328
329 ret_array.size = indices.size();
330 ret_array.data = const_cast<int*>(indices.data());
331
332 return ret_array;
333 }
334
335 template <typename T>
337 array_and_size<T> ret_array;
338
339 ret_array.size = verts.size();
340 ret_array.data = const_cast<T*>(verts.data());
341
342 return ret_array;
343 }
344}
345template class HF::Geometry::MeshInfo<double>;
346
347template class HF::Geometry::MeshInfo<float>;
Contains definitions for the Exceptions namespace.
Contains definitions for the MeshInfo class.
Manipulate and load geometry from disk.
Definition: meshinfo.cpp:21
T arrayDist(const array< T, 3 > from, const array< T, 3 > &to)
Calculate the distance between from and to.
Definition: meshinfo.cpp:306
void IndexRawVertices(const vector< array< T, 3 > > &vertices, vector< int > &mapped_indexes, vector< T > &mapped_vertices)
Index an array of vertices.
Definition: meshinfo.cpp:73
The OBJ file was not valid.
Definition: HFExceptions.h:65
A simple type to hold the size and data pointer of an array.
Definition: meshinfo.h:98
int size
Number of elements in data
Definition: meshinfo.h:99
A collection of vertices and indices representing geometry.
Definition: meshinfo.h:124
void AddVerts(const std::vector< std::array< numeric_type, 3 > > &verts)
Add more vertices to this mesh.
Definition: meshinfo.cpp:162
int GetMeshID() const
Get the ID of this mesh.
Definition: meshinfo.cpp:241
bool operator==(const MeshInfo &M2) const
Compare the vertices of two MeshInfo objects.
Definition: meshinfo.cpp:310
void PerformRotation(numeric_type rx, numeric_type ry, numeric_type rz)
Rotate this mesh by x, y, z rotations in degrees (pitch, yaw, roll).
Definition: meshinfo.cpp:209
std::array< numeric_type, 3 > operator[](int i) const
Get vertex at a specific index in the mesh.
Definition: meshinfo.cpp:285
void SetMeshID(int new_id)
Change the ID of this mesh.
Definition: meshinfo.cpp:282
std::vector< std::array< numeric_type, 3 > > GetUnindexedVertices() const
Retrieve an unindexed array of this mesh's vertices.
Definition: meshinfo.cpp:264
void SetVert(int index, numeric_type x, numeric_type y, numeric_type z)
Change the position of the vertex at index.
Definition: meshinfo.cpp:40
void ConvertToOBJCoordinates()
Convert a mesh from Z-Up to Y-Up.
Definition: meshinfo.cpp:196
int NumTris() const
Calculate the total number of triangles in this mesh.
Definition: meshinfo.cpp:181
int NumVerts() const
Determine how many vertices are in this mesh.
Definition: meshinfo.cpp:178
MeshInfo()
Construct an empty instance of MeshInfo.
Definition: meshinfo.h:177
void VectorsToBuffers(const std::vector< std::array< numeric_type, 3 > > &vertices)
Index vertices then insert them into verts and indices.
Definition: meshinfo.cpp:122
const array_and_size< int > GetIndexPointer() const
Get a pointer to the index array of this mesh.
Definition: meshinfo.cpp:326
const array_and_size< numeric_type > GetVertexPointer() const
Get a pointer to the vertex array of this mesh.
Definition: meshinfo.cpp:336
void ConvertToRhinoCoordinates()
Convert a mesh from Y-Up to Z-Up.
Definition: meshinfo.cpp:184
std::vector< numeric_type > GetIndexedVertices() const
A copy of every vertex in this array.
Definition: meshinfo.cpp:244
std::vector< int > getRawIndices() const
Retrieve a copy of this mesh's index buffer as a 1D array.
Definition: meshinfo.cpp:256