1 // Copyright (c) 1991-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #ifndef _gp_Ax2_HeaderFile
16 #define _gp_Ax2_HeaderFile
17
18 #include <gp_Ax1.hxx>
19 #include <gp_Dir.hxx>
20 #include <Precision.hxx>
21
22 class Standard_ConstructionError;
23 class gp_Pnt;
24 class gp_Trsf;
25 class gp_Vec;
26
27 //! Describes a right-handed coordinate system in 3D space.
28 //! A coordinate system is defined by:
29 //! - its origin (also referred to as its "Location point"), and
30 //! - three orthogonal unit vectors, termed respectively the
31 //! "X Direction", the "Y Direction" and the "Direction" (also
32 //! referred to as the "main Direction").
33 //! The "Direction" of the coordinate system is called its
34 //! "main Direction" because whenever this unit vector is
35 //! modified, the "X Direction" and the "Y Direction" are
36 //! recomputed. However, when we modify either the "X
37 //! Direction" or the "Y Direction", "Direction" is not modified.
38 //! The "main Direction" is also the "Z Direction".
39 //! Since an Ax2 coordinate system is right-handed, its
40 //! "main Direction" is always equal to the cross product of
41 //! its "X Direction" and "Y Direction". (To define a
42 //! left-handed coordinate system, use gp_Ax3.)
43 //! A coordinate system is used:
44 //! - to describe geometric entities, in particular to position
45 //! them. The local coordinate system of a geometric
46 //! entity serves the same purpose as the STEP function
47 //! "axis placement two axes", or
48 //! - to define geometric transformations.
49 //! Note: we refer to the "X Axis", "Y Axis" and "Z Axis",
50 //! respectively, as to axes having:
51 //! - the origin of the coordinate system as their origin, and
52 //! - the unit vectors "X Direction", "Y Direction" and "main
53 //! Direction", respectively, as their unit vectors.
54 //! The "Z Axis" is also the "main Axis".
55 class gp_Ax2
56 {
57 public:
58
59 DEFINE_STANDARD_ALLOC
60
61 //! Creates an object corresponding to the reference
62 //! coordinate system (OXYZ).
gp_Ax2()63 gp_Ax2() : vydir(0.,1.,0.)
64 // vxdir(1.,0.,0.) use default ctor of gp_Dir, as it creates the same dir(1,0,0)
65 {}
66
67 //! Creates an axis placement with an origin P such that:
68 //! - N is the Direction, and
69 //! - the "X Direction" is normal to N, in the plane
70 //! defined by the vectors (N, Vx): "X
71 //! Direction" = (N ^ Vx) ^ N,
72 //! Exception: raises ConstructionError if N and Vx are parallel (same or opposite orientation).
gp_Ax2(const gp_Pnt & P,const gp_Dir & N,const gp_Dir & Vx)73 gp_Ax2 (const gp_Pnt& P, const gp_Dir& N, const gp_Dir& Vx)
74 : axis (P, N),
75 vydir (N),
76 vxdir (N)
77 {
78 vxdir.CrossCross(Vx, N);
79 vydir.Cross(vxdir);
80 }
81
82 //! Creates - a coordinate system with an origin P, where V
83 //! gives the "main Direction" (here, "X Direction" and "Y
84 //! Direction" are defined automatically).
85 Standard_EXPORT gp_Ax2(const gp_Pnt& P, const gp_Dir& V);
86
87 //! Assigns the origin and "main Direction" of the axis A1 to
88 //! this coordinate system, then recomputes its "X Direction" and "Y Direction".
89 //! Note: The new "X Direction" is computed as follows:
90 //! new "X Direction" = V1 ^(previous "X Direction" ^ V)
91 //! where V is the "Direction" of A1.
92 //! Exceptions
93 //! Standard_ConstructionError if A1 is parallel to the "X
94 //! Direction" of this coordinate system.
95 void SetAxis (const gp_Ax1& A1);
96
97 //! Changes the "main Direction" of this coordinate system,
98 //! then recomputes its "X Direction" and "Y Direction".
99 //! Note: the new "X Direction" is computed as follows:
100 //! new "X Direction" = V ^ (previous "X Direction" ^ V)
101 //! Exceptions
102 //! Standard_ConstructionError if V is parallel to the "X
103 //! Direction" of this coordinate system.
104 void SetDirection (const gp_Dir& V);
105
106 //! Changes the "Location" point (origin) of <me>.
SetLocation(const gp_Pnt & theP)107 void SetLocation (const gp_Pnt& theP) { axis.SetLocation (theP); }
108
109 //! Changes the "Xdirection" of <me>. The main direction
110 //! "Direction" is not modified, the "Ydirection" is modified.
111 //! If <Vx> is not normal to the main direction then <XDirection>
112 //! is computed as follows XDirection = Direction ^ (Vx ^ Direction).
113 //! Exceptions
114 //! Standard_ConstructionError if Vx or Vy is parallel to
115 //! the "main Direction" of this coordinate system.
SetXDirection(const gp_Dir & theVx)116 void SetXDirection (const gp_Dir& theVx)
117 {
118 vxdir = axis.Direction().CrossCrossed (theVx, axis.Direction());
119 vydir = axis.Direction().Crossed (vxdir);
120 }
121
122 //! Changes the "Ydirection" of <me>. The main direction is not
123 //! modified but the "Xdirection" is changed.
124 //! If <Vy> is not normal to the main direction then "YDirection"
125 //! is computed as follows
126 //! YDirection = Direction ^ (<Vy> ^ Direction).
127 //! Exceptions
128 //! Standard_ConstructionError if Vx or Vy is parallel to
129 //! the "main Direction" of this coordinate system.
SetYDirection(const gp_Dir & theVy)130 void SetYDirection (const gp_Dir& theVy)
131 {
132 vxdir = theVy.Crossed (axis.Direction());
133 vydir = (axis.Direction()).Crossed (vxdir);
134 }
135
136 //! Computes the angular value, in radians, between the main direction of
137 //! <me> and the main direction of <theOther>. Returns the angle
138 //! between 0 and PI in radians.
Angle(const gp_Ax2 & theOther) const139 Standard_Real Angle (const gp_Ax2& theOther) const { return axis.Angle (theOther.axis); }
140
141 //! Returns the main axis of <me>. It is the "Location" point
142 //! and the main "Direction".
Axis() const143 const gp_Ax1& Axis() const { return axis; }
144
145 //! Returns the main direction of <me>.
Direction() const146 const gp_Dir& Direction() const { return axis.Direction(); }
147
148 //! Returns the "Location" point (origin) of <me>.
Location() const149 const gp_Pnt& Location() const { return axis.Location(); }
150
151 //! Returns the "XDirection" of <me>.
XDirection() const152 const gp_Dir& XDirection() const { return vxdir; }
153
154 //! Returns the "YDirection" of <me>.
YDirection() const155 const gp_Dir& YDirection() const { return vydir; }
156
157 Standard_Boolean IsCoplanar (const gp_Ax2& Other, const Standard_Real LinearTolerance, const Standard_Real AngularTolerance) const;
158
159 //! Returns True if
160 //! . the distance between <me> and the "Location" point of A1
161 //! is lower of equal to LinearTolerance and
162 //! . the main direction of <me> and the direction of A1 are normal.
163 //! Note: the tolerance criterion for angular equality is given by AngularTolerance.
164 Standard_Boolean IsCoplanar (const gp_Ax1& A1, const Standard_Real LinearTolerance, const Standard_Real AngularTolerance) const;
165
166 //! Performs a symmetrical transformation of this coordinate
167 //! system with respect to:
168 //! - the point P, and assigns the result to this coordinate system.
169 //! Warning
170 //! This transformation is always performed on the origin.
171 //! In case of a reflection with respect to a point:
172 //! - the main direction of the coordinate system is not changed, and
173 //! - the "X Direction" and the "Y Direction" are simply reversed
174 //! In case of a reflection with respect to an axis or a plane:
175 //! - the transformation is applied to the "X Direction"
176 //! and the "Y Direction", then
177 //! - the "main Direction" is recomputed as the cross
178 //! product "X Direction" ^ "Y Direction".
179 //! This maintains the right-handed property of the
180 //! coordinate system.
181 Standard_EXPORT void Mirror (const gp_Pnt& P);
182
183 //! Performs a symmetrical transformation of this coordinate
184 //! system with respect to:
185 //! - the point P, and creates a new one.
186 //! Warning
187 //! This transformation is always performed on the origin.
188 //! In case of a reflection with respect to a point:
189 //! - the main direction of the coordinate system is not changed, and
190 //! - the "X Direction" and the "Y Direction" are simply reversed
191 //! In case of a reflection with respect to an axis or a plane:
192 //! - the transformation is applied to the "X Direction"
193 //! and the "Y Direction", then
194 //! - the "main Direction" is recomputed as the cross
195 //! product "X Direction" ^ "Y Direction".
196 //! This maintains the right-handed property of the
197 //! coordinate system.
198 Standard_NODISCARD Standard_EXPORT gp_Ax2 Mirrored (const gp_Pnt& P) const;
199
200 //! Performs a symmetrical transformation of this coordinate
201 //! system with respect to:
202 //! - the axis A1, and assigns the result to this coordinate systeme.
203 //! Warning
204 //! This transformation is always performed on the origin.
205 //! In case of a reflection with respect to a point:
206 //! - the main direction of the coordinate system is not changed, and
207 //! - the "X Direction" and the "Y Direction" are simply reversed
208 //! In case of a reflection with respect to an axis or a plane:
209 //! - the transformation is applied to the "X Direction"
210 //! and the "Y Direction", then
211 //! - the "main Direction" is recomputed as the cross
212 //! product "X Direction" ^ "Y Direction".
213 //! This maintains the right-handed property of the
214 //! coordinate system.
215 Standard_EXPORT void Mirror (const gp_Ax1& A1);
216
217 //! Performs a symmetrical transformation of this coordinate
218 //! system with respect to:
219 //! - the axis A1, and creates a new one.
220 //! Warning
221 //! This transformation is always performed on the origin.
222 //! In case of a reflection with respect to a point:
223 //! - the main direction of the coordinate system is not changed, and
224 //! - the "X Direction" and the "Y Direction" are simply reversed
225 //! In case of a reflection with respect to an axis or a plane:
226 //! - the transformation is applied to the "X Direction"
227 //! and the "Y Direction", then
228 //! - the "main Direction" is recomputed as the cross
229 //! product "X Direction" ^ "Y Direction".
230 //! This maintains the right-handed property of the
231 //! coordinate system.
232 Standard_NODISCARD Standard_EXPORT gp_Ax2 Mirrored (const gp_Ax1& A1) const;
233
234 //! Performs a symmetrical transformation of this coordinate
235 //! system with respect to:
236 //! - the plane defined by the origin, "X Direction" and "Y
237 //! Direction" of coordinate system A2 and assigns the result to this coordinate systeme.
238 //! Warning
239 //! This transformation is always performed on the origin.
240 //! In case of a reflection with respect to a point:
241 //! - the main direction of the coordinate system is not changed, and
242 //! - the "X Direction" and the "Y Direction" are simply reversed
243 //! In case of a reflection with respect to an axis or a plane:
244 //! - the transformation is applied to the "X Direction"
245 //! and the "Y Direction", then
246 //! - the "main Direction" is recomputed as the cross
247 //! product "X Direction" ^ "Y Direction".
248 //! This maintains the right-handed property of the
249 //! coordinate system.
250 Standard_EXPORT void Mirror (const gp_Ax2& A2);
251
252 //! Performs a symmetrical transformation of this coordinate
253 //! system with respect to:
254 //! - the plane defined by the origin, "X Direction" and "Y
255 //! Direction" of coordinate system A2 and creates a new one.
256 //! Warning
257 //! This transformation is always performed on the origin.
258 //! In case of a reflection with respect to a point:
259 //! - the main direction of the coordinate system is not changed, and
260 //! - the "X Direction" and the "Y Direction" are simply reversed
261 //! In case of a reflection with respect to an axis or a plane:
262 //! - the transformation is applied to the "X Direction"
263 //! and the "Y Direction", then
264 //! - the "main Direction" is recomputed as the cross
265 //! product "X Direction" ^ "Y Direction".
266 //! This maintains the right-handed property of the
267 //! coordinate system.
268 Standard_NODISCARD Standard_EXPORT gp_Ax2 Mirrored (const gp_Ax2& A2) const;
269
Rotate(const gp_Ax1 & theA1,const Standard_Real theAng)270 void Rotate (const gp_Ax1& theA1, const Standard_Real theAng)
271 {
272 gp_Pnt aTemp = axis.Location();
273 aTemp.Rotate (theA1, theAng);
274 axis.SetLocation (aTemp);
275 vxdir.Rotate (theA1, theAng);
276 vydir.Rotate (theA1, theAng);
277 axis.SetDirection (vxdir.Crossed (vydir));
278 }
279
280 //! Rotates an axis placement. <theA1> is the axis of the rotation.
281 //! theAng is the angular value of the rotation in radians.
Rotated(const gp_Ax1 & theA1,const Standard_Real theAng) const282 Standard_NODISCARD gp_Ax2 Rotated (const gp_Ax1& theA1, const Standard_Real theAng) const
283 {
284 gp_Ax2 aTemp = *this;
285 aTemp.Rotate (theA1, theAng);
286 return aTemp;
287 }
288
Scale(const gp_Pnt & theP,const Standard_Real theS)289 void Scale (const gp_Pnt& theP, const Standard_Real theS)
290 {
291 gp_Pnt aTemp = axis.Location();
292 aTemp.Scale (theP, theS);
293 axis.SetLocation (aTemp);
294 if (theS < 0.0)
295 {
296 vxdir.Reverse();
297 vydir.Reverse();
298 }
299 }
300
301 //! Applies a scaling transformation on the axis placement.
302 //! The "Location" point of the axisplacement is modified.
303 //! Warnings :
304 //! If the scale <S> is negative :
305 //! . the main direction of the axis placement is not changed.
306 //! . The "XDirection" and the "YDirection" are reversed.
307 //! So the axis placement stay right handed.
Scaled(const gp_Pnt & theP,const Standard_Real theS) const308 Standard_NODISCARD gp_Ax2 Scaled (const gp_Pnt& theP, const Standard_Real theS) const
309 {
310 gp_Ax2 aTemp = *this;
311 aTemp.Scale (theP, theS);
312 return aTemp;
313 }
314
Transform(const gp_Trsf & theT)315 void Transform (const gp_Trsf& theT)
316 {
317 gp_Pnt aTemp = axis.Location();
318 aTemp.Transform (theT);
319 axis.SetLocation (aTemp);
320 vxdir.Transform (theT);
321 vydir.Transform (theT);
322 axis.SetDirection (vxdir.Crossed (vydir));
323 }
324
325 //! Transforms an axis placement with a Trsf.
326 //! The "Location" point, the "XDirection" and the "YDirection" are transformed with theT.
327 //! The resulting main "Direction" of <me> is the cross product between
328 //! the "XDirection" and the "YDirection" after transformation.
Transformed(const gp_Trsf & theT) const329 Standard_NODISCARD gp_Ax2 Transformed (const gp_Trsf& theT) const
330 {
331 gp_Ax2 aTemp = *this;
332 aTemp.Transform (theT);
333 return aTemp;
334 }
335
Translate(const gp_Vec & theV)336 void Translate (const gp_Vec& theV) { axis.Translate (theV); }
337
338 //! Translates an axis plaxement in the direction of the vector <theV>.
339 //! The magnitude of the translation is the vector's magnitude.
Translated(const gp_Vec & theV) const340 Standard_NODISCARD gp_Ax2 Translated (const gp_Vec& theV) const
341 {
342 gp_Ax2 aTemp = *this;
343 aTemp.Translate (theV);
344 return aTemp;
345 }
346
Translate(const gp_Pnt & theP1,const gp_Pnt & theP2)347 void Translate (const gp_Pnt& theP1, const gp_Pnt& theP2) { axis.Translate (theP1, theP2); }
348
349 //! Translates an axis placement from the point <theP1> to the point <theP2>.
Translated(const gp_Pnt & theP1,const gp_Pnt & theP2) const350 Standard_NODISCARD gp_Ax2 Translated (const gp_Pnt& theP1, const gp_Pnt& theP2) const
351 {
352 gp_Ax2 aTemp = *this;
353 aTemp.Translate (theP1, theP2);
354 return aTemp;
355 }
356
357 //! Dumps the content of me into the stream
358 Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
359
360 //! Inits the content of me from the stream
361 Standard_EXPORT Standard_Boolean InitFromJson (const Standard_SStream& theSStream, Standard_Integer& theStreamPos);
362
363 private:
364
365 gp_Ax1 axis;
366 gp_Dir vydir;
367 gp_Dir vxdir;
368
369 };
370
371 // =======================================================================
372 // function : SetAxis
373 // purpose :
374 // =======================================================================
SetAxis(const gp_Ax1 & theA1)375 inline void gp_Ax2::SetAxis (const gp_Ax1& theA1)
376 {
377 Standard_Real a = theA1.Direction() * vxdir;
378 if (Abs(Abs(a) - 1.) <= Precision::Angular())
379 {
380 if (a > 0.)
381 {
382 vxdir = vydir;
383 vydir = axis.Direction();
384 axis = theA1;
385 }
386 else
387 {
388 vxdir = axis.Direction();
389 axis = theA1;
390 }
391 }
392 else
393 {
394 axis = theA1;
395 vxdir = axis.Direction().CrossCrossed (vxdir, axis.Direction());
396 vydir = axis.Direction().Crossed (vxdir);
397 }
398 }
399
400 // =======================================================================
401 // function : SetDirection
402 // purpose :
403 // =======================================================================
SetDirection(const gp_Dir & theV)404 inline void gp_Ax2::SetDirection (const gp_Dir& theV)
405 {
406 Standard_Real a = theV * vxdir;
407 if (Abs(Abs(a) - 1.) <= Precision::Angular())
408 {
409 if(a > 0.)
410 {
411 vxdir = vydir;
412 vydir = axis.Direction();
413 axis.SetDirection (theV);
414 }
415 else
416 {
417 vxdir = axis.Direction();
418 axis.SetDirection (theV);
419 }
420 }
421 else
422 {
423 axis.SetDirection (theV);
424 vxdir = theV.CrossCrossed (vxdir, theV);
425 vydir = theV.Crossed (vxdir);
426 }
427 }
428
429 // =======================================================================
430 // function : IsCoplanar
431 // purpose :
432 // =======================================================================
IsCoplanar(const gp_Ax2 & theOther,const Standard_Real theLinearTolerance,const Standard_Real theAngularTolerance) const433 inline Standard_Boolean gp_Ax2::IsCoplanar (const gp_Ax2& theOther,
434 const Standard_Real theLinearTolerance,
435 const Standard_Real theAngularTolerance) const
436 {
437 const gp_Dir& DD = axis.Direction();
438 const gp_Pnt& PP = axis.Location();
439 const gp_Pnt& OP = theOther.axis.Location();
440 Standard_Real D1 = (DD.X() * (OP.X() - PP.X())
441 + DD.Y() * (OP.Y() - PP.Y())
442 + DD.Z() * (OP.Z() - PP.Z()));
443 if (D1 < 0)
444 {
445 D1 = -D1;
446 }
447 return D1 <= theLinearTolerance
448 && axis.IsParallel (theOther.axis, theAngularTolerance);
449 }
450
451 // =======================================================================
452 // function : IsCoplanar
453 // purpose :
454 // =======================================================================
IsCoplanar(const gp_Ax1 & theA,const Standard_Real theLinearTolerance,const Standard_Real theAngularTolerance) const455 inline Standard_Boolean gp_Ax2::IsCoplanar (const gp_Ax1& theA,
456 const Standard_Real theLinearTolerance,
457 const Standard_Real theAngularTolerance) const
458 {
459 const gp_Dir& DD = axis.Direction();
460 const gp_Pnt& PP = axis.Location();
461 const gp_Pnt& AP = theA.Location();
462 Standard_Real D1 = (DD.X() * (AP.X() - PP.X()) +
463 DD.Y() * (AP.Y() - PP.Y()) +
464 DD.Z() * (AP.Z() - PP.Z()));
465 if (D1 < 0)
466 {
467 D1 = -D1;
468 }
469 return D1 <= theLinearTolerance
470 && axis.IsNormal (theA, theAngularTolerance);
471 }
472
473 #endif // _gp_Ax2_HeaderFile
474