Salome HOME
Make SHAPEr STUDY fields exported in SMESH into MED file
[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
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         aStudy = getStudy()
100         aBuilder = aStudy.NewBuilder()
101         isGroup = theObject.GetType() == 37 or theObject.GetType() == 52
102         if not theFather:
103           if isGroup:
104             return None # Group may be added only under the shape-father
105           theFather = findOrCreateComponent()
106         aResultSO = None
107         if isGroup: # add group to the third sub-label or later to keep space for reference and "History"
108           aTag = 3
109           anIter = aStudy.NewChildIterator(theFather)
110           while anIter.More():
111             aCurrentTag = anIter.Value().Tag() + 1
112             if aTag < aCurrentTag:
113               aTag = aCurrentTag
114             anIter.Next()
115           aResultSO = aBuilder.NewObjectToTag(theFather, aTag)
116         else:
117           aResultSO = aBuilder.NewObject(theFather);
118         aResultSO.SetAttrString("AttributeName", theName)
119         if theObject is not None:
120             anIOR = salome.orb.object_to_string(theObject)
121             aResultSO.SetAttrString("AttributeIOR", anIOR)
122             theObject.SetSO(aResultSO)
123           
124             aAttr = aBuilder.FindOrCreateAttribute(aResultSO, "AttributePixMap")
125             aPixmap = aAttr._narrow(salome.SALOMEDS.AttributePixMap)
126             aType = 0
127             if isGroup:
128               aType = SHAPERSTUDY_Object.__shape_types__[theObject.GetSelectionType()]
129             else:
130               aType = theObject.GetShapeType()
131             aPixmap.SetPixMap(SHAPERSTUDY.ShaperIcons[aType])
132             
133         # add a red-reference that means that this is an active reference to SHAPER result
134         if not isGroup:
135           aSub = aBuilder.NewObjectToTag(aResultSO, 1)
136           aBuilder.Addreference(aSub, aResultSO)
137
138         return aResultSO
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 GetAllDumpNames( self ):
188         """
189         Returns all names with which Object's was dumped
190         into python script to avoid the same names in SMESH script
191         """
192         return [""]
193
194     def GetDumpName( self, theStudyEntry ):
195         """
196         Returns a name with which a GEOM_Object was dumped into python script
197
198         Parameters:
199             theStudyEntry is an entry of the Object in the study
200         """
201         return "test"
202
203     def Save( self, component, URL, isMultiFile ):
204         """
205         Saves data: all objects into one file
206         """
207         aResult = "" # string-pairs of internal entries and shape streams
208         aStudy = getStudy()
209         # get all sub-SObjects with IOR defined
210         anIters = [aStudy.NewChildIterator(findOrCreateComponent())]
211         aSOList = []
212         while len(anIters):
213           aLast = anIters[len(anIters) - 1]
214           if aLast.More():
215             aSO = aLast.Value()
216             anIOR = aSO.GetIOR()
217             if len(anIOR):
218               aSOList.append(aSO)
219             anIters.append(aStudy.NewChildIterator(aSO))
220             aLast.Next()
221           else:
222             anIters.remove(aLast)
223
224         for aSO in aSOList: # for each sobject export shapes stream if exists
225           anIOR = aSO.GetIOR()
226           anObj = salome.orb.string_to_object(anIOR)
227           if isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Group):
228             if len(aResult):
229               aResult = aResult + '|'
230             # store internal entry, type and list of indices of the group selection (separated by spaces)
231             aResult = aResult + anObj.GetEntry() + "|" + str(anObj.GetSelectionType())
232             aSelList = anObj.GetSelection()
233             aResult = aResult + "|" + str(' '.join(str(anI) for anI in aSelList))
234           elif isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Object):
235             if len(aResult):
236               aResult = aResult + '|'
237             # store internal entry, current and old shapes in BRep format
238             aResult = aResult + anObj.GetEntry() + "|" + anObj.GetShapeStream().decode()
239             aResult = aResult + "|" + anObj.GetOldShapeStream().decode()
240
241         return aResult.encode()
242
243     def Load( self, component, stream, URL, isMultiFile ):
244         """
245         Loads data
246         """
247         global __entry2IOR__
248         __entry2IOR__.clear()
249         aList=stream.decode().split('|')
250         aSubNum = 1
251         anId = ""
252         aNewShapeStream = ""
253         for aSub in aList:
254           if aSubNum == 1:
255             anId = aSub
256             aSubNum = 2
257           elif aSubNum == 2:
258             aNewShapeStream = aSub
259             aSubNum = 3
260           else: # create objects by 3 arguments
261             anObj = None
262             if anId.startswith('group'): # group object
263               anObj = SHAPERSTUDY_Object.SHAPERSTUDY_Group()
264               if len(aSub):
265                 anObj.SetSelection([int(anI) for anI in aSub.split(' ')])
266               anObj.SetSelectionType(int(aNewShapeStream))
267             else: # shape object by BRep in the stream: set old first then new
268               anObj = SHAPERSTUDY_Object.SHAPERSTUDY_Object()
269               if len(aSub):
270                 anObj.SetShapeByStream(aSub)
271               anObj.SetShapeByStream(aNewShapeStream)
272             if anObj:
273               anObj.SetEntry(anId)
274               anIOR = salome.orb.object_to_string(anObj._this())
275               __entry2IOR__[anId] = anIOR
276             aSubNum = 1
277         return 1
278         
279     def IORToLocalPersistentID(self, sobject, IOR, isMultiFile, isASCII):
280         """
281         Gets persistent ID for the CORBA object.
282         The internal entry of the Object is returned.
283         """
284         anObj = salome.orb.string_to_object(IOR)
285         if anObj and isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Object):
286           return anObj.GetEntry()
287         return ""
288
289     def LocalPersistentIDToIOR(self, sobject, persistentID, isMultiFile, isASCII):
290         "Converts persistent ID of the object to its IOR."
291         global __entry2IOR__
292         if persistentID in __entry2IOR__:
293           aRes = __entry2IOR__[persistentID]
294           if len(aRes): # set SO from the study, the sobject param is temporary, don't store it
295             salome.orb.string_to_object(aRes).SetSO(getStudy().FindObjectID(sobject.GetID()))
296           return aRes
297         return ""
298
299     def DumpPython( self, isPublished, isMultiFile ):
300         """
301         Dump module data to the Python script.
302         """
303         return ("".encode(), 1)
304
305
306
307     def CreateGroup( self, theMainShape, theShapeType ):
308         """
309         Creates a new group which will store sub-shapes of theMainShape
310         """
311         return GetIGroupOperations().CreateGroup( theMainShape, theShapeType );
312
313     def ExtractShapes( self, aShape, aType, isSorted = False ):
314         """
315         Extract shapes (excluding the main shape) of given type.
316
317         Parameters:
318             aShape The shape.
319             aType  The shape type (see geompy.ShapeType)
320             isSorted Boolean flag to switch sorting on/off.
321
322         Returns:
323             List of sub-shapes of type aType, contained in aShape.
324         """
325         return [ SHAPERSTUDY_Object()._this() ]
326
327     def GetSubShape( self, aShape, ListOfID ):
328         """
329         Obtain a composite sub-shape of aShape, composed from sub-shapes
330         of aShape, selected by their unique IDs inside aShape
331
332         Parameters:
333             aShape Shape to get sub-shape of.
334             ListOfID List of sub-shapes indices.
335         """
336         return SHAPERSTUDY_Object()._this()
337
338     def GetSubShapeID( self, aShape, aSubShape ):
339         """
340         Obtain unique ID of sub-shape aSubShape inside aShape
341         of aShape, selected by their unique IDs inside aShape
342
343         Parameters:
344            aShape Shape to get sub-shape of.
345            aSubShape Sub-shapes of aShape.
346         """
347         return 1
348
349     def MinDistance( self, theShape1, theShape2 ):
350         """
351         Get minimal distance between the given shapes.
352         """
353         return 0.
354
355     def NumberOfEdges( self, theShape ):
356         """
357         Gives quantity of edges in the given shape.
358         """
359         return 0
360
361     def NumberOfFaces( self,  ):
362         """
363         Gives quantity of faces in the given shape.
364         """
365         return 0
366
367     def PointCoordinates( self, theVertex ):
368         """
369         Get point coordinates
370         """
371         return 0,0,0
372
373     def SubShapeAll( self, aShape, aType ):
374         """
375         Explode a shape on sub-shapes of a given type.
376         If the shape itself matches the type, it is also returned.
377         """
378         return [ SHAPERSTUDY_Object()._this() ]
379
380     def SubShapeName( self, aSubObj, aMainObj ):
381         """
382         Get name for sub-shape aSubObj of shape aMainObj
383         """
384         return ""
385
386     def SubShapes( self, aShape, anIDs ):
387         """
388         Get a set of sub-shapes defined by their unique IDs inside theMainShape
389         """
390         return  [ SHAPERSTUDY_Object()._this() ]
391
392     def Tolerance( self, theShape ):
393         """
394         Get min and max tolerances of sub-shapes of theShape
395
396         Returns:
397             [FaceMin,FaceMax, EdgeMin,EdgeMax, VertMin,VertMax]
398         """
399         return [0,0, 0,0, 0,0]
400
401     def UnionList( self, theGroup, theSubShapes ):
402         """
403         Adds to the group all the given shapes. No errors, if some shapes are already included.
404         """
405         return GetIGroupOperations().UnionList( theGroup, theSubShapes )
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         # Replace shape object in the parent mesh
438         aMeshSObject = aSO.GetFather()
439         aMeshObject = aMeshSObject.GetObject()
440         aMeshObject.ReplaceShape(aDeadShape)
441        
442         aBuilder = aStudy.NewBuilder()
443         aBuilder.RemoveReference(aSO) # reset reference to the dead shape
444         aBuilder.Addreference(aSO, aDeadShape.GetSO())
445
446         # check also sub-structure of the mesh to find references to sub-objects that become dead
447         aRoot = aSO.GetFather()
448         anIters = [aStudy.NewChildIterator(aRoot)]
449         aSubList = []
450         while len(anIters):
451           aLast = anIters[len(anIters) - 1]
452           if aLast.More():
453             aSub = aLast.Value()
454             aRes, aSubRef = aSub.ReferencedObject()
455             if aRes and SHAPERSTUDY.IsFather(aSSO, aSubRef):
456               aReferenced = aSubRef.GetObject()
457               if aReferenced and not aReferenced.IsDead():
458                 aSubList.append(aSub)
459             anIters.append(aStudy.NewChildIterator(aSub))
460             aLast.Next()
461           else:
462             anIters.remove(aLast)
463         if len(aSubList):
464           # associate the number of sub-objects of the referenced objects
465           aMapSubEntryToIndex = {}
466           aSSOIter = aStudy.NewChildIterator(aSSO)
467           anIndex = 1
468           while aSSOIter.More():
469             aSub = aSSOIter.Value()
470             if aSub.GetIOR():
471               aMapSubEntryToIndex[aSub.GetID()] = anIndex
472               anIndex = anIndex + 1
473             aSSOIter.Next()
474           for aSubSO in aSubList:
475             aRes, aSubRef = aSubSO.ReferencedObject()
476             if aRes and aSubRef.GetID() in aMapSubEntryToIndex:
477               anIndex = aMapSubEntryToIndex[aSubRef.GetID()]
478               aDeadIter = aStudy.NewChildIterator(aDeadShape.GetSO())
479               while aDeadIter.More(): # iterate dead subs to find object with the same index
480                 aDeadSubSO = aDeadIter.Value()
481                 if aDeadSubSO.GetIOR():
482                   anIndex = anIndex - 1
483                   if anIndex == 0:
484                     # for a submesh there is no ReplaceShape, but the shape is not updated
485                     # anyway, so no need to update it here
486                     #aSubMeshSO = aSubSO.GetFather() # Replace shape object in the parent mesh
487                     #aSubMeshObject = aSubMeshSO.GetObject()
488                     #if aSubMeshObject:
489                     #  aSubMeshObject.ReplaceShape(aDeadSubSO.GetObject())
490                     aBuilder.RemoveReference(aSubSO) # reset reference to the dead shape
491                     aBuilder.Addreference(aSubSO, aDeadSubSO)
492                 aDeadIter.Next()