From c5c2d5966c1cb3007ce365c39e64d340535e08ad Mon Sep 17 00:00:00 2001 From: mpv Date: Wed, 12 Feb 2020 16:11:37 +0300 Subject: [PATCH] Make the SHAPERSTUDY python dump works on SHAPER objects stable, even after modifications. --- src/ConnectorAPI/Test/TestShaperStudy1.py | 161 +++++++++++++++++++++ src/ConnectorAPI/Test/tests.set | 1 + src/ExchangePlugin/ExchangePlugin_Dump.cpp | 15 +- src/ExchangePlugin/ExchangePlugin_Dump.h | 7 + src/ModelHighAPI/ModelHighAPI_Dumper.cpp | 22 ++- src/ModelHighAPI/ModelHighAPI_Dumper.h | 8 +- src/PythonAPI/model/dump/DumpAssistant.py | 14 ++ src/PythonAPI/model/services/__init__.py | 10 ++ src/SHAPERGUI/SHAPERGUI_DataModel.cpp | 6 +- 9 files changed, 239 insertions(+), 5 deletions(-) create mode 100644 src/ConnectorAPI/Test/TestShaperStudy1.py diff --git a/src/ConnectorAPI/Test/TestShaperStudy1.py b/src/ConnectorAPI/Test/TestShaperStudy1.py new file mode 100644 index 000000000..870278a53 --- /dev/null +++ b/src/ConnectorAPI/Test/TestShaperStudy1.py @@ -0,0 +1,161 @@ +# Copyright (C) 2014-2019 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 +# + +import sys +import salome + +salome.salome_init() + +### +### SHAPER component +### + +from SketchAPI import * + +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +model.addParameter(Part_1_doc, "r", "15") +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchCircle_1 = Sketch_1.addCircle(25, 25, 15) +SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) +SketchPoint_1 = SketchProjection_1.createdFeature() +SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchCircle_1.center(), SketchAPI_Point(SketchPoint_1).coordinates(), 25) +SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchCircle_1.center(), SketchAPI_Point(SketchPoint_1).coordinates(), 25) +SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], "r") +model.do() +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2r")], model.selection(), 10, 0) +model.do() + +Part_2 = model.addPart(partSet) +Part_2_doc = Part_2.document() +Sketch_2 = model.addSketch(Part_2_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_2.addLine(-5.176380902051512, 19.31851652579896, 19.31851652579829, -5.176380902058602) +SketchLine_2 = Sketch_2.addLine(19.31851652579829, -5.176380902058602, -14.14213562374638, -14.14213562374059) +SketchConstraintCoincidence_1 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchLine_3 = Sketch_2.addLine(-14.14213562374638, -14.14213562374059, -5.176380902051512, 19.31851652579896) +SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint()) +SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result()) +SketchConstraintEqual_2 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_2.result()) +SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) +SketchPoint_2 = SketchProjection_2.createdFeature() +SketchConstraintDistance_1 = Sketch_2.setDistance(SketchLine_2.startPoint(), SketchAPI_Point(SketchPoint_2).coordinates(), 20, True) +SketchConstraintDistance_2 = Sketch_2.setDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_2).coordinates(), 20, True) +SketchConstraintDistance_3 = Sketch_2.setDistance(SketchLine_3.startPoint(), SketchAPI_Point(SketchPoint_2).coordinates(), 20, True) +SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OX"), False) +SketchLine_4 = SketchProjection_3.createdFeature() +SketchConstraintAngle_1 = Sketch_2.setAngle(SketchLine_3.result(), SketchLine_4.result(), 75) +model.do() +Extrusion_2 = model.addExtrusion(Part_2_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 30, 0) +Fillet_1 = model.addFillet(Part_2_doc, [model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3][Extrusion_1_1/To_Face]")], 2) +model.do() + +Part_3 = model.addPart(partSet) +Part_3_doc = Part_3.document() +Sketch_3 = model.addSketch(Part_3_doc, model.defaultPlane("XOZ")) +SketchLine_5 = Sketch_3.addLine(52.5, 35, 22.5, 35) +SketchLine_6 = Sketch_3.addLine(22.5, 35, 22.5, 15) +SketchLine_7 = Sketch_3.addLine(22.5, 15, 52.5, 15) +SketchLine_8 = Sketch_3.addLine(52.5, 15, 52.5, 35) +SketchConstraintCoincidence_4 = Sketch_3.setCoincident(SketchLine_8.endPoint(), SketchLine_5.startPoint()) +SketchConstraintCoincidence_5 = Sketch_3.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint()) +SketchConstraintCoincidence_6 = Sketch_3.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint()) +SketchConstraintCoincidence_7 = Sketch_3.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint()) +SketchConstraintHorizontal_1 = Sketch_3.setHorizontal(SketchLine_5.result()) +SketchConstraintVertical_1 = Sketch_3.setVertical(SketchLine_6.result()) +SketchConstraintHorizontal_2 = Sketch_3.setHorizontal(SketchLine_7.result()) +SketchConstraintVertical_2 = Sketch_3.setVertical(SketchLine_8.result()) +SketchLine_9 = Sketch_3.addLine(0, 0, 52.5, 35) +SketchLine_9.setAuxiliary(True) +SketchProjection_4 = Sketch_3.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) +SketchPoint_3 = SketchProjection_4.createdFeature() +SketchConstraintCoincidence_8 = Sketch_3.setCoincident(SketchLine_9.startPoint(), SketchPoint_3.result()) +SketchConstraintCoincidence_9 = Sketch_3.setCoincident(SketchLine_5.startPoint(), SketchLine_9.endPoint()) +SketchConstraintCoincidence_10 = Sketch_3.setCoincident(SketchLine_6.endPoint(), SketchLine_9.result()) +SketchConstraintLength_1 = Sketch_3.setLength(SketchLine_8.result(), 20) +SketchConstraintLength_2 = Sketch_3.setLength(SketchLine_5.result(), 30) +SketchConstraintDistanceVertical_2 = Sketch_3.setVerticalDistance(SketchLine_7.endPoint(), SketchAPI_Point(SketchPoint_3).coordinates(), 15) +model.do() +Revolution_1 = model.addRevolution(Part_3_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection("EDGE", "PartSet/OX"), 45, 0) +model.end() + +### +### SHAPERSTUDY component +### + +if 'model' in globals(): + model.publishToShaperStudy() +import SHAPERSTUDY +Extrusion_1_1, = SHAPERSTUDY.shape(model.featureStringId(Extrusion_1)) +Fillet_1_1, = SHAPERSTUDY.shape(model.featureStringId(Fillet_1)) +Revolution_1_1, = SHAPERSTUDY.shape(model.featureStringId(Revolution_1)) +### +### SMESH component +### + +import SMESH, SALOMEDS +from salome.smesh import smeshBuilder + +smesh = smeshBuilder.New() +#smesh.SetEnablePublish( False ) # Set to False to avoid publish in study if not needed or in some particular situations: + # multiples meshes built in parallel, complex and numerous mesh edition (performance) + +Mesh_1 = smesh.Mesh(Fillet_1_1) +Regular_1D = Mesh_1.Segment() +Number_of_Segments_1 = Regular_1D.NumberOfSegments(7,None,[]) +MEFISTO_2D = Mesh_1.Triangle(algo=smeshBuilder.MEFISTO) +Max_Element_Area_1 = MEFISTO_2D.MaxElementArea(20) +isDone = Mesh_1.Compute() +assert(isDone) +Mesh_2 = smesh.Mesh(Extrusion_1_1) +Cartesian_3D = Mesh_2.BodyFitted() +Body_Fitting_Parameters_1 = Cartesian_3D.SetGrid([ [ '4.3589' ], [ 0, 1 ]],[ [ '4.3589' ], [ 0, 1 ]],[ [ '4.3589' ], [ 0, 1 ]],4,0) +Body_Fitting_Parameters_1.SetFixedPoint( SMESH.PointStruct ( 0, 0, 0 ), 1 ) +Body_Fitting_Parameters_1.SetAxesDirs( SMESH.DirStruct( SMESH.PointStruct ( 1, 0, 0 )), SMESH.DirStruct( SMESH.PointStruct ( 0, 1, 0 )), SMESH.DirStruct( SMESH.PointStruct ( 0, 0, 1 )) ) +isDone = Mesh_2.Compute() +assert(isDone) +Mesh_3 = smesh.Mesh(Revolution_1_1) +status = Mesh_3.AddHypothesis(Number_of_Segments_1) +Regular_1D_1 = Mesh_3.Segment() +isDone = Mesh_3.Compute() +assert(isDone) + +## Set names of Mesh objects +smesh.SetName(Regular_1D.GetAlgorithm(), 'Regular_1D') +smesh.SetName(MEFISTO_2D.GetAlgorithm(), 'MEFISTO_2D') +smesh.SetName(Cartesian_3D.GetAlgorithm(), 'Cartesian_3D') +smesh.SetName(Mesh_1.GetMesh(), 'Mesh_1') +smesh.SetName(Mesh_2.GetMesh(), 'Mesh_2') +smesh.SetName(Mesh_3.GetMesh(), 'Mesh_3') +smesh.SetName(Body_Fitting_Parameters_1, 'Body Fitting Parameters_1') +smesh.SetName(Max_Element_Area_1, 'Max. Element Area_1') +smesh.SetName(Number_of_Segments_1, 'Number of Segments_1') + +# check the SHAPER study objects generated names +assert(Extrusion_1_1.GetName() == "Extrusion_1_1") +assert(Fillet_1_1.GetName() == "Fillet_1_1") +assert(Revolution_1_1.GetName() == "Revolution_1_1") +# check the smesh mesh is computed correctly +assert(Mesh_1.NbNodes() == 235) +assert(Mesh_2.NbNodes() == 168) +assert(Mesh_3.NbNodes() == 80) diff --git a/src/ConnectorAPI/Test/tests.set b/src/ConnectorAPI/Test/tests.set index be23a5a85..4801850ae 100644 --- a/src/ConnectorAPI/Test/tests.set +++ b/src/ConnectorAPI/Test/tests.set @@ -25,4 +25,5 @@ SET(TEST_NAMES TestExportToGEOMWholeFeature Test2882 Test17917 + TestShaperStudy1.py ) diff --git a/src/ExchangePlugin/ExchangePlugin_Dump.cpp b/src/ExchangePlugin/ExchangePlugin_Dump.cpp index cf78b9b8c..9ca46901b 100644 --- a/src/ExchangePlugin/ExchangePlugin_Dump.cpp +++ b/src/ExchangePlugin/ExchangePlugin_Dump.cpp @@ -47,10 +47,13 @@ void ExchangePlugin_Dump::initAttributes() data()->addAttribute(GEOMETRIC_DUMP_ID(), ModelAPI_AttributeBoolean::typeId()); data()->addAttribute(WEAK_NAMING_DUMP_ID(), ModelAPI_AttributeBoolean::typeId()); + data()->addAttribute(EXPORT_VARIABLES_ID(), ModelAPI_AttributeBoolean::typeId()); + // default values boolean(TOPOLOGICAL_NAMING_DUMP_ID())->setValue(true); boolean(GEOMETRIC_DUMP_ID())->setValue(true); boolean(WEAK_NAMING_DUMP_ID())->setValue(false); + boolean(EXPORT_VARIABLES_ID())->setValue(false); } void ExchangePlugin_Dump::execute() @@ -141,6 +144,14 @@ void ExchangePlugin_Dump::dump(const std::string& theFileName) aDumper->addCustomStorage(aWeakNamingStorage); } - if (!aDumper->process(aDoc, theFileName)) - setError("An error occured while dumping to " + theFileName); + if (!aDumper->process(aDoc, theFileName)) { + setError("An error occurred while dumping to " + theFileName); + } else { + if (boolean(EXPORT_VARIABLES_ID())->value()) { + aDumper->exportVariables(); + } + } + // clear cashed data after export variables was performed + aDumper->clearCustomStorage(); + } diff --git a/src/ExchangePlugin/ExchangePlugin_Dump.h b/src/ExchangePlugin/ExchangePlugin_Dump.h index 5ee0f004b..1d7127b0b 100644 --- a/src/ExchangePlugin/ExchangePlugin_Dump.h +++ b/src/ExchangePlugin/ExchangePlugin_Dump.h @@ -71,6 +71,13 @@ public: return MY_WEAK_NAMING_DUMP_ID; } + /// attribute name for boolean flag to export variable names correspondence to another module + inline static const std::string& EXPORT_VARIABLES_ID() + { + static const std::string MY_EXPORT_VARIABLES_ID("export_variables"); + return MY_EXPORT_VARIABLES_ID; + } + /// Default constructor EXCHANGEPLUGIN_EXPORT ExchangePlugin_Dump(); /// Default destructor diff --git a/src/ModelHighAPI/ModelHighAPI_Dumper.cpp b/src/ModelHighAPI/ModelHighAPI_Dumper.cpp index 9df987e61..577f8b2db 100644 --- a/src/ModelHighAPI/ModelHighAPI_Dumper.cpp +++ b/src/ModelHighAPI/ModelHighAPI_Dumper.cpp @@ -645,7 +645,6 @@ bool ModelHighAPI_Dumper::process(const std::shared_ptr& theD // dump subfeatures and store result to file bool isOk = process(theDoc) && myDumpStorage->exportTo(theFileName, myModules); - clearCustomStorage(); return isOk; } @@ -1483,3 +1482,24 @@ ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper, return theDumper; } + + +void ModelHighAPI_Dumper::exportVariables() const +{ + DocumentPtr aRoot = ModelAPI_Session::get()->moduleDocument(); + EntityNameMap::const_iterator aNameIter = myNames.cbegin(); + for(; aNameIter != myNames.end(); aNameIter++) { + FeaturePtr aFeature = std::dynamic_pointer_cast(aNameIter->first); + if (aFeature.get() && aFeature->document() != aRoot) { + FeaturePtr aPartFeat = ModelAPI_Tools::findPartFeature(aRoot, aFeature->document()); + if (aPartFeat.get()) { + int aFeatureId = aFeature->data()->featureId(); + int aPartId = aPartFeat->data()->featureId(); + std::ostringstream anEntryStr; + anEntryStr<second.myCurrentName); + } + } + } +} diff --git a/src/ModelHighAPI/ModelHighAPI_Dumper.h b/src/ModelHighAPI/ModelHighAPI_Dumper.h index 2bbc29435..211ce075d 100644 --- a/src/ModelHighAPI/ModelHighAPI_Dumper.h +++ b/src/ModelHighAPI/ModelHighAPI_Dumper.h @@ -159,7 +159,6 @@ public: /// Clear custom storages list MODELHIGHAPI_EXPORT void clearCustomStorage(); - /// Dump given document into the file /// \return \c true, if succeed MODELHIGHAPI_EXPORT @@ -335,6 +334,13 @@ public: MODELHIGHAPI_EXPORT bool isDumped(const std::shared_ptr& theRefList) const; + /// Export variables names to another module (calls exportVariable implemented in python) + MODELHIGHAPI_EXPORT virtual void exportVariables() const; + + /// Export one variable name to another module (implemented in python) + MODELHIGHAPI_EXPORT virtual void exportVariable( + const std::string& theEntry, const std::string& theVarName) const {} + protected: /// Dump "setName" command if last entity had user-defined name MODELHIGHAPI_EXPORT void dumpEntitySetName(); diff --git a/src/PythonAPI/model/dump/DumpAssistant.py b/src/PythonAPI/model/dump/DumpAssistant.py index 0b3eeb167..3170cc857 100644 --- a/src/PythonAPI/model/dump/DumpAssistant.py +++ b/src/PythonAPI/model/dump/DumpAssistant.py @@ -44,6 +44,7 @@ class DumpAssistant(ModelHighAPI.ModelHighAPI_Dumper): ModelHighAPI.ModelHighAPI_Dumper.__init__(self) ModelHighAPI.ModelHighAPI_Dumper.setInstance(self) self.collectFeatures() + self.myEngine = None ## Collect feature wrappers, which allow dumping (have method dump) def collectFeatures(self): @@ -97,5 +98,18 @@ class DumpAssistant(ModelHighAPI.ModelHighAPI_Dumper): return self.myWrapperNames[aFeatureKind] return std_string() + ## Exports the dumped variables names to the SHAPERSTUDY + def exportVariable(self, theEntry, theVarName): + try: + if self.myEngine == None: + import SHAPERSTUDY_utils + aComponent = SHAPERSTUDY_utils.findOrCreateComponent() + self.myEngine = SHAPERSTUDY_utils.getEngine() + if self.myEngine != 1: + self.myEngine.StoreVariableName(theEntry, theVarName) + except: + self.myEngine = 1 # invalid access + pass + # Instance of dumper dumper = DumpAssistant diff --git a/src/PythonAPI/model/services/__init__.py b/src/PythonAPI/model/services/__init__.py index e5bc14478..5e10f000e 100644 --- a/src/PythonAPI/model/services/__init__.py +++ b/src/PythonAPI/model/services/__init__.py @@ -29,9 +29,19 @@ from ModelHighAPI import reset from ModelHighAPI import addFolder, removeFolder from ModelHighAPI import ModelHighAPI_Selection as selection from ModelHighAPI import checkPythonDump as checkPythonDump +from ModelAPI import findPartFeature # a method used for the python dump of the SHAPER STUDY def publishToShaperStudy(): begin() activeDocument().addFeature("PublishToStudy") end() + +# returns unique identifier of the feature : id of part it belongs to + ":" + id of feature +def featureStringId(theFeature): + aRoot = moduleDocument() + aCurrent = theFeature.feature().document() + if aRoot and aCurrent: + print(str(dir())) + return str(findPartFeature(aRoot, aCurrent).data().featureId()) + ":" + str(theFeature.feature().data().featureId()) + return "" diff --git a/src/SHAPERGUI/SHAPERGUI_DataModel.cpp b/src/SHAPERGUI/SHAPERGUI_DataModel.cpp index a84de59df..5a2effdc7 100644 --- a/src/SHAPERGUI/SHAPERGUI_DataModel.cpp +++ b/src/SHAPERGUI/SHAPERGUI_DataModel.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -199,6 +200,10 @@ bool SHAPERGUI_DataModel::dumpPython(const QString& thePath, CAM_Study* theStudy if (aAttr.get()) aAttr->setValue(".py"); +#ifdef HAVE_SALOME + aFeature->boolean(ExchangePlugin_Dump::EXPORT_VARIABLES_ID())->setValue(true); +#endif + ModelAPI_Session::get()->finishOperation(); if (QFile::exists(aFileName.c_str())) { @@ -237,4 +242,3 @@ bool SHAPERGUI_DataModel::dumpPython(const QString& thePath, CAM_Study* theStudy } return false; } - -- 2.39.2