I am trying the new function for geopshapes to prevent self-intersections. I want to combine this constraint/errormesage with a constraint to use at least 6 points to map an area. When I use this string in the constraint column:
(count-selected(.) -1) div 3 > 6 and not(intersects(.))
I get this error in ODK collect: Xpath evaluation: cannot handle function 'intersects'.
What could be the reason? Do I need to install a newer version of ODK collect? Or is it the string/code that is not correct? Thanks!!
Thanks. I updated ODK Collect. That changed things in a sense that I got a response. However, I am confused now with the new update. I attached an Excel to clarify. It looks like a former condition I had on a minimum of 6 points does not work any more (orange colored row) in the new update. The condition does not prevent users anymore to continue while they have mapped with less than 6 points... It worked fine in the previous ODK version....
Secondly, when I add a condition for intersection (red colored row), the geomapping does not allow me to map more than 3 points.... Even if there is no intersection, it starts to color red when I entered 3 points (and I cannot map any more points....).
Is it me, or is there an error in the new ODK collect version...?
In the end, of course I want to have a condition that forces enumerators to map a polygon with at least 6 points and do not have intersections.... Issues geoshape.xlsx (18.1 KB)
Let me take a look and see what’s going on there, but first, a quick question before I dig in… Why do you use div 3 in count-selected(.) -1) div 3 > 6? It should be div 4, since each point consists of 4 elements (lat, long, alt, and accuracy).
Not sure and I don't recall why. The only thing I know (maybe by try and error) is that is was working fine using this condition on the older ODK version. With the new version, it seems that there is no restriction on the number of points and it accepts polygons with 3-5 points. So it looks like the condition is not becoming active....?
I don't know if you test it if it would work...? As said, my would like to have a condition that only polygons with >= 6 points are accepted (not less) and do not have a self-intersection.
Hmm, I’m not sure exactly when that change was introduced, but there is a difference in how count-selected(.) is used in geoshape between the latest versions. Previously, it returned different numbers, which is probably why div 3 was used here and you needed to add -1. I’ll take a closer look to see what happened, but for now, the logic should be:
count-selected(.) div 4
because count-selected(.) returns the total number of elements, and each point consists of 4 values, as I mentioned above. That’s why we need to divide by 4. In previous versions, it seems it returned 3 for some points and 4 for others (as described here: ODK geofence (v1) ).
Please update the logic and let us know if it solves your problem.
Because of that, count-selected treated it as 3 elements in each point, as explained in:ODK geofence (v1)
Each geopoint actually consists of only three list elements, because the accuracy value of the previous geopoint is prepended to the latitude of the latter, eg "0;-40.550261", except for the last geopoint.
Currently, there is a space and count-selected sees 4 elements in every point which makes more sense.
@Edmonds As I said above, please update your constraint from (count-selected(.) -1) div 3 to count-selected(.) div 4.
We are currently trying to determine what caused this change, as it may not have been expected. If you need to use v2026.1 now, you can update to the logic I mentioned above. However, please keep in mind that this may change, and we might release a new version that restores the previous behavior. If that happens, we will let you know in this thread.
I think this is a regression which should probably be fixed, to restore the previous no-space format. ODK’s geo* formats are already rather non-industry standard, so its quite likely people are consuming them downstream with custom code, to either extract coordinates from the submitted data or convert them to more common GIS formats (eg KML polygons, GeoJSON, etc), code which is going to be very sensitive to the precise format.
Many thanks for clarifying it. I have to see how I am going to deal with this since many of our enumerators partly use the 2026 and partly the 2025 ODK version. Either way it will disturb some of them in their workflow. But happy it is solved. @Xiphware raises a good point below about the importance of maintaining the old standard of saving coordinates. I hope it is going to be solved:-). Thanks both!
Great to hear that the issue is solved. Thanks for pushing this forward that fast. I installed ODK version 2026.1.1. I use the following string in the constraint column for geoshape:
(count-selected(.) -1) div 4 > 6 and not(intersects(.))
However, the constraint (message) is activated already when I have entered 3 points (to create the geoshape) and the polygon turns red (even if I did not intersect). Moreover, it does not let me enter more (than 3) points. So basically, it gets stuck after entering 3 points. The constraint rule seems too early activated (during the creation of the polygon and not by a save).
I assume you’re using the incremental=true parameter in your form. If that’s the case, it won’t work as you expect. With incremental=true, the constraint is evaluated on every change. If the constraint is violated, adding new points is blocked until the issue is resolved. This behavior was specifically added for the intersects function. However, when combined with other conditions, as in your case, it can cause unexpected behavior in the question.
incremental=true can be used with any constraint expression on a geotrace or geoshape but note that it's only appropriate for constraints that can be satisfied by removing or moving existing points. For example, you could use incremental=true if the answer to a geoshape question has to stay below an allowable area (e.g. area(.) < 60000). For constraints that need new points to be added to be satisfied, incremental=true will block the user from making progress (e.g. area(.) > 20000).