1

I'm working through an XY problem, with the end goal of effectively visualising data representing different journeys.

Given I have ordered data of the various positions (each with a time stamp) along the journey, I am considering using a MultiPoint layer, with each feature representing a journey, and each point a position along that journey.

I have written minimal (but verbose to convey intent) code below to generate a MultiPoint layer and visualise some dummy journeys as points.

My question: Is it possible to visually connect each pair of adjoining points with a line (or better still an arrow)? If so, how would I extend the following code to do this using PyQGIS?

I need to automate this, at the time the layer is created, and I don't want to rely on external plugins.

    from collections import namedtuple

    from qgis.core import QgsFeature, QgsField, QgsGeometry, QgsPointXY, QgsProject, QgsVectorLayer
    from qgis.PyQt.QtCore import QVariant

    # Create a new multipoint layer
    layer = QgsVectorLayer('MultiPoint?crs=EPSG:4326', "Journeys", 'memory')
    layer.startEditing()

    # Define attribute table headers
    field_headers = [
        QgsField('journey_id', QVariant.String),
        QgsField('positions [(lat, long, time_step), ...]', QVariant.String),
    ]
    layer_provider = layer.dataProvider()
    layer_provider.addAttributes(field_headers)

    # Define sample data for 2 journeys
    Position = namedtuple('Position', 'lat long time_step')
    journeys = [
        ('journey_1', [Position(10, 0, 1), Position(1, 1, 2), Position(3, 0, 3)]),
        ('journey_2', [Position(-5, -5, 1), Position(2, 2, 2), Position(-4.5, 9, 3)]),
    ]

    # Create feature for each journey
    features = []
    for journey in journeys:
        journey_id, positions = journey

        # Create points list from positions
        points = [QgsPointXY(p.lat, p.long) for p in positions]

        # Create feature from points list
        feature = QgsFeature()
        feature.setGeometry(QgsGeometry.fromMultiPointXY(points))

        # Add entry to attributes table
        feature.setAttributes([
            journey_id,
            ", ".join(f"({p.lat}, {p.long}, {p.time_step})" for p in positions),
        ])

        features.append(feature)

    # Add features to layer, update, and commit
    layer_provider.addFeatures(features)
    layer.updateExtents()
    layer.commitChanges()

    # Add layer to legend
    QgsProject.instance().addMapLayer(layer)
  • If you know this is an XY problem, then what is the X? – Vince Feb 1 at 20:20
  • I've played around with your data. IMO it would be easier to put the points from one journey not as an multipoint. Use instead point with to columns journey_id and time_stamp (or order), which you now put together in one field. Then it's easy to connect the points with arrrows, e.g. we can use the geometry generator to do it – eurojam Feb 2 at 6:27
  • @Vince The X is "effectively visualising data representing different journeys" – Jonny Feb 4 at 11:08
2

How married are you to the idea that MultiPoints are the best data type for your problem? I've created Trajectools a plugin that deals specifically with movement data: https://github.com/anitagraser/qgis-processing-trajectory and it creates LineStringM features. The advantage is that we can retain all timestamp information by storing each location's timestamp in the line node's m value.

Here's a screenshot from a recent post which shows movement speed encoded using color along the trajectory:

enter image description here

You can look at the code an borrow whatever you need.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.