Salome HOME
A minor fix for breaking link for the newly created group or field
[modules/shaper_study.git] / src / PY / SHAPERSTUDY_Object.py
1 # Copyright (C) 2019-2020  CEA/DEN, EDF R&D
2 #
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2.1 of the License, or (at your option) any later version.
7 #
8 # This library is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 # Lesser General Public License for more details.
12 #
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 #
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 #
19
20 import SHAPERSTUDY_ORB
21 import SHAPERSTUDY_ORB__POA
22 import GEOM
23 from SHAPERSTUDY_utils import getEngine, getStudy
24 import salome
25
26 import StudyData_Swig
27
28 # converter from the integer values to idl shape_type enumerations
29 __shape_types__ = {
30   0:GEOM.COMPOUND, 1:GEOM.COMPSOLID, 2:GEOM.SOLID,
31   3:GEOM.SHELL, 4:GEOM.FACE, 5:GEOM.WIRE,
32   6:GEOM.EDGE, 7:GEOM.VERTEX, 8:GEOM.SHAPE, 9:GEOM.FLAT}
33
34 class SHAPERSTUDY_GenericObject:
35     """
36     Implement methods of SALOME::GenericObj
37     """
38     def __init__(self):
39         self.cnt=1
40
41     def Register(self):
42         """
43         Increase the reference count (mark as used by another object).
44         """
45         #print(self.GetEntry())
46         self.cnt+=1
47         #print("Register() --------- ", id(self), self.cnt)
48         return
49
50     def UnRegister(self):
51         """
52         Decrease the reference count (release by another object)
53         """
54         self.cnt-=1
55         #print("UnRegister() --------- ", id(self), self.cnt)
56         if self.cnt <= 0:
57             from SHAPERSTUDY_utils import getPOA
58             poa = getPOA()
59             oid=poa.servant_to_id(self)
60             poa.deactivate_object(oid)
61             if hasattr(self,"SetSO"):
62                 self.SetSO(None) # release a GenericObject SO
63             #print("UnRegister() --------- OK")
64         return
65
66     def Destroy(self):
67         """
68         Obsolete, left for compatibility reasons only. Use UnRegister() instead
69         """
70         self.UnRegister()
71         return
72
73     pass
74
75
76 class SHAPERSTUDY_Object(SHAPERSTUDY_ORB__POA.SHAPER_Object,
77                          SHAPERSTUDY_GenericObject):
78     """
79     Constructs an instance of SHAPERSTUDY Object.
80     """
81     def __init__ ( self, *args):
82         SHAPERSTUDY_GenericObject.__init__(self)
83         self.SO = None
84         self.data = None
85         self.entry = ""
86         self.type = 1 # by default it is a shape (Import feature in GEOMImpl_Types.hxx)
87         pass
88
89     def GetShapeType( self ):
90         """
91         Get a GEOM.shape_type of the object value.
92         """
93         if self.data is None:
94             return GEOM.SHAPE
95         global __shape_types__
96         return __shape_types__[self.data.type()];
97
98     def IsMainShape( self ):
99         """
100         Returns True if this object is not a sub-shape of another object.
101         """
102         return True
103
104     def GetSubShapeIndices( self ):
105         """
106         Get a list of ID's of sub-shapes in the main shape.
107         """
108         return []
109
110     def GetMainShape( self ):
111         """
112         Get a main shape object to which this object is a sub-shape.
113         """
114         return getShape()
115
116     def getShape( self ):
117         """
118         Get the TopoDS_Shape, for collocated case only.
119         Called by GEOM_Client to get TopoDS_Shape pointer
120         """
121         if self.data is None:
122             return 0
123         return self.data.shape()
124
125     def GetShapeStream( self ):
126         """
127         Get geometric shape of the object as a byte stream in BRep format
128         """
129         if self.data is None:
130             return b''
131         return self.data.shapeStream().encode()
132
133     def GetOldShapeStream( self ):
134         """
135         Get geometric shape of the object as a byte stream in BRep format
136         """
137         if self.data is None:
138             return b''
139         return self.data.oldShapeStream().encode()
140
141     def SetShapeByStream(self, theStream):
142         """
143         Sets geometric shape content of the object as a byte stream in BRep format
144         """
145         if self.data:
146           self.data.updateShape(theStream)
147         else:
148           self.data = StudyData_Swig.StudyData_Object(theStream)
149
150     """
151     Methods from BaseObject
152     """
153     def GetName( self ):
154         """
155         Get name of the object associated with this object.
156         """
157         return self.SO.GetName()
158
159     def SetEntry( self, theInternalEntry ):
160         """
161         Sets internal (unique) entry of the object in the component's data tree.
162         """
163         self.entry = theInternalEntry
164
165     def GetEntry( self ):
166         """
167         Get internal (unique) entry of the object in the component's data tree.
168         """
169         return self.entry
170
171     def GetType( self ):
172         """
173         Get internal type of operation created this object.
174         In SMESH is used to find out if an object is GROUP (type == 37)
175         """
176         return self.type
177
178     def SetType( self, theType ):
179         """
180         Sets internal type of operation created this object.
181         In SMESH is used to find out if an object is GROUP (type == 37, for shape it is default=1)
182         """
183         self.type = theType
184
185     def GetTick( self ):
186         """
187         Get value of a modification counter of the object
188         """
189         if self.data:
190           return self.data.getTick()
191         return 0
192
193     def SetTick( self, theValue ):
194         """
195         Sets value of a modification counter of the object
196         """
197         if self.data:
198           return self.data.setTick(theValue)
199         return 0
200
201     def GetStudyEntry( self ):
202         """
203         Get a Study entry where this object was published.
204         """
205         if self.SO:
206             return self.SO.GetID()
207         return ""
208
209     def IsShape( self ):
210         """
211         Return true if geom object represents a shape.
212         For example, method return false for GEOM_MARKER
213         """
214         return True
215
216     def IsSame( self, other ):
217         """
218         Return true if passed object is identical to this object
219         """
220         return self.GetType() == other.GetType() and self.GetEntry() == other.GetEntry()
221
222     def GetGen( self ):
223         """
224         Return the engine creating this object
225         """
226         e = getEngine()
227         return e._duplicate( e )
228
229     def SetSO( self, theSO ):
230         """
231         Sets SObject of this object (when it is published)
232         """
233         if theSO:
234             theSO.Register() # I hold a GenericObject!
235         if self.SO:
236             self.SO.UnRegister()
237         self.SO = theSO
238
239     def GetSO( self ):
240         """
241         Returns SObject of this object
242         """
243         return self.SO
244
245     def IsParametrical(self):
246         """
247         Returns true if the current object has connection to a parametrical model
248         which can be modified by parameters change.
249         """
250         return not self.IsDead() and self.type == 1 # only break link for shapes are accessible now
251
252     def IsDead(self):
253         """
254         Returns true if the shape is dead - no parametrical link to the SHAPER exists
255         """
256         return self.GetEntry().startswith("dead")
257
258     def MakeDead(self):
259         """
260         Makes the dead-copy of the shape and returns it.
261         """
262         aStudy = getStudy()
263         aBuilder = aStudy.NewBuilder()
264         aRes, aHistSO = self.SO.FindSubObject(10000)
265         if not aRes: # create a "history" folder if it does not exist
266           aHistSO = aBuilder.NewObjectToTag(self.SO, 10000)
267           aHistSO.SetAttrString("AttributeName", "History")
268
269         aDeadSO = aBuilder.NewObject(aHistSO)
270         anIndex = aDeadSO.Tag()
271         aDeadSO.SetAttrString("AttributeName", self.SO.GetName() + " (" + str(anIndex) + ")")
272         aRes, aPixMap = aBuilder.FindAttribute(self.SO, "AttributePixMap")
273         if aRes:
274           aDeadPixMap = aBuilder.FindOrCreateAttribute(aDeadSO, "AttributePixMap")
275           aDeadPixMap.SetPixMap(aPixMap.GetPixMap())
276         aDead = SHAPERSTUDY_Object()
277         aDeadEntry = "dead" + str(anIndex) + "_" + self.GetEntry()
278         aDead.SetEntry(aDeadEntry)
279         aDead.SetShapeByStream(self.data.oldShapeStream())
280         aDeadObj = aDead._this()
281         anIOR = salome.orb.object_to_string(aDeadObj)
282         aDeadSO.SetAttrString("AttributeIOR", anIOR)
283         aDead.SetSO(aDeadSO)
284         if self.GetTick() > 2:
285           aDead.data.setTick(self.GetTick() - 1) # set the tick of an old shape
286         # make dead-copy also sub-groups
287         aSOIter = aStudy.NewChildIterator(self.SO)
288         while aSOIter.More():
289           aGroupSO = aSOIter.Value()
290           anIOR = aGroupSO.GetIOR()
291           if len(anIOR):
292             aGroup = salome.orb.string_to_object(anIOR)
293             if isinstance(aGroup, SHAPERSTUDY_ORB._objref_SHAPER_Group) or \
294                isinstance(aGroup, SHAPERSTUDY_ORB._objref_SHAPER_Field):
295               if isinstance(aGroup, SHAPERSTUDY_ORB._objref_SHAPER_Group):
296                 aDeadGroup = SHAPERSTUDY_Group()
297               else:
298                 aDeadGroup = SHAPERSTUDY_Field()
299               aDeadGroupEntry = "dead" + str(anIndex) + "_" + aGroup.GetEntry()
300               aDeadGroup.SetEntry(aDeadGroupEntry)
301               aDeadGroup.SetSelectionType(aGroup.GetSelectionType())
302               anOldSelection = aGroup.GetSelectionOld()
303               if len(anOldSelection) == 0: # in case there is no old modification, get the current, same as in shape
304                 anOldSelection = aGroup.GetSelection()
305               aDeadGroup.SetSelection(anOldSelection)
306               if isinstance(aGroup, SHAPERSTUDY_ORB._objref_SHAPER_Field): # additional field data
307                 aDeadGroup.SetValuesType(aGroup.GetValuesType())
308                 aDeadGroup.SetSteps(aGroup.GetSteps())
309                 aDeadGroup.SetComponents(aGroup.GetComponents())
310                 for aStep in aGroup.GetSteps():
311                   aStepObj = aGroup.GetStep(aStep)
312                   aDeadGroup.AddFieldStep(aStepObj.GetStamp(), aStep, aStepObj.GetValues())
313               aDeadGroupSO = aBuilder.NewObject(aDeadSO)
314               aDeadGroup.SetSO(aDeadGroupSO)
315               # 15.01.20 groups and fields names stays the same
316               #aDeadGroupSO.SetAttrString("AttributeName", aGroupSO.GetName() + " (" + str(anIndex) + ")")
317               aDeadGroupSO.SetAttrString("AttributeName", aGroupSO.GetName())
318               aRes, aPixMap = aBuilder.FindAttribute(aGroupSO, "AttributePixMap")
319               if aRes:
320                 aDeadPixMap = aBuilder.FindOrCreateAttribute(aDeadGroupSO, "AttributePixMap")
321                 aDeadPixMap.SetPixMap(aPixMap.GetPixMap())
322               aDeadGroupObj = aDeadGroup._this()
323               anIOR = salome.orb.object_to_string(aDeadGroupObj)
324               aDeadGroupSO.SetAttrString("AttributeIOR", anIOR)
325           aSOIter.Next()
326
327         return aDeadObj
328     
329     def SetShapeByPointer(self, theShape):
330         """
331         Sets the shape by the pointer to the TopoDS_Shape
332         """
333         if not self.data:
334           self.data = StudyData_Swig.StudyData_Object()
335         self.data.SetShapeByPointer(theShape)
336         return
337
338     ### unnecessary methods that can be accidentally called from any module
339     def GetTopologyType(self, *args): return GEOM.SHAPE
340     def GetMinShapeType(self, *args): return GEOM.SHAPE
341     def GetMaxShapeType(self, *args): return GEOM.SHAPE
342     def GetSubShapeName(self, *args): return ""
343     def SetColor(self, *args): return
344     def GetColor(self, *args): import SALOMEDS; return SALOMEDS.Color( 0,0,0 )
345     def SetAutoColor(self, *args): return 
346     def GetAutoColor(self, *args): return False
347     def SetMarkerStd(self, *args): return 
348     def SetMarkerTexture(self, *args): return 
349     def GetMarkerType(self, *args): return GEOM.MT_NONE
350     def GetMarkerSize(self, *args): return GEOM.MS_NONE
351     def GetMarkerTexture(self, *args): return 0
352
353     pass
354
355 class SHAPERSTUDY_Group(SHAPERSTUDY_ORB__POA.SHAPER_Group, SHAPERSTUDY_Object):
356     """
357     Constructs an instance of SHAPERSTUDY Group
358     """
359     def __init__ ( self, *args):
360         SHAPERSTUDY_GenericObject.__init__(self)
361         self.seltype = None
362         self.selection = []
363         self.selectionTick = -2 # tick of the main shape when the current selection is set
364         self.selectionOld = [] # keep selection for breaking link
365         self.SO = None
366         self.data = None
367         self.entry = ""
368         self.type = 37 # a group type
369         pass
370
371     def SetSelectionType(self, theType):
372         """
373         Sets what is returned in the GEOM_IGroupOperations::GetType
374         """
375         self.seltype = theType
376
377     def GetSelectionType(self):
378         """
379         Returns the type of the selected sub-shapes
380         """
381         return self.seltype
382
383     def SetSelection(self, theSelection):
384         """
385         Sets what is returned in the GEOM_IGroupOperations::GetObjects
386         """
387         aTick = -2
388         if self.SO:
389           aMainShape = self.GetMainShape()
390           if aMainShape:
391             aTick = aMainShape.GetTick()
392         if aTick != self.selectionTick or aTick == -2:
393           self.selectionOld = self.selection
394           self.selection = theSelection
395           self.selectionTick = aTick
396           #print("Set selection " + self.entry + " old = " + str(self.selectionOld) + " new = " + str(self.selection) + " tick = " + str(aTick))
397         else:
398           self.selection = theSelection
399           #print("Set selection " + self.entry + " tick = " + str(aTick))
400         pass
401
402     def GetSelection(self):
403         """
404         Returns the selected sub-shapes indices
405         """
406         return self.selection
407
408     def GetSelectionOld(self):
409         """
410         Returns the previously selected sub-shapes indices
411         """
412         #print("get selection OLD " + self.entry + " old = " + str(self.selectionOld) + " new = " + str(self.selection))
413         return self.selectionOld
414
415     def IsMainShape( self ):
416         """
417         Returns True if this object is not a sub-shape of another object.
418         """
419         return False
420
421     def GetMainShape( self ):
422         """
423         Main shape is groups owner
424         """
425         return self.SO.GetFather().GetObject()
426
427     def GetSubShapeIndices( self ):
428         """
429         Get a list of ID's of sub-shapes in the main shape.
430         """
431         return self.selection
432
433     def getShape( self ):
434         """
435         Redefinition of the getShape method: here it creates a shape by the
436         main shape and the group index.
437         """
438         if not self.data:
439           self.data = StudyData_Swig.StudyData_Object()
440         # convert selection to long list
441         anArg = StudyData_Swig.LongList()
442         for l in self.selection:
443           anArg.append(l)
444         return self.data.groupShape(self.GetMainShape().getShape(), anArg)
445
446     def GetShapeType( self ):
447         """
448         Group shape type is always compound.
449         """
450         return GEOM.COMPOUND;
451
452     pass
453
454     def GetTick( self ):
455         """
456         Get value of a modification counter of the group
457         """
458         return self.selectionTick
459
460     def SetTick( self, theValue ):
461         """
462         Sets value of a modification counter of the group
463         """
464         #print("Set tick " + self.entry + " tick = " + str(theValue))
465         self.selectionTick = theValue
466
467 class SHAPERSTUDY_Field(SHAPERSTUDY_ORB__POA.SHAPER_Field, SHAPERSTUDY_Group):
468     """
469     Constructs an instance of SHAPERSTUDY Field (inherits selection from a Group object)
470     """
471     def __init__ ( self, *args):
472         SHAPERSTUDY_GenericObject.__init__(self)
473         self.seltype = None
474         self.selection = []
475         self.selectionTick = -2 # tick of the main shape when the current selection is set
476         self.selectionOld = [] # keep selection for breaking link
477         self.SO = None
478         self.data = None
479         self.entry = None
480         self.type = 52 # a field type
481         self.valtype = None # type of the values
482         self.steps = [] # list of long
483         self.components = [] # string array, names of the components
484         self.name = None # name, string
485         self.fieldsteps = {} # FieldSteps objects identified by step ID
486         pass
487
488     def SetValuesType( self, theType ):
489       """
490       Sets the type of values in the field
491       """
492       self.valtype = theType
493
494     def GetValuesType( self ):
495       """
496       Returns the type of values in the field
497       """
498       return self.valtype
499
500
501     def GetDataType( self ):
502       """
503       Returns the type of values in the field in terms of GEOM enumeration
504       """
505       if self.valtype == 0:
506         return GEOM.FDT_Bool
507       elif self.valtype == 1:
508         return GEOM.FDT_Int
509       elif self.valtype == 2:
510         return GEOM.FDT_Double
511       elif self.valtype == 3:
512         return GEOM.FDT_String
513       return None # unknown case
514
515     def GetShape ( self ):
516       """
517       Returns the shape the field lies on
518       """
519       return super().GetMainShape()
520
521     def SetSteps( self, theSteps ):
522       self.steps = theSteps
523
524     def GetSteps( self ):
525       return self.steps
526
527     def SetComponents( self, theComponents ):
528       self.components = theComponents
529     
530     def GetComponents( self ):
531       return self.components
532
533     def GetDimension( self ):
534       aShapeType = super().GetSelectionType()
535       if aShapeType == 8:
536         return -1 # whole part
537       elif aShapeType == 7:
538         return 0 # vertex
539       elif aShapeType == 6:
540         return 1 # edge
541       elif aShapeType == 4:
542         return 2 # face
543       elif aShapeType == 2:
544         return 3 # solid
545       return None # unknown case
546
547     def ClearFieldSteps( self ):
548        self.fieldsteps = {}
549
550     def AddFieldStep( self, theStampID, theStepID, theValues):
551       aFieldStep = None
552       if self.valtype == 0:
553         aFieldStep = SHAPER_BoolFieldStep()
554       elif self.valtype == 1:
555         aFieldStep = SHAPER_IntFieldStep()
556       elif self.valtype == 2:
557         aFieldStep = SHAPER_DoubleFieldStep()
558       
559       aFieldStep.SetStep(theStampID, theStepID, theValues)
560       self.fieldsteps[theStepID] = aFieldStep._this()
561
562     def GetStep( self, theStepID ):
563        return self.fieldsteps[theStepID]
564
565     pass
566
567 class SHAPER_FieldStep:
568     """
569     Base class for all step-classes
570     """
571     def __init__ ( self, *args):
572         self.stamp = None  # long, ID of stamp
573         self.step = None   # long, ID of step
574         self.values = None # array of values of the needed type
575
576     """
577     Defines all parameters of the step
578     """
579     def SetStep( self, theStamp, theStep, theValues ):
580         self.stamp = theStamp
581         self.step = theStep
582         self.values = theValues
583      
584     """
585     Returns stamp ID
586     """
587     def GetStamp( self ):
588         return self.stamp
589     """
590     Returns step ID
591     """
592     def GetID( self ):
593         return self.step
594     """
595     Returns a name of a sub-shape if the sub-shape is published in the study
596     """
597     def GetSubShape(self, theSubID):
598         # the SHAPER study does not support sub-shapes for now
599         return ""
600         
601
602 class SHAPER_DoubleFieldStep(SHAPERSTUDY_ORB__POA.SHAPER_DoubleFieldStep, SHAPER_FieldStep):
603     """
604     Constructs an instance of SHAPERSTUDY Field step of type Double
605     """
606     def __init__ ( self, *args):
607         pass
608
609     """
610     Returns values as an array of the needed type
611     """
612     def GetValues( self ):
613         aResult = [] # to make any type of result, create a corba-type
614         for i in self.values:
615           aResult.append(float(i))
616         return aResult
617
618     pass
619
620 class SHAPER_IntFieldStep(SHAPERSTUDY_ORB__POA.SHAPER_IntFieldStep, SHAPER_FieldStep):
621     """
622     Constructs an instance of SHAPERSTUDY Field step of type Double
623     """
624     def __init__ ( self, *args):
625         pass
626
627     """
628     Returns values as an array of the needed type
629     """
630     def GetValues( self ):
631         aResult = [] # to make any type of result, create a corba-type
632         for i in self.values:
633           aResult.append(int(i))
634         return aResult
635
636     pass
637
638 class SHAPER_BoolFieldStep(SHAPERSTUDY_ORB__POA.SHAPER_BoolFieldStep, SHAPER_FieldStep):
639     """
640     Constructs an instance of SHAPERSTUDY Field step of type Double
641     """
642     def __init__ ( self, *args):
643         pass
644
645     """
646     Returns values as an array of the needed type
647     """
648     def GetValues( self ):
649         aResult = [] # to make any type of result, create a corba-type
650         for i in self.values:
651           aResult.append(int(i))
652         return aResult
653
654     pass
655