mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-28 03:05:33 +00:00
Route boolean-op kernel logging through the injected logger
Ports #96e2efebc onto wgpu. wgpu's boolean_utils logged via the global ::logger::root() singleton (which IfcConvert never wires to --log-file), so boolean-op messages were effectively dropped. Thread the caller's injected logger through instead: - boolean_settings gains `::logger* logger` + `log()` accessor (falls back to ::logger::root()); boolean_operation logs via settings.log() - eliminate_narrow_operands / boolean_subtraction_2d_using_builder take a `::logger& logger = ::logger::root()` param; boolean_operation passes settings.log() into them - OpenCascadeKernel / boolean_result set bst.logger = &logger_ and log via logger_ (were ::logger::root()) Adapted from v0.8.0's Logger/Logger::Root() to wgpu's ::logger/::logger::root(). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
committed by
Dion Moult
parent
60b4f6191c
commit
bb908f3dfa
@@ -50,6 +50,7 @@ bool IfcGeom::OpenCascadeKernel::convert_openings(const express::Base& entity, c
|
|||||||
bst.attempt_2d = settings_.get<settings::BooleanAttempt2d>().get();
|
bst.attempt_2d = settings_.get<settings::BooleanAttempt2d>().get();
|
||||||
bst.debug = settings_.get<settings::DebugBooleanOperations>().get();
|
bst.debug = settings_.get<settings::DebugBooleanOperations>().get();
|
||||||
bst.precision = settings_.get<settings::Precision>().get();
|
bst.precision = settings_.get<settings::Precision>().get();
|
||||||
|
bst.logger = &logger_;
|
||||||
|
|
||||||
std::vector< std::pair<double, TopoDS_Shape> > opening_vector;
|
std::vector< std::pair<double, TopoDS_Shape> > opening_vector;
|
||||||
|
|
||||||
|
|||||||
@@ -118,14 +118,14 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result::ptr br, Con
|
|||||||
|
|
||||||
const double first_operand_volume = util::shape_volume(a);
|
const double first_operand_volume = util::shape_volume(a);
|
||||||
if (first_operand_volume <= ALMOST_ZERO) {
|
if (first_operand_volume <= ALMOST_ZERO) {
|
||||||
::logger::root().message(::logger::LOG_WARNING, "GEO", 119, "Empty solid for:", c->instance);
|
logger_.message(::logger::LOG_WARNING, "GEO", 119, "Empty solid for:", c->instance);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
for (auto& r : cr) {
|
for (auto& r : cr) {
|
||||||
auto S = std::static_pointer_cast<OpenCascadeShape>(r.Shape())->shape();
|
auto S = std::static_pointer_cast<OpenCascadeShape>(r.Shape())->shape();
|
||||||
if (S.IsNull()) {
|
if (S.IsNull()) {
|
||||||
::logger::root().error("GEO", 120, "Null operand");
|
logger_.error("GEO", 120, "Null operand");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
gp_GTrsf trsf;
|
gp_GTrsf trsf;
|
||||||
@@ -140,7 +140,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result::ptr br, Con
|
|||||||
// #2665 we also set a precision-independent threshold, because in the boolean op routine
|
// #2665 we also set a precision-independent threshold, because in the boolean op routine
|
||||||
// the working fuzziness might still be increased.
|
// the working fuzziness might still be increased.
|
||||||
if (d < tol * 20. || d < 0.00002) {
|
if (d < tol * 20. || d < 0.00002) {
|
||||||
::logger::root().message(::logger::LOG_WARNING, "GEO", 121, "Halfspace subtraction yields unchanged volume:", c->instance);
|
logger_.message(::logger::LOG_WARNING, "GEO", 121, "Halfspace subtraction yields unchanged volume:", c->instance);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
S = result;
|
S = result;
|
||||||
@@ -159,6 +159,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result::ptr br, Con
|
|||||||
bst.attempt_2d = settings_.get<settings::BooleanAttempt2d>().get();
|
bst.attempt_2d = settings_.get<settings::BooleanAttempt2d>().get();
|
||||||
bst.debug = settings_.get<settings::DebugBooleanOperations>().get();
|
bst.debug = settings_.get<settings::DebugBooleanOperations>().get();
|
||||||
bst.precision = settings_.get<settings::Precision>().get();
|
bst.precision = settings_.get<settings::Precision>().get();
|
||||||
|
bst.logger = &logger_;
|
||||||
|
|
||||||
TopoDS_Shape r;
|
TopoDS_Shape r;
|
||||||
|
|
||||||
|
|||||||
@@ -405,7 +405,7 @@ bool IfcGeom::util::is_extrusion(const gp_Vec & v, const TopoDS_Shape & s, TopoD
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IfcGeom::util::eliminate_narrow_operands(double prec, const NCollection_List<TopoDS_Shape>& bs, NCollection_List<TopoDS_Shape> & c) {
|
int IfcGeom::util::eliminate_narrow_operands(double prec, const NCollection_List<TopoDS_Shape>& bs, NCollection_List<TopoDS_Shape> & c, ::logger& logger) {
|
||||||
int N = 0;
|
int N = 0;
|
||||||
NCollection_List<TopoDS_Shape>::Iterator it(bs);
|
NCollection_List<TopoDS_Shape>::Iterator it(bs);
|
||||||
for (; it.More(); it.Next()) {
|
for (; it.More(); it.Next()) {
|
||||||
@@ -418,7 +418,7 @@ int IfcGeom::util::eliminate_narrow_operands(double prec, const NCollection_List
|
|||||||
|
|
||||||
bool is_narrow = min_dimension < prec;
|
bool is_narrow = min_dimension < prec;
|
||||||
|
|
||||||
::logger::root().notice("GEO", 122, "Min OBB dimension of operand = " + std::to_string(min_dimension));
|
logger.notice("GEO", 122, "Min OBB dimension of operand = " + std::to_string(min_dimension));
|
||||||
|
|
||||||
if (!is_narrow) {
|
if (!is_narrow) {
|
||||||
c.Append(it.Value());
|
c.Append(it.Value());
|
||||||
@@ -573,7 +573,7 @@ int IfcGeom::util::eliminate_touching_operands(double prec, const TopoDS_Shape &
|
|||||||
return N;
|
return N;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IfcGeom::util::boolean_subtraction_2d_using_builder(const TopoDS_Shape & a_input, const NCollection_List<TopoDS_Shape> & b_input, TopoDS_Shape & result, double eps) {
|
bool IfcGeom::util::boolean_subtraction_2d_using_builder(const TopoDS_Shape & a_input, const NCollection_List<TopoDS_Shape> & b_input, TopoDS_Shape & result, double eps, ::logger& logger) {
|
||||||
IfcGeom::impl::tree<int> edge_tree;
|
IfcGeom::impl::tree<int> edge_tree;
|
||||||
|
|
||||||
NCollection_List<TopoDS_Shape> ab_input = b_input;
|
NCollection_List<TopoDS_Shape> ab_input = b_input;
|
||||||
@@ -703,7 +703,7 @@ bool IfcGeom::util::boolean_subtraction_2d_using_builder(const TopoDS_Shape & a_
|
|||||||
if (u11 < U1 && U1 < u12 && u21 < U2 && U2 < u22) {
|
if (u11 < U1 && U1 < u12 && u21 < U2 && U2 < u22) {
|
||||||
// Edge curves belonging to different operands intersect, don't process
|
// Edge curves belonging to different operands intersect, don't process
|
||||||
// using builder.
|
// using builder.
|
||||||
::logger::root().notice("GEO", 123, "Intersecting boundaries");
|
logger.notice("GEO", 123, "Intersecting boundaries");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -750,7 +750,7 @@ bool IfcGeom::util::boolean_subtraction_2d_using_builder(const TopoDS_Shape & a_
|
|||||||
// any effect and marked as redundant. Feeding it to the builder algo
|
// any effect and marked as redundant. Feeding it to the builder algo
|
||||||
// will likely cause problems.
|
// will likely cause problems.
|
||||||
redundant[std::distance(wires.begin(), it)] = true;
|
redundant[std::distance(wires.begin(), it)] = true;
|
||||||
::logger::root().notice("GEO", 124, "Subtraction operand outside of outer bound");
|
logger.notice("GEO", 124, "Subtraction operand outside of outer bound");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -790,7 +790,7 @@ bool IfcGeom::util::boolean_subtraction_2d_using_builder(const TopoDS_Shape & a_
|
|||||||
if (wire_clss[wire_index]->Perform(p2d) == TopAbs_IN) {
|
if (wire_clss[wire_index]->Perform(p2d) == TopAbs_IN) {
|
||||||
// A wire is contained within another operand
|
// A wire is contained within another operand
|
||||||
redundant[other_index] = true;
|
redundant[other_index] = true;
|
||||||
::logger::root().notice("GEO", 125, "Subtraction operand contained in other");
|
logger.notice("GEO", 125, "Subtraction operand contained in other");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -848,7 +848,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "bool-" << std::this_thread::get_id() << "-" << (operation_counter_++);
|
ss << "bool-" << std::this_thread::get_id() << "-" << (operation_counter_++);
|
||||||
debug_identifier = ss.str();
|
debug_identifier = ss.str();
|
||||||
::logger::root().notice("GEO", 126, "Boolean debug identifier: " + debug_identifier);
|
settings.log().notice("GEO", 126, "Boolean debug identifier: " + debug_identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fuzziness < 0.) {
|
if (fuzziness < 0.) {
|
||||||
@@ -884,7 +884,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
|
|
||||||
a = unify(a_input, fuzziness * 1000.);
|
a = unify(a_input, fuzziness * 1000.);
|
||||||
|
|
||||||
::logger::root().message(
|
settings.log().message(
|
||||||
::logger::LOG_DEBUG, "GEO", 127,
|
::logger::LOG_DEBUG, "GEO", 127,
|
||||||
"Simplified operand A from "s +
|
"Simplified operand A from "s +
|
||||||
std::to_string(count(a_input, TopAbs_FACE)) +
|
std::to_string(count(a_input, TopAbs_FACE)) +
|
||||||
@@ -896,7 +896,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
NCollection_List<TopoDS_Shape>::Iterator it(b_input);
|
NCollection_List<TopoDS_Shape>::Iterator it(b_input);
|
||||||
for (; it.More(); it.Next()) {
|
for (; it.More(); it.Next()) {
|
||||||
b.Append(unify(it.Value(), fuzziness));
|
b.Append(unify(it.Value(), fuzziness));
|
||||||
::logger::root().message(
|
settings.log().message(
|
||||||
::logger::LOG_DEBUG, "GEO", 128,
|
::logger::LOG_DEBUG, "GEO", 128,
|
||||||
"Simplified operand B from "s +
|
"Simplified operand B from "s +
|
||||||
std::to_string(count(it.Value(), TopAbs_FACE)) +
|
std::to_string(count(it.Value(), TopAbs_FACE)) +
|
||||||
@@ -924,7 +924,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
|
|
||||||
auto N = bounding_box_overlap(fuzziness, a, b, b_tmp);
|
auto N = bounding_box_overlap(fuzziness, a, b, b_tmp);
|
||||||
if (N) {
|
if (N) {
|
||||||
::logger::root().notice("GEO", 129, "Eliminated " + std::to_string(N) + " disjoint operands");
|
settings.log().notice("GEO", 129, "Eliminated " + std::to_string(N) + " disjoint operands");
|
||||||
std::swap(b, b_tmp);
|
std::swap(b, b_tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -935,7 +935,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
b_tmp.Clear();
|
b_tmp.Clear();
|
||||||
auto N = eliminate_touching_operands(fuzziness, a, b, b_tmp);
|
auto N = eliminate_touching_operands(fuzziness, a, b, b_tmp);
|
||||||
if (N) {
|
if (N) {
|
||||||
::logger::root().notice("GEO", 130, "Eliminated " + std::to_string(N) + " touching operands");
|
settings.log().notice("GEO", 130, "Eliminated " + std::to_string(N) + " touching operands");
|
||||||
std::swap(b, b_tmp);
|
std::swap(b, b_tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -944,9 +944,9 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
PERF("boolean subtraction: eliminate narrow");
|
PERF("boolean subtraction: eliminate narrow");
|
||||||
|
|
||||||
b_tmp.Clear();
|
b_tmp.Clear();
|
||||||
auto N = eliminate_narrow_operands(fuzziness, b, b_tmp);
|
auto N = eliminate_narrow_operands(fuzziness, b, b_tmp, settings.log());
|
||||||
if (N) {
|
if (N) {
|
||||||
::logger::root().notice("GEO", 131, "Eliminated " + std::to_string(N) + " narrow operands");
|
settings.log().notice("GEO", 131, "Eliminated " + std::to_string(N) + " narrow operands");
|
||||||
std::swap(b, b_tmp);
|
std::swap(b, b_tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -960,21 +960,21 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (b.Extent() == 0) {
|
if (b.Extent() == 0) {
|
||||||
::logger::root().warning("GEO", 132, "No other operands remaining, using first operand");
|
settings.log().warning("GEO", 132, "No other operands remaining, using first operand");
|
||||||
result = a;
|
result = a;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_2d && ::logger::LOG_NOTICE >= ::logger::root().verbosity()) {
|
if (!is_2d && ::logger::LOG_NOTICE >= settings.log().verbosity()) {
|
||||||
PERF("preliminary manifoldness check");
|
PERF("preliminary manifoldness check");
|
||||||
|
|
||||||
if (!a.IsNull()) {
|
if (!a.IsNull()) {
|
||||||
::logger::root().notice("GEO", 133, "Operand A is " + (is_manifold(a) ? ""s : "non-"s) + "manifold");
|
settings.log().notice("GEO", 133, "Operand A is " + (is_manifold(a) ? ""s : "non-"s) + "manifold");
|
||||||
}
|
}
|
||||||
|
|
||||||
NCollection_List<TopoDS_Shape>::Iterator it(b);
|
NCollection_List<TopoDS_Shape>::Iterator it(b);
|
||||||
for (int i = 0; it.More(); it.Next(), ++i) {
|
for (int i = 0; it.More(); it.Next(), ++i) {
|
||||||
::logger::root().notice("GEO", 134, "Operand B " + std::to_string(i) + " is " + (is_manifold(it.Value()) ? ""s : "non-"s) + "manifold");
|
settings.log().notice("GEO", 134, "Operand B " + std::to_string(i) + " is " + (is_manifold(it.Value()) ? ""s : "non-"s) + "manifold");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1014,7 +1014,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
|
|
||||||
const double fuzz = (std::min)(min_length_orig / 3., fuzziness);
|
const double fuzz = (std::min)(min_length_orig / 3., fuzziness);
|
||||||
|
|
||||||
::logger::root().notice("GEO", 135, "Used fuzziness: " + std::to_string(fuzz));
|
settings.log().notice("GEO", 135, "Used fuzziness: " + std::to_string(fuzz));
|
||||||
|
|
||||||
const double new_fuzziness = fuzziness * 10.;
|
const double new_fuzziness = fuzziness * 10.;
|
||||||
const bool allow_retry = new_fuzziness - 1e-15 <= settings.precision * 10000. && new_fuzziness < min_length_orig;
|
const bool allow_retry = new_fuzziness - 1e-15 <= settings.precision * 10000. && new_fuzziness < min_length_orig;
|
||||||
@@ -1048,7 +1048,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_extrusion_a) {
|
if (is_extrusion_a) {
|
||||||
::logger::root().notice("GEO", 136, "Operand A 1/1 is an extrusion");
|
settings.log().notice("GEO", 136, "Operand A 1/1 is an extrusion");
|
||||||
|
|
||||||
NCollection_List<TopoDS_Shape>::Iterator it(b);
|
NCollection_List<TopoDS_Shape>::Iterator it(b);
|
||||||
for (int nb = 1; it.More(); it.Next(), ++nb) {
|
for (int nb = 1; it.More(); it.Next(), ++nb) {
|
||||||
@@ -1064,10 +1064,10 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_extrusion_b) {
|
if (is_extrusion_b) {
|
||||||
::logger::root().notice("GEO", 137, "Operand B " + std::to_string(nb) + "/" + std::to_string(b.Extent()) + " is an extrusion");
|
settings.log().notice("GEO", 137, "Operand B " + std::to_string(nb) + "/" + std::to_string(b.Extent()) + " is an extrusion");
|
||||||
|
|
||||||
if (b_interval.first < a_interval.first + (fuzz * 100.) && b_interval.second > a_interval.second - (fuzz * 100.)) {
|
if (b_interval.first < a_interval.first + (fuzz * 100.) && b_interval.second > a_interval.second - (fuzz * 100.)) {
|
||||||
::logger::root().notice("GEO", 138, "Operand B creates a through hole");
|
settings.log().notice("GEO", 138, "Operand B creates a through hole");
|
||||||
|
|
||||||
// Align b with a operand
|
// Align b with a operand
|
||||||
gp_Trsf trsf;
|
gp_Trsf trsf;
|
||||||
@@ -1091,7 +1091,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
PERF("boolean operation: 2d builder");
|
PERF("boolean operation: 2d builder");
|
||||||
// First try using face builder
|
// First try using face builder
|
||||||
|
|
||||||
boolean_op_2d_success = boolean_subtraction_2d_using_builder(a_face, b_faces, face_result, fuzziness);
|
boolean_op_2d_success = boolean_subtraction_2d_using_builder(a_face, b_faces, face_result, fuzziness, settings.log());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!boolean_op_2d_success) {
|
if (!boolean_op_2d_success) {
|
||||||
@@ -1107,23 +1107,23 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
BRepPrimAPI_MakePrism mp(face_result, gp_Vec(gp::DY()) * (a_interval.second - a_interval.first));
|
BRepPrimAPI_MakePrism mp(face_result, gp_Vec(gp::DY()) * (a_interval.second - a_interval.first));
|
||||||
if (mp.IsDone()) {
|
if (mp.IsDone()) {
|
||||||
if (b_remainder_3d.Extent()) {
|
if (b_remainder_3d.Extent()) {
|
||||||
::logger::root().notice("GEO", 139, std::to_string(b_remainder_3d.Extent()) + " operands remaining to process in 3D");
|
settings.log().notice("GEO", 139, std::to_string(b_remainder_3d.Extent()) + " operands remaining to process in 3D");
|
||||||
b = b_remainder_3d;
|
b = b_remainder_3d;
|
||||||
s1s.Clear();
|
s1s.Clear();
|
||||||
s1s.Append(mp.Shape());
|
s1s.Append(mp.Shape());
|
||||||
} else {
|
} else {
|
||||||
::logger::root().notice("GEO", 140, "Processed fully in 2D");
|
settings.log().notice("GEO", 140, "Processed fully in 2D");
|
||||||
result = mp.Shape();
|
result = mp.Shape();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
::logger::root().notice("GEO", 141, "Failed to extrude 2D boolean result. Retrying in 3D.");
|
settings.log().notice("GEO", 141, "Failed to extrude 2D boolean result. Retrying in 3D.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
::logger::root().notice("GEO", 142, "Failed to perform 2D boolean operation. Retrying in 3D.");
|
settings.log().notice("GEO", 142, "Failed to perform 2D boolean operation. Retrying in 3D.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
::logger::root().notice("GEO", 143, "No second operands can be processed as 2D inner bounds. Retrying in 3D.");
|
settings.log().notice("GEO", 143, "No second operands can be processed as 2D inner bounds. Retrying in 3D.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1145,7 +1145,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
}
|
}
|
||||||
if (builder->IsDone()) {
|
if (builder->IsDone()) {
|
||||||
if (false && builder->DSFiller()->HasWarning(STANDARD_TYPE(BOPAlgo_AlertAcquiredSelfIntersection))) {
|
if (false && builder->DSFiller()->HasWarning(STANDARD_TYPE(BOPAlgo_AlertAcquiredSelfIntersection))) {
|
||||||
::logger::root().notice("GEO", 144, "Builder reports self-intersection in output");
|
settings.log().notice("GEO", 144, "Builder reports self-intersection in output");
|
||||||
success = false;
|
success = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1159,7 +1159,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
} else if(builder->DSFiller()->HasWarning(STANDARD_TYPE(BOPAlgo_AlertBadPositioning)) && !TopoDS_Iterator(*builder).More()) {
|
} else if(builder->DSFiller()->HasWarning(STANDARD_TYPE(BOPAlgo_AlertBadPositioning)) && !TopoDS_Iterator(*builder).More()) {
|
||||||
::logger::root().notice("GEO", 145, "Builder reports bad positioning and result is empty");
|
settings.log().notice("GEO", 145, "Builder reports bad positioning and result is empty");
|
||||||
success = false;
|
success = false;
|
||||||
} else {
|
} else {
|
||||||
TopoDS_Shape r = *builder;
|
TopoDS_Shape r = *builder;
|
||||||
@@ -1173,7 +1173,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
fix.Perform();
|
fix.Perform();
|
||||||
r = fix.Shape();
|
r = fix.Shape();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
::logger::root().error("GEO", 146, "Shape healing failed on boolean result");
|
settings.log().error("GEO", 146, "Shape healing failed on boolean result");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1184,7 +1184,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
success = ana.IsValid() != 0;
|
success = ana.IsValid() != 0;
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
::logger::root().notice("GEO", 147, "Boolean operation yields invalid result");
|
settings.log().notice("GEO", 147, "Boolean operation yields invalid result");
|
||||||
|
|
||||||
std::stringstream str;
|
std::stringstream str;
|
||||||
bool any_emitted = false;
|
bool any_emitted = false;
|
||||||
@@ -1214,7 +1214,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
|
|
||||||
dump(r);
|
dump(r);
|
||||||
|
|
||||||
::logger::root().notice("GEO", 148, str.str());
|
settings.log().notice("GEO", 148, str.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1334,7 +1334,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
|
|
||||||
if (op == BOPAlgo_CUT && has_open_shells && all_faces_included_in_result && result_n_faces > first_op_n_faces) {
|
if (op == BOPAlgo_CUT && has_open_shells && all_faces_included_in_result && result_n_faces > first_op_n_faces) {
|
||||||
success = false;
|
success = false;
|
||||||
::logger::root().notice("GEO", 149, "Boolean result discarded because subtractions results in only the addition of faces");
|
settings.log().notice("GEO", 149, "Boolean result discarded because subtractions results in only the addition of faces");
|
||||||
} else {
|
} else {
|
||||||
// when there are edges or vertex-edge distances close to the used fuzziness, the
|
// when there are edges or vertex-edge distances close to the used fuzziness, the
|
||||||
// output is not trusted and the operation is attempted with a higher fuzziness.
|
// output is not trusted and the operation is attempted with a higher fuzziness.
|
||||||
@@ -1380,7 +1380,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
static const char* const reason_strings[] = { "edge length", "vertex-edge", "face-face" };
|
static const char* const reason_strings[] = { "edge length", "vertex-edge", "face-face" };
|
||||||
std::stringstream str;
|
std::stringstream str;
|
||||||
str << "Boolean operation result failing " << reason_strings[reason] << " interference check, with fuzziness " << fuzziness << " with length " << v;
|
str << "Boolean operation result failing " << reason_strings[reason] << " interference check, with fuzziness " << fuzziness << " with length " << v;
|
||||||
::logger::root().notice("GEO", 150, str.str());
|
settings.log().notice("GEO", 150, str.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1389,7 +1389,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
::logger::root().notice("GEO", 151, "Boolean operation yields non-manifold result");
|
settings.log().notice("GEO", 151, "Boolean operation yields non-manifold result");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1399,7 +1399,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
#if OCC_VERSION_HEX >= 0x70200
|
#if OCC_VERSION_HEX >= 0x70200
|
||||||
|
|
||||||
if (builder->HasError(STANDARD_TYPE(BOPAlgo_AlertBOPNotAllowed))) {
|
if (builder->HasError(STANDARD_TYPE(BOPAlgo_AlertBOPNotAllowed))) {
|
||||||
::logger::root().error("GEO", 152, "Invalid operands. Using first operand");
|
settings.log().error("GEO", 152, "Invalid operands. Using first operand");
|
||||||
result = a;
|
result = a;
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
@@ -1412,14 +1412,14 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
|||||||
#endif
|
#endif
|
||||||
std::string str_str = str.str();
|
std::string str_str = str.str();
|
||||||
if (str_str.size()) {
|
if (str_str.size()) {
|
||||||
::logger::root().notice("GEO", 153, str_str);
|
settings.log().notice("GEO", 153, str_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!success) {
|
if (!success) {
|
||||||
if (allow_retry) {
|
if (allow_retry) {
|
||||||
return boolean_operation(settings, a, b, op, result, new_fuzziness);
|
return boolean_operation(settings, a, b, op, result, new_fuzziness);
|
||||||
} else {
|
} else {
|
||||||
::logger::root().notice("GEO", 154, "No longer attempting boolean operation with higher fuzziness");
|
settings.log().notice("GEO", 154, "No longer attempting boolean operation with higher fuzziness");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return success && !result.IsNull();
|
return success && !result.IsNull();
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#include <BOPAlgo_Operation.hxx>
|
#include <BOPAlgo_Operation.hxx>
|
||||||
|
|
||||||
|
#include "../../../ifcparse/logger.h"
|
||||||
#include "../ifc_geomlibrary_api.h"
|
#include "../ifc_geomlibrary_api.h"
|
||||||
|
|
||||||
namespace IfcGeom {
|
namespace IfcGeom {
|
||||||
@@ -88,13 +89,17 @@ namespace IfcGeom {
|
|||||||
|
|
||||||
IFC_GEOMLIBRARY_API int eliminate_touching_operands(double prec, const TopoDS_Shape& a, const NCollection_List<TopoDS_Shape>& bs, NCollection_List<TopoDS_Shape>& c);
|
IFC_GEOMLIBRARY_API int eliminate_touching_operands(double prec, const TopoDS_Shape& a, const NCollection_List<TopoDS_Shape>& bs, NCollection_List<TopoDS_Shape>& c);
|
||||||
|
|
||||||
IFC_GEOMLIBRARY_API int eliminate_narrow_operands(double prec, const NCollection_List<TopoDS_Shape>& bs, NCollection_List<TopoDS_Shape> & c);
|
IFC_GEOMLIBRARY_API int eliminate_narrow_operands(double prec, const NCollection_List<TopoDS_Shape>& bs, NCollection_List<TopoDS_Shape> & c, ::logger& logger = ::logger::root());
|
||||||
|
|
||||||
IFC_GEOMLIBRARY_API bool boolean_subtraction_2d_using_builder(const TopoDS_Shape& a_input, const NCollection_List<TopoDS_Shape>& b_input, TopoDS_Shape& result, double eps);
|
IFC_GEOMLIBRARY_API bool boolean_subtraction_2d_using_builder(const TopoDS_Shape& a_input, const NCollection_List<TopoDS_Shape>& b_input, TopoDS_Shape& result, double eps, ::logger& logger = ::logger::root());
|
||||||
|
|
||||||
struct boolean_settings {
|
struct boolean_settings {
|
||||||
bool debug, attempt_2d;
|
bool debug, attempt_2d;
|
||||||
double precision;
|
double precision;
|
||||||
|
// Set by callers that carry a per-conversion logger (e.g. kernels deriving
|
||||||
|
// from AbstractKernel). Falls back to the global ::logger::root() singleton.
|
||||||
|
::logger* logger = nullptr;
|
||||||
|
::logger& log() const { return logger ? *logger : ::logger::root(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
IFC_GEOMLIBRARY_API bool boolean_operation(const boolean_settings& settings, const TopoDS_Shape&, const NCollection_List<TopoDS_Shape>&, BOPAlgo_Operation, TopoDS_Shape&, double fuzziness = -1.);
|
IFC_GEOMLIBRARY_API bool boolean_operation(const boolean_settings& settings, const TopoDS_Shape&, const NCollection_List<TopoDS_Shape>&, BOPAlgo_Operation, TopoDS_Shape&, double fuzziness = -1.);
|
||||||
|
|||||||
Reference in New Issue
Block a user