Isis 3.0 Programmer Reference
Back | Home
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 
148  if (p_camera != NULL) {
149  if (p_camera->SetGround(sp)) {
150  return p_camera->InCube();
151  }
152  else {
153  return false;
154  }
155  }
156  else {
158  sp.GetLongitude().degrees()); // This should work for rings (radius,azimuth)
159  }
160  }
161 
167  double UniversalGroundMap::Sample() const {
168  if (p_camera != NULL) {
169  return p_camera->Sample();
170  }
171  else {
172  return p_projection->WorldX();
173  }
174  }
175 
181  double UniversalGroundMap::Line() const {
182  if (p_camera != NULL) {
183  return p_camera->Line();
184  }
185  else {
186  return p_projection->WorldY();
187  }
188  }
189 
200  bool UniversalGroundMap::SetImage(double sample, double line) {
201  if (p_camera != NULL) {
202  return p_camera->SetImage(sample, line);
203  }
204  else {
205  return p_projection->SetWorld(sample, line);
206  }
207  }
208 
215  if (p_camera != NULL) {
216  return p_camera->UniversalLatitude();
217  }
218  else {
219  // Is this a triaxial projection or ring projection. If ring return Radius as latitude
221  if (projType == Projection::Triaxial) {
222  TProjection *tproj = (TProjection *) p_projection;
223  return tproj->UniversalLatitude();
224  }
225  else {
227  return rproj->RingRadius();
228  }
229  }
230  }
231 
238  if (p_camera != NULL) {
239  return p_camera->UniversalLongitude();
240  }
241  else {
242  // Is this a triaxial projection or ring projection. If ring return ring longitude as
243  // longitude
245  if (projType == Projection::Triaxial) {
246  TProjection *tproj = (TProjection *) p_projection;
247  return tproj->UniversalLongitude();
248  }
249  else {
251  return rproj->RingLongitude();
252  }
253  }
254  }
255 
262  if (p_camera != NULL) {
263  return p_camera->PixelResolution();
264  }
265  else {
266  return p_projection->Resolution();
267  }
268  }
269 
270 
288  Latitude &maxLat, Longitude &minLon, Longitude &maxLon,
289  bool allowEstimation) {
290  // Do we need a RingRange method?
291  // For now just return false
292  if (HasCamera())
293  if (p_camera->target()->shape()->name() == "Plane") return false;
294  if (HasProjection())
295  if (p_projection->projectionType() == Projection::RingPlane) return false;
296 
297  minLat = Latitude();
298  maxLat = Latitude();
299  minLon = Longitude();
300  maxLon = Longitude();
301 
302  // If we have a footprint, use it
303  try {
304  if (cube) {
305  ImagePolygon poly;
306  cube->read(poly);
307  geos::geom::MultiPolygon *footprint = PolygonTools::MakeMultiPolygon(
308  poly.Polys()->clone());
309 
310  geos::geom::Geometry *envelope = footprint->getEnvelope();
311  geos::geom::CoordinateSequence *coords = envelope->getCoordinates();
312 
313  for (unsigned int i = 0; i < coords->getSize(); i++) {
314  const geos::geom::Coordinate &coord = coords->getAt(i);
315 
316  Latitude coordLat(coord.y, Angle::Degrees);
317  Longitude coordLon(coord.x, Angle::Degrees);
318 
319  if (!minLat.isValid() || minLat > coordLat)
320  minLat = coordLat;
321  if (!maxLat.isValid() || maxLat < coordLat)
322  maxLat = coordLat;
323 
324  if (!minLon.isValid() || minLon > coordLon)
325  minLon = coordLon;
326  if (!maxLon.isValid() || maxLon < coordLon)
327  maxLon = coordLon;
328  }
329 
330  delete coords;
331  coords = NULL;
332 
333  delete envelope;
334  envelope = NULL;
335 
336  delete footprint;
337  footprint = NULL;
338  }
339  }
340  catch (IException &) {
341  }
342 
343  if (!minLat.isValid() || !maxLat.isValid() ||
344  !minLon.isValid() || !maxLon.isValid()) {
345  if (HasCamera()) {
346  // Footprint failed, ask the camera
347  PvlGroup mappingGrp("Mapping");
348  mappingGrp += PvlKeyword("LatitudeType", "Planetocentric");
349  mappingGrp += PvlKeyword("LongitudeDomain", "360");
350  mappingGrp += PvlKeyword("LongitudeDirection", "PositiveEast");
351 
352  Pvl mappingPvl;
353  mappingPvl += mappingGrp;
354  double minLatDouble;
355  double maxLatDouble;
356  double minLonDouble;
357  double maxLonDouble;
359  minLatDouble, maxLatDouble,
360  minLonDouble, maxLonDouble, mappingPvl);
361  minLat = Latitude(minLatDouble, Angle::Degrees);
362  maxLat = Latitude(maxLatDouble, Angle::Degrees);
363  minLon = Longitude(minLonDouble, Angle::Degrees);
364  maxLon = Longitude(maxLonDouble, Angle::Degrees);
365  }
366  else if (HasProjection()) {
367  // Footprint failed, look in the mapping group
368  PvlGroup mappingGrp = p_projection->Mapping();
369  if (mappingGrp.hasKeyword("MinimumLatitude") &&
370  mappingGrp.hasKeyword("MaximumLatitude") &&
371  mappingGrp.hasKeyword("MinimumLongitude") &&
372  mappingGrp.hasKeyword("MaximumLongitude")) {
373 
374  minLat = Latitude(mappingGrp["MinimumLatitude"],
375  mappingGrp, Angle::Degrees);
376  maxLat = Latitude(mappingGrp["MaximumLatitude"],
377  mappingGrp, Angle::Degrees);
378  minLon = Longitude(mappingGrp["MinimumLongitude"],
379  mappingGrp, Angle::Degrees);
380  maxLon = Longitude(mappingGrp["MaximumLongitude"],
381  mappingGrp, Angle::Degrees);
382 
383  }
384  else if (allowEstimation && cube) {
385  // Footprint and mapping failed... no lat/lon range of any kind is
386  // available. Let's test points in the image to try to make our own
387  // extent.
388  QList<QPointF> imagePoints;
389 
390  // Reset to TProjection
391  TProjection *tproj = (TProjection *) p_projection;
392 
393  /*
394  * This is where we're testing:
395  *
396  * |---------------|
397  * |***************|
398  * |** * **|
399  * |* * * * *|
400  * |* * * * *|
401  * |***************|
402  * |* * * * *|
403  * |* * * * *|
404  * |** * **|
405  * |***************|
406  * |---------------|
407  *
408  * We'll test at the edges, a plus (+) and an (X) to help DEMs work.
409  */
410 
411  int sampleCount = cube->sampleCount();
412  int lineCount = cube->lineCount();
413 
414  int stepsPerLength = 20; //number of steps per length
415  double aspectRatio = (double)lineCount / (double)sampleCount;
416  double xStepSize = sampleCount / stepsPerLength;
417  double yStepSize = xStepSize * aspectRatio;
418 
419  if (lineCount > sampleCount) {
420  aspectRatio = (double)sampleCount / (double)lineCount;
421  yStepSize = lineCount / stepsPerLength;
422  xStepSize = yStepSize * aspectRatio;
423  }
424 
425  double yWalked = 0.5;
426 
427  //3 vertical lines
428  for (int i = 0; i < 3; i++) {
429  double xValue = 0.5 + ( i * (sampleCount / 2) );
430 
431  while (yWalked <= lineCount) {
432  imagePoints.append( QPointF(xValue, yWalked) );
433  yWalked += yStepSize;
434  }
435 
436  yWalked = 0.5;
437  }
438 
439  double xWalked = 0.5;
440 
441  //3 horizontal lines
442  for (int i = 0; i < 3; i++) {
443  double yValue = 0.5 + ( i * (lineCount / 2) );
444 
445  while (xWalked <= sampleCount) {
446  imagePoints.append( QPointF(xWalked, yValue) );
447  xWalked += xStepSize;
448  }
449 
450  xWalked = 0.5;
451  }
452 
453  double xDiagonalWalked = 0.5;
454  double yDiagonalWalked = 0.5;
455  xStepSize = sampleCount / stepsPerLength;
456  yStepSize = lineCount / stepsPerLength;
457 
458  //Top-Down Diagonal
459  while ( (xDiagonalWalked <= sampleCount) && (yDiagonalWalked <= lineCount) ) {
460  imagePoints.append( QPointF(xDiagonalWalked, yDiagonalWalked) );
461  xDiagonalWalked += xStepSize;
462  yDiagonalWalked += yStepSize;
463  }
464 
465  xDiagonalWalked = 0.5;
466 
467  //Bottom-Up Diagonal
468  while ( (xDiagonalWalked <= sampleCount) && (yDiagonalWalked >= 0) ) {
469  imagePoints.append( QPointF(xDiagonalWalked, yDiagonalWalked) );
470  xDiagonalWalked += xStepSize;
471  yDiagonalWalked -= yStepSize;
472  }
473 
474  foreach (QPointF imagePoint, imagePoints) {
475  if (tproj->SetWorld(imagePoint.x(), imagePoint.y())) {
476  Latitude latResult(tproj->UniversalLatitude(),
478  Longitude lonResult(tproj->UniversalLongitude(),
480  if (minLat.isValid())
481  minLat = qMin(minLat, latResult);
482  else
483  minLat = latResult;
484 
485  if (maxLat.isValid())
486  maxLat = qMax(maxLat, latResult);
487  else
488  maxLat = latResult;
489 
490  if (minLon.isValid())
491  minLon = qMin(minLon, lonResult);
492  else
493  minLon = lonResult;
494 
495  if (maxLon.isValid())
496  maxLon = qMax(maxLon, lonResult);
497  else
498  maxLon = lonResult;
499  }
500  }
501  }
502  }
503  }
504 
505  return (minLat.isValid() && maxLat.isValid() &&
506  minLon.isValid() && maxLon.isValid() &&
507  minLat < maxLat && minLon < maxLon);
508  }
509 }
This class defines a body-fixed surface point.
Definition: SurfacePoint.h:86
double WorldX() const
This returns the world X coordinate provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
Definition: Projection.cpp:510
Isis::Camera * p_camera
The camera (if the image has a camera)
static Isis::Projection * CreateFromCube(Isis::Cube &cube)
This method is a helper method.
double Sample() const
Returns the current line value of the camera model or projection.
double degrees() const
Get the angle in units of Degrees.
Definition: Angle.h:245
QString name() const
Gets the shape name.
Definition: ShapeModel.cpp:454
Base class for Map TProjections.
Definition: TProjection.h:178
Isis::Projection * p_projection
The projection (if the image is projected)
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition: Cube.cpp:1298
~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:2681
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
double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition: Sensor.cpp:225
double Resolution() const
Returns the resolution of the camera model or projection.
This class is designed to encapsulate the concept of a Latitude.
Definition: Latitude.h:59
double UniversalLongitude()
This returns a universal longitude (positive east in 0 to 360 domain).
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:686
double Line() const
Returns the current line value of the camera model or projection.
Longitude GetLongitude() const
Return the body-fixed longitude for the surface point.
bool SetGround(Latitude latitude, Longitude longitude)
Sets the lat/lon values to get the sample/line values.
Definition: Camera.cpp:413
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:392
double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Definition: Sensor.cpp:248
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:166
This class is designed to encapsulate the concept of a Longitude.
Definition: Longitude.h:52
Target * target() const
Returns a pointer to the target object.
Definition: Spice.cpp:1277
These projections are used to map ring planes.
Definition: Projection.h:182
int sampleCount() const
Definition: Cube.cpp:1404
double RingLongitude() const
This returns a ring longitude with correct ring longitude direction and domain as specified in the la...
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition: Angle.h:69
bool SetGround(Latitude lat, Longitude lon)
Returns whether the lat/lon position was set successfully in the camera model or projection.
Latitude GetLatitude() const
Return the body-fixed latitude for the surface point.
static geos::geom::MultiPolygon * MakeMultiPolygon(const geos::geom::Geometry *geom)
Make a geos::geom::MultiPolygon out of the components of the argument.
double Resolution() const
This method returns the resolution for mapping world coordinates into projection coordinates.
Definition: Projection.cpp:661
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:1256
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:38
double Sample()
Returns the current sample number.
Definition: Camera.cpp:2752
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:126
double UniversalLongitude() const
Returns the universal longitude of the camera model or projection.
static Camera * Create(Cube &cube)
Creates a Camera object using Pvl Specifications.
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
bool isValid() const
This indicates whether we have a legitimate angle stored or are in an unset, or invalid, state.
Definition: Angle.cpp:110
UniversalGroundMap(Cube &cube, CameraPriority priority=CameraFirst)
Constructs a UniversalGroundMap object from a cube.
double UniversalLatitude()
This returns a universal latitude (planetocentric).
bool SetWorld(const double x, const double y)
This method is used to set a world coordinate.
Definition: Projection.cpp:483
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.
Base class for Map Projections of plane shapes.
void SetBand(const int band)
Set the image band number.
bool HasCamera()
Returns whether the ground map has a camera or not.
double Line()
Returns the current line number.
Definition: Camera.cpp:2772
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:744
Isis exception class.
Definition: IException.h:99
This is the default because cameras are projection-aware.
double RingRadius() const
This returns a radius.
bool SetUniversalGround(double lat, double lon)
Returns whether the lat/lon position was set successfully in the camera model or projection.
QString fileName() const
Returns the opened cube&#39;s filename.
Definition: Cube.cpp:1160
ShapeModel * shape() const
Return the shape.
Definition: Target.cpp:592
ProjectionType projectionType() const
Returns an enum value for the projection type.
Definition: Projection.cpp:213
geos::geom::MultiPolygon * Polys()
Return a geos Multipolygon.
Definition: ImagePolygon.h:221
int lineCount() const
Definition: Cube.cpp:1331
ProjectionType
This enum defines the subclasses of Projection supported in Isis.
Definition: Projection.h:180
virtual void SetBand(const int band)
Virtual method that sets the band number.
Definition: Camera.cpp:2742
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
bool HasProjection()
Returns whether the ground map has a projection or not.
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.
double WorldY() const
This returns the world Y coordinate provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
Definition: Projection.cpp:530
These projections are used to map triaxial and irregular-shaped bodies.
Definition: Projection.h:180
IO Handler for Isis Cubes.
Definition: Cube.h:158

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:31:12