From: azv Date: Fri, 1 Dec 2017 16:54:47 +0000 (+0300) Subject: Issue #2299: Wrong face support of sketch in script from python dump X-Git-Tag: V_2.10.0RC~121 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=ee691173934c004af668771da8421902fc04625c;p=modules%2Fshaper.git Issue #2299: Wrong face support of sketch in script from python dump Improve order of sketch entities during Python dump. --- diff --git a/src/ModelHighAPI/ModelHighAPI_Dumper.cpp b/src/ModelHighAPI/ModelHighAPI_Dumper.cpp index 8ada778b1..40852ee33 100644 --- a/src/ModelHighAPI/ModelHighAPI_Dumper.cpp +++ b/src/ModelHighAPI/ModelHighAPI_Dumper.cpp @@ -96,6 +96,9 @@ void ModelHighAPI_Dumper::clear(bool bufferOnly) myFeatureCount.clear(); while (!myEntitiesStack.empty()) myEntitiesStack.pop(); + + myPostponed.clear(); + myDumpPostponedInProgress = false; } } @@ -139,7 +142,6 @@ const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity, aName = aFolder->data()->name(); aKind = ModelAPI_Folder::ID(); isSaveNotDumped = false; - myNotDumpedFolders.insert(aFolder); } } @@ -362,17 +364,41 @@ bool ModelHighAPI_Dumper::processSubs( if (isDumpSetName) dumpEntitySetName(); // dump folders if any - dumpFolders(); + dumpPostponed(); return isOk; } -void ModelHighAPI_Dumper::dumpFolders() +void ModelHighAPI_Dumper::postpone(const EntityPtr& theEntity) { - std::set::const_iterator aFolderIt = myNotDumpedFolders.begin(); - while (aFolderIt != myNotDumpedFolders.end()) { - FolderPtr aFolder = *aFolderIt++; - dumpFolder(aFolder); + // keep the name + name(theEntity, false); + myPostponed.push_back(theEntity); +} + +void ModelHighAPI_Dumper::dumpPostponed() +{ + if (myDumpPostponedInProgress) + return; + + myDumpPostponedInProgress = true; + // make a copy of postponed entities, because the list will be updated + // if some features are not able to be dumped + std::list aPostponedCopy = myPostponed; + myPostponed.clear(); + + // iterate over postponed entities and try to dump them + std::list::const_iterator anIt = aPostponedCopy.begin(); + for (; anIt != aPostponedCopy.end(); ++anIt) { + FolderPtr aFolder = std::dynamic_pointer_cast(*anIt); + if (aFolder) + dumpFolder(aFolder); + else { + FeaturePtr aFeature = std::dynamic_pointer_cast(*anIt); + if (aFeature) + dumpFeature(aFeature); + } } + myDumpPostponedInProgress = false; } void ModelHighAPI_Dumper::dumpSubFeatureNameAndColor(const std::string theSubFeatureGet, @@ -513,6 +539,28 @@ bool ModelHighAPI_Dumper::isDumped(const EntityPtr& theEntity) const myFeaturesToSkip.find(aFeature) != myFeaturesToSkip.end(); } +bool ModelHighAPI_Dumper::isDumped(const AttributeRefAttrPtr& theRefAttr) const +{ + FeaturePtr aFeature; + if (theRefAttr->isObject()) + aFeature = ModelAPI_Feature::feature(theRefAttr->object()); + else + aFeature = ModelAPI_Feature::feature(theRefAttr->attr()->owner()); + return aFeature && isDumped(aFeature); +} + +bool ModelHighAPI_Dumper::isDumped(const AttributeRefListPtr& theRefList) const +{ + std::list aRefs = theRefList->list(); + std::list::iterator anIt = aRefs.begin(); + for (; anIt != aRefs.end(); ++anIt) { + FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt); + if (aFeature && !isDumped(aFeature)) + return false; + } + return true; +} + bool ModelHighAPI_Dumper::isDefaultColor(const ResultPtr& theResult) const { AttributeIntArrayPtr aColor = theResult->data()->intArray(ModelAPI_Result::COLOR_ID()); @@ -700,7 +748,6 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const FolderPtr& theFolder) { myDumpBuffer << name(theFolder); - myNotDumpedFolders.erase(theFolder); return *this; } @@ -990,7 +1037,7 @@ ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper, isCopy = aCopyAttr.get() && aCopyAttr->value(); } } - } while (isCopy); + } while (isCopy && !theDumper.myEntitiesStack.empty()); } // store all not-dumped entities first @@ -1031,8 +1078,8 @@ ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper, // then store currently dumped string theDumper.myFullDump << aBufCopy; - // now, store all not dumped folders - theDumper.dumpFolders(); + // now, store all postponed features + theDumper.dumpPostponed(); return theDumper; } diff --git a/src/ModelHighAPI/ModelHighAPI_Dumper.h b/src/ModelHighAPI/ModelHighAPI_Dumper.h index e02933598..b287dd6ec 100644 --- a/src/ModelHighAPI/ModelHighAPI_Dumper.h +++ b/src/ModelHighAPI/ModelHighAPI_Dumper.h @@ -121,6 +121,11 @@ public: /// Dump folder virtual void dumpFolder(const FolderPtr& theFolder) = 0; + /// Set feature postponed until all its dependencies are not dumped. + /// The name of the feature is stored anyway. + MODELHIGHAPI_EXPORT + void postpone(const EntityPtr& theEntity); + /// Set a feature that should not be dumped anyway MODELHIGHAPI_EXPORT void doNotDumpFeature(const FeaturePtr& theFeature) @@ -252,6 +257,16 @@ public: /// clear list of not dumped entities MODELHIGHAPI_EXPORT void clearNotDumped(); + /// Check the entity is already dumped + MODELHIGHAPI_EXPORT + bool isDumped(const EntityPtr& theEntity) const; + /// Check theRefAttr is already dumped + MODELHIGHAPI_EXPORT + bool isDumped(const std::shared_ptr& theRefAttr) const; + /// Check all objects in theRefList are already dumped + MODELHIGHAPI_EXPORT + bool isDumped(const std::shared_ptr& theRefList) const; + protected: /// Dump "setName" command if last entity had user-defined name MODELHIGHAPI_EXPORT void dumpEntitySetName(); @@ -274,9 +289,6 @@ private: bool processSubs(const std::shared_ptr& theComposite, bool theDumpModelDo = false); - /// Check the entity is already dumped - bool isDumped(const EntityPtr& theEntity) const; - /// Stores names of results for the given feature void saveResultNames(const FeaturePtr& theFeature); @@ -289,8 +301,8 @@ private: /// Check the result feature has default transparency bool isDefaultTransparency(const ResultPtr& theResult) const; - /// Dump stored folders if possible - void dumpFolders(); + /// Dump postponed entities + void dumpPostponed(); private: struct EntityName { @@ -340,11 +352,12 @@ private: /// features which should not be dumped (like coincidence and tangency created by tangent arc) std::set myFeaturesToSkip; + std::list myPostponed; ///< list of postponed entities (sketch constraints or folders) + bool myDumpPostponedInProgress; ///< processing postponed is in progress + protected: /// list of entities, used by other features but not dumped yet std::set myNotDumpedEntities; - /// list of folders which do not dumped yet - std::set myNotDumpedFolders; friend class SketchAPI_Sketch; friend class ModelHighAPI_Folder; diff --git a/src/ModelHighAPI/ModelHighAPI_Folder.cpp b/src/ModelHighAPI/ModelHighAPI_Folder.cpp index 047881482..e1ad23fae 100644 --- a/src/ModelHighAPI/ModelHighAPI_Folder.cpp +++ b/src/ModelHighAPI/ModelHighAPI_Folder.cpp @@ -67,14 +67,14 @@ void ModelHighAPI_Folder::dump(ModelHighAPI_Dumper& theDumper) const AttributeReferencePtr aEndRef = myFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID()); // Dump folder if it is empty or when its features have been already dumped. - // Otherwise, just store the name of the folder. + // Otherwise, store the folder postponed. if (!aEndRef->value()) theDumper << myFolder << " = model.addFolder(" << aDocName << ")" << std::endl; else if (theDumper.isDumped(aEndRef->value())) theDumper << myFolder << " = model.addFolder(" << aDocName << ", " << aStartRef << ", " << aEndRef << ")" << std::endl; else - theDumper.name(myFolder); + theDumper.postpone(myFolder); } //-------------------------------------------------------------------------------------- diff --git a/src/SketchAPI/SketchAPI_Constraint.cpp b/src/SketchAPI/SketchAPI_Constraint.cpp index c5a75fef3..5098ce99f 100644 --- a/src/SketchAPI/SketchAPI_Constraint.cpp +++ b/src/SketchAPI/SketchAPI_Constraint.cpp @@ -169,6 +169,18 @@ void SketchAPI_Constraint::dump(ModelHighAPI_Dumper& theDumper) const return; } + // Check all attributes are already dumped. If not, store the constraint as postponed. + bool areAttributesDumped = true; + for (int i = 0; i < CONSTRAINT_ATTR_SIZE && areAttributesDumped; ++i) { + AttributeRefAttrPtr aRefAttr = aBase->refattr(SketchPlugin_Constraint::ATTRIBUTE(i)); + if (aRefAttr && aRefAttr->isInitialized()) + areAttributesDumped = theDumper.isDumped(aRefAttr); + } + if (!areAttributesDumped) { + theDumper.postpone(aBase); + return; + } + bool isAngle = aBase->getKind() == SketchPlugin_ConstraintAngle::ID(); std::string aSetterSuffix; if (isAngle) diff --git a/src/SketchAPI/SketchAPI_Mirror.cpp b/src/SketchAPI/SketchAPI_Mirror.cpp index b13e94f03..73f13635d 100644 --- a/src/SketchAPI/SketchAPI_Mirror.cpp +++ b/src/SketchAPI/SketchAPI_Mirror.cpp @@ -70,8 +70,16 @@ void SketchAPI_Mirror::dump(ModelHighAPI_Dumper& theDumper) const FeaturePtr aBase = feature(); const std::string& aSketchName = theDumper.parentName(aBase); + AttributeRefAttrPtr aMirrorLine = mirrorLine(); AttributeRefListPtr aMirrorObjects = mirrorList(); + + // Check all attributes are already dumped. If not, store the constraint as postponed. + if (!theDumper.isDumped(aMirrorLine) || !theDumper.isDumped(aMirrorObjects)) { + theDumper.postpone(aBase); + return; + } + theDumper << aBase << " = " << aSketchName << ".addMirror(" << aMirrorLine << ", " << aMirrorObjects << ")" << std::endl; diff --git a/src/SketchAPI/SketchAPI_Rotation.cpp b/src/SketchAPI/SketchAPI_Rotation.cpp index b217ad0b3..a736df25b 100644 --- a/src/SketchAPI/SketchAPI_Rotation.cpp +++ b/src/SketchAPI/SketchAPI_Rotation.cpp @@ -86,6 +86,12 @@ void SketchAPI_Rotation::dump(ModelHighAPI_Dumper& theDumper) const AttributeIntegerPtr aNbCopies = numberOfObjects(); bool isFullValue = valueType()->value() != "SingleAngle"; + // Check all attributes are already dumped. If not, store the constraint as postponed. + if (!theDumper.isDumped(aCenter) || !theDumper.isDumped(aRotObjects)) { + theDumper.postpone(aBase); + return; + } + theDumper << aBase << " = " << aSketchName << ".addRotation(" << aRotObjects << ", " << aCenter << ", " << anAngle << ", " << aNbCopies; if (isFullValue) diff --git a/src/SketchAPI/SketchAPI_Translation.cpp b/src/SketchAPI/SketchAPI_Translation.cpp index 05dcb1c8f..dddf3b4ad 100644 --- a/src/SketchAPI/SketchAPI_Translation.cpp +++ b/src/SketchAPI/SketchAPI_Translation.cpp @@ -86,6 +86,13 @@ void SketchAPI_Translation::dump(ModelHighAPI_Dumper& theDumper) const AttributeIntegerPtr aNbCopies = numberOfObjects(); bool isFullValue = valueType()->value() != "SingleValue"; + // Check all attributes are already dumped. If not, store the constraint as postponed. + if (!theDumper.isDumped(aStart) || !theDumper.isDumped(aEnd) || + !theDumper.isDumped(aTransObjects)) { + theDumper.postpone(aBase); + return; + } + theDumper << aBase << " = " << aSketchName << ".addTranslation(" << aTransObjects << ", " << aStart << ", " << aEnd << ", " << aNbCopies; if (isFullValue) diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index 30bf99ae1..94e456777 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -179,6 +179,7 @@ ADD_UNIT_TESTS(TestSketchPointLine.py TestConstraintTangent.py TestConstraintAngle.py TestConstraintMiddlePoint.py + TestEdgesOrder.py TestMirror.py TestMultiRotation.py TestMultiTranslation.py diff --git a/src/SketchPlugin/SketchPlugin_Trim.cpp b/src/SketchPlugin/SketchPlugin_Trim.cpp index aedc76332..74be0dc1f 100644 --- a/src/SketchPlugin/SketchPlugin_Trim.cpp +++ b/src/SketchPlugin/SketchPlugin_Trim.cpp @@ -379,7 +379,7 @@ void SketchPlugin_Trim::execute() anIt != aLast; anIt++) { AttributePtr anAttribute = *anIt; - if (setCoincidenceToAttribute(anAttribute, aFurtherCoincidences)) + if (setCoincidenceToAttribute(anAttribute, aFurtherCoincidences, aFeaturesToDelete)) continue; // move tangency constraint to the nearest feature if possible @@ -533,7 +533,8 @@ std::string SketchPlugin_Trim::processEvent(const std::shared_ptr& theFurtherCoincidences) + const std::set& theFurtherCoincidences, + std::set>& theFeaturesToDelete) { FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner()); if (aFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID()) @@ -551,12 +552,9 @@ bool SketchPlugin_Trim::setCoincidenceToAttribute(const AttributePtr& theAttribu AttributePoint2DPtr aPointAttribute = (*anIt); std::shared_ptr aPoint2d = aPointAttribute->pnt(); if (aPoint2d->isEqual(aRefPnt2d)) { - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( - theAttribute); - if (aRefAttr.get()) { - aRefAttr->setAttr(aPointAttribute); - aFoundPoint = true; - } + // create new coincidence and then remove the old one + createConstraint(SketchPlugin_ConstraintCoincidence::ID(), aRefPointAttr, aPointAttribute); + theFeaturesToDelete.insert(aFeature); } } return aFoundPoint; diff --git a/src/SketchPlugin/SketchPlugin_Trim.h b/src/SketchPlugin/SketchPlugin_Trim.h index f03c5d59f..6ad6a58c4 100644 --- a/src/SketchPlugin/SketchPlugin_Trim.h +++ b/src/SketchPlugin/SketchPlugin_Trim.h @@ -117,7 +117,8 @@ class SketchPlugin_Trim : public SketchPlugin_Feature, public GeomAPI_IPresentab private: bool setCoincidenceToAttribute(const AttributePtr& theAttribute, - const std::set >& theFurtherCoincidences); + const std::set >& theFurtherCoincidences, + std::set>& theFeaturesToDelete); /// Move tangency constraint to the feature if it is geometrically closely to it /// \param theAttribute an attribute of a tangent constraint feature /// \param theFeature a feature that can be set into the attribute diff --git a/src/SketchPlugin/Test/TestEdgesOrder.py b/src/SketchPlugin/Test/TestEdgesOrder.py new file mode 100644 index 000000000..cc8ae38a7 --- /dev/null +++ b/src/SketchPlugin/Test/TestEdgesOrder.py @@ -0,0 +1,171 @@ +## Copyright (C) 2014-2017 CEA/DEN, EDF R&D +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## See http:##www.salome-platform.org/ or +## email : webmaster.salome@opencascade.com +## + +""" + Verify the order of sketch edges is the same after dump +""" + +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(40, 5, 40, -25) +SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 30) +SketchLine_2 = Sketch_1.addLine(40, -25, -10, -25) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 50) +SketchLine_3 = Sketch_1.addLine(-10, -25, -10, 5) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchLine_4 = Sketch_1.addLine(-10, 5, 40, 5) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_4.endPoint()) +model.do() + +# Change Length references +SketchConstraintLength_1.feature().refattr("ConstraintEntityA").setObject(SketchLine_3.feature().lastResult()) +SketchConstraintLength_2.feature().refattr("ConstraintEntityA").setObject(SketchLine_4.feature().lastResult()) +model.do() +# Remove the first line, then build it and constraints from scratch +Part_1_doc.removeFeature(SketchConstraintCoincidence_1.feature()) +Part_1_doc.removeFeature(SketchConstraintCoincidence_4.feature()) +Part_1_doc.removeFeature(SketchLine_1.feature()) +SketchLine_1 = Sketch_1.addLine(40, 5, 40, -25) +Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_4.endPoint()) +Sketch_1.setLength(SketchLine_1.result(), 20) +Sketch_1.setLength(SketchLine_2.result(), 40) +model.do() +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r")], model.selection(), 10, 0) + +# Extrude all lateral faces to check their area +Extrusion_2 = model.addExtrusion(Part_1_doc, [], model.selection(), 10, 0) +Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_1")) +SketchLine_5 = Sketch_2.addLine(0.7346748749771982, 2.736245541082907e-015, 0.7346748749771982, 10.00000000000001) +SketchProjection_1 = Sketch_2.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_1"), False) +SketchPoint_1 = SketchProjection_1.createdFeature() +SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_5.startPoint(), SketchPoint_1.result()) +SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1"), False) +SketchPoint_2 = SketchProjection_2.createdFeature() +SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchPoint_2.result()) +SketchLine_6 = Sketch_2.addLine(0.7346748749771982, 10.00000000000001, -19.2653251250228, 10.00000000000001) +SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint()) +SketchProjection_3 = Sketch_2.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1"), False) +SketchPoint_3 = SketchProjection_3.createdFeature() +SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchPoint_3.result()) +SketchLine_7 = Sketch_2.addLine(-19.2653251250228, 10.00000000000001, -19.2653251250228, 2.775557561562891e-015) +SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint()) +SketchProjection_4 = Sketch_2.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_1"), False) +SketchPoint_4 = SketchProjection_4.createdFeature() +SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchPoint_4.result()) +SketchLine_8 = Sketch_2.addLine(-19.2653251250228, 2.775557561562891e-015, 0.7346748749771974, 3.386180225106727e-015) +SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint()) +SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_5.startPoint(), SketchLine_8.endPoint()) +Extrusion_2.setNestedSketch(Sketch_2) + +Extrusion_3 = model.addExtrusion(Part_1_doc, [], model.selection(), 10, 0) +Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_2")) +SketchLine_9 = Sketch_3.addLine(36.86324678550901, 2.286454635368208e-015, 36.86324678550901, 10) +SketchProjection_5 = Sketch_3.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_1"), False) +SketchPoint_5 = SketchProjection_5.createdFeature() +SketchConstraintCoincidence_13 = Sketch_3.setCoincident(SketchLine_9.startPoint(), SketchPoint_5.result()) +SketchProjection_6 = Sketch_3.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1"), False) +SketchPoint_6 = SketchProjection_6.createdFeature() +SketchConstraintCoincidence_14 = Sketch_3.setCoincident(SketchLine_9.endPoint(), SketchPoint_6.result()) +SketchLine_10 = Sketch_3.addLine(36.86324678550901, 10, -3.136753214490995, 10) +SketchConstraintCoincidence_15 = Sketch_3.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint()) +SketchProjection_7 = Sketch_3.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_2&Extrusion_1_1/To_Face_1"), False) +SketchPoint_7 = SketchProjection_7.createdFeature() +SketchConstraintCoincidence_16 = Sketch_3.setCoincident(SketchLine_10.endPoint(), SketchPoint_7.result()) +SketchLine_11 = Sketch_3.addLine(-3.136753214490995, 10, -3.136753214490995, 2.275957200481571e-015) +SketchConstraintCoincidence_17 = Sketch_3.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint()) +SketchProjection_8 = Sketch_3.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_2&Extrusion_1_1/From_Face_1"), False) +SketchPoint_8 = SketchProjection_8.createdFeature() +SketchConstraintCoincidence_18 = Sketch_3.setCoincident(SketchLine_11.endPoint(), SketchPoint_8.result()) +SketchLine_12 = Sketch_3.addLine(-3.136753214490995, 2.275957200481571e-015, 36.86324678550902, 1.387778780781446e-015) +SketchConstraintCoincidence_19 = Sketch_3.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint()) +SketchConstraintCoincidence_20 = Sketch_3.setCoincident(SketchLine_9.startPoint(), SketchLine_12.endPoint()) +Extrusion_3.setNestedSketch(Sketch_3) + +Extrusion_4 = model.addExtrusion(Part_1_doc, [], model.selection(), 10, 0) +Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_3")) +SketchLine_13 = Sketch_4.addLine(22.60959895285982, 4.420942808558057e-016, 22.60959895285982, 10) +SketchProjection_9 = Sketch_4.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_2&Extrusion_1_1/From_Face_1"), False) +SketchPoint_9 = SketchProjection_9.createdFeature() +SketchConstraintCoincidence_21 = Sketch_4.setCoincident(SketchLine_13.startPoint(), SketchPoint_9.result()) +SketchProjection_10 = Sketch_4.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_2&Extrusion_1_1/To_Face_1"), False) +SketchPoint_10 = SketchProjection_10.createdFeature() +SketchConstraintCoincidence_22 = Sketch_4.setCoincident(SketchLine_13.endPoint(), SketchPoint_10.result()) +SketchLine_14 = Sketch_4.addLine(22.60959895285982, 10, -7.390401047140179, 10) +SketchConstraintCoincidence_23 = Sketch_4.setCoincident(SketchLine_13.endPoint(), SketchLine_14.startPoint()) +SketchProjection_11 = Sketch_4.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_1"), False) +SketchPoint_11 = SketchProjection_11.createdFeature() +SketchConstraintCoincidence_24 = Sketch_4.setCoincident(SketchLine_14.endPoint(), SketchPoint_11.result()) +SketchLine_15 = Sketch_4.addLine(-7.390401047140179, 10, -7.390401047140179, 8.881784197001252e-016) +SketchConstraintCoincidence_25 = Sketch_4.setCoincident(SketchLine_14.endPoint(), SketchLine_15.startPoint()) +SketchProjection_12 = Sketch_4.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_3&Extrusion_1_1/From_Face_1"), False) +SketchPoint_12 = SketchProjection_12.createdFeature() +SketchConstraintCoincidence_26 = Sketch_4.setCoincident(SketchLine_15.endPoint(), SketchPoint_12.result()) +SketchLine_16 = Sketch_4.addLine(-7.390401047140179, 8.881784197001252e-016, 22.60959895285983, 0) +SketchConstraintCoincidence_27 = Sketch_4.setCoincident(SketchLine_15.endPoint(), SketchLine_16.startPoint()) +SketchConstraintCoincidence_28 = Sketch_4.setCoincident(SketchLine_13.startPoint(), SketchLine_16.endPoint()) +Extrusion_4.setNestedSketch(Sketch_4) + +Extrusion_5 = model.addExtrusion(Part_1_doc, [], model.selection(), 10, 0) +Sketch_5 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_4")) +SketchLine_17 = Sketch_5.addLine(-10.64977324988603, -1.185841873934692e-016, -10.64977324988603, -10) +SketchProjection_13 = Sketch_5.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_3&Extrusion_1_1/From_Face_1"), False) +SketchPoint_13 = SketchProjection_13.createdFeature() +SketchConstraintCoincidence_29 = Sketch_5.setCoincident(SketchLine_17.startPoint(), SketchPoint_13.result()) +SketchProjection_14 = Sketch_5.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_1"), False) +SketchPoint_14 = SketchProjection_14.createdFeature() +SketchConstraintCoincidence_30 = Sketch_5.setCoincident(SketchLine_17.endPoint(), SketchPoint_14.result()) +SketchLine_18 = Sketch_5.addLine(-10.64977324988603, -10, 39.35022675011398, -10) +SketchConstraintCoincidence_31 = Sketch_5.setCoincident(SketchLine_17.endPoint(), SketchLine_18.startPoint()) +SketchProjection_15 = Sketch_5.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1"), False) +SketchPoint_15 = SketchProjection_15.createdFeature() +SketchConstraintCoincidence_32 = Sketch_5.setCoincident(SketchLine_18.endPoint(), SketchPoint_15.result()) +SketchLine_19 = Sketch_5.addLine(39.35022675011398, -10, 39.35022675011398, 4.440892098500626e-016) +SketchConstraintCoincidence_33 = Sketch_5.setCoincident(SketchLine_18.endPoint(), SketchLine_19.startPoint()) +SketchProjection_16 = Sketch_5.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_1"), False) +SketchPoint_16 = SketchProjection_16.createdFeature() +SketchConstraintCoincidence_34 = Sketch_5.setCoincident(SketchLine_19.endPoint(), SketchPoint_16.result()) +SketchLine_20 = Sketch_5.addLine(39.35022675011398, 4.440892098500626e-016, -10.64977324988603, 0) +SketchConstraintCoincidence_35 = Sketch_5.setCoincident(SketchLine_19.endPoint(), SketchLine_20.startPoint()) +SketchConstraintCoincidence_36 = Sketch_5.setCoincident(SketchLine_17.startPoint(), SketchLine_20.endPoint()) +Extrusion_5.setNestedSketch(Sketch_5) +model.do() +model.end() + +# check volumes +model.testResultsVolumes(Extrusion_2, [4000]) +model.testResultsVolumes(Extrusion_3, [3000]) +model.testResultsVolumes(Extrusion_4, [5000]) +model.testResultsVolumes(Extrusion_5, [2000]) + +assert(model.checkPythonDump()) + +# check volumes after dump and restore +model.testResultsVolumes(Extrusion_2, [4000]) +model.testResultsVolumes(Extrusion_3, [3000]) +model.testResultsVolumes(Extrusion_4, [5000]) +model.testResultsVolumes(Extrusion_5, [2000])