Add centroid function for geoshapes

Is there anyway to calculate the centroid of a geoshape the way we can calculate areas?

You can call area(${geoshape}) and it will return the area in meters. See https://docs.getodk.org/form-operators-functions/#geography for more.

1 Like

Thank you but I was asking if there was anything to calculate the centroid of a geoshape analagous to the way we cancalulate areas: e.g. something like centroid(${geoshape})

So sorry, @MartinFroglife. I misread the question! There's no built-in way to calculate centroid.

It sounds like it'd be helpful for us to add. Can you tell me more about how the centroid is used in your work? Also, any reason that it needs to be calculated on device rather than downstream in the analysis?

No worries. I'll preface my remarks to say that we could do this downstream or we could even get the user to enter this data with sufficient accuracy.

We are collecting data on ponds. The geoshapes are outlines of ponds and it would be nice to use the centroid as a location coordinate. The workflow (this is a new project so I am currently developing things) use the QRealtime QGIS plugin which takes the ODK data and imports it all into QGIS for display and query the data against any of the fields. If I can get all this to work it would be a very simple workflow with no code needing to be written but provide a very powerful tool.

As it happens I am having a bit of trouble with geoshapes and and QRealtime so doing things this way might be infeasable any way, and I will end up having to do more processing downstream and write some code somewhere, which I am not afraid of, but why reinvent stuff if I dont have to?. I just seem to be so close to something that is really simple yet meets our needs.

For what its worth, I would have thought centroid() would have been a pretty useful function in many circumstances, but if there is no demand for it from others I can see there may be many more important develeopments.

M

1 Like

If you can import successfully with qrealtime, or alternatively have an updated CSV of submissions land somewhere with the polygon WKT, you can create a layer from one of these, and then add a virtual field to the qrealtime layer or a separate layer linked to the CSV layer that will calculate the centroid and update with new or changed entries.

I have done similar to take geotrace and geoshape WKT or other shape data and calculate their centroids in ODK geopoint format to use as map select points in other forms.

The QGIS virtual field expression would look something like centroid($geometry). You can also create a new point layer as centroids of a selected layer in one click in QGIS, but this is a one time action and won't update, so only useful after all data are collected.

(Sorry if this is a bit unclear, I'm writing from mobile!)

Yeah the first in particular seems like a good workflow. But it is all so very close, but not quite all the way there, to being a zero work workflow. You can't blame me for checking!

And centroids do seem like a good idea to me, every bit as much as area:-)

This seems like a useful feature, so I've made this topic into a feature request. No idea when we'll be able to squeeze in this feature this in. Pull requests to JavaRosa and Enketo are welcome.

@MartinFroglife and @ahblake, do you think computing the centroid of a shape as though it were on a 2D plane would be sufficient? That would be less and less accurate the bigger the shape (because the Earth is a sphere, etc). I imagine it would be pretty accurate for ponds but very inaccurate for countries, for example. The accuracy will also depend on the distance from the equator. We could quantify that a bit more.

My understanding is that QGIS, GeoPandas and many other Python geo tools use the same common implementation for centroid on a 2D plane: https://gis.stackexchange.com/a/164270

It certainly is possible to get the 3D centroid and project it on a sphere but it's going to be more work to figure out a reasonable algorithm, test it, etc. (This stackoverflow post has some ideas)

I have externally calculated centroids from shapes in order to use the select from map appearance, and I used the QGIS vector tools or virtual field function to do so - the outputs appeared acceptable to me for the desired purpose (show the user where the item was with reasonable accuracy), but my polygons were smaller than most ponds and only 38 degrees south.

Given select from map will support traces and shapes soon, I likely won't need to do this in future.

1 Like

Ok I know that I started this hare running but I am now having second thoughts about whether this is a good idea:-)

For small objects as you suggest a 2D approximation is perfectly fine (certainly it is for my use) though I suspect that different people will have a different idea of what "small" and "fine" mean in this context. On the other hand in the context of ODK I find it hard to imagine when someone would input a "large" polygon into ODK, though that is probably just my limited experience of ODK.

I wonder if doing a 2D approximation and naming the function something like Centroid2D might be a good idea.

The full 3D solution proposed in that StackOverflow post is based on a spherical earth and of course the various lat long systems all use other models for the earth's shape. The same lat long using different lat long systems can be almost 200m apart over the UK. Not sure how much areas and centroids might differ! Presumably the difference between using a proper (WGS84 presumably for us) earth model and the StackOverflow spherical model might be a similar order of magnitude to that between different lat long standards. So its all a real minefield. But I was reminded of Stokes's Theorem, something I haven't used in anger since the eighties!

Could you maybe limit the calculation based on the size (area) of the polygon? So the centroid is only calculated if it is likely to be accurate in 2D? Beyond my pay grade to suggest a threshold for 'fine' and 'small' - but you can maybe provide feedback to the use on the degree of confidence if that exists? E.g. don't try this if you are looking for the centroid within 1m of Loch Ness or Lake Michigan :slight_smile:

I am guessing that in @MartinFroglife situation you might be walking around the perimeter (as opposed to trying to wade to the centre!) and it would be a rare situation that folk would need you to calculate the centroid of a Country or even County / State whilst collecting data in the field? Some folk might use a vehicle I suppose...

I can see that it would be useful to then be able to use / buffer that centroid to compare attributes with other datasets (e.g. in QGIS) - I can see a use for it for auditing restored bare-peat areas, for example...

Also note that there can be algorithmic complications with geoshapes that happen span longitude 0, or circumnavigate the poles