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