-2

open image to see result of below code

import numpy as np
from scipy.spatial import ConvexHull
import matplotlib.pyplot as plt

points = np.array([[1,1],[1,2],[1,3],[1,4],[2,1],[2,2],[2,3],[2,4],[3,1],[3,2],[3,3],[3,4],[4,1],[4,2],[4,3],[4,4]])  
hull = ConvexHull(points)
plt.plot(points[:,0], points[:,1], 'o')
for simplex in hull.simplices:
    plt.plot(points[simplex, 0], points[simplex, 1], 'k-')
    plt.plot(points[simplex,0], points[simplex,1], 'ro', alpha=.25, markersize=20)

I want to get index of coordinate of point that are on convex hull(the points that are black + on line).I choose rectangle just to get an extreme case.

hull.points can only give points that are marked red(only corner point of rectangle).

result of code

  • You could join consecutive "red" marked points to create convex polygon. Then for each point, you could check if it lies on any of the sides. – Rishit Sanmukhani Jun 16 '18 at 14:05
  • @RoryDaulton yes I want to return all the points on boundary of my convex hull. there was a typo, it should be hull.points .My convex hull is not a rectangle ,but has few points that lies on straight line,which get excluded when I used hull.points .I made a small program just to exemplify the situation there. – Sanket Chafle Jun 17 '18 at 11:48
  • @RishitSanmukhani I have a convex hull, I used red points just for representation of points that I get when I call hull.points . But I want all points on boundary. – Sanket Chafle Jun 17 '18 at 12:07
  • @SanketChafle That is what I wrote. "Red" marked points == hull.points. Use hull.points to create convex polygon. – Rishit Sanmukhani Jun 17 '18 at 14:13

1 Answers1

0

If you are sure that the convex hull is a perfect rectangle whose sides are aligned with the x- and y-axes, finding the indices of all boundary points is simple. The convex hull does not need to be calculated at all to do this. That description fits your example. Here is some code that does what you want in this case. The time complexity of this code is O(n) where n is the number of points overall.

# Find the indices of all boundary points, in increasing index order,
#   assuming the hull is a rectangle aligned with the axes.
x_limits = (min(pt[0] for pt in points), max(pt[0] for pt in points))
y_limits = (min(pt[1] for pt in points), max(pt[1] for pt in points))
boundary_indices = [idx for idx, (x, y) in enumerate(points) 
                    if x in x_limits or y in y_limits]

However, that case seems very simple. Here is more general code that works for all two-dimensional cases, but especially when the points have integral coordinates. This is because finding if a point is exactly on a line segment is tricky if the precision is not exact. This code runs in time complexity O(n*m), where n is the number of points and m is the number of vertices in the convex hull.

# Find the indices of all boundary points, in increasing index order,
#   making no assumptions on the hull.
def are_collinear2d(pt1, pt2, pt3):
    """Return if three 2-dimensional points are collinear, assuming 
    perfect precision"""
    return ((pt2[0] - pt1[0]) * (pt3[1] - pt1[1]) 
          - (pt2[1] - pt1[1]) * (pt3[0] - pt1[0])) == 0

vertex_pairs = list(zip(vertices, vertices[1:] + vertices[0:1]))
boundary_indices = []
for idx, pt in enumerate(points):
    for v1, v2 in vertex_pairs:
        if are_collinear2d(pt, v1, v2):
            boundary_indices.append(idx)
            break
Rory Daulton
  • 21,934
  • 6
  • 42
  • 50