7#include "ProjectionFactory.h"
16#include "Displacement.h"
19#include "IException.h"
21#include "Projection.h"
22#include "RingPlaneProjection.h"
23#include "TProjection.h"
28 Plugin ProjectionFactory::m_projPlugin;
57 if (m_projPlugin.fileName() ==
"") {
58 FileName localFile(
"Projection.plugin");
60 m_projPlugin.read(localFile.
expanded());
62 FileName systemFile(
"$ISISROOT/lib/Projection.plugin");
64 m_projPlugin.read(systemFile.
expanded());
70 QString proj = mapGroup[
"ProjectionName"];
75 ptr = m_projPlugin.GetPlugin(proj);
78 QString msg =
"Unsupported projection, unable to find plugin for [" +
91 QString message =
"Unable to initialize Projection information ";
92 message +=
"from group [Mapping]";
120 bool allowDefaults) {
125 if (m_projPlugin.fileName() ==
"") {
126 FileName localFile(
"Projection.plugin");
128 m_projPlugin.read(localFile.
expanded());
130 FileName systemFile(
"$ISISROOT/lib/Projection.plugin");
132 m_projPlugin.read(systemFile.
expanded());
138 QString proj = mapGroup[
"ProjectionName"];
141 QFunctionPointer ptr;
143 ptr = m_projPlugin.GetPlugin(proj);
146 QString msg =
"Unsupported projection, unable to find plugin for [" +
155 return (
Projection *) (*plugin)(label, allowDefaults);
158 QString message =
"Unable to initialize Projection information ";
159 message +=
"from group [Mapping]";
189 int &samples,
int &lines,
194 double localRadius = proj->
LocalRadius(trueScaleLat);
200 double scale, pixelResolution;
203 pixelResolution = mapGroup[
"PixelResolution"];
204 scale = (2.0 *
Isis::PI * localRadius) / (360.0 * pixelResolution);
211 scale = mapGroup[
"Scale"];
212 pixelResolution = (2.0 *
Isis::PI * localRadius) / (360.0 * scale);
224 bool sizeFound =
false;
225 double upperLeftX =
Null, upperLeftY =
Null;
228 samples = dims[
"Samples"];
229 lines = dims[
"Lines"];
231 upperLeftX = mapGroup[
"UpperLeftCornerX"];
232 upperLeftY = mapGroup[
"UpperLeftCornerY"];
235 if (!sizeMatch) sizeFound =
false;
243 QString msg =
"Invalid ground range [MinimumLatitude,MaximumLatitude,";
244 msg +=
"MinimumLongitude,MaximumLongitude] missing or invalid";
248 double minX, maxX, minY, maxY;
249 if (!proj->
XYRange(minX, maxX, minY, maxY)) {
250 QString msg =
"Invalid ground range [MinimumLatitude,MaximumLatitude,";
251 msg +=
"MinimumLongitude,MaximumLongitude] cause invalid computation ";
252 msg +=
"of image size";
267 double minXFlipped = minX;
268 double maxXFlipped = maxX;
269 double minYFlipped = minY;
270 double maxYFlipped = maxY;
281 if (fabs(fmod(minXFlipped, pixelResolution)) > 1.0e-6) {
282 if (pixelResolution - fabs(fmod(minXFlipped, pixelResolution)) > 1.0e-6) {
283 double sampleOffset = floor(minXFlipped / pixelResolution);
285 minXFlipped = sampleOffset * pixelResolution;
295 if (maxXFlipped < minXFlipped + pixelResolution) {
296 maxXFlipped = minXFlipped + pixelResolution;
308 if (fabs(fmod(maxYFlipped, pixelResolution)) > 1.0e-6) {
309 if (abs(pixelResolution - fabs(fmod(maxYFlipped, pixelResolution))) > 1.0e-6) {
310 double lineOffset = ceil(maxYFlipped / pixelResolution);
311 maxYFlipped = lineOffset * pixelResolution;
319 if (minYFlipped > maxYFlipped - pixelResolution) {
320 minYFlipped = maxYFlipped - pixelResolution;
325 samples = (int)((maxXFlipped - minXFlipped) / pixelResolution + 0.5);
326 lines = (int)((maxYFlipped - minYFlipped) / pixelResolution + 0.5);
335 upperLeftX = minXFlipped;
345 upperLeftY = maxYFlipped;
366 (QString) mapGroup[
"PixelResolution"],
367 "meters/pixel"), Isis::Pvl::Replace);
370 (QString) mapGroup[
"Scale"],
371 "pixels/degree"), Isis::Pvl::Replace);
374 (QString) mapGroup[
"UpperLeftCornerX"],
375 "meters"), Isis::Pvl::Replace);
378 (QString) mapGroup[
"UpperLeftCornerY"],
379 "meters"), Isis::Pvl::Replace);
382 (QString) mapGroup[
"EquatorialRadius"],
383 "meters"), Isis::Pvl::Replace);
386 (QString) mapGroup[
"PolarRadius"],
387 "meters"), Isis::Pvl::Replace);
397 QString msg =
"Unable to create projection";
400 finalError.
append(errors);
433 int &samples,
int &lines,
bool sizeMatch) {
445 double scale, pixelResolution;
448 pixelResolution = mapGroup[
"PixelResolution"];
449 scale = (2.0 *
Isis::PI * localRadius) / (360.0 * pixelResolution);
455 scale = mapGroup[
"Scale"];
456 pixelResolution = (2.0 *
Isis::PI * localRadius) / (360.0 * scale);
472 bool sizeFound =
false;
473 double upperLeftX =
Null, upperLeftY =
Null;
476 samples = dims[
"Samples"];
477 lines = dims[
"Lines"];
479 upperLeftX = mapGroup[
"UpperLeftCornerX"];
480 upperLeftY = mapGroup[
"UpperLeftCornerY"];
494 QString msg =
"Invalid ring range [MinimumRingRadius,MaximumRingRadius,";
495 msg +=
"MinimumRingLongitude,MaximumRingLongitude] missing or invalid";
499 double minX, maxX, minY, maxY;
500 if (!proj->
XYRange(minX, maxX, minY, maxY)) {
501 QString msg =
"Invalid ring range [MinimumRingRadius,MaximumRingRadius,";
502 msg +=
"MinimumRingLongitude,MaximumRingLongitude] cause invalid computation ";
503 msg +=
"of image size";
513 if (fabs(fmod(minX, pixelResolution)) > 1.0e-6) {
514 if (pixelResolution - fabs(fmod(minX, pixelResolution)) > 1.0e-6) {
515 double sampleOffset = floor(minX / pixelResolution);
516 minX = sampleOffset * pixelResolution;
521 if (maxX < minX + pixelResolution) {
522 maxX = minX + pixelResolution;
524 if (fabs(fmod(maxY, pixelResolution)) > 1.0e-6) {
525 if (pixelResolution - fabs(fmod(maxY, pixelResolution)) > 1.0e-6) {
526 double lineOffset = -1.0 * ceil(maxY / pixelResolution);
527 maxY = -1.0 * lineOffset * pixelResolution;
532 if (minY > maxY - pixelResolution) {
533 minY = maxY - pixelResolution;
537 samples = (int)((maxX - minX) / pixelResolution + 0.5);
538 lines = (int)((maxY - minY) / pixelResolution + 0.5);
555 mapGroup.AddKeyword(
Isis::PvlKeyword(
"SampleProjectionOffset", sampleOffset),
563 (QString) mapGroup[
"PixelResolution"],
564 "meters/pixel"), Isis::Pvl::Replace);
567 (QString) mapGroup[
"Scale"],
568 "pixels/degree"), Isis::Pvl::Replace);
571 (QString) mapGroup[
"UpperLeftCornerX"],
572 "meters"), Isis::Pvl::Replace);
575 (QString) mapGroup[
"UpperLeftCornerY"],
576 "meters"), Isis::Pvl::Replace);
586 QString msg =
"Unable to create projection";
589 finalError.
append(errors);
622 int &samples,
int &lines,
627 double localRadius = proj->
LocalRadius(trueScaleLat);
632 double scale, pixelResolution;
635 pixelResolution = mapGroup[
"PixelResolution"];
636 scale = (2.0 *
Isis::PI * localRadius) / (360.0 * pixelResolution);
641 scale = mapGroup[
"Scale"];
642 pixelResolution = (2.0 *
Isis::PI * localRadius) / (360.0 * scale);
653 double minX = DBL_MAX;
654 double maxX = -DBL_MAX;
655 double minY = DBL_MAX;
656 double maxY = -DBL_MAX;
659 int eband = cam.
Bands();
661 for(
int band = 1; band <= eband; band++) {
665 for(
int line = 0; line <= cam.
Lines(); line++) {
669 for(samp = 0; samp <= cam.
Samples(); samp++) {
670 if (cam.
SetImage((
double)samp + 0.5, (
double)line + 0.5)) {
679 if ((line != 0) && (line != cam.
Lines()))
break;
686 for(samp = cam.
Samples(); samp >= 0; samp--) {
687 if (cam.
SetImage((
double)samp + 0.5, (
double)line + 0.5)) {
705 if (cam.
Sample() >= 0.5 && cam.
Line() >= 0.5 &&
720 if (cam.
Sample() >= 0.5 && cam.
Line() >= 0.5 &&
738 for(
double lat = p_minlat; lat <= p_maxlat; lat += (p_maxlat - p_minlat) / 10.0) {
739 if (SetUniversalGround(lat, 0.0)) {
740 if (Sample() >= 0.5 && Line() >= 0.5 &&
741 Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
752 for(
double lat = p_minlat; lat <= p_maxlat; lat += (p_maxlat - p_minlat) / 10.0) {
753 if (SetUniversalGround(lat, 180.0)) {
754 if (Sample() >= 0.5 && Line() >= 0.5 &&
755 Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
756 p_minlon180 = -180.0;
771 if (fabs(fmod(minX, pixelResolution)) > 1.0e-6) {
772 if (pixelResolution - fabs(fmod(minX, pixelResolution)) > 1.0e-6) {
773 double sampleOffset = floor(minX / pixelResolution);
774 minX = sampleOffset * pixelResolution;
779 if (maxX < minX + pixelResolution) {
780 maxX = minX + pixelResolution;
782 if (fabs(fmod(maxY, pixelResolution)) > 1.0e-6) {
783 if (pixelResolution - fabs(fmod(maxY, pixelResolution)) > 1.0e-6) {
784 double lineOffset = -1.0 * ceil(maxY / pixelResolution);
785 maxY = -1.0 * lineOffset * pixelResolution;
790 if (minY > maxY - pixelResolution) {
791 minY = maxY - pixelResolution;
795 samples = (int)((maxX - minX) / pixelResolution + 0.5);
796 lines = (int)((maxY - minY) / pixelResolution + 0.5);
799 double upperLeftX = minX;
803 double upperLeftY = maxY;
809 (QString) mapGroup[
"PixelResolution"],
810 "meters/pixel"), Isis::Pvl::Replace);
813 (QString) mapGroup[
"Scale"],
814 "pixels/degree"), Isis::Pvl::Replace);
817 (QString) mapGroup[
"UpperLeftCornerX"],
818 "meters"), Isis::Pvl::Replace);
821 (QString) mapGroup[
"UpperLeftCornerY"],
822 "meters"), Isis::Pvl::Replace);
825 (QString) mapGroup[
"EquatorialRadius"],
826 "meters"), Isis::Pvl::Replace);
829 (QString) mapGroup[
"PolarRadius"],
830 "meters"), Isis::Pvl::Replace);
840 QString msg =
"Unable to create projection";
873 int &samples,
int &lines,
Camera &cam) {
883 double scale, pixelResolution;
886 pixelResolution = mapGroup[
"PixelResolution"];
887 scale = (2.0 *
Isis::PI * localRadius) / (360.0 * pixelResolution);
894 scale = mapGroup[
"Scale"];
895 pixelResolution = (2.0 *
Isis::PI * localRadius) / (360.0 * scale);
899 "meters/pixel"), Isis::Pvl::Replace);
905 double minX = DBL_MAX;
906 double maxX = -DBL_MAX;
907 double minY = DBL_MAX;
908 double maxY = -DBL_MAX;
911 int eband = cam.
Bands();
913 for(
int band = 1; band <= eband; band++) {
917 for(
int line = 0; line <= cam.
Lines(); line++) {
921 for(samp = 0; samp <= cam.
Samples(); samp++) {
922 if (cam.
SetImage((
double)samp + 0.5, (
double)line + 0.5)) {
931 if ((line != 0) && (line != cam.
Lines()))
break;
938 for(samp = cam.
Samples(); samp >= 0; samp--) {
939 if (cam.
SetImage((
double)samp + 0.5, (
double)line + 0.5)) {
959 for(
double rad = p_minRadius; rad <= p_maxRadius; rad += (p_maxRadius - p_minRadius) / 10.0) {
960 if (SetUniversalGround(rad, 0.0)) {
961 if (Sample() >= 0.5 && Line() >= 0.5 &&
962 Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
973 for(
double rad = p_minrad; rad <= p_maxrad; rad += (p_maxrad - p_minrad) / 10.0) {
974 if (SetUniversalGround(rad, 180.0)) {
975 if (Sample() >= 0.5 && Line() >= 0.5 &&
976 Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
992 if (fabs(fmod(minX, pixelResolution)) > 1.0e-6) {
993 if (pixelResolution - fabs(fmod(minX, pixelResolution)) > 1.0e-6) {
994 double sampleOffset = floor(minX / pixelResolution);
995 minX = sampleOffset * pixelResolution;
1000 if (maxX < minX + pixelResolution) {
1001 maxX = minX + pixelResolution;
1004 if (fabs(fmod(maxY, pixelResolution)) > 1.0e-6) {
1005 if (pixelResolution - fabs(fmod(maxY, pixelResolution)) > 1.0e-6) {
1006 double lineOffset = -1.0 * ceil(maxY / pixelResolution);
1007 maxY = -1.0 * lineOffset * pixelResolution;
1012 if (minY > maxY - pixelResolution) {
1013 minY = maxY - pixelResolution;
1017 samples = (int)((maxX - minX) / pixelResolution + 0.5);
1018 lines = (int)((maxY - minY) / pixelResolution + 0.5);
1021 double upperLeftX = minX;
1023 Isis::Pvl::Replace);
1025 double upperLeftY = maxY;
1027 Isis::Pvl::Replace);
1031 (QString) mapGroup[
"PixelResolution"],
1032 "meters/pixel"), Isis::Pvl::Replace);
1035 (QString) mapGroup[
"Scale"],
1036 "pixels/degree"), Isis::Pvl::Replace);
1039 (QString) mapGroup[
"UpperLeftCornerX"],
1040 "meters"), Isis::Pvl::Replace);
1043 (QString) mapGroup[
"UpperLeftCornerY"],
1044 "meters"), Isis::Pvl::Replace);
1054 QString msg =
"Unable to create projection";
1055 if (label.
fileName() !=
"") msg +=
" from file [" + label.
fileName() +
"]";
1100 double pixelResolution = mapGroup[
"PixelResolution"];
1103 double upperLeftX = mapGroup[
"UpperLeftCornerX"];
1104 double upperLeftY = mapGroup[
"UpperLeftCornerY"];
1117 QString msg =
"Unable to initialize cube projection";
1118 if (label.
fileName() !=
"") msg +=
" from file [" + label.
fileName() +
"]";
1139 double pixelResolution = mapGroup[
"PixelResolution"];
1142 double upperLeftX = mapGroup[
"UpperLeftCornerX"];
1143 double upperLeftY = mapGroup[
"UpperLeftCornerY"];
1156 QString msg =
"Unable to initialize cube projection";
1157 if (label.
fileName() !=
"") msg +=
" from file [" + label.
fileName() +
"]";
virtual double Line() const
Returns the current line number.
int Lines() const
Returns the number of lines in the image.
virtual double Sample() const
Returns the current sample number.
virtual bool SetImage(const double sample, const double line)
Sets the sample/line values of the image to get the lat/lon values.
virtual bool SetUniversalGround(const double latitude, const double longitude)
Sets the lat/lon values to get the sample/line values.
virtual bool IsBandIndependent()
Virtual method that checks if the band is independent.
int Samples() const
Returns the number of samples in the image.
virtual void SetBand(const int band)
Virtual method that sets the band number.
int Bands() const
Returns the number of bands in the image.
IO Handler for Isis Cubes.
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Displacement is a signed length, usually in meters.
@ Meters
The distance is being specified in meters.
double meters() const
Get the distance in meters.
File name manipulation and expansion.
bool fileExists() const
Returns true if the file exists; false otherwise.
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
@ Unknown
A type of error that cannot be classified as any of the other error types.
@ Io
A type of error that occurred when performing an actual I/O operation.
void append(const IException &exceptionSource)
Appends the given exception (and its list of previous exceptions) to this exception's causational exc...
Loads plugins from a shared library.
static Isis::Projection * CreateFromCube(Isis::Cube &cube)
This method is a helper method.
static Isis::Projection * RingsCreate(Isis::Pvl &label, bool allowDefaults=false)
This method returns a pointer to a RingPlaneProjection object.
static Isis::Projection * Create(Isis::Pvl &label, bool allowDefaults=false)
This method returns a pointer to a Projection object.
static Isis::Projection * RingsCreateForCube(Isis::Pvl &label, int &samples, int &lines, bool sizeMatch)
This method creates a projection for a cube to a ring plane given a label.
static Isis::Projection * RingsCreateFromCube(Isis::Cube &cube)
This method is a helper method.
static Isis::Projection * CreateForCube(Isis::Pvl &label, int &ns, int &nl, bool sizeMatch=true)
This method creates a map projection for a cube given a label.
Base class for Map Projections.
void SetWorldMapper(WorldMapper *mapper)
If desired the programmer can use this method to set a world mapper to be used in the SetWorld,...
double XCoord() const
This returns the projection X provided SetGround, SetCoordinate, SetUniversalGround,...
virtual bool HasGroundRange() const
This indicates if the longitude direction type is positive west (as opposed to postive east).
void SetUpperLeftCorner(const Displacement &x, const Displacement &y)
This method is used to find the XY range for oblique aspect projections (non-polar projections) by "w...
double YCoord() const
This returns the projection Y provided SetGround, SetCoordinate, SetUniversalGround,...
bool IsGood() const
This indicates if the last invocation of SetGround, SetCoordinate, SetUniversalGround,...
QString fileName() const
Returns the filename used to initialise the Pvl object.
void addKeyword(const PvlKeyword &keyword, const InsertMode mode=Append)
Add a keyword to the container.
Contains multiple PvlContainers.
Container for cube-like labels.
A single keyword-value pair.
bool hasObject(const QString &name) const
Returns a boolean value based on whether the object exists in the current PvlObject or not.
@ Traverse
Search child objects.
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Base class for Map Projections of plane shapes.
virtual double TrueScaleRingRadius() const
This method returns the radius of true scale.
virtual bool XYRange(double &minX, double &maxX, double &minY, double &maxY)
This method is used to determine the x/y range which completely covers the area of interest specified...
virtual bool SetGround(const double ringRadius, const double ringLongitude)
This method is used to set the ring radius/longitude (assumed to be of the correct LatitudeType,...
virtual double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
virtual double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Distance LocalRadius() const
Returns the local radius at the intersection point.
Base class for Map TProjections.
virtual bool XYRange(double &minX, double &maxX, double &minY, double &maxY)
This method is used to determine the x/y range which completely covers the area of interest specified...
double LocalRadius(double lat) const
This method returns the local radius in meters at the specified latitude position.
virtual bool SetUniversalGround(const double lat, const double lon)
This method is used to set the latitude/longitude which must be Planetocentric (latitude) and Positiv...
virtual double TrueScaleLatitude() const
This method returns the latitude of true scale.
This is free and unencumbered software released into the public domain.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
const double Null
Value for an Isis Null pixel.
const double PI
The mathematical constant PI.
Namespace for the standard library.