1

I am working in a discrete 2D grid of points in which there are "shapes" that I would like to create points outside of. I have been able to identify the vertices of these points and take convex hulls. So far, this leads to this and all is good and well. The purple here is the shape in question and the red line is the convex contour I have computed.

What I would like to do now is create two neighborhoods of points outside this shape. The first one is a set of points directly outside (as close as the grid size will allow), the second is another set of points but offset some distance away (the distance is not fixed, but rather an input).

I have attempted to write this in Python and get okay results. Here is an example of my current output. The problem is I notice the offsets are not perfect, for example look at the bottom most point in the image I attached. It kinks downwards whereas the original shape does not. It's not too bad in this example, but in other cases where the shape is smaller or if I take a smaller offset it gets worse. I also have an issue where the offsets sometimes overlap, even if they are supposed to be some distance away. I would also like there to be one line in each section of the contour, not two lines (for example in the top left).

My current attempt uses the Shapely package to handle most of the computational geometry. An outline of what I do once I have found the vertices of the convex contour is to offset these vertices by some amount, and interpolate along each pair of vertices to obtain many points alone these lines. Afterwards I use a coordinate transform to identify all points to the nearest grid point. This is how I obtain my final set of points. Below is the actual code I have written.

How can I improve this so I don't run into the issues I described?

Function #1 - Computes the offset points

def OutsidePoints(vertices, dist):
    poly_line = LinearRing(vertices)
    poly_line_offset = poly_line.buffer(dist, resolution=1, join_style=2, mitre_limit=1).exterior

    new_vertices = list(poly_line_offset.coords)
    new_vertices = np.asarray(new_vertices)


    shape = sg.Polygon(new_vertices)
    points = []
    for t in np.arange(0, shape.length, step_size):
        temp_points = np.transpose(shape.exterior.interpolate(t).xy)
        points.append(temp_points[0])
    points = np.array(points)
    points = np.unique(points, axis=0)
    return points

Function #2 - Transforming these points into points that are on my grid

def IndexFinder(points):
    index_points = invCoordinateTransform(points)
    for i in range(len(index_points)):
        for j in range(2):
            index_points[i][j] = math.floor(index_points[i][j])
    index_points = np.unique(index_points, axis=0)
    return index_points

Many thanks!

APM500
  • 85
  • 1
  • 7
  • I would recommend calculating the center of mass (CM) for the area inside the convex hull, then compute the line between the CM and each vertex. From there you can scale the entire convex hull and run the first algorithm to find the points closest to the expanded hull. – James Aug 29 '21 at 20:41
  • @James I am unfamiliar with the center of mass. I assume it is used to calculate the center of an irregular polygon? – APM500 Aug 29 '21 at 22:35
  • @James I tried implementing your idea (if I understood correctly and used the centroid), but I realized this will not work near corners. – APM500 Aug 30 '21 at 05:33
  • What you are trying to achieve is not completely clear to me. In particular I don't know if you want to offset from the shape or from that hull. This seems to be a job for a distance map, using Euclidean or perhaps taxicab distance. Then you can flag the pixels with distance below a threshold. (To illustrate: https://www.supergeotek.com/SpatialAnalyst_ENG_HTML/straight_line_distance.htm) –  Aug 30 '21 at 09:06
  • @YvesDaoust Sorry I will try to clarify a little more. I have the convex contour of some shape. I would like to do two things, first offset this shape by a fixed distance, and second along this new polygon create a set of equidistant points. I am able to get a rough code running, but run into some issues. – APM500 Aug 30 '21 at 20:39
  • Things are even more obscure now. –  Aug 30 '21 at 20:52
  • @YvesDaoust Sorry about that. So I have a convex polygon's contour. I wish to first offset this polygon by a fixed distance ("expand" it, so to speak). I'll focus on this part first. – APM500 Aug 31 '21 at 01:53
  • The true offset curve to a convex polygon is a convex shape made of straight lines and circular arcs. Is that what you want ? –  Aug 31 '21 at 07:08
  • @YvesDaoust Yes that is correct, my shapes are all straight lines and I would like the offset to consist of straight lines as well. – APM500 Sep 03 '21 at 20:30
  • So what you want is not a true offset. You need to be more epxlicit. –  Sep 04 '21 at 09:48
  • @YvesDaoust I see, given that this post has gotten drawn out I will make another post that is more descriptive. Thank you for your help. – APM500 Sep 04 '21 at 18:31
  • Does this answer your question? [Finding points outside a convex polygon which are normal to its edges](https://stackoverflow.com/questions/69058182/finding-points-outside-a-convex-polygon-which-are-normal-to-its-edges) –  Sep 07 '21 at 16:23
  • @YvesDaoust Not quite, that question has not been answered. – APM500 Sep 07 '21 at 16:28

0 Answers0