rinigus / mapbox-gl-qml

Unofficial Mapbox GL Native bindings for Qt QML
GNU Lesser General Public License v3.0
38 stars 10 forks source link

How to add images to the map at location #46

Closed patrickjane closed 3 years ago

patrickjane commented 3 years ago

I am trying to add a PNG image to the map at a given location. The API description is pretty unclear to me regarding images. While I was able to paint a circle as given by the examples, calling map.addImagePath("position-icon", Qt.resolvedUrl("qrc:///graphics/myimage.png")) returns false. According to the docs it should return true when the image was successfully added.

I can add a qml image like so:

   Image {
      z: 100
      source: "qrc:///graphics/myimage.png"
      x: 0
      y: 0
      width: 100
      height: 100
   }

And it will display just fine, so, the image exists, and can be accessed via qrc:///graphics/myimage.png. Why does the function return false?

Also, I fail to understand how I could assign a location to the added image. Do I need to add a source? How do I tie source and image?

Sidequestion: I guess MapboxMap does not just plain support MapQuickItem so any QML item could be added to the map?

rinigus commented 3 years ago

Corresponding section dealing with image loading: https://github.com/rinigus/mapbox-gl-qml/blob/master/src/qquickitemmapboxgl.cpp#L761

Images can be displayed using different means.

The method that you were calling is to integrate it into Mapbox map and display using Mapbox style. Example use is in Pure Maps. See initialization in Component.onCompleted and update of location at onPositionShownChanged.

Mapbox styles are described at https://docs.mapbox.com/mapbox-gl-js/style-spec/ with layers at https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/ (you are interested in symbol type). I would suggest to look also at examples on that page.

Depending on the image, this integration is recommended way for markers (current location, POIs), but also satellite images/videos (see Mapbox example with added video).

Alternative would be to use QML items and draw them on top of the map. See https://github.com/rinigus/mapbox-gl-qml/blob/master/api.md#tracking-locations-on-the-map for corresponding section.

Now coming back to your question regarding why it returns false - I don't know exactly. I can only speculate that for some reason image loading failed.

patrickjane commented 3 years ago

How would I draw e.g. a Rectangle on top of the map? I can see the API allows to associate coordinates with an ID (trackLocation), however it is unclear to me how I would add the actual QML item to said coordinates?

rinigus commented 3 years ago

You would have to add an item to pixel coordinates returned by locationChanged signal. Bit tricky, but possible. In principle,

patrickjane commented 3 years ago

Okay, sounds rather complicated. I actually only need to show (clickable) points of interest. I understand that the API resembles the Mapbox GL JS spec, yet I find it really difficult to understand/create simple tasks.

Your recommended way was to use layers, using the symbol type. I'm afraid I really sound stupid here, but I still don't get how I would add the image using the layers.

I understand that I can create a source (which is basically a named pair of coordinates), and add a layer for a given source, into which I can paint (using setPaintProperty). So tying the source with a layer enables one to paint at a given location.
But the question remains how I would tell the layer to "use" the image, or how I would assign coordinates to the image. I don't see any connection between image and source or image and layer in the API.

I guess I shall do something like:

var res = map.addImagePath("position-icon", Qt.resolvedUrl("qrc:///graphics/myimage.png"))   // returns false, but still

map.addLayer("position-something??", {"type": "symbol", "source": "???"}, "waterway-label")

I think I still didn't get the idea of how the API works, so it currently does not make sense to me and I am stuck.

rinigus commented 3 years ago

In this case it is rather simple as soon as you figure out the API. It is designed for cases like this and let me help you.

I'll respond later tonight or tomorrow morning.

rinigus commented 3 years ago

Let's start with showing just circles in your POIs. Later, we will change to icons

In Mapbox, to display those icons:

At this point, you should be able to see POIs shown as circles. If you add names, those should be shown as well. Note that as vector tiles maps are layered internally, it is possible also to incorporate your layer somewhere specific in the stack. But, as it sounds from your description, it is not needed.

To process clicks, you would need to add MapboxMapGestureArea https://github.com/rinigus/mapbox-gl-qml/blob/master/app/qml/main.qml#L95 . For just clicking, I suggest to set activeClickedGeo: true and follow onClickedGeo signal. Look into how it is implemented in Pure Maps: https://github.com/rinigus/pure-maps/blob/master/qml/MapGestureArea.qml . Notice that all geo clicks are checked by running all POIs in for loop to find the closest POI and check whether click was close enough. See method coordinatesMatch in that area implementation on how to link geo coordinates to distance on screen.

To get to show images in the layers, you would have to use bit more complicated layers. See https://github.com/rinigus/pure-maps/blob/master/qml/Map.qml#L359 for layer properties, how it is added https://github.com/rinigus/pure-maps/blob/master/qml/Map.qml#L457 and how corresponding image was added https://github.com/rinigus/pure-maps/blob/master/qml/Map.qml#L449

But I would suggest to start from the top and use circle first and proceed accordingly.

patrickjane commented 3 years ago

Thanks, got it to work, both the image and the clicking.

Its a bit unfortunate that appearently the image/symbol cannot reference icons coming from the resource file; it won't work when addressing e.g. "qrc:///graphics/something.png", but it will when taking e.g. "/usr/share/icons/.../something.png".

It does work, however it will force me to adjust the app to install icons in the filesystem accordingly. Would there be another solution maybe?

Oh and also do you happen to know if Mapbox GL QML can be run in the SailfishOS emulator?

rinigus commented 3 years ago

No idea regarding Mapbox GL QML in SFOS emulator - not sure whether its GLES drivers are OK for it.

Re qrc - Corresponding section dealing with image loading: https://github.com/rinigus/mapbox-gl-qml/blob/master/src/qquickitemmapboxgl.cpp#L761 . If you can figure out why it doesn't load your image, patches are welcome

patrickjane commented 3 years ago

Got it. While in QML it should be "qrc:///graphics/foo.png" in C++ (and therefore the addImagePath as well) it must be ":/graphics/foo.png".

rinigus commented 3 years ago

Excellent!

rinigus commented 3 years ago

Closing then here