USGS

Isis 3.0 Object Programmers' Reference

Home

PointPerspective.cpp
Go to the documentation of this file.
1 
23 #include "PointPerspective.h"
24 
25 #include <cmath>
26 #include <cfloat>
27 
28 #include "Constants.h"
29 #include "IException.h"
30 #include "TProjection.h"
31 #include "Pvl.h"
32 #include "PvlGroup.h"
33 #include "PvlKeyword.h"
34 
35 using namespace std;
36 namespace Isis {
53  PointPerspective::PointPerspective(Pvl &label, bool allowDefaults) :
54  TProjection::TProjection(label) {
55  try {
56  // Try to read the mapping group
57  PvlGroup &mapGroup = label.findGroup("Mapping", Pvl::Traverse);
58 
59  // Compute and write the default center longitude if allowed and
60  // necessary
61  if ((allowDefaults) && (!mapGroup.hasKeyword("CenterLongitude"))) {
62  double lon = (m_minimumLongitude + m_maximumLongitude) / 2.0;
63  mapGroup += PvlKeyword("CenterLongitude", toString(lon));
64  }
65 
66  // Compute and write the default center latitude if allowed and
67  // necessary
68  if ((allowDefaults) && (!mapGroup.hasKeyword("CenterLatitude"))) {
69  double lat = (m_minimumLatitude + m_maximumLatitude) / 2.0;
70  mapGroup += PvlKeyword("CenterLatitude", toString(lat));
71  }
72 
73  // Get the center longitude & latitude
74  m_centerLongitude = mapGroup["CenterLongitude"];
75  m_centerLatitude = mapGroup["CenterLatitude"];
76  if (IsPlanetocentric()) {
78  }
79 
80  // convert to radians, adjust for longitude direction
81  m_centerLongitude *= PI / 180.0;
82  m_centerLatitude *= PI / 180.0;
84 
85  // Calculate sine & cosine of center latitude
88 
89  // Get the distance above planet center (the point of perspective from
90  // the center of planet), and calculate P
91  m_distance = mapGroup["Distance"];
92  m_distance *= 1000.;
93  m_P = 1.0 + (m_distance / m_equatorialRadius);
94 
95  }
96  catch(IException &e) {
97  QString message = "Invalid label group [Mapping]";
98  throw IException(e, IException::Io, message, _FILEINFO_);
99  }
100  }
101 
104  }
105 
115  if (!Projection::operator==(proj)) return false;
116  // dont do the below it is a recusive plunge
117  // if (Projection::operator!=(proj)) return false;
118  PointPerspective *point = (PointPerspective *) &proj;
119  if((point->m_centerLongitude != this->m_centerLongitude) ||
120  (point->m_centerLatitude != this->m_centerLatitude) ||
121  (point->m_distance != this->m_distance)) return false;
122  return true;
123  }
124 
130  QString PointPerspective::Name() const {
131  return "PointPerspective";
132  }
133 
139  QString PointPerspective::Version() const {
140  return "1.0";
141  }
142 
150  return m_centerLatitude * 180.0 / PI;
151  }
152 
165  bool PointPerspective::SetGround(const double lat, const double lon) {
166  // Convert longitude to radians & clean up
167  m_longitude = lon;
168  double lonRadians = lon * PI / 180.0;
169  if (m_longitudeDirection == PositiveWest) lonRadians *= -1.0;
170 
171  // Now convert latitude to radians & clean up ... it must be planetographic
172  m_latitude = lat;
173  double latRadians = lat;
174  if (IsPlanetocentric()) latRadians = ToPlanetographic(latRadians);
175  latRadians *= PI / 180.0;
176 
177  // Compute helper variables
178  double deltaLon = (lonRadians - m_centerLongitude);
179  double sinphi = sin(latRadians);
180  double cosphi = cos(latRadians);
181  double coslon = cos(deltaLon);
182 
183  // Lat/Lon cannot be projected
184  double g = m_sinph0 * sinphi + m_cosph0 * cosphi * coslon;
185  if (g < (1.0 / m_P)) {
186  m_good = false;
187  return m_good;
188  }
189 
190  // Compute the coordinates
191  double ksp = (m_P - 1.0) / (m_P - g);
192  double x = m_equatorialRadius * ksp * cosphi * sin(deltaLon);
193  double y = m_equatorialRadius * ksp *
194  (m_cosph0 * sinphi - m_sinph0 * cosphi * coslon);
195  SetComputedXY(x, y);
196  m_good = true;
197  return m_good;
198  }
199 
213  bool PointPerspective::SetCoordinate(const double x, const double y) {
214  // Save the coordinate
215  SetXY(x, y);
216 
217  // Declare instance variables and calculate rho
218  double rho, rp, con, com, z, sinz, cosz;
219  const double epsilon = 1.0e-10;
220  rho = sqrt(GetX() * GetX() + GetY() * GetY());
221  rp = rho / m_equatorialRadius;
222  con = m_P - 1.0;
223  com = m_P + 1.0;
224 
225  // Error calculating rho - should be less than equatorial radius
226  if (rp > (sqrt(con / com))) {
227  m_good = false;
228  return m_good;
229  }
230 
231  // Calculate the latitude and longitude
233  if (fabs(rho) <= epsilon) {
235  }
236  else {
237  if (rp <= epsilon) {
238  sinz = 0.0;
239  }
240  else {
241  sinz = (m_P - sqrt(1.0 - rp * rp * com / con)) / (con / rp + rp / con);
242  }
243  z = asin(sinz);
244  sinz = sin(z);
245  cosz = cos(z);
246  con = cosz * m_sinph0 + GetY() * sinz * m_cosph0 / rho;
247  if (con > 1.0) con = 1.0;
248  if (con < -1.0) con = -1.0;
249  m_latitude = asin(con);
250 
251  con = fabs(m_centerLatitude) - HALFPI;
252  if (fabs(con) <= epsilon) {
253  if (m_centerLatitude >= 0.0) {
254  m_longitude += atan2(GetX(), -GetY());
255  }
256  else {
257  m_longitude += atan2(-GetX(), GetY());
258  }
259  }
260  else {
261  con = cosz - m_sinph0 * sin(m_latitude);
262  if ((fabs(con) >= epsilon) || (fabs(GetX()) >= epsilon)) {
263  m_longitude += atan2(GetX() * sinz * m_cosph0, con * rho);
264  }
265  }
266  }
267 
268  // Convert to degrees
269  m_latitude *= 180.0 / PI;
270  m_longitude *= 180.0 / PI;
271 
272  // Cleanup the longitude
274  // These need to be done for circular type projections
277 
278  // Cleanup the latitude
280 
281  m_good = true;
282  return m_good;
283  }
284 
308  bool PointPerspective::XYRange(double &minX, double &maxX, double &minY, double &maxY) {
309  double lat, lon;
310 
311  // Check the corners of the lat/lon range
316 
317  // Walk top and bottom edges
318  for (lat = m_minimumLatitude; lat <= m_maximumLatitude; lat += 0.01) {
319  lat = lat;
320  lon = m_minimumLongitude;
321  XYRangeCheck(lat, lon);
322 
323  lat = lat;
324  lon = m_maximumLongitude;
325  XYRangeCheck(lat, lon);
326  }
327 
328  // Walk left and right edges
329  for (lon = m_minimumLongitude; lon <= m_maximumLongitude; lon += 0.01) {
330  lat = m_minimumLatitude;
331  lon = lon;
332  XYRangeCheck(lat, lon);
333 
334  lat = m_maximumLatitude;
335  lon = lon;
336  XYRangeCheck(lat, lon);
337  }
338 
339  // Walk the limb
340  for (double angle = 0.0; angle <= 360.0; angle += 0.01) {
341  double x = m_equatorialRadius * cos(angle * PI / 180.0);
342  double y = m_equatorialRadius * sin(angle * PI / 180.0);
343  if (SetCoordinate(x, y) == 0) {
344  if (m_latitude > m_maximumLatitude) continue;
345  if (m_longitude > m_maximumLongitude) continue;
346  if (m_latitude < m_minimumLatitude) continue;
347  if (m_longitude < m_minimumLongitude) continue;
349  }
350  }
351 
352  // Make sure everything is ordered
353  if (m_minimumX >= m_maximumX) return false;
354  if (m_minimumY >= m_maximumY) return false;
355 
356  // Return X/Y min/maxs
357  minX = m_minimumX;
358  maxX = m_maximumX;
359  minY = m_minimumY;
360  maxY = m_maximumY;
361  return true;
362  }
363 
364 
371  PvlGroup mapping = TProjection::Mapping();
372 
373  mapping += m_mappingGrp["CenterLatitude"];
374  mapping += m_mappingGrp["CenterLongitude"];
375  mapping += m_mappingGrp["Distance"];
376 
377  return mapping;
378  }
379 
387 
388  mapping += m_mappingGrp["CenterLatitude"];
389 
390  return mapping;
391  }
392 
400 
401  mapping += m_mappingGrp["CenterLongitude"];
402 
403  return mapping;
404  }
405 } // end namespace isis
406 
417  bool allowDefaults) {
418  return new Isis::PointPerspective(lab, allowDefaults);
419 }
420