Salome HOME
4f9a01044a9583a0ad9efa4a914034fc08392cea
[modules/geom.git] / src / GEOM_PY / geomtools.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
4 #
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License.
9 #
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 #
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #
21 """
22 This module provides tools to facilitate the use of geom engine and geom
23 objects in Salome.
24 """
25
26 import salome
27 GEOM = None    # GEOM module is loaded only when needed
28
29 from salome.kernel.logger import Logger
30 from salome.kernel import termcolor
31 logger = Logger("salome.geom.geomtools", color = termcolor.RED)
32
33 from salome.kernel.studyedit import getActiveStudyId, getStudyEditor
34 from salome.kernel.services import IDToObject, IDToSObject
35 try:
36     from salome.gui import helper as guihelper
37 except:
38     pass
39
40 _geompys = {}
41
42 def getGeompy(studyId = None):
43     """
44     Return an object behaving exactly like geompy module, except that it is
45     associated with the study `studyId`. If `studyId` is :const:`None`, return
46     a pseudo geompy object for the current study.
47     """
48     # We can't use geompy module because it initializes GEOM with
49     # salome.myStudy, which may not exist. So we use this trick to create
50     # a pseudo geompy module. 
51     salome.salome_init()
52     if studyId is None:
53         studyId = getActiveStudyId()
54     if not _geompys.has_key(studyId):
55         from salome.geom import geomBuilder
56         study = salome.myStudyManager.GetStudyByID(studyId)
57         _geompys[studyId] = geomBuilder.New(study)
58     return _geompys[studyId]
59
60
61 ModeWireFrame = 0
62 ModeShading = 1
63 DisplayMode=ModeShading
64 PreviewColor=[236,163,255]
65
66 class GeomStudyTools:
67     """
68     This class provides several methods to manipulate geom objects in Salome
69     study. The parameter `studyEditor` defines a
70     :class:`~salome.kernel.studyedit.StudyEditor` object used to access the study. If
71     :const:`None`, the method returns a :class:`~salome.kernel.studyedit.StudyEditor`
72     object on the current study.
73
74     .. attribute:: editor
75     
76        This instance attribute contains the underlying
77        :class:`~salome.kernel.studyedit.StudyEditor` object. It can be used to access
78        the study but the attribute itself should not be modified.
79
80     """
81
82     def __init__(self, studyEditor = None):
83         global GEOM
84         if GEOM is None:
85             GEOM = __import__("GEOM")
86         if studyEditor is None:
87             studyEditor = getStudyEditor()
88         self.editor = studyEditor
89
90     # ======================================================================
91     # Helper functions to add/remove a geometrical shape in/from the study
92     # ======================================================================
93     def addShapeToStudy(self, shape,shapeName,folderName=None):
94         """
95         Add a GEOM shape in the study. It returns the associated entry
96         that corresponds to the identifier of the entry in the study. This
97         entry can be used to retrieve an object in the study. A folderName
98         can be specified. In this case, a folder with this name is first
99         created in the Geometry part of the study, and the shape study
100         object is stored in this folder of the study. 
101
102         :type   shape: GEOM object
103         :param  shape: the GEOM object defining the shape
104
105         :type   shapeName: string
106         :param  shapeName: the name for this shape in the study 
107
108         :type   folderName: string
109         :param  folderName: the name of a folder in the GEOM part of the study
110         """
111         study   = self.editor.study
112         studyId = study._get_StudyId()
113         geompy  = getGeompy(studyId)
114
115         if folderName is None:
116             # Insert the shape in the study by the standard way
117             entry = geompy.addToStudy( shape, shapeName )
118         else:
119             # A folder name has been specified to embed this shape. Find
120             # or create a folder with this name in the Geometry study, and
121             # then store the shape in this folder.
122             geomStudyFolder = self.editor.findOrCreateComponent("GEOM")
123             shapeStudyFolder = self.editor.findOrCreateItem(geomStudyFolder,folderName)
124             
125             shapeIor = salome.orb.object_to_string(shape)
126             geomgui = salome.ImportComponentGUI("GEOM")
127             shapeIcon = geomgui.getShapeTypeIcon(shapeIor)
128             
129             shapeStudyObject = self.editor.createItem(shapeStudyFolder,
130                                                       name=shapeName,
131                                                       IOR=shapeIor,
132                                                       icon=shapeIcon)
133             entry = shapeStudyObject.GetID()
134
135         return entry
136
137     def removeFromStudy(self, shapeStudyEntry):
138         """
139         This removes the specified entry from the study. Note that this
140         operation does not destroy the underlying GEOM object, neither
141         erase the drawing in the viewer.
142         The underlying GEOM object is returned (so that it can be destroyed)
143         """
144         study = self.editor.study
145         studyId = study._get_StudyId()
146         shape = self.getGeomObjectFromEntry(shapeStudyEntry)    
147         studyObject = IDToSObject(shapeStudyEntry)
148         self.editor.removeItem(studyObject,True)
149         return shape
150
151     # ======================================================================
152     # Helper functions to display/erase a shape in/from the viewer. The
153     # shape must be previously put in the study and the study entry must
154     # be known. Note also that these function works implicitly on the
155     # active study (WARN: it does not ensure consistency with the
156     # study associated to the studyEditor used to initiate this
157     # object. It's up to you to be self-consistent (or to improve this
158     # python source code). 
159     # ======================================================================
160
161     def displayShapeByName(self, shapeName, color = None, fit=True):
162         """
163         Display the geometrical shape whose name in the study is `shapeName`.
164         
165         :type   shapeName: string
166         :param  shapeName: name of the geometrical shape
167         
168         :type   color: tuple (triplet)
169         :param  color: RGB components of the color of the shape
170         
171         :return: True if the shape was found, False otherwise
172         """
173         logger.debug("displayShapeByName in PAL: %s with color %s" %
174                      (shapeName, color))
175         listSO = self.editor.study.FindObjectByName(shapeName, "GEOM")
176         for sObj in listSO:
177             entry = sObj.GetID()
178             geomObj = self.editor.getOrLoadObject(sObj)
179             if geomObj:
180                 shape = geomObj._narrow(GEOM.GEOM_Object)
181                 if shape:
182                     return self.displayShapeByEntry(entry,color,fit)
183         return False
184
185     def displayShapeByEntry(self, shapeStudyEntry, color = None, fit=True):
186         """
187         Display the geometrical shape whose entry is given by
188         `entry`. You should prefer use this function instead of the
189         displayShapeByName which can have an unpredictible behavior in
190         the case where several objects exist with the same name in the
191         study.
192         """
193         geomgui = salome.ImportComponentGUI("GEOM")
194         if fit:
195             geomgui.createAndDisplayFitAllGO(shapeStudyEntry)
196         else:
197             geomgui.createAndDisplayGO(shapeStudyEntry)
198         geomgui.setDisplayMode(shapeStudyEntry, DisplayMode)
199         if color is not None:
200             geomgui.setColor(shapeStudyEntry, color[0], color[1], color[2])
201         return True
202
203     def eraseShapeByEntry(self, shapeStudyEntry):
204         """
205         Erase the geometrical shape whose entry is given by
206         `entry`. Please note that the shape is just erased from the
207         viewer. The associated study object still exists in the study,
208         and the geom object still exists in the GEOM engine.
209         """
210         geomgui = salome.ImportComponentGUI("GEOM")
211         eraseFromAllWindows=True
212         geomgui.eraseGO(shapeStudyEntry,eraseFromAllWindows)
213         return True
214
215
216     # ======================================================================
217     # Helper functions for a complete suppression of a shape from the
218     # SALOME session.
219     # ======================================================================
220     def deleteShape(self,shapeStudyEntry):
221         """
222         This completly deletes a geom shape.
223         
224         WARNING: please be aware that to delete a geom object, you have
225         three operations to perform:
226         
227         1. erase the shape from the viewers
228         2. remove the entry from the study
229         3. destroy the underlying geom object
230         """
231         self.eraseShapeByEntry(shapeStudyEntry)
232         shape = self.removeFromStudy(shapeStudyEntry)
233         shape.Destroy()
234
235     # ======================================================================
236     # Helper functions for interactivity with the object browser
237     # ======================================================================
238     def getGeomObjectSelected(self):
239         '''
240         Returns the GEOM object currently selected in the objects browser.
241         '''
242         sobject, entry = guihelper.getSObjectSelected()
243         geomObject = self.getGeomObjectFromEntry(entry)
244         return geomObject
245
246     def getGeomObjectFromEntry(self,entry):
247         '''
248         Returns the GEOM object associated to the specified entry,
249         (the entry is the identifier of an item in the active study)
250         '''
251         if entry is None:
252             return None
253         geomObject=IDToObject(entry, self.editor.study)
254         return geomObject._narrow(GEOM.GEOM_Object)
255
256 #
257 # ==================================================================
258 # Use cases and demo functions
259 # ==================================================================
260 #
261
262 # How to test?
263 # 1. Run a SALOME application including GEOM, and create a new study
264 # 2. In the console, enter:
265 #    >>> from salome.geom import geomtools
266 #    >>> geomtools.TEST_createBox()
267 # 3. Select the object named "box" in the browser
268 # 4. In the console, enter:
269 #    >>> geomtools.TEST_getGeomObjectSelected()
270
271 def TEST_createBox():
272     geompy = getGeompy()
273     box = geompy.MakeBoxDXDYDZ(200, 200, 200)
274     geompy.addToStudy( box, 'box' )    
275     if salome.sg.hasDesktop():
276         salome.sg.updateObjBrowser(1)
277
278
279 def TEST_getGeomObjectSelected():
280     tool = GeomStudyTools()
281     myGeomObject = tool.getGeomObjectSelected()
282     print myGeomObject
283
284 def TEST_createAndDeleteShape():
285     """
286     This test is a simple use case that illustrates how to create a
287     GEOM shape in a SALOME session (create the GEOM object, put in in
288     the study, and display the shape in a viewer) and delete a shape
289     from a SALOME session (erase the shape from the viewer, delete the
290     entry from the study, and finally destroy the underlying GEOM
291     object).
292     """
293     import salome
294     salome.salome_init()
295     study   = salome.myStudy
296     studyId = salome.myStudyId
297
298     from salome.geom import geomtools
299     geompy = geomtools.getGeompy(studyId)
300     
301     from salome.kernel.studyedit import getStudyEditor
302     studyEditor = getStudyEditor(studyId)
303
304     gst = geomtools.GeomStudyTools(studyEditor)
305
306     # --------------------------------------------------
307     # Create a first shape (GEOM object)
308     radius = 5
309     length = 100
310     cylinder = geompy.MakeCylinderRH(radius, length)
311
312     # Register the shape in the study, at the root of the GEOM
313     # folder. A name must be specified. The register operation
314     # (addShapeToStudy) returns an identifier of the entry in the study.
315     cylinderName = "cyl.r%s.l%s"%(radius,length)
316     cylinderStudyEntry = gst.addShapeToStudy(cylinder, cylinderName)
317
318     # Display the registered shape in a viewer
319     gst.displayShapeByEntry(cylinderStudyEntry)
320
321     # --------------------------------------------------
322     # A second shape
323     radius = 10
324     sphere = geompy.MakeSphereR(radius)
325     sphereName = "sph.r%s"%radius
326     sphereStudyEntry = gst.addShapeToStudy(sphere, sphereName)
327     gst.displayShapeByEntry(sphereStudyEntry)
328
329     # --------------------------------------------------
330     # This new shape is stored in the study, but in a specific
331     # sub-folder, and is displayed in the viewer with a specific
332     # color.
333     length = 20
334     box = geompy.MakeBoxDXDYDZ(length,length,length)
335     boxName = "box.l%s"%length
336     folderName = "boxset" 
337     boxStudyEntry = gst.addShapeToStudy(box, boxName, folderName)
338     gst.displayShapeByEntry(boxStudyEntry,PreviewColor)
339
340     # --------------------------------------------------
341     # In this example, we illustrate how to erase a shape (the sphere)
342     # from the viewer. After this operation, the sphere is no longer
343     # displayed but still exists in the study. You can then redisplay
344     # it using the context menu of the SALOME object browser.
345     gst.eraseShapeByEntry(sphereStudyEntry)
346
347     # --------------------------------------------------
348     # In this last example, we completly delete an object from the
349     # SALOME session (erase from viewer, remove from study and finnaly
350     # destroy the object). This is done by a simple call to
351     # deleteShape().
352     gst.deleteShape(cylinderStudyEntry)
353
354     # --------------------------------------------------
355     # At the end of the executioon of this test, you should have in
356     # the SALOME session:
357     # - the box, in a dedicated folder of the study, and displayed in the viewer
358     # - the sphere, in the standard place of the study, and not displayed 
359
360     # If you comment the deleteShape line, you should see the cylinder
361     # in the study and displayed in the viewer. 
362
363 if __name__ == "__main__":
364     #TEST_getGeomObjectSelected()
365     TEST_createAndDeleteShape()
366
367
368