]> SALOME platform Git repositories - modules/shaper_study.git/blob - src/PY/SHAPERSTUDY.py
Salome HOME
Initial implementation of python dump in SHAPER STUDY
[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 __entry2IOR__ = {}
36 __entry2DumpName__ = {}
37
38 class SHAPERSTUDY(SHAPERSTUDY_ORB__POA.Gen,
39                   SALOME_ComponentPy.SALOME_ComponentPy_i,
40                   SALOME_DriverPy.SALOME_DriverPy_i):
41
42
43     ShapeType = {"AUTO":-1, "COMPOUND":0, "COMPSOLID":1, "SOLID":2, "SHELL":3, "FACE":4, "WIRE":5, "EDGE":6, "VERTEX":7, "SHAPE":8, "FLAT":9}
44     
45     ShaperIcons = {GEOM.COMPOUND:"SHAPER_ICON_COMPSOLID",
46         GEOM.COMPSOLID:"SHAPER_ICON_COMPSOLID",
47         GEOM.SOLID:"SHAPER_ICON_SOLID",
48         GEOM.SHELL:"SHAPER_ICON_SHELL",
49         GEOM.FACE:"SHAPER_ICON_FACE",
50         GEOM.WIRE:"SHAPER_ICON_WIRE",
51         GEOM.EDGE:"SHAPER_ICON_EDGE",
52         GEOM.VERTEX:"SHAPER_ICON_VERTEX",
53         GEOM.SHAPE:"SHAPER_ICON_SOLID",
54         GEOM.FLAT:"SHAPER_ICON_FACE"
55         }
56
57     def __init__ ( self, orb, poa, contID, containerName, instanceName, interfaceName ):
58         """
59         Construct an instance of SHAPERSTUDY module engine.
60         The class SHAPERSTUDY implements CORBA interface Gen (see SHAPERSTUDY_Gen.idl).
61         It is inherited (via GEOM_Gen) from the classes SALOME_ComponentPy_i (implementation of
62         Engines::EngineComponent CORBA interface - SALOME component) and SALOME_DriverPy_i
63         (implementation of SALOMEDS::Driver CORBA interface - SALOME module's engine).
64         """
65         SALOME_ComponentPy.SALOME_ComponentPy_i.__init__(self, orb, poa,
66                     contID, containerName, instanceName, interfaceName, False)
67         SALOME_DriverPy.SALOME_DriverPy_i.__init__(self, interfaceName)
68         #
69         #self._naming_service = SALOME_ComponentPy.SALOME_NamingServicePy_i( self._orb )
70         #
71         pass
72
73     def FindOrCreateShape( self, theInternalEntry ):
74         """
75         Searches existing or creates a new SHAPERSTUDY_Object to interact with SHAPER
76         """
77         # Searching in the study tree
78         aComponent = findOrCreateComponent()
79         aSOIter = getStudy().NewChildIterator(aComponent)
80         while aSOIter.More():
81           aSO = aSOIter.Value()
82           anIOR = aSO.GetIOR()
83           anObj = salome.orb.string_to_object(anIOR)
84           if isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Object):
85             if anObj.GetEntry() == theInternalEntry:
86               return anObj
87           aSOIter.Next()
88
89         aShapeObj = SHAPERSTUDY_Object.SHAPERSTUDY_Object()
90         aShapeObj.SetEntry(theInternalEntry)
91         return aShapeObj._this()
92
93     def AddInStudy( self, theObject, theName, theFather ):
94         """
95         Adds in theStudy a object theObject under theFather with a name theName,
96         if theFather is not NULL the object is placed under theFather's SObject.
97         Returns a SObject where theObject is placed
98         """
99         if not theObject.GetEntry():
100             return None # object not existing in shaper
101         aStudy = getStudy()
102         aBuilder = aStudy.NewBuilder()
103         isGroup = theObject.GetType() == 37 or theObject.GetType() == 52
104         if not theFather:
105           if isGroup:
106             return None # Group may be added only under the shape-father
107           theFatherSO = findOrCreateComponent()
108         else:
109           theFatherSO = theFather.GetSO()
110         aResultSO = None
111         if isGroup: # add group to the third sub-label or later to keep space for reference and "History"
112           aTag = 3
113           anIter = aStudy.NewChildIterator(theFatherSO)
114           while anIter.More():
115             aCurrentTag = anIter.Value().Tag() + 1
116             if aTag < aCurrentTag:
117               aTag = aCurrentTag
118             anIter.Next()
119           aResultSO = aBuilder.NewObjectToTag(theFatherSO, aTag)
120         else:
121           aResultSO = aBuilder.NewObject(theFatherSO);
122         aResultSO.SetAttrString("AttributeName", theName)
123         if theObject is not None:
124             anIOR = salome.orb.object_to_string(theObject)
125             aResultSO.SetAttrString("AttributeIOR", anIOR)
126             theObject.SetSO(aResultSO)
127           
128             aAttr = aBuilder.FindOrCreateAttribute(aResultSO, "AttributePixMap")
129             aPixmap = aAttr._narrow(salome.SALOMEDS.AttributePixMap)
130             aType = 0
131             if isGroup:
132               aType = SHAPERSTUDY_Object.__shape_types__[theObject.GetSelectionType()]
133             else:
134               aType = theObject.GetShapeType()
135             aPixmap.SetPixMap(self.ShaperIcons[aType])
136             
137         # add a red-reference that means that this is an active reference to SHAPER result
138         if not isGroup:
139           aSub = aBuilder.NewObjectToTag(aResultSO, 1)
140           aBuilder.Addreference(aSub, aResultSO)
141
142         return aResultSO
143
144     def AddSubShape( theMainShape, theIndices ):
145         """
146         Add a sub-shape defined by indices in theIndices
147         (contains unique IDs of sub-shapes inside theMainShape)
148         """
149         # no sub-shapes for the moment
150         go = SHAPERSTUDY_Object()._this()
151         return go
152
153     # For now it is impossible to remove anything from the SHAPER-STUDY
154     def RemoveObject( self, theObject ):
155         """
156         Removes the object from the component
157         """
158         # can not be removed for the moment
159         return
160
161     def GetIFieldOperations( self ):
162         """
163         """
164         return SHAPERSTUDY_IOperations.SHAPERSTUDY_IFieldOperations()._this()
165
166     def GetIGroupOperations( self ):
167         """
168         """
169         return SHAPERSTUDY_IOperations.SHAPERSTUDY_IGroupOperations()._this()
170
171     def GetIShapesOperations( self ):
172         """
173         """
174         return SHAPERSTUDY_IOperations.SHAPERSTUDY_IShapesOperations()._this()
175
176     def GetIMeasureOperations( self ):
177         """
178         """
179         return SHAPERSTUDY_IOperations.SHAPERSTUDY_IMeasureOperations()._this()
180
181     def GetStringFromIOR( self, theObject ):
182         """
183         Returns a string which contains an IOR of the SHAPERSTUDY_Object
184         """
185         IOR = ""
186         if theObject and getORB():
187             IOR = getORB().object_to_string( theObject )
188             pass
189         return IOR
190
191     def Save( self, component, URL, isMultiFile ):
192         """
193         Saves data: all objects into one file
194         """
195         aResult = "" # string-pairs of internal entries and shape streams
196         aStudy = getStudy()
197         # get all sub-SObjects with IOR defined
198         anIters = [aStudy.NewChildIterator(findOrCreateComponent())]
199         aSOList = []
200         while len(anIters):
201           aLast = anIters[len(anIters) - 1]
202           if aLast.More():
203             aSO = aLast.Value()
204             anIOR = aSO.GetIOR()
205             if len(anIOR):
206               aSOList.append(aSO)
207             anIters.append(aStudy.NewChildIterator(aSO))
208             aLast.Next()
209           else:
210             anIters.remove(aLast)
211
212         for aSO in aSOList: # for each sobject export shapes stream if exists
213           anIOR = aSO.GetIOR()
214           if not len(anIOR):
215             continue
216           anObj = salome.orb.string_to_object(anIOR)
217           if type(anObj) == SHAPERSTUDY_ORB._objref_SHAPER_Group:
218             if len(aResult):
219               aResult = aResult + '|'
220             # store internal entry, type and list of indices of the group selection (separated by spaces)
221             aResult = aResult + anObj.GetEntry() + "|" + str(anObj.GetSelectionType())
222             aSelList = anObj.GetSelection()
223             aResult = aResult + "|" + str(' '.join(str(anI) for anI in aSelList))
224           elif type(anObj) == SHAPERSTUDY_ORB._objref_SHAPER_Field:
225             if len(aResult):
226               aResult = aResult + '|'
227             # same as for group, but in addition to the second string part - field specifics
228             aResult = aResult + anObj.GetEntry() + "|" + str(anObj.GetSelectionType())
229             aResult = aResult + " " + str(anObj.GetDataType()) # values type
230             aSteps = anObj.GetSteps()
231             aResult = aResult + " " + str(len(aSteps)) # number of steps
232             aComps = anObj.GetComponents()
233             aResult = aResult + " " + str(len(aComps)) # number of components
234             for aComp in aComps: # components strings: but before remove spaces and '|'
235               aCoded = aComp.replace(" ", "__space__").replace("|", "__vertical_bar__")
236               aResult = aResult + " " + aCoded
237             for aStepNum in range(len(aSteps)):
238               aVals = anObj.GetStep(aStepNum + 1).GetValues()
239               if aStepNum == 0:
240                 aResult = aResult + " " + str(len(aVals)) # first the number of values in the step
241               aResult = aResult + " " + str(anObj.GetStep(aStepNum + 1).GetStamp()) # ID of stamp in step
242               for aVal in aVals:
243                 aResult = aResult + " " + str(aVal) # all values of step
244             aSelList = anObj.GetSelection()
245             aResult = aResult + "|" + str(' '.join(str(anI) for anI in aSelList))
246           elif isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Object):
247             if len(aResult):
248               aResult = aResult + '|'
249             # store internal entry, current and old shapes in BRep format
250             aResult = aResult + anObj.GetEntry() + "|" + anObj.GetShapeStream().decode()
251             aResult = aResult + "|" + anObj.GetOldShapeStream().decode()
252
253         return aResult.encode()
254
255     def Load( self, component, stream, URL, isMultiFile ):
256         """
257         Loads data
258         """
259         global __entry2IOR__
260         __entry2IOR__.clear()
261         aList=stream.decode().split('|')
262         aSubNum = 1
263         anId = ""
264         aNewShapeStream = ""
265         for aSub in aList:
266           if aSubNum == 1:
267             anId = aSub
268             aSubNum = 2
269           elif aSubNum == 2:
270             aNewShapeStream = aSub
271             aSubNum = 3
272           else: # create objects by 3 arguments
273             anObj = None
274             if anId.startswith('group') or (anId.startswith('dead') and anId.count("group") > 0): # group object
275               anObj = SHAPERSTUDY_Object.SHAPERSTUDY_Group()
276               if len(aSub):
277                 anObj.SetSelection([int(anI) for anI in aSub.split(' ')])
278               anObj.SetSelectionType(int(aNewShapeStream))
279             elif anId.startswith('field') or (anId.startswith('dead') and anId.count("field") > 0): # field object
280               anObj = SHAPERSTUDY_Object.SHAPERSTUDY_Field()
281               if len(aSub):
282                 anObj.SetSelection([int(anI) for anI in aSub.split(' ')])
283               aParams = aNewShapeStream.split(" ")
284               anObj.SetSelectionType(int(aParams[0]))
285               aTypeStr = aParams[1]
286               if (aTypeStr == "FDT_Bool"):
287                 anObj.SetValuesType(0)
288               elif (aTypeStr == "FDT_Int"):
289                 anObj.SetValuesType(1)
290               elif (aTypeStr == "FDT_Double"):
291                 anObj.SetValuesType(2)
292               elif (aTypeStr == "FDT_String"):
293                 anObj.SetValuesType(3)
294               aSteps = []
295               aNumSteps = int(aParams[2])
296               for aVal in range(aNumSteps):
297                 aSteps.append(aVal + 1)
298               anObj.SetSteps(aSteps)
299               aCompNum = int(aParams[3])
300               aCompNames = []
301               for aCompNameIndex in range(aCompNum):
302                 aCompName = aParams[4 + aCompNameIndex].replace("__space__", " ").replace("__vertical_bar__", "|")
303                 aCompNames.append(aCompName)
304               anObj.SetComponents(aCompNames)
305               aNumValsInStep = int(aParams[4 + aCompNum])
306               for aStepNum in range(aNumSteps):
307                 aStepStartIndex = 4 + aCompNum + aStepNum * (aNumValsInStep + 1) + 1
308                 aStampId = int(aParams[aStepStartIndex])
309                 aVals = []
310                 for aValIndex in range(aNumValsInStep):
311                   aVals.append(float(aParams[aStepStartIndex + aValIndex + 1]))
312                 anObj.AddFieldStep(aStampId, aStepNum + 1, aVals)
313             else: # shape object by BRep in the stream: set old first then new
314               anObj = SHAPERSTUDY_Object.SHAPERSTUDY_Object()
315               if len(aSub):
316                 anObj.SetShapeByStream(aSub)
317               anObj.SetShapeByStream(aNewShapeStream)
318             if anObj:
319               anObj.SetEntry(anId)
320               anIOR = salome.orb.object_to_string(anObj._this())
321               __entry2IOR__[anId] = anIOR
322             aSubNum = 1
323         return 1
324         
325     def IORToLocalPersistentID(self, sobject, IOR, isMultiFile, isASCII):
326         """
327         Gets persistent ID for the CORBA object.
328         The internal entry of the Object is returned.
329         """
330         anObj = salome.orb.string_to_object(IOR)
331         if anObj and (isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Object) or \
332                       isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Field)):
333           return anObj.GetEntry()
334         return ""
335
336     def LocalPersistentIDToIOR(self, sobject, persistentID, isMultiFile, isASCII):
337         "Converts persistent ID of the object to its IOR."
338         global __entry2IOR__
339         if persistentID in __entry2IOR__:
340           aRes = __entry2IOR__[persistentID]
341           if len(aRes): # set SO from the study, the sobject param is temporary, don't store it
342             salome.orb.string_to_object(aRes).SetSO(getStudy().FindObjectID(sobject.GetID()))
343           return aRes
344         return ""
345
346     def DumpPython( self, isPublished, isMultiFile ):
347         """
348         Dump module data to the Python script.
349         """
350         global __entry2DumpName__
351         __entry2DumpName__.clear()
352         # collect all shape-objects in the SHAPERSTUDY tree
353         aShapeObjects = []
354         aStudy = getStudy()
355         aRoots = aStudy.NewChildIterator(findOrCreateComponent())
356         while aRoots.More():
357           aSO = aRoots.Value()
358           anIOR = aSO.GetIOR()
359           if len(anIOR):
360             anObj = salome.orb.string_to_object(anIOR)
361             if anObj and type(anObj) == SHAPERSTUDY_ORB._objref_SHAPER_Object:
362               aShapeObjects.append(anObj)
363           aRoots.Next()
364         script = []
365         if len(aShapeObjects):
366           script.append("if 'model' in globals():")
367           script.append("\tmodel.publishToShaperStudy()")
368           script.append("import SHAPERSTUDY")
369           for aShapeObj in aShapeObjects:
370             aVarName = anObj.GetName()
371             aPrefix = 1
372             while aVarName in __entry2DumpName__:
373               aVarName = anObj.GetName() + "_" + str(aPrefix)
374               aPrefix = aPrefix + 1
375             __entry2DumpName__[aSO.GetID()] = aVarName
376             script.append(aVarName + " = SHAPERSTUDY.shape(\"" + anObj.GetEntry() +"\")")
377           pass
378         
379         script.append("") # to have an end-line in the end
380         result_str = "\n".join(script)
381         encoded_str = result_str.encode() + b'\0' # to avoid garbage symbols in the end
382         return (encoded_str, 1)
383
384     def GetAllDumpNames( self ):
385         """
386         Returns all names with which Object's was dumped
387         into python script to avoid the same names in SMESH script
388         """
389         global __entry2DumpName__
390         aResultList = []
391         for anEntry in __entry2DumpName__:
392           aResultList.append(__entry2DumpName__[anEntry])
393         return aResultList
394
395     def GetDumpName( self, theStudyEntry ):
396         """
397         Returns a name with which a GEOM_Object was dumped into python script
398
399         Parameters:
400             theStudyEntry is an entry of the Object in the study
401         """
402         global __entry2DumpName__
403         if theStudyEntry in __entry2DumpName__:
404           return __entry2DumpName__[theStudyEntry]
405         return ""
406
407     def IsFather(theFather, theChild):
408         """
409         Returns true if theChild SObject is a child of theFather SObject
410         """
411         aChild = theChild.GetFather()
412         while aChild.Depth() > theFather.Depth():
413           aChild = aChild.GetFather()
414         return aChild.GetID() == theFather.GetID()
415
416     def BreakLink(self, theEntry):
417         """
418         Breaks links to not-dead shape, make the shape as dead
419         """
420         aStudy = getStudy()
421         aSO = aStudy.FindObjectID(theEntry)
422         if not aSO:
423           return
424         aRes, aSSO = aSO.ReferencedObject()
425         if not aRes:
426           return # only SObjects referenced to the SHAPEr STUDY objects are allowed
427         anIOR = aSSO.GetIOR()
428         if not anIOR:
429           return # must be referenced to the SHAPER STUDY shape
430         anObj = salome.orb.string_to_object(anIOR)
431         if not anObj or not isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Object):
432           return
433         if anObj.IsDead():
434           return # do nothing for reference to already dead shape
435         aDeadShape = anObj.MakeDead()
436         
437         aMeshSObject = aSO.GetFather()
438         aMeshObject = aMeshSObject.GetObject()
439
440         aBuilder = aStudy.NewBuilder()
441         aBuilder.RemoveReference(aSO) # reset reference to the dead shape
442         aBuilder.Addreference(aSO, aDeadShape.GetSO())
443
444         # check also sub-structure of the mesh to find references to sub-objects that become dead
445         aRoot = aSO.GetFather()
446         anIters = [aStudy.NewChildIterator(aRoot)]
447         aSubList = []
448         while len(anIters):
449           aLast = anIters[len(anIters) - 1]
450           if aLast.More():
451             aSub = aLast.Value()
452             aRes, aSubRef = aSub.ReferencedObject()
453             if aRes and SHAPERSTUDY.IsFather(aSSO, aSubRef):
454               aReferenced = aSubRef.GetObject()
455               if aReferenced and not aReferenced.IsDead():
456                 aSubList.append(aSub)
457             anIters.append(aStudy.NewChildIterator(aSub))
458             aLast.Next()
459           else:
460             anIters.remove(aLast)
461         if len(aSubList):
462           # associate the number of sub-objects of the referenced objects
463           aMapSubEntryToIndex = {}
464           aSSOIter = aStudy.NewChildIterator(aSSO)
465           anIndex = 1
466           while aSSOIter.More():
467             aSub = aSSOIter.Value()
468             if aSub.GetIOR():
469               aMapSubEntryToIndex[aSub.GetID()] = anIndex
470               anIndex = anIndex + 1
471             aSSOIter.Next()
472           for aSubSO in aSubList:
473             aRes, aSubRef = aSubSO.ReferencedObject()
474             if aRes and aSubRef.GetID() in aMapSubEntryToIndex:
475               anIndex = aMapSubEntryToIndex[aSubRef.GetID()]
476               aDeadIter = aStudy.NewChildIterator(aDeadShape.GetSO())
477               while aDeadIter.More(): # iterate dead subs to find object with the same index
478                 aDeadSubSO = aDeadIter.Value()
479                 if aDeadSubSO.GetIOR():
480                   anIndex = anIndex - 1
481                   if anIndex == 0:
482                     # for a submesh there is no ReplaceShape, but the shape is not updated
483                     # anyway, so no need to update it here
484                     #aSubMeshSO = aSubSO.GetFather() # Replace shape object in the parent mesh
485                     #aSubMeshObject = aSubMeshSO.GetObject()
486                     #if aSubMeshObject:
487                     #  aSubMeshObject.ReplaceShape(aDeadSubSO.GetObject())
488                     aBuilder.RemoveReference(aSubSO) # reset reference to the dead shape
489                     aBuilder.Addreference(aSubSO, aDeadSubSO)
490                 aDeadIter.Next()
491
492         # Replace shape object in the parent mesh
493         aMeshObject.ReplaceShape(aDeadShape)
494
495 def shape(theEntry):
496   """
497   Searches a shape object by the SHAPER entry. Used in the python dump script
498   """
499   aStudy = getStudy()
500   aRoots = aStudy.NewChildIterator(findOrCreateComponent())
501   while aRoots.More():
502     aSO = aRoots.Value()
503     anIOR = aSO.GetIOR()
504     if len(anIOR):
505       anObj = salome.orb.string_to_object(anIOR)
506       if anObj and type(anObj) == SHAPERSTUDY_ORB._objref_SHAPER_Object and anObj.GetEntry() == theEntry:
507         return anObj
508   return None # not found