PartDesign, Transformed features: Improved intersection check
This commit is contained in:
parent
1c158ef924
commit
32628462c2
|
@ -27,14 +27,16 @@
|
||||||
# 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_Common.hxx>
|
||||||
# include <TopTools_ListIteratorOfListOfShape.hxx>
|
# include <TopTools_ListIteratorOfListOfShape.hxx>
|
||||||
# include <TopExp.hxx>
|
# include <TopExp.hxx>
|
||||||
# include <TopTools_IndexedMapOfShape.hxx>
|
# include <TopTools_IndexedMapOfShape.hxx>
|
||||||
# include <Standard_Failure.hxx>
|
# include <Standard_Failure.hxx>
|
||||||
// includes for findAllFacesCutBy()
|
|
||||||
# include <TopoDS_Face.hxx>
|
# include <TopoDS_Face.hxx>
|
||||||
# include <gp_Dir.hxx>
|
# include <gp_Dir.hxx>
|
||||||
# include <gp_Pln.hxx> // for Precision::Confusion()
|
# include <gp_Pln.hxx> // for Precision::Confusion()
|
||||||
|
# include <Bnd_Box.hxx>
|
||||||
|
# include <BRepBndLib.hxx>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -333,3 +335,34 @@ 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) {
|
||||||
|
Bnd_Box first_bb, second_bb;
|
||||||
|
BRepBndLib::Add(first, first_bb);
|
||||||
|
first_bb.SetGap(0);
|
||||||
|
BRepBndLib::Add(second, second_bb);
|
||||||
|
second_bb.SetGap(0);
|
||||||
|
|
||||||
|
// Note: Both tests fail if the objects are touching one another at zero distance!
|
||||||
|
if (first_bb.IsOut(second_bb))
|
||||||
|
return false; // no intersection
|
||||||
|
//if (first_bb.Distance(second_bb) > Precision::Confusion())
|
||||||
|
// return false;
|
||||||
|
if (quick)
|
||||||
|
return true; // assumed intersection
|
||||||
|
|
||||||
|
// Try harder
|
||||||
|
BRepAlgoAPI_Common mkCommon(first, second);
|
||||||
|
// FIXME: Error in boolean operation, return true by default
|
||||||
|
if (!mkCommon.IsDone())
|
||||||
|
return true;
|
||||||
|
if (mkCommon.Shape().IsNull())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
TopExp_Explorer xp;
|
||||||
|
xp.Init(mkCommon.Shape(),TopAbs_SOLID);
|
||||||
|
if (xp.More())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -135,6 +135,16 @@ PartExport
|
||||||
std::vector<cutFaces> findAllFacesCutBy(const TopoDS_Shape& shape,
|
std::vector<cutFaces> findAllFacesCutBy(const TopoDS_Shape& shape,
|
||||||
const TopoDS_Shape& face, const gp_Dir& dir);
|
const TopoDS_Shape& face, const gp_Dir& dir);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for intersection between the two shapes. Only solids are guaranteed to work properly
|
||||||
|
* There are two modes:
|
||||||
|
* 1. Bounding box check only - quick but inaccurate
|
||||||
|
* 2. Bounding box check plus (if necessary) boolean operation - costly but accurate
|
||||||
|
* Return true if the shapes intersect, false if they don't
|
||||||
|
*/
|
||||||
|
PartExport
|
||||||
|
const bool checkIntersection(const TopoDS_Shape& first, const TopoDS_Shape& second, const bool quick = true);
|
||||||
|
|
||||||
} //namespace Part
|
} //namespace Part
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,6 @@
|
||||||
# include <TopExp.hxx>
|
# include <TopExp.hxx>
|
||||||
# include <TopExp_Explorer.hxx>
|
# include <TopExp_Explorer.hxx>
|
||||||
# include <TopTools_IndexedMapOfShape.hxx>
|
# include <TopTools_IndexedMapOfShape.hxx>
|
||||||
# include <Bnd_Box.hxx>
|
|
||||||
# include <BRepBndLib.hxx>
|
|
||||||
# include <Precision.hxx>
|
# include <Precision.hxx>
|
||||||
# include <BRepBuilderAPI_Copy.hxx>
|
# include <BRepBuilderAPI_Copy.hxx>
|
||||||
#endif
|
#endif
|
||||||
|
@ -114,10 +112,6 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
|
||||||
supportShape.setTransform(Base::Matrix4D());
|
supportShape.setTransform(Base::Matrix4D());
|
||||||
TopoDS_Shape support = supportShape._Shape;
|
TopoDS_Shape support = supportShape._Shape;
|
||||||
|
|
||||||
// Prepare a bounding box for intersection tests
|
|
||||||
Bnd_Box support_bb;
|
|
||||||
BRepBndLib::Add(support, support_bb);
|
|
||||||
|
|
||||||
// NOTE: It would be possible to build a compound from all original addShapes/subShapes and then
|
// NOTE: It would be possible to build a compound from all original addShapes/subShapes and then
|
||||||
// transform the compounds as a whole. But we choose to apply the transformations to each
|
// transform the compounds as a whole. But we choose to apply the transformations to each
|
||||||
// Original separately. This way it is easier to discover what feature causes a fuse/cut
|
// Original separately. This way it is easier to discover what feature causes a fuse/cut
|
||||||
|
@ -162,9 +156,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
|
||||||
Bnd_Box transformed_bb;
|
if (!Part::checkIntersection(support, mkTrf.Shape(), false)) {
|
||||||
BRepBndLib::Add(mkTrf.Shape(), transformed_bb);
|
|
||||||
if (support_bb.Distance(transformed_bb) > Precision::Confusion()) {
|
|
||||||
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. If we remove here,
|
// Note: The removal happens in getSolid() after the fuse. If we remove here,
|
||||||
// the histories get messed up and we get a crash
|
// the histories get messed up and we get a crash
|
||||||
|
@ -193,11 +185,6 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for intersection of the original and the transformed shape
|
// Check for intersection of the original and the transformed shape
|
||||||
// Note: For performance reasons, we only check for intersection of bounding boxes
|
|
||||||
Bnd_Box original_bb;
|
|
||||||
BRepBndLib::Add(shape, original_bb);
|
|
||||||
original_bb.SetGap(0);
|
|
||||||
|
|
||||||
for (std::vector<TopoDS_Shape>::const_iterator s = v_transformedShapes.begin(); s != v_transformedShapes.end(); s++)
|
for (std::vector<TopoDS_Shape>::const_iterator s = v_transformedShapes.begin(); s != v_transformedShapes.end(); s++)
|
||||||
{
|
{
|
||||||
// If there is only one transformed feature, this check is not necessary (though it might seem
|
// If there is only one transformed feature, this check is not necessary (though it might seem
|
||||||
|
@ -205,12 +192,7 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
|
||||||
if (v_transformedShapes.size() == 1)
|
if (v_transformedShapes.size() == 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
Bnd_Box transformed_bb;
|
if (Part::checkIntersection(shape, *s, false))
|
||||||
BRepBndLib::Add(*s, transformed_bb);
|
|
||||||
transformed_bb.SetGap(0);
|
|
||||||
if (!original_bb.IsOut(transformed_bb))
|
|
||||||
// if (original_bb.Distance(transformed_bb) < Precision::Confusion())
|
|
||||||
// FIXME: Both tests fail if the objects are touching one another at zero distance
|
|
||||||
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
|
||||||
|
@ -220,6 +202,14 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
|
||||||
// features might overlap, even if the original and the first shape don't overlap!
|
// features might overlap, even if the original and the first shape don't overlap!
|
||||||
if (this->getTypeId() != PartDesign::MultiTransform::getClassTypeId())
|
if (this->getTypeId() != PartDesign::MultiTransform::getClassTypeId())
|
||||||
break;
|
break;
|
||||||
|
else {
|
||||||
|
// Check intersection with all other transformed shapes as well
|
||||||
|
std::vector<TopoDS_Shape>::const_iterator s2 = s;
|
||||||
|
s2++;
|
||||||
|
for (; s2 != v_transformedShapes.end(); s2++)
|
||||||
|
if (Part::checkIntersection(*s, *s2, false))
|
||||||
|
return new App::DocumentObjectExecReturn("Transformed objects are overlapping, try using a higher length or reducing the number of occurrences", (*o));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fuse/Cut the compounded transformed shapes with the support
|
// Fuse/Cut the compounded transformed shapes with the support
|
||||||
|
|
Loading…
Reference in New Issue
Block a user