/**************************************************************************** * * (c) 2009-2016 QGROUNDCONTROL PROJECT * * QGroundControl is licensed according to the terms in the file * COPYING.md in the root of the source code directory. * ****************************************************************************/ #include "TransectStyleComplexItem.h" #include "JsonHelper.h" #include "MissionController.h" #include "QGCGeo.h" #include "QGroundControlQmlGlobal.h" #include "QGCQGeoCoordinate.h" #include "SettingsManager.h" #include "AppSettings.h" #include "QGCQGeoCoordinate.h" #include QGC_LOGGING_CATEGORY(TransectStyleComplexItemLog, "TransectStyleComplexItemLog") const char* TransectStyleComplexItem::turnAroundDistanceName = "TurnAroundDistance"; const char* TransectStyleComplexItem::turnAroundDistanceMultiRotorName = "TurnAroundDistanceMultiRotor"; const char* TransectStyleComplexItem::cameraTriggerInTurnAroundName = "CameraTriggerInTurnAround"; const char* TransectStyleComplexItem::hoverAndCaptureName = "HoverAndCapture"; const char* TransectStyleComplexItem::refly90DegreesName = "Refly90Degrees"; const char* TransectStyleComplexItem::_jsonCameraCalcKey = "CameraCalc"; TransectStyleComplexItem::TransectStyleComplexItem(Vehicle* vehicle, QString settingsGroup, QObject* parent) : ComplexMissionItem (vehicle, parent) , _settingsGroup (settingsGroup) , _sequenceNumber (0) , _dirty (false) , _ignoreRecalc (false) , _scanDistance (0.0) , _cameraShots (0) , _cameraMinTriggerInterval (0) , _cameraCalc (vehicle) , _metaDataMap (FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/TransectStyle.SettingsGroup.json"), this)) , _turnAroundDistanceFact (_settingsGroup, _metaDataMap[_vehicle->multiRotor() ? turnAroundDistanceMultiRotorName : turnAroundDistanceName]) , _cameraTriggerInTurnAroundFact(_settingsGroup, _metaDataMap[cameraTriggerInTurnAroundName]) , _hoverAndCaptureFact (_settingsGroup, _metaDataMap[hoverAndCaptureName]) , _refly90DegreesFact (_settingsGroup, _metaDataMap[refly90DegreesName]) { connect(this, &TransectStyleComplexItem::altitudeRelativeChanged, this, &TransectStyleComplexItem::_setDirty); connect(this, &TransectStyleComplexItem::altitudeRelativeChanged, this, &TransectStyleComplexItem::coordinateHasRelativeAltitudeChanged); connect(this, &TransectStyleComplexItem::altitudeRelativeChanged, this, &TransectStyleComplexItem::exitCoordinateHasRelativeAltitudeChanged); connect(_cameraCalc.adjustedFootprintSide(), &Fact::valueChanged, this, &TransectStyleComplexItem::_rebuildTransects); connect(_cameraCalc.adjustedFootprintSide(), &Fact::valueChanged, this, &TransectStyleComplexItem::_signalLastSequenceNumberChanged); connect(&_turnAroundDistanceFact, &Fact::valueChanged, this, &TransectStyleComplexItem::_rebuildTransects); connect(&_surveyAreaPolygon, &QGCMapPolygon::pathChanged, this, &TransectStyleComplexItem::coveredAreaChanged); connect(this, &TransectStyleComplexItem::transectPointsChanged, this, &TransectStyleComplexItem::complexDistanceChanged); connect(this, &TransectStyleComplexItem::transectPointsChanged, this, &TransectStyleComplexItem::greatestDistanceToChanged); } void TransectStyleComplexItem::_setScanDistance(double scanDistance) { if (!qFuzzyCompare(_scanDistance, scanDistance)) { _scanDistance = scanDistance; emit complexDistanceChanged(); } } void TransectStyleComplexItem::_setCameraShots(int cameraShots) { if (_cameraShots != cameraShots) { _cameraShots = cameraShots; emit cameraShotsChanged(); } } void TransectStyleComplexItem::setDirty(bool dirty) { if (_dirty != dirty) { _dirty = dirty; emit dirtyChanged(_dirty); } } void TransectStyleComplexItem::_save(QJsonObject& complexObject) { complexObject[turnAroundDistanceName] = _turnAroundDistanceFact.rawValue().toDouble(); complexObject[cameraTriggerInTurnAroundName] = _cameraTriggerInTurnAroundFact.rawValue().toBool(); complexObject[hoverAndCaptureName] = _hoverAndCaptureFact.rawValue().toBool(); complexObject[refly90DegreesName] = _refly90DegreesFact.rawValue().toBool(); QJsonObject cameraCalcObject; _cameraCalc.save(cameraCalcObject); complexObject[_jsonCameraCalcKey] = cameraCalcObject; } void TransectStyleComplexItem::setSequenceNumber(int sequenceNumber) { if (_sequenceNumber != sequenceNumber) { _sequenceNumber = sequenceNumber; emit sequenceNumberChanged(sequenceNumber); emit lastSequenceNumberChanged(lastSequenceNumber()); } } bool TransectStyleComplexItem::_load(const QJsonObject& complexObject, QString& errorString) { QList keyInfoList = { { turnAroundDistanceName, QJsonValue::Double, true }, { cameraTriggerInTurnAroundName, QJsonValue::Bool, true }, { hoverAndCaptureName, QJsonValue::Bool, true }, { refly90DegreesName, QJsonValue::Bool, true }, { _jsonCameraCalcKey, QJsonValue::Object, true }, }; if (!JsonHelper::validateKeys(complexObject, keyInfoList, errorString)) { return false; } if (!_cameraCalc.load(complexObject[_jsonCameraCalcKey].toObject(), errorString)) { return false; } _turnAroundDistanceFact.setRawValue (complexObject[turnAroundDistanceName].toDouble()); _cameraTriggerInTurnAroundFact.setRawValue (complexObject[cameraTriggerInTurnAroundName].toBool()); _hoverAndCaptureFact.setRawValue (complexObject[hoverAndCaptureName].toBool()); _hoverAndCaptureFact.setRawValue (complexObject[refly90DegreesName].toBool()); return true; } double TransectStyleComplexItem::greatestDistanceTo(const QGeoCoordinate &other) const { double greatestDistance = 0.0; for (int i=0; i<_transectPoints.count(); i++) { QGeoCoordinate vertex = _transectPoints[i].value(); double distance = vertex.distanceTo(other); if (distance > greatestDistance) { greatestDistance = distance; } } return greatestDistance; } void TransectStyleComplexItem::setMissionFlightStatus(MissionController::MissionFlightStatus_t& missionFlightStatus) { ComplexMissionItem::setMissionFlightStatus(missionFlightStatus); if (!qFuzzyCompare(_cruiseSpeed, missionFlightStatus.vehicleSpeed)) { _cruiseSpeed = missionFlightStatus.vehicleSpeed; emit timeBetweenShotsChanged(); } } void TransectStyleComplexItem::_setDirty(void) { setDirty(true); } void TransectStyleComplexItem::applyNewAltitude(double newAltitude) { Q_UNUSED(newAltitude); // FIXME: NYI //_altitudeFact.setRawValue(newAltitude); } double TransectStyleComplexItem::timeBetweenShots(void) { return _cruiseSpeed == 0 ? 0 : _cameraCalc.adjustedFootprintSide()->rawValue().toDouble() / _cruiseSpeed; } void TransectStyleComplexItem::_updateCoordinateAltitudes(void) { emit coordinateChanged(coordinate()); emit exitCoordinateChanged(exitCoordinate()); } void TransectStyleComplexItem::_signalLastSequenceNumberChanged(void) { emit lastSequenceNumberChanged(lastSequenceNumber()); } double TransectStyleComplexItem::coveredArea(void) const { return _surveyAreaPolygon.area(); } bool TransectStyleComplexItem::_hasTurnaround(void) const { return _turnaroundDistance() > 0; } double TransectStyleComplexItem::_turnaroundDistance(void) const { return _turnAroundDistanceFact.rawValue().toDouble(); } bool TransectStyleComplexItem::hoverAndCaptureAllowed(void) const { return _vehicle->multiRotor() || _vehicle->vtol(); }