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