1#include "MosaicAreaTool.h"
7#include <QDoubleValidator>
8#include <QGraphicsEllipseItem>
9#include <QGraphicsScene>
20#include "FindSpotGraphicsItem.h"
21#include "MosaicGraphicsView.h"
22#include "MosaicSceneWidget.h"
23#include "Projection.h"
24#include "TProjection.h"
25#include "PvlKeyword.h"
43 connect(scene, SIGNAL(projectionChanged(
Projection *)),
44 this, SLOT(userChangedBox()));
52 void MosaicAreaTool::userChangedBox() {
53 bool latValid =
false;
54 bool lonValid =
false;
55 bool areaValid =
false;
64 if(latitude !=
"Null" && latitude !=
"") {
66 QValidator::State validLat =
68 if(validLat != QValidator::Acceptable) {
69 QMessageBox::warning(getWidget(),
"Error",
70 "Latitude value must be in the range -90 to 90",
71 QMessageBox::Ok, QMessageBox::NoButton,
72 QMessageBox::NoButton);
81 if(longitude !=
"Null" && longitude !=
"" && latValid) {
83 QValidator::State validLon =
85 if(validLon != QValidator::Acceptable) {
86 QMessageBox::warning(getWidget(),
"Error",
87 "Longitude value invalid",
88 QMessageBox::Ok, QMessageBox::NoButton,
89 QMessageBox::NoButton);
97 if(areaString !=
"Null" && areaString !=
"" && latValid && lonValid) {
99 QValidator::State validArea =
101 if(validArea != QValidator::Acceptable) {
102 QMessageBox::warning(getWidget(),
"Error",
103 "Area value invalid",
104 QMessageBox::Ok, QMessageBox::NoButton,
105 QMessageBox::NoButton);
113 if(latValid && lonValid && areaValid) {
114 double lat = IString(latitude.toStdString()).ToDouble();
115 double lon = IString(longitude.toStdString()).ToDouble();
116 double area = IString(areaString.toStdString()).ToDouble();
118 Projection *projection = getWidget()->getProjection();
122 TProjection * tproj = (TProjection *) projection;
123 if (tproj->SetGround(lat, lon)) {
124 QPointF scenePos(projection->XCoord(), -1 * projection->YCoord());
125 QRectF sceneRect(getWidget()->getView()->sceneRect());
127 if(sceneRect.contains(scenePos)) {
137 double xStep = latLonRange.width() / 100.0;
138 double yStep = latLonRange.height() / 100.0;
140 bool hasPole = (latLonRange.top() == -90 ||
141 latLonRange.bottom() == 90);
143 double yPos = latLonRange.top();
145 for(
double xPos = latLonRange.left();
146 xPos <= latLonRange.right();
148 if (tproj->SetGround(yPos, xPos)) {
149 QPointF pos(tproj->XCoord(), -1 * tproj->YCoord());
155 double xPos = latLonRange.right();
156 for (
double yPos = latLonRange.top();
157 !hasPole && yPos <= latLonRange.bottom();
159 if (tproj->SetGround(yPos, xPos)) {
160 QPointF pos(tproj->XCoord(), -1 * tproj->YCoord());
165 yPos = latLonRange.bottom();
167 for (
double xPos = latLonRange.right();
168 xPos >= latLonRange.left();
170 if (tproj->SetGround(yPos, xPos)) {
171 QPointF pos(tproj->XCoord(), -1 * tproj->YCoord());
177 xPos = latLonRange.left();
178 for (
double yPos = latLonRange.bottom();
179 !hasPole && yPos >= latLonRange.top();
181 if (tproj->SetGround(yPos, xPos)) {
182 QPointF pos(tproj->XCoord(), -1 * tproj->YCoord());
187 if (boxPoly.size() > 0) {
188 boxPoly << boxPoly[0];
190 m_box =
new QGraphicsPolygonItem(boxPoly);
191 m_box->setZValue(DBL_MAX);
194 pen.setCosmetic(
true);
197 getWidget()->getScene()->addItem(m_box);
198 getWidget()->getView()->centerOn(scenePos);
202 QString message =
"Lat/Lon not within this view.";
203 QMessageBox::information(getWidget(),
"Cannot Calculate Box",
204 message, QMessageBox::Ok);
222 m_action->setIcon(
getIcon(
"qmos_area.png"));
223 m_action->setToolTip(
"Show Area (a)");
224 m_action->setShortcut(Qt::Key_A);
226 "<b>Function:</b> Draw a box given a distance centered on a "
227 "latitude/longitude.<br><br>"
228 "This tool draws a black square, given an edge length in meters, "
229 "centered on a latitude/longitude point. This box would be a square on "
230 "the surface of the target, and is designed to be modified and warped by "
231 "the current projection."
232 "<p><b>Shortcut:</b> a</p> ";
233 m_action->setWhatsThis(text);
240 m_latLineEdit->setValidator(
new QDoubleValidator(-90.0, 90.0, 99,
this));
249 QLabel *latLabel =
new QLabel(
"Latitude");
250 QLabel *lonLabel =
new QLabel(
"Longitude");
251 QLabel *areaLabel =
new QLabel(
"Size (meters)");
252 areaLabel->setToolTip(
"This is the width and the height of the box");
255 QPushButton *okButton =
new QPushButton(
"Update Box");
256 connect(okButton, SIGNAL(clicked()),
this, SLOT(userChangedBox()));
258 QPushButton *clearButton =
new QPushButton(
"Clear Box");
259 connect(clearButton, SIGNAL(clicked()),
this, SLOT(clearBox()));
262 QHBoxLayout *actionLayout =
new QHBoxLayout();
263 actionLayout->addWidget(latLabel);
265 actionLayout->addWidget(lonLabel);
267 actionLayout->addWidget(areaLabel);
269 actionLayout->addWidget(okButton);
270 actionLayout->addWidget(clearButton);
271 actionLayout->addStretch(1);
272 actionLayout->setMargin(0);
275 toolBarWidget->setLayout(actionLayout);
277 return toolBarWidget;
292 PvlObject MosaicAreaTool::toPvl()
const {
306 void MosaicAreaTool::fromPvl(
const PvlObject &obj) {
307 if(obj.hasKeyword(
"Visible")) {
308 if(obj.hasKeyword(
"Latitude") && obj[
"Latitude"][0] !=
"Null")
311 if(obj.hasKeyword(
"Longitude") && obj[
"Longitude"][0] !=
"Null")
314 if(obj.hasKeyword(
"Area") && obj[
"Area"][0] !=
"Null")
317 if(
toBool(obj[
"Visible"][0]) !=
false) {
324 QString MosaicAreaTool::projectPvlObjectName()
const {
325 return "MosaicAreaTool";
343 void MosaicAreaTool::mouseButtonRelease(QPointF mouseLoc, Qt::MouseButton s) {
347 if(s == Qt::LeftButton) {
350 if(tproj && getWidget()->getView()->sceneRect().contains(mouseLoc)) {
351 if(tproj->SetCoordinate(mouseLoc.x(), -1 * mouseLoc.y())) {
352 if(m_drawBox != NULL) {
356 m_latLineEdit->setText(QString::number(tproj->Latitude(),
'g', 10));
357 m_lonLineEdit->setText(QString::number(tproj->Longitude(),
'g', 10));
370 void MosaicAreaTool::clearBox() {
372 getWidget()->getScene()->removeItem(m_box);
389 Distance distanceFromCenter = size / 2.0;
390 QRectF latLonBoundingBox;
398 bool longitudeWraps =
false;
399 Distance radius(tproj->LocalRadius(centerLat.degrees()),
406 latLonBoundingBox.setTop( (centerLat - deltaLat).degrees() );
408 if (latLonBoundingBox.top() < -90 && centerLatLon.y() != -90) {
411 if (centerLatLon.y() != 90) {
412 qWarning(
"The pole is included in the area but not centered");
413 centerLatLon.setY(-90);
419 else if (centerLatLon.y() == -90) {
420 longitudeWraps =
true;
423 latLonBoundingBox.setBottom( (centerLat + deltaLat).degrees() );
425 if (latLonBoundingBox.bottom() > 90 && centerLatLon.y() != 90) {
428 if (centerLatLon.y() != -90) {
429 qWarning(
"The pole is included in the area but not centered");
430 centerLatLon.setY(90);
436 else if (centerLatLon.y() == 90) {
437 longitudeWraps =
true;
442 asin( sin(centerLat.radians()) /
443 cos( distanceFromCenter / radius ) ),
446 double valueToASin = sin(distanceFromCenter / radius) /
447 cos(widestLat.radians());
449 if(valueToASin < -1 || valueToASin > 1)
450 longitudeWraps =
true;
453 if (longitudeWraps) {
454 if (tproj->Has360Domain()) {
455 latLonBoundingBox.setLeft( 0 );
456 latLonBoundingBox.setRight( 360 );
459 latLonBoundingBox.setLeft( -180 );
460 latLonBoundingBox.setRight( 180 );
465 asin( sin(distanceFromCenter / radius) /
466 cos(widestLat.radians())),
468 latLonBoundingBox.setLeft( (centerLon - deltaLon).degrees() );
469 latLonBoundingBox.setRight( (centerLon + deltaLon).degrees() );
473 return latLonBoundingBox;
Defines an angle and provides unit conversions.
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
@ Radians
Radians are generally used in mathematical equations, 0-2*PI is one circle, however these are more di...
Distance measurement, usually in meters.
@ Meters
The distance is being specified in meters.
Base class for Map Projections.
ProjectionType
This enum defines the subclasses of Projection supported in Isis.
@ Triaxial
These projections are used to map triaxial and irregular-shaped bodies.
ProjectionType projectionType() const
Returns an enum value for the projection type.
A single keyword-value pair.
Contains Pvl Groups and Pvl Objects.
Base class for Map TProjections.
This is free and unencumbered software released into the public domain.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
bool toBool(const QString &string)
Global function to convert from a string to a boolean.