Salome HOME
Make SHAPER STUDY fields exported in SMESH into MED file
[modules/shaper.git] / src / ConnectorPlugin / ConnectorPlugin_PublishToStudyFeature.py
1 # Copyright (C) 2014-2019  CEA/DEN, EDF R&D
2 #
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2.1 of the License, or (at your option) any later version.
7 #
8 # This library is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 # Lesser General Public License for more details.
12 #
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 #
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 #
19
20 ## @package Plugins
21 #  ExportFeature class definition
22
23 import ModelAPI
24 import ExchangeAPI
25 import EventsAPI
26 from GeomAPI import *
27 import GeomAlgoAPI
28
29 import salome
30 from salome.shaper import model
31
32 import SHAPERSTUDY_ORB
33 import SHAPERSTUDY_utils
34
35 ## @ingroup Plugins
36 #  Feature to export all shapes and groups into the GEOM module
37 class PublishToStudyFeature(ModelAPI.ModelAPI_Feature):
38
39     ## The constructor.
40     def __init__(self):
41         ModelAPI.ModelAPI_Feature.__init__(self)
42         pass
43
44     @staticmethod
45     ## Export kind. Static.
46     def ID():
47         return "PublishToStudy"
48
49     ## Returns the kind of a feature.
50     def getKind(self):
51         return PublishToStudyFeature.ID()
52
53     ## This feature is action: has no property panel and executes immediately.
54     def isAction(self):
55         return True
56
57     ## This feature has no attributes, as it is action.
58     def initAttributes(self):
59         pass
60
61     ## Exports all shapes and groups into the GEOM module.
62     def execute(self):
63         aSession = ModelAPI.ModelAPI_Session.get()
64         aPartSet = aSession.moduleDocument()
65         # check that the PartSet document current feature is the last to avoid problems with all
66         # features update
67         if aPartSet.size(model.ModelAPI_Feature_group()) > 0:
68           aLastFeature = ModelAPI.objectToFeature(aPartSet.object(model.ModelAPI_Feature_group(), aPartSet.size(model.ModelAPI_Feature_group()) - 1))
69           aCurrentFeature = aPartSet.currentFeature(True)
70           if aLastFeature.data().featureId() != aCurrentFeature.data().featureId():
71             EventsAPI.Events_InfoMessage("PublishToStudy", "Not all PartSet parts are up-to-date, nothing is published. Please, make the last PartSet feature as current.", self).send()
72             return
73         # find a shaper-study component
74         salome.salome_init(1)
75         aComponent = SHAPERSTUDY_utils.findOrCreateComponent()
76         anEngine = SHAPERSTUDY_utils.getEngine()
77         # collect all processed internal entries to break the link of unprocessed later
78         allProcessed = []
79
80         # iterate all parts and all results to publish them in SHAPER_STUDY
81         for aPartId in range(aPartSet.size(model.ModelAPI_ResultPart_group())):
82           aPartObject = aPartSet.object(model.ModelAPI_ResultPart_group(), aPartId)
83           aPartRes = ModelAPI.modelAPI_ResultPart(ModelAPI.modelAPI_Result(aPartObject))
84           aPartDoc = aPartRes.partDoc()
85           if aPartDoc is None and aPartObject is not None:
86             EventsAPI.Events_InfoMessage("PublishToStudy", "For publish to SHAPER-STUDY some Part is not activated", self).send()
87             break
88           aPartFeatureId = aPartSet.feature(aPartRes).data().featureId()
89           for aResId in range(aPartDoc.size(model.ModelAPI_ResultBody_group())):
90             aResObject = aPartDoc.object(model.ModelAPI_ResultBody_group(), aResId)
91             aRes = model.objectToResult(aResObject)
92             aResFeatureId = aPartDoc.feature(aRes).data().featureId()
93             aSSEntry = str(aPartFeatureId) + ":" + str(aResFeatureId)
94             aSShape = anEngine.FindOrCreateShape(aSSEntry)
95             aSShape.SetShapeByStream(aRes.shape().getShapeStream(False))
96             if not aSShape.GetSO(): # publish in case it is a new shape
97               anEngine.AddInStudy(aSShape, aRes.data().name(), None)
98             else: # restore a red reference if it was deleted
99               aDone, aSO2 = aSShape.GetSO().FindSubObject(1)
100               if aDone:
101                 aDone, aRef = aSO2.ReferencedObject()
102                 if not aDone:
103                   aBuilder = SHAPERSTUDY_utils.getStudy().NewBuilder()
104                   aBuilder.Addreference(aSO2, aSShape.GetSO())
105             allProcessed.append(aSSEntry)
106             # Groups
107             self.processGroups(aRes, anEngine, aPartFeatureId, aSShape, False)
108             # Fields
109             self.processGroups(aRes, anEngine, aPartFeatureId, aSShape, True)
110
111         # process all SHAPER-STUDY shapes to find dead
112         aSOIter = SHAPERSTUDY_utils.getStudy().NewChildIterator(aComponent)
113         while aSOIter.More():
114           aSO = aSOIter.Value()
115           anIOR = aSO.GetIOR()
116           if len(anIOR):
117             anObj = salome.orb.string_to_object(anIOR)
118             if isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Object):
119               anEntry = anObj.GetEntry()
120               if len(anEntry) == 0:
121                 continue;
122               elif anEntry not in allProcessed: # found a removed shape: make it dead for the moment
123                 # remove the reference - red node
124                 aRes, aSO2 = aSO.FindSubObject(1)
125                 if aRes:
126                   aRes, aRef = aSO2.ReferencedObject()
127                   if aRes:
128                     aBuilder = SHAPERSTUDY_utils.getStudy().NewBuilder()
129                     aBuilder.RemoveReference(aSO2)
130           aSOIter.Next()
131
132     # Part of the "execute" method: processes the Groups of theRes result publication.
133     # If theFields is true, the same is performed for Fields.
134     def processGroups(self, theRes, theEngine, thePartFeatureId, theStudyShape, theFields):
135       allGroupsProcessed = []
136       if theFields:
137         aRefGroups = ModelAPI.referencedFeatures(theRes, "Field", True)
138       else:
139         aRefGroups = ModelAPI.referencedFeatures(theRes, "Group", True)
140       for aRef in aRefGroups:
141         aGroupIndices = []
142         aGroupHasIndex = {}
143         aResShape = theRes.shape()
144         if theFields:
145           aSelList = aRef.selectionList("selected")
146         else:
147           aSelList = aRef.selectionList("group_list")
148         aSelType = GeomAPI_Shape.shapeTypeByStr(aSelList.selectionType())
149         for aSelIndex in range(aSelList.size()):
150           aSelection = aSelList.value(aSelIndex)
151           if aSelection.contextObject():
152             aShape = aSelection.value()
153             if aShape:
154               allShapesList = [] # collect all sub-shapes selected in the group
155               if aShape.shapeType() == 0: # compound
156                 anExplorer = GeomAPI_ShapeExplorer(aShape, aSelType)
157                 while anExplorer.more():
158                   allShapesList.append(anExplorer.current())
159                   anExplorer.next()
160               else:
161                 allShapesList.append(aShape)
162               # get index of each selected shape: if 0, this sub-shape is not in our result
163               for aSelected in allShapesList:
164                 anId = GeomAlgoAPI.GeomAlgoAPI_CompoundBuilder.id(aResShape, aSelected)
165                 if anId > 0 and not anId in aGroupHasIndex:
166                   aGroupIndices.append(anId)
167                   aGroupHasIndex[anId] = 0
168         if len(aGroupIndices): # create group
169           aGroupFeatureId = aRef.data().featureId()
170           if theFields:
171             aFieldOp = theEngine.GetIFieldOperations()
172             aGroupEntry = "field" + str(thePartFeatureId) + ":" + str(aGroupFeatureId)
173             aGroup = aFieldOp.FindField(theStudyShape, aGroupEntry)
174           else:
175             aGroupOp = theEngine.GetIGroupOperations()
176             aGroupEntry = "group" + str(thePartFeatureId) + ":" + str(aGroupFeatureId)
177             aGroup = aGroupOp.FindGroup(theStudyShape, aGroupEntry)
178           if not aGroup: # create a new
179             if theFields:
180               aGroup = aFieldOp.CreateFieldByType(theStudyShape, aSelType)
181             else:
182               aGroup = aGroupOp.CreateGroup(theStudyShape, aSelType)
183             aGroup.SetEntry(aGroupEntry)
184             theEngine.AddInStudy(aGroup, aRef.firstResult().data().name(), theStudyShape.GetSO())
185           aGroup.SetSelection(aGroupIndices)
186           if theFields:
187             self.fillField(aGroup, aRef, theEngine, aGroupIndices)
188           # a group takes shape from the main result
189           #aGroup.SetShapeByStream(aRef.firstResult().shape().getShapeStream(False)) # group shape
190           allGroupsProcessed.append(aGroupEntry)
191       # check all existing groups: if some does not processed, remove it from the tree
192       aSOIter = SHAPERSTUDY_utils.getStudy().NewChildIterator(theStudyShape.GetSO())
193       while aSOIter.More():
194         aSO = aSOIter.Value()
195         anIOR = aSO.GetIOR()
196         if len(anIOR):
197           anObj = salome.orb.string_to_object(anIOR)
198           if (theFields and isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Field)) or \
199              (not theFields and type(anObj) == SHAPERSTUDY_ORB._objref_SHAPER_Group):
200             anEntry = anObj.GetEntry()
201             if anEntry not in allGroupsProcessed: # found a removed group => remove
202               aBuilder = SHAPERSTUDY_utils.getStudy().NewBuilder()
203               aBuilder.RemoveObject(anObj.GetSO())
204         aSOIter.Next()
205
206     # Part of the "execute" method: theFiled fields filling.
207     def fillField(self, theField, theFeature, theEngine, theSelectionIndices):
208       aTables = theFeature.tables("values")
209       aValType = aTables.type() # type of the values
210       theField.SetValuesType(aValType)
211       aNumSteps = aTables.tables() # number of steps is number of tables
212       aSteps = []
213       for aVal in range(aNumSteps):
214         aSteps.append(aVal + 1)
215       theField.SetSteps(aSteps)
216       aCompNames = []
217       aCompNamesAttr = theFeature.stringArray("components_names")
218       for anIndex in range(aCompNamesAttr.size()):
219         aCompNames.append(aCompNamesAttr.value(anIndex))
220       theField.SetComponents(aCompNames)
221       # prepare the sub-shapes indices: all values for all sub-shapes must be defined
222       aShapeOp = theEngine.GetIShapesOperations()
223       allIndices = aShapeOp.GetAllSubShapesIDs(theField.GetShape(), theField.GetSelectionType(), False)
224       # define steps
225       theField.ClearFieldSteps()
226       for aVal in range(aNumSteps):
227         aVals = []
228         for aCol in range(aTables.columns()):
229           #for aRow in range(aTables.rows()):
230           for anIndex in allIndices:
231             if anIndex in theSelectionIndices:
232               aRow = theSelectionIndices.index(anIndex) + 1 # starting from the first line
233             else:
234               aRow = 0 # default value
235             aStrVal = aTables.valueStr(aRow, aCol, aVal)
236             if aValType == 0: # boolean
237               if aStrVal == "True":
238                 aVals.append(1)
239               else:
240                 aVals.append(0)
241             elif aValType == 1: # int
242               aVals.append(int(aStrVal))
243             elif aValType == 2: # double
244               aVals.append(float(aStrVal))
245         theField.AddFieldStep(theFeature.intArray("stamps").value(aVal), aVal + 1, aVals)