0

Question

Here's a function to calculate alphashape of a set of points. It's from the documentation of the library 'alphashape'.

points_2d = [(0., 0.), (0., 1.), (1., 1.), (1., 0.),(0.5, 0.25), (0.5, 0.75), (0.25, 0.5), (0.75, 0.5)]

alpha_shape = alphashape(
    points_2d,
    lambda ind, r: 1.0 + any(np.array(points_2d)[ind][:,0] == 0.0))

I don't understand how the lambda function above works in the following context (an excerpt from library's source code).

Specifically, my questions are:

  • where does variable r come from?
  • what does [:,0] mean?

Context

def alphashape(points: Union[List[Tuple[float]], np.ndarray],
               alpha: Union[None, float] = None):
    coords = np.array(points)
    for point_indices, circumradius in alphasimplices(coords):
        if callable(alpha):
            resolved_alpha = alpha(point_indices, circumradius)
from scipy.spatial import Delaunay

def alphasimplices(points: Union[List[Tuple[float]], np.ndarray]) -> \
        Union[List[Tuple[float]], np.ndarray]:
    coords = np.asarray(points)
    tri = Delaunay(coords)

    for simplex in tri.simplices:
        simplex_points = coords[simplex]
        try:
            yield simplex, circumradius(simplex_points)    
def circumradius(points: Union[List[Tuple[float]], np.ndarray]) -> float:
    points = np.asarray(points)
    return np.linalg.norm(points[0, :] - np.dot(circumcenter(points), points))
def circumcenter(points: Union[List[Tuple[float]], np.ndarray]) -> np.ndarray:
    points = np.asarray(points)
    num_rows, num_columns = points.shape
    A = np.bmat([[2 * np.dot(points, points.T),
                  np.ones((num_rows, 1))],
                 [np.ones((1, num_rows)), np.zeros((1, 1))]])
    b = np.hstack((np.sum(points * points, axis=1),
                   np.ones((1))))
    return np.linalg.solve(A, b)[:-1]
David H. J.
  • 340
  • 2
  • 12
  • 2
    The function is being passed as a parameter. Within `alphashape`, the function is called `alpha`. When you see `alpha(point_indicies, circumradius)`, it's calling that lambda just as if it had been defined with `def alpha(ind, r):`. – Tim Roberts Jul 18 '22 at 18:55
  • The type annotation for `alphashape` is completely wrong -- it looks like it's taking a `Callable`, not an `Optional[float]`. A `lambda` is just a quick way to construct a callable. – Samwise Jul 18 '22 at 18:56
  • @Samwise I omit a line of code from the source. It check if the variable `alpha` is callable first. I revised the question. – David H. J. Jul 18 '22 at 19:01
  • 1
    "where does variable r come from?" it's a *parameter to the function*. It is important to understand, `lambda` expressions just create regular functions. They are never *required*, they are syntactic sugar. You could use a function definition statement to create the same thing. – juanpa.arrivillaga Jul 18 '22 at 19:04
  • @TimRoberts Thanks. I added 2 more specific questions. Could you please have another look. – David H. J. Jul 18 '22 at 19:07
  • @juanpa.arrivillaga answered the first question. `x[:,0]` is a `numpy` thing that extracts the first "plane" of the array. That is, it creates a new one-dimensional array containing all of the elements where the second coordinate is 0. – Tim Roberts Jul 18 '22 at 19:11
  • @TimRoberts I understand `x[:,0]`, but `np.array(points_2d)[ind][:,0]` seems a bit different. When I executed this line of code, I got an error message: `IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed`. – David H. J. Jul 19 '22 at 02:45
  • 1
    Yep, that must be a mistake in their tutorial. You'd need `[0]`. – Tim Roberts Jul 19 '22 at 03:17
  • @TimRoberts Curiously, the [tutorial](https://alphashape.readthedocs.io/en/latest/readme.html#using-a-varying-alpha-parameter) works. Any idea why it could work? – David H. J. Jul 19 '22 at 03:29
  • You tried it and it didn't work, right? Isn't that what the whole question is about? – Tim Roberts Jul 19 '22 at 06:29
  • @TimRoberts The tutorial itself works. But when I extracted that code line and executed it, the error came in. It seems that that line code needs some context burying in the library, which I don't quite understand. – David H. J. Jul 19 '22 at 16:44

0 Answers0