All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ProjectiveGT.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008-2013 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/geometry/ProjectiveGT.cpp
22 
23  \brief 2D Projective Geometric transformation.
24 */
25 
26 // TerraLib
27 #include "../common/MatrixUtils.h"
28 #include "ProjectiveGT.h"
29 
30 // STL
31 #include <cmath>
32 
33 // Boost
34 #include <boost/numeric/ublas/matrix.hpp>
35 
37 {
38 }
39 
41 {
42 }
43 
44 const std::string& te::gm::ProjectiveGT::getName() const
45 {
46  static std::string name( "Projective" );
47  return name;
48 }
49 
50 bool te::gm::ProjectiveGT::isValid( const GTParameters& params ) const
51 {
52  return ( ( params.m_directParameters.size() == 8 ) &&
53  ( params.m_inverseParameters.size() == 8 ) );
54 }
55 
56 void te::gm::ProjectiveGT::directMap( const GTParameters& params, const double& pt1X,
57  const double& pt1Y, double& pt2X, double& pt2Y ) const
58 {
59  assert( isValid( params ) );
60 
61  pt2X = (
62  ( params.m_directParameters[0] * pt1X ) +
63  ( params.m_directParameters[1] * pt1Y ) +
64  params.m_directParameters[2]
65  )
66  /
67  (
68  ( params.m_directParameters[6] * pt1X ) +
69  ( params.m_directParameters[7] * pt1Y ) +
70  1
71  );
72 
73  pt2Y = (
74  ( params.m_directParameters[3] * pt1X ) +
75  ( params.m_directParameters[4] * pt1Y ) +
76  params.m_directParameters[5]
77  )
78  /
79  (
80  ( params.m_directParameters[6] * pt1X ) +
81  ( params.m_directParameters[7] * pt1Y ) +
82  1
83  );
84 }
85 
86 void te::gm::ProjectiveGT::inverseMap( const GTParameters& params, const double& pt2X,
87  const double& pt2Y, double& pt1X, double& pt1Y ) const
88 {
89  assert( isValid( params ) );
90 
91  pt1X = (
92  ( params.m_inverseParameters[0] * pt2X ) +
93  ( params.m_inverseParameters[1] * pt2Y ) +
94  params.m_inverseParameters[2]
95  )
96  /
97  (
98  ( params.m_inverseParameters[6] * pt2X ) +
99  ( params.m_inverseParameters[7] * pt2Y ) +
100  1
101  );
102 
103  pt1Y = (
104  ( params.m_inverseParameters[3] * pt2X ) +
105  ( params.m_inverseParameters[4] * pt2Y ) +
106  params.m_inverseParameters[5]
107  )
108  /
109  (
110  ( params.m_inverseParameters[6] * pt2X ) +
111  ( params.m_inverseParameters[7] * pt2Y ) +
112  1
113  );
114 }
115 
117 {
118  return 4;
119 }
120 
122 {
123  te::gm::ProjectiveGT* newTransPtr = new ProjectiveGT;
124  newTransPtr->m_internalParameters = m_internalParameters;
125  return newTransPtr;
126 };
127 
129 {
130  /*
131  | u | = | a b c | * | x |
132  | v | | d e f | | y |
133  | 1 | | g h 1 | | 1 |
134 
135  u = a.x + b.y + c
136  -------------------
137  g.x + h.y + 1
138 
139  v = d.x + e.y + f
140  -------------------
141  g.x + h.y + 1
142 
143  Method adapted from Albertz and Kreiling (1989).
144  Reference: Albertz, J.; Kreiling, W. Photogrametriches taschenbuch.
145  Karlsruhe: Wichmann, 1989.
146  */
147 
148  const unsigned int tiepointsSize = params.m_tiePoints.size();
149  if( tiepointsSize < getMinRequiredTiePoints() ) return false;
150 
151  // Direct mapping
152  boost::numeric::ublas::matrix< double > L_DM( 2*tiepointsSize, 1 );
153  boost::numeric::ublas::matrix< double > A_DM( 2*tiepointsSize, 8 );
154 
155  //Inverse mapping
156  boost::numeric::ublas::matrix< double > L_IM( 2*tiepointsSize, 1 );
157  boost::numeric::ublas::matrix< double > A_IM( 2*tiepointsSize, 8 );
158 
159  unsigned int index1 = 0;
160  unsigned int index2 = 0;
161 
162  for ( unsigned int blockOffset = 0 ; (blockOffset < tiepointsSize) ;
163  ++blockOffset)
164  {
165  index1 = blockOffset*2;
166  index2 = index1 + 1;
167 
168  const Coord2D& x_y = params.m_tiePoints[ blockOffset ].first;
169  const Coord2D& u_v = params.m_tiePoints[ blockOffset ].second;
170 
171  L_DM( index1, 0) = u_v.x;
172  L_DM( index2, 0) = u_v.y;
173 
174  A_DM( index1, 0 ) = x_y.x ;
175  A_DM( index1, 1 ) = x_y.y ;
176  A_DM( index1, 2 ) = 1 ;
177  A_DM( index1, 3 ) = 0 ;
178  A_DM( index1, 4 ) = 0 ;
179  A_DM( index1, 5 ) = 0 ;
180  A_DM( index1, 6 ) = - x_y.x * u_v.x;
181  A_DM( index1, 7 ) = - x_y.y * u_v.x;
182 
183  A_DM( index2, 0 ) = 0;
184  A_DM( index2, 1 ) = 0;
185  A_DM( index2, 2 ) = 0;
186  A_DM( index2, 3 ) = x_y.x ;
187  A_DM( index2, 4 ) = x_y.y ;
188  A_DM( index2, 5 ) = 1 ;
189  A_DM( index2, 6 ) = - x_y.x * u_v.y;
190  A_DM( index2, 7 ) = - x_y.y * u_v.y;
191 
192  L_IM( index1, 0) = x_y.x;
193  L_IM( index2, 0) = x_y.y;
194 
195  A_IM( index1, 0 ) = u_v.x ;
196  A_IM( index1, 1 ) = u_v.y ;
197  A_IM( index1, 2 ) = 1 ;
198  A_IM( index1, 3 ) = 0 ;
199  A_IM( index1, 4 ) = 0 ;
200  A_IM( index1, 5 ) = 0 ;
201  A_IM( index1, 6 ) = - u_v.x * x_y.x;
202  A_IM( index1, 7 ) = - u_v.y * x_y.x;
203 
204  A_IM( index2, 0 ) = 0;
205  A_IM( index2, 1 ) = 0;
206  A_IM( index2, 2 ) = 0;
207  A_IM( index2, 3 ) = u_v.x ;
208  A_IM( index2, 4 ) = u_v.y ;
209  A_IM( index2, 5 ) = 1 ;
210  A_IM( index2, 6 ) = - u_v.x * x_y.y;
211  A_IM( index2, 7 ) = - u_v.y * x_y.y;
212  }
213 
214  /* At calcule */
215  boost::numeric::ublas::matrix< double > A_DM_t( boost::numeric::ublas::trans( A_DM ) ) ;
216  boost::numeric::ublas::matrix< double > A_IM_t( boost::numeric::ublas::trans( A_IM ) ) ;
217 
218  /* N calcule */
219  boost::numeric::ublas::matrix< double > N_DM( boost::numeric::ublas::prod( A_DM_t, A_DM ) );
220  boost::numeric::ublas::matrix< double > N_IM( boost::numeric::ublas::prod( A_IM_t, A_IM ) );
221 
222  /* U calcule */
223  boost::numeric::ublas::matrix< double > U_DM( boost::numeric::ublas::prod( A_DM_t, L_DM ) );
224  boost::numeric::ublas::matrix< double > U_IM( boost::numeric::ublas::prod( A_IM_t, L_IM ) );
225 
226  /* N_inv calcule */
227  boost::numeric::ublas::matrix< double > N_DM_inv;
228  boost::numeric::ublas::matrix< double > N_IM_inv;
229 
230  if ( ! te::common::getInverseMatrix( N_DM, N_DM_inv ) ) return false;
231 
232  boost::numeric::ublas::matrix< double > X_DM(
233  boost::numeric::ublas::prod( N_DM_inv, U_DM ) );
234 
235  params.m_directParameters.resize( 8 );
236  params.m_directParameters[0] = X_DM(0,0);
237  params.m_directParameters[1] = X_DM(1,0);
238  params.m_directParameters[2] = X_DM(2,0);
239  params.m_directParameters[3] = X_DM(3,0);
240  params.m_directParameters[4] = X_DM(4,0);
241  params.m_directParameters[5] = X_DM(5,0);
242  params.m_directParameters[6] = X_DM(6,0);
243  params.m_directParameters[7] = X_DM(7,0);
244 
245  if ( ! te::common::getInverseMatrix( N_IM, N_IM_inv ) ) return false;
246 
247  boost::numeric::ublas::matrix< double > X_IM(
248  boost::numeric::ublas::prod( N_IM_inv, U_IM ) );
249 
250  params.m_inverseParameters.resize( 8 );
251  params.m_inverseParameters[0] = X_IM(0,0);
252  params.m_inverseParameters[1] = X_IM(1,0);
253  params.m_inverseParameters[2] = X_IM(2,0);
254  params.m_inverseParameters[3] = X_IM(3,0);
255  params.m_inverseParameters[4] = X_IM(4,0);
256  params.m_inverseParameters[5] = X_IM(5,0);
257  params.m_inverseParameters[6] = X_IM(6,0);
258  params.m_inverseParameters[7] = X_IM(7,0);
259 
260  return true;
261 }
262 
263 
void inverseMap(const GTParameters &params, const double &pt2X, const double &pt2Y, double &pt1X, double &pt1Y) const
Inverse mapping (from pt2 space into pt1 space).
void directMap(const GTParameters &params, const double &pt1X, const double &pt1Y, double &pt2X, double &pt2Y) const
Direct mapping (from pt1 space into pt2 space).
bool computeParameters(GTParameters &params) const
Calculate the transformation parameters following the new supplied tie-points.
double y
y-coordinate.
Definition: Coord2D.h:87
const std::string & getName() const
Returns the current transformation name.
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
bool isValid() const
Tells if the current instance has a valid transformation.
std::vector< TiePoint > m_tiePoints
Tie points.
Definition: GTParameters.h:95
2D Projective Geometric transformation.
ProjectiveGT()
Default constructor.
GTParameters m_internalParameters
The current internal parameters.
std::vector< double > m_inverseParameters
Transformation numeric inverse parameters.
Definition: GTParameters.h:101
GeometricTransformation * clone() const
Creat a clone copy of this instance.
bool getInverseMatrix(const boost::numeric::ublas::matrix< T > &inputMatrix, boost::numeric::ublas::matrix< T > &outputMatrix)
Matrix inversion.
Definition: MatrixUtils.h:104
2D Geometric transformation base class.
std::vector< double > m_directParameters
Transformation numeric direct parameters.
Definition: GTParameters.h:100
~ProjectiveGT()
Destructor.
2D Geometric transformation parameters.
Definition: GTParameters.h:50
double x
x-coordinate.
Definition: Coord2D.h:86
2D Projective Geometric transformation.
Definition: ProjectiveGT.h:72
unsigned int getMinRequiredTiePoints() const
Returns the minimum number of required tie-points for the current transformation. ...