295a770115181ff93f9d74b74b3df8e0c3a7adb8
[occt.git] / src / RWMesh / RWMesh_CoordinateSystemConverter.hxx
1 // Author: Kirill Gavrilov
2 // Copyright: Open CASCADE 2015-2019
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 _RWMesh_CoordinateSystemConverter_HeaderFile
16 #define _RWMesh_CoordinateSystemConverter_HeaderFile
17
18 #include <RWMesh_CoordinateSystem.hxx>
19
20 #include <gp.hxx>
21 #include <gp_Ax3.hxx>
22 #include <gp_XYZ.hxx>
23 #include <gp_Trsf.hxx>
24 #include <Graphic3d_Mat4.hxx>
25 #include <Graphic3d_Vec.hxx>
26
27 //! Coordinate system converter defining the following tools:
28 //! - Initialization for commonly used coordinate systems Z-up and Y-up.
29 //! - Perform length unit conversion (scaling).
30 //! - Conversion of three basic elements:
31 //!   a) mesh node Positions,
32 //!   b) mesh node Normals,
33 //!   c) model nodes Transformations (locations).
34 //!
35 //! RWMesh_CoordinateSystem enumeration is used for convenient conversion between two commonly
36 //! used coordinate systems, to make sure that imported model is oriented up.
37 //! But gp_Ax3 can be used instead for defining a conversion between arbitrary systems (e.g. including non-zero origin).
38 //!
39 //! The converter requires defining explicitly both input and output systems,
40 //! so that if either input or output is undefined, then conversion will be skipped.
41 //! Length units conversion and coordinate system conversion are decomposed,
42 //! so that application might specify no length units conversion but Y-up to Z-up coordinate system conversion.
43 //!
44 //! Class defines dedicated methods for parameters of input and output systems.
45 //! This allows passing tool through several initialization steps,
46 //! so that a reader can initialize input length units (only if file format defines such information),
47 //! while application specifies output length units, and conversion will be done only when both defined.
48 class RWMesh_CoordinateSystemConverter
49 {
50 public:
51
52   //! Return a standard coordinate system definition.
53   static gp_Ax3 StandardCoordinateSystem (RWMesh_CoordinateSystem theSys)
54   {
55     switch (theSys)
56     {
57       case RWMesh_CoordinateSystem_posYfwd_posZup: return gp_Ax3 (gp::Origin(), gp::DZ(), gp::DX());
58       case RWMesh_CoordinateSystem_negZfwd_posYup: return gp_Ax3 (gp::Origin(), gp::DY(), gp::DX());
59       case RWMesh_CoordinateSystem_Undefined: break;
60     }
61     return gp_Ax3();
62   }
63
64 public:
65
66   //! Empty constructor.
67   Standard_EXPORT RWMesh_CoordinateSystemConverter();
68
69   //! Return TRUE if there is no transformation (target and current coordinates systems are same).
70   Standard_Boolean IsEmpty() const { return myIsEmpty; }
71
72   //! Return source length units, defined as scale factor to m (meters).
73   //! -1.0 by default, which means that NO conversion will be applied (regardless output length unit).
74   Standard_Real InputLengthUnit() const { return myInputLengthUnit; }
75
76   //! Set source length units as scale factor to m (meters).
77   void SetInputLengthUnit (Standard_Real theInputScale)
78   {
79     Init (myInputAx3, theInputScale, myOutputAx3, myOutputLengthUnit);
80   }
81
82   //! Return destination length units, defined as scale factor to m (meters).
83   //! -1.0 by default, which means that NO conversion will be applied (regardless input length unit).
84   Standard_Real OutputLengthUnit() const { return myOutputLengthUnit; }
85
86   //! Set destination length units as scale factor to m (meters).
87   void SetOutputLengthUnit (Standard_Real theOutputScale)
88   {
89     Init (myInputAx3, myInputLengthUnit, myOutputAx3, theOutputScale);
90   }
91
92   //! Return TRUE if source coordinate system has been set; FALSE by default.
93   Standard_Boolean HasInputCoordinateSystem() const { return myHasInputAx3; }
94
95   //! Source coordinate system; UNDEFINED by default.
96   const gp_Ax3& InputCoordinateSystem() const { return myInputAx3; }
97
98   //! Set source coordinate system.
99   void SetInputCoordinateSystem (const gp_Ax3& theSysFrom)
100   {
101     myHasInputAx3 = Standard_True;
102     Init (theSysFrom, myInputLengthUnit, myOutputAx3, myOutputLengthUnit);
103   }
104
105   //! Set source coordinate system.
106   void SetInputCoordinateSystem (RWMesh_CoordinateSystem theSysFrom)
107   {
108     myHasInputAx3 = theSysFrom != RWMesh_CoordinateSystem_Undefined;
109     Init (StandardCoordinateSystem (theSysFrom), myInputLengthUnit, myOutputAx3, myOutputLengthUnit);
110   }
111
112   //! Return TRUE if destination coordinate system has been set; FALSE by default.
113   Standard_Boolean HasOutputCoordinateSystem() const { return myHasOutputAx3; }
114
115   //! Destination coordinate system; UNDEFINED by default.
116   const gp_Ax3& OutputCoordinateSystem() const { return myOutputAx3; }
117
118   //! Set destination coordinate system.
119   void SetOutputCoordinateSystem (const gp_Ax3& theSysTo)
120   {
121     myHasOutputAx3 = Standard_True;
122     Init (myInputAx3, myInputLengthUnit, theSysTo, myOutputLengthUnit);
123   }
124
125   //! Set destination coordinate system.
126   void SetOutputCoordinateSystem (RWMesh_CoordinateSystem theSysTo)
127   {
128     myHasOutputAx3 = theSysTo != RWMesh_CoordinateSystem_Undefined;
129     Init (myInputAx3, myInputLengthUnit, StandardCoordinateSystem (theSysTo), myOutputLengthUnit);
130   }
131
132   //! Initialize transformation.
133   Standard_EXPORT void Init (const gp_Ax3& theInputSystem,
134                              Standard_Real theInputLengthUnit,
135                              const gp_Ax3& theOutputSystem,
136                              Standard_Real theOutputLengthUnit);
137
138 public:
139
140   //! Transform transformation.
141   void TransformTransformation (gp_Trsf& theTrsf) const
142   {
143     if (myHasScale)
144     {
145       gp_XYZ aTransPart = theTrsf.TranslationPart();
146       aTransPart *= myUnitFactor;
147       theTrsf.SetTranslationPart (aTransPart);
148     }
149     if (myTrsf.Form() != gp_Identity)
150     {
151       theTrsf = myTrsf * theTrsf * myTrsfInv;
152     }
153   }
154
155   //! Transform position.
156   void TransformPosition (gp_XYZ& thePos) const
157   {
158     if (myHasScale)
159     {
160       thePos *= myUnitFactor;
161     }
162     if (myTrsf.Form() != gp_Identity)
163     {
164       myTrsf.Transforms (thePos);
165     }
166   }
167
168   //! Transform normal (e.g. exclude translation/scale part of transformation).
169   void TransformNormal (Graphic3d_Vec3& theNorm) const
170   {
171     if (myTrsf.Form() != gp_Identity)
172     {
173       const Graphic3d_Vec4 aNorm = myNormTrsf * Graphic3d_Vec4 (theNorm, 0.0f);
174       theNorm = aNorm.xyz();
175     }
176   }
177
178 private:
179
180   gp_Ax3           myInputAx3;         //!< source      coordinate system
181   gp_Ax3           myOutputAx3;        //!< destination coordinate system
182   Standard_Real    myInputLengthUnit;  //!< source      length units, defined as scale factor to m (meters); -1.0 by default which means UNDEFINED
183   Standard_Real    myOutputLengthUnit; //!< destination length units, defined as scale factor to m (meters); -1.0 by default which means UNDEFINED
184   Standard_Boolean myHasInputAx3;      //!< flag indicating if source coordinate system is defined or not
185   Standard_Boolean myHasOutputAx3;     //!< flag indicating if destination coordinate system is defined or not
186
187   gp_Trsf          myTrsf;             //!< transformation from input Ax3 to output Ax3
188   gp_Trsf          myTrsfInv;          //!< inversed transformation from input Ax3 to output Ax3
189   Graphic3d_Mat4   myNormTrsf;         //!< transformation 4x4 matrix from input Ax3 to output Ax3
190   Standard_Real    myUnitFactor;       //!< unit scale factor
191   Standard_Boolean myHasScale;         //!< flag indicating that length unit transformation should be performed
192   Standard_Boolean myIsEmpty;          //!< flag indicating that transformation is empty
193
194 };
195
196 #endif // _RWMesh_CoordinateSystemConverter_HeaderFile