diff options
author | Julian Sherollari <jdotsh@gmail.com> | 2018-07-27 16:04:42 +0200 |
---|---|---|
committer | Paolo Angelelli <paolo.angelelli@qt.io> | 2018-08-20 10:53:02 +0000 |
commit | 282d146923533eea6105758b9f09f29ee896975a (patch) | |
tree | b7223c5ca5cc0b896dd4cd2e003360eca6356f00 | |
parent | 367c49e91366aa9b13bc7d64209321168680841e (diff) | |
download | qtlocation-282d146923533eea6105758b9f09f29ee896975a.tar.gz |
Add hole support in QGeoPolygon
[ChangeLog][QtPositioning] Added holes in QGeoPolygons
Change-Id: I490bcf8c4a6d9f35fa364072d8ea70b914bfc640
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Reviewed-by: Paolo Angelelli <paolo.angelelli@qt.io>
-rw-r--r-- | src/positioning/qgeopath.cpp | 66 | ||||
-rw-r--r-- | src/positioning/qgeopath_p.h | 6 | ||||
-rw-r--r-- | src/positioning/qgeopolygon.cpp | 78 | ||||
-rw-r--r-- | src/positioning/qgeopolygon.h | 6 |
4 files changed, 156 insertions, 0 deletions
diff --git a/src/positioning/qgeopath.cpp b/src/positioning/qgeopath.cpp index 6fc79c07..3747474e 100644 --- a/src/positioning/qgeopath.cpp +++ b/src/positioning/qgeopath.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qgeopath.h" +#include "qgeopolygon.h" #include "qgeopath_p.h" #include "qgeocoordinate.h" @@ -580,11 +581,26 @@ bool QGeoPathPrivate::lineContains(const QGeoCoordinate &coordinate) const return (m_path[0].distanceTo(coordinate) <= lineRadius); } +/*! + modified version of polygonContains with holes support. +*/ bool QGeoPathPrivate::polygonContains(const QGeoCoordinate &coordinate) const { if (m_clipperDirty) const_cast<QGeoPathPrivate *>(this)->updateClipperPath(); + // iterates the holes List checking whether the point is contained inside the holes + for (const QList<QGeoCoordinate> &holePath : qAsConst(m_holesList)) { + + QGeoPolygon holePolygon; + holePolygon.setPath(holePath); + QGeoPath holeBoundary; + holeBoundary.setPath(holePath); + + if (holePolygon.contains(coordinate) && !(holeBoundary.contains(coordinate))) + return false; + } + QDoubleVector2D coord = QWebMercator::coordToMercator(coordinate); double tlx = QWebMercator::coordToMercator(m_bbox.topLeft()).x(); if (coord.x() < tlx) @@ -621,6 +637,14 @@ void QGeoPathPrivate::translate(double degreesLatitude, double degreesLongitude) p.setLatitude(p.latitude() + degreesLatitude); p.setLongitude(QLocationUtils::wrapLong(p.longitude() + degreesLongitude)); } + if (!m_holesList.isEmpty()){ + for (QList<QGeoCoordinate> &hole: m_holesList){ + for (QGeoCoordinate &holeVertex: hole){ + holeVertex.setLatitude(holeVertex.latitude() + degreesLatitude); + holeVertex.setLongitude(QLocationUtils::wrapLong(holeVertex.longitude() + degreesLongitude)); + } + } + } m_bbox.translate(degreesLatitude, degreesLongitude); m_minLati += degreesLatitude; m_maxLati += degreesLatitude; @@ -800,4 +824,46 @@ void QGeoPathPrivate::updateClipperPath() m_clipperPath = QClipperUtils::qListToPath(preservedPath); } + +/*! + Sets the \a path for an Hole inside the polygon.The hole has QList<QGeoCoordinate> type +*/ +void QGeoPathPrivate::addHole(const QList<QGeoCoordinate> &holePath) +{ + for (const QGeoCoordinate &holeVertex: holePath) + if (!holeVertex.isValid()) + return; + + m_holesList << holePath; +} + +/*! + Returns a QVariant containing a QList<QGeoCoordinate> representing the hole at index +*/ +const QList<QGeoCoordinate> QGeoPathPrivate::holePath(int index) const +{ + return m_holesList.at(index); +} + + +/*! + Removes element at position \a index from the holes QList. +*/ +void QGeoPathPrivate::removeHole(int index) +{ + if (index < 0 || index >= m_holesList.size()) + return; + + m_holesList.removeAt(index); +} + +/*! + Returns the number of holes. +*/ +int QGeoPathPrivate::holesCount() const +{ + return m_holesList.size(); +} + QT_END_NAMESPACE + diff --git a/src/positioning/qgeopath_p.h b/src/positioning/qgeopath_p.h index 6548ce84..d39f0ab2 100644 --- a/src/positioning/qgeopath_p.h +++ b/src/positioning/qgeopath_p.h @@ -101,8 +101,14 @@ public: void computeBoundingBox(); void updateBoundingBox(); void updateClipperPath(); + void addHole(const QList<QGeoCoordinate> &holePath); + const QList<QGeoCoordinate> holePath(int index) const; + void removeHole(int index); + int holesCount() const; + QList<QGeoCoordinate> m_path; + QList<QList<QGeoCoordinate>> m_holesList; QVector<double> m_deltaXs; // longitude deltas from m_path[0] double m_minX; // minimum value inside deltaXs double m_maxX; // maximum value inside deltaXs diff --git a/src/positioning/qgeopolygon.cpp b/src/positioning/qgeopolygon.cpp index 1cbbc06e..66659d4b 100644 --- a/src/positioning/qgeopolygon.cpp +++ b/src/positioning/qgeopolygon.cpp @@ -354,4 +354,82 @@ QString QGeoPolygon::toString() const return QStringLiteral("QGeoPolygon([ %1 ])").arg(pathString); } +/*! + Sets the \a path for a hole inside the polygon. The hole is a QVariant containing a QList<QGeoCoordinate>. + + \since 5.12 +*/ +void QGeoPolygon::addHole(const QVariant &holePath) +{ + Q_D(QGeoPolygon); + QList<QGeoCoordinate> qgcHolePath; + if (holePath.canConvert<QVariantList>()) { + const QVariantList qvlHolePath = holePath.toList(); + for (const QVariant &vertex : qvlHolePath) { + if (vertex.canConvert<QGeoCoordinate>()) + qgcHolePath << vertex.value<QGeoCoordinate>(); + } + } + //ToDo: add QGeoShape support + return d->addHole(qgcHolePath); +} + +/*! + Overloaded method. Sets the \a path for a hole inside the polygon. The hole is a QList<QGeoCoordinate>. + + \since 5.12 +*/ +void QGeoPolygon::addHole(const QList<QGeoCoordinate> &holePath) +{ + Q_D(QGeoPolygon); + return d->addHole(holePath); +} + +/*! + Returns a QVariant containing a QVariant containing a QList<QGeoCoordinate> which represents the hole at index. + + \since 5.12 +*/ +const QVariantList QGeoPolygon::hole(int index) const +{ + Q_D(const QGeoPolygon); + QVariantList holeCoordinates; + for (const QGeoCoordinate &coords: d->holePath(index)) + holeCoordinates << QVariant::fromValue(coords); + return holeCoordinates; +} + +/*! + Returns a QList<QGeoCoordinate> which represents the hole at \a index. + + \since 5.12 +*/ +const QList<QGeoCoordinate> QGeoPolygon::holePath(int index) const +{ + Q_D(const QGeoPolygon); + return d->holePath(index); +} + +/*! + Removes element at position \a index from the holes QList. + + \since 5.12 +*/ +void QGeoPolygon::removeHole(int index) +{ + Q_D(QGeoPolygon); + return d->removeHole(index); +} + +/*! + Returns the number of holes. + + \since 5.12 +*/ +int QGeoPolygon::holesCount() const +{ + Q_D(const QGeoPolygon); + return d->holesCount(); +} + QT_END_NAMESPACE diff --git a/src/positioning/qgeopolygon.h b/src/positioning/qgeopolygon.h index 85b09e34..ccc4b98b 100644 --- a/src/positioning/qgeopolygon.h +++ b/src/positioning/qgeopolygon.h @@ -73,6 +73,12 @@ public: void setPath(const QList<QGeoCoordinate> &path); // ### Qt6: rename into setPerimeter const QList<QGeoCoordinate> &path() const; + Q_INVOKABLE void addHole(const QVariant &holePath); + void addHole(const QList<QGeoCoordinate> &holePath); + Q_INVOKABLE const QVariantList hole(int index) const; + const QList<QGeoCoordinate> holePath(int index) const; + Q_INVOKABLE void removeHole(int index); + Q_INVOKABLE int holesCount() const; Q_INVOKABLE void translate(double degreesLatitude, double degreesLongitude); Q_INVOKABLE QGeoPolygon translated(double degreesLatitude, double degreesLongitude) const; Q_INVOKABLE double length(int indexFrom = 0, int indexTo = -1) const; |