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>
31 void gp_Trsf2d::SetMirror (const gp_Ax2d& A)
35 const gp_Dir2d& V = A.Direction ();
36 const gp_Pnt2d& P = A.Location ();
37 Standard_Real VX = V.X();
38 Standard_Real VY = V.Y();
39 Standard_Real X0 = P.X();
40 Standard_Real Y0 = P.Y();
41 matrix.SetCol (1, gp_XY (1.0 - 2.0 * VX * VX, -2.0 * VX * VY));
42 matrix.SetCol (2, gp_XY (-2.0 * VX * VY, 1.0 - 2.0 * VY * VY));
44 loc.SetCoord (-2.0 * ((VX * VX - 1.0) * X0 + (VX * VY * Y0)),
45 -2.0 * ((VX * VY * X0) + (VY * VY - 1.0) * Y0));
48 void gp_Trsf2d::SetTransformation (const gp_Ax2d& FromA1,
51 shape = gp_CompoundTrsf;
53 //matrix from XOY to A2 :
54 const gp_XY& V1 = ToA2.Direction().XY();
55 gp_XY V2 (-V1.Y(), V1.X());
56 matrix.SetCol (1, V1);
57 matrix.SetCol (2, V2);
58 loc = ToA2.Location().XY();
60 loc.Multiply (matrix);
62 //matrix FromA1 to XOY
63 const gp_XY& V3 = FromA1.Direction().XY();
64 gp_XY V4 (-V3.Y(), V3.X());
65 gp_Mat2d MA1 (V3, V4);
66 gp_XY MA1loc = FromA1.Location().XY();
67 //matrix * MA1 => FromA1 ToA2
68 MA1loc.Multiply (matrix);
70 matrix.Multiply (MA1);
73 void gp_Trsf2d::SetTransformation (const gp_Ax2d& A)
75 shape = gp_CompoundTrsf;
77 const gp_XY& V1 = A.Direction().XY();
78 gp_XY V2 (-V1.Y(), V1.X());
79 matrix.SetCol (1, V1);
80 matrix.SetCol (2, V2);
81 loc = A.Location().XY();
83 loc.Multiply (matrix);
87 void gp_Trsf2d::SetTranslationPart (const gp_Vec2d& V)
90 Standard_Real X = loc.X();
92 Standard_Real Y = loc.Y();
94 if (X <= gp::Resolution() && Y <= gp::Resolution()) {
95 if (shape == gp_Identity || shape == gp_PntMirror ||
96 shape == gp_Scale || shape == gp_Rotation ||
97 shape == gp_Ax1Mirror ) { }
98 else if (shape == gp_Translation) { shape = gp_Identity; }
99 else { shape = gp_CompoundTrsf; }
102 if (shape == gp_Translation || shape == gp_Scale ||
103 shape == gp_PntMirror) { }
104 else if (shape == gp_Identity) { shape = gp_Translation; }
105 else { shape = gp_CompoundTrsf; }
109 void gp_Trsf2d::SetScaleFactor (const Standard_Real S)
112 Standard_Real X = loc.X();
114 Standard_Real Y = loc.Y();
116 if (X <= gp::Resolution() && Y <= gp::Resolution()) {
117 if (shape == gp_Identity || shape == gp_Rotation) { }
118 else if (shape == gp_Scale) { shape = gp_Identity; }
119 else if (shape == gp_PntMirror) { shape = gp_Translation; }
120 else { shape = gp_CompoundTrsf; }
123 if (shape == gp_Identity || shape == gp_Rotation ||
124 shape == gp_Scale) { }
125 else if (shape == gp_PntMirror) { shape = gp_Translation; }
126 else { shape = gp_CompoundTrsf; }
130 if (shape == gp_PntMirror || shape == gp_Ax1Mirror) { }
131 else if (shape == gp_Identity || shape == gp_Scale) {
132 shape = gp_PntMirror;
134 else { shape = gp_CompoundTrsf; }
137 if (shape == gp_Scale) { }
138 else if (shape == gp_Identity || shape == gp_Translation ||
139 shape == gp_PntMirror) { shape = gp_Scale; }
140 else { shape = gp_CompoundTrsf; }
145 gp_Mat2d gp_Trsf2d::VectorialPart () const
147 if (scale == 1.0) return matrix;
149 if (shape == gp_Scale || shape == gp_PntMirror)
150 M.SetDiagonal (matrix.Value(1,1) * scale, matrix.Value(2,2) * scale);
156 Standard_Real gp_Trsf2d::RotationPart () const
158 return ATan2 ( matrix.Value(2,1), matrix.Value(1,1) );
161 void gp_Trsf2d::Invert()
164 // X' = scale * R * X + T => X = (R / scale) * ( X' - T)
166 // Pour les gp_Trsf2d puisque le scale est extrait de la matrice R
167 // on a toujours determinant (R) = 1 et R-1 = R transposee.
168 if (shape == gp_Identity) { }
169 else if ( shape == gp_Translation || shape == gp_PntMirror) {
172 else if ( shape == gp_Scale) {
173 Standard_Real As = scale;
174 if (As < 0) As = - As;
175 Standard_ConstructionError_Raise_if (As <= gp::Resolution(), "gp_Trsf2d::Invert() - transformation has zero scale");
177 loc.Multiply (-scale);
180 Standard_Real As = scale;
181 if (As < 0) As = - As;
182 Standard_ConstructionError_Raise_if (As <= gp::Resolution(), "gp_Trsf2d::Invert() - transformation has zero scale");
185 loc.Multiply (matrix);
186 loc.Multiply (-scale);
190 void gp_Trsf2d::Multiply(const gp_Trsf2d& T)
192 if (T.shape == gp_Identity) { }
193 else if (shape == gp_Identity) {
199 else if (shape == gp_Rotation && T.shape == gp_Rotation) {
200 if (loc.X() != 0.0 || loc.Y() != 0.0) {
201 loc.Add (T.loc.Multiplied (matrix));
203 matrix.Multiply(T.matrix);
205 else if (shape == gp_Translation && T.shape == gp_Translation) {
208 else if (shape == gp_Scale && T.shape == gp_Scale) {
209 loc.Add (T.loc.Multiplied(scale));
210 scale = scale * T.scale;
212 else if (shape == gp_PntMirror && T.shape == gp_PntMirror) {
214 shape = gp_Translation;
215 loc.Add (T.loc.Reversed());
217 else if (shape == gp_Ax1Mirror && T.shape == gp_Ax1Mirror) {
220 Tloc.Multiply (matrix);
221 Tloc.Multiply (scale);
222 scale = scale * T.scale;
224 matrix.Multiply (T.matrix);
226 else if ((shape == gp_CompoundTrsf || shape == gp_Rotation ||
227 shape == gp_Ax1Mirror) && T.shape == gp_Translation) {
229 Tloc.Multiply (matrix);
230 if (scale != 1.0) Tloc.Multiply (scale);
233 else if ((shape == gp_Scale || shape == gp_PntMirror)
234 && T.shape == gp_Translation) {
236 Tloc.Multiply (scale);
239 else if (shape == gp_Translation &&
240 (T.shape == gp_CompoundTrsf ||
241 T.shape == gp_Rotation || T.shape == gp_Ax1Mirror)) {
242 shape = gp_CompoundTrsf;
247 else if (shape == gp_Translation &&
248 (T.shape == gp_Scale || T.shape == gp_PntMirror)) {
253 else if ((shape == gp_PntMirror || shape == gp_Scale) &&
254 (T.shape == gp_PntMirror || T.shape == gp_Scale)) {
255 shape = gp_CompoundTrsf;
257 Tloc.Multiply (scale);
259 scale = scale * T.scale;
261 else if ((shape == gp_CompoundTrsf || shape == gp_Rotation ||
262 shape == gp_Ax1Mirror)
263 && (T.shape == gp_Scale || T.shape == gp_PntMirror)) {
264 shape = gp_CompoundTrsf;
266 Tloc.Multiply(matrix);
267 if (scale == 1.0) scale = T.scale;
269 Tloc.Multiply (scale);
270 scale = scale * T.scale;
274 else if ((T.shape == gp_CompoundTrsf || T.shape == gp_Rotation ||
275 T.shape == gp_Ax1Mirror)
276 && (shape == gp_Scale || shape == gp_PntMirror)) {
277 shape = gp_CompoundTrsf;
279 Tloc.Multiply (scale);
280 scale = scale * T.scale;
285 shape = gp_CompoundTrsf;
287 Tloc.Multiply (matrix);
289 Tloc.Multiply (scale);
290 scale = scale * T.scale;
292 else { scale = T.scale; }
294 matrix.Multiply (T.matrix);
298 void gp_Trsf2d::Power (const Standard_Integer N)
300 if (shape == gp_Identity) { }
305 matrix.SetIdentity();
306 loc = gp_XY (0.0, 0.0);
309 else if (N == -1) Invert();
312 if (shape == gp_Translation) {
313 Standard_Integer Npower = N;
314 if (Npower < 0) Npower = - Npower;
318 if (IsOdd(Npower)) loc.Add (Temploc);
319 if (Npower == 1) break;
320 Temploc.Add (Temploc);
324 else if (shape == gp_Scale) {
325 Standard_Integer Npower = N;
326 if (Npower < 0) Npower = - Npower;
329 Standard_Real Tempscale = scale;
332 loc.Add (Temploc.Multiplied(scale));
333 scale = scale * Tempscale;
335 if (Npower == 1) break;
336 Temploc.Add (Temploc.Multiplied(Tempscale));
337 Tempscale = Tempscale * Tempscale;
341 else if (shape == gp_Rotation) {
342 Standard_Integer Npower = N;
343 if (Npower < 0) Npower = - Npower;
345 gp_Mat2d Tempmatrix (matrix);
346 if (loc.X() == 0.0 && loc.Y() == 0.0) {
348 if (IsOdd(Npower)) matrix.Multiply (Tempmatrix);
349 if (Npower == 1) break;
350 Tempmatrix.Multiply (Tempmatrix);
358 loc.Add (Temploc.Multiplied (matrix));
359 matrix.Multiply (Tempmatrix);
361 if (Npower == 1) break;
362 Temploc.Add (Temploc.Multiplied (Tempmatrix));
363 Tempmatrix.Multiply (Tempmatrix);
368 else if (shape == gp_PntMirror || shape == gp_Ax1Mirror) {
372 matrix.SetIdentity ();
373 loc.SetCoord (0.0, 0.0);
377 shape = gp_CompoundTrsf;
378 Standard_Integer Npower = N;
379 if (Npower < 0) Npower = - Npower;
381 matrix.SetDiagonal (scale*matrix.Value(1,1),
382 scale*matrix.Value(2,2));
384 Standard_Real Tempscale = scale;
385 gp_Mat2d Tempmatrix (matrix);
388 loc.Add ((Temploc.Multiplied (matrix)).Multiplied (scale));
389 scale = scale * Tempscale;
390 matrix.Multiply (Tempmatrix);
392 if (Npower == 1) break;
393 Tempscale = Tempscale * Tempscale;
394 Temploc.Add ( (Temploc.Multiplied (Tempmatrix)).Multiplied
397 Tempmatrix.Multiply (Tempmatrix);
405 void gp_Trsf2d::PreMultiply (const gp_Trsf2d& T)
407 if (T.shape == gp_Identity) { }
408 else if (shape == gp_Identity) {
414 else if (shape == gp_Rotation && T.shape == gp_Rotation) {
415 loc.Multiply (T.matrix);
417 matrix.PreMultiply(T.matrix);
419 else if (shape == gp_Translation && T.shape == gp_Translation) {
422 else if (shape == gp_Scale && T.shape == gp_Scale) {
423 loc.Multiply (T.scale);
425 scale = scale * T.scale;
427 else if (shape == gp_PntMirror && T.shape == gp_PntMirror) {
429 shape = gp_Translation;
433 else if (shape == gp_Ax1Mirror && T.shape == gp_Ax1Mirror) {
435 loc.Multiply (T.matrix);
436 loc.Multiply(T.scale);
437 scale = scale * T.scale;
439 matrix.PreMultiply(T.matrix);
441 else if ((shape == gp_CompoundTrsf || shape == gp_Rotation ||
442 shape == gp_Ax1Mirror) && T.shape == gp_Translation) {
445 else if ((shape == gp_Scale || shape == gp_PntMirror)
446 && T.shape == gp_Translation) {
449 else if (shape == gp_Translation &&
450 (T.shape == gp_CompoundTrsf ||
451 T.shape == gp_Rotation || T.shape == gp_Ax1Mirror)) {
452 shape = gp_CompoundTrsf;
454 if (T.scale == 1.0) loc.Multiply (T.matrix);
457 loc.Multiply (matrix);
458 loc.Multiply (scale);
462 else if ((T.shape == gp_Scale || T.shape == gp_PntMirror)
463 && shape == gp_Translation) {
464 loc.Multiply (T.scale);
469 else if ((shape == gp_PntMirror || shape == gp_Scale) &&
470 (T.shape == gp_PntMirror || T.shape == gp_Scale)) {
471 shape = gp_CompoundTrsf;
472 loc.Multiply (T.scale);
474 scale = scale * T.scale;
476 else if ((shape == gp_CompoundTrsf || shape == gp_Rotation ||
477 shape == gp_Ax1Mirror)
478 && (T.shape == gp_Scale || T.shape == gp_PntMirror)) {
479 shape = gp_CompoundTrsf;
480 loc.Multiply (T.scale);
482 scale = scale * T.scale;
484 else if ((T.shape == gp_CompoundTrsf || T.shape == gp_Rotation ||
485 T.shape == gp_Ax1Mirror)
486 && (shape == gp_Scale || shape == gp_PntMirror)) {
487 shape = gp_CompoundTrsf;
489 if (T.scale == 1.0) loc.Multiply (T.matrix);
491 loc.Multiply (matrix);
492 loc.Multiply (T.scale);
493 scale = T.scale * scale;
498 shape = gp_CompoundTrsf;
499 loc.Multiply (T.matrix);
500 if (T.scale != 1.0) {
501 loc.Multiply(T.scale); scale = scale * T.scale;
504 matrix.PreMultiply(T.matrix);
508 //=======================================================================
509 //function : SetValues
511 //=======================================================================
512 void gp_Trsf2d::SetValues(const Standard_Real a11,
513 const Standard_Real a12,
514 const Standard_Real a13,
515 const Standard_Real a21,
516 const Standard_Real a22,
517 const Standard_Real a23)
522 // compute the determinant
523 gp_Mat2d M(col1,col2);
524 Standard_Real s = M.Determinant();
525 Standard_Real As = s;
528 Standard_ConstructionError_Raise_if
529 (As < gp::Resolution(),"gp_Trsf2d::SetValues, null determinant");
539 shape = gp_CompoundTrsf;
548 //=======================================================================
549 //function : Orthogonalize
552 // Orthogonalization is not equivalent transformation.Therefore, transformation with
553 // source matrix and with orthogonalized matrix can lead to different results for
554 // one shape. Consequently, source matrix must be close to orthogonalized
555 // matrix for reducing these differences.
556 //=======================================================================
557 void gp_Trsf2d::Orthogonalize()
559 //See correspond comment in gp_Trsf::Orthogonalize() method in order to make this
562 gp_Mat2d aTM(matrix);
564 gp_XY aV1 = aTM.Column(1);
565 gp_XY aV2 = aTM.Column(2);
569 aV2 -= aV1*(aV2.Dot(aV1));
572 aTM.SetCols(aV1, aV2);
579 aV2 -= aV1*(aV2.Dot(aV1));
582 aTM.SetRows(aV1, aV2);