How to create a default geotrace/geoshape value from WKT or other formats?

1. What is the issue? Please be detailed.
I would like to use pre-existing shape data (from another source) as a default entry to a geotrace/geoshape. I would have a series of lines/shapes, these have a centroid to be used as the point for the select from map appearance, then when the geotrace/geoshape widget is opened the line/polygon is displayed to be either left as is or updated.

Firstly - what is the best way to populate a default/starting trace/shape? I tried a few methods, and they either don't work at all or work differently in Collect/Enketo. I did land on one that does work.

  • In the calculation field, refer to a variable eg ${default_shape_string}: works in Enketo, not in Collect :x:
  • In the calculation field, use a concat('lat0 long0 alt0 acc0; lat1 long1 alt1 acc1; lat2 long2 alt2 acc2; ...; lat0 long0 alt0 acc0') works in both, but is not usable as it's a fixed string. :x:
  • In the calculation field, use a concat('',${default_shape_string},'') or concat(${default_shape_string}) works in Enketo but not Collect :x:
  • In the default field, refer to a variable eg ${default_shape_string}, breaks the Enketo widget completely, doesn't work in Collect but doesn't break it. :x:
  • In the default field, use an instance lookup eg instance('ref_priorfindings')/root/item[name=${oldfinding}]/shapestring breaks Enketo entirely again, doesn't work in Collect but doesn't break it. :x:
  • In the calculation field, use an instance lookup eg instance('ref_priorfindings')/root/item[name=${oldfinding}]/shapestring works in Enketo & Collect :white_check_mark:
    • For now I'm doing this, with a trigger to only update the calculation if the 'oldfinding' is changed and prevent it being overwritten at form submit.

Secondly - The raw value of the shape in Collect is of the form lat0 long0 alt0 acc0; lat1 long1 alt1 acc1; lat2 long2 alt2 acc2; ...; lat0 long0 alt0 acc0, but output from package like QGIS are of the form POLYGON ((long0 lat0 alt0, long1 lat 1 alt1, long2 lat2 alt2, ..., long0 lat0 alt0)). (Trace is similar, but doesn't repeat the first point to close the polygon). So each long-lat pair needs to swap, then append 0 0 for altitude and accuracy and replace the comma with a semicolon, as well as stripping the start and end of the string of POLYGON(( & ))

There are numerous ways to consume ODK raw values into other packages (and the queried value is already WKT), but going the other way seems less common. Getting a default POINT value is much easier as you only need extract the lat/long pair and can construct the string, but a shape has 3-to-many points to iterate over and also needs repeat the first value at the end for a shape

Getting the centroid for the map select part select is easy in QGIS with a virtual field to return something like y(centroid($geometry)) || ' ' || x(centroid($geometry)) || ' 0 0'. Extracting the polygons' vertices and converting to y, x then recombining seems overly convoluted however.

3. What have you tried to fix the issue?
Exporting geometry from QGIS in CSV/WKT/GeoJSON to see what the format looks like vs Collect

I have considered but not tried the following as I feel there must be a far simpler method I've missed

  • x-y coordinate swaps to simplify the string reconstruction.
  • Running powerquery over a shape with a known number of vertices to split to columns, then reassemble in the correct format with the right delimiters.
  • Reversing @mathieubossaert's ODK2WKT form calculations to convert the WKT to Collect format within the form

This looks like an ideal way to me. The ideas with calculate won't work as you allude to here and is described in the docs. As I understand it the ideas with default won't work because defaults are evaluated once at form load and it looks like some other form fields have to be set to pick the default (more in docs). Is there a reason you'd prefer to use values directly from the form? What would that look like?

I tried to verify the cases you described and came up with this XLSForm with traces.csv (151 Bytes) attached. I do see that Enketo geotraces don't work with defaults (issue filed) but I can't reproduce the other issues you've described.

The only reasonable way I can think of to do it is to write a script for this. If it would be helpful to you to see a Python example, please share an example of an input file you'd like to use (e.g. docs for the exact export format) and I could share a script for it.

I would recommend preprocessing this for performance reasons unless you really don't have very many.

Thanks @LN , glad to know that my approach to setting a default is ok and I haven't set myself up for a pitfall.

If you need to reproduce any of them I can try to modify your form to show the issues I ran into.

Sorry, I'm not sure what you mean here? I have an initial use case and a follow on;

initial: someone creates a series of traces or polygons in desktop GIS and pairs these with other fields, this then becomes a reference CSV of 'preexisting findings' that has a centroid to select from a map, some text/dates/etc as information and the line or shape string. After selecting the point off the map, old details are shown, updated status information can be collected and the geotrace/geoshape viewed and adjusted if not correct. This is why I want to take a polygon and use it as a default in the widget for the selected item.

follow-on: someone has gathered data using Collect, including a trace/shape, and this becomes the reference information for a follow up. The main difference is the trace/shape is created in the geowidget and not outside Collect. I think the raw ODK Collect string of coordinates for lines/shapes is only available if you include a text widget that has a calculate to populate it (?), as otherwise the Central view / CSV download / OData queried value is delivered as WKT. Unless there's a way to extract the raw ODK format the same translation in the initial workflow is needed for the ability to select/view/update.

I agree. I have started down this path but appreciate the offer of a script. I'll either look at a standalone python script or potentially a processing plugin for QGIS if the effort is warranted. I did setup a powerquery (that works with a set number of vertices or returns an error if there are too many) just to quickly convert a series of rectangles exported to a CSV of WKTs

It would be for a single line/shape per form, so the performance wouldn't be awful, but I agree it's better to preprocess. And with the upcoming select a line/shape from map development, all these issues might disappear soon anyway.

I'm happy to let them be mysteries until they get in someone's way!

Great, thanks for the additional details. As far as I know addressing both of those needs requires the form structure you've come up with so other possible bugs around calculates and defaults don't seem so important.

Yes, that would be the simplest way to get the raw values currently.

Don't hesitate to ask for an example here if it would be helpful.

Yes, I think with a combination of Central-managed entities and additions to select from map we're going to be getting closer to supporting your workflow more directly.

1 Like