mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Add support for IFC4.IfcTriangulatedFaceSet
This commit is contained in:
@@ -320,7 +320,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcArbitraryProfileDefWithVoids*
|
||||
|
||||
bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangleProfileDef* l, TopoDS_Shape& face) {
|
||||
const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
|
||||
if ( x < ALMOST_ZERO || y < ALMOST_ZERO ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
#include <BRepPrimAPI_MakeCylinder.hxx>
|
||||
#include <BRepPrimAPI_MakeSphere.hxx>
|
||||
#include <BRepPrimAPI_MakeWedge.hxx>
|
||||
#include <BRepBuilderAPI_MakePolygon.hxx>
|
||||
|
||||
#include <BRepBuilderAPI_Transform.hxx>
|
||||
#include <BRepBuilderAPI_MakeShell.hxx>
|
||||
@@ -824,4 +825,112 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcAdvancedBrep* l, TopoDS_Shape&
|
||||
return convert(l->Outer(), shape);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -54,6 +54,7 @@ SHAPE(IfcAdvancedBrep);
|
||||
// FIXME: Surfaces should have a shape type of their own
|
||||
SHAPE(IfcBSplineSurfaceWithKnots);
|
||||
SHAPE(IfcPlane);
|
||||
SHAPE(IfcTriangulatedFaceSet);
|
||||
#endif
|
||||
SHAPE(IfcExtrudedAreaSolid);
|
||||
SHAPE(IfcRevolvedAreaSolid);
|
||||
|
||||
Reference in New Issue
Block a user