Salome HOME
19a86e105f983a55fad7a79edb84958b436b0a40
[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 GetColor(self, *args): import SALOMEDS; return SALOMEDS.Color( -1,-1,-1 )
346     def SetAutoColor(self, *args): return 
347     def GetAutoColor(self, *args): return False
348     def SetMarkerStd(self, *args): return 
349     def SetMarkerTexture(self, *args): return 
350     def GetMarkerType(self, *args): return GEOM.MT_NONE
351     def GetMarkerSize(self, *args): return GEOM.MS_NONE
352     def GetMarkerTexture(self, *args): return 0
353
354     pass
355
356 class SHAPERSTUDY_Group(SHAPERSTUDY_ORB__POA.SHAPER_Group, SHAPERSTUDY_Object):
357     """
358     Constructs an instance of SHAPERSTUDY Group
359     """
360     def __init__ ( self, *args):
361         SHAPERSTUDY_GenericObject.__init__(self)
362         self.seltype = None
363         self.selection = []
364         self.selectionTick = -2 # tick of the main shape when the current selection is set
365         self.selectionOld = [] # keep selection for breaking link
366         self.SO = None
367         self.data = None
368         self.entry = ""
369         self.type = 37 # a group type
370         pass
371
372     def SetSelectionType(self, theType):
373         """
374         Sets what is returned in the GEOM_IGroupOperations::GetType
375         """
376         self.seltype = theType
377
378     def GetSelectionType(self):
379         """
380         Returns the type of the selected sub-shapes
381         """
382         return self.seltype
383
384     def SetSelection(self, theSelection):
385         """
386         Sets what is returned in the GEOM_IGroupOperations::GetObjects
387         """
388         aTick = -2
389         if self.SO:
390           aMainShape = self.GetMainShape()
391           if aMainShape:
392             aTick = aMainShape.GetTick()
393         if aTick > self.selectionTick or aTick == -2:
394           self.selectionOld = self.selection
395           self.selection = theSelection
396           self.selectionTick = aTick
397           #print("Set selection " + self.entry + " old = " + str(self.selectionOld) + " new = " + str(self.selection) + " tick = " + str(aTick))
398         elif self.selection != theSelection:
399           self.selectionOld = self.selection
400           self.selection = theSelection
401           if self.selectionTick < 0:
402             self.selectionTick = aTick + 1
403           else:
404             self.selectionTick = self.selectionTick + 1 # when the group is changed, but the main shape stays the same, make tick + 1
405           #print("Set selection " + self.entry + " old = " + str(self.selectionOld) + " new = " + str(self.selection) + " tick = " + str(self.selectionTick))
406         pass
407
408     def GetSelection(self):
409         """
410         Returns the selected sub-shapes indices
411         """
412         return self.selection
413
414     def GetSelectionOld(self):
415         """
416         Returns the previously selected sub-shapes indices
417         """
418         #print("get selection OLD " + self.entry + " old = " + str(self.selectionOld) + " new = " + str(self.selection))
419         return self.selectionOld
420
421     def IsMainShape( self ):
422         """
423         Returns True if this object is not a sub-shape of another object.
424         """
425         return False
426
427     def GetMainShape( self ):
428         """
429         Main shape is groups owner
430         """
431         return self.SO.GetFather().GetObject()
432
433     def GetSubShapeIndices( self ):
434         """
435         Get a list of ID's of sub-shapes in the main shape.
436         """
437         return self.selection
438
439     def getShape( self ):
440         """
441         Redefinition of the getShape method: here it creates a shape by the
442         main shape and the group index.
443         """
444         if not self.data:
445           self.data = StudyData_Swig.StudyData_Object()
446         # convert selection to long list
447         anArg = StudyData_Swig.LongList()
448         for l in self.selection:
449           anArg.append(l)
450         return self.data.groupShape(self.GetMainShape().getShape(), anArg)
451
452     def GetShapeType( self ):
453         """
454         Group shape type is always compound.
455         """
456         return GEOM.COMPOUND;
457
458     pass
459
460     def GetTick( self ):
461         """
462         Get value of a modification counter of the group
463         """
464         return self.selectionTick
465
466     def SetTick( self, theValue ):
467         """
468         Sets value of a modification counter of the group
469         """
470         #print("Set tick " + self.entry + " tick = " + str(theValue))
471         self.selectionTick = theValue
472
473 class SHAPERSTUDY_Field(SHAPERSTUDY_ORB__POA.SHAPER_Field, SHAPERSTUDY_Group):
474     """
475     Constructs an instance of SHAPERSTUDY Field (inherits selection from a Group object)
476     """
477     def __init__ ( self, *args):
478         SHAPERSTUDY_GenericObject.__init__(self)
479         self.seltype = None
480         self.selection = []
481         self.selectionTick = -2 # tick of the main shape when the current selection is set
482         self.selectionOld = [] # keep selection for breaking link
483         self.SO = None
484         self.data = None
485         self.entry = None
486         self.type = 52 # a field type
487         self.valtype = None # type of the values
488         self.steps = [] # list of long
489         self.components = [] # string array, names of the components
490         self.name = None # name, string
491         self.fieldsteps = {} # FieldSteps objects identified by step ID
492         pass
493
494     def SetValuesType( self, theType ):
495       """
496       Sets the type of values in the field
497       """
498       self.valtype = theType
499
500     def GetValuesType( self ):
501       """
502       Returns the type of values in the field
503       """
504       return self.valtype
505
506
507     def GetDataType( self ):
508       """
509       Returns the type of values in the field in terms of GEOM enumeration
510       """
511       if self.valtype == 0:
512         return GEOM.FDT_Bool
513       elif self.valtype == 1:
514         return GEOM.FDT_Int
515       elif self.valtype == 2:
516         return GEOM.FDT_Double
517       elif self.valtype == 3:
518         return GEOM.FDT_String
519       return None # unknown case
520
521     def GetShape ( self ):
522       """
523       Returns the shape the field lies on
524       """
525       return super().GetMainShape()
526
527     def SetSteps( self, theSteps ):
528       self.steps = theSteps
529
530     def GetSteps( self ):
531       return self.steps
532
533     def SetComponents( self, theComponents ):
534       self.components = theComponents
535     
536     def GetComponents( self ):
537       return self.components
538
539     def GetDimension( self ):
540       aShapeType = super().GetSelectionType()
541       if aShapeType == 8:
542         return -1 # whole part
543       elif aShapeType == 7:
544         return 0 # vertex
545       elif aShapeType == 6:
546         return 1 # edge
547       elif aShapeType == 4:
548         return 2 # face
549       elif aShapeType == 2:
550         return 3 # solid
551       return None # unknown case
552
553     def ClearFieldSteps( self ):
554        self.fieldsteps = {}
555
556     def AddFieldStep( self, theStampID, theStepID, theValues):
557       aFieldStep = None
558       if self.valtype == 0:
559         aFieldStep = SHAPER_BoolFieldStep()
560       elif self.valtype == 1:
561         aFieldStep = SHAPER_IntFieldStep()
562       elif self.valtype == 2:
563         aFieldStep = SHAPER_DoubleFieldStep()
564       
565       aFieldStep.SetStep(theStampID, theStepID, theValues)
566       self.fieldsteps[theStepID] = aFieldStep._this()
567
568     def GetStep( self, theStepID ):
569        return self.fieldsteps[theStepID]
570
571     pass
572
573 class SHAPER_FieldStep:
574     """
575     Base class for all step-classes
576     """
577     def __init__ ( self, *args):
578         self.stamp = None  # long, ID of stamp
579         self.step = None   # long, ID of step
580         self.values = None # array of values of the needed type
581
582     """
583     Defines all parameters of the step
584     """
585     def SetStep( self, theStamp, theStep, theValues ):
586         self.stamp = theStamp
587         self.step = theStep
588         self.values = theValues
589      
590     """
591     Returns stamp ID
592     """
593     def GetStamp( self ):
594         return self.stamp
595     """
596     Returns step ID
597     """
598     def GetID( self ):
599         return self.step
600     """
601     Returns a name of a sub-shape if the sub-shape is published in the study
602     """
603     def GetSubShape(self, theSubID):
604         # the SHAPER study does not support sub-shapes for now
605         return ""
606         
607
608 class SHAPER_DoubleFieldStep(SHAPERSTUDY_ORB__POA.SHAPER_DoubleFieldStep, SHAPER_FieldStep):
609     """
610     Constructs an instance of SHAPERSTUDY Field step of type Double
611     """
612     def __init__ ( self, *args):
613         pass
614
615     """
616     Returns values as an array of the needed type
617     """
618     def GetValues( self ):
619         aResult = [] # to make any type of result, create a corba-type
620         for i in self.values:
621           aResult.append(float(i))
622         return aResult
623
624     pass
625
626 class SHAPER_IntFieldStep(SHAPERSTUDY_ORB__POA.SHAPER_IntFieldStep, SHAPER_FieldStep):
627     """
628     Constructs an instance of SHAPERSTUDY Field step of type Double
629     """
630     def __init__ ( self, *args):
631         pass
632
633     """
634     Returns values as an array of the needed type
635     """
636     def GetValues( self ):
637         aResult = [] # to make any type of result, create a corba-type
638         for i in self.values:
639           aResult.append(int(i))
640         return aResult
641
642     pass
643
644 class SHAPER_BoolFieldStep(SHAPERSTUDY_ORB__POA.SHAPER_BoolFieldStep, SHAPER_FieldStep):
645     """
646     Constructs an instance of SHAPERSTUDY Field step of type Double
647     """
648     def __init__ ( self, *args):
649         pass
650
651     """
652     Returns values as an array of the needed type
653     """
654     def GetValues( self ):
655         aResult = [] # to make any type of result, create a corba-type
656         for i in self.values:
657           aResult.append(int(i))
658         return aResult
659
660     pass
661