1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 // JCV 08/01/91 Modif introduction des classes Mat2d et XY dans gp
17 #define No_Standard_OutOfRange
19 #include <gp_Trsf2d.hxx>
22 #include <gp_Ax2d.hxx>
23 #include <gp_GTrsf2d.hxx>
24 #include <gp_Mat2d.hxx>
25 #include <gp_Pnt2d.hxx>
26 #include <gp_Trsf.hxx>
27 #include <gp_Vec2d.hxx>
29 #include <Standard_ConstructionError.hxx>
30 #include <Standard_OutOfRange.hxx>
32 void gp_Trsf2d::SetMirror (const gp_Ax2d& A)
36 const gp_Dir2d& V = A.Direction ();
37 const gp_Pnt2d& P = A.Location ();
38 Standard_Real VX = V.X();
39 Standard_Real VY = V.Y();
40 Standard_Real X0 = P.X();
41 Standard_Real Y0 = P.Y();
42 matrix.SetCol (1, gp_XY (1.0 - 2.0 * VX * VX, -2.0 * VX * VY));
43 matrix.SetCol (2, gp_XY (-2.0 * VX * VY, 1.0 - 2.0 * VY * VY));
45 loc.SetCoord (-2.0 * ((VX * VX - 1.0) * X0 + (VX * VY * Y0)),
46 -2.0 * ((VX * VY * X0) + (VY * VY - 1.0) * Y0));
49 void gp_Trsf2d::SetTransformation (const gp_Ax2d& FromA1,
52 shape = gp_CompoundTrsf;
54 //matrix from XOY to A2 :
55 const gp_XY& V1 = ToA2.Direction().XY();
56 gp_XY V2 (-V1.Y(), V1.X());
57 matrix.SetCol (1, V1);
58 matrix.SetCol (2, V2);
59 loc = ToA2.Location().XY();
61 loc.Multiply (matrix);
63 //matrix FromA1 to XOY
64 const gp_XY& V3 = FromA1.Direction().XY();
65 gp_XY V4 (-V3.Y(), V3.X());
66 gp_Mat2d MA1 (V3, V4);
67 gp_XY MA1loc = FromA1.Location().XY();
68 //matrix * MA1 => FromA1 ToA2
69 MA1loc.Multiply (matrix);
71 matrix.Multiply (MA1);
74 void gp_Trsf2d::SetTransformation (const gp_Ax2d& A)
76 shape = gp_CompoundTrsf;
78 const gp_XY& V1 = A.Direction().XY();
79 gp_XY V2 (-V1.Y(), V1.X());
80 matrix.SetCol (1, V1);
81 matrix.SetCol (2, V2);
82 loc = A.Location().XY();
84 loc.Multiply (matrix);
88 void gp_Trsf2d::SetTranslationPart (const gp_Vec2d& V)
91 Standard_Real X = loc.X();
93 Standard_Real Y = loc.Y();
95 if (X <= gp::Resolution() && Y <= gp::Resolution()) {
96 if (shape == gp_Identity || shape == gp_PntMirror ||
97 shape == gp_Scale || shape == gp_Rotation ||
98 shape == gp_Ax1Mirror ) { }
99 else if (shape == gp_Translation) { shape = gp_Identity; }
100 else { shape = gp_CompoundTrsf; }
103 if (shape == gp_Translation || shape == gp_Scale ||
104 shape == gp_PntMirror) { }
105 else if (shape == gp_Identity) { shape = gp_Translation; }
106 else { shape = gp_CompoundTrsf; }
110 void gp_Trsf2d::SetScaleFactor (const Standard_Real S)
113 Standard_Real X = loc.X();
115 Standard_Real Y = loc.Y();
117 if (X <= gp::Resolution() && Y <= gp::Resolution()) {
118 if (shape == gp_Identity || shape == gp_Rotation) { }
119 else if (shape == gp_Scale) { shape = gp_Identity; }
120 else if (shape == gp_PntMirror) { shape = gp_Translation; }
121 else { shape = gp_CompoundTrsf; }
124 if (shape == gp_Identity || shape == gp_Rotation ||
125 shape == gp_Scale) { }
126 else if (shape == gp_PntMirror) { shape = gp_Translation; }
127 else { shape = gp_CompoundTrsf; }
131 if (shape == gp_PntMirror || shape == gp_Ax1Mirror) { }
132 else if (shape == gp_Identity || shape == gp_Scale) {
133 shape = gp_PntMirror;
135 else { shape = gp_CompoundTrsf; }
138 if (shape == gp_Scale) { }
139 else if (shape == gp_Identity || shape == gp_Translation ||
140 shape == gp_PntMirror) { shape = gp_Scale; }
141 else { shape = gp_CompoundTrsf; }
146 gp_Mat2d gp_Trsf2d::VectorialPart () const
148 if (scale == 1.0) return matrix;
150 if (shape == gp_Scale || shape == gp_PntMirror)
151 M.SetDiagonal (matrix.Value(1,1) * scale, matrix.Value(2,2) * scale);
157 Standard_Real gp_Trsf2d::RotationPart () const
159 return ATan2 ( matrix.Value(2,1), matrix.Value(1,1) );
162 void gp_Trsf2d::Invert()
165 // X' = scale * R * X + T => X = (R / scale) * ( X' - T)
167 // Pour les gp_Trsf2d puisque le scale est extrait de la matrice R
168 // on a toujours determinant (R) = 1 et R-1 = R transposee.
169 if (shape == gp_Identity) { }
170 else if ( shape == gp_Translation || shape == gp_PntMirror) {
173 else if ( shape == gp_Scale) {
174 Standard_Real As = scale;
175 if (As < 0) As = - As;
176 Standard_ConstructionError_Raise_if (As <= gp::Resolution(), "gp_Trsf2d::Invert() - transformation has zero scale");
178 loc.Multiply (-scale);
181 Standard_Real As = scale;
182 if (As < 0) As = - As;
183 Standard_ConstructionError_Raise_if (As <= gp::Resolution(), "gp_Trsf2d::Invert() - transformation has zero scale");
186 loc.Multiply (matrix);
187 loc.Multiply (-scale);
191 void gp_Trsf2d::Multiply(const gp_Trsf2d& T)
193 if (T.shape == gp_Identity) { }
194 else if (shape == gp_Identity) {
200 else if (shape == gp_Rotation && T.shape == gp_Rotation) {
201 if (loc.X() != 0.0 || loc.Y() != 0.0) {
202 loc.Add (T.loc.Multiplied (matrix));
204 matrix.Multiply(T.matrix);
206 else if (shape == gp_Translation && T.shape == gp_Translation) {
209 else if (shape == gp_Scale && T.shape == gp_Scale) {
210 loc.Add (T.loc.Multiplied(scale));
211 scale = scale * T.scale;
213 else if (shape == gp_PntMirror && T.shape == gp_PntMirror) {
215 shape = gp_Translation;
216 loc.Add (T.loc.Reversed());
218 else if (shape == gp_Ax1Mirror && T.shape == gp_Ax1Mirror) {
221 Tloc.Multiply (matrix);
222 Tloc.Multiply (scale);
223 scale = scale * T.scale;
225 matrix.Multiply (T.matrix);
227 else if ((shape == gp_CompoundTrsf || shape == gp_Rotation ||
228 shape == gp_Ax1Mirror) && T.shape == gp_Translation) {
230 Tloc.Multiply (matrix);
231 if (scale != 1.0) Tloc.Multiply (scale);
234 else if ((shape == gp_Scale || shape == gp_PntMirror)
235 && T.shape == gp_Translation) {
237 Tloc.Multiply (scale);
240 else if (shape == gp_Translation &&
241 (T.shape == gp_CompoundTrsf ||
242 T.shape == gp_Rotation || T.shape == gp_Ax1Mirror)) {
243 shape = gp_CompoundTrsf;
248 else if (shape == gp_Translation &&
249 (T.shape == gp_Scale || T.shape == gp_PntMirror)) {
254 else if ((shape == gp_PntMirror || shape == gp_Scale) &&
255 (T.shape == gp_PntMirror || T.shape == gp_Scale)) {
256 shape = gp_CompoundTrsf;
258 Tloc.Multiply (scale);
260 scale = scale * T.scale;
262 else if ((shape == gp_CompoundTrsf || shape == gp_Rotation ||
263 shape == gp_Ax1Mirror)
264 && (T.shape == gp_Scale || T.shape == gp_PntMirror)) {
265 shape = gp_CompoundTrsf;
267 Tloc.Multiply(matrix);
268 if (scale == 1.0) scale = T.scale;
270 Tloc.Multiply (scale);
271 scale = scale * T.scale;
275 else if ((T.shape == gp_CompoundTrsf || T.shape == gp_Rotation ||
276 T.shape == gp_Ax1Mirror)
277 && (shape == gp_Scale || shape == gp_PntMirror)) {
278 shape = gp_CompoundTrsf;
280 Tloc.Multiply (scale);
281 scale = scale * T.scale;
286 shape = gp_CompoundTrsf;
288 Tloc.Multiply (matrix);
290 Tloc.Multiply (scale);
291 scale = scale * T.scale;
293 else { scale = T.scale; }
295 matrix.Multiply (T.matrix);
299 void gp_Trsf2d::Power (const Standard_Integer N)
301 if (shape == gp_Identity) { }
306 matrix.SetIdentity();
307 loc = gp_XY (0.0, 0.0);
310 else if (N == -1) Invert();
313 if (shape == gp_Translation) {
314 Standard_Integer Npower = N;
315 if (Npower < 0) Npower = - Npower;
319 if (IsOdd(Npower)) loc.Add (Temploc);
320 if (Npower == 1) break;
321 Temploc.Add (Temploc);
325 else if (shape == gp_Scale) {
326 Standard_Integer Npower = N;
327 if (Npower < 0) Npower = - Npower;
330 Standard_Real Tempscale = scale;
333 loc.Add (Temploc.Multiplied(scale));
334 scale = scale * Tempscale;
336 if (Npower == 1) break;
337 Temploc.Add (Temploc.Multiplied(Tempscale));
338 Tempscale = Tempscale * Tempscale;
342 else if (shape == gp_Rotation) {
343 Standard_Integer Npower = N;
344 if (Npower < 0) Npower = - Npower;
346 gp_Mat2d Tempmatrix (matrix);
347 if (loc.X() == 0.0 && loc.Y() == 0.0) {
349 if (IsOdd(Npower)) matrix.Multiply (Tempmatrix);
350 if (Npower == 1) break;
351 Tempmatrix.Multiply (Tempmatrix);
359 loc.Add (Temploc.Multiplied (matrix));
360 matrix.Multiply (Tempmatrix);
362 if (Npower == 1) break;
363 Temploc.Add (Temploc.Multiplied (Tempmatrix));
364 Tempmatrix.Multiply (Tempmatrix);
369 else if (shape == gp_PntMirror || shape == gp_Ax1Mirror) {
373 matrix.SetIdentity ();
374 loc.SetCoord (0.0, 0.0);
378 shape = gp_CompoundTrsf;
379 Standard_Integer Npower = N;
380 if (Npower < 0) Npower = - Npower;
382 matrix.SetDiagonal (scale*matrix.Value(1,1),
383 scale*matrix.Value(2,2));
385 Standard_Real Tempscale = scale;
386 gp_Mat2d Tempmatrix (matrix);
389 loc.Add ((Temploc.Multiplied (matrix)).Multiplied (scale));
390 scale = scale * Tempscale;
391 matrix.Multiply (Tempmatrix);
393 if (Npower == 1) break;
394 Tempscale = Tempscale * Tempscale;
395 Temploc.Add ( (Temploc.Multiplied (Tempmatrix)).Multiplied
398 Tempmatrix.Multiply (Tempmatrix);
406 void gp_Trsf2d::PreMultiply (const gp_Trsf2d& T)
408 if (T.shape == gp_Identity) { }
409 else if (shape == gp_Identity) {
415 else if (shape == gp_Rotation && T.shape == gp_Rotation) {
416 loc.Multiply (T.matrix);
418 matrix.PreMultiply(T.matrix);
420 else if (shape == gp_Translation && T.shape == gp_Translation) {
423 else if (shape == gp_Scale && T.shape == gp_Scale) {
424 loc.Multiply (T.scale);
426 scale = scale * T.scale;
428 else if (shape == gp_PntMirror && T.shape == gp_PntMirror) {
430 shape = gp_Translation;
434 else if (shape == gp_Ax1Mirror && T.shape == gp_Ax1Mirror) {
436 loc.Multiply (T.matrix);
437 loc.Multiply(T.scale);
438 scale = scale * T.scale;
440 matrix.PreMultiply(T.matrix);
442 else if ((shape == gp_CompoundTrsf || shape == gp_Rotation ||
443 shape == gp_Ax1Mirror) && T.shape == gp_Translation) {
446 else if ((shape == gp_Scale || shape == gp_PntMirror)
447 && T.shape == gp_Translation) {
450 else if (shape == gp_Translation &&
451 (T.shape == gp_CompoundTrsf ||
452 T.shape == gp_Rotation || T.shape == gp_Ax1Mirror)) {
453 shape = gp_CompoundTrsf;
455 if (T.scale == 1.0) loc.Multiply (T.matrix);
458 loc.Multiply (matrix);
459 loc.Multiply (scale);
463 else if ((T.shape == gp_Scale || T.shape == gp_PntMirror)
464 && shape == gp_Translation) {
465 loc.Multiply (T.scale);
470 else if ((shape == gp_PntMirror || shape == gp_Scale) &&
471 (T.shape == gp_PntMirror || T.shape == gp_Scale)) {
472 shape = gp_CompoundTrsf;
473 loc.Multiply (T.scale);
475 scale = scale * T.scale;
477 else if ((shape == gp_CompoundTrsf || shape == gp_Rotation ||
478 shape == gp_Ax1Mirror)
479 && (T.shape == gp_Scale || T.shape == gp_PntMirror)) {
480 shape = gp_CompoundTrsf;
481 loc.Multiply (T.scale);
483 scale = scale * T.scale;
485 else if ((T.shape == gp_CompoundTrsf || T.shape == gp_Rotation ||
486 T.shape == gp_Ax1Mirror)
487 && (shape == gp_Scale || shape == gp_PntMirror)) {
488 shape = gp_CompoundTrsf;
490 if (T.scale == 1.0) loc.Multiply (T.matrix);
492 loc.Multiply (matrix);
493 loc.Multiply (T.scale);
494 scale = T.scale * scale;
499 shape = gp_CompoundTrsf;
500 loc.Multiply (T.matrix);
501 if (T.scale != 1.0) {
502 loc.Multiply(T.scale); scale = scale * T.scale;
505 matrix.PreMultiply(T.matrix);
509 //=======================================================================
510 //function : SetValues
512 //=======================================================================
513 void gp_Trsf2d::SetValues(const Standard_Real a11,
514 const Standard_Real a12,
515 const Standard_Real a13,
516 const Standard_Real a21,
517 const Standard_Real a22,
518 const Standard_Real a23)
523 // compute the determinant
524 gp_Mat2d M(col1,col2);
525 Standard_Real s = M.Determinant();
526 Standard_Real As = s;
529 Standard_ConstructionError_Raise_if
530 (As < gp::Resolution(),"gp_Trsf2d::SetValues, null determinant");
540 shape = gp_CompoundTrsf;
549 //=======================================================================
550 //function : Orthogonalize
553 // Orthogonalization is not equivalent transformation.Therefore, transformation with
554 // source matrix and with orthogonalized matrix can lead to different results for
555 // one shape. Consequently, source matrix must be close to orthogonalized
556 // matrix for reducing these differences.
557 //=======================================================================
558 void gp_Trsf2d::Orthogonalize()
560 //See correspond comment in gp_Trsf::Orthogonalize() method in order to make this
563 gp_Mat2d aTM(matrix);
565 gp_XY aV1 = aTM.Column(1);
566 gp_XY aV2 = aTM.Column(2);
570 aV2 -= aV1*(aV2.Dot(aV1));
573 aTM.SetCols(aV1, aV2);
580 aV2 -= aV1*(aV2.Dot(aV1));
583 aTM.SetRows(aV1, aV2);