Salome HOME
b2e45190d31fd604b2dcd98c24472c357c5cf5ad
[modules/shaper_study.git] / src / PY / SHAPERSTUDY.py
1 # Copyright (C) 2019-2020  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 import SHAPERSTUDY_ORB__POA
21 import SHAPERSTUDY_ORB
22 import SALOME_ComponentPy
23 import SALOME_DriverPy
24 import SALOMEDS
25 from SHAPERSTUDY_utils import findOrCreateComponent, moduleName, getStudy, getORB
26 import salome
27 import SHAPERSTUDY_Object
28 import SHAPERSTUDY_IOperations
29 import GEOM
30 import SMESH
31
32 import StudyData_Swig
33
34 # for unit tests correct execution
35 salome.salome_init(1)
36
37 __entry2IOR__ = {}
38 __entry2DumpName__ = {}
39
40 class SHAPERSTUDY_Gen(SHAPERSTUDY_ORB__POA.Gen, SALOME_ComponentPy.SALOME_ComponentPy_i, SALOME_DriverPy.SALOME_DriverPy_i):
41
42     ShapeType = {"AUTO":-1, "COMPOUND":0, "COMPSOLID":1, "SOLID":2, "SHELL":3, "FACE":4, "WIRE":5, "EDGE":6, "VERTEX":7, "SHAPE":8, "FLAT":9}
43     
44     ShaperIcons = {GEOM.COMPOUND:"compsolid.png",
45         GEOM.COMPSOLID:"compsolid.png",
46         GEOM.SOLID:"solid.png",
47         GEOM.SHELL:"shell.png",
48         GEOM.FACE:"face.png",
49         GEOM.WIRE:"wire.png",
50         GEOM.EDGE:"edge.png",
51         GEOM.VERTEX:"vertex.png",
52         GEOM.SHAPE:"solid.png",
53         GEOM.FLAT:"face.png"
54         }
55
56     def FindOrCreateShape( self, theInternalEntry ):
57         """
58         Searches existing or creates a new SHAPERSTUDY_Object to interact with SHAPER
59         """
60         # Searching in the study tree
61         aComponent = findOrCreateComponent()
62         aSOIter = getStudy().NewChildIterator(aComponent)
63         while aSOIter.More():
64           aSO = aSOIter.Value()
65           anIOR = aSO.GetIOR()
66           if len(anIOR):
67             anObj = salome.orb.string_to_object(anIOR)
68             if anObj and isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Object):
69               if anObj.GetEntry() == theInternalEntry:
70                 return anObj
71           aSOIter.Next()
72
73         aShapeObj = SHAPERSTUDY_Object.SHAPERSTUDY_Object()
74         aShapeObj.SetEntry(theInternalEntry)
75         return aShapeObj._this()
76
77     def AddInStudy( self, theObject, theName, theFather ):
78         """
79         Adds in theStudy a object theObject under theFather with a name theName,
80         if theFather is not NULL the object is placed under theFather's SObject.
81         Returns a SObject where theObject is placed
82         """
83         if not theObject.GetEntry():
84             return None # object not existing in shaper
85         aStudy = getStudy()
86         aBuilder = aStudy.NewBuilder()
87         isGroup = theObject.GetType() == 37 or theObject.GetType() == 52
88         if not theFather:
89           if isGroup:
90             return None # Group may be added only under the shape-father
91           theFatherSO = findOrCreateComponent()
92         else:
93           theFatherSO = theFather.GetSO()
94         aResultSO = None
95         if isGroup:
96           aTag = 2
97           anIter = aStudy.NewChildIterator(theFatherSO)
98           while anIter.More():
99             if anIter.Value().Tag() == 10000: # skip the history folder
100               anIter.Next()
101               continue
102             aCurrentTag = anIter.Value().Tag() + 1
103             anIter.Next()
104             if aTag < aCurrentTag:
105               aTag = aCurrentTag
106           if aTag == 10000: # to avoid putting the object to the history folder
107             aTag += 1
108           aResultSO = aBuilder.NewObjectToTag(theFatherSO, aTag)
109         else:
110           aResultSO = aBuilder.NewObject(theFatherSO);
111         aResultSO.SetAttrString("AttributeName", theName)
112         if theObject is not None:
113             anIOR = salome.orb.object_to_string(theObject)
114             aResultSO.SetAttrString("AttributeIOR", anIOR)
115             theObject.SetSO(aResultSO)
116           
117             aAttr = aBuilder.FindOrCreateAttribute(aResultSO, "AttributePixMap")
118             aPixmap = aAttr._narrow(salome.SALOMEDS.AttributePixMap)
119             aType = 0
120             if isGroup:
121               aType = SHAPERSTUDY_Object.__shape_types__[theObject.GetSelectionType()]
122             else:
123               aType = theObject.GetShapeType()
124             aPixmap.SetPixMap(self.ShaperIcons[aType])
125             
126         # add a red-reference that means that this is an active reference to SHAPER result
127         if not isGroup:
128           aSub = aBuilder.NewObjectToTag(aResultSO, 1)
129           aBuilder.Addreference(aSub, aResultSO)
130
131         return aResultSO
132
133     def StoreVariableName(self, theEntry, theVarName):
134         """
135         Stores the variable names of the SHAPER dump to python
136         """
137         __entry2DumpName__["s" + theEntry] = theVarName
138
139
140     def AddSubShape( theMainShape, theIndices ):
141         """
142         Add a sub-shape defined by indices in theIndices
143         (contains unique IDs of sub-shapes inside theMainShape)
144         """
145         # no sub-shapes for the moment
146         go = SHAPERSTUDY_Object()._this()
147         return go
148
149     # For now it is impossible to remove anything from the SHAPER-STUDY
150     def RemoveObject( self, theObject ):
151         """
152         Removes the object from the component
153         """
154         # can not be removed for the moment
155         return
156
157     def GetIFieldOperations( self ):
158         """
159         """
160         return SHAPERSTUDY_IOperations.SHAPERSTUDY_IFieldOperations()._this()
161
162     def GetIGroupOperations( self ):
163         """
164         """
165         return SHAPERSTUDY_IOperations.SHAPERSTUDY_IGroupOperations()._this()
166
167     def GetIShapesOperations( self ):
168         """
169         """
170         return SHAPERSTUDY_IOperations.SHAPERSTUDY_IShapesOperations()._this()
171
172     def GetIMeasureOperations( self ):
173         """
174         """
175         return SHAPERSTUDY_IOperations.SHAPERSTUDY_IMeasureOperations()._this()
176
177     def GetStringFromIOR( self, theObject ):
178         """
179         Returns a string which contains an IOR of the SHAPERSTUDY_Object
180         """
181         IOR = ""
182         if theObject and getORB():
183             IOR = getORB().object_to_string( theObject )
184             pass
185         return IOR
186
187     def Save( self, component, URL, isMultiFile ):
188         """
189         Saves data: all objects into one file
190         """
191         aResult = "" # string-pairs of internal entries and shape streams
192         aStudy = getStudy()
193         # get all sub-SObjects with IOR defined
194         anIters = [aStudy.NewChildIterator(findOrCreateComponent())]
195         aSOList = []
196         while len(anIters):
197           aLast = anIters[len(anIters) - 1]
198           if aLast.More():
199             aSO = aLast.Value()
200             anIOR = aSO.GetIOR()
201             if len(anIOR):
202               aSOList.append(aSO)
203             anIters.append(aStudy.NewChildIterator(aSO))
204             aLast.Next()
205           else:
206             anIters.remove(aLast)
207
208         for aSO in aSOList: # for each sobject export shapes stream if exists
209           anIOR = aSO.GetIOR()
210           if not len(anIOR):
211             continue
212           anObj = salome.orb.string_to_object(anIOR)
213           if type(anObj) == SHAPERSTUDY_ORB._objref_SHAPER_Group:
214             if len(aResult):
215               aResult += '|'
216             # store internal entry, type and list of indices of the group selection (separated by spaces)
217             aResult += anObj.GetEntry() + "|" + str(anObj.GetSelectionType())
218             aSelList = anObj.GetSelection()
219             aResult += "|" + str(' '.join(str(anI) for anI in aSelList))
220             aSelListOld = anObj.GetSelectionOld()
221             aResult += ";" + str(' '.join(str(anI) for anI in aSelListOld))
222           elif type(anObj) == SHAPERSTUDY_ORB._objref_SHAPER_Field:
223             if len(aResult):
224               aResult += '|'
225             # same as for group, but in addition to the second string part - field specifics
226             aResult += anObj.GetEntry() + "|" + str(anObj.GetSelectionType())
227             aResult += " " + str(anObj.GetDataType()) # values type
228             aSteps = anObj.GetSteps()
229             aResult += " " + str(len(aSteps)) # number of steps
230             aComps = anObj.GetComponents()
231             aResult += " " + str(len(aComps)) # number of components
232             for aComp in aComps: # components strings: but before remove spaces and '|'
233               aCoded = aComp.replace(" ", "__space__").replace("|", "__vertical_bar__")
234               aResult += " " + aCoded
235             for aStepNum in range(len(aSteps)):
236               aVals = anObj.GetStep(aStepNum + 1).GetValues()
237               if aStepNum == 0:
238                 aResult += " " + str(len(aVals)) # first the number of values in the step
239               aResult += " " + str(anObj.GetStep(aStepNum + 1).GetStamp()) # ID of stamp in step
240               for aVal in aVals:
241                 aResult += " " + str(aVal) # all values of step
242             aSelList = anObj.GetSelection()
243             aResult += "|" + str(' '.join(str(anI) for anI in aSelList))
244             aSelListOld = anObj.GetSelectionOld()
245             aResult += ";" + str(' '.join(str(anI) for anI in aSelListOld))
246           elif isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Object):
247             if len(aResult):
248               aResult += '|'
249             # store internal entry + tick, current and old shapes in BRep format
250             aResult += anObj.GetEntry() + " " + str(anObj.GetTick())
251             aResult += "|" + anObj.GetShapeStream().decode()
252             aResult += "|" + anObj.GetOldShapeStream().decode()
253
254         return aResult.encode()
255
256     def Load( self, component, stream, URL, isMultiFile ):
257         """
258         Loads data
259         """
260         global __entry2IOR__
261         __entry2IOR__.clear()
262         aList=stream.decode().split('|')
263         aSubNum = 1
264         anId = ""
265         aNewShapeStream = ""
266         for aSub in aList:
267           if aSubNum == 1:
268             anId = aSub
269             aSubNum = 2
270           elif aSubNum == 2:
271             aNewShapeStream = aSub
272             aSubNum = 3
273           else: # create objects by 3 arguments
274             anObj = None
275             if anId.startswith('group') or (anId.startswith('dead') and anId.count("group") > 0): # group object
276               anObj = SHAPERSTUDY_Object.SHAPERSTUDY_Group()
277               if len(aSub):
278                 aSel = aSub.split(";")
279                 if len(aSel) > 1 and len(aSel[1]):
280                   anObj.SetSelection([int(anI) for anI in aSel[1].split(' ')]) # old selection
281                 anObj.SetSelection([int(anI) for anI in aSel[0].split(' ')])
282               anObj.SetSelectionType(int(aNewShapeStream))
283             elif anId.startswith('field') or (anId.startswith('dead') and anId.count("field") > 0): # field object
284               anObj = SHAPERSTUDY_Object.SHAPERSTUDY_Field()
285               if len(aSub):
286                 aSel = aSub.split(";")
287                 if len(aSel) > 1:
288                   anObj.SetSelection([int(anI) for anI in aSel[1].split(' ')]) # old selection
289                 anObj.SetSelection([int(anI) for anI in aSel[0].split(' ')])
290               aParams = aNewShapeStream.split(" ")
291               anObj.SetSelectionType(int(aParams[0]))
292               aTypeStr = aParams[1]
293               if (aTypeStr == "FDT_Bool"):
294                 anObj.SetValuesType(0)
295               elif (aTypeStr == "FDT_Int"):
296                 anObj.SetValuesType(1)
297               elif (aTypeStr == "FDT_Double"):
298                 anObj.SetValuesType(2)
299               elif (aTypeStr == "FDT_String"):
300                 anObj.SetValuesType(3)
301               aSteps = []
302               aNumSteps = int(aParams[2])
303               for aVal in range(aNumSteps):
304                 aSteps.append(aVal + 1)
305               anObj.SetSteps(aSteps)
306               aCompNum = int(aParams[3])
307               aCompNames = []
308               for aCompNameIndex in range(aCompNum):
309                 aCompName = aParams[4 + aCompNameIndex].replace("__space__", " ").replace("__vertical_bar__", "|")
310                 aCompNames.append(aCompName)
311               anObj.SetComponents(aCompNames)
312               aNumValsInStep = int(aParams[4 + aCompNum])
313               for aStepNum in range(aNumSteps):
314                 aStepStartIndex = 4 + aCompNum + aStepNum * (aNumValsInStep + 1) + 1
315                 aStampId = int(aParams[aStepStartIndex])
316                 aVals = []
317                 for aValIndex in range(aNumValsInStep):
318                   aVals.append(float(aParams[aStepStartIndex + aValIndex + 1]))
319                 anObj.AddFieldStep(aStampId, aStepNum + 1, aVals)
320               anObj.SetTick(-3)
321             else: # shape object by BRep in the stream: set old first then new
322               anObj = SHAPERSTUDY_Object.SHAPERSTUDY_Object()
323               if len(aSub):
324                 anObj.SetShapeByStream(aSub)
325               anObj.SetShapeByStream(aNewShapeStream)
326             if anObj:
327               anEntryAndTick = anId.split(" ")
328               anObj.SetEntry(anEntryAndTick[0])
329               if len(anEntryAndTick) > 1:
330                 anObj.SetTick(int(anEntryAndTick[1]))
331               anIOR = salome.orb.object_to_string(anObj._this())
332               __entry2IOR__[anEntryAndTick[0]] = anIOR
333             aSubNum = 1
334         return 1
335         
336     def IORToLocalPersistentID(self, sobject, IOR, isMultiFile, isASCII):
337         """
338         Gets persistent ID for the CORBA object.
339         The internal entry of the Object is returned.
340         """
341         anObj = salome.orb.string_to_object(IOR)
342         if anObj and (isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Object) or \
343                       isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Field)):
344           return anObj.GetEntry()
345         return ""
346
347     def LocalPersistentIDToIOR(self, sobject, persistentID, isMultiFile, isASCII):
348         "Converts persistent ID of the object to its IOR."
349         global __entry2IOR__
350         if persistentID in __entry2IOR__:
351           aRes = __entry2IOR__[persistentID]
352           if len(aRes): # set SO from the study, the sobject param is temporary, don't store it
353              aSO = getStudy().FindObjectID(sobject.GetID())
354              anObj = salome.orb.string_to_object(aRes)
355              anObj.SetSO(aSO)
356              # restore tick of the sub-object
357              anIOR = aSO.GetFather().GetIOR()
358              if len(anIOR):
359                anFatherObj = salome.orb.string_to_object(anIOR)
360                if anFatherObj and isinstance(anFatherObj, SHAPERSTUDY_ORB._objref_SHAPER_Object):
361                  anObj.SetTick(anFatherObj.GetTick())
362           return aRes
363         return ""
364     
365     def UniqueDumpName( self, theBaseName, theID ):
366         """
367         Returns a unique name from the theBaseName. Keeps theBaseName if it was not used yet.
368         Stores the newly generated name into the global map __entry2DumpName__.
369         """
370         global __entry2DumpName__
371         aPrefix = 1
372         # to avoid spaces and parenthesis in the variable name
373         aBaseName = theBaseName.replace(" ", "_").replace("(", "").replace(")", "")
374         aName = aBaseName
375         while aName in __entry2DumpName__.values():
376           aName = aBaseName + "_" + str(aPrefix)
377           aPrefix = aPrefix + 1
378         __entry2DumpName__[theID] = aName
379         return aName
380
381     def GetShaperEntry(self, theShapeObj):
382         """
383         Returns string in the python dump that generates the SHAPER entry:
384         it may be just entry string, or call for the SHAPER dump variable.
385         """
386         global __entry2DumpName__
387         anEntry = "s" + theShapeObj.GetEntry()
388         if anEntry in __entry2DumpName__:
389           anArg = ""
390           if anEntry.count(":") == 2: # not first result of the feature, set argument as a number
391             anArg = ", " + anEntry[anEntry.rfind(":") + 1:]
392           return "model.featureStringId(" + __entry2DumpName__[anEntry] + anArg + ")"
393         return "\"" + theShapeObj.GetEntry() + "\""
394
395     def OrderGroups(self, theStudy, theStartSO, theIsGroup):
396         """
397         An internal method for returning sub-groups or sub-fields in a correct order basing on their IDs
398         """
399         aResult = []
400         anIter = theStudy.NewChildIterator(theStartSO)
401         anOrder = {} # entry to object
402         while anIter.More():
403           anSO = anIter.Value()
404           anIter.Next()
405           anIOR = anSO.GetIOR()
406           if len(anIOR):
407             anObj = salome.orb.string_to_object(anIOR)
408             if (theIsGroup and isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Group)) or \
409                (not theIsGroup and isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Field)):
410               anEntry = anObj.GetEntry()
411               aSplit = anEntry.split(":")
412               if len(aSplit) > 1 and aSplit[1].isdecimal():
413                 anID = int(aSplit[1])
414                 anOrder[anID] = anObj
415
416         for aKey in sorted(anOrder.keys()):
417           aResult.append(anOrder[aKey])
418
419         return aResult
420
421
422     def DumpPython( self, isPublished, isMultiFile ):
423         """
424         Dump module data to the Python script.
425         """
426         global __entry2DumpName__
427         # remove all non-SHAPER entries
428         aCopyMap = {}
429         for anEntry in __entry2DumpName__:
430           if anEntry.startswith("s"):
431             aCopyMap[anEntry] = __entry2DumpName__[anEntry]
432         __entry2DumpName__ = aCopyMap
433
434         anArchiveNum = 1
435         # collect all shape-objects in the SHAPERSTUDY tree
436         aShapeObjects = []
437         aStudy = getStudy()
438         aRoots = aStudy.NewChildIterator(findOrCreateComponent())
439         while aRoots.More():
440           aSO = aRoots.Value()
441           anIOR = aSO.GetIOR()
442           if len(anIOR):
443             anObj = salome.orb.string_to_object(anIOR)
444             if anObj and type(anObj) == SHAPERSTUDY_ORB._objref_SHAPER_Object:
445               aShapeObjects.append(anObj)
446           aRoots.Next()
447         script = []
448         if len(aShapeObjects):
449           script.append("model.publishToShaperStudy()")
450           script.append("import SHAPERSTUDY")
451           for aShapeObj in aShapeObjects:
452             # check this shape also has sub-groups and fields
453             anOrderedGroups = self.OrderGroups(aStudy, aShapeObj.GetSO(), True)
454             anOrderedFields = self.OrderGroups(aStudy, aShapeObj.GetSO(), False)
455             anObjects = anOrderedGroups + anOrderedFields
456
457             aGroupVarNames = []
458             for anObj in anObjects:
459               aGroupVarName = self.UniqueDumpName(anObj.GetName(), anObj.GetSO().GetID())
460               aGroupVarNames.append(aGroupVarName)
461
462             aShapeVar = self.UniqueDumpName(aShapeObj.GetName(), aShapeObj.GetSO().GetID())
463             aShapeStr = aShapeVar + ", "
464             for aGName in aGroupVarNames:
465               aShapeStr += aGName + ", "
466             aShaperEntry = self.GetShaperEntry(aShapeObj)
467             aShapeStr += "= SHAPERSTUDY.shape(" + aShaperEntry +")"
468             # 18884 : comment the line with dead shapes for now
469             if aShaperEntry.startswith("\"dead"):
470               script.append("# This shape does not exist among the SHAPER results; if it is referenced by SMESH, this may cause an error")
471               aShapeStr = "# " + aShapeStr
472             script.append(aShapeStr)
473             # dump also dead-shapes with groups and fields in the XAO format
474             aRes, aHistSO = aShapeObj.GetSO().FindSubObject(10000) # the History folder
475             if aRes:
476               aDeads = aStudy.NewChildIterator(aHistSO)
477               while aDeads.More():
478                 aDSO = aDeads.Value()
479                 aDIOR = aDSO.GetIOR()
480                 if len(aDIOR):
481                   aDeadShape = salome.orb.string_to_object(aDIOR)
482                   if aDeadShape and type(aDeadShape) == SHAPERSTUDY_ORB._objref_SHAPER_Object:
483                     aDeadString = ""
484                     aXAO = StudyData_Swig.StudyData_XAO()
485                     aXAO.SetShape(aDeadShape.getShape())
486                     anArchiveName = "archive_" + str(anArchiveNum) + ".xao"
487                     if len(aStudy.GetDumpPath()):
488                       anArchiveName = aStudy.GetDumpPath() + "/" + anArchiveName
489                     anArchiveNum += 1
490                     aDeadVarName = self.UniqueDumpName(aDeadShape.GetName(), aDSO.GetID())
491                     aDeadString += aDeadVarName + ", "
492
493                     aGroups = self.OrderGroups(aStudy, aDSO, True)
494                     for aDeadGroup in aGroups:
495                       aDGroupVarName = self.UniqueDumpName(aDeadGroup.GetName(), aDeadGroup.GetSO().GetID())
496                       aDeadString += aDGroupVarName + ", "
497                       aGroupID = aXAO.AddGroup(aDeadGroup.GetSelectionType(), aDGroupVarName)
498                       for aSel in aDeadGroup.GetSelection():
499                         aXAO.AddGroupSelection(aGroupID, aSel)
500
501                     aFields = self.OrderGroups(aStudy, aDSO, False)
502                     for aDeadField in aFields:
503                       aDFieldVarName = self.UniqueDumpName(aDeadField.GetName(), aDeadField.GetSO().GetID())
504                       aDeadString += aDFieldVarName + ", "
505                       aComponents = aDeadField.GetComponents()
506                       aFieldID = aXAO.AddField(aDeadField.GetValuesType(), aDeadField.GetSelectionType(), \
507                         len(aComponents), aDFieldVarName)
508                       for aCompIndex in range(len(aComponents)):
509                         aXAO.SetFieldComponent(aFieldID, aCompIndex, aComponents[aCompIndex])
510                       aSteps = aDeadField.GetSteps()
511                       for aStep in aSteps:
512                         aFieldStep = aDeadField.GetStep(aStep)
513                         aXAO.AddStep(aFieldID, aStep, aFieldStep.GetStamp())
514                         aStepVals = aFieldStep.GetValues()
515                         for aValue in aStepVals:
516                           aXAO.AddStepValue(aFieldID, aStep, str(aValue))
517
518                     aXAO.Export(anArchiveName)
519                     aDeadString += " = SHAPERSTUDY.archive(" + aShapeVar + ", \"" + anArchiveName + "\")"
520                     script.append(aDeadString)
521                 aDeads.Next()
522           pass
523         
524         script.append("") # to have an end-line in the end
525         result_str = "\n".join(script)
526         encoded_str = result_str.encode() + b'\0' # to avoid garbage symbols in the end
527         return (encoded_str, 1)
528
529     def GetAllDumpNames( self ):
530         """
531         Returns all names with which Object's was dumped
532         into python script to avoid the same names in SMESH script
533         """
534         global __entry2DumpName__
535         aResultList = []
536         for anEntry in __entry2DumpName__:
537           aResultList.append(__entry2DumpName__[anEntry])
538         return aResultList
539
540     def GetDumpName( self, theStudyEntry ):
541         """
542         Returns a name with which a GEOM_Object was dumped into python script
543
544         Parameters:
545             theStudyEntry is an entry of the Object in the study
546         """
547         global __entry2DumpName__
548         if theStudyEntry in __entry2DumpName__:
549           return __entry2DumpName__[theStudyEntry]
550         return ""
551
552     def BreakLink(self, theEntry):
553         """
554         Breaks links to not-dead shape, make the shape as dead
555         """
556         aStudy = getStudy()
557         aSO = aStudy.FindObjectID(theEntry)
558         if not aSO:
559           return
560         aRes, aSSO = aSO.ReferencedObject()
561         if not aRes:
562           return # only SObjects referenced to the SHAPER STUDY objects are allowed
563         anIOR = aSSO.GetIOR()
564         if not anIOR:
565           return # must be referenced to the SHAPER STUDY shape
566         anObj = salome.orb.string_to_object(anIOR)
567         if not anObj or not isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Object):
568           return
569         if anObj.IsDead():
570           return # do nothing for reference to already dead shape
571         aDeadShape = anObj.MakeDead()
572         
573         aMeshSObject = aSO.GetFather()
574         aMeshObject = aMeshSObject.GetObject()
575
576         aBuilder = aStudy.NewBuilder()
577         aBuilder.RemoveReference(aSO) # reset reference to the dead shape
578         aBuilder.Addreference(aSO, aDeadShape.GetSO())
579
580         # check also sub-structure of the mesh to find references to sub-objects that become dead
581         breakLinkForSubElements(aSO, aDeadShape)
582
583         # Replace shape object in the parent mesh
584         aMeshObject.ReplaceShape(aDeadShape)
585
586 def shape(theEntry):
587   """
588   Searches a shape object by the SHAPER entry. Used in the python dump script
589   """
590   aStudy = getStudy()
591   aRoots = aStudy.NewChildIterator(findOrCreateComponent())
592   while aRoots.More():
593     aSO = aRoots.Value()
594     anIOR = aSO.GetIOR()
595     if len(anIOR):
596       anObj = salome.orb.string_to_object(anIOR)
597       if anObj and type(anObj) == SHAPERSTUDY_ORB._objref_SHAPER_Object and anObj.GetEntry() == theEntry:
598         aRes = (anObj,)
599         # add groups and fields to the result
600         aSOIter = aStudy.NewChildIterator(aSO)
601         while aSOIter.More():
602           aGroupSO = aSOIter.Value()
603           anIOR = aGroupSO.GetIOR()
604           if len(anIOR):
605             aGroup = salome.orb.string_to_object(anIOR)
606             if isinstance(aGroup, SHAPERSTUDY_ORB._objref_SHAPER_Group) or \
607                isinstance(aGroup, SHAPERSTUDY_ORB._objref_SHAPER_Field):
608               aRes = aRes + (aGroup,)
609           aSOIter.Next()
610         return aRes
611     aRoots.Next()
612   return None # not found
613
614 def archive(theShape, theXAOFile):
615   """
616   Creates a dead shapes under the theShape and restores these dead objects state basing on theXAOFile
617   """
618   theShape.MakeDead()
619   aStudy = getStudy()
620   # searching for the last dead
621   aDeads = aStudy.NewChildIterator(theShape.GetSO().FindSubObject(10000)[1])
622   aLastDeadSO = aDeads.Value()
623   while aDeads.More():
624     aLastDeadSO = aDeads.Value()
625     aDeads.Next()
626
627   aDShape = aLastDeadSO.GetObject()
628   if aDShape:
629     aXAO = StudyData_Swig.StudyData_XAO()
630     anError = aXAO.Import(theXAOFile)
631     if (len(anError)):
632       print("Error of XAO file import: " + anError)
633       return None
634     aDShape.SetShapeByPointer(aXAO.GetShape())
635     aRes = (aDShape,)
636     # add groups and fields to the result
637     aGroupIndex = 0
638     aFieldIndex = 0
639     aSOIter = aStudy.NewChildIterator(aLastDeadSO)
640     while aSOIter.More():
641       aGroupSO = aSOIter.Value()
642       anIOR = aGroupSO.GetIOR()
643       if len(anIOR):
644         aGroup = salome.orb.string_to_object(anIOR)
645         if isinstance(aGroup, SHAPERSTUDY_ORB._objref_SHAPER_Group):
646           aRes += (aGroup,)
647           aGroup.SetSelectionType(aXAO.GetGroupDimension(aGroupIndex))
648           aSelection = []
649           for aSel in aXAO.GetGroupSelection(aGroupIndex):
650             aSelection.append(aSel)
651           aGroup.SetSelection(aSelection)
652           aGroupIndex += 1
653         elif isinstance(aGroup, SHAPERSTUDY_ORB._objref_SHAPER_Field):
654           aField = aGroup
655           aRes += (aField,)
656           aValType = aXAO.GetValuesType(aFieldIndex)
657           aField.SetValuesType(aValType)
658           aField.SetSelectionType(aXAO.GetSelectionType(aFieldIndex))
659           aCompNames = []
660           for aCompName in aXAO.GetComponents(aFieldIndex):
661             aCompNames.append(aCompName)
662           aField.SetComponents(aCompNames)
663           aField.ClearFieldSteps()
664           aXAO.BeginSteps(aFieldIndex)
665           while aXAO.More(aFieldIndex):
666             aValsList = []
667             for aVal in aXAO.GetValues():
668               if aValType == 0: # boolean
669                 aValsList.append(int(aVal))
670               elif aValType == 1: # int
671                 aValsList.append(int(aVal))
672               elif aValType == 2: # double
673                 aValsList.append(float(aVal))
674             aField.AddFieldStep(aXAO.GetStamp(), aXAO.GetStepIndex(), aValsList)
675             aXAO.Next()
676           aFieldIndex += 1
677       aSOIter.Next()
678     return aRes
679   return None # not found
680
681 def isFather(theFather, theChild):
682     """
683     Returns true if theChild SObject is a child of theFather SObject
684     """
685     aChild = theChild.GetFather()
686     while aChild.Depth() > theFather.Depth():
687       aChild = aChild.GetFather()
688     return aChild.GetID() == theFather.GetID()
689
690 def breakLinkForSubElements(theMainShapeSO, theDeadShape):
691   """
692   Checks sub-structure of the SMESH-mesh to find references to sub-objects that become dead.
693   theMainShapeSO is SObject with reference to real SHAPERSTUDY shape, located under the Mesh node.
694   theDeadShape is a newly created dead shape instance
695   """
696   aStudy = getStudy()
697   aBuilder = aStudy.NewBuilder()
698   aRoot = theMainShapeSO.GetFather()
699   anIters = [aStudy.NewChildIterator(aRoot)]
700   aSubList = []
701   anOriginShapeSO = theDeadShape.GetSO().GetFather().GetFather()
702   while len(anIters):
703     aLast = anIters[len(anIters) - 1]
704     if aLast.More():
705       aSub = aLast.Value()
706       aRes, aSubRef = aSub.ReferencedObject()
707       if aRes and isFather(anOriginShapeSO, aSubRef):
708         aReferenced = aSubRef.GetObject()
709         if aReferenced and not aReferenced.IsDead():
710           aSubList.append(aSub)
711       anIters.append(aStudy.NewChildIterator(aSub))
712       aLast.Next()
713     else:
714       anIters.remove(aLast)
715   if len(aSubList):
716     # associate the number of sub-objects of the referenced objects
717     aMapSubEntryToIndex = {}
718     aSSOIter = aStudy.NewChildIterator(anOriginShapeSO)
719     anIndex = 1
720     while aSSOIter.More():
721       aSub = aSSOIter.Value()
722       if aSub.GetIOR():
723         aMapSubEntryToIndex[aSub.GetID()] = anIndex
724         anIndex = anIndex + 1
725       aSSOIter.Next()
726     for aSubSO in aSubList:
727       aRes, aSubRef = aSubSO.ReferencedObject()
728       if aRes and aSubRef.GetID() in aMapSubEntryToIndex:
729         anIndex = aMapSubEntryToIndex[aSubRef.GetID()]
730         aDeadIter = aStudy.NewChildIterator(theDeadShape.GetSO())
731         while aDeadIter.More(): # iterate dead subs to find object with the same index
732           aDeadSubSO = aDeadIter.Value()
733           if aDeadSubSO.GetIOR():
734             anIndex = anIndex - 1
735             if anIndex == 0:
736               aBuilder.RemoveReference(aSubSO) # reset reference to the dead shape
737               aBuilder.Addreference(aSubSO, aDeadSubSO)
738           aDeadIter.Next()
739   pass
740
741 class SHAPERSTUDY(SHAPERSTUDY_Gen, SHAPERSTUDY_ORB__POA.Gen, SALOME_ComponentPy.SALOME_ComponentPy_i, SALOME_DriverPy.SALOME_DriverPy_i):
742     """
743     Implementation with naming_service server.
744     """
745     def __init__ ( self, orb, poa, contID, containerName, instanceName, interfaceName ):
746         """
747         Construct an instance of SHAPERSTUDY module engine.
748         The class SHAPERSTUDY implements CORBA interface Gen (see SHAPERSTUDY_Gen.idl).
749         It is inherited (via GEOM_Gen) from the classes SALOME_ComponentPy_i (implementation of
750         Engines::EngineComponent CORBA interface - SALOME component) and SALOME_DriverPy_i
751         (implementation of SALOMEDS::Driver CORBA interface - SALOME module's engine).
752         """
753         global __entry2IOR__, __entry2DumpName__
754         __entry2IOR__.clear()
755         __entry2DumpName__.clear()
756         SALOME_ComponentPy.SALOME_ComponentPy_i.__init__(self, orb, poa, contID, containerName, instanceName, interfaceName, False)
757         SALOME_DriverPy.SALOME_DriverPy_i.__init__(self, interfaceName)
758         pass
759
760 class SHAPERSTUDY_No_Session(SHAPERSTUDY_Gen, SHAPERSTUDY_ORB__POA.Gen, SALOME_ComponentPy.SALOME_ComponentPy_Gen_i, SALOME_DriverPy.SALOME_DriverPy_i):
761     """
762     Implementation without naming_service server.
763     """
764     def __init__ ( self, orb, poa, contID, containerName, instanceName, interfaceName ):
765         global __entry2IOR__, __entry2DumpName__
766         __entry2IOR__.clear()
767         __entry2DumpName__.clear()
768         SALOME_ComponentPy.SALOME_ComponentPy_Gen_i.__init__(self, orb, poa, contID, containerName, instanceName, interfaceName, False)
769         SALOME_DriverPy.SALOME_DriverPy_i.__init__(self, interfaceName)
770         pass