Official websites use .gov
A .gov website belongs to an official government organization in the United States.

Secure .gov websites use HTTPS
A lock ( ) or https:// means you’ve safely connected to the .gov website. Share sensitive information only on official, secure websites.

Isis 3 Programmer Reference
UniversalGroundMap.cpp
1
5
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 p_priority = priority;
37
38 Pvl &pvl = *cube.label();
39 try {
41 }
42 catch (IException &e) {
43 if (p_priority == CameraFirst) {
44 p_priority = ProjectionFirst;
45 }
46 p_camera = NULL;
47 }
48
49 try {
51 }
52 catch (IException &e) {
53 if (p_priority == ProjectionFirst) {
54 p_priority = CameraFirst;
55 }
56 p_projection = NULL;
57 }
58
59 if (p_camera == NULL && p_projection == NULL) {
60 QString msg = "Could not create camera or projection for [" +
61 cube.fileName() + "]";
62 IException realError(IException::Unknown, msg, _FILEINFO_);
63 throw realError;
64 }
65 }
66
73 void UniversalGroundMap::SetBand(const int band) {
74 if (p_camera != NULL)
75 p_camera->SetBand(band);
76 }
77
78
79
82 if (p_camera != NULL) {
83 delete p_camera;
84 p_camera = NULL;
85 }
86
87 if (p_projection != NULL) {
88 delete p_projection;
89 p_projection = NULL;
90 }
91 }
92
103 bool UniversalGroundMap::SetUniversalGround(double lat, double lon) {
104 if (p_priority == CameraFirst) {
105 if (p_camera->SetUniversalGround(lat, lon)) { // This should work for rings (radius,azimuth)
106 return p_camera->InCube();
107 }
108 else {
109 return false;
110 }
111 }
112 else {
113 return p_projection->SetUniversalGround(lat, lon); // This should work for rings (radius,azimuth)
114 }
115 }
116
117
129 if(p_priority == CameraFirst) {
130 if(p_camera->SetGround(lat, lon)) { // This should work for rings (radius,azimuth)
131 return p_camera->InCube();
132 }
133 else {
134 return false;
135 }
136 }
137 else {
138 double universalLat = lat.degrees();
139 double universalLon = lon.degrees();
140 return p_projection->SetUniversalGround(universalLat, universalLon); // This should work for rings (radius,azimuth)
141 }
142 }
143
144
156 if(p_priority == CameraFirst) {
157 if(p_camera->SetGround(lat, lon)) { // This should work for rings (radius,azimuth)
158 return p_camera->InCube();
159 }
160 else {
161 return false;
162 }
163 }
164 else {
165 double universalLat = lat.degrees();
166 double universalLon = lon.degrees();
167 return p_projection->SetUnboundUniversalGround(universalLat, universalLon);
168 }
169 }
170
171
182 if (p_priority == CameraFirst) {
183 if (p_camera->SetGround(sp)) {
184 return p_camera->InCube();
185 }
186 else {
187 return false;
188 }
189 }
190 else {
191 return p_projection->SetUniversalGround(sp.GetLatitude().degrees(),
192 sp.GetLongitude().degrees()); // This should work for rings (radius,azimuth)
193 }
194 }
195
202 if (p_priority == CameraFirst) {
203 return p_camera->Sample();
204 }
205 else {
206 return p_projection->WorldX();
207 }
208 }
209
216 if (p_priority == CameraFirst) {
217 return p_camera->Line();
218 }
219 else {
220 return p_projection->WorldY();
221 }
222 }
223
234 bool UniversalGroundMap::SetImage(double sample, double line) {
235 if (p_priority == CameraFirst) {
236 return p_camera->SetImage(sample, line);
237 }
238 else {
239 return p_projection->SetWorld(sample, line);
240 }
241 }
242
249 if (p_priority == CameraFirst) {
250 return p_camera->UniversalLatitude();
251 }
252 else {
253 // Is this a triaxial projection or ring projection. If ring return Radius as latitude
254 Projection::ProjectionType projType = p_projection->projectionType();
255 if (projType == Projection::Triaxial) {
257 return tproj->UniversalLatitude();
258 }
259 else {
261 return rproj->RingRadius();
262 }
263 }
264 }
265
272 if (p_priority == CameraFirst) {
273 return p_camera->UniversalLongitude();
274 }
275 else {
276 // Is this a triaxial projection or ring projection. If ring return ring longitude as
277 // longitude
278 Projection::ProjectionType projType = p_projection->projectionType();
279 if (projType == Projection::Triaxial) {
281 return tproj->UniversalLongitude();
282 }
283 else {
285 return rproj->RingLongitude();
286 }
287 }
288 }
289
296 if (p_priority == CameraFirst) {
297 return p_camera->LocalRadius().meters();
298 }
299 else {
300 return p_projection->LocalRadius();
301 }
302 }
303
310 if (p_priority == CameraFirst) {
311 return p_camera->PixelResolution();
312 }
313 else {
314 return p_projection->Resolution();
315 }
316 }
317
318
336 Latitude &maxLat, Longitude &minLon, Longitude &maxLon,
337 bool allowEstimation) {
338 // Do we need a RingRange method?
339 // For now just return false
340 if (HasCamera())
341 if (p_camera->target()->shape()->name() == "Plane") return false;
342 if (HasProjection())
343 if (p_projection->projectionType() == Projection::RingPlane) return false;
344
345 minLat = Latitude();
346 maxLat = Latitude();
347 minLon = Longitude();
348 maxLon = Longitude();
349
350 // If we have a footprint, use it
351 try {
352 if (cube) {
353 ImagePolygon poly = cube->readFootprint();
354 geos::geom::MultiPolygon *footprint = PolygonTools::MakeMultiPolygon(
355 poly.Polys()->clone().release());
356
357 geos::geom::Geometry *envelope = footprint->getEnvelope().release();
358 geos::geom::CoordinateSequence *coords = envelope->getCoordinates().release();
359
360 for (unsigned int i = 0; i < coords->getSize(); i++) {
361 const geos::geom::Coordinate &coord = coords->getAt(i);
362
363 Latitude coordLat(coord.y, Angle::Degrees);
364 Longitude coordLon(coord.x, Angle::Degrees);
365
366 if (!minLat.isValid() || minLat > coordLat)
367 minLat = coordLat;
368 if (!maxLat.isValid() || maxLat < coordLat)
369 maxLat = coordLat;
370
371 if (!minLon.isValid() || minLon > coordLon)
372 minLon = coordLon;
373 if (!maxLon.isValid() || maxLon < coordLon)
374 maxLon = coordLon;
375 }
376
377 delete coords;
378 coords = NULL;
379
380 delete envelope;
381 envelope = NULL;
382
383 delete footprint;
384 footprint = NULL;
385 }
386 }
387 catch (IException &) {
388 }
389
390 if (!minLat.isValid() || !maxLat.isValid() ||
391 !minLon.isValid() || !maxLon.isValid()) {
392 if (p_priority == CameraFirst) {
393 // Footprint failed, ask the camera
394 PvlGroup mappingGrp("Mapping");
395 mappingGrp += PvlKeyword("LatitudeType", "Planetocentric");
396 mappingGrp += PvlKeyword("LongitudeDomain", "360");
397 mappingGrp += PvlKeyword("LongitudeDirection", "PositiveEast");
398
399 Pvl mappingPvl;
400 mappingPvl += mappingGrp;
401 double minLatDouble;
402 double maxLatDouble;
403 double minLonDouble;
404 double maxLonDouble;
405 p_camera->GroundRange(
406 minLatDouble, maxLatDouble,
407 minLonDouble, maxLonDouble, mappingPvl);
408 minLat = Latitude(minLatDouble, Angle::Degrees);
409 maxLat = Latitude(maxLatDouble, Angle::Degrees);
410 minLon = Longitude(minLonDouble, Angle::Degrees);
411 maxLon = Longitude(maxLonDouble, Angle::Degrees);
412 }
413 else if (p_priority == ProjectionFirst) {
414 // Footprint failed, look in the mapping group
415 PvlGroup mappingGrp = p_projection->Mapping();
416 if (mappingGrp.hasKeyword("MinimumLatitude") &&
417 mappingGrp.hasKeyword("MaximumLatitude") &&
418 mappingGrp.hasKeyword("MinimumLongitude") &&
419 mappingGrp.hasKeyword("MaximumLongitude")) {
420
421 minLat = Latitude(mappingGrp["MinimumLatitude"],
422 mappingGrp, Angle::Degrees);
423 maxLat = Latitude(mappingGrp["MaximumLatitude"],
424 mappingGrp, Angle::Degrees);
425 minLon = Longitude(mappingGrp["MinimumLongitude"],
426 mappingGrp, Angle::Degrees);
427 maxLon = Longitude(mappingGrp["MaximumLongitude"],
428 mappingGrp, Angle::Degrees);
429
430 }
431 else if (allowEstimation && cube) {
432 // Footprint and mapping failed... no lat/lon range of any kind is
433 // available. Let's test points in the image to try to make our own
434 // extent.
435 QList<QPointF> imagePoints;
436
437 // Reset to TProjection
439
440 /*
441 * This is where we're testing:
442 *
443 * |---------------|
444 * |***************|
445 * |** * **|
446 * |* * * * *|
447 * |* * * * *|
448 * |***************|
449 * |* * * * *|
450 * |* * * * *|
451 * |** * **|
452 * |***************|
453 * |---------------|
454 *
455 * We'll test at the edges, a plus (+) and an (X) to help DEMs work.
456 */
457
458 int sampleCount = cube->sampleCount();
459 int lineCount = cube->lineCount();
460
461 int stepsPerLength = 20; //number of steps per length
462 double aspectRatio = (double)lineCount / (double)sampleCount;
463 double xStepSize = sampleCount / stepsPerLength;
464 double yStepSize = xStepSize * aspectRatio;
465
466 if (lineCount > sampleCount) {
467 aspectRatio = (double)sampleCount / (double)lineCount;
468 yStepSize = lineCount / stepsPerLength;
469 xStepSize = yStepSize * aspectRatio;
470 }
471
472 double yWalked = 0.5;
473
474 //3 vertical lines
475 for (int i = 0; i < 3; i++) {
476 double xValue = 0.5 + ( i * (sampleCount / 2) );
477
478 while (yWalked <= lineCount) {
479 imagePoints.append( QPointF(xValue, yWalked) );
480 yWalked += yStepSize;
481 }
482
483 yWalked = 0.5;
484 }
485
486 double xWalked = 0.5;
487
488 //3 horizontal lines
489 for (int i = 0; i < 3; i++) {
490 double yValue = 0.5 + ( i * (lineCount / 2) );
491
492 while (xWalked <= sampleCount) {
493 imagePoints.append( QPointF(xWalked, yValue) );
494 xWalked += xStepSize;
495 }
496
497 xWalked = 0.5;
498 }
499
500 double xDiagonalWalked = 0.5;
501 double yDiagonalWalked = 0.5;
502 xStepSize = sampleCount / stepsPerLength;
503 yStepSize = lineCount / stepsPerLength;
504
505 //Top-Down Diagonal
506 while ( (xDiagonalWalked <= sampleCount) && (yDiagonalWalked <= lineCount) ) {
507 imagePoints.append( QPointF(xDiagonalWalked, yDiagonalWalked) );
508 xDiagonalWalked += xStepSize;
509 yDiagonalWalked += yStepSize;
510 }
511
512 xDiagonalWalked = 0.5;
513
514 //Bottom-Up Diagonal
515 while ( (xDiagonalWalked <= sampleCount) && (yDiagonalWalked >= 0) ) {
516 imagePoints.append( QPointF(xDiagonalWalked, yDiagonalWalked) );
517 xDiagonalWalked += xStepSize;
518 yDiagonalWalked -= yStepSize;
519 }
520
521 foreach (QPointF imagePoint, imagePoints) {
522 if (tproj->SetWorld(imagePoint.x(), imagePoint.y())) {
523 Latitude latResult(tproj->UniversalLatitude(),
525 Longitude lonResult(tproj->UniversalLongitude(),
527 if (minLat.isValid())
528 minLat = qMin(minLat, latResult);
529 else
530 minLat = latResult;
531
532 if (maxLat.isValid())
533 maxLat = qMax(maxLat, latResult);
534 else
535 maxLat = latResult;
536
537 if (minLon.isValid())
538 minLon = qMin(minLon, lonResult);
539 else
540 minLon = lonResult;
541
542 if (maxLon.isValid())
543 maxLon = qMax(maxLon, lonResult);
544 else
545 maxLon = lonResult;
546 }
547 }
548 }
549 }
550 }
551
552 return (minLat.isValid() && maxLat.isValid() &&
553 minLon.isValid() && maxLon.isValid() &&
554 minLat < maxLat && minLon < maxLon);
555 }
556
557 void UniversalGroundMap::setPriority(int priority) {
558 if (priority == UniversalGroundMap::CameraFirst && HasCamera()) {
559 p_priority = (CameraPriority) priority;
560 }
561 else if (priority == UniversalGroundMap::ProjectionFirst && HasProjection()) {
562 p_priority = (CameraPriority) priority;
563 }
564 }
565}
bool isValid() const
This indicates whether we have a legitimate angle stored or are in an unset, or invalid,...
Definition Angle.cpp:96
double degrees() const
Get the angle in units of Degrees.
Definition Angle.h:232
@ 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.
IO Handler for Isis Cubes.
Definition Cube.h:168
ImagePolygon readFootprint() const
Read the footprint polygon for the Cube.
Definition Cube.cpp:1114
int lineCount() const
Definition Cube.cpp:2008
int sampleCount() const
Definition Cube.cpp:2081
virtual QString fileName() const
Returns the opened cube's filename.
Definition Cube.cpp:1837
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition Cube.cpp:1975
Create cube polygons, read/write polygons to blobs.
geos::geom::MultiPolygon * Polys()
Return a geos Multipolygon.
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.
ProjectionType
This enum defines the subclasses of Projection supported in Isis.
Definition Projection.h:165
@ Triaxial
These projections are used to map triaxial and irregular-shaped bodies.
Definition Projection.h:165
@ RingPlane
These projections are used to map ring planes.
Definition Projection.h:167
virtual bool SetWorld(const double x, const double y)
This method is used to set a world coordinate.
Base class for Map Projections of plane shapes.
double RingRadius() const
This returns a radius.
double RingLongitude() const
This returns a ring longitude with correct ring longitude direction and domain as specified in the la...
This class defines a body-fixed surface point.
Latitude GetLatitude() const
Return the body-fixed latitude for the surface point.
Longitude GetLongitude() const
Return the body-fixed longitude for the surface point.
Base class for Map TProjections.
virtual double UniversalLongitude()
This returns a universal longitude (positive east in 0 to 360 domain).
virtual double UniversalLatitude()
This returns a universal latitude (planetocentric).
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...
@ ProjectionFirst
Use the projection for functionality well outside the original image if available,...
@ CameraFirst
This is the default because cameras are projection-aware.
double LocalRadius() const
Returns the radius of the camera model or projection.
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.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16