#include "qmapboxgl_p.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include QMapboxGLSettings::QMapboxGLSettings() : m_cacheMaximumSize(mbgl::util::DEFAULT_MAX_CACHE_SIZE) , m_cacheDatabasePath(":memory:") , m_assetPath(QCoreApplication::applicationDirPath()) { } unsigned QMapboxGLSettings::cacheDatabaseMaximumSize() const { return m_cacheMaximumSize; } void QMapboxGLSettings::setCacheDatabaseMaximumSize(unsigned size) { m_cacheMaximumSize = size; } QString QMapboxGLSettings::cacheDatabasePath() const { return m_cacheDatabasePath; } void QMapboxGLSettings::setCacheDatabasePath(const QString &path) { m_cacheDatabasePath = path; } QString QMapboxGLSettings::assetPath() const { return m_assetPath; } void QMapboxGLSettings::setAssetPath(const QString &path) { m_assetPath = path; } QString QMapboxGLSettings::accessToken() const { return m_accessToken; } void QMapboxGLSettings::setAccessToken(const QString &token) { m_accessToken = token; } QMapboxGL::QMapboxGL(QObject *parent_, const QMapboxGLSettings &settings) : QObject(parent_) , d_ptr(new QMapboxGLPrivate(this, settings)) { d_ptr->fileSourceObj->setAccessToken(settings.accessToken().toStdString()); d_ptr->mapObj = std::make_unique(*d_ptr, *d_ptr->fileSourceObj, mbgl::MapMode::Continuous, mbgl::GLContextMode::Shared); } QMapboxGL::~QMapboxGL() { delete d_ptr; } void QMapboxGL::cycleDebugOptions() { d_ptr->mapObj->cycleDebugOptions(); } QString QMapboxGL::styleJSON() const { return QString::fromStdString(d_ptr->mapObj->getStyleJSON()); } QString QMapboxGL::styleURL() const { return QString::fromStdString(d_ptr->mapObj->getStyleURL()); } void QMapboxGL::setStyleJSON(const QString &style) { d_ptr->mapObj->setStyleJSON(style.toStdString()); } void QMapboxGL::setStyleURL(const QString &url) { d_ptr->mapObj->setStyleURL(url.toStdString()); } double QMapboxGL::latitude() const { return d_ptr->mapObj->getLatLng().latitude; } void QMapboxGL::setLatitude(double latitude_) { d_ptr->mapObj->setLatLng(mbgl::LatLng { latitude_, longitude() }); } double QMapboxGL::longitude() const { return d_ptr->mapObj->getLatLng().longitude; } void QMapboxGL::setLongitude(double longitude_) { d_ptr->mapObj->setLatLng(mbgl::LatLng { latitude(), longitude_ }); } double QMapboxGL::scale() const { return d_ptr->mapObj->getScale(); } void QMapboxGL::setScale(double scale_, const QPointF ¢er, int milliseconds) { d_ptr->mapObj->setScale(scale_, mbgl::ScreenCoordinate{ center.x(), center.y() }, std::chrono::milliseconds(milliseconds)); } double QMapboxGL::zoom() const { return d_ptr->mapObj->getZoom(); } void QMapboxGL::setZoom(double zoom_, int milliseconds) { d_ptr->mapObj->setZoom(zoom_, std::chrono::milliseconds(milliseconds)); } double QMapboxGL::minimumZoom() const { return d_ptr->mapObj->getMinZoom(); } double QMapboxGL::maximumZoom() const { return d_ptr->mapObj->getMaxZoom(); } QMapboxGL::Coordinate QMapboxGL::coordinate() const { const mbgl::LatLng& latLng = d_ptr->mapObj->getLatLng(); return Coordinate(latLng.latitude, latLng.longitude); } void QMapboxGL::setCoordinate(const Coordinate &coordinate_, int milliseconds) { d_ptr->mapObj->setLatLng( mbgl::LatLng { coordinate_.first, coordinate_.second }, mbgl::Duration(std::chrono::milliseconds(milliseconds))); } void QMapboxGL::setCoordinateZoom(const Coordinate &coordinate_, double zoom_, int milliseconds) { d_ptr->mapObj->setLatLngZoom( mbgl::LatLng { coordinate_.first, coordinate_.second }, zoom_, std::chrono::milliseconds(milliseconds)); } double QMapboxGL::bearing() const { return d_ptr->mapObj->getBearing(); } void QMapboxGL::setBearing(double degrees, int milliseconds) { d_ptr->mapObj->setBearing(degrees, mbgl::Duration(std::chrono::milliseconds(milliseconds))); } void QMapboxGL::setBearing(double degrees, const QPointF ¢er) { d_ptr->mapObj->setBearing(degrees, mbgl::ScreenCoordinate { center.x(), center.y() }); } double QMapboxGL::pitch() const { return d_ptr->mapObj->getPitch(); } void QMapboxGL::setPitch(double pitch_, int milliseconds) { d_ptr->mapObj->setPitch(pitch_, std::chrono::milliseconds(milliseconds)); } QMapboxGL::NorthOrientation QMapboxGL::northOrientation() const { using NO = mbgl::NorthOrientation; switch (d_ptr->mapObj->getNorthOrientation()) { case NO::Rightwards: return NorthRightwards; case NO::Downwards: return NorthDownwards; case NO::Leftwards: return NorthLeftwards; default: return NorthUpwards; } } void QMapboxGL::setNorthOrientation(NorthOrientation orientation) { using NO = mbgl::NorthOrientation; switch (orientation) { case NorthRightwards: d_ptr->mapObj->setNorthOrientation(NO::Rightwards); break; case NorthDownwards: d_ptr->mapObj->setNorthOrientation(NO::Downwards); break; case NorthLeftwards: d_ptr->mapObj->setNorthOrientation(NO::Leftwards); break; default: d_ptr->mapObj->setNorthOrientation(NO::Upwards); break; } } void QMapboxGL::setGestureInProgress(bool inProgress) { d_ptr->mapObj->setGestureInProgress(inProgress); } void QMapboxGL::addClass(const QString &className) { d_ptr->mapObj->addClass(className.toStdString()); } void QMapboxGL::removeClass(const QString &className) { d_ptr->mapObj->removeClass(className.toStdString()); } bool QMapboxGL::hasClass(const QString &className) const { return d_ptr->mapObj->hasClass(className.toStdString()); } void QMapboxGL::setClasses(const QStringList &classNames) { std::vector mbglClassNames; mbglClassNames.reserve(classNames.size()); for (const QString &className : classNames) { mbglClassNames.emplace_back(className.toStdString()); } d_ptr->mapObj->setClasses(mbglClassNames); } QStringList QMapboxGL::getClasses() const { QStringList classNames; for (const std::string &mbglClass : d_ptr->mapObj->getClasses()) { classNames << QString::fromStdString(mbglClass); } return classNames; } mbgl::PointAnnotation fromQMapboxGLPointAnnotation(const QMapboxGL::PointAnnotation &pointAnnotation) { const QMapboxGL::Coordinate &coordinate = pointAnnotation.first; const QString &icon = pointAnnotation.second; return { { coordinate.first, coordinate.second }, icon.toStdString() }; } QMapboxGL::AnnotationID QMapboxGL::addPointAnnotation(const PointAnnotation &pointAnnotation) { return d_ptr->mapObj->addPointAnnotation(fromQMapboxGLPointAnnotation(pointAnnotation)); } QMapboxGL::AnnotationIDs QMapboxGL::addPointAnnotations(const PointAnnotations &pointAnnotations) { std::vector mbglPointAnnotations; mbglPointAnnotations.reserve(pointAnnotations.size()); for (const PointAnnotation &pointAnnotation : pointAnnotations) { mbglPointAnnotations.emplace_back(fromQMapboxGLPointAnnotation(pointAnnotation)); } AnnotationIDs ids; for (const mbgl::AnnotationID &id : d_ptr->mapObj->addPointAnnotations(mbglPointAnnotations)) { ids << id; } return ids; } mbgl::ShapeAnnotation fromQMapboxGLShapeAnnotation(const QMapboxGL::ShapeAnnotation &shapeAnnotation) { const QMapboxGL::CoordinateSegments &segments = shapeAnnotation.first; const QString &styleLayer = shapeAnnotation.second; mbgl::AnnotationSegments mbglAnnotationSegments; mbglAnnotationSegments.reserve(segments.size()); for (const QMapboxGL::Coordinates &coordinates : segments) { mbgl::AnnotationSegment mbglAnnotationSegment; mbglAnnotationSegment.reserve(coordinates.size()); for (const QMapboxGL::Coordinate &coordinate : coordinates) { mbgl::LatLng mbglCoordinate(coordinate.first, coordinate.second); mbglAnnotationSegment.emplace_back(mbglCoordinate); } mbglAnnotationSegments.emplace_back(mbglAnnotationSegment); } return { mbglAnnotationSegments, styleLayer.toStdString() }; } QMapboxGL::AnnotationID QMapboxGL::addShapeAnnotation(const ShapeAnnotation &shapeAnnotation) { return d_ptr->mapObj->addShapeAnnotation(fromQMapboxGLShapeAnnotation(shapeAnnotation)); } QMapboxGL::AnnotationIDs QMapboxGL::addShapeAnnotations(const ShapeAnnotations &shapeAnnotations) { std::vector mbglShapeAnnotations; mbglShapeAnnotations.reserve(shapeAnnotations.size()); for (const ShapeAnnotation &shapeAnnotation : shapeAnnotations) { mbglShapeAnnotations.emplace_back(fromQMapboxGLShapeAnnotation(shapeAnnotation)); } AnnotationIDs ids; for (const mbgl::AnnotationID &id : d_ptr->mapObj->addShapeAnnotations(mbglShapeAnnotations)) { ids << id; } return ids; } void QMapboxGL::removeAnnotation(AnnotationID annotationID) { d_ptr->mapObj->removeAnnotation(annotationID); } void QMapboxGL::removeAnnotations(const AnnotationIDs &annotationIDs) { std::vector mbglAnnotationIds; mbglAnnotationIds.reserve(annotationIDs.size()); for (const AnnotationID annotationID : annotationIDs) { mbglAnnotationIds.emplace_back(annotationID); } d_ptr->mapObj->removeAnnotations(mbglAnnotationIds); } bool QMapboxGL::isRotating() const { return d_ptr->mapObj->isRotating(); } bool QMapboxGL::isScaling() const { return d_ptr->mapObj->isScaling(); } bool QMapboxGL::isPanning() const { return d_ptr->mapObj->isPanning(); } bool QMapboxGL::isFullyLoaded() const { return d_ptr->mapObj->isFullyLoaded(); } void QMapboxGL::moveBy(const QPointF &offset) { d_ptr->mapObj->moveBy(mbgl::ScreenCoordinate { offset.x(), offset.y() }); } void QMapboxGL::scaleBy(double scale_, const QPointF ¢er, int milliseconds) { d_ptr->mapObj->scaleBy( scale_, mbgl::ScreenCoordinate { center.x(), center.y() }, std::chrono::milliseconds(milliseconds)); } void QMapboxGL::rotateBy(const QPointF &first, const QPointF &second) { d_ptr->mapObj->rotateBy( mbgl::ScreenCoordinate { first.x(), first.y() }, mbgl::ScreenCoordinate { second.x(), second.y() }); } void QMapboxGL::resize(const QSize& size) { if (d_ptr->size == size) return; d_ptr->size = size; d_ptr->mapObj->update(mbgl::Update::Dimensions); } void QMapboxGL::addAnnotationIcon(const QString &name, const QImage &sprite) { if (sprite.isNull()) return; const QImage swapped = sprite .rgbSwapped() .convertToFormat(QImage::Format_ARGB32_Premultiplied); auto img = std::make_unique(swapped.byteCount()); memcpy(img.get(), swapped.constBits(), swapped.byteCount()); d_ptr->mapObj->addAnnotationIcon(name.toStdString(), std::make_shared( mbgl::PremultipliedImage { size_t(swapped.width()), size_t(swapped.height()), std::move(img) }, 1.0)); } QPointF QMapboxGL::pixelForCoordinate(const Coordinate &coordinate_) const { const mbgl::vec2 pixel = d_ptr->mapObj->pixelForLatLng(mbgl::LatLng { coordinate_.first, coordinate_.second }); return QPointF(pixel.x, pixel.y); } QMapboxGL::Coordinate QMapboxGL::coordinateForPixel(const QPointF &pixel) const { const mbgl::LatLng latLng = d_ptr->mapObj->latLngForPixel(mbgl::ScreenCoordinate { pixel.x(), pixel.y() }); return Coordinate(latLng.latitude, latLng.longitude); } void QMapboxGL::render() { d_ptr->mapObj->render(); } void QMapboxGL::connectionEstablished() { d_ptr->connectionEstablished(); } QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settings) : QObject(q) , size(0, 0) , q_ptr(q) , fileSourceObj(std::make_unique( settings.cacheDatabasePath().toStdString(), settings.assetPath().toStdString(), settings.cacheDatabaseMaximumSize())) , mapObj(std::make_unique( *this, *fileSourceObj, mbgl::MapMode::Continuous, mbgl::GLContextMode::Shared)) { connect(this, SIGNAL(needsRendering()), q_ptr, SIGNAL(needsRendering())); connect(this, SIGNAL(mapRegionDidChange()), q_ptr, SIGNAL(mapRegionDidChange())); } QMapboxGLPrivate::~QMapboxGLPrivate() { } float QMapboxGLPrivate::getPixelRatio() const { // FIXME: Should handle pixel ratio. return 1.0; } std::array QMapboxGLPrivate::getSize() const { return {{ static_cast(size.width()), static_cast(size.height()) }}; } std::array QMapboxGLPrivate::getFramebufferSize() const { return getSize(); } void QMapboxGLPrivate::invalidate() { emit needsRendering(); } void QMapboxGLPrivate::notifyMapChange(mbgl::MapChange change) { // Map thread. switch (change) { case mbgl::MapChangeRegionDidChange: case mbgl::MapChangeRegionDidChangeAnimated: case mbgl::MapChangeRegionIsChanging: emit mapRegionDidChange(); break; default: break; } } void QMapboxGLPrivate::connectionEstablished() { mbgl::NetworkStatus::Reachable(); }