Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Large amount of QML MapItems



  • Hi everyone :)

    I am currently trying to plot a large amount of items onto a QML Map (30,000 - 120,000 points). These items shall be updated dependent of the position of a QSlider. Performance decreases strongly from about 1,000 items upwards, when I use 30,000 it takes several minutes until the QML Map has all the data visualized and is responsive again. I have a machine which is absolutely capable of fulfilling this task in general, so I think the problem is QML. I am using Qt 5.8.

    Is there any way to improve this performance or is it just not possible with a QML-map to plot so many MapItems at a time? I tried MapCircles, Polylines, Polygons and MapQuickItems with images, but for me it seems like the performance issue just arises from adding this amount of MapItems, as I could not see a significant difference in processing time between these types.

    I have more data on the map visualized, which should not be refreshed every time the QSlider is moved. Even though I tried just to clear all MapItems and add the new ones for performance tests, but even this did not improve the performance.

    My code (a bit abstracted) looks like this:

    ///-------------- Widget.cpp-----------------///
    void ProcessInput(int qslider_pos) {
          QVariantList lat_vec;
          QVariantList lon_vec;
    
          // Fill vectors with lateral and longitudinal positions
          // ...
    
          // Clean current points on map and draw new ones
          SendToQmlFuncRemovePoints();
          SendToQmlFuncAddPoints(lat_vec, lon_vec);
    }
    
    void QmlConnector::SendToQmlFuncRemovePoints()
    {
        QVariant returnedValue;
        QMetaObject::invokeMethod(QmlMapSingleton::instance()->GetRoot(), "remove_points",
            Q_RETURN_ARG(QVariant, returnedValue));
    }
    
    void QmlConnector::SendToQmlFuncAddPoints(QVariantList input_one, QVariantList input_two)
    {
        QVariant returnedValue;
        QMetaObject::invokeMethod(QmlMapSingleton::instance()->GetRoot(), "add_points",
            Q_RETURN_ARG(QVariant, returnedValue),
            Q_ARG(QVariant, QVariant::fromValue(input_one)), Q_ARG(QVariant, QVariant::fromValue(input_two)));
    }
    
    ///-------------- Map.qml -----------------///
    
    Map {
         anchors.fill: parent
         property variant points: ({})
         property int pointCounter: 0
    
         Plugin
         {
            id: osmplugin
            name: "osm"
            PluginParameter { name: "osm.mapping.highdpi_tiles"; value: true }
         }
    
         Component.onCompleted: {
             points = new Array();
         }
        id: map
        plugin: osmplugin
    
        //Javascript functions
        function add_points(array_lat, array_lon) {
            var myArray = new Array()
            var component = Qt.createComponent("mapcircle.qml");
            for (var i=0; i<array_lat.length; i++)
            {
                var object = component.createObject(map, { "center": QtPositioning.coordinate(array_lat[i], array_lon[i]})
                map.addMapItem(object)
                myArray.push(object)
            }
            map.points = myArray
        }
    
        function remove_points() {
            var count = map.points.length
            for (var i = 0; i<count; i++){
                map.removeMapItem(map.points[i])
                map.points[i].destroy()
            }
            map.points = []
        }
    }
    
    ///-------------- mapcircle.qml -----------------///
    import QtQuick 2.0
    import QtLocation 5.6
    
    MapCircle {
          radius: 1
          border.width: 0
          color: 'green'
    }
    


  • Do you need all items at once? If not, you could try to group nearby data points together into one marker point. I did something similar for one of my applications, where there is also the possibility that there will be ten thousand of data points someday.

    What I am doing is, I am offloading the grouping of the data points to a database server. When the user opens the map, I am looking at the current zoom level and the visible rectangle. Based on that information, I am sending a request to my database server, which uses the geohash algorithm (https://en.wikipedia.org/wiki/Geohash) to group nearby data points together.

    e.q: If I am looking at the map with the biggest zoom level it doesn't matter to me, if there are data points that are 100km apart - the data points would be so narrow that I can't click on them anyway. So I can easily group all data points within a certain distance together. If the user zooms in or the current visible rectangle changed, I am again sending a request to the server which again returns the data based on the zoom level and visible rectangle.



  • @Schluchti Hi, thanks for the response :)

    Some kind of clustering would be my plan B, I also already thought about some grid-visualization or something similiar to just reduce the amount of points, so your Geohash-tip goes exactly in that direction. But as OpenGL is the basis of QML Maps (when I understood that correctly), I thought it should be possible to visualize all of the points, because OpenGL is kind of fast. So before I wanted to implement my plan B I wanted to reach out to some more experienced Qml-users to see if there's a native method to visualize that many points while having a good performance.



  • I know this is somewhat old, but I'm facing with exactly the same problem, so I try to warm this up. Is there any other solution to show 4-5000 of items on a QML map with acceptable performance other than grouping them?



  • Similar problem here. Reading https://doc.qt.io/qt-5/qml-qtlocation-mapcircle.html#backend-prop, it looks like certain-- perhaps even all-- QtLocation items were drawn with software, not GPU acceleration.

    Trying out with and without acceleration, I can definitely tell a difference in panning. However, it's still not "good" with ~2.7k points. Even setting the environment variable QTLOCATION_OPENGL_ITEMS to 1, in case there are other elements subtly serving as bottlenecks, I don't see what I would consider to be good, smooth performance.

    It's hard to know if this limitation isn't also possibly due to the fact that calculating a polygon-- in this case a MapCircle-- is intensive no matter what. Also, my GPU is an integrated Intel UHD Graphics 617, so nothing stellar. However, presumably my PC GPU is better than the standard phone GPU, so it's a reasonable performance data point.

    However, since I can pan and zoom on maps with aplomb, it seems like there's still low-hanging fruit available. Here's hoping to see future speed bumps.


Log in to reply