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