Re-worked Part::checkIntersection to give less false positives for pattern features

This commit is contained in:
jrheinlaender 2013-01-18 16:43:41 +04:30 committed by logari81
parent 5df7f2db88
commit 18da371546
3 changed files with 46 additions and 20 deletions

View File

@ -27,6 +27,7 @@
# include <gp_Trsf.hxx> # include <gp_Trsf.hxx>
# include <gp_Ax1.hxx> # include <gp_Ax1.hxx>
# include <BRepBuilderAPI_MakeShape.hxx> # include <BRepBuilderAPI_MakeShape.hxx>
# include <BRepAlgoAPI_Fuse.hxx>
# include <BRepAlgoAPI_Common.hxx> # include <BRepAlgoAPI_Common.hxx>
# include <TopTools_ListIteratorOfListOfShape.hxx> # include <TopTools_ListIteratorOfListOfShape.hxx>
# include <TopExp.hxx> # include <TopExp.hxx>
@ -336,33 +337,50 @@ std::vector<Part::cutFaces> Part::findAllFacesCutBy(
return result; return result;
} }
const bool Part::checkIntersection(const TopoDS_Shape& first, const TopoDS_Shape& second, const bool quick) { const bool Part::checkIntersection(const TopoDS_Shape& first, const TopoDS_Shape& second,
const bool quick, const bool touch_is_intersection) {
Bnd_Box first_bb, second_bb; Bnd_Box first_bb, second_bb;
BRepBndLib::Add(first, first_bb); BRepBndLib::Add(first, first_bb);
first_bb.SetGap(0); first_bb.SetGap(0);
BRepBndLib::Add(second, second_bb); BRepBndLib::Add(second, second_bb);
second_bb.SetGap(0); second_bb.SetGap(0);
// Note: Both tests fail if the objects are touching one another at zero distance! // Note: This test fails if the objects are touching one another at zero distance
if (first_bb.IsOut(second_bb)) if (first_bb.IsOut(second_bb))
return false; // no intersection return false; // no intersection
//if (first_bb.Distance(second_bb) > Precision::Confusion())
// return false;
if (quick) if (quick)
return true; // assumed intersection return true; // assumed intersection
// Try harder // Try harder
BRepAlgoAPI_Common mkCommon(first, second); if (touch_is_intersection) {
// FIXME: Error in boolean operation, return true by default // If both shapes fuse to a single solid, then they intersect
if (!mkCommon.IsDone()) BRepAlgoAPI_Fuse mkFuse(first, second);
return true; if (!mkFuse.IsDone())
if (mkCommon.Shape().IsNull()) return false;
return true; if (mkFuse.Shape().IsNull())
return false;
TopExp_Explorer xp; // Did we get one or two solids?
xp.Init(mkCommon.Shape(),TopAbs_SOLID); TopExp_Explorer xp;
if (xp.More()) xp.Init(mkFuse.Shape(),TopAbs_SOLID);
return true; if (xp.More()) {
// At least one solid
xp.Next();
return (xp.More() == Standard_False);
} else {
return false;
}
} else {
// If both shapes have common material, then they intersect
BRepAlgoAPI_Common mkCommon(first, second);
if (!mkCommon.IsDone())
return false;
if (mkCommon.Shape().IsNull())
return false;
return false; // Did we get a solid?
TopExp_Explorer xp;
xp.Init(mkCommon.Shape(),TopAbs_SOLID);
return (xp.More() == Standard_True);
}
} }

View File

@ -141,9 +141,17 @@ std::vector<cutFaces> findAllFacesCutBy(const TopoDS_Shape& shape,
* 1. Bounding box check only - quick but inaccurate * 1. Bounding box check only - quick but inaccurate
* 2. Bounding box check plus (if necessary) boolean operation - costly but accurate * 2. Bounding box check plus (if necessary) boolean operation - costly but accurate
* Return true if the shapes intersect, false if they don't * Return true if the shapes intersect, false if they don't
* The flag touch_is_intersection decides whether shapes touching at distance zero are regarded
* as intersecting or not
* 1. If set to true, a true check result means that a boolean fuse operation between the two shapes
* will return a single solid
* 2. If set to false, a true check result means that a boolean common operation will return a
* valid solid
* If there is any error in the boolean operations, the check always returns false
*/ */
PartExport PartExport
const bool checkIntersection(const TopoDS_Shape& first, const TopoDS_Shape& second, const bool quick = true); const bool checkIntersection(const TopoDS_Shape& first, const TopoDS_Shape& second,
const bool quick, const bool touch_is_intersection);
} //namespace Part } //namespace Part

View File

@ -170,7 +170,7 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
return new App::DocumentObjectExecReturn("Transformation failed", (*o)); return new App::DocumentObjectExecReturn("Transformation failed", (*o));
// Check for intersection with support // Check for intersection with support
if (!Part::checkIntersection(support, mkTrf.Shape(), false)) { if (!Part::checkIntersection(support, mkTrf.Shape(), false, true)) {
Base::Console().Warning("Transformed shape does not intersect support %s: Removed\n", (*o)->getNameInDocument()); Base::Console().Warning("Transformed shape does not intersect support %s: Removed\n", (*o)->getNameInDocument());
// Note: The removal happens in getSolid() after the fuse // Note: The removal happens in getSolid() after the fuse
rejected.push_back(*t); rejected.push_back(*t);
@ -203,7 +203,7 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
if (v_transformedShapes.size() == 1) if (v_transformedShapes.size() == 1)
break; break;
if (Part::checkIntersection(shape, *s, false)) if (Part::checkIntersection(shape, *s, false, false))
return new App::DocumentObjectExecReturn("Transformed objects are overlapping, try using a higher length or reducing the number of occurrences", (*o)); return new App::DocumentObjectExecReturn("Transformed objects are overlapping, try using a higher length or reducing the number of occurrences", (*o));
// Note: This limitation could be overcome by fusing the transformed features instead of // Note: This limitation could be overcome by fusing the transformed features instead of
// compounding them, probably at the expense of quite a bit of performance and complexity // compounding them, probably at the expense of quite a bit of performance and complexity
@ -218,7 +218,7 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
std::vector<TopoDS_Shape>::const_iterator s2 = s; std::vector<TopoDS_Shape>::const_iterator s2 = s;
s2++; s2++;
for (; s2 != v_transformedShapes.end(); s2++) for (; s2 != v_transformedShapes.end(); s2++)
if (Part::checkIntersection(*s, *s2, false)) if (Part::checkIntersection(*s, *s2, false, false))
return new App::DocumentObjectExecReturn("Transformed objects are overlapping, try using a higher length or reducing the number of occurrences", (*o)); return new App::DocumentObjectExecReturn("Transformed objects are overlapping, try using a higher length or reducing the number of occurrences", (*o));
} }
} }