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