Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions src/core/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <mbgl/map/map_options.hpp>
#include <mbgl/math/log2.hpp>
#include <mbgl/math/minmax.hpp>
#include <mbgl/renderer/query.hpp>
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/storage/file_source_manager.hpp>
#include <mbgl/storage/network_status.hpp>
Expand Down Expand Up @@ -1622,6 +1623,16 @@ void Map::setConnectionEstablished() {
have changed. This can be caused by a style change or adding a new source.
*/

std::vector<mbgl::Feature> Map::queryRenderedFeatures(const mbgl::ScreenCoordinate &point,
const mbgl::RenderedQueryOptions &options) const {
return d_ptr->queryRenderedFeatures(point, options);
}

std::vector<mbgl::Feature> Map::queryRenderedFeatures(const mbgl::ScreenBox &screenBox,
const mbgl::RenderedQueryOptions &options) const {
return d_ptr->queryRenderedFeatures(screenBox, options);
}

/*! \cond PRIVATE */

MapPrivate::MapPrivate(Map *map, const Settings &settings, const QSize &size, qreal pixelRatio_)
Expand Down Expand Up @@ -1791,6 +1802,24 @@ bool MapPrivate::setProperty(const PropertySetter &setter,
return true;
}

std::vector<mbgl::Feature> MapPrivate::queryRenderedFeatures(const mbgl::ScreenCoordinate &point,
const mbgl::RenderedQueryOptions &options) const {
if (m_mapRenderer == nullptr) {
return {};
}

return m_mapRenderer->queryRenderedFeatures(point, options);
}

std::vector<mbgl::Feature> MapPrivate::queryRenderedFeatures(const mbgl::ScreenBox &box,
const mbgl::RenderedQueryOptions &options) const {
if (m_mapRenderer == nullptr) {
return {};
}

return m_mapRenderer->queryRenderedFeatures(box, options);
}

/*! \endcond */

} // namespace QMapLibre
9 changes: 9 additions & 0 deletions src/core/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
#include <QMapLibre/Settings>
#include <QMapLibre/Types>

#include <mbgl/renderer/query.hpp>
#include <mbgl/util/geo.hpp>

#include <QtCore/QMargins>
#include <QtCore/QObject>
#include <QtCore/QPointF>
Expand Down Expand Up @@ -175,6 +178,12 @@ class Q_MAPLIBRE_CORE_EXPORT Map : public QObject {
void destroyRenderer();
void setOpenGLFramebufferObject(quint32 fbo, const QSize &size);

std::vector<mbgl::Feature> queryRenderedFeatures(const mbgl::ScreenCoordinate &,
const mbgl::RenderedQueryOptions &options = {}) const;

std::vector<mbgl::Feature> queryRenderedFeatures(const mbgl::ScreenBox &screenBox,
const mbgl::RenderedQueryOptions &options = {}) const;

public slots:
void render();
void setConnectionEstablished();
Expand Down
6 changes: 6 additions & 0 deletions src/core/map_p.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ class MapPrivate : public QObject, public mbgl::RendererFrontend {
mbgl::EdgeInsets margins;
std::unique_ptr<mbgl::Map> mapObj{};

std::vector<mbgl::Feature> queryRenderedFeatures(const mbgl::ScreenCoordinate &,
const mbgl::RenderedQueryOptions &options = {}) const;

std::vector<mbgl::Feature> queryRenderedFeatures(const mbgl::ScreenBox &screenBox,
const mbgl::RenderedQueryOptions &options = {}) const;

public slots:
void requestRendering();

Expand Down
11 changes: 11 additions & 0 deletions src/core/map_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "utils/scheduler.hpp"

#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/util/geo.hpp>

#include <QtCore/QThreadStorage>

Expand Down Expand Up @@ -105,6 +106,16 @@ void MapRenderer::setObserver(mbgl::RendererObserver *observer) {
m_renderer->setObserver(observer);
}

std::vector<mbgl::Feature> MapRenderer::queryRenderedFeatures(const mbgl::ScreenCoordinate &point,
const mbgl::RenderedQueryOptions &options) const {
return m_renderer->queryRenderedFeatures(point, options);
}

std::vector<mbgl::Feature> MapRenderer::queryRenderedFeatures(const mbgl::ScreenBox &box,
const mbgl::RenderedQueryOptions &options) const {
return m_renderer->queryRenderedFeatures(box, options);
}

/*! \endcond */

} // namespace QMapLibre
12 changes: 9 additions & 3 deletions src/core/map_renderer_p.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include <mbgl/renderer/renderer.hpp>
#include <mbgl/renderer/renderer_observer.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/util.hpp>

#include <QtCore/QObject>
Expand All @@ -33,16 +34,21 @@ class MapRenderer : public QObject {
Q_OBJECT

public:
MapRenderer(qreal pixelRatio, Settings::GLContextMode, const QString &localFontFamily);
MapRenderer(qreal pixelRatio, Settings::GLContextMode, const QString& localFontFamily);
~MapRenderer() override;

void render();
void updateFramebuffer(quint32 fbo, const mbgl::Size &size);
void setObserver(mbgl::RendererObserver *observer);
void updateFramebuffer(quint32 fbo, const mbgl::Size& size);
void setObserver(mbgl::RendererObserver* observer);

// Thread-safe, called by the Frontend
void updateParameters(std::shared_ptr<mbgl::UpdateParameters> parameters);

std::vector<mbgl::Feature> queryRenderedFeatures(const mbgl::ScreenCoordinate&,
const mbgl::RenderedQueryOptions& options = {}) const;

std::vector<mbgl::Feature> queryRenderedFeatures(const mbgl::ScreenBox& screenBox,
const mbgl::RenderedQueryOptions& options = {}) const;
signals:
void needsRendering();

Expand Down
6 changes: 6 additions & 0 deletions src/widgets/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
set(MLN_CORE_PATH "${PROJECT_SOURCE_DIR}/vendor/maplibre-native" CACHE STRING "MapLibre Native Core source path" FORCE)

# Public headers
string(TOLOWER ${MLN_QT_NAME}Widgets MLN_QT_WIDGETS_LOWERCASE)
set(MLNQtWidgets_Headers
Expand Down Expand Up @@ -73,6 +75,10 @@ target_include_directories(
${CMAKE_CURRENT_BINARY_DIR}/include
${CMAKE_SOURCE_DIR}/src/core
${CMAKE_BINARY_DIR}/src/core/include
${MLN_CORE_PATH}/include
${MLN_CORE_PATH}/vendor/mapbox-base/deps/variant/include
${MLN_CORE_PATH}/vendor/mapbox-base/include
${MLN_CORE_PATH}/vendor/mapbox-base/deps/geometry.hpp/include
)

# Common link libraries
Expand Down
6 changes: 6 additions & 0 deletions test/core/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# set(MLN_CORE_PATH "${PROJECT_SOURCE_DIR}/vendor/maplibre-native" CACHE STRING "MapLibre Native Core source path" FORCE)

if(Qt5_FOUND)
return()
endif()
Expand All @@ -19,6 +21,10 @@ target_include_directories(
${CMAKE_SOURCE_DIR}/src/core
${CMAKE_BINARY_DIR}/src/core/include
${CMAKE_SOURCE_DIR}/test/common
${MLN_CORE_PATH}/include
${MLN_CORE_PATH}/vendor/mapbox-base/deps/variant/include
${MLN_CORE_PATH}/vendor/mapbox-base/include
${MLN_CORE_PATH}/vendor/mapbox-base/deps/geometry.hpp/include
)

find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Test REQUIRED)
Expand Down
7 changes: 7 additions & 0 deletions test/widgets/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
set(MLN_CORE_PATH "${PROJECT_SOURCE_DIR}/vendor/maplibre-native" CACHE STRING "MapLibre Native Core source path" FORCE)

set(test_sources
../common/test_rendering.cpp ../common/test_rendering.hpp
gl_tester.cpp gl_tester.hpp
Expand All @@ -17,6 +19,11 @@ target_include_directories(
${CMAKE_SOURCE_DIR}/src/widgets
${CMAKE_BINARY_DIR}/src/widgets/include
${CMAKE_SOURCE_DIR}/test/common
${CMAKE_BINARY_DIR}/include
${MLN_CORE_PATH}/include
${MLN_CORE_PATH}/vendor/mapbox-base/deps/variant/include
${MLN_CORE_PATH}/vendor/mapbox-base/include
${MLN_CORE_PATH}/vendor/mapbox-base/deps/geometry.hpp/include
)

find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Test REQUIRED)
Expand Down
57 changes: 56 additions & 1 deletion test/widgets/gl_tester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,64 @@ constexpr int kAnimationDuration = 5000;

namespace QMapLibre {

GLTester::GLTester(const QMapLibre::Settings &settings)
struct IdentifierToQStringVisitor {
QString operator()(const std::string& value) const { return QString::fromStdString(value); }
QString operator()(uint64_t value) const { return QString::number(value); }
QString operator()(int64_t value) const { return QString::number(value); }
QString operator()(double value) const { return QString::number(value); }
QString operator()(mapbox::feature::null_value_t) const { return QStringLiteral("null"); }
};

QString identifierToQString(const mapbox::feature::identifier& id) {
return mapbox::util::apply_visitor(IdentifierToQStringVisitor(), id);
}

GLTester::GLTester(const QMapLibre::Settings& settings)
: GLWidget(settings) {}

QString valueToQString(const mapbox::feature::value& val) {
if (val.is<std::string>()) {
return QString::fromStdString(val.get<std::string>());
} else if (val.is<bool>()) {
return val.get<bool>() ? "true" : "false";
} else if (val.is<double>()) {
return QString::number(val.get<double>());
} else if (val.is<uint64_t>()) {
return QString::number(val.get<uint64_t>());
} else if (val.is<int64_t>()) {
return QString::number(val.get<int64_t>());
} else if (val.is<mapbox::feature::null_value_t>()) {
return "(null)";
} else {
return "(unsupported)";
}
}

void GLTester::initializeQuery() {
connect(this, &GLTester::onMousePressEvent, [this](Coordinate coordinate) {
qDebug() << "onMousePressEvent" << coordinate;

/* This feels stupid, need to change the interface. */
QPointF pixel = map()->pixelForCoordinate(coordinate);
mbgl::ScreenCoordinate screenPoint(pixel.x(), pixel.y());

mbgl::RenderedQueryOptions options;
options.layerIDs = {"countries-fill"};

std::vector<mbgl::Feature> features = map()->queryRenderedFeatures(screenPoint, options);

for (const auto& feature : features) {
qDebug() << "Feature ID:" << identifierToQString(feature.id);

for (const auto& [key, value] : feature.properties) {
QString keyStr = QString::fromStdString(key);
QString valueStr = valueToQString(value);
qDebug() << keyStr << ":" << valueStr;
}
}
});
}

void GLTester::initializeAnimation() {
m_bearingAnimation = std::make_unique<QPropertyAnimation>(map(), "bearing");
m_zoomAnimation = std::make_unique<QPropertyAnimation>(map(), "zoom");
Expand Down
1 change: 1 addition & 0 deletions test/widgets/gl_tester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class GLTester : public GLWidget {
explicit GLTester(const QMapLibre::Settings &);

void initializeAnimation();
void initializeQuery();
int selfTest();

private slots:
Expand Down
21 changes: 21 additions & 0 deletions test/widgets/test_widgets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ private slots:
void testGLWidgetNoProvider();
void testGLWidgetMapLibreProvider();
void testGLWidgetStyle();
void testGLWidgetQuery();
};

void TestWidgets::testGLWidgetNoProvider() {
Expand Down Expand Up @@ -69,6 +70,26 @@ void TestWidgets::testGLWidgetStyle() {
QTest::qWait(tester->selfTest());
}

void TestWidgets::testGLWidgetQuery() {
const std::unique_ptr<QSurface> surface = QMapLibre::createTestSurface(QSurface::Window);
QVERIFY(surface != nullptr);

QOpenGLContext ctx;
QVERIFY(ctx.create());
QVERIFY(ctx.makeCurrent(surface.get()));

QMapLibre::Styles styles;
styles.append(QMapLibre::Style("https://demotiles.maplibre.org/style.json", "Demo tiles"));

QMapLibre::Settings settings;
settings.setStyles(styles);
auto tester = std::make_unique<QMapLibre::GLTester>(settings);
tester->show();
QTest::qWait(100);
tester->initializeQuery();
QTest::qWait(10000);
}

// NOLINTNEXTLINE(misc-const-correctness)
QTEST_MAIN(TestWidgets)
#include "test_widgets.moc"
Loading