I need a way to compute the distance beetween a point and the bounding edge of a polygon.
This is called SDF for Signed Distance Field/Function
The polygon itself is composed of multiple paths, can be concave, with holes, but not self intersecting, and with a lot of clockwise ordered points (10000+).
I've found some existing solutions, but they require to test the point against each polygon edge, which is not efficient enough.
Here is the visual result produced (green is positive, red is negative):
So I've tried the following:
Put the polygon edges in a quadtree
To compute the distance, find the closest edge to the point and change the sign depending on which side of the edge the point is.
Sadly, it doesn't works when the point is at the same distance of multiple edges, such as corners.
I've tried adding condition so a point is outside the polygon if it's on the exterior side of all the edges, but it doesn't solve the interior problem, and the other way around.
Can't wrap my head around it...
If anyone curious, the idea is to later use some shader to produce images like this :
EDIT
To clarify, here is a close up of the problem arising at corners :
One might think that a point has to be on the interior side of both segments in order to be considered "in". It solves the problem for angles < 180°, but the problem is mirrored for angles > 180°
Worst, two or more corners can share the same position (like the four way corner in the low part of first image)...
Area, like distance, and volume in customary language are quantities that are always positive. However, we will find it useful to give signs to them.
Euclidean Signed Distance Field (ESDF) is useful for online motion planning of aerial robots since it can easily query the distance and gradient information against obstacles. Fast incrementally built ESDF map is the bottleneck for conducting real-time motion planning.
Signed distance fields (SDFs) An SDF is just a function which takes a position as an input, and outputs the distance from that position to the nearest part of a shape. For example, the simplest possible SDF is that of a 2D circle, namely for a circle centred at with radius the function.
I hope this solves your problem.
This is implemented in Python.
First, we use imageio to import the image as an array. We need to use a modified version of your image (I filled the interior region in white).
Then, we transform the RGBA matrix into a binary matrix with a 0 contour defining your interface (phi in the code snippet)
Here's phi from the snippet below (interior region value = +0.5, exterior region value = -0.5):
import imageio
import numpy as np
import matplotlib.pyplot as plt
import skfmm
# Load image
im = imageio.imread("0WmVI_filled.png")
ima = np.array(im)
# Differentiate the inside / outside region
phi = np.int64(np.any(ima[:, :, :3], axis = 2))
# The array will go from - 1 to 0. Add 0.5(arbitrary) so there 's a 0 contour.
phi = np.where(phi, 0, -1) + 0.5
# Show phi
plt.imshow(phi)
plt.xticks([])
plt.yticks([])
plt.colorbar()
plt.show()
# Compute signed distance
# dx = cell(pixel) size
sd = skfmm.distance(phi, dx = 1)
# Plot results
plt.imshow(sd)
plt.colorbar()
plt.show()
Finally, we use the scikit-fmm module to compute the signed distance.
Here's the resulting signed distance field:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With