[Qt] Refactor QMapbox Annotations API

This commit is contained in:
Bruno de Oliveira Abinader
2017-01-24 18:05:22 +02:00
parent fb759e949f
commit be43310b6f
6 changed files with 222 additions and 48 deletions

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -1,6 +1,7 @@
#ifndef QMAPBOX_H
#define QMAPBOX_H
#include <QColor>
#include <QList>
#include <QPair>
#include <QVariant>
@@ -10,19 +11,65 @@
namespace QMapbox {
// Reflects mapbox::geometry::point<double>.
typedef QPair<double, double> Coordinate;
typedef QList<Coordinate> LineString;
typedef QPair<Coordinate, double> CoordinateZoom;
// 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;
};
// Reflects mbgl::StyleSourcedAnnotation.
struct Q_DECL_EXPORT StyleSourcedAnnotation {
ShapeAnnotationGeometry geometry;
QString layerID;
};
// SymbolAnnotation, LineAnnotation, FillAnnotation, StyleSourcedAnnotation.
typedef QVariant Annotation;
typedef quint32 AnnotationID;
typedef QList<AnnotationID> AnnotationIDs;
typedef QPair<Coordinate, QString> PointAnnotation;
// FIXME: We need to add support for custom style properties
typedef QPair<LineString, QString> ShapeAnnotation;
// Reflects mbgl::NetworkStatus::Status.
enum NetworkMode {
Online, // Default
@@ -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

View File

@@ -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);

View File

@@ -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>

View File

@@ -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;
};
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;
};
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;
};
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 {};
}
/*!
Adds a \a point annotation to the map.
Adds an \a annotation to the map.
Returns the unique identifier for the new annotation.
\sa addAnnotationIcon()
*/
QMapbox::AnnotationID QMapboxGL::addPointAnnotation(const QMapbox::PointAnnotation &point)
QMapbox::AnnotationID QMapboxGL::addAnnotation(const QMapbox::Annotation &annotation)
{
return d_ptr->mapObj->addAnnotation(fromPointAnnotation(point));
return d_ptr->mapObj->addAnnotation(asMapboxGLAnnotation(annotation));
}
/*!
Updates an existing \a point annotation referred by \a id.
Updates an existing \a annotation referred by \a id.
\sa addAnnotationIcon()
*/
void QMapboxGL::updatePointAnnotation(QMapbox::AnnotationID id, const QMapbox::PointAnnotation &point)
void QMapboxGL::updateAnnotation(QMapbox::AnnotationID id, const QMapbox::Annotation &annotation)
{
d_ptr->mapObj->updateAnnotation(id, fromPointAnnotation(point));
}
/*!
Adds a \a shape annotation to the map.
Returns the unique identifier for the new annotation.
*/
QMapbox::AnnotationID QMapboxGL::addShapeAnnotation(const QMapbox::ShapeAnnotation &shape)
{
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)
{