diff options
author | Bruno de Oliveira Abinader <bruno@mapbox.com> | 2017-01-24 18:05:22 +0200 |
---|---|---|
committer | Bruno de Oliveira Abinader <bruno@mapbox.com> | 2017-01-26 14:53:45 +0200 |
commit | be43310b6ff5465e6717128b577f6e61c0335c44 (patch) | |
tree | 330ba9aa8c9a1af84e9d504301c9d716fafe53b6 /platform/qt | |
parent | fb759e949fc6381b92eb2149cbea1db3e282de4b (diff) | |
download | qtlocation-mapboxgl-be43310b6ff5465e6717128b577f6e61c0335c44.tar.gz |
[Qt] Refactor QMapbox Annotations API
Diffstat (limited to 'platform/qt')
-rw-r--r-- | platform/qt/app/mapwindow.cpp | 55 | ||||
-rw-r--r-- | platform/qt/app/mapwindow.hpp | 5 | ||||
-rw-r--r-- | platform/qt/include/qmapbox.hpp | 70 | ||||
-rw-r--r-- | platform/qt/include/qmapboxgl.hpp | 7 | ||||
-rw-r--r-- | platform/qt/resources/common.qrc | 1 | ||||
-rw-r--r-- | platform/qt/src/qmapboxgl.cpp | 132 |
6 files changed, 222 insertions, 48 deletions
diff --git a/platform/qt/app/mapwindow.cpp b/platform/qt/app/mapwindow.cpp index 0b453406f3..3e6a14736f 100644 --- a/platform/qt/app/mapwindow.cpp +++ b/platform/qt/app/mapwindow.cpp @@ -203,6 +203,61 @@ void MapWindow::keyPressEvent(QKeyEvent *ev) m_map->setLayoutProperty("road-label-small", "text-size", 30.0); } break; + case Qt::Key_1: { + if (m_symbolAnnotationId.isNull()) { + QMapbox::Coordinate coordinate = m_map->coordinate(); + QMapbox::SymbolAnnotation symbol { coordinate, "default_marker" }; + m_map->addAnnotationIcon("default_marker", QImage(":default_marker.svg")); + m_symbolAnnotationId = m_map->addAnnotation(QVariant::fromValue<QMapbox::SymbolAnnotation>(symbol)); + } else { + m_map->removeAnnotation(m_symbolAnnotationId.toUInt()); + m_symbolAnnotationId.clear(); + } + } + break; + case Qt::Key_2: { + if (m_lineAnnotationId.isNull()) { + QMapbox::Coordinate topLeft = m_map->coordinateForPixel({ 0, 0 }); + QMapbox::Coordinate bottomRight = m_map->coordinateForPixel({ qreal(size().width()), qreal(size().height()) }); + QMapbox::CoordinatesCollections geometry { { { topLeft, bottomRight } } }; + QMapbox::LineAnnotation line { { QMapbox::ShapeAnnotationGeometry::Type::LineStringType, geometry }, 0.5f, 1.0f, Qt::red }; + m_lineAnnotationId = m_map->addAnnotation(QVariant::fromValue<QMapbox::LineAnnotation>(line)); + } else { + m_map->removeAnnotation(m_lineAnnotationId.toUInt()); + m_lineAnnotationId.clear(); + } + } + break; + case Qt::Key_3: { + if (m_fillAnnotationId.isNull()) { + QMapbox::Coordinate topLeft = m_map->coordinateForPixel({ 0, 0 }); + QMapbox::Coordinate topRight = m_map->coordinateForPixel({ 0, qreal(size().height()) }); + QMapbox::Coordinate bottomLeft = m_map->coordinateForPixel({ qreal(size().width()), 0 }); + QMapbox::Coordinate bottomRight = m_map->coordinateForPixel({ qreal(size().width()), qreal(size().height()) }); + QMapbox::CoordinatesCollections geometry { { { bottomLeft, bottomRight, topRight, topLeft, bottomLeft } } }; + QMapbox::FillAnnotation fill { { QMapbox::ShapeAnnotationGeometry::Type::PolygonType, geometry }, 0.5f, Qt::green, QVariant::fromValue<QColor>(QColor(Qt::black)) }; + m_fillAnnotationId = m_map->addAnnotation(QVariant::fromValue<QMapbox::FillAnnotation>(fill)); + } else { + m_map->removeAnnotation(m_fillAnnotationId.toUInt()); + m_fillAnnotationId.clear(); + } + } + break; + case Qt::Key_4: { + if (m_styleSourcedAnnotationId.isNull()) { + QMapbox::Coordinate topLeft = m_map->coordinateForPixel({ 0, 0 }); + QMapbox::Coordinate topRight = m_map->coordinateForPixel({ 0, qreal(size().height()) }); + QMapbox::Coordinate bottomLeft = m_map->coordinateForPixel({ qreal(size().width()), 0 }); + QMapbox::Coordinate bottomRight = m_map->coordinateForPixel({ qreal(size().width()), qreal(size().height()) }); + QMapbox::CoordinatesCollections geometry { { { bottomLeft, bottomRight, topRight, topLeft, bottomLeft } } }; + QMapbox::StyleSourcedAnnotation styleSourced { { QMapbox::ShapeAnnotationGeometry::Type::PolygonType, geometry }, "water" }; + m_styleSourcedAnnotationId = m_map->addAnnotation(QVariant::fromValue<QMapbox::StyleSourcedAnnotation>(styleSourced)); + } else { + m_map->removeAnnotation(m_styleSourcedAnnotationId.toUInt()); + m_styleSourcedAnnotationId.clear(); + } + } + break; case Qt::Key_Tab: m_map->cycleDebugOptions(); break; diff --git a/platform/qt/app/mapwindow.hpp b/platform/qt/app/mapwindow.hpp index 23880902d3..6b4b7fd1cc 100644 --- a/platform/qt/app/mapwindow.hpp +++ b/platform/qt/app/mapwindow.hpp @@ -61,6 +61,11 @@ private: unsigned m_animationTicks = 0; unsigned m_frameDraws = 0; + QVariant m_symbolAnnotationId; + QVariant m_lineAnnotationId; + QVariant m_fillAnnotationId; + QVariant m_styleSourcedAnnotationId; + bool m_sourceAdded = false; }; diff --git a/platform/qt/include/qmapbox.hpp b/platform/qt/include/qmapbox.hpp index 3aaacb84ea..1388c0f513 100644 --- a/platform/qt/include/qmapbox.hpp +++ b/platform/qt/include/qmapbox.hpp @@ -1,6 +1,7 @@ #ifndef QMAPBOX_H #define QMAPBOX_H +#include <QColor> #include <QList> #include <QPair> #include <QVariant> @@ -10,18 +11,64 @@ namespace QMapbox { +// Reflects mapbox::geometry::point<double>. typedef QPair<double, double> Coordinate; -typedef QList<Coordinate> LineString; - typedef QPair<Coordinate, double> CoordinateZoom; -typedef quint32 AnnotationID; -typedef QList<AnnotationID> AnnotationIDs; +// Reflects mapbox::geometry::line_string<double> and mapbox::geometry::linear_ring<double>. +typedef QList<Coordinate> Coordinates; + +// Reflects mapbox::geometry::multi_line_string<double> and mapbox::geometry::polygon<double>. +typedef QList<Coordinates> CoordinatesCollection; + +// Reflects mapbox::geometry::multi_polygon<double>. +typedef QList<CoordinatesCollection> CoordinatesCollections; + +// Reflects mbgl::ShapeAnnotationGeometry. +struct Q_DECL_EXPORT ShapeAnnotationGeometry { + enum Type { + LineStringType, + PolygonType, + MultiLineStringType, + MultiPolygonType + }; + Type type; + CoordinatesCollections geometry; +}; + +// Reflects mbgl::SymbolAnnotation. +struct Q_DECL_EXPORT SymbolAnnotation { + Coordinate geometry; + QString icon; +}; + +// Reflects mbgl::LineAnnotation. +struct Q_DECL_EXPORT LineAnnotation { + ShapeAnnotationGeometry geometry; + float opacity = 1.0f; + float width = 1.0f; + QColor color = Qt::black; +}; + +// Reflects mbgl::FillAnnotation. +struct Q_DECL_EXPORT FillAnnotation { + ShapeAnnotationGeometry geometry; + float opacity = 1.0f; + QColor color = Qt::black; + QVariant outlineColor; +}; -typedef QPair<Coordinate, QString> PointAnnotation; +// Reflects mbgl::StyleSourcedAnnotation. +struct Q_DECL_EXPORT StyleSourcedAnnotation { + ShapeAnnotationGeometry geometry; + QString layerID; +}; -// FIXME: We need to add support for custom style properties -typedef QPair<LineString, QString> ShapeAnnotation; +// SymbolAnnotation, LineAnnotation, FillAnnotation, StyleSourcedAnnotation. +typedef QVariant Annotation; + +typedef quint32 AnnotationID; +typedef QList<AnnotationID> AnnotationIDs; // Reflects mbgl::NetworkStatus::Status. enum NetworkMode { @@ -55,5 +102,14 @@ Q_DECL_EXPORT void initializeGLExtensions(); } // namespace QMapbox Q_DECLARE_METATYPE(QMapbox::Coordinate); +Q_DECLARE_METATYPE(QMapbox::Coordinates); +Q_DECLARE_METATYPE(QMapbox::CoordinatesCollection); +Q_DECLARE_METATYPE(QMapbox::CoordinatesCollections); + +Q_DECLARE_METATYPE(QMapbox::SymbolAnnotation); +Q_DECLARE_METATYPE(QMapbox::ShapeAnnotationGeometry); +Q_DECLARE_METATYPE(QMapbox::LineAnnotation); +Q_DECLARE_METATYPE(QMapbox::FillAnnotation); +Q_DECLARE_METATYPE(QMapbox::StyleSourcedAnnotation); #endif // QMAPBOX_H diff --git a/platform/qt/include/qmapboxgl.hpp b/platform/qt/include/qmapboxgl.hpp index be2d60608b..0f1ab7c293 100644 --- a/platform/qt/include/qmapboxgl.hpp +++ b/platform/qt/include/qmapboxgl.hpp @@ -183,11 +183,8 @@ public: void addAnnotationIcon(const QString &name, const QImage &sprite); - QMapbox::AnnotationID addPointAnnotation(const QMapbox::PointAnnotation &); - QMapbox::AnnotationID addShapeAnnotation(const QMapbox::ShapeAnnotation &); - - void updatePointAnnotation(QMapbox::AnnotationID, const QMapbox::PointAnnotation &); - + QMapbox::AnnotationID addAnnotation(const QMapbox::Annotation &); + void updateAnnotation(QMapbox::AnnotationID, const QMapbox::Annotation &); void removeAnnotation(QMapbox::AnnotationID); void setLayoutProperty(const QString &layer, const QString &property, const QVariant &value); diff --git a/platform/qt/resources/common.qrc b/platform/qt/resources/common.qrc index d02c04a3c2..4c792b057c 100644 --- a/platform/qt/resources/common.qrc +++ b/platform/qt/resources/common.qrc @@ -1,6 +1,7 @@ <RCC> <qresource prefix="/"> <file alias="icon.png">../../../common/icon.png</file> + <file alias="default_marker.svg">../../../platform/default/resources/default_marker.svg</file> <file>source1.geojson</file> <file>source2.geojson</file> <file>label-arrow.svg</file> diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp index 86604a945f..fb56c4d993 100644 --- a/platform/qt/src/qmapboxgl.cpp +++ b/platform/qt/src/qmapboxgl.cpp @@ -17,8 +17,10 @@ #include <mbgl/style/transition_options.hpp> #include <mbgl/sprite/sprite_image.hpp> #include <mbgl/storage/network_status.hpp> +#include <mbgl/util/color.hpp> #include <mbgl/util/constants.hpp> #include <mbgl/util/geo.hpp> +#include <mbgl/util/geometry.hpp> #include <mbgl/util/run_loop.hpp> #include <mbgl/util/traits.hpp> @@ -85,20 +87,6 @@ QThreadStorage<std::shared_ptr<mbgl::util::RunLoop>> loop; // Conversion helper functions. -auto fromQMapboxGLShapeAnnotation(const ShapeAnnotation &shapeAnnotation) { - const LineString &lineString = shapeAnnotation.first; - const QString &styleLayer = shapeAnnotation.second; - - mbgl::LineString<double> mbglLineString; - mbglLineString.reserve(lineString.size()); - - for (const Coordinate &coordinate : lineString) { - mbglLineString.emplace_back(mbgl::Point<double> { coordinate.first, coordinate.second }); - } - - return mbgl::StyleSourcedAnnotation { std::move(mbglLineString), styleLayer.toStdString() }; -} - auto fromQStringList(const QStringList &list) { std::vector<std::string> strings; @@ -848,42 +836,114 @@ void QMapboxGL::setTransitionOptions(qint64 duration, qint64 delay) { d_ptr->mapObj->setTransitionOptions(mbgl::style::TransitionOptions{ convert(duration), convert(delay) }); } -mbgl::Annotation fromPointAnnotation(const PointAnnotation &pointAnnotation) { - const Coordinate &coordinate = pointAnnotation.first; - const QString &icon = pointAnnotation.second; - return mbgl::SymbolAnnotation { mbgl::Point<double> { coordinate.second, coordinate.first }, icon.toStdString() }; -} +mbgl::ShapeAnnotationGeometry asMapboxGLGeometry(const QMapbox::ShapeAnnotationGeometry &geometry) { + auto asMapboxGLLineString = [&](const QMapbox::Coordinates &lineString) { + mbgl::LineString<double> mbglLineString; + mbglLineString.reserve(lineString.size()); + for (const auto &coordinate : lineString) { + mbglLineString.emplace_back(mbgl::Point<double> { coordinate.second, coordinate.first }); + } + return mbglLineString; + }; -/*! - Adds a \a point annotation to the map. + auto asMapboxGLMultiLineString = [&](const QMapbox::CoordinatesCollection &multiLineString) { + mbgl::MultiLineString<double> mbglMultiLineString; + mbglMultiLineString.reserve(multiLineString.size()); + for (const auto &lineString : multiLineString) { + mbglMultiLineString.emplace_back(std::forward<mbgl::LineString<double>>(asMapboxGLLineString(lineString))); + } + return mbglMultiLineString; + }; - Returns the unique identifier for the new annotation. + auto asMapboxGLPolygon = [&](const QMapbox::CoordinatesCollection &polygon) { + mbgl::Polygon<double> mbglPolygon; + mbglPolygon.reserve(polygon.size()); + for (const auto &linearRing : polygon) { + mbgl::LinearRing<double> mbglLinearRing; + mbglLinearRing.reserve(linearRing.size()); + for (const auto &coordinate: linearRing) { + mbglLinearRing.emplace_back(mbgl::Point<double> { coordinate.second, coordinate.first }); + } + mbglPolygon.emplace_back(std::move(mbglLinearRing)); + } + return mbglPolygon; + }; - \sa addAnnotationIcon() -*/ -QMapbox::AnnotationID QMapboxGL::addPointAnnotation(const QMapbox::PointAnnotation &point) -{ - return d_ptr->mapObj->addAnnotation(fromPointAnnotation(point)); + auto asMapboxGLMultiPolygon = [&](const QMapbox::CoordinatesCollections &multiPolygon) { + mbgl::MultiPolygon<double> mbglMultiPolygon; + mbglMultiPolygon.reserve(multiPolygon.size()); + for (const auto &polygon : multiPolygon) { + mbglMultiPolygon.emplace_back(std::forward<mbgl::Polygon<double>>(asMapboxGLPolygon(polygon))); + } + return mbglMultiPolygon; + }; + + mbgl::ShapeAnnotationGeometry result; + switch (geometry.type) { + case QMapbox::ShapeAnnotationGeometry::LineStringType: + result = { asMapboxGLLineString(geometry.geometry.first().first()) }; + break; + case QMapbox::ShapeAnnotationGeometry::PolygonType: + result = { asMapboxGLPolygon(geometry.geometry.first()) }; + break; + case QMapbox::ShapeAnnotationGeometry::MultiLineStringType: + result = { asMapboxGLMultiLineString(geometry.geometry.first()) }; + break; + case QMapbox::ShapeAnnotationGeometry::MultiPolygonType: + result = { asMapboxGLMultiPolygon(geometry.geometry) }; + break; + } + + return result; +} + +mbgl::Annotation asMapboxGLAnnotation(const QMapbox::Annotation & annotation) { + if (annotation.canConvert<QMapbox::SymbolAnnotation>()) { + QMapbox::SymbolAnnotation symbolAnnotation = annotation.value<QMapbox::SymbolAnnotation>(); + QMapbox::Coordinate& pair = symbolAnnotation.geometry; + return mbgl::SymbolAnnotation { mbgl::Point<double> { pair.second, pair.first }, symbolAnnotation.icon.toStdString() }; + } else if (annotation.canConvert<QMapbox::LineAnnotation>()) { + QMapbox::LineAnnotation lineAnnotation = annotation.value<QMapbox::LineAnnotation>(); + auto color = mbgl::Color::parse(lineAnnotation.color.name().toStdString()); + return mbgl::LineAnnotation { asMapboxGLGeometry(lineAnnotation.geometry), lineAnnotation.opacity, lineAnnotation.width, { *color } }; + } else if (annotation.canConvert<QMapbox::FillAnnotation>()) { + QMapbox::FillAnnotation fillAnnotation = annotation.value<QMapbox::FillAnnotation>(); + auto color = mbgl::Color::parse(fillAnnotation.color.name().toStdString()); + if (fillAnnotation.outlineColor.canConvert<QColor>()) { + auto outlineColor = mbgl::Color::parse(fillAnnotation.outlineColor.value<QColor>().name().toStdString()); + return mbgl::FillAnnotation { asMapboxGLGeometry(fillAnnotation.geometry), fillAnnotation.opacity, { *color }, { *outlineColor } }; + } else { + return mbgl::FillAnnotation { asMapboxGLGeometry(fillAnnotation.geometry), fillAnnotation.opacity, { *color }, {} }; + } + } else if (annotation.canConvert<QMapbox::StyleSourcedAnnotation>()) { + QMapbox::StyleSourcedAnnotation styleSourcedAnnotation = annotation.value<QMapbox::StyleSourcedAnnotation>(); + return mbgl::StyleSourcedAnnotation { asMapboxGLGeometry(styleSourcedAnnotation.geometry), styleSourcedAnnotation.layerID.toStdString() }; + } + + qWarning() << "Unable to convert annotation:" << annotation; + return {}; } /*! - Updates an existing \a point annotation referred by \a id. + Adds an \a annotation to the map. + + Returns the unique identifier for the new annotation. \sa addAnnotationIcon() */ -void QMapboxGL::updatePointAnnotation(QMapbox::AnnotationID id, const QMapbox::PointAnnotation &point) +QMapbox::AnnotationID QMapboxGL::addAnnotation(const QMapbox::Annotation &annotation) { - d_ptr->mapObj->updateAnnotation(id, fromPointAnnotation(point)); + return d_ptr->mapObj->addAnnotation(asMapboxGLAnnotation(annotation)); } /*! - Adds a \a shape annotation to the map. + Updates an existing \a annotation referred by \a id. - Returns the unique identifier for the new annotation. + \sa addAnnotationIcon() */ -QMapbox::AnnotationID QMapboxGL::addShapeAnnotation(const QMapbox::ShapeAnnotation &shape) +void QMapboxGL::updateAnnotation(QMapbox::AnnotationID id, const QMapbox::Annotation &annotation) { - return d_ptr->mapObj->addAnnotation(fromQMapboxGLShapeAnnotation(shape)); + d_ptr->mapObj->updateAnnotation(id, asMapboxGLAnnotation(annotation)); } /*! @@ -1087,10 +1147,10 @@ void QMapboxGL::resize(const QSize& size, const QSize& framebufferSize) Adds an \a icon to the annotation icon pool. This can be later used by the annotation functions to shown any drawing on the map by referencing its \a name. - Unlike using addIcon() for runtime styling, annotations added with addPointAnnotation() + Unlike using addIcon() for runtime styling, annotations added with addAnnotation() will survive style changes. - \sa addPointAnnotation() + \sa addAnnotation() */ void QMapboxGL::addAnnotationIcon(const QString &name, const QImage &icon) { |