PartDesign: Show overlapping transformations as rejected
This commit is contained in:
parent
62dc05ffd9
commit
8235008ae7
|
@ -98,9 +98,10 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
|
|||
this->positionBySupport();
|
||||
|
||||
// get transformations from subclass by calling virtual method
|
||||
std::list<gp_Trsf> transformations;
|
||||
std::vector<gp_Trsf> transformations;
|
||||
try {
|
||||
transformations = getTransformations(originals);
|
||||
std::list<gp_Trsf> t_list = getTransformations(originals);
|
||||
transformations.insert(transformations.end(), t_list.begin(), t_list.end());
|
||||
} catch (Base::Exception& e) {
|
||||
return new App::DocumentObjectExecReturn(e.what());
|
||||
}
|
||||
|
@ -122,6 +123,9 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
|
|||
supportShape.setTransform(Base::Matrix4D());
|
||||
TopoDS_Shape support = supportShape._Shape;
|
||||
|
||||
std::set<std::vector<gp_Trsf>::const_iterator> nointersect_trsfms;
|
||||
std::set<std::vector<gp_Trsf>::const_iterator> overlapping_trsfms;
|
||||
|
||||
// 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
|
||||
// Original separately. This way it is easier to discover what feature causes a fuse/cut
|
||||
|
@ -129,6 +133,7 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
|
|||
// safe to assume that in most cases there are few originals and many transformations
|
||||
for (std::vector<App::DocumentObject*>::const_iterator o = originals.begin(); o != originals.end(); o++)
|
||||
{
|
||||
// Extract the original shape and determine whether to cut or to fuse
|
||||
TopoDS_Shape shape;
|
||||
bool fuse;
|
||||
|
||||
|
@ -148,16 +153,13 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
|
|||
return new App::DocumentObjectExecReturn("Only additive and subtractive features can be transformed");
|
||||
}
|
||||
|
||||
// Transform the add/subshape and build a compound from the transformations,
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound transformedShapes;
|
||||
builder.MakeCompound(transformedShapes);
|
||||
std::vector<TopoDS_Shape> v_transformedShapes; // collect all the transformed shapes for intersection testing
|
||||
std::list<gp_Trsf>::const_iterator t = transformations.begin();
|
||||
t++; // Skip first transformation, which is always the identity transformation
|
||||
// Transform the add/subshape and collect the resulting shapes for overlap testing
|
||||
std::vector<std::vector<gp_Trsf>::const_iterator> v_transformations;
|
||||
std::vector<TopoDS_Shape> v_transformedShapes;
|
||||
|
||||
for (; t != transformations.end(); t++)
|
||||
{
|
||||
std::vector<gp_Trsf>::const_iterator t = transformations.begin();
|
||||
t++; // Skip first transformation, which is always the identity transformation
|
||||
for (; t != transformations.end(); t++) {
|
||||
// Make an explicit copy of the shape because the "true" parameter to BRepBuilderAPI_Transform
|
||||
// seems to be pretty broken
|
||||
BRepBuilderAPI_Copy copy(shape);
|
||||
|
@ -172,57 +174,81 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
|
|||
// Check for intersection with support
|
||||
if (!Part::checkIntersection(support, mkTrf.Shape(), false, true)) {
|
||||
Base::Console().Warning("Transformed shape does not intersect support %s: Removed\n", (*o)->getNameInDocument());
|
||||
// Note: The removal happens in getSolid() after the fuse
|
||||
rejected.push_back(*t);
|
||||
nointersect_trsfms.insert(t);
|
||||
} else {
|
||||
v_transformations.push_back(t);
|
||||
v_transformedShapes.push_back(mkTrf.Shape());
|
||||
// Note: Transformations that do not intersect the support are ignored in the overlap tests
|
||||
}
|
||||
builder.Add(transformedShapes, mkTrf.Shape());
|
||||
v_transformedShapes.push_back(mkTrf.Shape());
|
||||
|
||||
/*
|
||||
// Note: This method is only stable for Linear and Polar transformations. No need to
|
||||
// make an explicit copy of the shape, either
|
||||
TopoDS_Shape trfShape = shape.Moved(TopLoc_Location(*t));
|
||||
|
||||
// Check for intersection with support
|
||||
Bnd_Box transformed_bb;
|
||||
BRepBndLib::Add(trfShape, transformed_bb);
|
||||
if (support_bb.Distance(transformed_bb) > Precision::Confusion()) {
|
||||
Base::Console().Warning("Transformed shape does not intersect support %s: Removed\n", (*o)->getNameInDocument());
|
||||
// Note: The removal happens in getSolid() after the fuse
|
||||
}
|
||||
builder.Add(transformedShapes, trfShape);
|
||||
v_transformedShapes.push_back(trfShape);
|
||||
*/
|
||||
}
|
||||
|
||||
// Check for intersection of the original and the transformed shape
|
||||
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
|
||||
// illogical to the user why we allow overlapping shapes in this case!
|
||||
if (v_transformedShapes.size() == 1)
|
||||
break;
|
||||
|
||||
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));
|
||||
// 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
|
||||
// in this code
|
||||
if (v_transformedShapes.empty())
|
||||
break; // Skip the overlap check and go on to next original
|
||||
|
||||
// Check for overlapping of the original and the transformed shapes, and remove the overlapping transformations
|
||||
if (this->getTypeId() != PartDesign::MultiTransform::getClassTypeId()) {
|
||||
// If there is only one transformed feature, we allow an overlap (though it might seem
|
||||
// illogical to the user why we allow overlapping shapes in this case!)
|
||||
if (v_transformedShapes.size() > 1)
|
||||
if (Part::checkIntersection(shape, v_transformedShapes.front(), false, false)) {
|
||||
// For single transformations, if one overlaps, all overlap, as long as we have uniform increments
|
||||
overlapping_trsfms.insert(v_transformations.begin(),v_transformations.end());
|
||||
v_transformedShapes.clear();
|
||||
}
|
||||
} else {
|
||||
// For MultiTransform, just checking the first transformed shape is not sufficient - any two
|
||||
// features might overlap, even if the original and the first shape don't overlap!
|
||||
if (this->getTypeId() != PartDesign::MultiTransform::getClassTypeId())
|
||||
break;
|
||||
else {
|
||||
// Check intersection with all other transformed shapes as well
|
||||
std::vector<TopoDS_Shape>::const_iterator s2 = s;
|
||||
|
||||
std::set<std::vector<TopoDS_Shape>::iterator> rejected_iterators;
|
||||
|
||||
std::vector<TopoDS_Shape>::iterator s1 = v_transformedShapes.begin();
|
||||
std::vector<TopoDS_Shape>::iterator s2 = s1;
|
||||
s2++;
|
||||
std::vector<std::vector<gp_Trsf>::const_iterator>::const_iterator t1 = v_transformations.begin();
|
||||
std::vector<std::vector<gp_Trsf>::const_iterator>::const_iterator t2 = t1;
|
||||
t2++;
|
||||
for (; s2 != v_transformedShapes.end();) {
|
||||
// Check intersection with the original
|
||||
if (Part::checkIntersection(shape, *s1, false, false)) {
|
||||
rejected_iterators.insert(s1);
|
||||
overlapping_trsfms.insert(*t1);
|
||||
}
|
||||
// Check intersection with other transformations
|
||||
for (; s2 != v_transformedShapes.end(); s2++, t2++)
|
||||
if (Part::checkIntersection(*s1, *s2, false, false)) {
|
||||
rejected_iterators.insert(s1);
|
||||
rejected_iterators.insert(s2);
|
||||
overlapping_trsfms.insert(*t1);
|
||||
overlapping_trsfms.insert(*t2);
|
||||
}
|
||||
s1++;
|
||||
s2 = s1;
|
||||
s2++;
|
||||
for (; s2 != v_transformedShapes.end(); s2++)
|
||||
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));
|
||||
t1++;
|
||||
t2 = t1;
|
||||
t2++;
|
||||
}
|
||||
// Check intersection of last transformation with the original
|
||||
if (Part::checkIntersection(shape, *s1, false, false)) {
|
||||
rejected_iterators.insert(s1);
|
||||
overlapping_trsfms.insert(*t1);
|
||||
}
|
||||
|
||||
for (std::set<std::vector<TopoDS_Shape>::iterator>::reverse_iterator it = rejected_iterators.rbegin();
|
||||
it != rejected_iterators.rend(); it++)
|
||||
v_transformedShapes.erase(*it);
|
||||
}
|
||||
|
||||
if (v_transformedShapes.empty())
|
||||
break; // Skip the boolean operation and go on to next original
|
||||
|
||||
// Build a compound from all the valid transformations
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound transformedShapes;
|
||||
builder.MakeCompound(transformedShapes);
|
||||
for (std::vector<TopoDS_Shape>::const_iterator s = v_transformedShapes.begin(); s != v_transformedShapes.end(); s++)
|
||||
builder.Add(transformedShapes, *s);
|
||||
|
||||
// Fuse/Cut the compounded transformed shapes with the support
|
||||
TopoDS_Shape result;
|
||||
|
||||
|
@ -231,19 +257,10 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
|
|||
if (!mkFuse.IsDone())
|
||||
return new App::DocumentObjectExecReturn("Fusion with support failed", *o);
|
||||
// we have to get the solids (fuse sometimes creates compounds)
|
||||
// Note: Because getSolid() only returns the first solid in the explorer, all
|
||||
// solids that are outside the support automatically disappear!
|
||||
result = this->getSolid(mkFuse.Shape());
|
||||
// lets check if the result is a solid
|
||||
if (result.IsNull())
|
||||
return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o);
|
||||
// check if mkFuse created more than one solids
|
||||
TopExp_Explorer xp;
|
||||
xp.Init(mkFuse.Shape(),TopAbs_SOLID);
|
||||
if (xp.More())
|
||||
xp.Next();
|
||||
if (!xp.More()) // There are no rejected transformations even
|
||||
rejected.clear(); // if the bb check guessed that there would be
|
||||
} else {
|
||||
BRepAlgoAPI_Cut mkCut(support, transformedShapes);
|
||||
if (!mkCut.IsDone())
|
||||
|
@ -254,9 +271,24 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
|
|||
support = result; // Use result of this operation for fuse/cut of next original
|
||||
}
|
||||
|
||||
if (!overlapping_trsfms.empty())
|
||||
// Concentrate on overlapping shapes since they are more serious
|
||||
for (std::set<std::vector<gp_Trsf>::const_iterator>::const_iterator it = overlapping_trsfms.begin();
|
||||
it != overlapping_trsfms.end(); it++)
|
||||
rejected.push_back(**it);
|
||||
else
|
||||
for (std::set<std::vector<gp_Trsf>::const_iterator>::const_iterator it = nointersect_trsfms.begin();
|
||||
it != nointersect_trsfms.end(); it++)
|
||||
rejected.push_back(**it);
|
||||
|
||||
this->Shape.setValue(support);
|
||||
|
||||
return App::DocumentObject::StdReturn;
|
||||
if (!overlapping_trsfms.empty())
|
||||
return new App::DocumentObjectExecReturn("Transformed objects are overlapping, try using a higher length or reducing the number of occurrences");
|
||||
// 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
|
||||
// in this code
|
||||
else
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user