Occasional geolocation assignment errors involving polygon-shaped locations
Is there an existing issue for this?
- [x] I checked and did not find my issue in the already reported ones
Describe the bug
In the map view, I rarely observed assignment errors in darktable's locations module if the location's shape is a polygon. On the one hand, images located inside a polygon-shaped geolocation were sometimes not assigned to that location, and on the other hand, images were sometimes assigned to a geolocation they don't belong to.
Steps to reproduce
This issue is hard to reproduce.
Expected behavior
No response
Logfile | Screenshot | Screencast
No response
Commit
No response
Where did you obtain darktable from?
self compiled
darktable version
5.2.0
What OS are you using?
Linux
What is the version of your OS?
Ubuntu 25.10
Describe your system
No response
Are you using OpenCL GPU in darktable?
No
If yes, what is the GPU card and driver?
No response
Please provide additional context if applicable. You can attach files too, but might need to rename to .txt or .zip
I analyzed these errors and could isolate the problem to function _is_point_in_polygon() (src/common/map_locations.c). This function does not handle the following corner case correctly:
AFAIKS function _is_point_in_polygon() implements the ray casting algorithm. The observed assignment errors occurred when the latitude of one of the polygon's corners was identical to the latitude of the image's GPS location, i.e., when the cast ray intersected the polygon exactly through this corner. In this case, the current ray casting algorithm implementation counts this intersection twice for both line segments connected at this corner, instead of only counting it once. This inverts the final result of the ray casting algorithm, i.e., if the point lies inside a polygon, the function _is_point_in_polygon() returns false, and the other way round, as described above.
In detail, if there are two consecutive line segments of the polygon's edge represented by three consecutive corners and the intermediate corner has the same latitude lat as the point pt to be checked, i.e., pt->lat == lat, the condition in lines 266 - 267 is true for both line segments.
In fact, this condition should only be true for one of the two line segments. In other words, it should only be true if the point's latitude pt->lat is equal to either lat1 or lat2, but not both. The condition in lines 266 - 267 could be modified, for instance, to ((lat1 > pt->lat) != (lat2 > pt->lat)). A possible implementation example can be found here.
In addition, I recommend modifying line 269 to avoid division by very small values lat2 - lat1, in case lat1 ≈ lat2. An alternative implementation can also be found in the aforementioned implementation example.