From 0e5b6cb443294ea0ee25c530b9482d01879fc13a Mon Sep 17 00:00:00 2001 From: Sam Mason Date: Tue, 1 Feb 2022 10:32:14 +0000 Subject: [PATCH] record shapes with negative intersecting volume as touching after sleeping on my change last night, this seems like the least bad solution. at least until this gets fixed in OCCT! this limit of 10% is debatable, in practice I've only seen volumes of smaller than 0.1% so should be generous. --- src/geometry.cpp | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/geometry.cpp b/src/geometry.cpp index 3ecbed6..57f9bec 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -333,16 +334,10 @@ intersect_result classify_solid_intersection( TopExp_Explorer ex; ex.Init(op.Shape(), TopAbs_SOLID); if (ex.More()) { - // we expect the common volume to occasionally come back negative. - // OCCT appears to do this when the two solids have faces that are - // within the given tolerance/fuzzy value + // OCCT (version 7.5) appears to occasionally come back with a + // negative volume. it appears to do this when the two solids have + // non-trivial faces that are within the given tolerance/fuzzy value result.vol_common = volume_of_shape_maybe_neg(op.Shape()); - if (result.vol_common < 0) { - // returning failed here should cause the overlap checker will - // retry with a stricter tolerance, which tends to cause this - // error to disappear! - return result; - } op.SetOperation(BOPAlgo_CUT); op.Build(); @@ -358,7 +353,25 @@ intersect_result classify_solid_intersection( } result.vol_cut12 = volume_of_shape(op.Shape()); - result.status = intersect_status::overlap; + if (result.vol_common < 0) { + // ensure the this negative volume is "small", relative to the + // input shapes, as we only expect this to happen along the + // boundary of shapes + const double limit = std::min(result.vol_cut, result.vol_cut12) * 0.1; + if (-result.vol_common < limit) { + throw std::runtime_error("negative volume too large"); + } + + // until this is fixed upstream in OCCT, recording them as + // touching seems to be best. an alternative would be to fail, and + // let the caller retry with stricter tolerance (which tends to + // succeed). touching seems best as we later steps want to know + // which solids are close to each other and therefore need to + // considered during merging + result.status = intersect_status::touching; + } else { + result.status = intersect_status::overlap; + } return result; }