From 6024168ef21dd4fe6c5ddd7e837d56076e886e01 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Tue, 28 Feb 2017 18:26:19 -0800 Subject: Mapbox GL native circle support Circles crossing one pole are drawn inverted. Circles crossing 2 poles do not even have the correct geometry. Nevertheless, a first approximation. Task-number: QTBUG-58869 Change-Id: I5a508f5d6e27c4f08412a7ae327883866068a1e9 Reviewed-by: Paolo Angelelli --- .../declarativemaps/qdeclarativecirclemapitem.cpp | 10 ++--- .../declarativemaps/qdeclarativecirclemapitem_p.h | 8 +++- .../geoservices/mapboxgl/qgeomapmapboxgl.cpp | 22 ++++++---- .../geoservices/mapboxgl/qmapboxglstylechange.cpp | 48 ++++++++++++++++++++++ .../geoservices/mapboxgl/qmapboxglstylechange_p.h | 1 + 5 files changed, 75 insertions(+), 14 deletions(-) diff --git a/src/location/declarativemaps/qdeclarativecirclemapitem.cpp b/src/location/declarativemaps/qdeclarativecirclemapitem.cpp index 5f002bf9..91328dc7 100644 --- a/src/location/declarativemaps/qdeclarativecirclemapitem.cpp +++ b/src/location/declarativemaps/qdeclarativecirclemapitem.cpp @@ -262,7 +262,7 @@ void QGeoMapCircleGeometry::updateScreenPointsInvert(const QList &path, +void QDeclarativeCircleMapItem::calculatePeripheralPoints(QList &path, const QGeoCoordinate ¢er, qreal distance, int steps, @@ -644,9 +644,9 @@ void QDeclarativeCircleMapItem::updateCirclePathForRendering(QList &path, const QGeoCoordinate ¢er, + qreal distance, int steps, QGeoCoordinate &leftBound); + bool preserveCircleGeometry(QList &path, const QGeoCoordinate ¢er, + qreal distance); + Q_SIGNALS: void centerChanged(const QGeoCoordinate ¢er); void radiusChanged(qreal radius); @@ -111,8 +117,6 @@ protected Q_SLOTS: private: void updateCirclePath(); - bool preserveCircleGeometry(QList &path, const QGeoCoordinate ¢er, - qreal distance); void updateCirclePathForRendering(QList &path, const QGeoCoordinate ¢er, qreal distance); diff --git a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp index 1001ca31..2f506325 100644 --- a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp +++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp @@ -176,8 +176,7 @@ void QGeoMapMapboxGLPrivate::removeParameter(QGeoMapParameter *param) QGeoMap::ItemTypes QGeoMapMapboxGLPrivate::supportedMapItemTypes() const { - // TODO https://bugreports.qt.io/browse/QTBUG-58869 - return QGeoMap::MapRectangle | QGeoMap::MapPolygon | QGeoMap::MapPolyline; + return QGeoMap::MapRectangle | QGeoMap::MapCircle | QGeoMap::MapPolygon | QGeoMap::MapPolyline; } void QGeoMapMapboxGLPrivate::addMapItem(QDeclarativeGeoMapItemBase *item) @@ -188,25 +187,32 @@ void QGeoMapMapboxGLPrivate::addMapItem(QDeclarativeGeoMapItemBase *item) case QGeoMap::NoItem: case QGeoMap::MapQuickItem: case QGeoMap::CustomMapItem: - case QGeoMap::MapCircle: return; case QGeoMap::MapRectangle: { - QDeclarativeRectangleMapItem *mapItem = qobject_cast(item); + QDeclarativeRectangleMapItem *mapItem = static_cast(item); QObject::connect(mapItem, &QDeclarativeRectangleMapItem::bottomRightChanged, q, &QGeoMapMapboxGL::onMapItemGeometryChanged); QObject::connect(mapItem, &QDeclarativeRectangleMapItem::topLeftChanged, q, &QGeoMapMapboxGL::onMapItemGeometryChanged); QObject::connect(mapItem, &QDeclarativeRectangleMapItem::colorChanged, q, &QGeoMapMapboxGL::onMapItemPropertyChanged); QObject::connect(mapItem->border(), &QDeclarativeMapLineProperties::colorChanged, q, &QGeoMapMapboxGL::onMapItemSubPropertyChanged); QObject::connect(mapItem->border(), &QDeclarativeMapLineProperties::widthChanged, q, &QGeoMapMapboxGL::onMapItemUnsupportedPropertyChanged); } break; + case QGeoMap::MapCircle: { + QDeclarativeCircleMapItem *mapItem = static_cast(item); + QObject::connect(mapItem, &QDeclarativeCircleMapItem::centerChanged, q, &QGeoMapMapboxGL::onMapItemGeometryChanged); + QObject::connect(mapItem, &QDeclarativeCircleMapItem::radiusChanged, q, &QGeoMapMapboxGL::onMapItemGeometryChanged); + QObject::connect(mapItem, &QDeclarativeCircleMapItem::colorChanged, q, &QGeoMapMapboxGL::onMapItemPropertyChanged); + QObject::connect(mapItem->border(), &QDeclarativeMapLineProperties::colorChanged, q, &QGeoMapMapboxGL::onMapItemSubPropertyChanged); + QObject::connect(mapItem->border(), &QDeclarativeMapLineProperties::widthChanged, q, &QGeoMapMapboxGL::onMapItemUnsupportedPropertyChanged); + } break; case QGeoMap::MapPolygon: { - QDeclarativePolygonMapItem *mapItem = qobject_cast(item); + QDeclarativePolygonMapItem *mapItem = static_cast(item); QObject::connect(mapItem, &QDeclarativePolygonMapItem::pathChanged, q, &QGeoMapMapboxGL::onMapItemGeometryChanged); QObject::connect(mapItem, &QDeclarativePolygonMapItem::colorChanged, q, &QGeoMapMapboxGL::onMapItemGeometryChanged); QObject::connect(mapItem->border(), &QDeclarativeMapLineProperties::colorChanged, q, &QGeoMapMapboxGL::onMapItemSubPropertyChanged); QObject::connect(mapItem->border(), &QDeclarativeMapLineProperties::widthChanged, q, &QGeoMapMapboxGL::onMapItemUnsupportedPropertyChanged); } break; case QGeoMap::MapPolyline: { - QDeclarativePolylineMapItem *mapItem = qobject_cast(item); + QDeclarativePolylineMapItem *mapItem = static_cast(item); QObject::connect(mapItem, &QDeclarativePolylineMapItem::pathChanged, q, &QGeoMapMapboxGL::onMapItemGeometryChanged); QObject::connect(mapItem->line(), &QDeclarativeMapLineProperties::colorChanged, q, &QGeoMapMapboxGL::onMapItemSubPropertyChanged); QObject::connect(mapItem->line(), &QDeclarativeMapLineProperties::widthChanged, q, &QGeoMapMapboxGL::onMapItemSubPropertyChanged); @@ -228,11 +234,13 @@ void QGeoMapMapboxGLPrivate::removeMapItem(QDeclarativeGeoMapItemBase *item) case QGeoMap::NoItem: case QGeoMap::MapQuickItem: case QGeoMap::CustomMapItem: - case QGeoMap::MapCircle: return; case QGeoMap::MapRectangle: q->disconnect(static_cast(item)->border()); break; + case QGeoMap::MapCircle: + q->disconnect(static_cast(item)->border()); + break; case QGeoMap::MapPolygon: q->disconnect(static_cast(item)->border()); break; diff --git a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp index f79f0a38..f8bd9b4d 100644 --- a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp +++ b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp @@ -86,6 +86,32 @@ QMapbox::Feature featureFromMapRectangle(QDeclarativeRectangleMapItem *mapItem) return QMapbox::Feature(QMapbox::Feature::PolygonType, geometry, {}, getId(mapItem)); } +QMapbox::Feature featureFromMapCircle(QDeclarativeCircleMapItem *mapItem) +{ + static const int circleSamples = 128; + + QList path; + QGeoCoordinate leftBound; + QDeclarativeCircleMapItem::calculatePeripheralPoints(path, mapItem->center(), mapItem->radius(), circleSamples, leftBound); + QList pathProjected; + for (const QGeoCoordinate &c : qAsConst(path)) + pathProjected << mapItem->map()->geoProjection().geoToMapProjection(c); + if (QDeclarativeCircleMapItem::crossEarthPole(mapItem->center(), mapItem->radius())) + mapItem->preserveCircleGeometry(pathProjected, mapItem->center(), mapItem->radius()); + path.clear(); + for (const QDoubleVector2D &c : qAsConst(pathProjected)) + path << mapItem->map()->geoProjection().mapProjectionToGeo(c); + + + QMapbox::Coordinates coordinates; + for (const QGeoCoordinate &coordinate : path) { + coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() }; + } + coordinates.append(coordinates.first()); // closing the path + QMapbox::CoordinatesCollections geometry { { coordinates } }; + return QMapbox::Feature(QMapbox::Feature::PolygonType, geometry, {}, getId(mapItem)); +} + QMapbox::Feature featureFromMapPolygon(QDeclarativePolygonMapItem *mapItem) { const QGeoPath *path = static_cast(&mapItem->geoShape()); @@ -126,6 +152,8 @@ QMapbox::Feature featureFromMapItem(QDeclarativeGeoMapItemBase *item) switch (item->itemType()) { case QGeoMap::MapRectangle: return featureFromMapRectangle(static_cast(item)); + case QGeoMap::MapCircle: + return featureFromMapCircle(static_cast(item)); case QGeoMap::MapPolygon: return featureFromMapPolygon(static_cast(item)); case QGeoMap::MapPolyline: @@ -182,6 +210,7 @@ QList> QMapboxGLStyleChange::addMapItem(QDe switch (item->itemType()) { case QGeoMap::MapRectangle: + case QGeoMap::MapCircle: case QGeoMap::MapPolygon: case QGeoMap::MapPolyline: break; @@ -325,6 +354,8 @@ QList> QMapboxGLStyleSetPaintProperty::from switch (item->itemType()) { case QGeoMap::MapRectangle: return fromMapItem(static_cast(item)); + case QGeoMap::MapCircle: + return fromMapItem(static_cast(item)); case QGeoMap::MapPolygon: return fromMapItem(static_cast(item)); case QGeoMap::MapPolyline: @@ -352,6 +383,23 @@ QList> QMapboxGLStyleSetPaintProperty::from return changes; } +QList> QMapboxGLStyleSetPaintProperty::fromMapItem(QDeclarativeCircleMapItem *item) +{ + QList> changes; + changes.reserve(3); + + const QString id = getId(item); + + changes << QSharedPointer( + new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-opacity"), item->mapItemOpacity())); + changes << QSharedPointer( + new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-color"), item->color())); + changes << QSharedPointer( + new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-outline-color"), item->border()->color())); + + return changes; +} + QList> QMapboxGLStyleSetPaintProperty::fromMapItem(QDeclarativePolygonMapItem *item) { QList> changes; diff --git a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h index aa81d89f..33737c1d 100644 --- a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h +++ b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h @@ -93,6 +93,7 @@ public: private: static QList> fromMapItem(QDeclarativeRectangleMapItem *); + static QList> fromMapItem(QDeclarativeCircleMapItem *); static QList> fromMapItem(QDeclarativePolygonMapItem *); static QList> fromMapItem(QDeclarativePolylineMapItem *); -- cgit v1.2.1