bool IfcGeom::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) { BRepOffsetAPI_Sewing builder; builder.SetTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); builder.SetMaxTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); builder.SetMinTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); TopExp_Explorer exp(compound,TopAbs_FACE); if ( ! exp.More() ) return false; for ( ; exp.More(); exp.Next() ) { TopoDS_Face face = TopoDS::Face(exp.Current()); builder.Add(face); } builder.Perform(); shape = builder.SewedShape(); try { ShapeFix_Solid sf_solid; sf_solid.LimitTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); shape = sf_solid.SolidFromShell(TopoDS::Shell(shape)); } catch(...) {} return true; }
bool IfcGeom::Kernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, TopoDS_Shape& shape) { IfcSchema::IfcCartesianPointList3D* point_list = l->Coordinates(); const std::vector< std::vector<double> > coordinates = point_list->CoordList(); std::vector<gp_Pnt> points; points.reserve(coordinates.size()); for (std::vector< std::vector<double> >::const_iterator it = coordinates.begin(); it != coordinates.end(); ++it) { const std::vector<double>& coords = *it; if (coords.size() != 3) { Logger::Message(Logger::LOG_ERROR, "Invalid dimensions encountered on Coordinates", l->entity); return false; } points.push_back(gp_Pnt(coords[0] * getValue(GV_LENGTH_UNIT), coords[1] * getValue(GV_LENGTH_UNIT), coords[2] * getValue(GV_LENGTH_UNIT))); } std::vector< std::vector<int> > indices = l->CoordIndex(); std::vector<TopoDS_Face> faces; faces.reserve(indices.size()); for(std::vector< std::vector<int> >::const_iterator it = indices.begin(); it != indices.end(); ++ it) { const std::vector<int>& tri = *it; if (tri.size() != 3) { Logger::Message(Logger::LOG_ERROR, "Invalid dimensions encountered on CoordIndex", l->entity); return false; } const int min_index = *std::min_element(tri.begin(), tri.end()); const int max_index = *std::max_element(tri.begin(), tri.end()); if (min_index < 1 || max_index > points.size()) { Logger::Message(Logger::LOG_ERROR, "Contents of CoordIndex out of bounds", l->entity); return false; } const gp_Pnt& a = points[tri[0] - 1]; // account for zero- vs const gp_Pnt& b = points[tri[1] - 1]; // one-based indices in const gp_Pnt& c = points[tri[2] - 1]; // c++ and express TopoDS_Wire wire = BRepBuilderAPI_MakePolygon(a, b, c, true).Wire(); TopoDS_Face face = BRepBuilderAPI_MakeFace(wire).Face(); TopoDS_Iterator face_it(face, false); const TopoDS_Wire& w = TopoDS::Wire(face_it.Value()); const bool reversed = w.Orientation() == TopAbs_REVERSED; if (reversed) { face.Reverse(); } if (face_area(face) > getValue(GV_MINIMAL_FACE_AREA)) { faces.push_back(face); } } if (faces.empty()) return false; const unsigned int num_faces = indices.size(); bool valid_shell = false; if (faces.size() < getValue(GV_MAX_FACES_TO_SEW)) { BRepOffsetAPI_Sewing builder; builder.SetTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); builder.SetMaxTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); builder.SetMinTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); for (std::vector<TopoDS_Face>::const_iterator it = faces.begin(); it != faces.end(); ++it) { builder.Add(*it); } try { builder.Perform(); shape = builder.SewedShape(); valid_shell = BRepCheck_Analyzer(shape).IsValid(); } catch(...) {} if (valid_shell) { try { ShapeFix_Solid solid; solid.LimitTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); TopoDS_Solid solid_shape = solid.SolidFromShell(TopoDS::Shell(shape)); if (!solid_shape.IsNull()) { try { BRepClass3d_SolidClassifier classifier(solid_shape); shape = solid_shape; } catch (...) {} } } catch(...) {} } else { Logger::Message(Logger::LOG_WARNING, "Failed to sew faceset:", l->entity); } } if (!valid_shell) { TopoDS_Compound compound; BRep_Builder builder; builder.MakeCompound(compound); for (std::vector<TopoDS_Face>::const_iterator it = faces.begin(); it != faces.end(); ++it) { builder.Add(compound, *it); } shape = compound; } return true; }
bool IfcGeom::Kernel::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Shape& shape) { IfcSchema::IfcFace::list::ptr faces = l->CfsFaces(); bool facesAdded = false; const unsigned int num_faces = faces->size(); bool valid_shell = false; if ( num_faces < getValue(GV_MAX_FACES_TO_SEW) ) { BRepOffsetAPI_Sewing builder; builder.SetTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); builder.SetMaxTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); builder.SetMinTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); for( IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++ it ) { TopoDS_Face face; bool converted_face = false; try { converted_face = convert_face(*it,face); } catch (...) {} if ( converted_face && face_area(face) > getValue(GV_MINIMAL_FACE_AREA) ) { builder.Add(face); facesAdded = true; } else { Logger::Message(Logger::LOG_WARNING,"Invalid face:",(*it)->entity); } } if ( ! facesAdded ) return false; try { builder.Perform(); shape = builder.SewedShape(); valid_shell = BRepCheck_Analyzer(shape).IsValid(); } catch(...) {} if (valid_shell) { try { ShapeFix_Solid solid; solid.LimitTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); TopoDS_Solid solid_shape = solid.SolidFromShell(TopoDS::Shell(shape)); if (!solid_shape.IsNull()) { try { BRepClass3d_SolidClassifier classifier(solid_shape); shape = solid_shape; } catch (...) {} } } catch(...) {} } else { Logger::Message(Logger::LOG_WARNING,"Failed to sew faceset:",l->entity); } } if (!valid_shell) { TopoDS_Compound compound; BRep_Builder builder; builder.MakeCompound(compound); for( IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++ it ) { TopoDS_Face face; bool converted_face = false; try { converted_face = convert_face(*it,face); } catch (...) {} if ( converted_face && face_area(face) > getValue(GV_MINIMAL_FACE_AREA) ) { builder.Add(compound,face); facesAdded = true; } else { Logger::Message(Logger::LOG_WARNING,"Invalid face:",(*it)->entity); } } if ( ! facesAdded ) return false; shape = compound; } return true; }