Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Feature: Weighted Centroid for Polygons #2021

Open
carlosg-m opened this issue Mar 12, 2024 · 0 comments
Open

New Feature: Weighted Centroid for Polygons #2021

carlosg-m opened this issue Mar 12, 2024 · 0 comments

Comments

@carlosg-m
Copy link

carlosg-m commented Mar 12, 2024

Consider:

  • An input set of points
  • An input list of weights (1-1 with set of geometries)
  • A polygon outline to clip the surface (achieved in this example with Convex Hull)

The centroid of the multipoint geometry or point cloud is different from the centroid of a polygon that considers the entire surface.

The objective is to allocate weights to the entire surface of the polygon, this is achieved through Voronoy used to extend each weight to the corresponding polygon surface (similar to KNN interpolation in raster format), calculating the centroid for each voronoy polygon, and averaging all centroids weighted by area and weight.

In theory this method should yield an exact solution for the weighted polygon centroid.

# input point array
p = np.array([[1,1],[2,4],[2,4],[0,3],[0,3],[0,3],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[3,3],[2.5,2.5],[2.5,2.5],[-2,2],[-1.5,-0.5],[2,-1]])

# p points
p, p_count = np.unique(p, return_counts=True, axis=0)
p_point = shapely.points(p)

# p geometries
p_geo = shapely.MultiPoint(p)
p_convex_hull = p_geo.convex_hull

# voronoy
v = shapely.ops.voronoi_diagram(p_geo)
v = np.array(v.geoms)

# sjoin
p_order, v_order = shapely.STRtree(v).query(p_point, predicate='intersects')
assert np.all(p_order == np.arange(len(p_count)))

# ordered voronoy and ordered weights
v_intersection = shapely.intersection(v[v_order], p_convex_hull)
p_weights = p_count[p_order]
p_order, v_order = shapely.STRtree(v_intersection).query(p_point, predicate='intersects')

# properties
v_area = shapely.area(v_intersection)
v_centroid = shapely.centroid(v_intersection)
v_centroid_coos = shapely.get_coordinates(v_centroid)

# centroids
polygon_uniform_centroid = shapely.points(np.average(v_centroid_coos, weights=v_area, axis=0))
polygon_weighted_centroid = shapely.points(np.average(v_centroid_coos, weights=v_area*p_weights, axis=0))
multipoint_uniform_centroid = shapely.points(np.average(p, axis=0))
multipoint_weighted_centroid = shapely.points(np.average(p, weights=p_count, axis=0))

Yellow Starts: original points with weights
Light Green Centroid: uniform multipoint centroid
Dark Green Centroid: uniform polygon centroid
Light Blue Centroid: weighted multipoint centroid
Dark Blue Centroid: weighted polygon centroid
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant