lib/vector: improve numerical stability for point-in-polygon calculations#7333
lib/vector: improve numerical stability for point-in-polygon calculations#7333metzm wants to merge 4 commits intoOSGeo:mainfrom
Conversation
ee3e17e to
ca061ca
Compare
| /* new version, considers isles | ||
| * the centroid can still be inside an isle or completely outside of the | ||
| * area for very thin polygons, the centroid might be on the boundary */ | ||
| Vect_find_poly_centroid_cog(Points, IPoints, n_isles, ¢_x, ¢_y); |
There was a problem hiding this comment.
Claude's review:
Vect_find_poly_centroid_cog is declared non-static and has no public header entry. It's only used inside poly.c. Either mark it static (and drop the forward declaration at the top of the file) or, if the intent is to
expose it as a peer of Vect_find_poly_centroid, add it to the vector API header. Currently it's a globally visible symbol with no prototype in a header — a namespace-pollution hazard and a linker footgun if another
translation unit ever defines a same-named function.
There was a problem hiding this comment.
Vect_find_poly_centroid_cog is now in the public header alongside Vect_find_poly_centroid.
There are arguments to not use at all Vect_find_poly_centroid in Vect_get_point_in_poly_isl and use only Vect_find_poly_centroid_cog followed by the hard way:
Vect_find_poly_centroiddoes not consider isles inside an areaVect_find_poly_centroidcalculates the center of gravity of the outer polygon line, not the area. For very thin areas, this can cause the centroid to be dangerously close to the polygon line, such that the distance to the polygon line is not safely representable due to floating point precision limits.Vect_find_poly_centroid_cogis in this regard more robust.
|
Could you add a test, e.g. based on the branch name, you have a v.overlay error this is fixing? |
|
Here are test data for nc_spm: Unpack the two vectors in GRASS with v.unpack in=ainput.pack out=ainput
v.unpack in=binput.pack out=binputTest command is v.overlay ainput=ainput binput=binput output=test_topoerror snap=1e-8 operator=or --vWith main, this gives the following topology building output of the intermediate vector: [...]
Number of boundaries: 91768
Number of centroids: 0
Number of areas: 23827
Number of isles: 349
WARNING: Vect_get_point_in_poly_isl(): collapsed area
WARNING: Cannot calculate area centroid
WARNING: Vect_get_point_in_poly_isl(): collapsed area
WARNING: Cannot calculate area centroid
WARNING: Vect_get_point_in_poly_isl(): collapsed area
WARNING: Cannot calculate area centroid
WARNING: Vect_get_point_in_poly_isl(): collapsed area
WARNING: Cannot calculate area centroid
WARNING: Vect_get_point_in_poly_isl(): collapsed area
WARNING: Cannot calculate area centroid
[...]
WARNING: Number of duplicate centroids: 4With this PR, the output is [...]
Number of boundaries: 91768
Number of centroids: 0
Number of areas: 23827
Number of isles: 349
WARNING: Vect_get_point_in_poly_isl(): collapsed area
WARNING: Cannot calculate area centroid
[...]
WARNING: Number of duplicate centroids: 1As I wrote in the description, for very small or very thin areas it is technically not possible to calculate a centroid that is guaranteed to be inside the area. For |
Co-authored-by: Anna Petrasova <kratochanna@gmail.com>
40461f3 to
e8a1e09
Compare
What this PR does:
dig_x_intersect(),Vect__intersect_x_line_with_poly()andVect__intersect_y_line_with_poly()Vect_point_in_poly()whenever possible for consistency and to reduce code maintenance burdenThe motivation for this PR arises from two issues:
Vect_get_point_in_poly_isl()fails for very small or very thin areas. This PR improves this fn by successfully calculating centroid's coordinates for more very small or very thin areas. However, because of fp precision limits, it is technically not possible to calculate centroid's coordinates for too small or too thin areas. In these cases it can not be guaranteed that the centroid is really inside the area.Vect_get_point_in_poly_isl()confirm that the calculated centroid's coordinates are indeed inside the given area,Vect_find_area()might in extreme cases later on assign this centroid to a different area, causing problems with both duplicate centroids and missing centroids.I am not sure if this PR should be regarded as a bug fix or as an enhancement. Suggestions welcome!
Please excuse the many changes in this single PR, but they really belong together.