#include "CircularSurveyComplexItem.h" const char* CircularSurveyComplexItem::settingsGroup = "Survey"; CircularSurveyComplexItem::CircularSurveyComplexItem(Vehicle *vehicle, bool flyView, const QString &kmlOrShpFile, QObject *parent) : TransectStyleComplexItem (vehicle, flyView, settingsGroup, parent) , _referencePoint(QGeoCoordinate(47.770859, 16.531076,0)) { } void CircularSurveyComplexItem::setRefPoint(const QGeoCoordinate &refPt) { if (refPt != _referencePoint){ _referencePoint = refPt; emit refPointChanged(); } } QGeoCoordinate CircularSurveyComplexItem::refPoint() const { return _referencePoint; } bool CircularSurveyComplexItem::load(const QJsonObject &complexObject, int sequenceNumber, QString &errorString) { return false; } void CircularSurveyComplexItem::save(QJsonArray &planItems) { } void CircularSurveyComplexItem::appendMissionItems(QList &items, QObject *missionItemParent) { } void CircularSurveyComplexItem::applyNewAltitude(double newAltitude) { } double CircularSurveyComplexItem::timeBetweenShots() { return 1; } bool CircularSurveyComplexItem::readyForSave() const { return false; } double CircularSurveyComplexItem::additionalTimeDelay() const { return 0; } void CircularSurveyComplexItem::_rebuildTransectsPhase1() { using namespace GeoUtilities; using namespace PolygonCalculus; using namespace PlanimetryCalculus; if ( _surveyAreaPolygon.count() < 3) return; _transects.clear(); QPolygonF surveyPolygon = toQPolygonF(toCartesian2D(_surveyAreaPolygon.coordinateList(), _referencePoint)); QVector distances; for (const QPointF &p : surveyPolygon) distances.append(norm(p)); double dalpha = 0.5/180*M_PI; // radiants double dr = 30; // meter double r_min = dr; // meter double r_max = (*std::max_element(distances.begin(), distances.end())); // meter QPointF origin(0, 0); IntersectType type; if (!contains(surveyPolygon, origin, type)) { QVector angles; for (const QPointF &p : surveyPolygon) angles.append(truncateAngle(angle(p))); // determine r_min by successive approximation double r = r_max; while ( r > r_min) { Circle circle(r, origin); if (!intersects(circle, surveyPolygon)) { r_min = r; break; } r -= dr; } } qWarning("r_min, r_max:"); qWarning() << r_min; qWarning() << r_max; QList convexPolygons; decomposeToConvex(surveyPolygon, convexPolygons); QList> fullPath; for (int i = 0; i < convexPolygons.size(); i++){ const QPolygonF &polygon = convexPolygons[i]; double r = r_min; QList> currPolyPath; bool currentPolyPathUpdated = false; int direction = 1; while (r < r_max) { Circle circle(r, origin); QList intersectPoints; QList typeList; if (intersects(circle, polygon, intersectPoints, typeList)) { if (intersectPoints.size() >= 1) { // continue here QPointF p1 = intersectPoints.first()[0]; QPointF p2 = intersectPoints.first()[1]; double beta1 = angle(p1); double beta2 = angle(p2); double alpha1 = fmin(beta1, beta2); double alpha2 = fmax(beta1, beta2); QList sector = circle.approximateSektor(direction*dalpha, alpha1, alpha2); QList sectorPath; for ( const QPointF &p : sector) { if (polygon.containsPoint(p, Qt::FillRule::OddEvenFill)) sectorPath.append(p); } if (sectorPath.size() > 0 ) { if (direction == -1){ direction = 1; } else direction = -1; // use shortestPath() here if necessary, could be a problem if dr >> currPolyPath.append(sectorPath); currentPolyPathUpdated = true; } } } r += dr; } if (currentPolyPathUpdated) { if (fullPath.size() > 1) { QPointF start = fullPath.last().last(); QPointF end = currPolyPath.last().first(); QList path; if(!shortestPath(surveyPolygon, start, end, path)) return; path.removeFirst(); path.removeLast(); currPolyPath.last().append(path); } fullPath.append(currPolyPath); } } for ( const QList &transect : fullPath) { QList geoPath = toGeo(transect, _referencePoint); QList transectList; for ( const QGeoCoordinate &coordinate : geoPath) { CoordInfo_t coordinfo = {coordinate, CoordTypeInterior}; transectList.append(coordinfo); } _transects.append(transectList); } } void CircularSurveyComplexItem::_recalcComplexDistance() { } void CircularSurveyComplexItem::_recalcCameraShots() { } /*! \class CircularSurveyComplexItem \inmodule Wima \brief The \c CircularSurveyComplexItem class provides a survey mission item with circular transects around a point of interest. CircularSurveyComplexItem class provides a survey mission item with circular transects around a point of interest. Within the \c Wima module it's used to scan a defined area with constant angle (circular transects) to the base station (point of interest). \sa WimaArea */