From 20d3523826ce3572bd431a1a6a4f191d954949ce Mon Sep 17 00:00:00 2001 From: Valentin Platzgummer Date: Tue, 28 May 2019 18:12:46 +0200 Subject: [PATCH] about to add poly join fkt --- src/Wima/WimaArea.cc | 177 ++++++++++++++++++++++++++++++++++++++----- src/Wima/WimaArea.h | 43 ++++++++--- 2 files changed, 190 insertions(+), 30 deletions(-) diff --git a/src/Wima/WimaArea.cc b/src/Wima/WimaArea.cc index aff3cb08a..a2a34c3f6 100644 --- a/src/Wima/WimaArea.cc +++ b/src/Wima/WimaArea.cc @@ -8,22 +8,20 @@ WimaArea::WimaArea(QObject *parent) : //qWarning() << "WimaPolygon:: polygon count" << _polygon->count(); } -WimaArea::WimaArea(WimaArea *other, QObject *parent): - QGCMapPolygon (parent) - ,_maxAltitude (30) - ,_wimaVehicle (new WimaVehicle(this)) -{ - if (other != nullptr) { - _maxAltitude = other->maxAltitude(); - _wimaVehicle = other->vehicle(); - setPath (other->path()); - setCenter (other->center()); - setCenterDrag (other->centerDrag()); - setInteractive (other->interactive()); +WimaArea::WimaArea(QGCMapPolygon *other, QObject *parent) + : QGCMapPolygon (other, parent) +{ + WimaArea* wimaPoly = qobject_cast(other); + if (wimaPoly != nullptr) { + _maxAltitude = wimaPoly->maxAltitude(); + _wimaVehicle = wimaPoly->vehicle(); + } else { + _maxAltitude = 30; + _wimaVehicle = new WimaVehicle(this); } - } + WimaArea::~WimaArea() { @@ -110,23 +108,64 @@ QGCMapPolygon* WimaArea::toQGCPolygon(WimaArea *poly) } } -QGCMapPolygon *WimaArea::joinPolygons(QList* polyList) +WimaArea *WimaArea::joinPolygons(QList* polyList) { - return new QGCMapPolygon(this); + return nullptr; } -QGCMapPolygon *WimaArea::joinPolygons(QGCMapPolygon *poly1, QGCMapPolygon *poly2) +WimaArea *WimaArea::joinPolygons(WimaArea *poly1, WimaArea *poly2) { - return new QGCMapPolygon(this); + if (poly1 != nullptr && poly2 != nullptr) { + if (poly1->count() >= 3 && poly2->count() >= 3) { + WimaArea* joinedPolygon = new WimaArea(this); + + poly1->verifyClockwiseWinding(); + poly2->verifyClockwiseWinding(); + + WimaArea* walkerPoly = poly1; // "walk" on this polygon towards higher indices + WimaArea* crossPoly = poly2; // check for crossings with this polygon while "walking" + // and swicht to this polygon on a intersection, + // continue to walk towards higher indices + QGCMapPolyline lineSegment; // segment of walkerPoly, containing only two coordinates + int currentPolyIndex = 0; + do { + QGeoCoordinate currentVertex = walkerPoly->vertexCoordinate(currentPolyIndex);// change req. + QGeoCoordinate nextVertex = walkerPoly->vertexCoordinate(walkerPoly->nextVertexIndex(currentPolyIndex)); + joinedPolygon->appendVertex(currentVertex); + + QGCMapPolyline walkerPolySegment; + walkerPolySegment.appendVertex(currentVertex); + walkerPolySegment.appendVertex(nextVertex); + + QList* intersectionList = intersects(&walkerPolySegment, crossPoly); + + if (intersectionList != nullptr) { + // todo + } else { + return nullptr; + } + + } while (currentPolyIndex != 0 || walkerPoly != poly1); + + return joinedPolygon; + } else { + qWarning("WimaArea::joinPolygons(poly1, poly2): poly->count() < 3"); + return nullptr; + } + + } else { + qWarning("WimaArea::joinPolygons(poly1, poly2): nullptr"); + return nullptr; + } } -bool WimaArea::isDisjunct(QList* polyList) +bool WimaArea::isDisjunct(QList* polyList) { // needs improvement if (polyList != nullptr){ for (int i = 0;i < polyList->size()-1; i++) { - QGCMapPolygon* currPoly = polyList->takeAt(i); + WimaArea* currPoly = polyList->takeAt(i); for (int j = i+1; i < polyList->size(); j++) { if (isDisjunct(currPoly, polyList->takeAt(j))) { return false; @@ -140,7 +179,7 @@ bool WimaArea::isDisjunct(QList* polyList) } } -bool WimaArea::isDisjunct(QGCMapPolygon *poly1, QGCMapPolygon *poly2) +bool WimaArea::isDisjunct(WimaArea *poly1, WimaArea *poly2) { if (poly1 != nullptr && poly2 != nullptr) { QGCMapPolygon* poly1Copy = new QGCMapPolygon(this); @@ -158,4 +197,102 @@ bool WimaArea::isDisjunct(QGCMapPolygon *poly1, QGCMapPolygon *poly2) } } +int WimaArea::nextVertexIndex(int index) +{ + if (index >= 0 && index < count()-1) { + return index + 1; + } else if (index == count()-1) { + return 0; + } else { + qWarning("WimaArea::nextVertexIndex(): Index out of bounds! index:count = %i:%i", index, count()); + return -1; + } +} + +int WimaArea::previousVertexIndex(int index) +{ + if (index > 0 && index < count()) { + return index - 1; + } else if (index == 0) { + return count()-1; + } else { + qWarning("WimaArea::previousVertexIndex(): Index out of bounds! index:count = %i:%i", index, count()); + return -1; + } +} + +QGeoCoordinate* WimaArea::intersects(QGCMapPolyline *geoLine1, QGCMapPolyline *geoLine2) +{ + if (geoLine1 != nullptr && geoLine2 != nullptr) { + if (geoLine1->count() == 2 && geoLine2->count() == 2 ) { + QPointF pt11(0, 0); + + double x, y, z; + QGeoCoordinate origin = geoLine1->vertexCoordinate(0); + convertGeoToNed(geoLine1->vertexCoordinate(1), origin, &x, &y, &z); + QPointF pt12(x, y); + + QLineF kartLine1(pt11, pt12); + + + convertGeoToNed(geoLine2->vertexCoordinate(0), origin, &x, &y, &z); + QPointF pt21(x, y); + + convertGeoToNed(geoLine2->vertexCoordinate(1), origin, &x, &y, &z); + QPointF pt22(x, y); + + QLineF kartLine2(pt21, pt22); + + QPointF intersectionPoint; + if (kartLine1.intersect(kartLine2, &intersectionPoint) != QLineF::NoIntersection) { + QGeoCoordinate* retValue = new QGeoCoordinate(); + convertNedToGeo(intersectionPoint.x(), intersectionPoint.y(), origin.altitude(), origin, retValue); + + return retValue; + } else { + return nullptr; + } + + + } else { + qWarning("WimaArea::intersect(geoLine1, geoLine2): geoLine1->count() != 2 || geoLine2->count() != 2!"); + return nullptr; + } + } else { + qWarning("WimaArea::intersect(geoLine1, geoLine2): geoLine1 == nullptr || geoLine2 == nullptr!"); + return nullptr; + } +} + +QList* WimaArea::intersects(QGCMapPolyline *line, WimaArea *poly) +{ + QList* intersectionList = new QList(); + if (line != nullptr && poly != nullptr) { + if (line->count() == 2 && poly->count() >= 3) { + QVariantList polyPath = poly->path(); + QGeoCoordinate pt1; + QGeoCoordinate pt2; + for (int i = 0; i < poly->count(); i++) { + QGCMapPolyline polySegment; + polySegment.appendVertex(polyPath.takeAt(i).value()); + polySegment.appendVertex(polyPath.takeAt(poly->nextVertexIndex(i)).value()); + + QGeoCoordinate* intersectionPoint = intersects(line, &polySegment); + + if (intersectionPoint != nullptr){ + intersectionList->append(intersectionPoint); + } + } + return intersectionList; + } else { + qWarning("WimaArea::intersects(line, poly): line->count() != 2 || poly->count() < 3"); + return nullptr; + } + + } else { + qWarning("WimaArea::intersects(line, poly): line == nullptr || poly == nullptr!"); + return nullptr; + } +} + diff --git a/src/Wima/WimaArea.h b/src/Wima/WimaArea.h index 87a5a132f..8ea2d78b8 100644 --- a/src/Wima/WimaArea.h +++ b/src/Wima/WimaArea.h @@ -1,16 +1,21 @@ #pragma once #include "QGCMapPolygon.h" +#include "QGCMapPolyline.h" #include "Vehicle.h" #include "qobject.h" #include "WimaVehicle.h" +#include "WimaArea.h" +#include +#include +#include "QGCGeo.h" class WimaArea : public QGCMapPolygon //abstract base class for all WimaAreas { Q_OBJECT public: WimaArea(QObject* parent = nullptr); - WimaArea(WimaArea* other, QObject* parent = nullptr); + WimaArea(QGCMapPolygon* other = nullptr, QObject* parent = nullptr); ~WimaArea(); @@ -24,8 +29,8 @@ public: double maxAltitude (void) const { return _maxAltitude;} WimaVehicle* vehicle (void) const { return _wimaVehicle;} - virtual QString mapVisualQML (void) const = 0; - virtual QString editorQML (void) const = 0; + QString mapVisualQML (void) const { return "WimaAreaMapVisual.qml";} + QString editorQML (void) const { return "WimaAreaEditor.qml";} //Property setters void setMaxAltitude (double alt); @@ -37,14 +42,32 @@ public: template QList* splitArea (int numberOfFractions); // use QScopedPointer to store return value*/ //iterates over all vertices in _polygon and returns the index of that one closest to coordinate - int getClosestVertexIndex (QGeoCoordinate coordinate); + int getClosestVertexIndex (QGeoCoordinate coordinate); //iterates over all vertices in _polygon and returns that one closest to coordinate - QGeoCoordinate getClosestVertex (QGeoCoordinate coordinate); - QGCMapPolygon* toQGCPolygon (WimaArea* poly); - QGCMapPolygon* joinPolygons (QList* polyList); - QGCMapPolygon* joinPolygons (QGCMapPolygon* poly1, QGCMapPolygon* poly2); - bool isDisjunct (QList* polyList); - bool isDisjunct (QGCMapPolygon* poly1, QGCMapPolygon* poly2); + QGeoCoordinate getClosestVertex (QGeoCoordinate coordinate); + QGCMapPolygon* toQGCPolygon (WimaArea* poly); + WimaArea* joinPolygons (QList* polyList); + /// joins the poly1 and poly2 if possible, joins the polygons to form a simple polygon (no holes) + /// see https://en.wikipedia.org/wiki/Simple_polygon + /// @return the joined polygon of poly1 and poly2 if possible, poly1 else + WimaArea* joinPolygons (WimaArea* poly1, WimaArea* poly2); + bool isDisjunct (QList* polyList); + bool isDisjunct (WimaArea* poly1, WimaArea* poly2); + /// calculates the next polygon vertex index + /// @return index + 1 if index < poly->count()-1 && index >= 0, or 0 if index == poly->count()-1, -1 else + int nextVertexIndex (int index); + /// calculates the previous polygon vertex index + /// @return index - 1 if index < poly->count() && index > 0, or poly->count()-1 if index == 0, -1 else + int previousVertexIndex (int index); + /// checks if line1 and line2 intersect with each other, takes latitude and longitute into account only (height neglected) + /// @param line1 line containing two coordinates, height not taken into account + /// @param line2 line containing two coordinates, height not taken into account + /// @return the intersection point if line1 intersects line2, nullptr else + QGeoCoordinate* intersects(QGCMapPolyline* line1, QGCMapPolyline* line2); + /// checks if line1 and poly intersect with each other, takes latitude and longitute into account only (height neglected) + /// @param line line containing two coordinates, height not taken into account + /// @return a list of intersection points if line intersects poly, or an empty list else + QList* intersects(QGCMapPolyline* line, WimaArea* poly); // Accurracy used to compute isDisjunct static const double numericalAccuracy; -- 2.22.0