PartDesign: change feature DressUp behavior when used for pattern

Repurpose DressUp.SupportTransform property to define the following
behavior,

* When disabled (default), only the dressing will be used for patterning.

* When enabled, the additive/subtractive shape of the dressed base
  feature will be used for patterning. Any dressing that is not applied
  to the based feature will be ignored.

* If the dressing is applied to non-additive/subtractive feature, then
  only the dressing will be used for patterning.

New API FreatureAddSub::getAddSubShape() is added to account for the
fact that a dressing (e.g. a fillet) can be either additive or
subtractive, which means that a DressUP feature may contain both
additive and subtractive shapes.

FeatureTransformed is modified to perform both fusion and cut if
required.
This commit is contained in:
Zheng, Lei
2020-03-21 15:22:48 +08:00
committed by wmayer
parent 8b23d814f8
commit a045f58a85
6 changed files with 162 additions and 99 deletions

View File

@@ -256,15 +256,14 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
{
// Extract the original shape and determine whether to cut or to fuse
TopoDS_Shape shape;
bool fuse;
Part::TopoShape fuseShape;
Part::TopoShape cutShape;
if ((*o)->getTypeId().isDerivedFrom(PartDesign::FeatureAddSub::getClassTypeId())) {
PartDesign::FeatureAddSub* feature = static_cast<PartDesign::FeatureAddSub*>(*o);
shape = feature->AddSubShape.getShape().getShape();
if (shape.IsNull())
return new App::DocumentObjectExecReturn("Shape of additive feature is empty");
fuse = (feature->getAddSubType() == FeatureAddSub::Additive) ? true : false;
feature->getAddSubShape(fuseShape, cutShape);
if (fuseShape.isNull() && cutShape.isNull())
return new App::DocumentObjectExecReturn("Shape of addsub feature is empty");
}
else {
return new App::DocumentObjectExecReturn("Only additive and subtractive features can be transformed");
@@ -280,7 +279,7 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
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);
BRepBuilderAPI_Copy copy(fuseShape.isNull()?cutShape.getShape():fuseShape.getShape());
shape = copy.Shape();
if (shape.IsNull())
return new App::DocumentObjectExecReturn("Transformed: Linked shape object is empty");
@@ -289,15 +288,24 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
if (!mkTrf.IsDone())
return new App::DocumentObjectExecReturn("Transformation failed", (*o));
// Check for intersection with support
shape = mkTrf.Shape();
try {
// Intersection checking for additive shape is redundant.
// Because according to CheckIntersection() source code, it is
// implemented using fusion and counting of the resulting
// solid, which will be done in the following modeling step
// anyway.
//
// There is little reason for doing intersection checking on
// subtractive shape either, because it does not produce
// multiple solids.
//
// if (!Part::checkIntersection(support, mkTrf.Shape(), false, true)) {
if (!Part::checkIntersection(support, mkTrf.Shape(), false, true)) {
#ifdef FC_DEBUG // do not write this in release mode because a message appears already in the task view
Base::Console().Warning("Transformed shape does not intersect support %s: Removed\n", (*o)->getNameInDocument());
#endif
nointersect_trsfms[*o].insert(t);
} else {
TopoDS_Shape current = support;
if (!fuseShape.isNull()) {
// We cannot wait to fuse a transformation with the support until all the transformations are done,
// because the "support" potentially changes with every transformation, basically when checking intersection
// above you need:
@@ -310,7 +318,7 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
/*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
//insert scheme here.
@@ -320,48 +328,45 @@ App::DocumentObjectExecReturn *Transformed::execute(void)
// Fuse/Cut the compounded transformed shapes with the support
//TopoDS_Shape result;
TopoDS_Shape current = support;
if (fuse) {
BRepAlgoAPI_Fuse mkFuse(current, mkTrf.Shape());
if (!mkFuse.IsDone())
return new App::DocumentObjectExecReturn("Fusion with support failed", *o);
// we have to get the solids (fuse sometimes creates compounds)
current = this->getSolid(mkFuse.Shape());
// lets check if the result is a solid
if (current.IsNull())
return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o);
/*std::vector<TopoDS_Shape>::const_iterator individualIt;
for (individualIt = individualTools.begin(); individualIt != individualTools.end(); ++individualIt)
{
BRepAlgoAPI_Fuse mkFuse2(current, *individualIt);
if (!mkFuse2.IsDone())
return new App::DocumentObjectExecReturn("Fusion with support failed", *o);
// we have to get the solids (fuse sometimes creates compounds)
current = this->getSolid(mkFuse2.Shape());
// lets check if the result is a solid
if (current.IsNull())
return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o);
}*/
} else {
BRepAlgoAPI_Cut mkCut(current, mkTrf.Shape());
if (!mkCut.IsDone())
return new App::DocumentObjectExecReturn("Cut out of support failed", *o);
current = mkCut.Shape();
/*std::vector<TopoDS_Shape>::const_iterator individualIt;
for (individualIt = individualTools.begin(); individualIt != individualTools.end(); ++individualIt)
{
BRepAlgoAPI_Cut mkCut2(current, *individualIt);
if (!mkCut2.IsDone())
return new App::DocumentObjectExecReturn("Cut out of support failed", *o);
current = this->getSolid(mkCut2.Shape());
if (current.IsNull())
return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o);
}*/
BRepAlgoAPI_Fuse mkFuse(current, shape);
if (!mkFuse.IsDone())
return new App::DocumentObjectExecReturn("Fusion with support failed", *o);
if(Part::TopoShape(current).countSubShapes(TopAbs_SOLID)
!= Part::TopoShape(mkFuse.Shape()).countSubShapes(TopAbs_SOLID))
{
#ifdef FC_DEBUG // do not write this in release mode because a message appears already in the task view
Base::Console().Warning("Transformed shape does not intersect support %s: Removed\n", (*o)->getNameInDocument());
#endif
nointersect_trsfms[*o].insert(t);
continue;
}
// we have to get the solids (fuse sometimes creates compounds)
current = this->getSolid(mkFuse.Shape());
// lets check if the result is a solid
if (current.IsNull())
return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o);
if (!cutShape.isNull()) {
BRepBuilderAPI_Copy copy(cutShape.getShape());
shape = copy.Shape();
if (shape.IsNull())
return new App::DocumentObjectExecReturn("Transformed: Linked shape object is empty");
BRepBuilderAPI_Transform mkTrf(shape, *t, false); // No need to copy, now
if (!mkTrf.IsDone())
return new App::DocumentObjectExecReturn("Transformation failed", (*o));
shape = mkTrf.Shape();
}
support = current; // Use result of this operation for fuse/cut of next original
}
if (!cutShape.isNull()) {
BRepAlgoAPI_Cut mkCut(current, shape);
if (!mkCut.IsDone())
return new App::DocumentObjectExecReturn("Cut out of support failed", *o);
current = mkCut.Shape();
}
support = current; // Use result of this operation for fuse/cut of next original
} catch (Standard_Failure& e) {
// Note: Ignoring this failure is probably pointless because if the intersection check fails, the later
// fuse operation of the transformation result will also fail