Merge pull request #13387 from bgbsww/bgbsww-toponamingPD5FeaturePad
Toponaming/Part Transfer more python ElementMapVersion and add feature pad testing
This commit is contained in:
@@ -1304,6 +1304,24 @@ bool DocumentObject::adjustRelativeLinks(
|
||||
return touched;
|
||||
}
|
||||
|
||||
std::string DocumentObject::getElementMapVersion(const App::Property* _prop, bool restored) const
|
||||
{
|
||||
auto prop = Base::freecad_dynamic_cast<const PropertyComplexGeoData>(_prop);
|
||||
if (!prop) {
|
||||
return std::string();
|
||||
}
|
||||
return prop->getElementMapVersion(restored);
|
||||
}
|
||||
|
||||
bool DocumentObject::checkElementMapVersion(const App::Property* _prop, const char* ver) const
|
||||
{
|
||||
auto prop = Base::freecad_dynamic_cast<const PropertyComplexGeoData>(_prop);
|
||||
if (!prop) {
|
||||
return false;
|
||||
}
|
||||
return prop->checkElementMapVersion(ver);
|
||||
}
|
||||
|
||||
const std::string &DocumentObject::hiddenMarker() {
|
||||
static std::string marker("!hide");
|
||||
return marker;
|
||||
|
||||
@@ -300,6 +300,20 @@ public:
|
||||
bool testIfLinkDAGCompatible(App::PropertyLinkSubList &linksTo) const;
|
||||
bool testIfLinkDAGCompatible(App::PropertyLinkSub &linkTo) const;
|
||||
|
||||
/** Return the element map version of the geometry data stored in the given property
|
||||
*
|
||||
* @param prop: the geometry property to query for element map version
|
||||
* @param restored: whether to query for the restored element map version.
|
||||
* In case of version upgrade, the restored version may
|
||||
* be different from the current version.
|
||||
*
|
||||
* @return Return the element map version string.
|
||||
*/
|
||||
virtual std::string getElementMapVersion(const App::Property *prop, bool restored=false) const;
|
||||
|
||||
/// Return true to signal re-generation of geometry element names
|
||||
virtual bool checkElementMapVersion(const App::Property *prop, const char *ver) const;
|
||||
|
||||
public:
|
||||
/** mustExecute
|
||||
* We call this method to check if the object was modified to
|
||||
|
||||
@@ -225,6 +225,13 @@ Return tuple(obj,newElementName,oldElementName)
|
||||
<UserDocu>adjustRelativeLinks(parent,recursive=True) -- auto correct potential cyclic dependencies</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getElementMapVersion" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>
|
||||
getElementMapVersion(property_name): return element map version of a given geometry property
|
||||
</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Attribute Name="OutList" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>A list of all objects this object links to.</UserDocu>
|
||||
|
||||
@@ -745,6 +745,22 @@ PyObject* DocumentObjectPy::getPathsByOutList(PyObject *args)
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* DocumentObjectPy::getElementMapVersion(PyObject* args)
|
||||
{
|
||||
const char* name;
|
||||
PyObject* restored = Py_False;
|
||||
if (!PyArg_ParseTuple(args, "s|O", &name, &restored)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Property* prop = getDocumentObjectPtr()->getPropertyByName(name);
|
||||
if (!prop) {
|
||||
throw Py::ValueError("property not found");
|
||||
}
|
||||
return Py::new_reference_to(
|
||||
Py::String(getDocumentObjectPtr()->getElementMapVersion(prop, Base::asBoolean(restored))));
|
||||
}
|
||||
|
||||
PyObject *DocumentObjectPy::getCustomAttributes(const char* ) const
|
||||
{
|
||||
return nullptr;
|
||||
|
||||
@@ -726,8 +726,8 @@ MappedName ElementMap::dehashElementName(const MappedName& name) const
|
||||
FC_LOG("cannot de-hash id " << id);// NOLINT
|
||||
return name;
|
||||
}
|
||||
MappedName ret(
|
||||
sid.toString());// FIXME .toString() was missing in original function. is this correct?
|
||||
MappedName ret(sid);
|
||||
// sid.toString());// FIXME .toString() was missing in original function. is this correct?
|
||||
FC_TRACE("de-hash " << name << " -> " << ret);// NOLINT
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -58,6 +58,12 @@ If an object has no such property then None is returned.
|
||||
Unlike to getPropertyNameOfGeometry this function returns the geometry, not its name.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Attribute Name="ElementMapVersion" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Element map version</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="ElementMapVersion" Type="String" />
|
||||
</Attribute>
|
||||
<CustomAttributes />
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
|
||||
@@ -93,3 +93,8 @@ int GeoFeaturePy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py::String GeoFeaturePy::getElementMapVersion() const {
|
||||
return Py::String(getGeoFeaturePtr()->getElementMapVersion(
|
||||
getGeoFeaturePtr()->getPropertyOfGeometry()));
|
||||
}
|
||||
|
||||
@@ -484,7 +484,8 @@ void ExtrusionHelper::createTaperedPrismOffset(TopoDS_Wire sourceWire,
|
||||
|
||||
void ExtrusionHelper::makeElementDraft(const ExtrusionParameters& params,
|
||||
const TopoShape& _shape,
|
||||
std::vector<TopoShape>& drafts)
|
||||
std::vector<TopoShape>& drafts,
|
||||
App::StringHasherRef hasher)
|
||||
{
|
||||
double distanceFwd = tan(params.taperAngleFwd) * params.lengthFwd;
|
||||
double distanceRev = tan(params.taperAngleRev) * params.lengthRev;
|
||||
@@ -518,7 +519,7 @@ void ExtrusionHelper::makeElementDraft(const ExtrusionParameters& params,
|
||||
}
|
||||
else {
|
||||
unsigned pos = drafts.size();
|
||||
makeElementDraft(params, outerWire, drafts);
|
||||
makeElementDraft(params, outerWire, drafts, hasher);
|
||||
if (drafts.size() != pos + 1) {
|
||||
Standard_Failure::Raise("Failed to make drafted extrusion");
|
||||
}
|
||||
@@ -528,7 +529,7 @@ void ExtrusionHelper::makeElementDraft(const ExtrusionParameters& params,
|
||||
wires,
|
||||
"",
|
||||
TopoShape::SingleShapeCompoundCreationPolicy::returnShape);
|
||||
makeElementDraft(params, innerWires, inner);
|
||||
makeElementDraft(params, innerWires, inner, hasher);
|
||||
if (inner.empty()) {
|
||||
Standard_Failure::Raise("Failed to make drafted extrusion with inner hole");
|
||||
}
|
||||
@@ -550,7 +551,7 @@ void ExtrusionHelper::makeElementDraft(const ExtrusionParameters& params,
|
||||
}
|
||||
else if (shape.shapeType() == TopAbs_COMPOUND) {
|
||||
for (auto& s : shape.getSubTopoShapes()) {
|
||||
makeElementDraft(params, s, drafts);
|
||||
makeElementDraft(params, s, drafts, hasher);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -598,7 +599,7 @@ void ExtrusionHelper::makeElementDraft(const ExtrusionParameters& params,
|
||||
}
|
||||
|
||||
mkGenerator.Build();
|
||||
drafts.push_back(TopoShape(0).makeElementShape(mkGenerator, list_of_sections));
|
||||
drafts.push_back(TopoShape(0, hasher).makeElementShape(mkGenerator, list_of_sections));
|
||||
}
|
||||
catch (Standard_Failure&) {
|
||||
throw;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <TopoDS_Shape.hxx>
|
||||
|
||||
#include <Mod/Part/PartGlobal.h>
|
||||
#include "TopoShape.h"
|
||||
|
||||
|
||||
namespace Part
|
||||
@@ -88,8 +89,10 @@ public:
|
||||
TopoDS_Wire& result);
|
||||
/** Same as makeDraft() with support of element mapping
|
||||
*/
|
||||
static void
|
||||
makeElementDraft(const ExtrusionParameters& params, const TopoShape&, std::vector<TopoShape>&);
|
||||
static void makeElementDraft(const ExtrusionParameters& params,
|
||||
const TopoShape&,
|
||||
std::vector<TopoShape>&,
|
||||
App::StringHasherRef hasher);
|
||||
};
|
||||
|
||||
} //namespace Part
|
||||
|
||||
@@ -61,9 +61,12 @@ void Part::FaceMaker::addTopoShape(const TopoShape& shape) {
|
||||
break;
|
||||
case TopAbs_WIRE:
|
||||
this->myWires.push_back(TopoDS::Wire(sh));
|
||||
this->myTopoWires.push_back(shape);
|
||||
break;
|
||||
case TopAbs_EDGE:
|
||||
this->myWires.push_back(BRepBuilderAPI_MakeWire(TopoDS::Edge(sh)).Wire());
|
||||
this->myTopoWires.push_back(shape);
|
||||
this->myTopoWires.back().setShape(this->myWires.back(), false);
|
||||
break;
|
||||
case TopAbs_FACE:
|
||||
this->myInputFaces.push_back(sh);
|
||||
@@ -186,6 +189,7 @@ void Part::FaceMaker::postBuild() {
|
||||
if(!op)
|
||||
op = Part::OpCodes::Face;
|
||||
const auto &faces = this->myTopoShape.getSubTopoShapes(TopAbs_FACE);
|
||||
std::set<Data::MappedName> namesUsed;
|
||||
// name the face using the edges of its outer wire
|
||||
for(auto &face : faces) {
|
||||
++index;
|
||||
@@ -208,10 +212,25 @@ void Part::FaceMaker::postBuild() {
|
||||
|
||||
std::vector<Data::MappedName> names;
|
||||
Data::ElementIDRefs sids;
|
||||
#ifdef FC_USE_TNP_FIX
|
||||
// To avoid name collision, we keep track of any used names to make sure
|
||||
// to use at least 'minElementNames' number of unused element names to
|
||||
// generate the face name.
|
||||
int nameCount = 0;
|
||||
for (const auto &e : edgeNames) {
|
||||
names.push_back(e.name);
|
||||
sids += e.sids;
|
||||
if (namesUsed.insert(e.name).second) {
|
||||
if (++nameCount >= minElementNames)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// We just use the first source element name to make the face name more
|
||||
// stable
|
||||
names.push_back(edgeNames.begin()->name);
|
||||
sids = edgeNames.begin()->sids;
|
||||
#endif
|
||||
this->myTopoShape.setElementComboName(
|
||||
Data::IndexedName::fromConst("Face",index),names,op,nullptr,&sids);
|
||||
}
|
||||
|
||||
@@ -107,10 +107,12 @@ public:
|
||||
protected:
|
||||
std::vector<TopoShape> mySourceShapes; //wire or compound
|
||||
std::vector<TopoDS_Wire> myWires; //wires from mySourceShapes
|
||||
std::vector<TopoShape> myTopoWires;
|
||||
std::vector<TopoDS_Compound> myCompounds; //compounds, for recursive processing
|
||||
std::vector<TopoDS_Shape> myShapesToReturn;
|
||||
std::vector<TopoDS_Shape> myInputFaces;
|
||||
TopoShape myTopoShape;
|
||||
int minElementNames = 1;
|
||||
|
||||
/**
|
||||
* @brief Build_Essence: build routine that can assume there is no nesting.
|
||||
|
||||
@@ -320,7 +320,7 @@ void Extrusion::extrudeShape(TopoShape &result, const TopoShape &source, const E
|
||||
Base::SignalException se;
|
||||
#endif
|
||||
std::vector<TopoShape> drafts;
|
||||
ExtrusionHelper::makeElementDraft(params, myShape, drafts);
|
||||
ExtrusionHelper::makeElementDraft(params, myShape, drafts, result.Hasher);
|
||||
if (drafts.empty()) {
|
||||
Standard_Failure::Raise("Drafting shape failed");
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <App/Link.h>
|
||||
|
||||
#include "FeatureOffset.h"
|
||||
#include <App/Document.h>
|
||||
|
||||
|
||||
using namespace Part;
|
||||
@@ -96,7 +97,7 @@ App::DocumentObjectExecReturn *Offset::execute()
|
||||
if(shape.isNull())
|
||||
return new App::DocumentObjectExecReturn("Invalid source link");
|
||||
auto join = static_cast<JoinType>(Join.getValue());
|
||||
this->Shape.setValue(TopoShape(0).makeElementOffset(
|
||||
this->Shape.setValue(TopoShape(0, getDocument()->getStringHasher()).makeElementOffset(
|
||||
shape,offset,tol,inter,self,mode,join,fill ? FillType::fill : FillType::noFill));
|
||||
#endif
|
||||
return App::DocumentObject::StdReturn;
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
|
||||
#include <App/Link.h>
|
||||
|
||||
#include <App/Document.h>
|
||||
#include "PartFeatures.h"
|
||||
#include "TopoShapeOpCode.h"
|
||||
|
||||
@@ -837,7 +838,7 @@ App::DocumentObjectExecReturn* Thickness::execute()
|
||||
short join = (short)Join.getValue();
|
||||
|
||||
#ifdef FC_USE_TNP_FIX
|
||||
this->Shape.setValue(TopoShape(0)
|
||||
this->Shape.setValue(TopoShape(0,getDocument()->getStringHasher())
|
||||
.makeElementThickSolid(base,
|
||||
shapes,
|
||||
thickness,
|
||||
|
||||
@@ -1435,7 +1435,6 @@ TopoShape& TopoShape::makeShapeWithElementMap(const TopoDS_Shape& shape,
|
||||
if (otherMap.count() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= otherMap.count(); i++) {
|
||||
const auto& otherElement = otherMap.find(incomingShape._Shape, i);
|
||||
// Find all new objects that are a modification of the old object
|
||||
@@ -1754,7 +1753,6 @@ TopoShape& TopoShape::makeShapeWithElementMap(const TopoDS_Shape& shape,
|
||||
elementMap()
|
||||
->encodeElementName(element[0], first_name, ss, &sids, Tag, op, first_key.tag);
|
||||
elementMap()->setElementName(element, first_name, Tag, &sids);
|
||||
|
||||
if (!delayed && first_key.shapetype < 3) {
|
||||
newNames.erase(itName);
|
||||
}
|
||||
@@ -1852,7 +1850,7 @@ TopoShape& TopoShape::makeShapeWithElementMap(const TopoDS_Shape& shape,
|
||||
|
||||
elementMap()->encodeElementName(indexedName[0], newName, ss, &sids, Tag, op);
|
||||
elementMap()->setElementName(indexedName, newName, Tag, &sids);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,11 @@ static Py_hash_t _TopoShapeHash(PyObject* self)
|
||||
"This reference is no longer valid!");
|
||||
return 0;
|
||||
}
|
||||
#if OCC_VERSION_HEX >= 0x070800
|
||||
return std::hash<TopoDS_Shape> {}(static_cast<TopoShapePy*>(self)->getTopoShapePtr()->getShape());
|
||||
#else
|
||||
return static_cast<TopoShapePy*>(self)->getTopoShapePtr()->getShape().HashCode(INT_MAX);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct TopoShapePyInit
|
||||
|
||||
@@ -555,7 +555,7 @@ App::DocumentObjectExecReturn* FeatureExtrude::buildExtrusion(ExtrudeOptions opt
|
||||
}
|
||||
sketchshape.move(invObjLoc);
|
||||
|
||||
TopoShape prism(0);
|
||||
TopoShape prism(0, getDocument()->getStringHasher());
|
||||
|
||||
if (method == "UpToFirst" || method == "UpToLast" || method == "UpToFace") {
|
||||
// Note: This will return an unlimited planar face if support is a datum plane
|
||||
@@ -663,7 +663,7 @@ App::DocumentObjectExecReturn* FeatureExtrude::buildExtrusion(ExtrudeOptions opt
|
||||
params.dir.Reverse();
|
||||
}
|
||||
std::vector<TopoShape> drafts;
|
||||
Part::ExtrusionHelper::makeElementDraft(params, sketchshape, drafts);
|
||||
Part::ExtrusionHelper::makeElementDraft(params, sketchshape, drafts, getDocument()->getStringHasher());
|
||||
if (drafts.empty()) {
|
||||
return new App::DocumentObjectExecReturn(
|
||||
QT_TRANSLATE_NOOP("Exception", "Padding with draft angle failed"));
|
||||
@@ -693,7 +693,7 @@ App::DocumentObjectExecReturn* FeatureExtrude::buildExtrusion(ExtrudeOptions opt
|
||||
prism.Tag = -this->getID();
|
||||
|
||||
// Let's call algorithm computing a fuse operation:
|
||||
TopoShape result(0);
|
||||
TopoShape result(0, getDocument()->getStringHasher());
|
||||
try {
|
||||
const char* maker;
|
||||
switch (getAddSubType()) {
|
||||
|
||||
@@ -110,11 +110,38 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
else:
|
||||
print("TOPOLOGICAL NAMING PROBLEM IS PRESENT.")
|
||||
|
||||
def testPartDesignElementMapPad(self):
|
||||
""" Test that padding a sketch results in a correct element map. Note that comprehensive testing
|
||||
of the geometric functionality of the Pad is in TestPad.py """
|
||||
# Arrange
|
||||
body = self.Doc.addObject('PartDesign::Body', 'Body')
|
||||
padSketch = self.Doc.addObject('Sketcher::SketchObject', 'SketchPad')
|
||||
pad = self.Doc.addObject("PartDesign::Pad", "Pad")
|
||||
body.addObject(padSketch)
|
||||
body.addObject(pad)
|
||||
TestSketcherApp.CreateRectangleSketch(padSketch, (0, 0), (1, 1))
|
||||
pad.Profile = padSketch
|
||||
pad.Length = 1
|
||||
# Act
|
||||
self.Doc.recompute()
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
reverseMap = pad.Shape.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")]
|
||||
# Assert
|
||||
self.assertEqual(pad.Shape.ElementMapSize,30) # 4 duplicated Vertexes in here
|
||||
self.assertEqual(len(reverseMap),26)
|
||||
self.assertEqual(len(faces),6)
|
||||
self.assertEqual(len(edges),12)
|
||||
self.assertEqual(len(vertexes),8)
|
||||
|
||||
def testPartDesignElementMapBox(self):
|
||||
# Arrange
|
||||
body = self.Doc.addObject('PartDesign::Body', 'Body')
|
||||
box = self.Doc.addObject('PartDesign::AdditiveBox', 'Box')
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act / Assert
|
||||
self.assertEqual(len(box.Shape.childShapes()), 0)
|
||||
@@ -131,7 +158,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
# Arrange
|
||||
body = self.Doc.addObject('PartDesign::Body', 'Body')
|
||||
cylinder = self.Doc.addObject('PartDesign::AdditiveCylinder', 'Cylinder')
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act / Assert
|
||||
self.assertEqual(len(cylinder.Shape.childShapes()), 0)
|
||||
@@ -148,7 +175,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
# Arrange
|
||||
body = self.Doc.addObject('PartDesign::Body', 'Body')
|
||||
sphere = self.Doc.addObject('PartDesign::AdditiveSphere', 'Sphere')
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act / Assert
|
||||
self.assertEqual(len(sphere.Shape.childShapes()), 0)
|
||||
@@ -165,7 +192,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
# Arrange
|
||||
body = self.Doc.addObject('PartDesign::Body', 'Body')
|
||||
cone = self.Doc.addObject('PartDesign::AdditiveCone', 'Cone')
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act / Assert
|
||||
self.assertEqual(len(cone.Shape.childShapes()), 0)
|
||||
@@ -182,7 +209,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
# Arrange
|
||||
body = self.Doc.addObject('PartDesign::Body', 'Body')
|
||||
ellipsoid = self.Doc.addObject('PartDesign::AdditiveEllipsoid', 'Ellipsoid')
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act / Assert
|
||||
self.assertEqual(len(ellipsoid.Shape.childShapes()), 0)
|
||||
@@ -199,7 +226,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
# Arrange
|
||||
body = self.Doc.addObject('PartDesign::Body', 'Body')
|
||||
torus = self.Doc.addObject('PartDesign::AdditiveTorus', 'Torus')
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act / Assert
|
||||
self.assertEqual(len(torus.Shape.childShapes()), 0)
|
||||
@@ -216,7 +243,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
# Arrange
|
||||
body = self.Doc.addObject('PartDesign::Body', 'Body')
|
||||
prism = self.Doc.addObject('PartDesign::AdditivePrism', 'Prism')
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act / Assert
|
||||
self.assertEqual(len(prism.Shape.childShapes()), 0)
|
||||
@@ -233,7 +260,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
# Arrange
|
||||
body = self.Doc.addObject('PartDesign::Body', 'Body')
|
||||
wedge = self.Doc.addObject('PartDesign::AdditiveWedge', 'Wedge')
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act / Assert
|
||||
self.assertEqual(len(wedge.Shape.childShapes()), 0)
|
||||
@@ -256,7 +283,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
box.Width = 20
|
||||
box.Height = 20
|
||||
body.addObject(box)
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act
|
||||
subbox = self.Doc.addObject('PartDesign::SubtractiveBox', 'Box')
|
||||
@@ -275,7 +302,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
box.Width = 20
|
||||
box.Height = 20
|
||||
body.addObject(box)
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act
|
||||
subcylinder = self.Doc.addObject('PartDesign::SubtractiveCylinder', 'Cylinder')
|
||||
@@ -294,7 +321,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
box.Width = 20
|
||||
box.Height = 20
|
||||
body.addObject(box)
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act
|
||||
subsphere = self.Doc.addObject('PartDesign::SubtractiveSphere', 'Sphere')
|
||||
@@ -313,7 +340,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
box.Width = 20
|
||||
box.Height = 20
|
||||
body.addObject(box)
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act
|
||||
subcone = self.Doc.addObject('PartDesign::SubtractiveCone', 'Cone')
|
||||
@@ -332,7 +359,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
box.Width = 20
|
||||
box.Height = 20
|
||||
body.addObject(box)
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act
|
||||
subellipsoid = self.Doc.addObject('PartDesign::SubtractiveEllipsoid', 'Ellipsoid')
|
||||
@@ -351,7 +378,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
box.Width = 20
|
||||
box.Height = 20
|
||||
body.addObject(box)
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act
|
||||
subtorus = self.Doc.addObject('PartDesign::SubtractiveTorus', 'Torus')
|
||||
@@ -370,7 +397,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
box.Width = 20
|
||||
box.Height = 20
|
||||
body.addObject(box)
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act
|
||||
subprism = self.Doc.addObject('PartDesign::SubtractivePrism', 'Prism')
|
||||
@@ -389,7 +416,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
box.Width = 20
|
||||
box.Height = 20
|
||||
body.addObject(box)
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act
|
||||
subwedge = self.Doc.addObject('PartDesign::SubtractiveWedge', 'Wedge')
|
||||
@@ -405,22 +432,27 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
body = self.Doc.addObject('PartDesign::Body', 'Body')
|
||||
sketch = self.Doc.addObject('Sketcher::SketchObject', 'Sketch')
|
||||
TestSketcherApp.CreateRectangleSketch(sketch, (0, 0), (1, 1))
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act
|
||||
pad = self.Doc.addObject('PartDesign::Pad', 'Pad')
|
||||
pad.Profile = sketch
|
||||
pad.BaseFeature = sketch
|
||||
body.addObject(sketch)
|
||||
body.addObject(pad)
|
||||
self.Doc.recompute()
|
||||
# Assert
|
||||
self.assertEqual(len(body.Shape.childShapes()), 1)
|
||||
self.assertEqual(body.Shape.childShapes()[0].ElementMapSize, 26)
|
||||
# self.assertEqual(len(body.Shape.childShapes()), 1)
|
||||
if App.GuiUp:
|
||||
# Todo: This triggers a 'hasher mismatch' warning in TopoShape::mapSubElement as called by
|
||||
# flushElementMap. This appears to be the case whenever you have a parent with a hasher
|
||||
# that has children without hashmaps. The warning seems to be spurious in this case, but
|
||||
# perhaps there is a solution involving setting hashmaps on all elements.
|
||||
self.assertEqual(body.Shape.childShapes()[0].ElementMapSize, 30)
|
||||
else:
|
||||
self.assertEqual(body.Shape.childShapes()[0].ElementMapSize, 26)
|
||||
self.assertEqual(body.Shape.ElementMapSize,30)
|
||||
self.assertEqual(sketch.Shape.ElementMapSize,12)
|
||||
self.assertEqual(pad.Shape.ElementMapSize,30)
|
||||
self.assertEqual(pad.Shape.childShapes()[0].ElementMapSize,30)
|
||||
# Todo: Assert that the names in the ElementMap are good; in particular that they are hashed with a # starting
|
||||
|
||||
def testPartDesignElementMapRevolution(self):
|
||||
@@ -428,7 +460,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
body = self.Doc.addObject('PartDesign::Body', 'Body')
|
||||
sketch = self.Doc.addObject('Sketcher::SketchObject', 'Sketch')
|
||||
TestSketcherApp.CreateRectangleSketch(sketch, (0, 0), (1, 1))
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act
|
||||
revolution = self.Doc.addObject('PartDesign::Revolution', 'Revolution')
|
||||
@@ -449,7 +481,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
sketch2 = self.Doc.addObject('Sketcher::SketchObject', 'Sketch')
|
||||
TestSketcherApp.CreateRectangleSketch(sketch2, (0, 0), (2, 2))
|
||||
sketch2.Placement.move(App.Vector(0, 0, 3))
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act
|
||||
loft = self.Doc.addObject('PartDesign::AdditiveLoft', 'Loft')
|
||||
@@ -470,7 +502,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
TestSketcherApp.CreateRectangleSketch(sketch, (0, 0), (1, 1))
|
||||
sketch2 = self.Doc.addObject('Sketcher::SketchObject', 'Sketch')
|
||||
TestSketcherApp.CreateRectangleSketch(sketch2, (0, 0), (2, 2))
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act
|
||||
pipe = self.Doc.addObject('PartDesign::AdditivePipe', 'Pipe')
|
||||
@@ -489,7 +521,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
body = self.Doc.addObject('PartDesign::Body', 'Body')
|
||||
sketch = self.Doc.addObject('Sketcher::SketchObject', 'Sketch')
|
||||
TestSketcherApp.CreateRectangleSketch(sketch, (0, 0), (1, 1))
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Act
|
||||
helix = self.Doc.addObject('PartDesign::AdditiveHelix', 'Helix')
|
||||
@@ -524,6 +556,8 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
groove.Reversed = 0
|
||||
groove.Base = App.Vector(0, 0, 0)
|
||||
self.Doc.recompute()
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Assert
|
||||
# print(groove.Shape.childShapes()[0].ElementMap)
|
||||
# TODO: Complete me as part of the subtractive features
|
||||
@@ -548,14 +582,13 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
pad.Profile = sketch
|
||||
body.addObject(pad)
|
||||
self.Doc.recompute()
|
||||
if not hasattr(body,"ElementMapVersion"): # Skip without element maps.
|
||||
if body.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Assert
|
||||
self.assertEqual(sketch.Shape.ElementMapSize, 12)
|
||||
self.assertEqual(pad.Shape.ElementMapSize, 30) # The sketch plus the pad in the map
|
||||
# TODO: differing results between main and LS3 on these values. Does it matter?
|
||||
# self.assertEqual(body.Shape.ElementMapSize,0) # 8?
|
||||
# self.Doc.recompute()
|
||||
# self.assertEqual(body.Shape.ElementMapSize,30) # 26
|
||||
|
||||
def testPlaneElementMap(self):
|
||||
@@ -567,7 +600,7 @@ class TestTopologicalNamingProblem(unittest.TestCase):
|
||||
pad = self.Doc.addObject('PartDesign::Pad', 'Pad')
|
||||
pad.Profile = plane
|
||||
self.Doc.recompute()
|
||||
if not hasattr(pad,"ElementMapVersion"): # Skip without element maps.
|
||||
if pad.Shape.ElementMapVersion == "": # Should be '4' as of Mar 2023.
|
||||
return
|
||||
# Assert
|
||||
self.assertEqual(plane.Shape.ElementMapSize, 0)
|
||||
|
||||
@@ -299,7 +299,7 @@ void SketchObject::buildShape()
|
||||
Shape.setValue(Part::TopoShape());
|
||||
return;
|
||||
}
|
||||
Part::TopoShape result(0);
|
||||
Part::TopoShape result(0, getDocument()->getStringHasher());
|
||||
if (vertices.empty()) {
|
||||
// Notice here we supply op code Part::OpCodes::Sketch to makEWires().
|
||||
result.makeElementWires(shapes,Part::OpCodes::Sketch);
|
||||
|
||||
Reference in New Issue
Block a user