diff --git a/src/imports/location/location.cpp b/src/imports/location/location.cpp index 049d52c095151550545f1854a4ced57e1753b632..5d1b6e23264c44b9dca61084264dcb46d618d261 100644 --- a/src/imports/location/location.cpp +++ b/src/imports/location/location.cpp @@ -176,6 +176,7 @@ public: // Register the 5.11 types minor = 11; + qmlRegisterType<QGeoMapObject>(); qmlRegisterType<QDeclarativeGeoManeuver, 11>(uri, major, minor, "RouteManeuver"); qmlRegisterType<QDeclarativeGeoMap, 11>(uri, major, minor, "Map"); qmlRegisterUncreatableType<QDeclarativeGeoMapItemBase, 11>(uri, major, minor, "GeoMapItemBase", diff --git a/src/imports/locationlabs/locationlabs.cpp b/src/imports/locationlabs/locationlabs.cpp index c90993eb15266ebdf3d8e2f0e45b5d1d437c0e4e..09fba2846658adefe901a39d08ceb1c32f369d1a 100644 --- a/src/imports/locationlabs/locationlabs.cpp +++ b/src/imports/locationlabs/locationlabs.cpp @@ -43,13 +43,20 @@ #include <QtLocation/private/qdeclarativenavigator_p.h> #include <QtLocation/private/qdeclarativenavigator_p_p.h> #include <QtLocation/private/qnavigationmanagerengine_p.h> - #include <QtQml/qqmlextensionplugin.h> #include <QtQml/qqml.h> #include <QtCore/QDebug> +#include "locationlabssingleton_p.h" QT_BEGIN_NAMESPACE +static QObject *singleton_type_factory(QQmlEngine *engine, QJSEngine *jsEngine) +{ + Q_UNUSED(engine); + Q_UNUSED(jsEngine); + + return new LocationLabsSingleton; +} class QtLocationLabsDeclarativeModule: public QQmlExtensionPlugin { @@ -78,6 +85,7 @@ public: qmlRegisterType<QDeclarativeNavigationBasicDirections>(); qmlRegisterType<QDeclarativeNavigator>(uri, major, minor, "Navigator"); qmlRegisterType<QAbstractNavigator>(); + qmlRegisterSingletonType<LocationLabsSingleton>(uri, major, minor, "QtLocationLabs", singleton_type_factory); } else { qDebug() << "Unsupported URI given to load location QML plugin: " << QLatin1String(uri); } diff --git a/src/imports/locationlabs/locationlabs.pro b/src/imports/locationlabs/locationlabs.pro index 2fcc1adc426623d221b0411dd63e0e45cdf1bd7d..c55b09b88efdf0d51d45cdb9fcd4e84c83b7c41c 100644 --- a/src/imports/locationlabs/locationlabs.pro +++ b/src/imports/locationlabs/locationlabs.pro @@ -5,8 +5,12 @@ CXX_MODULE = $$TARGET TARGETPATH = Qt/labs/location IMPORT_VERSION = 1.0 +HEADERS += \ + locationlabssingleton_p.h + SOURCES += \ - locationlabs.cpp + locationlabs.cpp \ + locationlabssingleton.cpp #CONFIG += no_cxx_module load(qml_plugin) diff --git a/src/imports/locationlabs/locationlabssingleton.cpp b/src/imports/locationlabs/locationlabssingleton.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c053da9e04ab60f08770e10c85c70b32d12a2ac0 --- /dev/null +++ b/src/imports/locationlabs/locationlabssingleton.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "locationlabssingleton_p.h" + +/*! + \qmltype QtLocationLabs + \instantiates LocationLabsSingleton + \inqmlmodule Qt.labs.location + \since 5.13 + + \brief The QtLocationLabs global object provides experimental, tech-preview functions for working with + location-based types in QML. + + \qml + import Qt.labs.location 1.0 + + Map { + id: map + MouseArea { + anchors.fill: parent + onClicked: { + var mapObjects = QtLocationLabs.mapObjectsAt(map.toCoordinate(Qt.point(mouseX,mouseY)), map) + } + } + } + \endqml +*/ + +LocationLabsSingleton::LocationLabsSingleton(QObject *parent) +: QObject(parent) +{ +} + +/*! + \qmlmethod coordinate ::QtLocationLabs::mapObjectsAt(coordinate, map) + + Returns the map objects in \a map covering \a coordinate. +*/ +QList<QObject *> LocationLabsSingleton::mapObjectsAt(const QGeoCoordinate &coordinate, QDeclarativeGeoMap *map) const +{ + if (!map) + return QList<QObject *>(); + return map->map()->mapObjectsAt(coordinate); +} diff --git a/src/imports/locationlabs/locationlabssingleton_p.h b/src/imports/locationlabs/locationlabssingleton_p.h new file mode 100644 index 0000000000000000000000000000000000000000..42f4a21c8a1ed1b7ef5d3aaae92fde21e950f780 --- /dev/null +++ b/src/imports/locationlabs/locationlabssingleton_p.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LOCATIONLABSSINGLETON_P_H +#define LOCATIONLABSSINGLETON_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/QObject> +#include <QtPositioning/QGeoCoordinate> +#include <QtLocation/private/qdeclarativegeomap_p.h> + +class LocationLabsSingleton : public QObject +{ + Q_OBJECT + +public: + explicit LocationLabsSingleton(QObject *parent = 0); + + Q_INVOKABLE QList<QObject *> mapObjectsAt(const QGeoCoordinate &coordinate, QDeclarativeGeoMap *map) const; +}; + +#endif // LOCATIONLABSSINGLETON_P_H diff --git a/src/imports/positioning/locationsingleton.h b/src/imports/positioning/locationsingleton.h index 9372b8f1a1ae21941253781b72038eed11d763de..16d838e67c465e38fb2184e56dfb42be035d2491 100644 --- a/src/imports/positioning/locationsingleton.h +++ b/src/imports/positioning/locationsingleton.h @@ -40,6 +40,17 @@ #ifndef LOCATIONSINGLETON_H #define LOCATIONSINGLETON_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QObject> #include <QtCore/qnumeric.h> #include <QtPositioning/QGeoCoordinate> diff --git a/src/location/declarativemaps/qgeomapobject_p.h b/src/location/declarativemaps/qgeomapobject_p.h index bc63e0a6c5465009b933ab08fe69bdbfda4d8662..000d832064877429e93daffdb42986fc10222fa3 100644 --- a/src/location/declarativemaps/qgeomapobject_p.h +++ b/src/location/declarativemaps/qgeomapobject_p.h @@ -51,6 +51,7 @@ #include <QtLocation/private/qparameterizableobject_p.h> #include <QExplicitlySharedDataPointer> #include <QtPositioning/qgeoshape.h> +#include <qqml.h> QT_BEGIN_NAMESPACE @@ -133,6 +134,9 @@ protected: friend class QGeoMapLayer; friend class QDeclarativeNavigator; }; + QT_END_NAMESPACE +QML_DECLARE_TYPE(QGeoMapObject) + #endif // QGEOMAPOBJECTBASE_H diff --git a/src/location/labs/qgeotiledmaplabs.cpp b/src/location/labs/qgeotiledmaplabs.cpp index 22d582c0eeb0a4ad0d81e30f62055f0ca6f8b818..7d8d71080275fed3a9a1d0681748c17ed22f3e28 100644 --- a/src/location/labs/qgeotiledmaplabs.cpp +++ b/src/location/labs/qgeotiledmaplabs.cpp @@ -44,6 +44,8 @@ #include <QtLocation/private/qmapiconobjectqsg_p_p.h> #include <QtLocation/private/qdeclarativepolylinemapitem_p.h> #include <QtLocation/private/qgeomapobjectqsgsupport_p.h> +#include <QtPositioning/private/qlocationutils_p.h> +#include <math.h> QT_BEGIN_NAMESPACE @@ -57,6 +59,7 @@ public: QGeoMapObjectPrivate *createMapObjectImplementation(QGeoMapObject *obj) override; virtual QList<QGeoMapObject *> mapObjects() const override; void removeMapObject(QGeoMapObject *obj); + QList<QObject *>mapObjectsAt(const QGeoCoordinate &coordinate) const; void updateMapObjects(QSGNode *root, QQuickWindow *window); void updateObjectsGeometry(); @@ -95,6 +98,34 @@ void QGeoTiledMapLabsPrivate::removeMapObject(QGeoMapObject *obj) m_qsgSupport.removeMapObject(obj); } +QList<QObject *> QGeoTiledMapLabsPrivate::mapObjectsAt(const QGeoCoordinate &coordinate) const +{ + // ToDo: use a space partitioning strategy + QList<QObject *> res; + for (const auto o: mapObjects()) { + // explicitly handle lines + bool contains = false; + if (o->type() == QGeoMapObject::PolylineType ) { + QMapPolylineObject *mpo = static_cast<QMapPolylineObject *>(o); + qreal mpp = QLocationUtils::metersPerPixel(m_cameraData.zoomLevel(), coordinate); + QGeoPath path = o->geoShape(); + path.setWidth(mpp * mpo->border()->width()); + contains = path.contains(coordinate); + } else if (o->type() == QGeoMapObject::RouteType) { + qreal mpp = QLocationUtils::metersPerPixel(m_cameraData.zoomLevel(), coordinate); + QGeoPath path = o->geoShape(); + path.setWidth(mpp * 4); // MapRouteObjectQSG has a hardcoded 4 pixels width; + contains = path.contains(coordinate); + } else { + contains = o->geoShape().contains(coordinate); + } + + if (contains) + res.append(o); + } + return res; +} + void QGeoTiledMapLabsPrivate::updateMapObjects(QSGNode *root, QQuickWindow *window) { m_qsgSupport.updateMapObjects(root, window); @@ -161,6 +192,12 @@ void QGeoTiledMapLabs::removeMapObject(QGeoMapObject *obj) d->removeMapObject(obj); } +QList<QObject *> QGeoTiledMapLabs::mapObjectsAt(const QGeoCoordinate &coordinate) const +{ + Q_D(const QGeoTiledMapLabs); + return d->mapObjectsAt(coordinate); +} + QGeoTiledMapLabs::QGeoTiledMapLabs(QGeoTiledMapLabsPrivate &dd, QGeoTiledMappingManagerEngine *engine, QObject *parent) : QGeoTiledMap(dd, engine, parent) { diff --git a/src/location/labs/qgeotiledmaplabs_p.h b/src/location/labs/qgeotiledmaplabs_p.h index 4f17902874bdbb158c75cc6257f0465bb1fcdea9..d10ec6338ca44ee0559d16bda10547fc5b96a2c9 100644 --- a/src/location/labs/qgeotiledmaplabs_p.h +++ b/src/location/labs/qgeotiledmaplabs_p.h @@ -72,6 +72,7 @@ public: bool createMapObjectImplementation(QGeoMapObject *obj) override; void removeMapObject(QGeoMapObject *obj) override; + QList<QObject *> mapObjectsAt(const QGeoCoordinate &coordinate) const override; protected: QSGNode *updateSceneGraph(QSGNode *node, QQuickWindow *window) override; diff --git a/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp b/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp index e0e3a6d74c990571b1c3eb7bae379483c3ac7c55..1a1b102b3c35e801db3f672e098c43416b781f79 100644 --- a/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp +++ b/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp @@ -126,7 +126,11 @@ QGeoMapObjectPrivate *QGeoMapObjectQSGSupport::createMapObjectImplementationPriv QList<QGeoMapObject *> QGeoMapObjectQSGSupport::mapObjects() const { - return QList<QGeoMapObject *>(); + QList<QGeoMapObject *> res; + for (int i = 0; i < m_mapObjects.size(); ++i) { + res.append(m_mapObjects.at(i).object.data()); + } + return res; } void QGeoMapObjectQSGSupport::removeMapObject(QGeoMapObject *obj) diff --git a/src/location/labs/qsg/qmaprouteobjectqsg.cpp b/src/location/labs/qsg/qmaprouteobjectqsg.cpp index eaea64f3369c04b89704b8aee7c6800994f74b23..8f347f884bc62e03eb455b3387759da408e19311 100644 --- a/src/location/labs/qsg/qmaprouteobjectqsg.cpp +++ b/src/location/labs/qsg/qmaprouteobjectqsg.cpp @@ -100,4 +100,9 @@ void QMapRouteObjectPrivateQSG::setVisible(bool visible) m_polyline->setVisible(visible); } +QGeoShape QMapRouteObjectPrivateQSG::geoShape() const +{ + return m_polyline->geoShape(); +} + QT_END_NAMESPACE diff --git a/src/location/labs/qsg/qmaprouteobjectqsg_p_p.h b/src/location/labs/qsg/qmaprouteobjectqsg_p_p.h index 0c946259f994490f2679ca6fbc00f2317602f1cf..2ade5d5343474acf6fa4d8b719afef8893497f99 100644 --- a/src/location/labs/qsg/qmaprouteobjectqsg_p_p.h +++ b/src/location/labs/qsg/qmaprouteobjectqsg_p_p.h @@ -80,6 +80,7 @@ public: QGeoMapObjectPrivate *clone() override; void setMap(QGeoMap *map) override; void setVisible(bool visible) override; + virtual QGeoShape geoShape() const override; // Data Members QScopedPointer<QMapPolylineObjectPrivateQSG> m_polyline; diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp index 80edac1aff8fe8460a2f97444b04122788e67af0..dc8aa2c87a205e8b2687d5db68c31693190ff82d 100644 --- a/src/location/maps/qgeomap.cpp +++ b/src/location/maps/qgeomap.cpp @@ -305,6 +305,11 @@ void QGeoMap::removeMapObject(QGeoMapObject * /*obj*/) { } +QList<QObject *> QGeoMap::mapObjectsAt(const QGeoCoordinate &/*coordinate*/) const +{ + return QList<QObject *>(); +} + void QGeoMap::setVisibleArea(const QRectF &visibleArea) { Q_D(QGeoMap); diff --git a/src/location/maps/qgeomap_p.h b/src/location/maps/qgeomap_p.h index c0af9e10cc923382a008e4158eec3eed7c81767f..216c8b64f4197fb78ee3a9641f300506c745a881 100644 --- a/src/location/maps/qgeomap_p.h +++ b/src/location/maps/qgeomap_p.h @@ -154,6 +154,7 @@ public: virtual void setCopyrightVisible(bool visible); virtual void removeMapObject(QGeoMapObject *obj); + virtual QList<QObject *> mapObjectsAt(const QGeoCoordinate &coordinate) const; void setVisibleArea(const QRectF &visibleArea); QRectF visibleArea() const; diff --git a/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp b/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp index f65204849f8fb68b9e39f0fdc66870dd952161c3..1ebad08dab567af7138270de630d287c5c0720c0 100644 --- a/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp +++ b/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp @@ -65,6 +65,7 @@ public: virtual QList<QGeoMapObject *> mapObjects() const override; void removeMapObject(QGeoMapObject *obj); void updateMapObjects(QSGNode *root, QQuickWindow *window); + QList<QObject *>mapObjectsAt(const QGeoCoordinate &coordinate) const; QGeoMapObjectQSGSupport m_qsgSupport; #endif @@ -137,6 +138,16 @@ void QGeoMapItemsOverlay::removeMapObject(QGeoMapObject *obj) #endif } +QList<QObject *> QGeoMapItemsOverlay::mapObjectsAt(const QGeoCoordinate &coordinate) const +{ +#ifdef LOCATIONLABS + Q_D(const QGeoMapItemsOverlay); + return d->mapObjectsAt(coordinate); +#else + return QGeoMap::mapObjectsAt(coordinate); +#endif +} + void QGeoMapItemsOverlayPrivate::setVisibleArea(const QRectF &visibleArea) { Q_Q(QGeoMapItemsOverlay); @@ -185,6 +196,34 @@ void QGeoMapItemsOverlayPrivate::updateMapObjects(QSGNode *root, QQuickWindow *w { m_qsgSupport.updateMapObjects(root, window); } + +QList<QObject *> QGeoMapItemsOverlayPrivate::mapObjectsAt(const QGeoCoordinate &coordinate) const +{ + // ToDo: use a space partitioning strategy + QList<QObject *> res; + for (const auto o: mapObjects()) { + // explicitly handle lines + bool contains = false; + if (o->type() == QGeoMapObject::PolylineType ) { + QMapPolylineObject *mpo = static_cast<QMapPolylineObject *>(o); + qreal mpp = QLocationUtils::metersPerPixel(m_cameraData.zoomLevel(), coordinate); + QGeoPath path = o->geoShape(); + path.setWidth(mpp * mpo->border()->width()); + contains = path.contains(coordinate); + } else if (o->type() == QGeoMapObject::RouteType) { + qreal mpp = QLocationUtils::metersPerPixel(m_cameraData.zoomLevel(), coordinate); + QGeoPath path = o->geoShape(); + path.setWidth(mpp * 4); // MapRouteObjectQSG has a hardcoded 4 pixels width; + contains = path.contains(coordinate); + } else { + contains = o->geoShape().contains(coordinate); + } + + if (contains) + res.append(o); + } + return res; +} #endif void QGeoMapItemsOverlayPrivate::updateObjectsGeometry() diff --git a/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.h b/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.h index 1594ffb316e8d6a5c667e26fae1bf37de01c537f..c287345c3e7a6c4b601b6c9dae714c7c4eb99581 100644 --- a/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.h +++ b/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.h @@ -56,6 +56,7 @@ public: QGeoMap::Capabilities capabilities() const override; bool createMapObjectImplementation(QGeoMapObject *obj) override; void removeMapObject(QGeoMapObject *obj) override; + QList<QObject *> mapObjectsAt(const QGeoCoordinate &coordinate) const override; protected: QSGNode *updateSceneGraph(QSGNode *node, QQuickWindow *window) override; diff --git a/src/positioning/qlocationutils_p.h b/src/positioning/qlocationutils_p.h index d9e6524a34b1e1ef130d7868418510b570ddbe17..e3881f6f594fcdc5fad663ab7f126158496c3b78 100644 --- a/src/positioning/qlocationutils_p.h +++ b/src/positioning/qlocationutils_p.h @@ -229,7 +229,7 @@ public: return 6371007.2; } - inline static double earthMeanDiameter() + inline static double earthMeanCircumference() { return earthMeanRadius() * 2.0 * M_PI; } @@ -256,6 +256,12 @@ public: return wrapLong(centerLongitude - leftOffset); } + static qreal metersPerPixel(qreal zoomLevel, const QGeoCoordinate &coordinate) + { + const qreal metersPerTile = earthMeanCircumference() * std::cos(radians(coordinate.latitude())) / std::pow(2, zoomLevel); + return metersPerTile / 256.0; + } + /* returns the NMEA sentence type. */