7

I have a performance issue while displaying large amounts MapItems on a Map provided by the QML Location module. I already asked the question here (https://forum.qt.io/topic/79229/large-amount-of-qml-mapitems), but nobody could help me, so I wanted to try it here once. I also found this question (How to use the QML/QtLocation module for displaying a large amount of offline data on a map?), but before adding another dependency, I wanted to see if my code can be improved so that QML can handle this situation without any help.

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'
}
Community
  • 1
  • 1
slisystem
  • 73
  • 5
  • Maybe the ``MapItemView`` with a data model helps? – Hyndrix Aug 07 '17 at 15:03
  • Nah, same problem arises with lots of items in model. Tried this approach to draw a small cross for each entry in a list of coordinates exported from C++ into QML as a model and hooked to a `MapItemView`, with a `MapQuickItem` wrapping a `Canvas` as the view delegate. Worked just fine during development with a few dozen coordinates in the model, but as soon as we hit beta testing with a realistic real-world case of 20,000 odd coordinates in the collection, displaying them chewed 500 MB of RAM and ground the UI to a halt. – Richard Lang Jan 23 '19 at 08:32

1 Answers1

0

Qt says that the performance decreases with the number of elements added to the map. Do you need all the points to be visible on the map in the same time, if not you can play around with visibility.
Can't you use QQuickPaintedItem to paint the points in C++ and wrap it into an MapQuickItem, if you have multiple polygonsfor e.g? But also there are some limitation, you cannot have to big images displayed.
If you need all the points maybe you can have different points based on the map zoom level and reduce the number of points added to the map at small zoom level, as was recommended on the other group ...

smaryus
  • 349
  • 3
  • 12