mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-25 17:57:02 +00:00
Accept IfcBooleanResult operands that convert to set of shapes in IfcOpenShell rather than a single shape (i.e IfcShellBasedSurfaceModel, IfcFaceBasedSurfaceModel, IfcFacetedBrep, IfcGeometricSet)
This commit is contained in:
@@ -84,6 +84,7 @@ namespace IfcGeom {
|
|||||||
bool convert_shapes(const IfcUtil::IfcBaseClass* L, IfcRepresentationShapeItems& result);
|
bool convert_shapes(const IfcUtil::IfcBaseClass* L, IfcRepresentationShapeItems& result);
|
||||||
bool is_shape_collection(const IfcUtil::IfcBaseClass* L);
|
bool is_shape_collection(const IfcUtil::IfcBaseClass* L);
|
||||||
bool convert_shape(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result);
|
bool convert_shape(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result);
|
||||||
|
bool flatten_shape_list(const IfcGeom::IfcRepresentationShapeItems& shapes, TopoDS_Shape& result, bool fuse);
|
||||||
bool convert_wire(const IfcUtil::IfcBaseClass* L, TopoDS_Wire& result);
|
bool convert_wire(const IfcUtil::IfcBaseClass* L, TopoDS_Wire& result);
|
||||||
bool convert_curve(const IfcUtil::IfcBaseClass* L, Handle(Geom_Curve)& result);
|
bool convert_curve(const IfcUtil::IfcBaseClass* L, Handle(Geom_Curve)& result);
|
||||||
bool convert_face(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result);
|
bool convert_face(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result);
|
||||||
|
|||||||
@@ -69,6 +69,7 @@
|
|||||||
#include <BRepBuilderAPI_MakeSolid.hxx>
|
#include <BRepBuilderAPI_MakeSolid.hxx>
|
||||||
#include <BRepPrimAPI_MakeHalfSpace.hxx>
|
#include <BRepPrimAPI_MakeHalfSpace.hxx>
|
||||||
#include <BRepAlgoAPI_Cut.hxx>
|
#include <BRepAlgoAPI_Cut.hxx>
|
||||||
|
#include <BRepAlgoAPI_Fuse.hxx>
|
||||||
|
|
||||||
#include <ShapeFix_Shape.hxx>
|
#include <ShapeFix_Shape.hxx>
|
||||||
#include <ShapeFix_ShapeTolerance.hxx>
|
#include <ShapeFix_ShapeTolerance.hxx>
|
||||||
@@ -691,4 +692,61 @@ bool IfcGeom::fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape) {
|
|||||||
} catch(...) {}
|
} catch(...) {}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IfcGeom::flatten_shape_list(const IfcGeom::IfcRepresentationShapeItems& shapes, TopoDS_Shape& result, bool fuse) {
|
||||||
|
TopoDS_Compound compound;
|
||||||
|
BRep_Builder builder;
|
||||||
|
builder.MakeCompound(compound);
|
||||||
|
|
||||||
|
result = TopoDS_Shape();
|
||||||
|
|
||||||
|
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
|
||||||
|
TopoDS_Shape merged;
|
||||||
|
const TopoDS_Shape& s = it->Shape();
|
||||||
|
if (fuse) {
|
||||||
|
IfcGeom::ensure_fit_for_subtraction(s, merged);
|
||||||
|
} else {
|
||||||
|
merged = s;
|
||||||
|
}
|
||||||
|
const gp_GTrsf& trsf = it->Placement();
|
||||||
|
bool trsf_valid = false;
|
||||||
|
gp_Trsf _trsf;
|
||||||
|
try {
|
||||||
|
_trsf = trsf.Trsf();
|
||||||
|
trsf_valid = true;
|
||||||
|
} catch (...) {}
|
||||||
|
const TopoDS_Shape moved_shape = trsf_valid ? merged.Moved(_trsf) :
|
||||||
|
BRepBuilderAPI_GTransform(merged,trsf,true).Shape();
|
||||||
|
|
||||||
|
if (shapes.size() == 1) {
|
||||||
|
result = moved_shape;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fuse) {
|
||||||
|
if (result.IsNull()) {
|
||||||
|
result = moved_shape;
|
||||||
|
} else {
|
||||||
|
BRepAlgoAPI_Fuse brep_fuse(result, moved_shape);
|
||||||
|
if ( brep_fuse.IsDone() ) {
|
||||||
|
TopoDS_Shape fused = brep_fuse;
|
||||||
|
|
||||||
|
ShapeFix_Shape fix(result);
|
||||||
|
fix.Perform();
|
||||||
|
result = fix.Shape();
|
||||||
|
|
||||||
|
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
|
||||||
|
if ( is_valid ) {
|
||||||
|
result = fused;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
builder.Add(compound,moved_shape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !result.IsNull();
|
||||||
|
}
|
||||||
|
|
||||||
@@ -242,19 +242,34 @@ bool IfcGeom::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, IfcRepresen
|
|||||||
|
|
||||||
bool IfcGeom::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape& shape) {
|
bool IfcGeom::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape& shape) {
|
||||||
TopoDS_Shape s1, s2;
|
TopoDS_Shape s1, s2;
|
||||||
|
IfcRepresentationShapeItems items1, items2;
|
||||||
TopoDS_Wire boundary_wire;
|
TopoDS_Wire boundary_wire;
|
||||||
IfcSchema::IfcBooleanOperand operand1 = l->FirstOperand();
|
IfcSchema::IfcBooleanOperand operand1 = l->FirstOperand();
|
||||||
IfcSchema::IfcBooleanOperand operand2 = l->SecondOperand();
|
IfcSchema::IfcBooleanOperand operand2 = l->SecondOperand();
|
||||||
bool is_halfspace = operand2->is(IfcSchema::Type::IfcHalfSpaceSolid);
|
bool is_halfspace = operand2->is(IfcSchema::Type::IfcHalfSpaceSolid);
|
||||||
|
|
||||||
if ( ! IfcGeom::convert_shape(operand1,s1) )
|
if ( is_shape_collection(operand1) ) {
|
||||||
return false;
|
if (!(convert_shapes(operand1, items1) && flatten_shape_list(items1, s1, true))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ( ! IfcGeom::convert_shape(operand1,s1) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const double first_operand_volume = shape_volume(s1);
|
const double first_operand_volume = shape_volume(s1);
|
||||||
if ( first_operand_volume <= ALMOST_ZERO )
|
if ( first_operand_volume <= ALMOST_ZERO )
|
||||||
Logger::Message(Logger::LOG_WARNING,"Empty solid for:",l->FirstOperand()->entity);
|
Logger::Message(Logger::LOG_WARNING,"Empty solid for:",l->FirstOperand()->entity);
|
||||||
|
|
||||||
if ( !IfcGeom::convert_shape(l->SecondOperand(),s2) ) {
|
bool shape2_processed = false;
|
||||||
|
if ( is_shape_collection(operand2) ) {
|
||||||
|
shape2_processed = convert_shapes(operand2, items2) && flatten_shape_list(items2, s2, true);
|
||||||
|
} else {
|
||||||
|
shape2_processed = IfcGeom::convert_shape(operand2,s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shape2_processed) {
|
||||||
shape = s1;
|
shape = s1;
|
||||||
Logger::Message(Logger::LOG_ERROR,"Failed to convert SecondOperand of:",l->entity);
|
Logger::Message(Logger::LOG_ERROR,"Failed to convert SecondOperand of:",l->entity);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user