Concave Hull (Alpha Shape) from list of points with Python?

I cleaned up the code a bit:

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import Line

from math import sqrt, hypot

points, alpha = IN
OUT = []

pLen = len(points)
alpha2 = alpha * alpha
if pLen < 2:
    raise Exception('AlphaShape needs at least 2 points')
    
for i, p in enumerate(points):
    for j in xrange(i+1, pLen):
        if p.IsAlmostEqualTo(points[j]):
           raise Exception('AlphaShape needs pairwise distinct points')
        dist = hypot(p.X - points[j].X, p.Y - points[j].Y)                    
        if (dist > 2 * alpha) : continue #circle fits between points ==> p_i, p_j can't be alpha-exposed                    

        x1, y1, x2, y2 = p.X, p.Y, points[j].X, points[j].Y
        midX, midY = (x1 + x2) / 2, (y1 + y2) / 2

        #find two circles that contain p_i and p_j; note that center1 == center2 if dist == 2*alpha
        alphaDist = sqrt(alpha2 - (dist / 2) ** 2)
        deltaX, deltaY = (x2 - x1) / dist, (y1 - y2) / dist
        c1x, c1y = midX + alphaDist * deltaY, midY + alphaDist * deltaX
        c2x, c2y = midX - alphaDist * deltaY, midY - alphaDist * deltaX
        
        #check if one of the circles is alpha-exposed, i.e. no other point lies in it
        c1_empty = True 
        c2_empty = True
        for k in xrange(pLen):                
            if i == k or j == k: 
                continue
            if ((c1x - points[k].X) * (c1x - points[k].X) + (c1y - points[k].Y) * (c1y - points[k].Y) < alpha2):
                c1_empty = False
            if ((c2x - points[k].X) * (c2x - points[k].X) + (c2y - points[k].Y) * (c2y - points[k].Y) < alpha2):
                c2_empty = False
            if not c1_empty and not c2_empty:
            	break
        if c1_empty or c2_empty:
             OUT.append(Line.ByStartPointEndPoint(p, points[j]))

Another interesting question is, how do you determine the alpha (scoop) size? It’s correlated to the distance to the nearest neighbors but can’t be deducted exactly from it:

26 Likes