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)) {
 
  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;
 
 
Defines an angle and provides unit conversions.
 
double radians() const
Convert an angle to a double.
 
double degrees() const
Get the angle in units of Degrees.
 
@ 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.
 
A single keyword-value pair.
 
Contains Pvl Groups and Pvl Objects.
 
Base class for Map TProjections.
 
double LocalRadius(double lat) const
This method returns the local radius in meters at the specified latitude position.
 
virtual bool SetCoordinate(const double x, const double y)
This method is used to set the projection x/y.
 
virtual double Latitude() const
This returns a latitude with correct latitude type as specified in the label object.
 
bool Has360Domain() const
This indicates if the longitude domain is 0 to 360 (as opposed to -180 to 180).
 
virtual double Longitude() const
This returns a longitude with correct longitude direction and domain as specified in the label object...
 
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.