1 #include <Core/Geometry/deprecated/TopologicalMesh.hpp>
3 #include <Core/RaCore.hpp>
4 #include <Core/Utils/Log.hpp>
6 #include <Eigen/StdVector>
8 #include <unordered_map>
15 namespace deprecated {
17 using namespace Utils;
21 template <
typename P,
typename T>
22 void addAttribPairToCore( TriangleMesh& triMesh,
23 const TopologicalMesh* topoMesh,
24 OpenMesh::HPropHandleT<T> oh,
25 std::vector<P>& vprop ) {
26 AttribHandle<T> h = triMesh.addAttrib<T>( topoMesh->property( oh ).name() );
27 vprop.push_back( std::make_pair( h, oh ) );
31 using HandleAndValueVector = std::vector<std::pair<AttribHandle<T>, T>,
32 Eigen::aligned_allocator<std::pair<AttribHandle<T>, T>>>;
34 template <
typename P,
typename T>
35 void copyAttribToCoreVertex( HandleAndValueVector<T>& data,
36 const TopologicalMesh* topoMesh,
37 const std::vector<P>& vprop,
38 TopologicalMesh::HalfedgeHandle heh ) {
39 for (
auto pp : vprop ) {
40 data.push_back( std::make_pair( pp.first, topoMesh->property( pp.second, heh ) ) );
45 void copyAttribToCore( TriangleMesh& triMesh,
const HandleAndValueVector<T>& data ) {
47 for (
auto pp : data ) {
48 auto& attr = triMesh.getAttrib( pp.first );
49 auto& attrData = attr.getDataWithLock();
50 attrData.push_back( pp.second );
62 inline void process(
const std::vector<TopologicalMesh::VertexHandle>& ) {
63 LOG( logWARNING ) <<
"Invalid face handle returned : face not added " + m_details;
73 std::string m_details;
80 add_property( m_inputTriangleMeshIndexPph );
84 struct VertexDataInternal {
88 HandleAndValueVector<Scalar> _float;
89 HandleAndValueVector<Vector2> _vec2;
90 HandleAndValueVector<Vector3> _vec3;
91 HandleAndValueVector<Vector4> _vec4;
93 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
95 bool operator==(
const VertexDataInternal& lhs )
const {
96 return _vertex == lhs._vertex && _normal == lhs._normal && _float == lhs._float &&
97 _vec2 == lhs._vec2 && _vec3 == lhs._vec3 && _vec4 == lhs._vec4;
102 size_t operator()(
const VertexDataInternal& lvalue )
const {
103 size_t hx = std::hash<Scalar>()( lvalue._vertex[0] );
104 size_t hy = std::hash<Scalar>()( lvalue._vertex[1] );
105 size_t hz = std::hash<Scalar>()( lvalue._vertex[2] );
106 return ( hx ^ ( hy << 1 ) ) ^ hz;
112 using VertexMap = std::unordered_map<VertexDataInternal, int, hash_vec>;
114 VertexMap vertexHandles;
116 if ( !get_property_handle( m_outputTriangleMeshIndexPph,
"OutputTriangleMeshIndices" ) ) {
117 add_property( m_outputTriangleMeshIndexPph,
"OutputTriangleMeshIndices" );
119 std::vector<PropPair<Scalar>> vprop_float;
120 std::vector<PropPair<Vector2>> vprop_vec2;
121 std::vector<PropPair<Vector3>> vprop_vec3;
122 std::vector<PropPair<Vector4>> vprop_vec4;
125 vprop_float.reserve( m_floatPph.size() );
126 for (
auto oh : m_floatPph )
127 addAttribPairToCore( out,
this, oh, vprop_float );
128 vprop_vec2.reserve( m_vec2Pph.size() );
129 for (
auto oh : m_vec2Pph )
130 addAttribPairToCore( out,
this, oh, vprop_vec2 );
131 vprop_vec3.reserve( m_vec3Pph.size() );
132 for (
auto oh : m_vec3Pph )
133 addAttribPairToCore( out,
this, oh, vprop_vec3 );
134 vprop_vec4.reserve( m_vec4Pph.size() );
135 for (
auto oh : m_vec4Pph )
136 addAttribPairToCore( out,
this, oh, vprop_vec4 );
139 unsigned int vertexIndex = 0;
142 TriangleMesh::PointAttribHandle::Container vertices;
143 TriangleMesh::NormalAttribHandle::Container normals;
146 vertices.reserve( n_vertices() );
147 normals.reserve( n_vertices() );
148 indices.reserve( n_faces() );
150 for ( TopologicalMesh::FaceIter f_it = faces_sbegin(); f_it != faces_end(); ++f_it ) {
155 for ( TopologicalMesh::ConstFaceHalfedgeIter fh_it = cfh_iter( *f_it ); fh_it.is_valid();
157 VertexDataInternal v;
158 CORE_ASSERT( i < 3,
"Non-triangular face found." );
159 v._vertex = point( to_vertex_handle( *fh_it ) );
161 if ( has_halfedge_normals() ) {
162 v._normal =
normal( to_vertex_handle( *fh_it ), *f_it );
164 copyAttribToCoreVertex( v._float,
this, vprop_float, *fh_it );
165 copyAttribToCoreVertex( v._vec2,
this, vprop_vec2, *fh_it );
166 copyAttribToCoreVertex( v._vec3,
this, vprop_vec3, *fh_it );
167 copyAttribToCoreVertex( v._vec4,
this, vprop_vec4, *fh_it );
170 VertexMap::iterator vtr = vertexHandles.find( v );
171 if ( vtr == vertexHandles.end() ) {
172 vi = int( vertexIndex++ );
173 vertexHandles.insert( vtr, VertexMap::value_type( v, vi ) );
174 vertices.push_back( v._vertex );
175 if ( has_halfedge_normals() ) { normals.push_back( v._normal ); }
176 copyAttribToCore( out, v._float );
177 copyAttribToCore( out, v._vec2 );
178 copyAttribToCore( out, v._vec3 );
179 copyAttribToCore( out, v._vec4 );
181 else { vi = vtr->second; }
183 property( m_outputTriangleMeshIndexPph, *fh_it ) = vi;
186 indices.emplace_back( tindices[0], tindices[1], tindices[2] );
188 out.setVertices( std::move( vertices ) );
189 if ( has_halfedge_normals() ) { out.setNormals( std::move( normals ) ); }
190 out.setIndices( std::move( indices ) );
191 CORE_ASSERT( vertexIndex == vertices.size(),
192 "Inconsistent number of faces in generated TriangleMesh." );
217 if ( f < 0 || f > 1 ) {
return false; }
222 VertexHandle v0 = to_vertex_handle( he0 );
223 VertexHandle v1 = to_vertex_handle( he1 );
224 FaceHandle F0 = face_handle( he0 );
225 FaceHandle F1 = face_handle( he1 );
228 if ( ( !is_boundary( he0 ) && valence( F0 ) != 3 ) ||
229 ( !is_boundary( he1 ) && valence( F1 ) != 3 ) ) {
234 const Point p = Point( f * point( v0 ) + ( Scalar( 1. ) - f ) * point( v1 ) );
235 VertexHandle v = add_vertex( p );
238 HalfedgeHandle he3 = new_edge( v, v1 );
239 HalfedgeHandle he2 = opposite_halfedge_handle( he3 );
240 set_halfedge_handle( v, he0 );
241 set_vertex_handle( he1, v );
244 if ( !is_boundary( he0 ) ) {
245 HalfedgeHandle h0 = next_halfedge_handle( he0 );
246 HalfedgeHandle h1 = next_halfedge_handle( h0 );
248 VertexHandle A = to_vertex_handle( h0 );
249 HalfedgeHandle e2 = new_edge( v, A );
250 HalfedgeHandle e0 = opposite_halfedge_handle( e2 );
252 FaceHandle F2 = new_face();
253 set_halfedge_handle( F0, he0 );
254 set_halfedge_handle( F2, h1 );
256 set_face_handle( h0, F0 );
257 set_face_handle( e0, F0 );
258 set_face_handle( he0, F0 );
259 set_next_halfedge_handle( he0, h0 );
260 set_next_halfedge_handle( h0, e0 );
261 set_next_halfedge_handle( e0, he0 );
263 set_face_handle( h1, F2 );
264 set_face_handle( he2, F2 );
265 set_face_handle( e2, F2 );
266 set_next_halfedge_handle( e2, h1 );
267 set_next_halfedge_handle( h1, he2 );
268 set_next_halfedge_handle( he2, e2 );
276 HalfedgeHandle h1 = prev_halfedge_handle( he0 );
277 set_next_halfedge_handle( h1, he2 );
278 set_next_halfedge_handle( he2, he0 );
284 if ( !is_boundary( he1 ) ) {
285 HalfedgeHandle o1 = next_halfedge_handle( he1 );
286 HalfedgeHandle o0 = next_halfedge_handle( o1 );
288 VertexHandle B = to_vertex_handle( o1 );
289 HalfedgeHandle e1 = new_edge( v, B );
290 HalfedgeHandle e3 = opposite_halfedge_handle( e1 );
292 FaceHandle F3 = new_face();
293 set_halfedge_handle( F3, o1 );
294 set_halfedge_handle( F1, he1 );
296 set_face_handle( o1, F3 );
297 set_face_handle( e3, F3 );
298 set_face_handle( he3, F3 );
299 set_next_halfedge_handle( he3, o1 );
300 set_next_halfedge_handle( o1, e3 );
301 set_next_halfedge_handle( e3, he3 );
303 set_face_handle( o0, F1 );
304 set_face_handle( he1, F1 );
305 set_face_handle( e1, F1 );
306 set_next_halfedge_handle( he1, e1 );
307 set_next_halfedge_handle( e1, o0 );
308 set_next_halfedge_handle( o0, he1 );
319 HalfedgeHandle o1 = next_halfedge_handle( he1 );
321 set_next_halfedge_handle( he1, he3 );
322 set_next_halfedge_handle( he3, o1 );
327 if (
halfedge_handle( v1 ) == he0 ) { set_halfedge_handle( v1, he2 ); }
334 void TopologicalMesh::split( EdgeHandle _eh, VertexHandle _vh ) {
338 VertexHandle v2 = to_vertex_handle( o0 );
340 HalfedgeHandle e1 = new_edge( _vh, v2 );
341 HalfedgeHandle t1 = opposite_halfedge_handle( e1 );
343 FaceHandle f0 = face_handle( h0 );
344 FaceHandle f3 = face_handle( o0 );
346 set_halfedge_handle( _vh, h0 );
347 set_vertex_handle( o0, _vh );
349 if ( !is_boundary( h0 ) ) {
350 HalfedgeHandle h1 = next_halfedge_handle( h0 );
351 HalfedgeHandle h2 = next_halfedge_handle( h1 );
353 VertexHandle v1 = to_vertex_handle( h1 );
355 HalfedgeHandle e0 = new_edge( _vh, v1 );
356 HalfedgeHandle t0 = opposite_halfedge_handle( e0 );
358 FaceHandle f1 = new_face();
359 set_halfedge_handle( f0, h0 );
360 set_halfedge_handle( f1, h2 );
362 set_face_handle( h1, f0 );
363 set_face_handle( t0, f0 );
364 set_face_handle( h0, f0 );
366 set_face_handle( h2, f1 );
367 set_face_handle( t1, f1 );
368 set_face_handle( e0, f1 );
370 set_next_halfedge_handle( h0, h1 );
371 set_next_halfedge_handle( h1, t0 );
372 set_next_halfedge_handle( t0, h0 );
374 set_next_halfedge_handle( e0, h2 );
375 set_next_halfedge_handle( h2, t1 );
376 set_next_halfedge_handle( t1, e0 );
379 set_next_halfedge_handle( prev_halfedge_handle( h0 ), t1 );
380 set_next_halfedge_handle( t1, h0 );
384 if ( !is_boundary( o0 ) ) {
385 HalfedgeHandle o1 = next_halfedge_handle( o0 );
386 HalfedgeHandle o2 = next_halfedge_handle( o1 );
388 VertexHandle v3 = to_vertex_handle( o1 );
390 HalfedgeHandle e2 = new_edge( _vh, v3 );
391 HalfedgeHandle t2 = opposite_halfedge_handle( e2 );
393 FaceHandle f2 = new_face();
394 set_halfedge_handle( f2, o1 );
395 set_halfedge_handle( f3, o0 );
397 set_face_handle( o1, f2 );
398 set_face_handle( t2, f2 );
399 set_face_handle( e1, f2 );
401 set_face_handle( o2, f3 );
402 set_face_handle( o0, f3 );
403 set_face_handle( e2, f3 );
405 set_next_halfedge_handle( e1, o1 );
406 set_next_halfedge_handle( o1, t2 );
407 set_next_halfedge_handle( t2, e1 );
409 set_next_halfedge_handle( o0, e2 );
410 set_next_halfedge_handle( e2, o2 );
411 set_next_halfedge_handle( o2, o0 );
414 set_next_halfedge_handle( e1, next_halfedge_handle( o0 ) );
415 set_next_halfedge_handle( o0, e1 );
416 set_halfedge_handle( _vh, e1 );
424 void TopologicalMesh::split_copy( EdgeHandle _eh, VertexHandle _vh ) {
428 const int nf = n_faces();
435 for ( VEIter ve_it = ve_iter( _vh ); ve_it.is_valid(); ++ve_it )
436 copy_all_properties( _eh, *ve_it,
true );
438 for (
auto vh : { v0, v1 } ) {
440 const HalfedgeHandle h = find_halfedge( _vh, vh );
442 if ( !is_boundary( h ) ) {
443 FaceHandle fh0 = face_handle( h );
444 FaceHandle fh1 = face_handle( opposite_halfedge_handle( prev_halfedge_handle( h ) ) );
446 if ( fh0.idx() >= nf ) std::swap( fh0, fh1 );
449 copy_all_properties( fh0, fh1,
true );
const Normal & normal(VertexHandle vh, FaceHandle fh) const
void copyAllProps(HalfedgeHandle input_heh, HalfedgeHandle copy_heh)
void interpolateAllProps(HalfedgeHandle in_a, HalfedgeHandle in_b, HalfedgeHandle out, Scalar f)
bool splitEdge(TopologicalMesh::EdgeHandle eh, Scalar f)
HalfedgeHandle halfedge_handle(VertexHandle vh, FaceHandle fh) const
TriangleMesh toTriangleMesh()
[Default command implementation]
void initialize(const TriangleMesh &)
Initalize with input Ra::Core::Geometry::TriangleMesh.
DefaultNonManifoldFaceCommand(const std::string &details={})
details string is printed along with the message
void postProcess(TopologicalMesh &)
If needed, apply post-processing on the TopologicalMesh.
void process(const std::vector< TopologicalMesh::VertexHandle > &)
Process non-manifold face.