1 //*******************************************************************
2 //
3 // License:  See top level LICENSE.txt file.
4 //
5 // DESCRIPTION:
6 //  This class maintains the relationship between a local space rectangular
7 //  (LSR) coordinate system and the earth-centered, earth-fixed (ECEF) system.
8 //
9 // SOFTWARE HISTORY:
10 //
11 //   09Aug2001  Oscar Kramer (okramer@imagelinks.com)
12 //              Initial coding.
13 //
14 //*****************************************************************************
15 //  $Id: ossimLsrSpace.cpp 17593 2010-06-17 19:07:26Z dburken $
16 
17 #include <ossim/base/ossimLsrSpace.h>
18 #include <ossim/base/ossimCommon.h>
19 #include <ossim/base/ossimGpt.h>
20 #include <ossim/base/ossimColumnVector3d.h>
21 #include <ossim/base/ossimEcefVector.h>
22 
23 using namespace std;
24 
25 
26 //*****************************************************************************
27 //  CONSTRUCTOR: ossimLsrSpace(origin, x_dir, y_dir, int)
28 //
29 //  Constructs the space given origin, and X and Y ECEF directions. The int
30 //  argument is a place holder only and not used.
31 //
32 //*****************************************************************************
ossimLsrSpace(const ossimEcefPoint & origin,const ossimEcefVector & x_dir_ecf_vec,const ossimEcefVector & y_dir_ecf_vec,int)33 ossimLsrSpace::ossimLsrSpace(const ossimEcefPoint&  origin,
34                              const ossimEcefVector& x_dir_ecf_vec,
35                              const ossimEcefVector& y_dir_ecf_vec,
36                              int   /* z_not_provided_space_holder */)
37    : theOrigin (origin)
38 {
39    //***
40    // Compute the remaining axis given first two:
41    //***
42    ossimColumnVector3d xdir (x_dir_ecf_vec.data().unit());
43    ossimColumnVector3d ydir (y_dir_ecf_vec.data().unit());
44    ossimColumnVector3d zdir (xdir.cross(ydir));
45 
46    //***
47    // Fill the rotation matrix:
48    //***
49    theLsrToEcefRotMatrix = ossimMatrix3x3::create(xdir[0], ydir[0], zdir[0],
50                                                   xdir[1], ydir[1], zdir[1],
51                                                   xdir[2], ydir[2], zdir[2]);
52 }
53 
54 //*****************************************************************************
55 //  CONSTRUCTOR: ossimLsrSpace
56 //
57 //  Constructs the space given origin, and X and Z ECEF directions. The int
58 //  argument is a place holder only and not used.
59 //
60 //*****************************************************************************
ossimLsrSpace(const ossimEcefPoint & origin,const ossimEcefVector & x_dir_ecf_vec,int,const ossimEcefVector & z_dir_ecf_vec)61 ossimLsrSpace::ossimLsrSpace(const ossimEcefPoint&  origin,
62                              const ossimEcefVector& x_dir_ecf_vec,
63                              int   /* y_not_provided_space_holder */,
64                              const ossimEcefVector& z_dir_ecf_vec)
65    : theOrigin (origin)
66 {
67    //***
68    // Compute the remaining axis given first two:
69    //***
70    ossimColumnVector3d xdir (x_dir_ecf_vec.data().unit());
71    ossimColumnVector3d zdir (z_dir_ecf_vec.data().unit());
72    ossimColumnVector3d ydir (zdir.cross(xdir));
73 
74    //***
75    // Fill the rotation matrix:
76    //***
77    theLsrToEcefRotMatrix = ossimMatrix3x3::create(xdir[0], ydir[0], zdir[0],
78                                                   xdir[1], ydir[1], zdir[1],
79                                                   xdir[2], ydir[2], zdir[2]);
80 }
81 
82 //*****************************************************************************
83 //  CONSTRUCTOR: ossimLsrSpace
84 //
85 //  Constructs the space given origin, and Y and Z ECEF directions. The int
86 //  argument is a place holder only and not used.
87 //
88 //*****************************************************************************
ossimLsrSpace(const ossimEcefPoint & origin,int,const ossimEcefVector & y_dir_ecf_vec,const ossimEcefVector & z_dir_ecf_vec)89 ossimLsrSpace::ossimLsrSpace(const ossimEcefPoint&  origin,
90                              int   /* x_not_provided_space_holder */,
91                              const ossimEcefVector& y_dir_ecf_vec,
92                              const ossimEcefVector& z_dir_ecf_vec)
93    : theOrigin (origin)
94 {
95    //***
96    // Compute the remaining axis given first two:
97    //***
98    ossimColumnVector3d ydir (y_dir_ecf_vec.data().unit());
99    ossimColumnVector3d zdir (z_dir_ecf_vec.data().unit());
100    ossimColumnVector3d xdir (ydir.cross(zdir));
101 
102    //***
103    // Fill the rotation matrix:
104    //***
105    theLsrToEcefRotMatrix = ossimMatrix3x3::create(xdir[0], ydir[0], zdir[0],
106                                                   xdir[1], ydir[1], zdir[1],
107                                                   xdir[2], ydir[2], zdir[2]);
108 }
109 
110 //*****************************************************************************
111 //  CONSTRUCTORS: ossimLsrSpace(ossimGpt, y_azimuth)
112 //
113 //  This constructor sets up a local coordinate system centered at the
114 //  specified groundpoint, with the Z-axis normal to the ellipsoid and the
115 //  Y-axis rotated clockwise from north by the y_azimuth. This angle defaults
116 //  to 0, producing an East-North-Up system.
117 //
118 //*****************************************************************************
ossimLsrSpace(const ossimGpt & origin,const double & y_azimuth)119 ossimLsrSpace::ossimLsrSpace(const ossimGpt& origin,
120                              const double&   y_azimuth)
121 {
122    //***
123    // Convert ground point origin to ECEF coordinates:
124    //***
125    theOrigin = ossimEcefPoint(origin);
126 
127    //***
128    // Establish the component vectors for ENU system::
129    //***
130    double sin_lat = ossim::sind(origin.lat);
131    double cos_lat = ossim::cosd(origin.lat);
132    double sin_lon = ossim::sind(origin.lon);
133    double cos_lon = ossim::cosd(origin.lon);
134 
135    ossimColumnVector3d E (-sin_lon,
136                           cos_lon,
137                           0.0);
138    ossimColumnVector3d N (-sin_lat*cos_lon,
139                           -sin_lat*sin_lon,
140                           cos_lat);
141    ossimColumnVector3d U (E.cross(N));
142 
143    //
144    // Fill rotation matrix with these components, rotated about the Z axis
145    // by the azimuth indicated:
146    //
147    if (std::abs(y_azimuth) > FLT_EPSILON)
148    {
149       double cos_azim = ossim::cosd(y_azimuth);
150       double sin_azim = ossim::sind(y_azimuth);
151       ossimColumnVector3d X (cos_azim*E - sin_azim*N);
152       ossimColumnVector3d Y (sin_azim*E + cos_azim*N);
153       ossimColumnVector3d Z (X.cross(Y));
154 
155       theLsrToEcefRotMatrix
156          = ossimMatrix3x3::create(X[0], Y[0], Z[0],
157                                   X[1], Y[1], Z[1],
158                                   X[2], Y[2], Z[2]);
159    }
160    else
161    {
162       //***
163       // No azimuth rotation, so simplify:
164       //***
165       theLsrToEcefRotMatrix = ossimMatrix3x3::create(E[0], N[0], U[0],
166                                                      E[1], N[1], U[1],
167                                                      E[2], N[2], U[2]);
168    }
169 }
170 
171 //*****************************************************************************
172 //  OPERATOR: ==
173 //*****************************************************************************
operator ==(const ossimLsrSpace & that) const174 bool ossimLsrSpace::operator == (const ossimLsrSpace& that) const
175 {
176    if (theOrigin != that.origin())
177       return false;
178 
179    if (theLsrToEcefRotMatrix != that.theLsrToEcefRotMatrix)
180       return false;
181 
182    return true;
183 }
184 
185 //*****************************************************************************
186 //  OPERATOR: =
187 //*****************************************************************************
operator =(const ossimLsrSpace & space)188 const ossimLsrSpace& ossimLsrSpace::operator = (const ossimLsrSpace& space)
189 {
190    theOrigin = space.theOrigin;
191    theLsrToEcefRotMatrix = space.theLsrToEcefRotMatrix;
192    return *this;
193 }
194 
195 //*****************************************************************************
196 //  STATIC METHOD: lsrSpaceErrorMessage()
197 //
198 //  Convenience method accessible to all owners of an ossimLsrSpace for
199 //  displaying an error message when LSR spaces do not match between
200 //  objects. All operations between LSR objects must be in a common space.
201 //
202 //*****************************************************************************
lsrSpaceErrorMessage(ostream & os)203 ostream& ossimLsrSpace::lsrSpaceErrorMessage(ostream& os)
204 {
205    os<<"ossimLsrSpace ERROR: An operation was attempted between two LSR \n"
206      <<"  objects with differing LSR spaces. This is an illegal condition.\n"
207      <<"  Please check the data and/or report the error to OSSIM development."
208      << std::endl;
209 
210    return os;
211 }
212 
213 //*****************************************************************************
214 //  METHOD: print()
215 //
216 //  Dumps contents to stream for debug purposes. Defaults to cout.
217 //
218 //*****************************************************************************
print(ostream & stream) const219 void ossimLsrSpace::print(ostream& stream) const
220 {
221    stream << "(ossimLsrSpace)"
222           << "\n   theOrigin = " << theOrigin
223           << "\n   theLsrToEcefRotMatrix = \n" << theLsrToEcefRotMatrix << std::endl;
224 }
225 
226