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" 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;
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) /
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) /
468 latLonBoundingBox.setLeft( (centerLon - deltaLon).degrees() );
469 latLonBoundingBox.setRight( (centerLon + deltaLon).degrees() );
473 return latLonBoundingBox;
double radians() const
Convert an angle to a double.
Base class for Map TProjections.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
Distance measurement, usually in meters.
Base class for Map Projections.
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
double Longitude() const
This returns a longitude with correct longitude direction and domain as specified in the label object...
A single keyword-value pair.
double ToDouble(const T &value)
Helper function to convert values to doubles.
Defines an angle and provides unit conversions.
virtual bool SetCoordinate(const double x, const double y)
This method is used to set the projection x/y.
bool toBool(const QString &string)
Global function to convert from a string to a boolean.
double Latitude() const
This returns a latitude with correct latitude type as specified in the label object.
Namespace for ISIS/Bullet specific routines.
The distance is being specified in meters.
Radians are generally used in mathematical equations, 0-2*PI is one circle, however these are more di...
Contains Pvl Groups and Pvl Objects.
ProjectionType
This enum defines the subclasses of Projection supported in Isis.
These projections are used to map triaxial and irregular-shaped bodies.