]> Creatis software - gdcm.git/blob - src/gdcmOrientation.cxx
ENH: Moving Orientation stuff into its own class. gdcm::File is already too complicat...
[gdcm.git] / src / gdcmOrientation.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmOrientation.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/07/24 02:34:42 $
7   Version:   $Revision: 1.1 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18
19 #include "gdcmOrientation.h"
20 #include "gdcmFile.h"
21
22 namespace gdcm 
23 {
24 //--------------------------------------------------------------------
25 //  THERALYS Algorithm to determine the most similar basic orientation
26 //
27 //  Transliterated from original Python code.
28 //  Kept as close as possible to the original code
29 //  in order to speed up any further modif of Python code :-(
30 //-----------------------------------------------------------------------
31
32 /**
33  * \brief  THERALYS' Algorithm to determine the most similar basic orientation
34  *           (Axial, Coronal, Sagital) of the image
35  * \note Should be run on the first gdcm::File of a 'coherent' Serie
36  * @return orientation code
37  * @return orientation code
38  *   #   0 :   Not Applicable (neither 0020,0037 Image Orientation Patient 
39  *   #                         nor     0020,0032Image Position     found )
40  *   #   1 :   Axial
41  *   #  -1 :   Axial invert
42  *   #   2 :   Coronal
43  *   #  -2 :   Coronal invert
44  *   #   3 :   Sagital
45  *   #  -3 :   Sagital invert
46  *   #   4 :   Heart Axial
47  *   #  -4 :   Heart Axial invert
48  *   #   5 :   Heart Coronal
49  *   #  -5 :   Heart Coronal invert
50  *   #   6 :   Heart Sagital
51  *   #  -6 :   Heart Sagital invert
52  */
53 double Orientation::TypeOrientation( File *f )
54 {
55    float iop[6];
56    bool succ = f->GetImageOrientationPatient( iop );
57    if ( !succ )
58    {
59       return 0.;
60    }
61
62    vector3D ori1;
63    vector3D ori2;
64
65    ori1.x = iop[0]; ori1.y = iop[1]; ori1.z = iop[2]; 
66    ori1.x = iop[3]; ori2.y = iop[4]; ori2.z = iop[5];
67
68    // two perpendicular vectors describe one plane
69    double dicPlane[6][2][3] =
70    { {  {1,    0,    0   },{0,       1,     0     }  },       // Axial
71      {  {1,    0,    0   },{0,       0,    -1     }  },       // Coronal
72      {  {0,    1,    0   },{0,       0,    -1     }  },       // Sagittal
73      {  { 0.8, 0.5,  0.0 },{-0.1,    0.1 , -0.95  }  },       // Axial - HEART
74      {  { 0.8, 0.5,  0.0 },{-0.6674, 0.687, 0.1794}  },       // Coronal - HEART
75      {  {-0.1, 0.1, -0.95},{-0.6674, 0.687, 0.1794}  }        // Sagittal - HEART
76    };
77
78    vector3D refA;
79    vector3D refB;
80    int i = 0;
81    Res res;   // [ <result> , <memory of the last succes calcule> ]
82    res.first = 0;
83    res.second = 99999;
84    for (int numDicPlane=0; numDicPlane<6; numDicPlane++)
85    {
86        ++i;
87        // refA=plane[0]
88        refA.x = dicPlane[numDicPlane][0][0]; 
89        refA.y = dicPlane[numDicPlane][0][1]; 
90        refA.z = dicPlane[numDicPlane][0][2];
91        // refB=plane[1]
92        refB.x = dicPlane[numDicPlane][1][0]; 
93        refB.y = dicPlane[numDicPlane][1][1]; 
94        refB.z = dicPlane[numDicPlane][1][2];
95        res=VerfCriterion(  i, CalculLikelyhood2Vec(refA,refB,ori1,ori2), res );
96        res=VerfCriterion( -i, CalculLikelyhood2Vec(refB,refA,ori1,ori2), res );
97    }
98    return res.first;
99 /*
100 //             i=0
101 //             res=[0,99999]  ## [ <result> , <memory of the last succes calculus> ]
102 //             for plane in dicPlane:
103 //                 i=i+1
104 //                 refA=plane[0]
105 //                 refB=plane[1]
106 //                 res=self.VerfCriterion(  i , self.CalculLikelyhood2Vec(refA,refB,ori1,ori2) , res )
107 //                 res=self.VerfCriterion( -i , self.CalculLikelyhood2Vec(refB,refA,ori1,ori2) , res )
108 //             return res[0]
109 */
110
111 }
112
113 Res 
114 Orientation::VerfCriterion(int typeCriterion, double criterionNew, Res const & in)
115 {
116    Res res;
117    double criterion = in.second;
118    if (criterionNew < criterion)
119    {
120       res.first  = criterionNew;
121       res.second = typeCriterion;
122    }
123 /*
124 //   type = res[0]
125 //   criterion = res[1]
126 // #     if criterionNew<0.1 and criterionNew<criterion:
127 //   if criterionNew<criterion:
128 //      criterion=criterionNew
129 //      type=typeCriterion
130 //   return [ type , criterion ]
131 */
132    return res;
133
134
135 inline double square_dist(vector3D const &v1, vector3D const & v2)
136 {
137   double res;
138   res = (v1.x - v2.x)*(v1.x - v2.x) +
139         (v1.y - v2.y)*(v1.y - v2.y) +
140         (v1.z - v2.z)*(v1.z - v2.z);
141   return res;
142 }
143
144 //------------------------- Purpose : -----------------------------------
145 //- This function determines the orientation similarity of two planes.
146 //  Each plane is described by two vectors.
147 //------------------------- Parameters : --------------------------------
148 //- <refA>  : - type : vector 3D (double)
149 //- <refB>  : - type : vector 3D (double)
150 //            - Description of the first plane
151 //- <ori1>  : - type : vector 3D (double)
152 //- <ori2>  : - type : vector 3D (double)
153 //            - Description of the second plane
154 //------------------------- Return : ------------------------------------
155 // double :   0 if the planes are perpendicular. While the difference of
156 //            the orientation between the planes are big more enlarge is
157 //            the criterion.
158 //------------------------- Other : -------------------------------------
159 // The calculus is based with vectors normalice
160 double
161 Orientation::CalculLikelyhood2Vec(vector3D const & refA, vector3D const & refB, 
162                            vector3D const & ori1, vector3D const & ori2 )
163 {
164
165    vector3D ori3 = ProductVectorial(ori1,ori2);
166    vector3D refC = ProductVectorial(refA,refB);
167    double res = square_dist(refC, ori3);
168
169    return sqrt(res);
170 }
171
172 //------------------------- Purpose : -----------------------------------
173 //- Calculus of the poduct vectorial between two vectors 3D
174 //------------------------- Parameters : --------------------------------
175 //- <vec1>  : - type : vector 3D (double)
176 //- <vec2>  : - type : vector 3D (double)
177 //------------------------- Return : ------------------------------------
178 // (vec) :    - Vector 3D
179 //------------------------- Other : -------------------------------------
180 vector3D
181 Orientation::ProductVectorial(vector3D const & vec1, vector3D const & vec2)
182 {
183    vector3D vec3;
184    vec3.x =    vec1.y*vec2.z - vec1.z*vec2.y;
185    vec3.y = -( vec1.x*vec2.z - vec1.z*vec2.x);
186    vec3.z =    vec1.x*vec2.y - vec1.y*vec2.x;
187
188    return vec3;
189 }
190
191 } // end namespace gdcm
192