6#include <QtCore/QDebug>
7#include <QtCore/QMetaProperty>
8#include <QtCore/QRegularExpression>
9#include <QtCore/QStringList>
10#include <QtPositioning/QGeoPath>
11#include <QtPositioning/QGeoPolygon>
12#include <QtQml/QJSValue>
13#include <QtLocation/private/qdeclarativecirclemapitem_p_p.h>
17QByteArray formatPropertyName(
const QByteArray &name)
19 QString nameAsString = QString::fromLatin1(name);
20 static const QRegularExpression camelCaseRegex(QStringLiteral(
"([a-z0-9])([A-Z])"));
21 return nameAsString.replace(camelCaseRegex, QStringLiteral(
"\\1-\\2")).toLower().toLatin1();
24bool isImmutableProperty(
const QByteArray &name)
26 return name == QStringLiteral(
"type") || name == QStringLiteral(
"layer");
29QString getId(QDeclarativeGeoMapItemBase *mapItem)
31 return QStringLiteral(
"QtLocation-") +
32 ((mapItem->objectName().isEmpty()) ? QString::number(quint64(mapItem)) : mapItem->objectName());
38static bool geoRectangleCrossesDateLine(
const QGeoRectangle &rect) {
39 return rect.topLeft().longitude() > rect.bottomRight().longitude();
42QMapbox::Feature featureFromMapRectangle(QDeclarativeRectangleMapItem *mapItem)
44 const QGeoRectangle *rect =
static_cast<
const QGeoRectangle *>(&mapItem->geoShape());
45 QMapbox::Coordinate bottomLeft { rect->bottomLeft().latitude(), rect->bottomLeft().longitude() };
46 QMapbox::Coordinate topLeft { rect->topLeft().latitude(), rect->topLeft().longitude() };
47 QMapbox::Coordinate bottomRight { rect->bottomRight().latitude(), rect->bottomRight().longitude() };
48 QMapbox::Coordinate topRight { rect->topRight().latitude(), rect->topRight().longitude() };
49 if (geoRectangleCrossesDateLine(*rect)) {
50 bottomRight.second += 360.0;
51 topRight.second += 360.0;
53 QMapbox::CoordinatesCollections geometry { { { bottomLeft, bottomRight, topRight, topLeft, bottomLeft } } };
55 return QMapbox::Feature(QMapbox::Feature::PolygonType, geometry, {}, getId(mapItem));
58QMapbox::Feature featureFromMapCircle(QDeclarativeCircleMapItem *mapItem)
60 static const int circleSamples = 128;
61 const QGeoProjectionWebMercator &p =
static_cast<
const QGeoProjectionWebMercator&>(mapItem->map()->geoProjection());
62 QList<QGeoCoordinate> path;
63 QGeoCoordinate leftBound;
64 QDeclarativeCircleMapItemPrivate::calculatePeripheralPoints(path, mapItem->center(), mapItem->radius(), circleSamples, leftBound);
65 QList<QDoubleVector2D> pathProjected;
66 for (
const QGeoCoordinate &c : std::as_const(path))
67 pathProjected << p.geoToMapProjection(c);
68 if (QDeclarativeCircleMapItemPrivateCPU::crossEarthPole(mapItem->center(), mapItem->radius()))
69 QDeclarativeCircleMapItemPrivateCPU::preserveCircleGeometry(pathProjected, mapItem->center(), mapItem->radius(), p);
71 for (
const QDoubleVector2D &c : std::as_const(pathProjected))
72 path << p.mapProjectionToGeo(c);
75 QMapbox::Coordinates coordinates;
76 for (
const QGeoCoordinate &coordinate : path) {
77 coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() };
79 coordinates.append(coordinates.first());
80 QMapbox::CoordinatesCollections geometry { { coordinates } };
81 return QMapbox::Feature(QMapbox::Feature::PolygonType, geometry, {}, getId(mapItem));
84static QMapbox::Coordinates qgeocoordinate2mapboxcoordinate(
const QList<QGeoCoordinate> &crds,
const bool crossesDateline,
bool closed =
false)
86 QMapbox::Coordinates coordinates;
87 for (
const QGeoCoordinate &coordinate : crds) {
88 if (!coordinates.empty() && crossesDateline && qAbs(coordinate.longitude() - coordinates.last().second) > 180.0) {
89 coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() + (coordinate.longitude() >= 0 ? -360.0 : 360.0) };
91 coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() };
94 if (closed && !coordinates.empty() && coordinates.last() != coordinates.first())
95 coordinates.append(coordinates.first());
99QMapbox::Feature featureFromMapPolygon(QDeclarativePolygonMapItem *mapItem)
101 const QGeoPolygon *polygon =
static_cast<
const QGeoPolygon *>(&mapItem->geoShape());
102 const bool crossesDateline = geoRectangleCrossesDateLine(polygon->boundingGeoRectangle());
103 QMapbox::CoordinatesCollections geometry;
104 QMapbox::CoordinatesCollection poly;
105 QMapbox::Coordinates coordinates = qgeocoordinate2mapboxcoordinate(polygon->perimeter(), crossesDateline,
true);
106 poly.push_back(coordinates);
107 for (
int i = 0; i < polygon->holesCount(); ++i) {
108 coordinates = qgeocoordinate2mapboxcoordinate(polygon->holePath(i), crossesDateline,
true);
109 poly.push_back(coordinates);
112 geometry.push_back(poly);
113 return QMapbox::Feature(QMapbox::Feature::PolygonType, geometry, {}, getId(mapItem));
116QMapbox::Feature featureFromMapPolyline(QDeclarativePolylineMapItem *mapItem)
118 const QGeoPath *path =
static_cast<
const QGeoPath *>(&mapItem->geoShape());
119 QMapbox::Coordinates coordinates;
120 const bool crossesDateline = geoRectangleCrossesDateLine(path->boundingGeoRectangle());
121 for (
const QGeoCoordinate &coordinate : path->path()) {
122 if (!coordinates.empty() && crossesDateline && qAbs(coordinate.longitude() - coordinates.last().second) > 180.0) {
123 coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() + (coordinate.longitude() >= 0 ? -360.0 : 360.0) };
125 coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() };
128 QMapbox::CoordinatesCollections geometry { { coordinates } };
130 return QMapbox::Feature(QMapbox::Feature::LineStringType, geometry, {}, getId(mapItem));
133QMapbox::Feature featureFromMapItem(QDeclarativeGeoMapItemBase *item)
135 switch (item->itemType()) {
136 case QGeoMap::MapRectangle:
137 return featureFromMapRectangle(
static_cast<QDeclarativeRectangleMapItem *>(item));
138 case QGeoMap::MapCircle:
139 return featureFromMapCircle(
static_cast<QDeclarativeCircleMapItem *>(item));
140 case QGeoMap::MapPolygon:
141 return featureFromMapPolygon(
static_cast<QDeclarativePolygonMapItem *>(item));
142 case QGeoMap::MapPolyline:
143 return featureFromMapPolyline(
static_cast<QDeclarativePolylineMapItem *>(item));
145 qWarning() <<
"Unsupported QGeoMap item type: " << item->itemType();
146 return QMapbox::Feature();
150QList<QByteArray> getAllPropertyNamesList(QObject *object)
152 const QMetaObject *metaObject = object->metaObject();
153 QList<QByteArray> propertyNames(object->dynamicPropertyNames());
154 for (
int i = metaObject->propertyOffset(); i < metaObject->propertyCount(); ++i) {
155 propertyNames.append(metaObject->property(i).name());
157 return propertyNames;
163QList<QSharedPointer<QMapboxGLStyleChange>>
QMapboxGLStyleChange::addMapItem(QDeclarativeGeoMapItemBase *item,
const QString &before)
165 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
167 switch (item->itemType()) {
168 case QGeoMap::MapRectangle:
169 case QGeoMap::MapCircle:
170 case QGeoMap::MapPolygon:
171 case QGeoMap::MapPolyline:
174 qWarning() <<
"Unsupported QGeoMap item type: " << item->itemType();
178 QMapbox::Feature feature = featureFromMapItem(item);
180 changes << QMapboxGLStyleAddLayer::fromFeature(feature, before);
181 changes << QMapboxGLStyleAddSource::fromFeature(feature);
182 changes << QMapboxGLStyleSetPaintProperty::fromMapItem(item);
183 changes << QMapboxGLStyleSetLayoutProperty::fromMapItem(item);
188QList<QSharedPointer<QMapboxGLStyleChange>>
QMapboxGLStyleChange::removeMapItem(QDeclarativeGeoMapItemBase *item)
190 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
192 const QString id = getId(item);
204 map->setLayoutProperty(m_layer, m_property, m_value);
209 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
211 switch (item->itemType()) {
212 case QGeoMap::MapPolyline:
213 changes = fromMapItem(
static_cast<QDeclarativePolylineMapItem *>(item));
218 changes << QSharedPointer<QMapboxGLStyleChange>(
219 new QMapboxGLStyleSetLayoutProperty(getId(item), QStringLiteral(
"visibility"),
220 item->isVisible() ? QStringLiteral(
"visible") : QStringLiteral(
"none")));
227 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
230 const QString id = getId(item);
241 : m_layer(layer), m_property(property), m_value(value)
248 : m_layer(layer), m_property(property), m_value(value)
254 map->setPaintProperty(m_layer, m_property, m_value);
259 switch (item->itemType()) {
260 case QGeoMap::MapRectangle:
261 return fromMapItem(
static_cast<QDeclarativeRectangleMapItem *>(item));
262 case QGeoMap::MapCircle:
263 return fromMapItem(
static_cast<QDeclarativeCircleMapItem *>(item));
264 case QGeoMap::MapPolygon:
265 return fromMapItem(
static_cast<QDeclarativePolygonMapItem *>(item));
266 case QGeoMap::MapPolyline:
267 return fromMapItem(
static_cast<QDeclarativePolylineMapItem *>(item));
269 qWarning() <<
"Unsupported QGeoMap item type: " << item->itemType();
270 return QList<QSharedPointer<QMapboxGLStyleChange>>();
276 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
279 const QString id = getId(item);
293 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
296 const QString id = getId(item);
310 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
313 const QString id = getId(item);
327 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
330 const QString id = getId(item);
346 map->addLayer(m_params, m_before);
349QSharedPointer<QMapboxGLStyleChange>
QMapboxGLStyleAddLayer::fromFeature(
const QMapbox::Feature &feature,
const QString &before)
352 layer->m_params[QStringLiteral(
"id")] = feature.id;
353 layer->m_params[QStringLiteral(
"source")] = feature.id;
355 switch (feature.type) {
356 case QMapbox::Feature::PointType:
357 layer->m_params[QStringLiteral(
"type")] = QStringLiteral(
"circle");
359 case QMapbox::Feature::LineStringType:
360 layer->m_params[QStringLiteral(
"type")] = QStringLiteral(
"line");
362 case QMapbox::Feature::PolygonType:
363 layer->m_params[QStringLiteral(
"type")] = QStringLiteral(
"fill");
367 layer->m_before = before;
377 map->removeLayer(m_id);
389 map->updateSource(m_id, m_params);
396 source->m_id = feature.id.toString();
397 source->m_params[QStringLiteral(
"type")] = QStringLiteral(
"geojson");
398 source->m_params[QStringLiteral(
"data")] = QVariant::fromValue<QMapbox::Feature>(feature);
405 return fromFeature(featureFromMapItem(item));
413 map->removeSource(m_id);
425 map->setFilter(m_layer, m_filter);
432 map->addImage(m_name, m_sprite);
void apply(QMapboxGL *map) override
void apply(QMapboxGL *map) override
void apply(QMapboxGL *map) override
QMapboxGLStyleRemoveLayer(const QString &id)
void apply(QMapboxGL *map) override
QMapboxGLStyleRemoveSource(const QString &id)
void apply(QMapboxGL *map) override
void apply(QMapboxGL *map) override
void apply(QMapboxGL *map) override
void apply(QMapboxGL *map) override