Tag: foss4g

FOSS4G SotM Oceania 2023 Auckland round up

Recently, we had the pleasure of helping organise the FOSS4G SotM Oceania 2023 conference in Auckland. It was a fantastic week and felt like a worthy return to pre-covid events full of great presentations, catching up with old friends, making new ones, and of course – delicious food! The venue, Auckland University of Technology, put on a really professional event with catering, venue spaces and their Audio Visual operations. Auckland gave us great weather, and great venues to enjoy each others company in.

We were blown away with the variety of presentations and the talent our Oceania region holds. We got to meet some of our clients in person including Koordinates, A.B. Heritage and Soar, which we loved, plus we spent valuable time connecting with our community.

At North Road we are passionate about supporting open-source and our local Oceania region, so we took an active part in making this year’s conference happen. Aside from being a conference sponsor, our very own powerhouse Emma Hain worked tirelessly as Program Chair to organise the conference program and ensure that the talks ran smoothly and were of very high value.  Nyall ran a workshop for Advanced Cartography, presented on his journey in the FOSS4G workspace and contributed as panel member on making  a living in FOSS4G. Emma also presented a lightning talk on GitHub QGIS Issues and was a community day facilitator on an exciting project to develop digital stories with a map component. We really love community and being involved in “building it” is integral. But it is also super fun as well!

One of the great things about this conference is the legacy it leaves, not only in the relationships formed, but in the recordings of all the presentations that end up on the FOSS4G Oceania YouTube channel. This is not only knowledge captured for the community, but also a showcase for the talent that exists in FOSS4G. Not every  presentations was technical or about case studies, they also covered personal observations, hobbies and general mapping topics.

You can view the presentations from our staff below:

Also, check out the presentations from some of the great companies we have worked with:

Soar: Soar: lessons from our start-up experience, From Satellites to Slobs,   Maps, Media and Manipulation

Koordinates: Kart – the geospatial version control system – now with Rasters!Making it up: map making bots, generative mapping and TTRPG tools

Community Day

On the last day of the conference we attended the Community Day. This involves a Mapathon run by HOTOSM, and rooms for brainstorming and workshopping of ideas. These were really valuable! First we attended the FOSS4G Hui run by Byron Cochrane from OpenWork (one of the conference sponsors). It was a great discussion on how to make FOSS4G more relevant in Oceania. If you are keen to help out with this, contact the OSGeo Oceania Board – as they need helpers with Communications and members to espouse FOSS4G at outside conferences.

Emma also ran the session on developing digital stories with a map component in a FOSS4G environment. This was well attended with a lot of ideas. We developed our MVP and we are now looking at our next steps. The question here is do we develop a new tool within existing software, find a standalone software where we could add in a map component, or approach a current OS Story Map software and provide our MVP and find funding. If you’re keen to take part in these discussions, you can join in on the Maptime Oceania slack channel under #foss4g-productdev.

A Big Thank-you!

The Organisation committee worked so hard on putting this conference on, and we would like to express our heartfelt thanks for this. This is the keystone event for our community and so much grows from this. Without the Organisation Committee’s sweat, tears, frustration and joy this would not have happened. We thank their families who supported them whilst they gave up their valuable time and their employers who supported them to give their time and effort to making this special event happen.

Bring on FOSS4G/SOTM Oceania 2024!

Learn More

Thoughts on “FOSS4G/SOTM Oceania 2018”, and the PyQGIS API improvements which it caused

Last week the first official “FOSS4G/SOTM Oceania” conference was held at Melbourne University. This was a fantastic event, and there’s simply no way I can extend sufficient thanks to all the organisers and volunteers who put this event together. They did a brilliant job, and their efforts are even more impressive considering it was the inaugural event!

Upfront — this is not a recap of the conference (I’m sure someone else is working on a much more detailed write up of the event!), just some musings I’ve had following my experiences assisting Nathan Woodrow deliver an introductory Python for QGIS workshop he put together for the conference. In short, we both found that delivering this workshop to a group of PyQGIS newcomers was a great way for us to identify “pain points” in the PyQGIS API and areas where we need to improve. The good news is that as a direct result of the experiences during this workshop the API has been improved and streamlined! Let’s explore how:

Part of Nathan’s workshop (notes are available here) focused on a hands-on example of creating a custom QGIS “Processing” script. I’ve found that preparing workshops is guaranteed to expose a bunch of rare and tricky software bugs, and this was no exception! Unfortunately the workshop was scheduled just before the QGIS 3.4.2 patch release which fixed these bugs, but at least they’re fixed now and we can move on…

The bulk of Nathan’s example algorithm is contained within the following block (where “distance” is the length of line segments we want to chop our features up into):

for input_feature in enumerate(features):
    geom = feature.geometry().constGet()
    if isinstance(geom, QgsLineString):
        continue
    first_part = geom.geometryN(0)
    start = 0
    end = distance
    length = first_part.length()

    while start < length:
        new_geom = first_part.curveSubstring(start,end)

        output_feature = input_feature
        output_feature.setGeometry(QgsGeometry(new_geom))
        sink.addFeature(output_feature)

        start += distance
        end += distance

There’s a lot here, but really the guts of this algorithm breaks down to one line:

new_geom = first_part.curveSubstring(start,end)

Basically, a new geometry is created for each trimmed section in the output layer by calling the “curveSubstring” method on the input geometry and passing it a start and end distance along the input line. This returns the portion of that input LineString (or CircularString, or CompoundCurve) between those distances. The PyQGIS API nicely hides the details here – you can safely call this one method and be confident that regardless of the input geometry type the result will be correct.

Unfortunately, while calling the “curveSubstring” method is elegant, all the code surrounding this call is not so elegant. As a (mostly) full-time QGIS developer myself, I tend to look over oddities in the API. It’s easy to justify ugly API as just “how it’s always been”, and over time it’s natural to develop a type of blind spot to these issues.

Let’s start with the first ugly part of this code:

geom = input_feature.geometry().constGet()
if isinstance(geom, QgsLineString):
    continue
first_part = geom.geometryN(0)
# chop first_part into sections of desired length
...

This is rather… confusing… logic to follow. Here the script is fetching the geometry of the input feature, checking if it’s a LineString, and if it IS, then it skips that feature and continues to the next. Wait… what? It’s skipping features with LineString geometries?

Well, yes. The algorithm was written specifically for one workshop, which was using a MultiLineString layer as the demo layer. The script takes a huge shortcut here and says “if the input feature isn’t a MultiLineString, ignore it — we only know how to deal with multi-part geometries”. Immediately following this logic there’s a call to geometryN( 0 ), which returns just the first part of the MultiLineString geometry.

There’s two issues here — one is that the script just plain won’t work for LineString inputs, and the second is that it ignores everything BUT the first part in the geometry. While it would be possible to fix the script and add a check for the input geometry type, put in logic to loop over all the parts of a multi-part input, etc, that’s instantly going to add a LOT of complexity or duplicate code here.

Fortunately, this was the perfect excuse to improve the PyQGIS API itself so that this kind of operation is simpler in future! Nathan and I had a debrief/brainstorm after the workshop, and as a result a new “parts iterator” has been implemented and merged to QGIS master. It’ll be available from version 3.6 on. Using the new iterator, we can simplify the script:

geom = input_feature.geometry()
for part in geom.parts():
    # chop part into sections of desired length
    ...

Win! This is simultaneously more readable, more Pythonic, and automatically works for both LineString and MultiLineString inputs (and in the case of MultiLineStrings, we now correctly handle all parts).

Here’s another pain-point. Looking at the block:

new_geom = part.curveSubstring(start,end)
output_feature = input_feature
output_feature.setGeometry(QgsGeometry(new_geom))

At first glance this looks reasonable – we use curveSubstring to get the portion of the curve, then make a copy of the input_feature as output_feature (this ensures that the features output by the algorithm maintain all the attributes from the input features), and finally set the geometry of the output_feature to be the newly calculated curve portion. The ugliness here comes in this line:

output_feature.setGeometry(QgsGeometry(new_geom))

What’s that extra QgsGeometry(…) call doing here? Without getting too sidetracked into the QGIS geometry API internals, QgsFeature.setGeometry requires a QgsGeometry argument, not the QgsAbstractGeometry subclass which is returned by curveSubstring.

This is a prime example of a “paper-cut” style issue in the PyQGIS API. Experienced developers know and understand the reasons behind this, but for newcomers to PyQGIS, it’s an obscure complexity. Fortunately the solution here was simple — and after the workshop Nathan and I added a new overload to QgsFeature.setGeometry which accepts a QgsAbstractGeometry argument. So in QGIS 3.6 this line can be simplified to:

output_feature.setGeometry(new_geom)

Or, if you wanted to make things more concise, you could put the curveSubstring call directly in here:

output_feature = input_feature
output_feature.setGeometry(part.curveSubstring(start,end))

Let’s have a look at the simplified script for QGIS 3.6:

for input_feature in enumerate(features):
    geom = feature.geometry()
    for part in geom.parts():
        start = 0
        end = distance
        length = part.length()

        while start < length:
            output_feature = input_feature
            output_feature.setGeometry(part.curveSubstring(start,end))
            sink.addFeature(output_feature)

            start += distance
            end += distance

This is MUCH nicer, and will be much easier to explain in the next workshop! The good news is that Nathan has more niceness on the way which will further improve the process of writing QGIS Processing script algorithms. You can see some early prototypes of this work here:

So there we go. The process of writing and delivering a workshop helps to look past “API blind spots” and identify the ugly points and traps for those new to the API. As a direct result of this FOSS4G/SOTM Oceania 2018 Workshop, the QGIS 3.6 PyQGIS API will be easier to use, more readable, and less buggy! That’s a win all round!

Learn More