2

I have a cloud of vertices. I'd like to tessellate a "shell" around the vertex cloud using only vertices in the cloud, such that the shell conforms roughly to the shape of the vertex cloud.

Is there an easy way to do this? I figured I could spherically parameterize the point cloud and then "walk" the outermost vertices to tessellate the cloud, but I'm not sure this will work.

I suppose it's acceptable to add vertices, but the general shape of the "shell" should match the shape of the vertex cloud.

Matt Fichman
  • 5,458
  • 4
  • 39
  • 59

5 Answers5

2

I have an algorithm for you that works in the 2D case. It is tricky, but do-able to generalize it to 3D space. The basic idea is to start with a minimum-surface (triangle in 2D or tetrahedron in 3D), and split each edge (face) as you traverse the array of points.

2D algorithm (python. FULL SOURCE/DEMO HERE: http://pastebin.com/jmwUt3ES)

edit: this demo is fun to watch: http://pastebin.com/K0WpMyA3

def surface(pts):
center = pt_center(pts)
tx = -center[0]
ty = -center[1]
pts = translate_pts(pts, (tx, ty))
# tricky part: initialization
# initialize edges such that you have a triangle with the origin inside of it
# in 3D, this will be a tetrahedron.
ptA, ptB, ptC = get_center_triangle(pts)
print ptA, ptB, ptC
# tracking edges we've already included (triangles in 3D)
edges = [(ptA, ptB), (ptB, ptC), (ptC, ptA)]
# loop over all other points
pts.remove(ptA)
pts.remove(ptB)
pts.remove(ptC)
for pt in pts:
    ptA = (0,0)
    ptB = (0,0)
    # find the edge that this point will be splitting
    for (ptA, ptB) in edges:
        if crossz(ptA, pt) > 0 and crossz(pt, ptB) > 0:
            break
    edges.remove((ptA, ptB))
    edges.append((ptA, pt))
    edges.append((pt, ptB))
# translate everything back
edges = [((ptA[0] - tx, ptA[1] - ty), (ptB[0] - tx, ptB[1] - ty)) for (ptA, ptB) in edges]
return edges

RESULT:

2D demo result

Generalizing to 3D

  • instead of edges, you have triangles.
  • initialization is a tetrahedron around the origin
  • finding the splitting face involves projecting a triangle, and checking if the pt is interior to that triangle
  • splitting involves adding 3 new faces whereas 2D was 2 new edges
  • need to be careful about orientation of the face (in my 2D code, I was easily able to guarantee A->B would be CCW orientation)

Depending on the size of your point cloud and speed requirements, you may need to be more clever about data structures for faster add/remove.

wrongu
  • 560
  • 3
  • 13
1

3D convex hull (convex hull algorithm for 3d surface z = f(x, y)).

Then for points on each of the largest faces search for the closest point on the cloud and re-triangulate that face to include the point.

Repeat until it is "close enough" based on largest distance from the nearest cloud point for each of the remaining faces, or on the size (length/are?) of the largest remaining face

Community
  • 1
  • 1
Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
0

I would think about a "metric" function f(x, y, z) that returns a scalar value for an arbitrary point in 3D space. This function should be constructed in a way to consider whether a given point (x, y, z) is "inside" or "outside" of a cloud. For instance, this can be a length of an average vector from (x, y, z) to every point in a cloud, or it can be a number of cloud points within a certain vicinity of (x, y, z). Choice of the function will affect the final result.

Having this f(x, y, z) you use the marching cubes algorithm to perform tessellation, basically constructing an iso-surface of f(x, y, z) for a certain value.

Archie
  • 2,644
  • 21
  • 21
0

You should try 3d Delaunay Triangulation. This will tessellate the point cloud, while making sure that the tri mesh only has vertices from the point cloud. CGAL has a two implementations of triangulating the point cloud - delaunay and regular. The regular version triangulates the points using the idea described here.

You can use their implementation, if you're using C++. If not, you can still look at their code to implement it yourself (it is pretty complex though).

Arun R
  • 873
  • 6
  • 10
0

Sounds like you are looking for the "concave hull". This delivers a "reasonable" boundary around a set of points, "reasonable" meaning fitting the set up to a given tolerance. It is not a geometric property, like the convex hull, but a good approximation for a lot of "real world" problems, like finding a closely fitting boundary around a city.

You can find an implementation in the Point Cloud Library.

JayneDoe
  • 21
  • 3