1 #include "MosaicAreaTool.h"
7 #include <QDoubleValidator>
8 #include <QGraphicsEllipseItem>
9 #include <QGraphicsScene>
10 #include <QGridLayout>
14 #include <QMessageBox>
15 #include <QPushButton>
20 #include "FindSpotGraphicsItem.h"
21 #include "MosaicGraphicsView.h"
22 #include "MosaicSceneWidget.h"
23 #include "Projection.h"
24 #include "TProjection.h"
25 #include "PvlKeyword.h"
26 #include "PvlObject.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)) {
352 if(m_drawBox != NULL) {
370 void MosaicAreaTool::clearBox() {
372 getWidget()->getScene()->removeItem(m_box);
389 Distance distanceFromCenter = size / 2.0;
390 QRectF latLonBoundingBox;
398 bool longitudeWraps =
false;
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) /
449 if(valueToASin < -1 || valueToASin > 1)
450 longitudeWraps =
true;
453 if (longitudeWraps) {
455 latLonBoundingBox.setLeft( 0 );
456 latLonBoundingBox.setRight( 360 );
459 latLonBoundingBox.setLeft( -180 );
460 latLonBoundingBox.setRight( 180 );
465 asin( sin(distanceFromCenter / radius) /
468 latLonBoundingBox.setLeft( (centerLon - deltaLon).degrees() );
469 latLonBoundingBox.setRight( (centerLon + deltaLon).degrees() );
473 return latLonBoundingBox;