Salome HOME
1bc68d1863769f9248eff46bb8759530b8c34f6b
[modules/geom.git] / src / GEOM_PY / structelem / orientation.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 is used to compute the orientation of the different parts in a
23 structural element and to build the corresponding markers (trihedrons).
24 """
25
26 import math
27
28 from salome.kernel.logger import Logger
29 from salome.kernel import termcolor
30 logger = Logger("salome.geom.structelem.orientation", color = termcolor.RED)
31
32
33 class Orientation1D:
34     """
35     This class is used to compute the orientation of 1D elements and to build
36     the corresponding markers.
37     """
38     
39     def __init__(self):
40         self.geom = None
41         self._vectorYCoords = None
42         self._angle = 0.0
43
44     def __repr__(self):
45         reprdict = self.__dict__.copy()
46         del reprdict["geom"]
47         return '%s(%s)' % (self.__class__.__name__, reprdict)
48
49     def addParams(self, params):
50         """
51         Add orientation parameters. `params` is a dictionary containing one or
52         several orientation parameters. The valid parameters are:
53
54         * "VECT_Y": Triplet defining the local Y axis (the X axis is the
55           main direction of the 1D element).
56         * "ANGL_VRIL": Angle of rotation along the X axis to define the local
57           coordinate system.
58         
59         The parameters can be specified several times. In this case, only the
60         last "VECT_Y" or "ANGL_VRIL" is taken into account.
61         """
62         if self._vectorYCoords is not None or self._angle != 0.0:
63             logger.warning('Orientation parameters are specified several '
64                            'times for the same mesh group, only the last '
65                            'parameter will be used')
66         mydict = params.copy()
67         if mydict.has_key("VECT_Y"):
68             newVecCoords = mydict.pop("VECT_Y")
69             logger.debug("Setting orientation vector Y to %s" %
70                              str(newVecCoords))
71             self._vectorYCoords = newVecCoords
72             self._angle = 0.0
73         if mydict.has_key("ANGL_VRIL"):
74             newAngle = mydict.pop("ANGL_VRIL")
75             logger.debug("Setting orientation angle to %f" % newAngle)
76             self._angle = newAngle
77             self._vectorYCoords = None
78         if len(mydict) > 0:
79             logger.warning("Invalid orientation parameter(s) (ignored): %s" %
80                            str(mydict))
81
82     def _getDefaultVecYZ(self, center, vecX):
83         """
84         Get the vectors Y and Z for the default LCS, that use the main
85         direction of the 1D object as the local X axis and the global Z axis
86         to determine the local Z axis.
87         """
88         xPoint = self.geom.MakeTranslationVector(center, vecX)
89         givenVecZ = self.geom.MakeVectorDXDYDZ(0.0, 0.0, 1.0)
90         angle = self.geom.GetAngleRadians(vecX, givenVecZ)
91         if abs(angle) < 1e-7 or abs(angle - math.pi) < 1e-7:
92             logger.warning("Beam X axis is colinear to absolute Z axis. "
93                            "Absolute X axis will be used to determine "
94                            "local Z axis.")
95             givenVecZ = self.geom.MakeVectorDXDYDZ(1.0, 0.0, 0.0)
96         zPoint = self.geom.MakeTranslationVector(center, givenVecZ)
97         locPlaneZX = self.geom.MakePlaneThreePnt(center, zPoint, xPoint, 1.0)
98         locY = self.geom.GetNormal(locPlaneZX)
99         yPoint = self.geom.MakeTranslationVector(center, locY)
100         locPlaneXY = self.geom.MakePlaneThreePnt(center, xPoint, yPoint, 1.0)
101         locZ = self.geom.GetNormal(locPlaneXY)
102         return (locY, locZ)
103
104     def buildMarker(self, geom, center, vecX):
105         """
106         Create a marker with origin `center` and X axis `vecX`. `geom` is the
107         pseudo-geompy object used to build the geometric shapes.
108         """
109         (locY, locZ) = self.getVecYZ(geom, center, vecX)
110         marker = geom.MakeMarkerPntTwoVec(center, vecX, locY)
111         return marker
112
113     def getVecYZ(self, geom, center, vecX):
114         """
115         Get the vectors Y and Z for the LCS with origin `center` and X axis
116         `vecX`. `geom` is the pseudo-geompy object used to build the geometric
117         shapes.
118         """
119         self.geom = geom
120         locY = None
121         locZ = None
122         if self._vectorYCoords is None:
123             (locY, locZ) = self._getDefaultVecYZ(center, vecX)
124         else:
125             xPoint = self.geom.MakeTranslationVector(center, vecX)
126             givenLocY = self.geom.MakeVectorDXDYDZ(self._vectorYCoords[0],
127                                                    self._vectorYCoords[1],
128                                                    self._vectorYCoords[2])
129             angle = self.geom.GetAngleRadians(vecX, givenLocY)
130             if abs(angle) < 1e-7 or abs(angle - math.pi) < 1e-7:
131                 logger.warning("Vector Y is colinear to the beam X axis, "
132                                "using default LCS.")
133                 (locY, locZ) = self._getDefaultVecYZ(center, vecX)
134             else:
135                 yPoint = self.geom.MakeTranslationVector(center, givenLocY)
136                 locPlaneXY = self.geom.MakePlaneThreePnt(center, xPoint,
137                                                          yPoint, 1.0)
138                 locZ = self.geom.GetNormal(locPlaneXY)
139                 zPoint = self.geom.MakeTranslationVector(center, locZ)
140                 locPlaneZX = self.geom.MakePlaneThreePnt(center, zPoint,
141                                                          xPoint, 1.0)
142                 locY = self.geom.GetNormal(locPlaneZX)
143
144         if self._angle != 0.0:
145             angleRad = math.radians(self._angle)
146             locY = self.geom.Rotate(locY, vecX, angleRad)
147             locZ = self.geom.Rotate(locZ, vecX, angleRad)
148
149         return (locY, locZ)
150
151
152 class Orientation2D:
153     """
154     This class is used to compute the orientation of 2D elements and to build
155     the corresponding markers. Angles `alpha` and `beta` are used to determine
156     the local coordinate system for the 2D element. If `vect` is not
157     :const:`None`, it is used instead of `alpha` and `beta`.
158     """
159
160     def __init__(self, alpha, beta, vect):
161         self.geom = None
162         self._alpha = alpha
163         self._beta = beta
164         self._vect = vect
165
166     def __repr__(self):
167         reprdict = self.__dict__.copy()
168         del reprdict["geom"]
169         return '%s(%s)' % (self.__class__.__name__, reprdict)
170
171     def _buildDefaultMarker(self, center, normal, warnings = True):
172         """
173         Create the default marker, that use the normal vector of the 2D object
174         as the local Z axis and the global X axis to determine the local X
175         axis. `warnings` can be used to enable or disable the logging of
176         warning messages.
177         """
178         marker = None
179         globalVecX = self.geom.MakeVectorDXDYDZ(1.0, 0.0, 0.0)
180         angle = self.geom.GetAngleRadians(normal, globalVecX)
181         if abs(angle) < 1e-7 or abs(angle - math.pi) < 1e-7:
182             if warnings:
183                 logger.warning("Face normal is colinear to absolute X axis. "
184                                "Absolute Y axis will be used to determine "
185                                "local X axis.")
186             globalVecY = self.geom.MakeVectorDXDYDZ(0.0, 1.0, 0.0)
187             marker = self._buildMarkerRefVecX(center, normal, globalVecY)
188         else:
189             marker = self._buildMarkerRefVecX(center, normal, globalVecX)
190         return marker
191
192     def _buildMarkerRefVecX(self, center, normal, refVecX):
193         """
194         Create a marker using `normal` as Z axis and `refVecX` to determine
195         the X axis.
196         """
197         xPoint = self.geom.MakeTranslationVector(center, refVecX)
198         zPoint = self.geom.MakeTranslationVector(center, normal)
199         locPlaneZX = self.geom.MakePlaneThreePnt(center, zPoint, xPoint, 1.0)
200         locY = self.geom.GetNormal(locPlaneZX)
201         yPoint = self.geom.MakeTranslationVector(center, locY)
202         locPlaneYZ = self.geom.MakePlaneThreePnt(center, yPoint, zPoint, 1.0)
203         locX = self.geom.GetNormal(locPlaneYZ)
204         marker = self.geom.MakeMarkerPntTwoVec(center, locX, locY)
205         return marker
206
207     def buildMarker(self, geom, center, normal, warnings = True):
208         """
209         Create a marker with origin `center` and `normal` as Z axis. The other
210         axes are computed using the parameters alpha and beta of the
211         Orientation2D instance. `geom` is the pseudo-geompy object used to
212         build the geometric shapes. `warnings` can be used to enable or
213         disable the logging of warning messages.
214         """
215         self.geom = geom
216         marker = None
217         refVecX = None
218         if self._vect is not None:
219             # Using vector parameter
220             if abs(self._vect[0]) <= 1e-7 and abs(self._vect[1]) <= 1e-7 and \
221                                               abs(self._vect[2]) <= 1e-7:
222                 if warnings:
223                     logger.warning("Vector too small: %s, using default LCS" %
224                                    self._vect)
225             else:
226                 refVecX = self.geom.MakeVectorDXDYDZ(self._vect[0],
227                                                      self._vect[1],
228                                                      self._vect[2])
229         elif self._alpha is not None and self._beta is not None:
230             # Using alpha and beta angles
231             alphaRad = math.radians(self._alpha)
232             betaRad = math.radians(self._beta)
233             if abs(alphaRad) <= 1e-7 and abs(betaRad) <= 1e-7:
234                 if warnings:
235                     logger.warning("Angles too small: (%g, %g), using "
236                                    "default LCS" % (self._alpha, self._beta))
237             else:
238                 # rotate global CS with angles alpha and beta
239                 refVecX = self.geom.MakeVectorDXDYDZ(1.0, 0.0, 0.0)
240                 refVecY = self.geom.MakeVectorDXDYDZ(0.0, 1.0, 0.0)
241                 globalVecZ = self.geom.MakeVectorDXDYDZ(0.0, 0.0, 1.0)
242                 if abs(alphaRad) > 1e-7:
243                     refVecX = self.geom.Rotate(refVecX, globalVecZ, alphaRad)
244                     refVecY = self.geom.Rotate(refVecY, globalVecZ, alphaRad)
245                 if abs(betaRad) > 1e-7:
246                     refVecX = self.geom.Rotate(refVecX, refVecY, betaRad)
247     
248         if refVecX is not None:
249             # build local coordinate system
250             angle = self.geom.GetAngleRadians(normal, refVecX)
251             if abs(angle) < 1e-7 or abs(angle - math.pi) < 1e-7:
252                 if warnings:
253                     logger.warning("Face normal is colinear to the reference "
254                                    "X axis, using default LCS.")
255             else:
256                 marker = self._buildMarkerRefVecX(center, normal, refVecX)
257
258         if marker is None:
259             marker = self._buildDefaultMarker(center, normal, warnings)
260
261         return marker