Skip to content
CircularSurvey.cc 44 KiB
Newer Older
#include "CircularSurvey.h"
#include "RoutingThread.h"
#include "JsonHelper.h"
#include "QGCApplication.h"
#include "QGCLoggingCategory.h"
#include "snake.h"
#define CLIPPER_SCALE 1000000
#include "clipper/clipper.hpp"

#include "Geometry/GenericCircle.h"
#include "Snake/SnakeTile.h"

#include <boost/units/io.hpp>
#include <boost/units/systems/si.hpp>

QGC_LOGGING_CATEGORY(CircularSurveyLog, "CircularSurveyLog")

using namespace ClipperLib;
template <> auto get<0>(const IntPoint &p) { return p.X; }
template <> auto get<1>(const IntPoint &p) { return p.Y; }

template <class Functor> class CommandRAII {
public:
  CommandRAII(Functor f) : fun(f) {}
  ~CommandRAII() { fun(); }

private:
  Functor fun;
};

Valentin Platzgummer's avatar
Valentin Platzgummer committed
template <typename T>
constexpr typename std::underlying_type<T>::type integral(T value) {
  return static_cast<typename std::underlying_type<T>::type>(value);
}

Valentin Platzgummer's avatar
Valentin Platzgummer committed
bool circularTransects(const snake::FPolygon &polygon,
                       const std::vector<snake::FPolygon> &tiles,
                       snake::Length deltaR, snake::Angle deltaAlpha,
                       snake::Length minLength, snake::Transects &transects);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
bool linearTransects(const snake::FPolygon &polygon,
                     const std::vector<snake::FPolygon> &tiles,
                     snake::Length distance, snake::Angle angle,
                     snake::Length minLength, snake::Transects &transects);
const char *CircularSurvey::settingsGroup = "CircularSurvey";
Valentin Platzgummer's avatar
Valentin Platzgummer committed
const char *CircularSurvey::transectDistanceName = "TransectDistance";
const char *CircularSurvey::alphaName = "Alpha";
const char *CircularSurvey::minLengthName = "MinLength";
const char *CircularSurvey::typeName = "Type";
const char *CircularSurvey::CircularSurveyName = "CircularSurvey";
const char *CircularSurvey::refPointLatitudeName = "ReferencePointLat";
const char *CircularSurvey::refPointLongitudeName = "ReferencePointLong";
const char *CircularSurvey::refPointAltitudeName = "ReferencePointAlt";
const char *CircularSurvey::variantName = "Variant";
const char *CircularSurvey::numRunsName = "NumRuns";
const char *CircularSurvey::runName = "Run";

CircularSurvey::CircularSurvey(Vehicle *vehicle, bool flyView,
                               const QString &kmlOrShpFile, QObject *parent)
    : TransectStyleComplexItem(vehicle, flyView, settingsGroup, parent),
      _referencePoint(QGeoCoordinate(0, 0, 0)),
      _metaDataMap(FactMetaData::createMapFromJsonFile(
          QStringLiteral(":/json/CircularSurvey.SettingsGroup.json"), this)),
Valentin Platzgummer's avatar
Valentin Platzgummer committed
      _transectDistance(settingsGroup, _metaDataMap[transectDistanceName]),
      _alpha(settingsGroup, _metaDataMap[alphaName]),
      _minLength(settingsGroup, _metaDataMap[minLengthName]),
      _type(settingsGroup, _metaDataMap[typeName]),
      _variant(settingsGroup, _metaDataMap[variantName]),
      _numRuns(settingsGroup, _metaDataMap[numRunsName]),
      _run(settingsGroup, _metaDataMap[runName]),
      _pWorker(std::make_unique<RoutingThread>()), _state(STATE::DEFAULT),
      _hidePolygon(false) {
  Q_UNUSED(kmlOrShpFile)
  _editorQml = "qrc:/qml/CircularSurveyItemEditor.qml";

  // Connect facts.
Valentin Platzgummer's avatar
Valentin Platzgummer committed
  connect(&_transectDistance, &Fact::valueChanged, this,
          &CircularSurvey::_rebuildTransects);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
  connect(&_alpha, &Fact::valueChanged, this,
          &CircularSurvey::_rebuildTransects);
  connect(&_minLength, &Fact::valueChanged, this,
          &CircularSurvey::_rebuildTransects);
  connect(this, &CircularSurvey::refPointChanged, this,
          &CircularSurvey::_rebuildTransects);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
  connect(this, &CircularSurvey::depotChanged, this,
          &CircularSurvey::_rebuildTransects);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
  connect(&this->_type, &Fact::rawValueChanged, this,
          &CircularSurvey::_rebuildTransects);
  connect(&this->_variant, &Fact::rawValueChanged, this,
          &CircularSurvey::_changeVariant);
  connect(&this->_run, &Fact::rawValueChanged, this,
          &CircularSurvey::_changeRun);
  connect(&this->_numRuns, &Fact::rawValueChanged, this,
          &CircularSurvey::_rebuildTransects);

  // Areas.
  connect(this, &CircularSurvey::measurementAreaChanged, this,
          &CircularSurvey::_rebuildTransects);
  connect(this, &CircularSurvey::joinedAreaChanged, this,
          &CircularSurvey::_rebuildTransects);

  // Connect worker.
  connect(this->_pWorker.get(), &RoutingThread::result, this,
          &CircularSurvey::_setTransects);
  connect(this->_pWorker.get(), &RoutingThread::calculatingChanged, this,
          &CircularSurvey::calculatingChanged);
  this->_transectsDirty = true;

  // Altitude
  connect(&_cameraCalc, &CameraCalc::distanceToSurfaceRelativeChanged, this,
          &CircularSurvey::coordinateHasRelativeAltitudeChanged);
  connect(&_cameraCalc, &CameraCalc::distanceToSurfaceRelativeChanged, this,
          &CircularSurvey::exitCoordinateHasRelativeAltitudeChanged);
CircularSurvey::~CircularSurvey() {}

void CircularSurvey::resetReference() { setRefPoint(_mArea.center()); }
void CircularSurvey::reverse() {
  this->_state = STATE::REVERSE;
  this->_rebuildTransects();
}

void CircularSurvey::setRefPoint(const QGeoCoordinate &refPt) {
  if (refPt != _referencePoint) {
    _referencePoint = refPt;
Valentin Platzgummer's avatar
Valentin Platzgummer committed
    _referencePoint.setAltitude(0);

    emit refPointChanged();
  }
}

QGeoCoordinate CircularSurvey::refPoint() const { return _referencePoint; }

Valentin Platzgummer's avatar
Valentin Platzgummer committed
Fact *CircularSurvey::transectDistance() { return &_transectDistance; }
Valentin Platzgummer's avatar
Valentin Platzgummer committed
Fact *CircularSurvey::alpha() { return &_alpha; }
Valentin Platzgummer's avatar
Valentin Platzgummer committed
bool CircularSurvey::hidePolygon() const { return _hidePolygon; }

QList<QString> CircularSurvey::variantNames() const { return _variantNames; }

QList<QString> CircularSurvey::runNames() const { return _runNames; }

Valentin Platzgummer's avatar
Valentin Platzgummer committed
QGeoCoordinate CircularSurvey::depot() const { return this->_depot; }

Valentin Platzgummer's avatar
Valentin Platzgummer committed
const QList<QList<QGeoCoordinate>> &CircularSurvey::rawTransects() const {
  return this->_rawTransects;
}

Valentin Platzgummer's avatar
Valentin Platzgummer committed
void CircularSurvey::setHidePolygon(bool hide) {
  if (this->_hidePolygon != hide) {
    this->_hidePolygon = hide;
    emit hidePolygonChanged();
  }
}

void CircularSurvey::setMeasurementArea(const WimaMeasurementAreaData &mArea) {
  if (this->_mArea != mArea) {
    this->_mArea = mArea;
    emit measurementAreaChanged();
  }
}

void CircularSurvey::setJoinedArea(const WimaJoinedAreaData &jArea) {
  if (this->_jArea != jArea) {
    this->_jArea = jArea;
    emit joinedAreaChanged();
void CircularSurvey::setMeasurementArea(const WimaMeasurementArea &mArea) {
  if (this->_mArea != mArea) {
    this->_mArea = mArea;
    emit measurementAreaChanged();
  }
}

void CircularSurvey::setJoinedArea(const WimaJoinedArea &jArea) {
  if (this->_jArea != jArea) {
    this->_jArea = jArea;
    emit joinedAreaChanged();
Valentin Platzgummer's avatar
Valentin Platzgummer committed
void CircularSurvey::setDepot(const QGeoCoordinate &depot) {
  if (this->_depot.latitude() != depot.latitude() ||
      this->_depot.longitude() != depot.longitude()) {
    this->_depot = depot;
    this->_depot.setAltitude(0);
    emit depotChanged();
  }
}

bool CircularSurvey::load(const QJsonObject &complexObject, int sequenceNumber,
Loading
Loading full blame...