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