Salome HOME
*** empty log message ***
[modules/geom.git] / src / GEOM_PY / structelem / orientation.py
1 # -*- coding: utf-8 -*-
2 #
3 #  Copyright (C) 2007-2009       EDF R&D
4
5 #    This file is part of PAL_SRC.
6 #
7 #    PAL_SRC is free software; you can redistribute it and/or modify
8 #    it under the terms of the GNU General Public License as published by
9 #    the Free Software Foundation; either version 2 of the License, or
10 #    (at your option) any later version.
11 #
12 #    PAL_SRC is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU General Public License for more details.
16 #
17 #    You should have received a copy of the GNU General Public License
18 #    along with PAL_SRC; if not, write to the Free Software
19 #    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
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("__PAL_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         first "VECT_Y" is taken into account, and the values of "ANGL_VRIL"
61         are added to obtain the total rotation angle.
62         """
63         mydict = params.copy()
64         if mydict.has_key("VECT_Y"):
65             newVecCoords = mydict.pop("VECT_Y")
66             if self._vectorYCoords is None:
67                 logger.debug("Setting orientation vector Y to %s" %
68                              str(newVecCoords))
69                 self._vectorYCoords = newVecCoords
70             else:
71                 logger.warning('Orientation parameter "VECT_Y" is specified '
72                                'several times for the same mesh group, vector'
73                                ' %s will be used' % str(self._vectorYCoords))
74         if mydict.has_key("ANGL_VRIL"):
75             newAngle = mydict.pop("ANGL_VRIL")
76             self._angle += newAngle
77             logger.debug("Adding angle %f to orientation, new angle is %f." %
78                          (newAngle, self._angle))
79         if len(mydict) > 0:
80             logger.warning("Invalid orientation parameter(s) (ignored): %s" %
81                            str(mydict))
82
83     def _buildDefaultMarker(self, center, vecX):
84         """
85         Create the default marker, that use the main direction of the 1D
86         object as the local X axis and the global Z axis to determine the
87         local Z axis.
88         """
89         xPoint = self.geom.MakeTranslationVector(center, vecX)
90         givenVecZ = self.geom.MakeVectorDXDYDZ(0.0, 0.0, 1.0)
91         angle = self.geom.GetAngleRadians(vecX, givenVecZ)
92         if abs(angle) < 1e-7 or abs(angle - math.pi) < 1e-7:
93             logger.warning("Beam X axis is colinear to absolute Z axis. "
94                            "Absolute X axis will be used to determine "
95                            "local Z axis.")
96             givenVecZ = self.geom.MakeVectorDXDYDZ(1.0, 0.0, 0.0)
97         zPoint = self.geom.MakeTranslationVector(center, givenVecZ)
98         locPlaneZX = self.geom.MakePlaneThreePnt(center, zPoint, xPoint, 1.0)
99         locY = self.geom.GetNormal(locPlaneZX)
100         marker = self.geom.MakeMarkerPntTwoVec(center,vecX,locY)
101         return marker
102
103     def buildMarker(self, geom, center, vecX):
104         """
105         Create a marker with origin `center` and X axis `vecX`. `geom` is the
106         pseudo-geompy object used to build the geometric shapes.
107         """
108         self.geom = geom
109         marker = None
110         if self._vectorYCoords is None:
111             marker = self._buildDefaultMarker(center, vecX)
112         else:
113             xPoint = self.geom.MakeTranslationVector(center, vecX)
114             givenLocY = self.geom.MakeVectorDXDYDZ(self._vectorYCoords[0],
115                                                    self._vectorYCoords[1],
116                                                    self._vectorYCoords[2])
117             angle = self.geom.GetAngleRadians(vecX, givenLocY)
118             if abs(angle) < 1e-7 or abs(angle - math.pi) < 1e-7:
119                 logger.warning("Vector Y is colinear to the beam X axis, "
120                                "using default LCS.")
121                 marker = self._buildDefaultMarker(center, vecX)
122             else:
123                 yPoint = self.geom.MakeTranslationVector(center, givenLocY)
124                 locPlaneXY = self.geom.MakePlaneThreePnt(center, xPoint,
125                                                          yPoint, 1.0)
126                 locZ = self.geom.GetNormal(locPlaneXY)
127                 zPoint = self.geom.MakeTranslationVector(center, locZ)
128                 locPlaneZX = self.geom.MakePlaneThreePnt(center, zPoint,
129                                                          xPoint, 1.0)
130                 locY = self.geom.GetNormal(locPlaneZX)
131                 marker = self.geom.MakeMarkerPntTwoVec(center,vecX,locY)
132
133         if self._angle != 0.0:
134             angleRad = math.radians(self._angle)
135             marker = self.geom.Rotate(marker, vecX, angleRad)
136
137         return marker
138
139
140 class Orientation2D:
141     """
142     This class is used to compute the orientation of 2D elements and to build
143     the corresponding markers. Angles `alpha` and `beta` are used to determine
144     the local coordinate system for the 2D element. If `vect` is not
145     :const:`None`, it is used instead of `alpha` and `beta`.
146     """
147
148     def __init__(self, alpha, beta, vect):
149         self.geom = None
150         self._alpha = alpha
151         self._beta = beta
152         self._vect = vect
153
154     def __repr__(self):
155         reprdict = self.__dict__.copy()
156         del reprdict["geom"]
157         return '%s(%s)' % (self.__class__.__name__, reprdict)
158
159     def _buildDefaultMarker(self, center, normal, warnings = True):
160         """
161         Create the default marker, that use the normal vector of the 2D object
162         as the local Z axis and the global X axis to determine the local X
163         axis. `warnings` can be used to enable or disable the logging of
164         warning messages.
165         """
166         marker = None
167         globalVecX = self.geom.MakeVectorDXDYDZ(1.0, 0.0, 0.0)
168         angle = self.geom.GetAngleRadians(normal, globalVecX)
169         if abs(angle) < 1e-7 or abs(angle - math.pi) < 1e-7:
170             if warnings:
171                 logger.warning("Face normal is colinear to absolute X axis. "
172                                "Absolute Y axis will be used to determine "
173                                "local X axis.")
174             globalVecY = self.geom.MakeVectorDXDYDZ(0.0, 1.0, 0.0)
175             marker = self._buildMarkerRefVecX(center, normal, globalVecY)
176         else:
177             marker = self._buildMarkerRefVecX(center, normal, globalVecX)
178         return marker
179
180     def _buildMarkerRefVecX(self, center, normal, refVecX):
181         """
182         Create a marker using `normal` as Z axis and `refVecX` to determine
183         the X axis.
184         """
185         xPoint = self.geom.MakeTranslationVector(center, refVecX)
186         zPoint = self.geom.MakeTranslationVector(center, normal)
187         locPlaneZX = self.geom.MakePlaneThreePnt(center, zPoint, xPoint, 1.0)
188         locY = self.geom.GetNormal(locPlaneZX)
189         yPoint = self.geom.MakeTranslationVector(center, locY)
190         locPlaneYZ = self.geom.MakePlaneThreePnt(center, yPoint, zPoint, 1.0)
191         locX = self.geom.GetNormal(locPlaneYZ)
192         marker = self.geom.MakeMarkerPntTwoVec(center, locX, locY)
193         return marker
194
195     def buildMarker(self, geom, center, normal, warnings = True):
196         """
197         Create a marker with origin `center` and `normal` as Z axis. The other
198         axes are computed using the parameters alpha and beta of the
199         Orientation2D instance. `geom` is the pseudo-geompy object used to
200         build the geometric shapes. `warnings` can be used to enable or
201         disable the logging of warning messages.
202         """
203         self.geom = geom
204         marker = None
205         refVecX = None
206         if self._vect is not None:
207             # Using vector parameter
208             if abs(self._vect[0]) <= 1e-7 and abs(self._vect[1]) <= 1e-7 and \
209                                               abs(self._vect[2]) <= 1e-7:
210                 if warnings:
211                     logger.warning("Vector too small: %s, using default LCS" %
212                                    self._vect)
213             else:
214                 refVecX = self.geom.MakeVectorDXDYDZ(self._vect[0],
215                                                      self._vect[1],
216                                                      self._vect[2])
217         elif self._alpha is not None and self._beta is not None:
218             # Using alpha and beta angles
219             alphaRad = math.radians(self._alpha)
220             betaRad = math.radians(self._beta)
221             if abs(alphaRad) <= 1e-7 and abs(betaRad) <= 1e-7:
222                 if warnings:
223                     logger.warning("Angles too small: (%g, %g), using "
224                                    "default LCS" % (self._alpha, self._beta))
225             else:
226                 # rotate global CS with angles alpha and beta
227                 refVecX = self.geom.MakeVectorDXDYDZ(1.0, 0.0, 0.0)
228                 refVecY = self.geom.MakeVectorDXDYDZ(0.0, 1.0, 0.0)
229                 globalVecZ = self.geom.MakeVectorDXDYDZ(0.0, 0.0, 1.0)
230                 if abs(alphaRad) > 1e-7:
231                     refVecX = self.geom.Rotate(refVecX, globalVecZ, alphaRad)
232                     refVecY = self.geom.Rotate(refVecY, globalVecZ, alphaRad)
233                 if abs(betaRad) > 1e-7:
234                     refVecX = self.geom.Rotate(refVecX, refVecY, betaRad)
235     
236         if refVecX is not None:
237             # build local coordinate system
238             angle = self.geom.GetAngleRadians(normal, refVecX)
239             if abs(angle) < 1e-7 or abs(angle - math.pi) < 1e-7:
240                 if warnings:
241                     logger.warning("Face normal is colinear to the reference "
242                                    "X axis, using default LCS.")
243             else:
244                 marker = self._buildMarkerRefVecX(center, normal, refVecX)
245
246         if marker is None:
247             marker = self._buildDefaultMarker(center, normal, warnings)
248
249         return marker