From b37dc510271b3d07bab0a2bad40203ac6d5a87b9 Mon Sep 17 00:00:00 2001 From: "fabian.gerold@gmail.com" Date: Mon, 21 Nov 2022 21:09:54 +0100 Subject: [PATCH] add method addFacesReversed() as a variant to fix open meshes --- .../src/ifcpp/geometry/Carve/FaceConverter.h | 29 +- .../ifcpp/geometry/Carve/GeometryConverter.h | 21 - .../ifcpp/geometry/Carve/GeometryInputData.h | 1777 +++++++++-------- .../src/ifcpp/geometry/Carve/MeshUtils.h | 96 +- .../src/main.cpp | 3 + 5 files changed, 1055 insertions(+), 871 deletions(-) diff --git a/IfcPlusPlus/src/ifcpp/geometry/Carve/FaceConverter.h b/IfcPlusPlus/src/ifcpp/geometry/Carve/FaceConverter.h index 45bd59003..d69920473 100644 --- a/IfcPlusPlus/src/ifcpp/geometry/Carve/FaceConverter.h +++ b/IfcPlusPlus/src/ifcpp/geometry/Carve/FaceConverter.h @@ -319,6 +319,7 @@ class FaceConverter : public StatusCallback } PolyInputCache3D poly_cache(m_epsMergePoints); BuildingEntity* report_entity = nullptr; + bool dumpPolygon = false; for( const shared_ptr& ifc_face : vec_faces ) { @@ -395,15 +396,14 @@ class FaceConverter : public StatusCallback } #ifdef _DEBUG - if( ifc_face->m_tag == 3517290 ) - { - glm::vec4 color(0.5, 0.6, 0.7, 1.0); - GeomDebugDump::dumpPolyline(loop_points, color, true); - } + //glm::vec4 color(0.5, 0.6, 0.7, 1.0); + //GeomDebugDump::dumpPolyline(loop_points, color, false); + //GeomDebugDump::moveOffset(0.01); + //dumpPolygon = true; #endif } - bool dumpPolygon = false; + for( size_t iiLoop = 0; iiLoop < face_loops.size(); ++iiLoop ) { std::vector& loop = face_loops[iiLoop]; @@ -423,7 +423,22 @@ class FaceConverter : public StatusCallback } else if( st == CLOSED_SHELL ) { - item_data->addClosedPolyhedron(poly_cache.m_poly_data); + bool success = item_data->addClosedPolyhedron(poly_cache.m_poly_data); + if( !success ) + { +#ifdef _DEBUG + if( item_data->m_meshsets_open.size() > 0) + { + glm::vec4 color(0.5, 0.6, 0.7, 1.0); + GeomDebugDump::dumpMeshset(item_data->m_meshsets_open[0], color, true); + } + if( item_data->m_meshsets.size() > 0) + { + glm::vec4 color(0.5, 0.6, 0.7, 1.0); + GeomDebugDump::dumpMeshset(item_data->m_meshsets[0], color, true); + } +#endif + } } } }; diff --git a/IfcPlusPlus/src/ifcpp/geometry/Carve/GeometryConverter.h b/IfcPlusPlus/src/ifcpp/geometry/Carve/GeometryConverter.h index 0bfe7f9c1..9fc23383b 100644 --- a/IfcPlusPlus/src/ifcpp/geometry/Carve/GeometryConverter.h +++ b/IfcPlusPlus/src/ifcpp/geometry/Carve/GeometryConverter.h @@ -792,27 +792,6 @@ class GeometryConverter : public StatusCallback return; } -#ifdef _DEBUG - if( ifc_product->m_GlobalId->m_value.compare("1Ymw2Qiez6buX6OkNzOEaT")==0 || ifc_product->m_GlobalId->m_value.compare("1Ymw2Qiez6buX6OkVzOEnI") == 0 ) - { - int wait = ifc_product->m_tag; // 181595 - } - if( ifc_product->m_GlobalId->m_value.compare("1GVZve0001O34pDJ0qDZ0m") == 0 ) - { - int wait = ifc_product->m_tag; // 181595 - } - - if( ifc_product->m_GlobalId->m_value.compare("2O2Fr$t4X7Zf8NOew3FLR9") == 0 ) - { - int wait = ifc_product->m_tag; // 181595 - } - - if( ifc_product->m_GlobalId->m_value.compare("3ThA22djr8AQQ9eQMA5s7I") == 0 ) - { - int wait = ifc_product->m_tag; - } -#endif - shared_ptr& product_representation = ifc_product->m_Representation; if( !product_representation ) { diff --git a/IfcPlusPlus/src/ifcpp/geometry/Carve/GeometryInputData.h b/IfcPlusPlus/src/ifcpp/geometry/Carve/GeometryInputData.h index 6c3ff61e6..96217e75c 100644 --- a/IfcPlusPlus/src/ifcpp/geometry/Carve/GeometryInputData.h +++ b/IfcPlusPlus/src/ifcpp/geometry/Carve/GeometryInputData.h @@ -39,11 +39,13 @@ inline void premultMatrix( const carve::math::Matrix& matrix_to_append, carve::m { target_matrix = matrix_to_append*target_matrix; } - +class PolyInputCache3D; namespace MeshUtils { inline void intersectOpenEdges(shared_ptr>& meshset, double eps, bool dumpMeshes); static void resolveOpenEdges(shared_ptr>& meshset, double eps, bool dumpPolygons); + inline void polyhedronFromMesh(const carve::mesh::Mesh<3>* mesh, PolyInputCache3D& polyInput); + inline bool addFacesReversed(const PolyInputCache3D& poly_cache_source, PolyInputCache3D& poly_cache_target); } /** @@ -265,1146 +267,1241 @@ inline bool fixPolyhedronData(const shared_ptr& po return inputCorrect; } -class RepresentationData; -class ProductShapeData; - -/** -*\brief Class ItemShapeData: holds input data of one IFC geometric representation item. -* Parent-child relationship of ItemShapeData, RepresentationData, ProductShapeData: -* ... -* |-> ProductShapeData [1...n] -* |-> ProductShapeData [1...n] -* |-> RepresentationData [1...n] -* |-> ItemShapeData [1...n] -*/ -class ItemShapeData +inline bool reverseFacesInPolyhedronData(const shared_ptr& poly_data) { -public: - ItemShapeData(){} - ~ItemShapeData(){} - - std::vector > m_polylines; - std::vector > > m_meshsets; - std::vector > > m_meshsets_open; - std::vector > m_vec_item_appearances; - std::vector > m_vec_text_literals; - weak_ptr m_parent_representation; // Pointer to representation object that this item belongs to - shared_ptr m_ifc_item; - -protected: - std::vector > m_vertex_points; + if( !poly_data ) + { + return false; + } -public: - bool isEmpty() + std::vector& faceIndices = poly_data->faceIndices; + if( faceIndices.size() == 0 ) { - if( m_vertex_points.size() > 0 ) { return false; } - if( m_polylines.size() > 0 ) { return false; } - if( m_meshsets.size() > 0 ) { return false; } - if( m_meshsets_open.size() > 0 ) { return false; } - if( m_vec_item_appearances.size() > 0 ) { return false; } - if( m_vec_text_literals.size() > 0 ) { return false; } + return true; + } + size_t numPointsAll = poly_data->points.size(); + if( numPointsAll < 2 ) + { return true; } + bool inputCorrect = true; + size_t maxPointIndex = numPointsAll - 1; - void addOpenOrClosedPolyhedron( const shared_ptr& poly_data ) + std::vector polyDataReversed; + int numFacesCorrected = 0; + + for( size_t iiFace = 0; iiFace < faceIndices.size(); ) { - if( !poly_data ) - { - return; - } + int numPoints = faceIndices[iiFace]; + int numPointsIdx = iiFace; - // check if it is open or closed - if( poly_data->getVertexCount() < 3 ) + if( iiFace + numPoints >= faceIndices.size() ) { - return; + // skip face + break; } - bool correct = checkPolyhedronData(poly_data); - if( !correct ) + std::vector pointIdxCurrentFace; + for( size_t iiPoint = 1; iiPoint <= numPoints; ++iiPoint ) { - fixPolyhedronData(poly_data); -#ifdef _DEBUG - bool correct2 = checkPolyhedronData(poly_data); - if( !correct2 ) - { - std::cout << "incorrect idx"; - } -#endif + int idx = faceIndices[iiFace + iiPoint]; + pointIdxCurrentFace.push_back(idx); } - shared_ptr > meshset( poly_data->createMesh( carve::input::opts() ) ); - if( meshset->isClosed() ) + polyDataReversed.push_back(numPoints); + std::copy(pointIdxCurrentFace.rbegin(), pointIdxCurrentFace.rend(), std::back_inserter(polyDataReversed)); + + iiFace += numPoints + 1; + + if( iiFace > faceIndices.size() ) { - m_meshsets.push_back( meshset ); + inputCorrect = false; + break; } - else + if( iiFace == faceIndices.size() ) { - m_meshsets_open.push_back( meshset ); + break; } } - void addOpenPolyhedron( const shared_ptr& poly_data ) - { - if( poly_data->getVertexCount() < 3 ) - { - return; - } - - bool correct = checkPolyhedronData(poly_data); - if( !correct ) - { - fixPolyhedronData(poly_data); -#ifdef _DEBUG - bool correct2 = checkPolyhedronData(poly_data); - if( !correct2 ) - { - std::cout << "incorrect idx"; - } -#endif - } + faceIndices = polyDataReversed; - shared_ptr > meshset( poly_data->createMesh( carve::input::opts() ) ); - m_meshsets_open.push_back( meshset ); - } + return inputCorrect; +} - bool addClosedPolyhedron( const shared_ptr& poly_data ) +typedef double mapPointEpsType; +class PolyInputCache3D +{ +public: + PolyInputCache3D( double epsMergePoints = -1 ) { - if( poly_data->getVertexCount() < 3 ) - { - return false; - } + m_mergePointsFactor = 1.0/epsMergePoints; - bool correct = checkPolyhedronData(poly_data); - if( !correct ) - { - fixPolyhedronData(poly_data); #ifdef _DEBUG - std::cout << "fixing polyhedron data" << std::endl; - bool correct2 = checkPolyhedronData(poly_data); - if( !correct2 ) - { - std::cout << "incorrect idx"; - } -#endif - //return false; - } - - bool dumpMeshes = false; - std::map mesh_input_options; - shared_ptr > meshset( poly_data->createMesh( mesh_input_options ) ); - if( meshset->isClosed() ) - { - m_meshsets.push_back( meshset ); - } - else + if( epsMergePoints > 0 && epsMergePoints < 10000000000000000 ) { - double eps = carve::CARVE_EPSILON; - MeshUtils::intersectOpenEdges(meshset, eps, dumpMeshes); - for( size_t i = 0; i < meshset->meshes.size(); ++i ) - { - meshset->meshes[i]->recalc(); - } - if( meshset->isClosed() ) - { - m_meshsets.push_back(meshset); - return true; - } - else + double epsCheck = EPS_DEFAULT; + double mergePointsFactor = 1.0/epsCheck; + + double x2 = -3.7725000000000155; + mapPointEpsType vertex_x2_key = round(x2 * mergePointsFactor); + double x2_restored = double(vertex_x2_key) / mergePointsFactor; + double x2_restored_check = double(vertex_x2_key) *epsCheck; + + if(false) { - MeshUtils::resolveOpenEdges(meshset, eps, dumpMeshes); + // check int casting + double mult = x2 * mergePointsFactor; + double vertex_x2_key = int( mult ); + int vertex_x2_key_int = int( mult ); + int vertex_x2_key_check = int( mult + 0.5); - if( meshset->isClosed() ) + double x2_restored1 = double(vertex_x2_key - 0.5)/mergePointsFactor; + double x2_restored2 = double(vertex_x2_key) / mergePointsFactor; + double x2_restored_check = double(vertex_x2_key) *epsCheck; + double dx2 = x2_restored1 - x2; + if( std::abs(dx2) > epsCheck ) { - m_meshsets.push_back(meshset); - return true; + std::cout << "int casting incorrect"; } - - m_meshsets_open.push_back(meshset); // still may be useful as open mesh - } - // Meshset is not closed - return false; - } - return true; - } - - void addPoint( const vec3& point ) - { - shared_ptr vertex_data; - if( m_vertex_points.size() > 0 ) - { - if( !m_vertex_points[0] ) - { - m_vertex_points[0] = shared_ptr( new carve::input::VertexData() ); } - vertex_data = m_vertex_points[0]; - } - else - { - vertex_data = shared_ptr( new carve::input::VertexData() ); - m_vertex_points.push_back( vertex_data ); - } - vertex_data->points.push_back( point ); - } + double x2_key = x2/epsMergePoints; + double x2_key_long = static_cast(x2_key); + double x2_key_long2 = round(x2_key); // should be -2515000000 with eps=1.50E-09 + long x2_key_long3 = round(x2_key); // should be -2515000000 + long x2_key_long4 = long(x2_key); // should be -2515000000 + int x2_key_int = round(x2_key); // should be -2515000000 + double x2_key_restored = x2_key*epsMergePoints; // should be -3.7725000000000155 - void applyTransformToItem( const shared_ptr& transform, bool matrix_identity_checked = false ) - { - if( !transform ) - { - return; - } - if( !matrix_identity_checked ) - { - if( GeomUtils::isMatrixIdentity( transform->m_matrix ) ) + double dx2 = x2_restored - x2; + if( std::abs(dx2) > epsMergePoints ) { - return; + std::cout << "check"; } } - applyTransformToItem( transform->m_matrix, true ); +#endif + + m_poly_data = shared_ptr( new carve::input::PolyhedronData() ); } - void applyTransformToItem( const carve::math::Matrix& mat, bool matrix_identity_checked = false ) + virtual size_t addPoint( const vec3& v ) { - if( !matrix_identity_checked ) - { - if( GeomUtils::isMatrixIdentity( mat ) ) - { - return; - } - } + double vertex_x = v.x; + double vertex_y = v.y; + double vertex_z = v.z; - for( size_t ii = 0; ii < m_vertex_points.size(); ++ii ) + if( m_mergePointsFactor > EPS_M16 ) { - shared_ptr& vertex_data = m_vertex_points[ii]; - for( size_t j = 0; jpoints.size(); ++j ) - { - vec3& point = vertex_data->points[j]; - point = mat*point; - } - } + mapPointEpsType vertex_x_key = round(vertex_x * m_mergePointsFactor); + mapPointEpsType vertex_y_key = round(vertex_y * m_mergePointsFactor); + mapPointEpsType vertex_z_key = round(vertex_z * m_mergePointsFactor); - for( size_t polyline_i = 0; polyline_i < m_polylines.size(); ++polyline_i ) - { - shared_ptr& polyline_data = m_polylines[polyline_i]; - for( size_t j = 0; jpoints.size(); ++j ) + // TODO: in case there are two points within eps, but dx/dy/dz > EPS_M16, try merging points to mid point +#ifdef _DEBUG + bool existingPointFound = false; + if( false ) { - vec3& point = polyline_data->points[j]; - point = mat*point; - } - } + double eps = 1.0 / m_mergePointsFactor; + for( auto it : m_existing_vertices_coords_merged ) + { + mapPointEpsType existing_key_x = it.first; + if( existing_key_x != vertex_x_key ) + { + continue; + } - //is negative if coordinate system changes handedness (for example as result of mirroring) - //in this case invert the meshes to not make them look inside out (only noticeable if using - //back face culling) - bool const invert_meshes = 0 > carve::geom::dotcross( - carve::geom::VECTOR(mat.m[0][0], mat.m[1][0], mat.m[2][0]), - carve::geom::VECTOR(mat.m[0][1], mat.m[1][1], mat.m[2][1]), - carve::geom::VECTOR(mat.m[0][2], mat.m[1][2], mat.m[2][2])); + double x_restored = existing_key_x / m_mergePointsFactor; + double dx = x_restored - vertex_x; + if( std::abs(dx) > eps ) + { + continue; + } - for( size_t i_meshsets = 0; i_meshsets < m_meshsets_open.size(); ++i_meshsets ) - { - shared_ptr >& item_meshset = m_meshsets_open[i_meshsets]; + for( auto itY : it.second ) + { + mapPointEpsType existing_key_y = itY.first; + if( existing_key_y != vertex_y_key ) + { + continue; + } - for( size_t i = 0; i < item_meshset->vertex_storage.size(); ++i ) - { - vec3& point = item_meshset->vertex_storage[i].v; - point = mat*point; - } - for( size_t i = 0; i < item_meshset->meshes.size(); ++i ) - { - item_meshset->meshes[i]->recalc(); - if(invert_meshes) - { - item_meshset->meshes[i]->invert(); + double y_restored = existing_key_y / m_mergePointsFactor; + double dy = y_restored - vertex_y; + if( std::abs(dy) > eps ) + { + continue; + } + + for( auto itZ : itY.second ) + { + mapPointEpsType existing_key_z = itZ.first; + if( existing_key_z != vertex_z_key ) + { + continue; + } + + double z_restored = existing_key_z / m_mergePointsFactor; + double dz = z_restored - vertex_z; + if( std::abs(dz) > eps ) + { + continue; + } + existingPointFound = true; + + } + } } } - } - - for( size_t i_meshsets = 0; i_meshsets < m_meshsets.size(); ++i_meshsets ) - { - shared_ptr >& item_meshset = m_meshsets[i_meshsets]; +#endif - for( size_t i = 0; i < item_meshset->vertex_storage.size(); ++i ) + std::map >& map_y_index = m_existing_vertices_coords_merged.insert( std::make_pair( vertex_x_key, std::map >() ) ).first->second; + std::map& map_z_index = map_y_index.insert( std::make_pair( vertex_y_key, std::map() ) ).first->second; + auto it_find_z = map_z_index.find( vertex_z_key ); + if( it_find_z != map_z_index.end() ) { - vec3& point = item_meshset->vertex_storage[i].v; - point = mat*point; + // vertex already exists in polyhedron. return its index + size_t vertex_index = it_find_z->second; +#ifdef _DEBUG + if( !existingPointFound ) + { + //std::cout << "!existingPointFound, check m_existing_vertices_coords_merged.insert" << std::endl; + } +#endif + return vertex_index; } - for( size_t i = 0; i < item_meshset->meshes.size(); ++i ) + else { - item_meshset->meshes[i]->recalc(); - if(invert_meshes) +#ifdef _DEBUG + if( existingPointFound ) { - item_meshset->meshes[i]->invert(); - //calcOrientation resets isNegative flag (usually) - item_meshset->meshes[i]->calcOrientation(); + //std::cout << "existingPointFound, check m_existing_vertices_coords_merged.insert" << std::endl; } +#endif + + // add point to polyhedron + size_t vertex_index = m_poly_data->addVertex( v ); + map_z_index[vertex_z_key] = vertex_index; + return vertex_index; } } - for( size_t text_i = 0; text_i < m_vec_text_literals.size(); ++text_i ) + // insert: returns a pair, with its member pair::first set to an iterator pointing to either the newly inserted element or to the element with an equivalent key in the map + std::map >& map_y_index = m_existing_vertices_coords.insert( std::make_pair( vertex_x, std::map >() ) ).first->second; + std::map& map_z_index = map_y_index.insert( std::make_pair( vertex_y, std::map() ) ).first->second; + auto it_find_z = map_z_index.find( vertex_z ); + if( it_find_z != map_z_index.end() ) { - shared_ptr& text_literals = m_vec_text_literals[text_i]; - text_literals->m_text_position = mat*text_literals->m_text_position; + // vertex already exists in polyhedron. return its index + size_t vertex_index = it_find_z->second; + return vertex_index; + } + else + { + // add point to polyhedron + size_t vertex_index = m_poly_data->addVertex( v ); + map_z_index[vertex_z] = vertex_index; + return vertex_index; } } - shared_ptr getItemShapeDataDeepCopy() +#ifdef _DEBUG + virtual int getPointIndex(const vec3& v) { - shared_ptr copy_item( new ItemShapeData() ); + double vertex_x = v.x; + double vertex_y = v.y; + double vertex_z = v.z; - for( size_t ii = 0; ii < m_vertex_points.size(); ++ii ) + if( m_mergePointsFactor > EPS_M16 ) { - shared_ptr& data = m_vertex_points[ii]; - copy_item->m_vertex_points.push_back( shared_ptr( new carve::input::VertexData( *( data.get() ) ) ) ); - } + mapPointEpsType vertex_x_key = round(vertex_x * m_mergePointsFactor); + mapPointEpsType vertex_y_key = round(vertex_y * m_mergePointsFactor); + mapPointEpsType vertex_z_key = round(vertex_z * m_mergePointsFactor); + + auto itFindX = m_existing_vertices_coords.find(vertex_x_key); + if( itFindX == m_existing_vertices_coords.end() ) + { + return -1; + } + + std::map >& map_y_index = itFindX->second; + + auto itFindY = map_y_index.find(vertex_y_key); + if( itFindY== map_y_index.end() ) + { + return -1; + } + + std::map& map_z_index = itFindY->second; + auto it_find_z = map_z_index.find(vertex_z_key); + if( it_find_z != map_z_index.end() ) + { + // vertex exists in polyhedron. return its index + size_t vertex_index = it_find_z->second; + return vertex_index; + } + return -1; - for( size_t ii = 0; ii < m_polylines.size(); ++ii ) - { - shared_ptr& polyline_data = m_polylines[ii]; - copy_item->m_polylines.push_back( shared_ptr( new carve::input::PolylineSetData( *( polyline_data.get() ) ) ) ); } - for( auto it_meshsets = m_meshsets_open.begin(); it_meshsets != m_meshsets_open.end(); ++it_meshsets ) + // insert: returns a pair, with its member pair::first set to an iterator pointing to either the newly inserted element or to the element with an equivalent key in the map + auto itFindX = m_existing_vertices_coords.find(vertex_x); + if( itFindX == m_existing_vertices_coords.end() ) { - shared_ptr >& item_meshset = ( *it_meshsets ); - copy_item->m_meshsets.push_back( shared_ptr >( item_meshset->clone() ) ); + return -1; } - for( auto it_meshsets = m_meshsets.begin(); it_meshsets != m_meshsets.end(); ++it_meshsets ) + std::map >& map_y_index = itFindX->second; + + auto itFindY = map_y_index.find(vertex_y); + if( itFindY== map_y_index.end() ) { - shared_ptr >& item_meshset = ( *it_meshsets ); - copy_item->m_meshsets.push_back( shared_ptr >( item_meshset->clone() ) ); + return -1; } - for( size_t ii = 0; ii < m_vec_text_literals.size(); ++ii ) + std::map& map_z_index = itFindY->second; + auto it_find_z = map_z_index.find(vertex_z); + if( it_find_z != map_z_index.end() ) { - shared_ptr& text_data = m_vec_text_literals[ii]; - - shared_ptr text_data_copy( new TextItemData() ); - text_data_copy->m_text = text_data->m_text.c_str(); - text_data_copy->m_text_position = text_data->m_text_position; - copy_item->m_vec_text_literals.push_back( text_data_copy ); + // vertex exists in polyhedron. return its index + size_t vertex_index = it_find_z->second; + return vertex_index; } - - std::copy( m_vec_item_appearances.begin(), m_vec_item_appearances.end(), std::back_inserter( copy_item->m_vec_item_appearances ) ); - - return copy_item; - } - - /** copies the content of other instance and adds it to own content */ - void addItemData( const shared_ptr& other ) - { - std::copy( other->m_vertex_points.begin(), other->m_vertex_points.end(), std::back_inserter( m_vertex_points ) ); - std::copy( other->m_polylines.begin(), other->m_polylines.end(), std::back_inserter( m_polylines ) ); - std::copy( other->m_meshsets.begin(), other->m_meshsets.end(), std::back_inserter( m_meshsets ) ); - std::copy( other->m_meshsets_open.begin(), other->m_meshsets_open.end(), std::back_inserter( m_meshsets_open ) ); - std::copy( other->m_vec_item_appearances.begin(), other->m_vec_item_appearances.end(), std::back_inserter( m_vec_item_appearances ) ); - std::copy( other->m_vec_text_literals.begin(), other->m_vec_text_literals.end(), std::back_inserter( m_vec_text_literals ) ); + return -1; } +#endif - const std::vector >& getVertexPoints() { return m_vertex_points; } - - void computeBoundingBox( carve::geom::aabb<3>& bbox ) const + bool checkFaceIndices() { - for( size_t ii = 0; ii < m_vertex_points.size(); ++ii ) + const std::vector& vec_points = m_poly_data->points; + const std::vector& face_indices = m_poly_data->faceIndices; + int face_count = 0; + for( size_t ii = 0; ii < face_indices.size(); ++ii ) { - const shared_ptr& vertex_data = m_vertex_points[ii]; - for( size_t j = 0; jpoints.size(); ++j ) + int num_vertices = face_indices[ii]; + for( int jj = 0; jj < num_vertices; ++jj ) { - const vec3& point = vertex_data->points[j]; - if( bbox.isEmpty() ) + ++ii; + if( ii >= face_indices.size() ) { - bbox = carve::geom::aabb<3>( point, carve::geom::VECTOR( 0, 0, 0 ) ); + return false; } - else + int vertex_index = face_indices[ii]; + if( vertex_index >= (int)vec_points.size() ) { - bbox.unionAABB( carve::geom::aabb<3>( point, carve::geom::VECTOR( 0, 0, 0 ) ) ); + return false; } } - } - for( size_t polyline_i = 0; polyline_i < m_polylines.size(); ++polyline_i ) - { - const shared_ptr& polyline_data = m_polylines[polyline_i]; - for( size_t j = 0; jpoints.size(); ++j ) - { - const vec3& point = polyline_data->points[j]; - if( bbox.isEmpty() ) - { - bbox = carve::geom::aabb<3>( point, carve::geom::VECTOR( 0, 0, 0 ) ); - } - else - { - bbox.unionAABB( carve::geom::aabb<3>( point, carve::geom::VECTOR( 0, 0, 0 ) ) ); - } - } + ++face_count; } - for( size_t i_meshsets = 0; i_meshsets < m_meshsets_open.size(); ++i_meshsets ) - { - const shared_ptr >& item_meshset = m_meshsets_open[i_meshsets]; - if (!item_meshset) - { - continue; - } - carve::geom::aabb<3> meshBBox = item_meshset->getAABB(); - if( bbox.isEmpty() ) - { - bbox = meshBBox; - } - else - { - if( !meshBBox.isEmpty() ) - { - bbox.unionAABB(meshBBox); - } - } - } - - for( size_t i_meshsets = 0; i_meshsets < m_meshsets.size(); ++i_meshsets ) + if( face_count != m_poly_data->faceCount ) { - const shared_ptr >& item_meshset = m_meshsets[i_meshsets]; - if (!item_meshset) - { - continue; - } - carve::geom::aabb<3> meshBBox = item_meshset->getAABB(); - if( bbox.isEmpty() ) - { - bbox = item_meshset->getAABB(); - } - else - { - if( !meshBBox.isEmpty() ) - { - bbox.unionAABB(meshBBox); - } - } + return false; } + return true; + } - for( size_t text_i = 0; text_i < m_vec_text_literals.size(); ++text_i ) - { - const shared_ptr& text_literals = m_vec_text_literals[text_i]; - const carve::math::Matrix& mat = text_literals->m_text_position; - vec3 text_pos = carve::geom::VECTOR( mat._41, mat._42, mat._43 ); - if( bbox.isEmpty() ) - { - bbox = carve::geom::aabb<3>( text_pos, carve::geom::VECTOR( 0, 0, 0 ) ); - } - else - { - bbox.unionAABB( carve::geom::aabb<3>( text_pos, carve::geom::VECTOR( 0, 0, 0 ) ) ); - } - } + void clearAllData() + { + m_poly_data->clearFaces(); + m_existing_vertices_coords.clear(); + m_existing_vertices_coords_merged.clear(); } + + double m_mergePointsFactor = -1; + shared_ptr m_poly_data; + std::map > > m_existing_vertices_coords; + std::map > > m_existing_vertices_coords_merged; }; -class RepresentationData + +class RepresentationData; +class ProductShapeData; + +/** +*\brief Class ItemShapeData: holds input data of one IFC geometric representation item. +* Parent-child relationship of ItemShapeData, RepresentationData, ProductShapeData: +* ... +* |-> ProductShapeData [1...n] +* |-> ProductShapeData [1...n] +* |-> RepresentationData [1...n] +* |-> ItemShapeData [1...n] +*/ +class ItemShapeData { public: - RepresentationData() {} - ~RepresentationData(){} + ItemShapeData(){} + ~ItemShapeData(){} - weak_ptr m_ifc_representation; - weak_ptr m_ifc_representation_context; - std::vector > m_vec_item_data; - std::vector > m_vec_representation_appearances; - std::string m_representation_identifier; - std::string m_representation_type; - weak_ptr m_parent_product; // Pointer to product object that this representation belongs to + std::vector > m_polylines; + std::vector > > m_meshsets; + std::vector > > m_meshsets_open; + std::vector > m_vec_item_appearances; + std::vector > m_vec_text_literals; + weak_ptr m_parent_representation; // Pointer to representation object that this item belongs to + shared_ptr m_ifc_item; - shared_ptr getRepresentationDataDeepCopy() +protected: + std::vector > m_vertex_points; + +public: + bool isEmpty() { - shared_ptr copy_representation( new RepresentationData() ); - copy_representation->m_ifc_representation = m_ifc_representation; - copy_representation->m_ifc_representation_context = m_ifc_representation_context; - for( size_t ii = 0; ii < m_vec_item_data.size(); ++ii ) - { - shared_ptr& item_data = m_vec_item_data[ii]; - copy_representation->m_vec_item_data.push_back( item_data->getItemShapeDataDeepCopy() ); - } - std::copy( m_vec_representation_appearances.begin(), m_vec_representation_appearances.end(), std::back_inserter( copy_representation->m_vec_representation_appearances ) ); - return copy_representation; + if( m_vertex_points.size() > 0 ) { return false; } + if( m_polylines.size() > 0 ) { return false; } + if( m_meshsets.size() > 0 ) { return false; } + if( m_meshsets_open.size() > 0 ) { return false; } + if( m_vec_item_appearances.size() > 0 ) { return false; } + if( m_vec_text_literals.size() > 0 ) { return false; } + + return true; } - void addChildItem( shared_ptr& item_data, shared_ptr& ptr_self ) + void addOpenOrClosedPolyhedron( const shared_ptr& poly_data ) { - if( ptr_self.get() != this ) + if( !poly_data ) { - std::cout << __FUNCTION__ << "ptr_self != this" << std::endl; + return; } - m_vec_item_data.push_back( item_data ); - item_data->m_parent_representation = ptr_self; - } - void appendRepresentationData( shared_ptr& other, shared_ptr& ptr_self ) - { - if( ptr_self.get() != this ) + // check if it is open or closed + if( poly_data->getVertexCount() < 3 ) { - std::cout << __FUNCTION__ << "ptr_self != this" << std::endl; + return; } - for( auto item_data : other->m_vec_item_data ) + + bool correct = checkPolyhedronData(poly_data); + if( !correct ) { - item_data->m_parent_representation = ptr_self; - m_vec_item_data.push_back( item_data ); + fixPolyhedronData(poly_data); +#ifdef _DEBUG + bool correct2 = checkPolyhedronData(poly_data); + if( !correct2 ) + { + std::cout << "incorrect idx"; + } +#endif + } + + shared_ptr > meshset( poly_data->createMesh( carve::input::opts() ) ); + if( meshset->isClosed() ) + { + m_meshsets.push_back( meshset ); + } + else + { + m_meshsets_open.push_back( meshset ); } - // TODO: Check if placement is same - std::copy( other->m_vec_representation_appearances.begin(), other->m_vec_representation_appearances.end(), std::back_inserter( m_vec_representation_appearances ) ); } - void addAppearance( shared_ptr& appearance ) + void addOpenPolyhedron( const shared_ptr& poly_data ) { - if( !appearance ) + if( poly_data->getVertexCount() < 3 ) { return; } - int append_id = appearance->m_step_style_id; - for( size_t ii = 0; ii < m_vec_representation_appearances.size(); ++ii ) + + bool correct = checkPolyhedronData(poly_data); + if( !correct ) { - shared_ptr& appearance = m_vec_representation_appearances[ii]; - if( appearance->m_step_style_id == append_id ) + fixPolyhedronData(poly_data); +#ifdef _DEBUG + bool correct2 = checkPolyhedronData(poly_data); + if( !correct2 ) { - return; + std::cout << "incorrect idx"; } +#endif } - m_vec_representation_appearances.push_back( appearance ); - } - void clearAppearanceData() - { - m_vec_representation_appearances.clear(); + shared_ptr > meshset( poly_data->createMesh( carve::input::opts() ) ); + m_meshsets_open.push_back( meshset ); } - void clearAll() + bool addClosedPolyhedron(const shared_ptr& poly_data) { - m_vec_representation_appearances.clear(); - m_ifc_representation.reset(); - m_ifc_representation_context.reset(); - m_vec_item_data.clear(); - m_representation_identifier = ""; - m_representation_type = ""; - } - - void applyTransformToRepresentation( const carve::math::Matrix& matrix, bool matrix_identity_checked = false ) - { - if( !matrix_identity_checked ) + if( poly_data->getVertexCount() < 3 ) { - if( GeomUtils::isMatrixIdentity( matrix ) ) + return false; + } + + bool correct = checkPolyhedronData(poly_data); + if( !correct ) + { + fixPolyhedronData(poly_data); +#ifdef _DEBUG + std::cout << "fixing polyhedron data" << std::endl; + bool correct2 = checkPolyhedronData(poly_data); + if( !correct2 ) { - return; + std::cout << "incorrect idx"; } +#endif + //return false; } - for( size_t i_item = 0; i_item < m_vec_item_data.size(); ++i_item ) + + bool dumpMeshes = false; + std::map mesh_input_options; + shared_ptr > meshset(poly_data->createMesh(mesh_input_options)); + if( meshset->isClosed() ) { - m_vec_item_data[i_item]->applyTransformToItem( matrix, matrix_identity_checked ); + m_meshsets.push_back(meshset); + return true; } - } - void computeBoundingBox( carve::geom::aabb<3>& bbox ) const - { - for( size_t ii = 0; ii < m_vec_item_data.size(); ++ii ) + if( meshset->meshes.size() > 1 ) { - const shared_ptr& item_data = m_vec_item_data[ii]; - item_data->computeBoundingBox( bbox ); - } - } -}; + // try to add faces of mesh[1] reversed into mesh[0] + carve::mesh::Mesh<3>* meshSmall = meshset->meshes[0]; + carve::mesh::Mesh<3>* meshBig = meshset->meshes[1]; + if( meshSmall->faces.size() > meshBig->faces.size() ) + { + std::swap(meshSmall, meshBig); + } + PolyInputCache3D polyhedronSmall; + MeshUtils::polyhedronFromMesh(meshSmall, polyhedronSmall); -class ProductShapeData -{ -public: - std::string m_entity_guid; - weak_ptr m_ifc_object_definition; - weak_ptr m_object_placement; - std::vector > m_vec_representations; - bool m_added_to_spatial_structure = false; - weak_ptr m_parent; - std::vector > m_vec_transforms; - std::vector > m_vec_children; - std::vector > m_vec_product_appearances; + PolyInputCache3D polyhedronBig; + MeshUtils::polyhedronFromMesh(meshBig, polyhedronBig); + MeshUtils::addFacesReversed(polyhedronSmall, polyhedronBig); + meshset = shared_ptr >(polyhedronBig.m_poly_data->createMesh(mesh_input_options)); + if( meshset->isClosed() ) + { + m_meshsets.push_back(meshset); + return true; + } + } - ProductShapeData() {} - ProductShapeData( std::string entity_guid ) : m_entity_guid(entity_guid) { } - - const std::vector >& getChildren() { return m_vec_children; } - shared_ptr getDeepCopy() - { - shared_ptr copy_data( new ProductShapeData(m_entity_guid) ); - for( size_t item_i = 0; item_i < m_vec_representations.size(); ++item_i ) + // try to fix winding order + reverseFacesInPolyhedronData(poly_data); + meshset = shared_ptr >(poly_data->createMesh(mesh_input_options)); + if( meshset->isClosed() ) { - shared_ptr& representation_data = m_vec_representations[item_i]; - shared_ptr representation_data_copy = representation_data->getRepresentationDataDeepCopy(); - copy_data->m_vec_representations.push_back( representation_data_copy ); + m_meshsets.push_back(meshset); + return true; } - std::copy( m_vec_product_appearances.begin(), m_vec_product_appearances.end(), std::back_inserter( copy_data->m_vec_product_appearances ) ); - for( auto child_product_data : m_vec_children ) - { - shared_ptr child_copy = child_product_data->getDeepCopy(); - copy_data->m_vec_children.push_back( child_copy ); - } - copy_data->m_parent = m_parent; + double eps = carve::CARVE_EPSILON; + MeshUtils::intersectOpenEdges(meshset, eps, dumpMeshes); - for( auto transform : m_vec_transforms ) + for( size_t i = 0; i < meshset->meshes.size(); ++i ) { - if( transform ) - { - shared_ptr transform_deep_copy( new TransformData( transform->m_matrix, transform->m_placement_entity, transform->m_placement_tag ) ); - copy_data->m_vec_transforms.push_back( transform_deep_copy ); - } + meshset->meshes[i]->recalc(); } - - return copy_data; - } - - void addAppearance( shared_ptr& appearance ) - { - if( !appearance ) + if( meshset->isClosed() ) { - return; + m_meshsets.push_back(meshset); + return true; } - int append_id = appearance->m_step_style_id; - for( size_t ii = 0; ii < m_vec_product_appearances.size(); ++ii ) + else { - shared_ptr& appearance = m_vec_product_appearances[ii]; - if( appearance->m_step_style_id == append_id ) + MeshUtils::resolveOpenEdges(meshset, eps, dumpMeshes); + + if( meshset->isClosed() ) { - return; + m_meshsets.push_back(meshset); + return true; } - } - m_vec_product_appearances.push_back( appearance ); - } - void clearAppearanceData() - { - m_vec_product_appearances.clear(); + m_meshsets_open.push_back(meshset); // still may be useful as open mesh + } + // Meshset is not closed + return false; } - void clearAll() - { - m_vec_product_appearances.clear(); - - m_ifc_object_definition.reset(); - m_object_placement.reset(); - m_vec_children.clear(); - m_vec_representations.clear(); - m_added_to_spatial_structure = false; - } - - bool isContainedInParentsList( shared_ptr& product_data_check ) + void addPoint( const vec3& point ) { - if( !m_parent.expired() ) + shared_ptr vertex_data; + if( m_vertex_points.size() > 0 ) { - shared_ptr product_data_parent( m_parent ); - if( product_data_parent == product_data_check ) + if( !m_vertex_points[0] ) { - return true; + m_vertex_points[0] = shared_ptr( new carve::input::VertexData() ); } - product_data_parent->isContainedInParentsList( product_data_check ); + vertex_data = m_vertex_points[0]; } - return false; + else + { + vertex_data = shared_ptr( new carve::input::VertexData() ); + m_vertex_points.push_back( vertex_data ); + } + + vertex_data->points.push_back( point ); } - void addChildProduct( shared_ptr& add_child, shared_ptr& ptr_self ) + void applyTransformToItem( const shared_ptr& transform, bool matrix_identity_checked = false ) { - if( ptr_self.get() != this ) - { - std::cout << __FUNCTION__ << ": ptr_self.get() != this" << std::endl; - } - if( isContainedInParentsList( add_child ) ) + if( !transform ) { - std::cout << __FUNCTION__ << ": isContainedInParentsList" << std::endl; return; } - - for( size_t ii = 0; ii < m_vec_children.size(); ++ii ) + if( !matrix_identity_checked ) { - const shared_ptr& existing_child = m_vec_children[ii]; - if( existing_child == add_child ) + if( GeomUtils::isMatrixIdentity( transform->m_matrix ) ) { -#ifdef _DEBUG - if( existing_child->m_entity_guid.compare( add_child->m_entity_guid ) == 0 ) - { - std::cout << __FUNCTION__ << ": child already added, tag: " << add_child->m_entity_guid << std::endl; - } - else - { - std::cout << __FUNCTION__ << ": tag mismatch: " << add_child->m_entity_guid << " != " << existing_child->m_entity_guid << std::endl; - } -#endif return; } } - - m_vec_children.push_back( add_child ); - add_child->m_parent = ptr_self; + applyTransformToItem( transform->m_matrix, true ); } - /** - * \brief method getTransform: Computes the transformation matrix, that puts the geometry of this product into global coordinates - * All transformation matrices of all parent coordinate systems are multiplied. - */ - carve::math::Matrix getTransform() + void applyTransformToItem( const carve::math::Matrix& mat, bool matrix_identity_checked = false ) { - carve::math::Matrix transform_matrix; - if( m_vec_transforms.size() > 0 ) + if( !matrix_identity_checked ) { - for( shared_ptr& transform : m_vec_transforms ) + if( GeomUtils::isMatrixIdentity( mat ) ) { - if( transform ) - { - transform_matrix = transform->m_matrix*transform_matrix; - } + return; } } - return transform_matrix; - } - carve::math::Matrix getRelativeTransform(const shared_ptr& other) - { - carve::math::Matrix transform_matrix; - if (!other) - { - return transform_matrix; - } - - if (m_vec_transforms.size() > 0) + for( size_t ii = 0; ii < m_vertex_points.size(); ++ii ) { - std::vector > diff_transforms; - auto it_self = m_vec_transforms.rbegin(); - auto it_other = other->m_vec_transforms.rbegin(); - for (size_t ii_self = 0; ii_self < m_vec_transforms.size(); ++ii_self) + shared_ptr& vertex_data = m_vertex_points[ii]; + for( size_t j = 0; jpoints.size(); ++j ) { - if (it_self == m_vec_transforms.rend()) - { - break; - } - - shared_ptr& transform_self = *it_self; - - if (it_other != other->m_vec_transforms.rend()) - { - shared_ptr& transform_other = *it_other; - - if (transform_self->m_placement_tag >= 0 && transform_self->m_placement_tag == transform_other->m_placement_tag) - { - // skip matrices that are the same at both products, to avoid unnecessary multiplications and numerical inaccuracies - ++it_self; - ++it_other; - continue; - } - } - - if (transform_self) - { - transform_matrix = transform_self->m_matrix*transform_matrix; - } - ++it_self; + vec3& point = vertex_data->points[j]; + point = mat*point; } } - return transform_matrix; - } - void addTransform( shared_ptr& transform_data ) - { - if( !transform_data ) + for( size_t polyline_i = 0; polyline_i < m_polylines.size(); ++polyline_i ) { - return; + shared_ptr& polyline_data = m_polylines[polyline_i]; + for( size_t j = 0; jpoints.size(); ++j ) + { + vec3& point = polyline_data->points[j]; + point = mat*point; + } } - for( auto existing_transform : m_vec_transforms ) + //is negative if coordinate system changes handedness (for example as result of mirroring) + //in this case invert the meshes to not make them look inside out (only noticeable if using + //back face culling) + bool const invert_meshes = 0 > carve::geom::dotcross( + carve::geom::VECTOR(mat.m[0][0], mat.m[1][0], mat.m[2][0]), + carve::geom::VECTOR(mat.m[0][1], mat.m[1][1], mat.m[2][1]), + carve::geom::VECTOR(mat.m[0][2], mat.m[1][2], mat.m[2][2])); + + for( size_t i_meshsets = 0; i_meshsets < m_meshsets_open.size(); ++i_meshsets ) { - if( existing_transform ) + shared_ptr >& item_meshset = m_meshsets_open[i_meshsets]; + + for( size_t i = 0; i < item_meshset->vertex_storage.size(); ++i ) { - if( transform_data->isSameTransform( existing_transform ) ) + vec3& point = item_meshset->vertex_storage[i].v; + point = mat*point; + } + for( size_t i = 0; i < item_meshset->meshes.size(); ++i ) + { + item_meshset->meshes[i]->recalc(); + if(invert_meshes) { - return; + item_meshset->meshes[i]->invert(); } } } - m_vec_transforms.insert( m_vec_transforms.begin(), transform_data ); - } - void applyTransformToProduct( const carve::math::Matrix& matrix, bool matrix_identity_checked = false ) - { - if( !matrix_identity_checked ) + for( size_t i_meshsets = 0; i_meshsets < m_meshsets.size(); ++i_meshsets ) { - if( GeomUtils::isMatrixIdentity( matrix ) ) + shared_ptr >& item_meshset = m_meshsets[i_meshsets]; + + for( size_t i = 0; i < item_meshset->vertex_storage.size(); ++i ) { - return; + vec3& point = item_meshset->vertex_storage[i].v; + point = mat*point; + } + for( size_t i = 0; i < item_meshset->meshes.size(); ++i ) + { + item_meshset->meshes[i]->recalc(); + if(invert_meshes) + { + item_meshset->meshes[i]->invert(); + //calcOrientation resets isNegative flag (usually) + item_meshset->meshes[i]->calcOrientation(); + } } } - for( size_t i_item = 0; i_item < m_vec_representations.size(); ++i_item ) - { - m_vec_representations[i_item]->applyTransformToRepresentation( matrix, true ); - } - for( auto child_product_data : m_vec_children ) + + for( size_t text_i = 0; text_i < m_vec_text_literals.size(); ++text_i ) { - child_product_data->applyTransformToProduct( matrix, true ); + shared_ptr& text_literals = m_vec_text_literals[text_i]; + text_literals->m_text_position = mat*text_literals->m_text_position; } } - const std::vector >& getAppearances() { return m_vec_product_appearances; } - bool isEmpty( bool check_also_children ) const + shared_ptr getItemShapeDataDeepCopy() { - if( m_vec_representations.size() > 0 ) + shared_ptr copy_item( new ItemShapeData() ); + + for( size_t ii = 0; ii < m_vertex_points.size(); ++ii ) { - return false; + shared_ptr& data = m_vertex_points[ii]; + copy_item->m_vertex_points.push_back( shared_ptr( new carve::input::VertexData( *( data.get() ) ) ) ); } - if( m_vec_product_appearances.size() > 0 ) + + for( size_t ii = 0; ii < m_polylines.size(); ++ii ) { - return false; + shared_ptr& polyline_data = m_polylines[ii]; + copy_item->m_polylines.push_back( shared_ptr( new carve::input::PolylineSetData( *( polyline_data.get() ) ) ) ); } - if( check_also_children ) + + for( auto it_meshsets = m_meshsets_open.begin(); it_meshsets != m_meshsets_open.end(); ++it_meshsets ) { - if( m_vec_product_appearances.size() > 0 ) + shared_ptr >& item_meshset = ( *it_meshsets ); + copy_item->m_meshsets.push_back( shared_ptr >( item_meshset->clone() ) ); + } + + for( auto it_meshsets = m_meshsets.begin(); it_meshsets != m_meshsets.end(); ++it_meshsets ) + { + shared_ptr >& item_meshset = ( *it_meshsets ); + copy_item->m_meshsets.push_back( shared_ptr >( item_meshset->clone() ) ); + } + + for( size_t ii = 0; ii < m_vec_text_literals.size(); ++ii ) + { + shared_ptr& text_data = m_vec_text_literals[ii]; + + shared_ptr text_data_copy( new TextItemData() ); + text_data_copy->m_text = text_data->m_text.c_str(); + text_data_copy->m_text_position = text_data->m_text_position; + copy_item->m_vec_text_literals.push_back( text_data_copy ); + } + + std::copy( m_vec_item_appearances.begin(), m_vec_item_appearances.end(), std::back_inserter( copy_item->m_vec_item_appearances ) ); + + return copy_item; + } + + /** copies the content of other instance and adds it to own content */ + void addItemData( const shared_ptr& other ) + { + std::copy( other->m_vertex_points.begin(), other->m_vertex_points.end(), std::back_inserter( m_vertex_points ) ); + std::copy( other->m_polylines.begin(), other->m_polylines.end(), std::back_inserter( m_polylines ) ); + std::copy( other->m_meshsets.begin(), other->m_meshsets.end(), std::back_inserter( m_meshsets ) ); + std::copy( other->m_meshsets_open.begin(), other->m_meshsets_open.end(), std::back_inserter( m_meshsets_open ) ); + std::copy( other->m_vec_item_appearances.begin(), other->m_vec_item_appearances.end(), std::back_inserter( m_vec_item_appearances ) ); + std::copy( other->m_vec_text_literals.begin(), other->m_vec_text_literals.end(), std::back_inserter( m_vec_text_literals ) ); + } + + const std::vector >& getVertexPoints() { return m_vertex_points; } + + void computeBoundingBox( carve::geom::aabb<3>& bbox ) const + { + for( size_t ii = 0; ii < m_vertex_points.size(); ++ii ) + { + const shared_ptr& vertex_data = m_vertex_points[ii]; + for( size_t j = 0; jpoints.size(); ++j ) { - for( size_t ii = 0; ii < m_vec_children.size(); ++ii ) + const vec3& point = vertex_data->points[j]; + if( bbox.isEmpty() ) { - const shared_ptr& child = m_vec_children[ii]; - bool child_empty = child->isEmpty( check_also_children ); - if( !child_empty ) - { - return false; - } + bbox = carve::geom::aabb<3>( point, carve::geom::VECTOR( 0, 0, 0 ) ); + } + else + { + bbox.unionAABB( carve::geom::aabb<3>( point, carve::geom::VECTOR( 0, 0, 0 ) ) ); } } } - return true; - } - bool hasGeometricRepresentation( bool includeChildren = true ) const - { - if( includeChildren ) + for( size_t polyline_i = 0; polyline_i < m_polylines.size(); ++polyline_i ) { - for( size_t ii = 0; ii < m_vec_children.size(); ++ii ) + const shared_ptr& polyline_data = m_polylines[polyline_i]; + for( size_t j = 0; jpoints.size(); ++j ) { - const shared_ptr& child = m_vec_children[ii]; - bool childHasGeom = child->hasGeometricRepresentation(includeChildren); - if( childHasGeom ) + const vec3& point = polyline_data->points[j]; + if( bbox.isEmpty() ) { - return true; + bbox = carve::geom::aabb<3>( point, carve::geom::VECTOR( 0, 0, 0 ) ); + } + else + { + bbox.unionAABB( carve::geom::aabb<3>( point, carve::geom::VECTOR( 0, 0, 0 ) ) ); } } } - if( m_vec_representations.size() > 0 ) + for( size_t i_meshsets = 0; i_meshsets < m_meshsets_open.size(); ++i_meshsets ) { - // TODO: check if further check for mesh bounding box is necessary - return true; + const shared_ptr >& item_meshset = m_meshsets_open[i_meshsets]; + if (!item_meshset) + { + continue; + } + carve::geom::aabb<3> meshBBox = item_meshset->getAABB(); + if( bbox.isEmpty() ) + { + bbox = meshBBox; + } + else + { + if( !meshBBox.isEmpty() ) + { + bbox.unionAABB(meshBBox); + } + } } - return false; - } - //void computeBoundingBoxLocalCoords( carve::geom::aabb<3>& bbox, bool include_children ) const - //{ - // for( size_t ii = 0; ii < m_vec_representations.size(); ++ii ) - // { - // const shared_ptr& representation_data = m_vec_representations[ii]; - // representation_data->computeBoundingBox( bbox ); - // } + for( size_t i_meshsets = 0; i_meshsets < m_meshsets.size(); ++i_meshsets ) + { + const shared_ptr >& item_meshset = m_meshsets[i_meshsets]; + if (!item_meshset) + { + continue; + } + carve::geom::aabb<3> meshBBox = item_meshset->getAABB(); + if( bbox.isEmpty() ) + { + bbox = item_meshset->getAABB(); + } + else + { + if( !meshBBox.isEmpty() ) + { + bbox.unionAABB(meshBBox); + } + } + } - // if( include_children ) - // { - // for( auto child_product_data : m_vec_children ) - // { - // child_product_data->computeBoundingBoxLocalCoords( bbox, include_children ); - // } - // } - //} + for( size_t text_i = 0; text_i < m_vec_text_literals.size(); ++text_i ) + { + const shared_ptr& text_literals = m_vec_text_literals[text_i]; + const carve::math::Matrix& mat = text_literals->m_text_position; + vec3 text_pos = carve::geom::VECTOR( mat._41, mat._42, mat._43 ); + if( bbox.isEmpty() ) + { + bbox = carve::geom::aabb<3>( text_pos, carve::geom::VECTOR( 0, 0, 0 ) ); + } + else + { + bbox.unionAABB( carve::geom::aabb<3>( text_pos, carve::geom::VECTOR( 0, 0, 0 ) ) ); + } + } + } }; - -typedef double mapPointEpsType; -class PolyInputCache3D +class RepresentationData { public: - PolyInputCache3D( double epsMergePoints = -1 ) - { - m_mergePointsFactor = 1.0/epsMergePoints; + RepresentationData() {} + ~RepresentationData(){} -#ifdef _DEBUG - if( epsMergePoints > 0 && epsMergePoints < 10000000000000000 ) + weak_ptr m_ifc_representation; + weak_ptr m_ifc_representation_context; + std::vector > m_vec_item_data; + std::vector > m_vec_representation_appearances; + std::string m_representation_identifier; + std::string m_representation_type; + weak_ptr m_parent_product; // Pointer to product object that this representation belongs to + + shared_ptr getRepresentationDataDeepCopy() + { + shared_ptr copy_representation( new RepresentationData() ); + copy_representation->m_ifc_representation = m_ifc_representation; + copy_representation->m_ifc_representation_context = m_ifc_representation_context; + for( size_t ii = 0; ii < m_vec_item_data.size(); ++ii ) { + shared_ptr& item_data = m_vec_item_data[ii]; + copy_representation->m_vec_item_data.push_back( item_data->getItemShapeDataDeepCopy() ); + } + std::copy( m_vec_representation_appearances.begin(), m_vec_representation_appearances.end(), std::back_inserter( copy_representation->m_vec_representation_appearances ) ); + return copy_representation; + } - double epsCheck = EPS_DEFAULT; - double mergePointsFactor = 1.0/epsCheck; + void addChildItem( shared_ptr& item_data, shared_ptr& ptr_self ) + { + if( ptr_self.get() != this ) + { + std::cout << __FUNCTION__ << "ptr_self != this" << std::endl; + } + m_vec_item_data.push_back( item_data ); + item_data->m_parent_representation = ptr_self; + } - double x2 = -3.7725000000000155; - mapPointEpsType vertex_x2_key = round(x2 * mergePointsFactor); - double x2_restored = double(vertex_x2_key) / mergePointsFactor; - double x2_restored_check = double(vertex_x2_key) *epsCheck; + void appendRepresentationData( shared_ptr& other, shared_ptr& ptr_self ) + { + if( ptr_self.get() != this ) + { + std::cout << __FUNCTION__ << "ptr_self != this" << std::endl; + } + for( auto item_data : other->m_vec_item_data ) + { + item_data->m_parent_representation = ptr_self; + m_vec_item_data.push_back( item_data ); + } + // TODO: Check if placement is same + std::copy( other->m_vec_representation_appearances.begin(), other->m_vec_representation_appearances.end(), std::back_inserter( m_vec_representation_appearances ) ); + } - if(false) + void addAppearance( shared_ptr& appearance ) + { + if( !appearance ) + { + return; + } + int append_id = appearance->m_step_style_id; + for( size_t ii = 0; ii < m_vec_representation_appearances.size(); ++ii ) + { + shared_ptr& appearance = m_vec_representation_appearances[ii]; + if( appearance->m_step_style_id == append_id ) { - // check int casting - double mult = x2 * mergePointsFactor; - double vertex_x2_key = int( mult ); - int vertex_x2_key_int = int( mult ); - int vertex_x2_key_check = int( mult + 0.5); - - double x2_restored1 = double(vertex_x2_key - 0.5)/mergePointsFactor; - double x2_restored2 = double(vertex_x2_key) / mergePointsFactor; - double x2_restored_check = double(vertex_x2_key) *epsCheck; - double dx2 = x2_restored1 - x2; - if( std::abs(dx2) > epsCheck ) - { - std::cout << "int casting incorrect"; - } + return; } + } + m_vec_representation_appearances.push_back( appearance ); + } - double x2_key = x2/epsMergePoints; - double x2_key_long = static_cast(x2_key); - double x2_key_long2 = round(x2_key); // should be -2515000000 with eps=1.50E-09 - long x2_key_long3 = round(x2_key); // should be -2515000000 - long x2_key_long4 = long(x2_key); // should be -2515000000 - int x2_key_int = round(x2_key); // should be -2515000000 - double x2_key_restored = x2_key*epsMergePoints; // should be -3.7725000000000155 + void clearAppearanceData() + { + m_vec_representation_appearances.clear(); + } - double dx2 = x2_restored - x2; - if( std::abs(dx2) > epsMergePoints ) + void clearAll() + { + m_vec_representation_appearances.clear(); + m_ifc_representation.reset(); + m_ifc_representation_context.reset(); + m_vec_item_data.clear(); + m_representation_identifier = ""; + m_representation_type = ""; + } + + void applyTransformToRepresentation( const carve::math::Matrix& matrix, bool matrix_identity_checked = false ) + { + if( !matrix_identity_checked ) + { + if( GeomUtils::isMatrixIdentity( matrix ) ) { - std::cout << "check"; + return; } } -#endif + for( size_t i_item = 0; i_item < m_vec_item_data.size(); ++i_item ) + { + m_vec_item_data[i_item]->applyTransformToItem( matrix, matrix_identity_checked ); + } + } - m_poly_data = shared_ptr( new carve::input::PolyhedronData() ); + void computeBoundingBox( carve::geom::aabb<3>& bbox ) const + { + for( size_t ii = 0; ii < m_vec_item_data.size(); ++ii ) + { + const shared_ptr& item_data = m_vec_item_data[ii]; + item_data->computeBoundingBox( bbox ); + } } +}; - virtual size_t addPoint( const vec3& v ) +class ProductShapeData +{ +public: + std::string m_entity_guid; + weak_ptr m_ifc_object_definition; + weak_ptr m_object_placement; + std::vector > m_vec_representations; + bool m_added_to_spatial_structure = false; + weak_ptr m_parent; + std::vector > m_vec_transforms; + std::vector > m_vec_children; + std::vector > m_vec_product_appearances; + + ProductShapeData() {} + ProductShapeData( std::string entity_guid ) : m_entity_guid(entity_guid) { } + + const std::vector >& getChildren() { return m_vec_children; } + shared_ptr getDeepCopy() { - double vertex_x = v.x; - double vertex_y = v.y; - double vertex_z = v.z; + shared_ptr copy_data( new ProductShapeData(m_entity_guid) ); + for( size_t item_i = 0; item_i < m_vec_representations.size(); ++item_i ) + { + shared_ptr& representation_data = m_vec_representations[item_i]; + shared_ptr representation_data_copy = representation_data->getRepresentationDataDeepCopy(); + copy_data->m_vec_representations.push_back( representation_data_copy ); + } - if( m_mergePointsFactor > EPS_M16 ) + std::copy( m_vec_product_appearances.begin(), m_vec_product_appearances.end(), std::back_inserter( copy_data->m_vec_product_appearances ) ); + for( auto child_product_data : m_vec_children ) { - mapPointEpsType vertex_x_key = round(vertex_x * m_mergePointsFactor); - mapPointEpsType vertex_y_key = round(vertex_y * m_mergePointsFactor); - mapPointEpsType vertex_z_key = round(vertex_z * m_mergePointsFactor); + shared_ptr child_copy = child_product_data->getDeepCopy(); + copy_data->m_vec_children.push_back( child_copy ); + } + copy_data->m_parent = m_parent; - // TODO: in case there are two points within eps, but dx/dy/dz > EPS_M16, try merging points to mid point -#ifdef _DEBUG - bool existingPointFound = false; - if( false ) + for( auto transform : m_vec_transforms ) + { + if( transform ) { - double eps = 1.0 / m_mergePointsFactor; - for( auto it : m_existing_vertices_coords_merged ) - { - mapPointEpsType existing_key_x = it.first; - if( existing_key_x != vertex_x_key ) - { - continue; - } - - double x_restored = existing_key_x / m_mergePointsFactor; - double dx = x_restored - vertex_x; - if( std::abs(dx) > eps ) - { - continue; - } + shared_ptr transform_deep_copy( new TransformData( transform->m_matrix, transform->m_placement_entity, transform->m_placement_tag ) ); + copy_data->m_vec_transforms.push_back( transform_deep_copy ); + } + } - for( auto itY : it.second ) - { - mapPointEpsType existing_key_y = itY.first; - if( existing_key_y != vertex_y_key ) - { - continue; - } + return copy_data; + } - double y_restored = existing_key_y / m_mergePointsFactor; - double dy = y_restored - vertex_y; - if( std::abs(dy) > eps ) - { - continue; - } + void addAppearance( shared_ptr& appearance ) + { + if( !appearance ) + { + return; + } + int append_id = appearance->m_step_style_id; + for( size_t ii = 0; ii < m_vec_product_appearances.size(); ++ii ) + { + shared_ptr& appearance = m_vec_product_appearances[ii]; + if( appearance->m_step_style_id == append_id ) + { + return; + } + } + m_vec_product_appearances.push_back( appearance ); + } - for( auto itZ : itY.second ) - { - mapPointEpsType existing_key_z = itZ.first; - if( existing_key_z != vertex_z_key ) - { - continue; - } + void clearAppearanceData() + { + m_vec_product_appearances.clear(); + } - double z_restored = existing_key_z / m_mergePointsFactor; - double dz = z_restored - vertex_z; - if( std::abs(dz) > eps ) - { - continue; - } - existingPointFound = true; + void clearAll() + { + m_vec_product_appearances.clear(); - } - } - } + m_ifc_object_definition.reset(); + m_object_placement.reset(); + m_vec_children.clear(); + m_vec_representations.clear(); + m_added_to_spatial_structure = false; + } + + bool isContainedInParentsList( shared_ptr& product_data_check ) + { + if( !m_parent.expired() ) + { + shared_ptr product_data_parent( m_parent ); + if( product_data_parent == product_data_check ) + { + return true; } -#endif + product_data_parent->isContainedInParentsList( product_data_check ); + } + return false; + } - std::map >& map_y_index = m_existing_vertices_coords_merged.insert( std::make_pair( vertex_x_key, std::map >() ) ).first->second; - std::map& map_z_index = map_y_index.insert( std::make_pair( vertex_y_key, std::map() ) ).first->second; - auto it_find_z = map_z_index.find( vertex_z_key ); - if( it_find_z != map_z_index.end() ) + void addChildProduct( shared_ptr& add_child, shared_ptr& ptr_self ) + { + if( ptr_self.get() != this ) + { + std::cout << __FUNCTION__ << ": ptr_self.get() != this" << std::endl; + } + if( isContainedInParentsList( add_child ) ) + { + std::cout << __FUNCTION__ << ": isContainedInParentsList" << std::endl; + return; + } + + for( size_t ii = 0; ii < m_vec_children.size(); ++ii ) + { + const shared_ptr& existing_child = m_vec_children[ii]; + if( existing_child == add_child ) { - // vertex already exists in polyhedron. return its index - size_t vertex_index = it_find_z->second; #ifdef _DEBUG - if( !existingPointFound ) + if( existing_child->m_entity_guid.compare( add_child->m_entity_guid ) == 0 ) { - //std::cout << "!existingPointFound, check m_existing_vertices_coords_merged.insert" << std::endl; + std::cout << __FUNCTION__ << ": child already added, tag: " << add_child->m_entity_guid << std::endl; + } + else + { + std::cout << __FUNCTION__ << ": tag mismatch: " << add_child->m_entity_guid << " != " << existing_child->m_entity_guid << std::endl; } #endif - return vertex_index; + return; } - else + } + + m_vec_children.push_back( add_child ); + add_child->m_parent = ptr_self; + } + + /** + * \brief method getTransform: Computes the transformation matrix, that puts the geometry of this product into global coordinates + * All transformation matrices of all parent coordinate systems are multiplied. + */ + carve::math::Matrix getTransform() + { + carve::math::Matrix transform_matrix; + if( m_vec_transforms.size() > 0 ) + { + for( shared_ptr& transform : m_vec_transforms ) { -#ifdef _DEBUG - if( existingPointFound ) + if( transform ) { - //std::cout << "existingPointFound, check m_existing_vertices_coords_merged.insert" << std::endl; + transform_matrix = transform->m_matrix*transform_matrix; } -#endif - - // add point to polyhedron - size_t vertex_index = m_poly_data->addVertex( v ); - map_z_index[vertex_z_key] = vertex_index; - return vertex_index; } } + return transform_matrix; + } - // insert: returns a pair, with its member pair::first set to an iterator pointing to either the newly inserted element or to the element with an equivalent key in the map - std::map >& map_y_index = m_existing_vertices_coords.insert( std::make_pair( vertex_x, std::map >() ) ).first->second; - std::map& map_z_index = map_y_index.insert( std::make_pair( vertex_y, std::map() ) ).first->second; - auto it_find_z = map_z_index.find( vertex_z ); - if( it_find_z != map_z_index.end() ) + carve::math::Matrix getRelativeTransform(const shared_ptr& other) + { + carve::math::Matrix transform_matrix; + if (!other) { - // vertex already exists in polyhedron. return its index - size_t vertex_index = it_find_z->second; - return vertex_index; + return transform_matrix; } - else + + if (m_vec_transforms.size() > 0) { - // add point to polyhedron - size_t vertex_index = m_poly_data->addVertex( v ); - map_z_index[vertex_z] = vertex_index; - return vertex_index; + std::vector > diff_transforms; + auto it_self = m_vec_transforms.rbegin(); + auto it_other = other->m_vec_transforms.rbegin(); + for (size_t ii_self = 0; ii_self < m_vec_transforms.size(); ++ii_self) + { + if (it_self == m_vec_transforms.rend()) + { + break; + } + + shared_ptr& transform_self = *it_self; + + if (it_other != other->m_vec_transforms.rend()) + { + shared_ptr& transform_other = *it_other; + + if (transform_self->m_placement_tag >= 0 && transform_self->m_placement_tag == transform_other->m_placement_tag) + { + // skip matrices that are the same at both products, to avoid unnecessary multiplications and numerical inaccuracies + ++it_self; + ++it_other; + continue; + } + } + + if (transform_self) + { + transform_matrix = transform_self->m_matrix*transform_matrix; + } + ++it_self; + } } + return transform_matrix; } -#ifdef _DEBUG - virtual int getPointIndex(const vec3& v) + void addTransform( shared_ptr& transform_data ) { - double vertex_x = v.x; - double vertex_y = v.y; - double vertex_z = v.z; - - if( m_mergePointsFactor > EPS_M16 ) + if( !transform_data ) { - mapPointEpsType vertex_x_key = round(vertex_x * m_mergePointsFactor); - mapPointEpsType vertex_y_key = round(vertex_y * m_mergePointsFactor); - mapPointEpsType vertex_z_key = round(vertex_z * m_mergePointsFactor); - - auto itFindX = m_existing_vertices_coords.find(vertex_x_key); - if( itFindX == m_existing_vertices_coords.end() ) - { - return -1; - } - - std::map >& map_y_index = itFindX->second; + return; + } - auto itFindY = map_y_index.find(vertex_y_key); - if( itFindY== map_y_index.end() ) + for( auto existing_transform : m_vec_transforms ) + { + if( existing_transform ) { - return -1; + if( transform_data->isSameTransform( existing_transform ) ) + { + return; + } } + } + m_vec_transforms.insert( m_vec_transforms.begin(), transform_data ); + } - std::map& map_z_index = itFindY->second; - auto it_find_z = map_z_index.find(vertex_z_key); - if( it_find_z != map_z_index.end() ) + void applyTransformToProduct( const carve::math::Matrix& matrix, bool matrix_identity_checked = false ) + { + if( !matrix_identity_checked ) + { + if( GeomUtils::isMatrixIdentity( matrix ) ) { - // vertex exists in polyhedron. return its index - size_t vertex_index = it_find_z->second; - return vertex_index; + return; } - return -1; - } - - // insert: returns a pair, with its member pair::first set to an iterator pointing to either the newly inserted element or to the element with an equivalent key in the map - auto itFindX = m_existing_vertices_coords.find(vertex_x); - if( itFindX == m_existing_vertices_coords.end() ) + for( size_t i_item = 0; i_item < m_vec_representations.size(); ++i_item ) { - return -1; + m_vec_representations[i_item]->applyTransformToRepresentation( matrix, true ); } - - std::map >& map_y_index = itFindX->second; - - auto itFindY = map_y_index.find(vertex_y); - if( itFindY== map_y_index.end() ) + for( auto child_product_data : m_vec_children ) { - return -1; + child_product_data->applyTransformToProduct( matrix, true ); } + } + const std::vector >& getAppearances() { return m_vec_product_appearances; } - std::map& map_z_index = itFindY->second; - auto it_find_z = map_z_index.find(vertex_z); - if( it_find_z != map_z_index.end() ) + bool isEmpty( bool check_also_children ) const + { + if( m_vec_representations.size() > 0 ) { - // vertex exists in polyhedron. return its index - size_t vertex_index = it_find_z->second; - return vertex_index; + return false; } - return -1; + if( m_vec_product_appearances.size() > 0 ) + { + return false; + } + if( check_also_children ) + { + if( m_vec_product_appearances.size() > 0 ) + { + for( size_t ii = 0; ii < m_vec_children.size(); ++ii ) + { + const shared_ptr& child = m_vec_children[ii]; + bool child_empty = child->isEmpty( check_also_children ); + if( !child_empty ) + { + return false; + } + } + } + } + return true; } -#endif - bool checkFaceIndices() + bool hasGeometricRepresentation( bool includeChildren = true ) const { - const std::vector& vec_points = m_poly_data->points; - const std::vector& face_indices = m_poly_data->faceIndices; - int face_count = 0; - for( size_t ii = 0; ii < face_indices.size(); ++ii ) + if( includeChildren ) { - int num_vertices = face_indices[ii]; - for( int jj = 0; jj < num_vertices; ++jj ) + for( size_t ii = 0; ii < m_vec_children.size(); ++ii ) { - ++ii; - if( ii >= face_indices.size() ) - { - return false; - } - int vertex_index = face_indices[ii]; - if( vertex_index >= (int)vec_points.size() ) + const shared_ptr& child = m_vec_children[ii]; + bool childHasGeom = child->hasGeometricRepresentation(includeChildren); + if( childHasGeom ) { - return false; + return true; } } - - ++face_count; } - if( face_count != m_poly_data->faceCount ) + if( m_vec_representations.size() > 0 ) { - return false; + // TODO: check if further check for mesh bounding box is necessary + return true; } - return true; + return false; } - void clearAllData() - { - m_poly_data->clearFaces(); - m_existing_vertices_coords.clear(); - m_existing_vertices_coords_merged.clear(); - } + //void computeBoundingBoxLocalCoords( carve::geom::aabb<3>& bbox, bool include_children ) const + //{ + // for( size_t ii = 0; ii < m_vec_representations.size(); ++ii ) + // { + // const shared_ptr& representation_data = m_vec_representations[ii]; + // representation_data->computeBoundingBox( bbox ); + // } - double m_mergePointsFactor = -1; - shared_ptr m_poly_data; - std::map > > m_existing_vertices_coords; - std::map > > m_existing_vertices_coords_merged; + // if( include_children ) + // { + // for( auto child_product_data : m_vec_children ) + // { + // child_product_data->computeBoundingBoxLocalCoords( bbox, include_children ); + // } + // } + //} }; + + static carve::geom::aabb<3> computeBoundingBoxLocalCoords( shared_ptr& productData, bool includeChildren ) { carve::geom::aabb<3> bbox; diff --git a/IfcPlusPlus/src/ifcpp/geometry/Carve/MeshUtils.h b/IfcPlusPlus/src/ifcpp/geometry/Carve/MeshUtils.h index 2860f6bb0..0daf4d7a6 100644 --- a/IfcPlusPlus/src/ifcpp/geometry/Carve/MeshUtils.h +++ b/IfcPlusPlus/src/ifcpp/geometry/Carve/MeshUtils.h @@ -1144,7 +1144,9 @@ namespace MeshUtils int idxB = meshOut.addPoint(v1); int idxC = meshOut.addPoint(v2); int idxD = meshOut.addPoint(v3); - meshOut.m_poly_data->addFace(idxA, idxB, idxC, idxD); + //meshOut.m_poly_data->addFace(idxA, idxB, idxC, idxD); + meshOut.m_poly_data->addFace(idxA, idxB, idxC); + meshOut.m_poly_data->addFace(idxA, idxC, idxD); #ifdef _DEBUG if( dumpPolygon ) @@ -2165,7 +2167,7 @@ namespace MeshUtils return false; } - inline void meshset2PolyInput(const shared_ptr>& meshset, PolyInputCache3D& polyInput) + inline void polyhedronFromMeshSet(const shared_ptr>& meshset, PolyInputCache3D& polyInput) { for( size_t ii = 0; ii < meshset->meshes.size(); ++ii ) { @@ -2200,12 +2202,100 @@ namespace MeshUtils continue; } polyInput.m_poly_data->addFace(vecPointIndexes.begin(), vecPointIndexes.end()); + } + } + } + } + + inline void polyhedronFromMesh(const carve::mesh::Mesh<3>* mesh, PolyInputCache3D& polyInput) + { + for( size_t jj = 0; jj < mesh->faces.size(); ++jj ) + { + carve::mesh::Face<3>* face = mesh->faces[jj]; + carve::mesh::Edge<3>* edge = face->edge; + if( edge ) + { + std::vector vecPointIndexes; + size_t maxNumEdges = 1000; + for( size_t kk = 0; kk < face->n_edges; ++kk ) + { + vec3& edgeEndPoint = edge->v2()->v; + int idx = polyInput.addPoint(edgeEndPoint); + vecPointIndexes.push_back(idx); + edge = edge->next; + if( edge == face->edge ) + { + break; + } + } + if( vecPointIndexes.size() < 3 ) + { +#ifdef _DEBUG + std::cout << "face with < 3 edges" << std::endl; +#endif + continue; } + polyInput.m_poly_data->addFace(vecPointIndexes.begin(), vecPointIndexes.end()); } } } + inline bool addFacesReversed(const PolyInputCache3D& poly_cache_source, PolyInputCache3D& poly_cache_target) + { + shared_ptr poly_data_source = poly_cache_source.m_poly_data; + + std::vector& faceIndices = poly_data_source->faceIndices; + if( faceIndices.size() == 0 ) + { + return true; + } + + size_t numPointsAll = poly_data_source->points.size(); + if( numPointsAll < 2 ) + { + return true; + } + bool inputCorrect = true; + for( size_t iiFace = 0; iiFace < faceIndices.size(); ) + { + int numPoints = faceIndices[iiFace]; + int numPointsIdx = iiFace; + + if( iiFace + numPoints >= faceIndices.size() ) + { + // skip face + break; + } + + std::vector pointIdxCurrentFace; + for( size_t iiPoint = 1; iiPoint <= numPoints; ++iiPoint ) + { + int idx = faceIndices[iiFace + iiPoint]; + + carve::geom3d::Vector point = poly_data_source->points[idx]; + int idxTarget = poly_cache_target.addPoint(point); + pointIdxCurrentFace.push_back(idxTarget); + } + + poly_cache_target.m_poly_data->addFace(pointIdxCurrentFace.rbegin(), pointIdxCurrentFace.rend()); + + iiFace += numPoints + 1; + + if( iiFace > faceIndices.size() ) + { + inputCorrect = false; + break; + } + if( iiFace == faceIndices.size() ) + { + break; + } + } + + return inputCorrect; + } + static void resolveOpenEdges(shared_ptr>& meshset, double eps, bool dumpPolygons) { if( !meshset ) @@ -2243,7 +2333,7 @@ namespace MeshUtils } PolyInputCache3D polyInput( eps ); - meshset2PolyInput(meshset, polyInput); + polyhedronFromMeshSet(meshset, polyInput); bool meshsetChanged = false; diff --git a/examples/LoadFileWithGeometryExampleConsole/src/main.cpp b/examples/LoadFileWithGeometryExampleConsole/src/main.cpp index a8b892ec6..2fd49e9fc 100644 --- a/examples/LoadFileWithGeometryExampleConsole/src/main.cpp +++ b/examples/LoadFileWithGeometryExampleConsole/src/main.cpp @@ -187,6 +187,9 @@ int main() geometry_converter->setCsgEps(1.5e-9); // convert IFC geometry representations to Carve meshes +#ifdef _DEBUG + GeomDebugDump::clearMeshsetDump(); +#endif std::cout << "Converting IFC geometry: "; geometry_converter->convertGeometry();