Isis 3 Programmer Reference
UniversalGroundMap.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "UniversalGroundMap.h"
8
9#include <QPointF>
10
11#include "Camera.h"
12#include "CameraFactory.h"
13#include "ImagePolygon.h"
14#include "Latitude.h"
15#include "Longitude.h"
16#include "Latitude.h"
17#include "Longitude.h"
18#include "PolygonTools.h"
19#include "Projection.h"
20#include "RingPlaneProjection.h"
21#include "TProjection.h"
22#include "ProjectionFactory.h"
23#include "SurfacePoint.h"
24#include "Target.h"
25
26namespace Isis {
34 p_camera = NULL;
35 p_projection = NULL;
36
37 Pvl &pvl = *cube.label();
38 try {
39 if(priority == CameraFirst)
41 else
43 }
44 catch (IException &firstError) {
45 p_camera = NULL;
46 p_projection = NULL;
47
48 try {
49 if(priority == CameraFirst)
51 else
53 }
54 catch (IException &secondError) {
55 p_projection = NULL;
56 QString msg = "Could not create camera or projection for [" +
57 cube.fileName() + "]";
58 IException realError(IException::Unknown, msg, _FILEINFO_);
59 realError.append(firstError);
60 realError.append(secondError);
61 throw realError;
62 }
63 }
64 }
65
72 void UniversalGroundMap::SetBand(const int band) {
73 if (p_camera != NULL)
74 p_camera->SetBand(band);
75 }
76
77
78
81 if (p_camera != NULL) {
82 delete p_camera;
83 p_camera = NULL;
84 }
85
86 if (p_projection != NULL) {
87 delete p_projection;
88 p_projection = NULL;
89 }
90 }
91
102 bool UniversalGroundMap::SetUniversalGround(double lat, double lon) {
103 if (p_camera != NULL) {
104 if (p_camera->SetUniversalGround(lat, lon)) { // This should work for rings (radius,azimuth)
105 return p_camera->InCube();
106 }
107 else {
108 return false;
109 }
110 }
111 else {
112 return p_projection->SetUniversalGround(lat, lon); // This should work for rings (radius,azimuth)
113 }
114 }
115
116
128 if(p_camera != NULL) {
129 if(p_camera->SetGround(lat, lon)) { // This should work for rings (radius,azimuth)
130 return p_camera->InCube();
131 }
132 else {
133 return false;
134 }
135 }
136 else {
137 double universalLat = lat.degrees();
138 double universalLon = lon.degrees();
139 return p_projection->SetUniversalGround(universalLat, universalLon); // This should work for rings (radius,azimuth)
140 }
141 }
142
143
155 if(p_camera != NULL) {
156 if(p_camera->SetGround(lat, lon)) { // This should work for rings (radius,azimuth)
157 return p_camera->InCube();
158 }
159 else {
160 return false;
161 }
162 }
163 else {
164 double universalLat = lat.degrees();
165 double universalLon = lon.degrees();
166 return p_projection->SetUnboundUniversalGround(universalLat, universalLon);
167 }
168 }
169
170
181 if (p_camera != NULL) {
182 if (p_camera->SetGround(sp)) {
183 return p_camera->InCube();
184 }
185 else {
186 return false;
187 }
188 }
189 else {
190 return p_projection->SetUniversalGround(sp.GetLatitude().degrees(),
191 sp.GetLongitude().degrees()); // This should work for rings (radius,azimuth)
192 }
193 }
194
201 if (p_camera != NULL) {
202 return p_camera->Sample();
203 }
204 else {
205 return p_projection->WorldX();
206 }
207 }
208
215 if (p_camera != NULL) {
216 return p_camera->Line();
217 }
218 else {
219 return p_projection->WorldY();
220 }
221 }
222
233 bool UniversalGroundMap::SetImage(double sample, double line) {
234 if (p_camera != NULL) {
235 return p_camera->SetImage(sample, line);
236 }
237 else {
238 return p_projection->SetWorld(sample, line);
239 }
240 }
241
248 if (p_camera != NULL) {
249 return p_camera->UniversalLatitude();
250 }
251 else {
252 // Is this a triaxial projection or ring projection. If ring return Radius as latitude
254 if (projType == Projection::Triaxial) {
256 return tproj->UniversalLatitude();
257 }
258 else {
260 return rproj->RingRadius();
261 }
262 }
263 }
264
271 if (p_camera != NULL) {
273 }
274 else {
275 // Is this a triaxial projection or ring projection. If ring return ring longitude as
276 // longitude
278 if (projType == Projection::Triaxial) {
280 return tproj->UniversalLongitude();
281 }
282 else {
284 return rproj->RingLongitude();
285 }
286 }
287 }
288
295 if (p_camera != NULL) {
296 return p_camera->PixelResolution();
297 }
298 else {
299 return p_projection->Resolution();
300 }
301 }
302
303
321 Latitude &maxLat, Longitude &minLon, Longitude &maxLon,
322 bool allowEstimation) {
323 // Do we need a RingRange method?
324 // For now just return false
325 if (HasCamera())
326 if (p_camera->target()->shape()->name() == "Plane") return false;
327 if (HasProjection())
328 if (p_projection->projectionType() == Projection::RingPlane) return false;
329
330 minLat = Latitude();
331 maxLat = Latitude();
332 minLon = Longitude();
333 maxLon = Longitude();
334
335 // If we have a footprint, use it
336 try {
337 if (cube) {
338 ImagePolygon poly = cube->readFootprint();
339 geos::geom::MultiPolygon *footprint = PolygonTools::MakeMultiPolygon(
340 poly.Polys()->clone().release());
341
342 geos::geom::Geometry *envelope = footprint->getEnvelope().release();
343 geos::geom::CoordinateSequence *coords = envelope->getCoordinates().release();
344
345 for (unsigned int i = 0; i < coords->getSize(); i++) {
346 const geos::geom::Coordinate &coord = coords->getAt(i);
347
348 Latitude coordLat(coord.y, Angle::Degrees);
349 Longitude coordLon(coord.x, Angle::Degrees);
350
351 if (!minLat.isValid() || minLat > coordLat)
352 minLat = coordLat;
353 if (!maxLat.isValid() || maxLat < coordLat)
354 maxLat = coordLat;
355
356 if (!minLon.isValid() || minLon > coordLon)
357 minLon = coordLon;
358 if (!maxLon.isValid() || maxLon < coordLon)
359 maxLon = coordLon;
360 }
361
362 delete coords;
363 coords = NULL;
364
365 delete envelope;
366 envelope = NULL;
367
368 delete footprint;
369 footprint = NULL;
370 }
371 }
372 catch (IException &) {
373 }
374
375 if (!minLat.isValid() || !maxLat.isValid() ||
376 !minLon.isValid() || !maxLon.isValid()) {
377 if (HasCamera()) {
378 // Footprint failed, ask the camera
379 PvlGroup mappingGrp("Mapping");
380 mappingGrp += PvlKeyword("LatitudeType", "Planetocentric");
381 mappingGrp += PvlKeyword("LongitudeDomain", "360");
382 mappingGrp += PvlKeyword("LongitudeDirection", "PositiveEast");
383
384 Pvl mappingPvl;
385 mappingPvl += mappingGrp;
386 double minLatDouble;
387 double maxLatDouble;
388 double minLonDouble;
389 double maxLonDouble;
391 minLatDouble, maxLatDouble,
392 minLonDouble, maxLonDouble, mappingPvl);
393 minLat = Latitude(minLatDouble, Angle::Degrees);
394 maxLat = Latitude(maxLatDouble, Angle::Degrees);
395 minLon = Longitude(minLonDouble, Angle::Degrees);
396 maxLon = Longitude(maxLonDouble, Angle::Degrees);
397 }
398 else if (HasProjection()) {
399 // Footprint failed, look in the mapping group
400 PvlGroup mappingGrp = p_projection->Mapping();
401 if (mappingGrp.hasKeyword("MinimumLatitude") &&
402 mappingGrp.hasKeyword("MaximumLatitude") &&
403 mappingGrp.hasKeyword("MinimumLongitude") &&
404 mappingGrp.hasKeyword("MaximumLongitude")) {
405
406 minLat = Latitude(mappingGrp["MinimumLatitude"],
407 mappingGrp, Angle::Degrees);
408 maxLat = Latitude(mappingGrp["MaximumLatitude"],
409 mappingGrp, Angle::Degrees);
410 minLon = Longitude(mappingGrp["MinimumLongitude"],
411 mappingGrp, Angle::Degrees);
412 maxLon = Longitude(mappingGrp["MaximumLongitude"],
413 mappingGrp, Angle::Degrees);
414
415 }
416 else if (allowEstimation && cube) {
417 // Footprint and mapping failed... no lat/lon range of any kind is
418 // available. Let's test points in the image to try to make our own
419 // extent.
420 QList<QPointF> imagePoints;
421
422 // Reset to TProjection
424
425 /*
426 * This is where we're testing:
427 *
428 * |---------------|
429 * |***************|
430 * |** * **|
431 * |* * * * *|
432 * |* * * * *|
433 * |***************|
434 * |* * * * *|
435 * |* * * * *|
436 * |** * **|
437 * |***************|
438 * |---------------|
439 *
440 * We'll test at the edges, a plus (+) and an (X) to help DEMs work.
441 */
442
443 int sampleCount = cube->sampleCount();
444 int lineCount = cube->lineCount();
445
446 int stepsPerLength = 20; //number of steps per length
447 double aspectRatio = (double)lineCount / (double)sampleCount;
448 double xStepSize = sampleCount / stepsPerLength;
449 double yStepSize = xStepSize * aspectRatio;
450
451 if (lineCount > sampleCount) {
452 aspectRatio = (double)sampleCount / (double)lineCount;
453 yStepSize = lineCount / stepsPerLength;
454 xStepSize = yStepSize * aspectRatio;
455 }
456
457 double yWalked = 0.5;
458
459 //3 vertical lines
460 for (int i = 0; i < 3; i++) {
461 double xValue = 0.5 + ( i * (sampleCount / 2) );
462
463 while (yWalked <= lineCount) {
464 imagePoints.append( QPointF(xValue, yWalked) );
465 yWalked += yStepSize;
466 }
467
468 yWalked = 0.5;
469 }
470
471 double xWalked = 0.5;
472
473 //3 horizontal lines
474 for (int i = 0; i < 3; i++) {
475 double yValue = 0.5 + ( i * (lineCount / 2) );
476
477 while (xWalked <= sampleCount) {
478 imagePoints.append( QPointF(xWalked, yValue) );
479 xWalked += xStepSize;
480 }
481
482 xWalked = 0.5;
483 }
484
485 double xDiagonalWalked = 0.5;
486 double yDiagonalWalked = 0.5;
487 xStepSize = sampleCount / stepsPerLength;
488 yStepSize = lineCount / stepsPerLength;
489
490 //Top-Down Diagonal
491 while ( (xDiagonalWalked <= sampleCount) && (yDiagonalWalked <= lineCount) ) {
492 imagePoints.append( QPointF(xDiagonalWalked, yDiagonalWalked) );
493 xDiagonalWalked += xStepSize;
494 yDiagonalWalked += yStepSize;
495 }
496
497 xDiagonalWalked = 0.5;
498
499 //Bottom-Up Diagonal
500 while ( (xDiagonalWalked <= sampleCount) && (yDiagonalWalked >= 0) ) {
501 imagePoints.append( QPointF(xDiagonalWalked, yDiagonalWalked) );
502 xDiagonalWalked += xStepSize;
503 yDiagonalWalked -= yStepSize;
504 }
505
506 foreach (QPointF imagePoint, imagePoints) {
507 if (tproj->SetWorld(imagePoint.x(), imagePoint.y())) {
508 Latitude latResult(tproj->UniversalLatitude(),
510 Longitude lonResult(tproj->UniversalLongitude(),
512 if (minLat.isValid())
513 minLat = qMin(minLat, latResult);
514 else
515 minLat = latResult;
516
517 if (maxLat.isValid())
518 maxLat = qMax(maxLat, latResult);
519 else
520 maxLat = latResult;
521
522 if (minLon.isValid())
523 minLon = qMin(minLon, lonResult);
524 else
525 minLon = lonResult;
526
527 if (maxLon.isValid())
528 maxLon = qMax(maxLon, lonResult);
529 else
530 maxLon = lonResult;
531 }
532 }
533 }
534 }
535 }
536
537 return (minLat.isValid() && maxLat.isValid() &&
538 minLon.isValid() && maxLon.isValid() &&
539 minLat < maxLat && minLon < maxLon);
540 }
541}
bool isValid() const
This indicates whether we have a legitimate angle stored or are in an unset, or invalid,...
Definition Angle.cpp:95
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition Angle.h:56
static Camera * Create(Cube &cube)
Creates a Camera object using Pvl Specifications.
virtual double Line() const
Returns the current line number.
Definition Camera.cpp:2740
virtual double Sample() const
Returns the current sample number.
Definition Camera.cpp:2720
virtual double PixelResolution()
Returns the pixel resolution at the current position in meters/pixel.
Definition Camera.cpp:681
virtual 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:156
bool InCube()
This returns true if the current Sample() or Line() value is outside of the cube (meaning the point m...
Definition Camera.cpp:2649
virtual bool SetUniversalGround(const double latitude, const double longitude)
Sets the lat/lon values to get the sample/line values.
Definition Camera.cpp:382
virtual bool SetGround(Latitude latitude, Longitude longitude)
Sets the lat/lon values to get the sample/line values.
Definition Camera.cpp:403
bool GroundRange(double &minlat, double &maxlat, double &minlon, double &maxlon, Pvl &pvl)
Computes the Ground Range.
Definition Camera.cpp:1193
virtual void SetBand(const int band)
Virtual method that sets the band number.
Definition Camera.cpp:2710
IO Handler for Isis Cubes.
Definition Cube.h:168
ImagePolygon readFootprint() const
Read the footprint polygon for the Cube.
Definition Cube.cpp:872
int lineCount() const
Definition Cube.cpp:1740
int sampleCount() const
Definition Cube.cpp:1813
virtual QString fileName() const
Returns the opened cube's filename.
Definition Cube.cpp:1569
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition Cube.cpp:1707
Isis exception class.
Definition IException.h:91
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition IException.h:118
Create cube polygons, read/write polygons to blobs.
This class is designed to encapsulate the concept of a Latitude.
Definition Latitude.h:51
This class is designed to encapsulate the concept of a Longitude.
Definition Longitude.h:40
static geos::geom::MultiPolygon * MakeMultiPolygon(const geos::geom::Geometry *geom)
Make a geos::geom::MultiPolygon out of the components of the argument.
static Isis::Projection * CreateFromCube(Isis::Cube &cube)
This method is a helper method.
virtual bool SetUniversalGround(const double coord1, const double coord2)
This method is used to set the lat/lon or radius/azimuth (i.e.
ProjectionType
This enum defines the subclasses of Projection supported in Isis.
Definition Projection.h:166
@ Triaxial
These projections are used to map triaxial and irregular-shaped bodies.
Definition Projection.h:166
@ RingPlane
These projections are used to map ring planes.
Definition Projection.h:168
double Resolution() const
This method returns the resolution for mapping world coordinates into projection coordinates.
virtual bool SetWorld(const double x, const double y)
This method is used to set a world coordinate.
virtual bool SetUnboundUniversalGround(const double coord1, const double coord2)
This method is used to set the lat/lon or radius/azimuth (i.e.
virtual double WorldY() const
This returns the world Y coordinate provided SetGround, SetCoordinate, SetUniversalGround,...
virtual double WorldX() const
This returns the world X coordinate provided SetGround, SetCoordinate, SetUniversalGround,...
ProjectionType projectionType() const
Returns an enum value for the projection type.
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
A single keyword-value pair.
Definition PvlKeyword.h:87
Base class for Map Projections of plane shapes.
virtual double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition Sensor.cpp:212
virtual double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Definition Sensor.cpp:235
virtual Target * target() const
Returns a pointer to the target object.
Definition Spice.cpp:1380
This class defines a body-fixed surface point.
Base class for Map TProjections.
Isis::Projection * p_projection
The projection (if the image is projected)
double Sample() const
Returns the current line value of the camera model or projection.
double UniversalLongitude() const
Returns the universal longitude of the camera model or projection.
bool SetImage(double sample, double line)
Returns whether the sample/line postion was set successfully in the camera model or projection.
double Resolution() const
Returns the resolution of the camera model or projection.
~UniversalGroundMap()
Destroys the UniversalGroundMap object.
void SetBand(const int band)
Set the image band number.
Isis::Camera * p_camera
The camera (if the image has a camera)
double UniversalLatitude() const
Returns the universal latitude of the camera model or projection.
bool SetUnboundGround(Latitude lat, Longitude lon)
Returns whether the lat/lon position was set successfully in the camera model or projection.
double Line() const
Returns the current line value of the camera model or projection.
bool HasProjection()
Returns whether the ground map has a projection or not.
CameraPriority
This enum is used to define whether to use a camera or projection primarily, and which to fall back o...
@ CameraFirst
This is the default because cameras are projection-aware.
bool HasCamera()
Returns whether the ground map has a camera or not.
UniversalGroundMap(Cube &cube, CameraPriority priority=CameraFirst)
Constructs a UniversalGroundMap object from a cube.
bool SetUniversalGround(double lat, double 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.
bool GroundRange(Cube *cube, Latitude &minLat, Latitude &maxLat, Longitude &minLon, Longitude &maxLon, bool allowEstimation=true)
Find the lat/lon range of the image.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16