mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Apply openings in batches sorted by increasing detail
This commit is contained in:
@@ -706,22 +706,31 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings,
|
|
||||||
const IfcGeom::IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::IfcRepresentationShapeItems& cut_shapes) {
|
namespace {
|
||||||
|
struct opening_sorter {
|
||||||
TopTools_ListOfShape opening_shapelist;
|
bool operator()(const std::pair<double, TopoDS_Shape>& a, const std::pair<double, TopoDS_Shape>& b) const {
|
||||||
|
return a.first > b.first;
|
||||||
for ( IfcSchema::IfcRelVoidsElement::list::it it = openings->begin(); it != openings->end(); ++ it ) {
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings,
|
||||||
|
const IfcGeom::IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::IfcRepresentationShapeItems& cut_shapes) {
|
||||||
|
|
||||||
|
std::vector< std::pair<double, TopoDS_Shape> > opening_vector;
|
||||||
|
|
||||||
|
for (IfcSchema::IfcRelVoidsElement::list::it it = openings->begin(); it != openings->end(); ++it) {
|
||||||
IfcSchema::IfcRelVoidsElement* v = *it;
|
IfcSchema::IfcRelVoidsElement* v = *it;
|
||||||
IfcSchema::IfcFeatureElementSubtraction* fes = v->RelatedOpeningElement();
|
IfcSchema::IfcFeatureElementSubtraction* fes = v->RelatedOpeningElement();
|
||||||
if ( fes->is(IfcSchema::Type::IfcOpeningElement) ) {
|
if (fes->is(IfcSchema::Type::IfcOpeningElement)) {
|
||||||
if (!fes->hasRepresentation()) continue;
|
if (!fes->hasRepresentation()) continue;
|
||||||
|
|
||||||
// Convert the IfcRepresentation of the IfcOpeningElement
|
// Convert the IfcRepresentation of the IfcOpeningElement
|
||||||
gp_Trsf opening_trsf;
|
gp_Trsf opening_trsf;
|
||||||
if (fes->hasObjectPlacement()) {
|
if (fes->hasObjectPlacement()) {
|
||||||
try {
|
try {
|
||||||
convert(fes->ObjectPlacement(),opening_trsf);
|
convert(fes->ObjectPlacement(), opening_trsf);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
Logger::Error(e);
|
Logger::Error(e);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
@@ -736,24 +745,26 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
|
|||||||
IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations();
|
IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations();
|
||||||
|
|
||||||
IfcGeom::IfcRepresentationShapeItems opening_shapes;
|
IfcGeom::IfcRepresentationShapeItems opening_shapes;
|
||||||
|
|
||||||
for ( IfcSchema::IfcRepresentation::list::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) {
|
for (IfcSchema::IfcRepresentation::list::it it2 = reps->begin(); it2 != reps->end(); ++it2) {
|
||||||
convert_shapes(*it2,opening_shapes);
|
convert_shapes(*it2, opening_shapes);
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( unsigned int i = 0; i < opening_shapes.size(); ++ i ) {
|
for (unsigned int i = 0; i < opening_shapes.size(); ++i) {
|
||||||
TopoDS_Shape opening_shape_solid;
|
TopoDS_Shape opening_shape_solid;
|
||||||
const TopoDS_Shape& opening_shape_unlocated = ensure_fit_for_subtraction(opening_shapes[i].Shape(), opening_shape_solid);
|
const TopoDS_Shape& opening_shape_unlocated = ensure_fit_for_subtraction(opening_shapes[i].Shape(), opening_shape_solid);
|
||||||
|
|
||||||
gp_GTrsf gtrsf = opening_shapes[i].Placement();
|
gp_GTrsf gtrsf = opening_shapes[i].Placement();
|
||||||
gtrsf.PreMultiply(opening_trsf);
|
gtrsf.PreMultiply(opening_trsf);
|
||||||
TopoDS_Shape opening_shape = apply_transformation(opening_shape_unlocated, gtrsf);
|
TopoDS_Shape opening_shape = apply_transformation(opening_shape_unlocated, gtrsf);
|
||||||
opening_shapelist.Append(opening_shape);
|
opening_vector.push_back(std::make_pair(min_edge_length(opening_shape), opening_shape));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::sort(opening_vector.begin(), opening_vector.end(), opening_sorter());
|
||||||
|
|
||||||
// Iterate over the shapes of the IfcProduct
|
// Iterate over the shapes of the IfcProduct
|
||||||
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
|
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
|
||||||
TopoDS_Shape entity_shape_solid;
|
TopoDS_Shape entity_shape_solid;
|
||||||
@@ -764,13 +775,35 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
|
|||||||
}
|
}
|
||||||
TopoDS_Shape entity_shape = apply_transformation(entity_shape_unlocated, entity_shape_gtrsf);
|
TopoDS_Shape entity_shape = apply_transformation(entity_shape_unlocated, entity_shape_gtrsf);
|
||||||
|
|
||||||
TopoDS_Shape result;
|
TopoDS_Shape result = entity_shape;
|
||||||
if (boolean_operation(entity_shape, opening_shapelist, BOPAlgo_CUT, result)) {
|
|
||||||
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(result, &it3->Style()));
|
auto it = opening_vector.begin();
|
||||||
} else {
|
auto jt = it;
|
||||||
Logger::Message(Logger::LOG_ERROR, "Opening subtraction failed:", entity->entity);
|
|
||||||
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(entity_shape, &it3->Style()));
|
for (;; ++it) {
|
||||||
|
if (it == opening_vector.end() || jt->first / it->first > 10.) {
|
||||||
|
|
||||||
|
TopTools_ListOfShape opening_list;
|
||||||
|
for (auto kt = jt; kt < it; ++kt) {
|
||||||
|
opening_list.Append(kt->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
TopoDS_Shape intermediate_result;
|
||||||
|
if (boolean_operation(result, opening_list, BOPAlgo_CUT, intermediate_result)) {
|
||||||
|
result = intermediate_result;
|
||||||
|
} else {
|
||||||
|
Logger::Message(Logger::LOG_ERROR, "Opening subtraction failed for " + boost::lexical_cast<std::string>(std::distance(jt, it)) + " openings", entity->entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
jt = it;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it == opening_vector.end()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(result, &it3->Style()));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user