Isis 3 Programmer Reference
UniversalGroundMap.cpp
1 #include "UniversalGroundMap.h"
2 
3 #include <QPointF>
4 
5 #include "Camera.h"
6 #include "CameraFactory.h"
7 #include "ImagePolygon.h"
8 #include "Latitude.h"
9 #include "Longitude.h"
10 #include "Latitude.h"
11 #include "Longitude.h"
12 #include "PolygonTools.h"
13 #include "Projection.h"
14 #include "RingPlaneProjection.h"
15 #include "TProjection.h"
16 #include "ProjectionFactory.h"
17 #include "SurfacePoint.h"
18 #include "Target.h"
19 
20 namespace Isis {
28  p_camera = NULL;
29  p_projection = NULL;
30 
31  Pvl &pvl = *cube.label();
32  try {
33  if(priority == CameraFirst)
35  else
37  }
38  catch (IException &firstError) {
39  p_camera = NULL;
40  p_projection = NULL;
41 
42  try {
43  if(priority == CameraFirst)
45  else
47  }
48  catch (IException &secondError) {
49  p_projection = NULL;
50  QString msg = "Could not create camera or projection for [" +
51  cube.fileName() + "]";
52  IException realError(IException::Unknown, msg, _FILEINFO_);
53  realError.append(firstError);
54  realError.append(secondError);
55  throw realError;
56  }
57  }
58  }
59 
66  void UniversalGroundMap::SetBand(const int band) {
67  if (p_camera != NULL)
68  p_camera->SetBand(band);
69  }
70 
71 
72 
75  if (p_camera != NULL) {
76  delete p_camera;
77  p_camera = NULL;
78  }
79 
80  if (p_projection != NULL) {
81  delete p_projection;
82  p_projection = NULL;
83  }
84  }
85 
96  bool UniversalGroundMap::SetUniversalGround(double lat, double lon) {
97  if (p_camera != NULL) {
98  if (p_camera->SetUniversalGround(lat, lon)) { // This should work for rings (radius,azimuth)
99  return p_camera->InCube();
100  }
101  else {
102  return false;
103  }
104  }
105  else {
106  return p_projection->SetUniversalGround(lat, lon); // This should work for rings (radius,azimuth)
107  }
108  }
109 
110 
122  if(p_camera != NULL) {
123  if(p_camera->SetGround(lat, lon)) { // This should work for rings (radius,azimuth)
124  return p_camera->InCube();
125  }
126  else {
127  return false;
128  }
129  }
130  else {
131  double universalLat = lat.degrees();
132  double universalLon = lon.degrees();
133  return p_projection->SetUniversalGround(universalLat, universalLon); // This should work for rings (radius,azimuth)
134  }
135  }
136 
137 
149  if(p_camera != NULL) {
150  if(p_camera->SetGround(lat, lon)) { // This should work for rings (radius,azimuth)
151  return p_camera->InCube();
152  }
153  else {
154  return false;
155  }
156  }
157  else {
158  double universalLat = lat.degrees();
159  double universalLon = lon.degrees();
160  return p_projection->SetUnboundUniversalGround(universalLat, universalLon);
161  }
162  }
163 
164 
175  if (p_camera != NULL) {
176  if (p_camera->SetGround(sp)) {
177  return p_camera->InCube();
178  }
179  else {
180  return false;
181  }
182  }
183  else {
185  sp.GetLongitude().degrees()); // This should work for rings (radius,azimuth)
186  }
187  }
188 
194  double UniversalGroundMap::Sample() const {
195  if (p_camera != NULL) {
196  return p_camera->Sample();
197  }
198  else {
199  return p_projection->WorldX();
200  }
201  }
202 
208  double UniversalGroundMap::Line() const {
209  if (p_camera != NULL) {
210  return p_camera->Line();
211  }
212  else {
213  return p_projection->WorldY();
214  }
215  }
216 
227  bool UniversalGroundMap::SetImage(double sample, double line) {
228  if (p_camera != NULL) {
229  return p_camera->SetImage(sample, line);
230  }
231  else {
232  return p_projection->SetWorld(sample, line);
233  }
234  }
235 
242  if (p_camera != NULL) {
243  return p_camera->UniversalLatitude();
244  }
245  else {
246  // Is this a triaxial projection or ring projection. If ring return Radius as latitude
248  if (projType == Projection::Triaxial) {
249  TProjection *tproj = (TProjection *) p_projection;
250  return tproj->UniversalLatitude();
251  }
252  else {
254  return rproj->RingRadius();
255  }
256  }
257  }
258 
265  if (p_camera != NULL) {
266  return p_camera->UniversalLongitude();
267  }
268  else {
269  // Is this a triaxial projection or ring projection. If ring return ring longitude as
270  // longitude
272  if (projType == Projection::Triaxial) {
273  TProjection *tproj = (TProjection *) p_projection;
274  return tproj->UniversalLongitude();
275  }
276  else {
278  return rproj->RingLongitude();
279  }
280  }
281  }
282 
289  if (p_camera != NULL) {
290  return p_camera->PixelResolution();
291  }
292  else {
293  return p_projection->Resolution();
294  }
295  }
296 
297 
315  Latitude &maxLat, Longitude &minLon, Longitude &maxLon,
316  bool allowEstimation) {
317  // Do we need a RingRange method?
318  // For now just return false
319  if (HasCamera())
320  if (p_camera->target()->shape()->name() == "Plane") return false;
321  if (HasProjection())
322  if (p_projection->projectionType() == Projection::RingPlane) return false;
323 
324  minLat = Latitude();
325  maxLat = Latitude();
326  minLon = Longitude();
327  maxLon = Longitude();
328 
329  // If we have a footprint, use it
330  try {
331  if (cube) {
332  ImagePolygon poly;
333  cube->read(poly);
334  geos::geom::MultiPolygon *footprint = PolygonTools::MakeMultiPolygon(
335  poly.Polys()->clone());
336 
337  geos::geom::Geometry *envelope = footprint->getEnvelope();
338  geos::geom::CoordinateSequence *coords = envelope->getCoordinates();
339 
340  for (unsigned int i = 0; i < coords->getSize(); i++) {
341  const geos::geom::Coordinate &coord = coords->getAt(i);
342 
343  Latitude coordLat(coord.y, Angle::Degrees);
344  Longitude coordLon(coord.x, Angle::Degrees);
345 
346  if (!minLat.isValid() || minLat > coordLat)
347  minLat = coordLat;
348  if (!maxLat.isValid() || maxLat < coordLat)
349  maxLat = coordLat;
350 
351  if (!minLon.isValid() || minLon > coordLon)
352  minLon = coordLon;
353  if (!maxLon.isValid() || maxLon < coordLon)
354  maxLon = coordLon;
355  }
356 
357  delete coords;
358  coords = NULL;
359 
360  delete envelope;
361  envelope = NULL;
362 
363  delete footprint;
364  footprint = NULL;
365  }
366  }
367  catch (IException &) {
368  }
369 
370  if (!minLat.isValid() || !maxLat.isValid() ||
371  !minLon.isValid() || !maxLon.isValid()) {
372  if (HasCamera()) {
373  // Footprint failed, ask the camera
374  PvlGroup mappingGrp("Mapping");
375  mappingGrp += PvlKeyword("LatitudeType", "Planetocentric");
376  mappingGrp += PvlKeyword("LongitudeDomain", "360");
377  mappingGrp += PvlKeyword("LongitudeDirection", "PositiveEast");
378 
379  Pvl mappingPvl;
380  mappingPvl += mappingGrp;
381  double minLatDouble;
382  double maxLatDouble;
383  double minLonDouble;
384  double maxLonDouble;
386  minLatDouble, maxLatDouble,
387  minLonDouble, maxLonDouble, mappingPvl);
388  minLat = Latitude(minLatDouble, Angle::Degrees);
389  maxLat = Latitude(maxLatDouble, Angle::Degrees);
390  minLon = Longitude(minLonDouble, Angle::Degrees);
391  maxLon = Longitude(maxLonDouble, Angle::Degrees);
392  }
393  else if (HasProjection()) {
394  // Footprint failed, look in the mapping group
395  PvlGroup mappingGrp = p_projection->Mapping();
396  if (mappingGrp.hasKeyword("MinimumLatitude") &&
397  mappingGrp.hasKeyword("MaximumLatitude") &&
398  mappingGrp.hasKeyword("MinimumLongitude") &&
399  mappingGrp.hasKeyword("MaximumLongitude")) {
400 
401  minLat = Latitude(mappingGrp["MinimumLatitude"],
402  mappingGrp, Angle::Degrees);
403  maxLat = Latitude(mappingGrp["MaximumLatitude"],
404  mappingGrp, Angle::Degrees);
405  minLon = Longitude(mappingGrp["MinimumLongitude"],
406  mappingGrp, Angle::Degrees);
407  maxLon = Longitude(mappingGrp["MaximumLongitude"],
408  mappingGrp, Angle::Degrees);
409 
410  }
411  else if (allowEstimation && cube) {
412  // Footprint and mapping failed... no lat/lon range of any kind is
413  // available. Let's test points in the image to try to make our own
414  // extent.
415  QList<QPointF> imagePoints;
416 
417  // Reset to TProjection
418  TProjection *tproj = (TProjection *) p_projection;
419 
420  /*
421  * This is where we're testing:
422  *
423  * |---------------|
424  * |***************|
425  * |** * **|
426  * |* * * * *|
427  * |* * * * *|
428  * |***************|
429  * |* * * * *|
430  * |* * * * *|
431  * |** * **|
432  * |***************|
433  * |---------------|
434  *
435  * We'll test at the edges, a plus (+) and an (X) to help DEMs work.
436  */
437 
438  int sampleCount = cube->sampleCount();
439  int lineCount = cube->lineCount();
440 
441  int stepsPerLength = 20; //number of steps per length
442  double aspectRatio = (double)lineCount / (double)sampleCount;
443  double xStepSize = sampleCount / stepsPerLength;
444  double yStepSize = xStepSize * aspectRatio;
445 
446  if (lineCount > sampleCount) {
447  aspectRatio = (double)sampleCount / (double)lineCount;
448  yStepSize = lineCount / stepsPerLength;
449  xStepSize = yStepSize * aspectRatio;
450  }
451 
452  double yWalked = 0.5;
453 
454  //3 vertical lines
455  for (int i = 0; i < 3; i++) {
456  double xValue = 0.5 + ( i * (sampleCount / 2) );
457 
458  while (yWalked <= lineCount) {
459  imagePoints.append( QPointF(xValue, yWalked) );
460  yWalked += yStepSize;
461  }
462 
463  yWalked = 0.5;
464  }
465 
466  double xWalked = 0.5;
467 
468  //3 horizontal lines
469  for (int i = 0; i < 3; i++) {
470  double yValue = 0.5 + ( i * (lineCount / 2) );
471 
472  while (xWalked <= sampleCount) {
473  imagePoints.append( QPointF(xWalked, yValue) );
474  xWalked += xStepSize;
475  }
476 
477  xWalked = 0.5;
478  }
479 
480  double xDiagonalWalked = 0.5;
481  double yDiagonalWalked = 0.5;
482  xStepSize = sampleCount / stepsPerLength;
483  yStepSize = lineCount / stepsPerLength;
484 
485  //Top-Down Diagonal
486  while ( (xDiagonalWalked <= sampleCount) && (yDiagonalWalked <= lineCount) ) {
487  imagePoints.append( QPointF(xDiagonalWalked, yDiagonalWalked) );
488  xDiagonalWalked += xStepSize;
489  yDiagonalWalked += yStepSize;
490  }
491 
492  xDiagonalWalked = 0.5;
493 
494  //Bottom-Up Diagonal
495  while ( (xDiagonalWalked <= sampleCount) && (yDiagonalWalked >= 0) ) {
496  imagePoints.append( QPointF(xDiagonalWalked, yDiagonalWalked) );
497  xDiagonalWalked += xStepSize;
498  yDiagonalWalked -= yStepSize;
499  }
500 
501  foreach (QPointF imagePoint, imagePoints) {
502  if (tproj->SetWorld(imagePoint.x(), imagePoint.y())) {
503  Latitude latResult(tproj->UniversalLatitude(),
505  Longitude lonResult(tproj->UniversalLongitude(),
507  if (minLat.isValid())
508  minLat = qMin(minLat, latResult);
509  else
510  minLat = latResult;
511 
512  if (maxLat.isValid())
513  maxLat = qMax(maxLat, latResult);
514  else
515  maxLat = latResult;
516 
517  if (minLon.isValid())
518  minLon = qMin(minLon, lonResult);
519  else
520  minLon = lonResult;
521 
522  if (maxLon.isValid())
523  maxLon = qMax(maxLon, lonResult);
524  else
525  maxLon = lonResult;
526  }
527  }
528  }
529  }
530  }
531 
532  return (minLat.isValid() && maxLat.isValid() &&
533  minLon.isValid() && maxLon.isValid() &&
534  minLat < maxLat && minLon < maxLon);
535  }
536 }
This class defines a body-fixed surface point.
Definition: SurfacePoint.h:148
Isis::Camera * p_camera
The camera (if the image has a camera)
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
double Line() const
Returns the current line value of the camera model or projection.
static Isis::Projection * CreateFromCube(Isis::Cube &cube)
This method is a helper method.
ProjectionType projectionType() const
Returns an enum value for the projection type.
Definition: Projection.cpp:213
double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition: Sensor.cpp:225
Base class for Map TProjections.
Definition: TProjection.h:182
Isis::Projection * p_projection
The projection (if the image is projected)
int sampleCount() const
Definition: Cube.cpp:1452
~UniversalGroundMap()
Destroys the UniversalGroundMap object.
bool InCube()
This returns true if the current Sample() or Line() value is outside of the cube (meaning the point m...
Definition: Camera.cpp:2631
void append(const IException &exceptionSource)
Appends the given exception (and its list of previous exceptions) to this exception&#39;s causational exc...
Definition: IException.cpp:425
virtual bool SetUnboundUniversalGround(const double coord1, const double coord2)
This method is used to set the lat/lon or radius/azimuth (i.e.
Definition: Projection.cpp:461
This class is designed to encapsulate the concept of a Latitude.
Definition: Latitude.h:63
double UniversalLongitude()
This returns a universal longitude (positive east in 0 to 360 domain).
double Resolution() const
This method returns the resolution for mapping world coordinates into projection coordinates.
Definition: Projection.cpp:690
Latitude GetLatitude() const
Return the body-fixed latitude for the surface point.
double degrees() const
Get the angle in units of Degrees.
Definition: Angle.h:249
bool SetGround(Latitude latitude, Longitude longitude)
Sets the lat/lon values to get the sample/line values.
Definition: Camera.cpp:417
Create cube polygons, read/write polygons to blobs.
Definition: ImagePolygon.h:167
bool SetUniversalGround(const double latitude, const double longitude)
Sets the lat/lon values to get the sample/line values.
Definition: Camera.cpp:396
double WorldX() const
This returns the world X coordinate provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
Definition: Projection.cpp:539
bool SetImage(const double sample, const double line)
Sets the sample/line values of the image to get the lat/lon values.
Definition: Camera.cpp:170
This class is designed to encapsulate the concept of a Longitude.
Definition: Longitude.h:52
These projections are used to map ring planes.
Definition: Projection.h:184
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition: Angle.h:73
Target * target() const
Returns a pointer to the target object.
Definition: Spice.cpp:1290
bool SetUnboundGround(Latitude lat, Longitude lon)
Returns whether the lat/lon position was set successfully in the camera model or projection.
bool SetGround(Latitude lat, Longitude lon)
Returns whether the lat/lon position was set successfully in the camera model or projection.
static geos::geom::MultiPolygon * MakeMultiPolygon(const geos::geom::Geometry *geom)
Make a geos::geom::MultiPolygon out of the components of the argument.
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
bool GroundRange(double &minlat, double &maxlat, double &minlon, double &maxlon, Pvl &pvl)
Computes the Ground Range.
Definition: Camera.cpp:1201
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
double Sample()
Returns the current sample number.
Definition: Camera.cpp:2702
A single keyword-value pair.
Definition: PvlKeyword.h:98
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:134
double UniversalLatitude() const
Returns the universal latitude of the camera model or projection.
void read(Blob &blob) const
This method will read data from the specified Blob object.
Definition: Cube.cpp:724
static Camera * Create(Cube &cube)
Creates a Camera object using Pvl Specifications.
ShapeModel * shape() const
Return the shape.
Definition: Target.cpp:615
CameraPriority
This enum is used to define whether to use a camera or projection primarily, and which to fall back o...
Container for cube-like labels.
Definition: Pvl.h:135
double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Definition: Sensor.cpp:248
UniversalGroundMap(Cube &cube, CameraPriority priority=CameraFirst)
Constructs a UniversalGroundMap object from a cube.
double UniversalLatitude()
This returns a universal latitude (planetocentric).
double RingRadius() const
This returns a radius.
bool SetWorld(const double x, const double y)
This method is used to set a world coordinate.
Definition: Projection.cpp:512
bool SetImage(double sample, double line)
Returns whether the sample/line postion was set successfully in the camera model or projection...
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
QString name() const
Gets the shape name.
Definition: ShapeModel.cpp:537
Longitude GetLongitude() const
Return the body-fixed longitude for the surface point.
Base class for Map Projections of plane shapes.
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition: Cube.cpp:1346
void SetBand(const int band)
Set the image band number.
bool HasCamera()
Returns whether the ground map has a camera or not.
virtual QString fileName() const
Returns the opened cube&#39;s filename.
Definition: Cube.cpp:1208
double Line()
Returns the current line number.
Definition: Camera.cpp:2722
int lineCount() const
Definition: Cube.cpp:1379
virtual bool SetUniversalGround(const double coord1, const double coord2)
This method is used to set the lat/lon or radius/azimuth (i.e.
Definition: Projection.cpp:432
double PixelResolution()
Returns the pixel resolution at the current position in meters/pixel.
Definition: Camera.cpp:689
Isis exception class.
Definition: IException.h:107
This is the default because cameras are projection-aware.
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
bool SetUniversalGround(double lat, double lon)
Returns whether the lat/lon position was set successfully in the camera model or projection.
bool isValid() const
This indicates whether we have a legitimate angle stored or are in an unset, or invalid, state.
Definition: Angle.cpp:110
double Sample() const
Returns the current line value of the camera model or projection.
double RingLongitude() const
This returns a ring longitude with correct ring longitude direction and domain as specified in the la...
geos::geom::MultiPolygon * Polys()
Return a geos Multipolygon.
Definition: ImagePolygon.h:221
double UniversalLongitude() const
Returns the universal longitude of the camera model or projection.
double Resolution() const
Returns the resolution of the camera model or projection.
ProjectionType
This enum defines the subclasses of Projection supported in Isis.
Definition: Projection.h:182
virtual void SetBand(const int band)
Virtual method that sets the band number.
Definition: Camera.cpp:2692
bool HasProjection()
Returns whether the ground map has a projection or not.
double WorldY() const
This returns the world Y coordinate provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
Definition: Projection.cpp:559
bool GroundRange(Cube *cube, Latitude &minLat, Latitude &maxLat, Longitude &minLon, Longitude &maxLon, bool allowEstimation=true)
Find the lat/lon range of the image.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
These projections are used to map triaxial and irregular-shaped bodies.
Definition: Projection.h:182
IO Handler for Isis Cubes.
Definition: Cube.h:170