Merge pull request #13411 from bgbsww/bgbsww-toponamingFeatureDressup10399

Toponaming/Part:  feature dressup and transform
This commit is contained in:
Chris Hennes
2024-04-14 17:22:00 -05:00
committed by GitHub
3 changed files with 124 additions and 3 deletions

View File

@@ -231,7 +231,11 @@ void DressUp::getAddSubShape(Part::TopoShape &addShape, Part::TopoShape &subShap
baseShape.move(base->getLocation().Inverted());
if (base->getAddSubType() == Additive) {
if(!baseShape.isNull() && baseShape.hasSubShape(TopAbs_SOLID))
#ifdef FC_USE_TNP_FIX
shapes.emplace_back(shape.makeElementCut(baseShape.getShape()));
#else
shapes.emplace_back(shape.cut(baseShape.getShape()));
#endif
else
shapes.push_back(shape);
} else {
@@ -241,22 +245,35 @@ void DressUp::getAddSubShape(Part::TopoShape &addShape, Part::TopoShape &subShap
// push an empty compound to indicate null additive shape
shapes.emplace_back(comp);
if(!baseShape.isNull() && baseShape.hasSubShape(TopAbs_SOLID))
#ifdef FC_USE_TNP_FIX
shapes.emplace_back(baseShape.makeElementCut(shape.getShape()));
#else
shapes.emplace_back(baseShape.cut(shape.getShape()));
#endif
else
shapes.push_back(shape);
}
} else {
baseShape = getBaseTopoShape();
baseShape.move(getLocation().Inverted());
#ifdef FC_USE_TNP_FIX
shapes.emplace_back(shape.makeElementCut(baseShape.getShape()));
shapes.emplace_back(baseShape.makeElementCut(shape.getShape()));
#else
shapes.emplace_back(shape.cut(baseShape.getShape()));
shapes.emplace_back(baseShape.cut(shape.getShape()));
#endif
}
// Make a compound to contain both additive and subtractive shape,
// bceause a dressing (e.g. a fillet) can either be additive or
// subtractive. And the dressup feature can contain mixture of both.
AddSubShape.setValue(Part::TopoShape().makeCompound(shapes));
#ifdef FC_USE_TNP_FIX
AddSubShape.setValue(Part::TopoShape().makeElementCompound(shapes));
#else
AddSubShape.setValue(Part::TopoShape().makeCompound(shapes));
#endif
} catch (Standard_Failure &e) {
FC_THROWM(Base::CADKernelError, "Failed to calculate AddSub shape: "
<< e.GetMessageString());
@@ -274,12 +291,12 @@ void DressUp::getAddSubShape(Part::TopoShape &addShape, Part::TopoShape &subShap
if(!count)
throw Part::NullShapeException("Null AddSub shape");
if(count) {
Part::TopoShape s = res.getSubShape(TopAbs_SHAPE, 1);
Part::TopoShape s = res.getSubTopoShape(TopAbs_SHAPE, 1);
if(!s.isNull() && s.hasSubShape(TopAbs_SOLID))
addShape = s;
}
if(count > 1) {
Part::TopoShape s = res.getSubShape(TopAbs_SHAPE, 2);
Part::TopoShape s = res.getSubTopoShape(TopAbs_SHAPE, 2);
if(!s.isNull() && s.hasSubShape(TopAbs_SOLID))
subShape = s;
}

View File

@@ -273,10 +273,18 @@ App::DocumentObjectExecReturn *Transformed::execute()
if (fuseShape.isNull() && cutShape.isNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Shape of additive/subtractive feature is empty"));
gp_Trsf trsf = feature->getLocation().Transformation().Multiplied(trsfInv);
#ifdef FC_USE_TNP_FIX
if (!fuseShape.isNull())
fuseShape = fuseShape.makeElementTransform(trsf);
if (!cutShape.isNull())
cutShape = cutShape.makeElementTransform(trsf);
#else
if (!fuseShape.isNull())
fuseShape = fuseShape.makeTransform(trsf);
if (!cutShape.isNull())
cutShape = cutShape.makeTransform(trsf);
#endif
}
else {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Only additive and subtractive features can be transformed"));

View File

@@ -627,6 +627,102 @@ class TestTopologicalNamingProblem(unittest.TestCase):
def testPartDesignElementMapSubHelix(self):
pass # TODO
def testPartDesignElementMapChamfer(self):
""" Test Chamfer ( and FeatureDressup )"""
# Arrange
body = self.Doc.addObject('PartDesign::Body', 'Body')
box = self.Doc.addObject('PartDesign::AdditiveBox', 'Box')
if body.Shape.ElementMapVersion == "": # Skip without element maps.
return
chamfer = self.Doc.addObject('PartDesign::Chamfer', 'Chamfer')
chamfer.Base = (box, ['Edge1',
'Edge2',
'Edge3',
'Edge4',
'Edge5',
'Edge6',
'Edge7',
'Edge8',
'Edge9',
'Edge10',
'Edge11',
'Edge12',
])
chamfer.Size = 1
chamfer.UseAllEdges = True
# Act / Assert
body.addObject(box)
body.addObject(chamfer)
self.Doc.recompute()
reverseMap = body.Shape.childShapes()[0].ElementReverseMap
faces = [name for name in reverseMap.keys() if name.startswith("Face")]
edges = [name for name in reverseMap.keys() if name.startswith("Edge")]
vertexes = [name for name in reverseMap.keys() if name.startswith("Vertex")]
self.assertEqual(len(body.Shape.childShapes()), 1)
self.assertEqual(body.Shape.childShapes()[0].ElementMapSize, 98)
self.assertEqual(len(reverseMap),98)
self.assertEqual(len(faces),26) # 6 Faces become 26 ( +8 + 2*6 )
self.assertEqual(len(edges),48) # 12 Edges become 48
self.assertEqual(len(vertexes),24) # 8 Vertices become 24
def testPartDesignElementMapFillet(self):
""" Test Fillet ( and FeatureDressup )"""
# Arrange
body = self.Doc.addObject('PartDesign::Body', 'Body')
box = self.Doc.addObject('PartDesign::AdditiveBox', 'Box')
if body.Shape.ElementMapVersion == "": # Skip without element maps.
return
fillet = self.Doc.addObject('PartDesign::Fillet', 'Fillet')
fillet.Base = (box, ['Edge1',
'Edge2',
'Edge3',
'Edge4',
'Edge5',
'Edge6',
'Edge7',
'Edge8',
'Edge9',
'Edge10',
'Edge11',
'Edge12',
])
# Act / Assert
body.addObject(box)
body.addObject(fillet)
self.Doc.recompute()
reverseMap = body.Shape.childShapes()[0].ElementReverseMap
faces = [name for name in reverseMap.keys() if name.startswith("Face")]
edges = [name for name in reverseMap.keys() if name.startswith("Edge")]
vertexes = [name for name in reverseMap.keys() if name.startswith("Vertex")]
self.assertEqual(len(body.Shape.childShapes()), 1)
self.assertEqual(body.Shape.childShapes()[0].ElementMapSize, 106)
self.assertEqual(len(reverseMap),106)
self.assertEqual(len(faces),26) # 6 Faces become 26 ( +8 + 2*6 )
self.assertEqual(len(edges),56) # 12 Edges become 56 Why?
self.assertEqual(len(vertexes),24) # 8 Vertices become 24
def testPartDesignElementMapTransform(self):
# Arrange
body = self.Doc.addObject('PartDesign::Body', 'Body')
box = self.Doc.addObject('PartDesign::AdditiveBox', 'Box')
if body.Shape.ElementMapVersion == "": # Skip without element maps.
return
multitransform = self.Doc.addObject('PartDesign::MultiTransform', 'MultiTransform')
scaled = self.Doc.addObject('PartDesign::Scaled', 'Scaled')
scaled.Factor = 2
scaled.Occurrences = 2
multitransform.Transformations = scaled
multitransform.Shape = box.Shape
# Act / Assert
self.Doc.recompute()
body.addObject(box)
body.addObject(multitransform)
self.assertEqual(len(body.Shape.childShapes()), 0)
self.Doc.recompute()
self.assertEqual(len(body.Shape.childShapes()), 1)
self.assertEqual(body.Shape.childShapes()[0].ElementMapSize, 26)
def testPartDesignElementMapShapeBinder(self):
# Arrange
body = self.Doc.addObject('PartDesign::Body', 'Body')