3D Visualization of a Convex Hull with D3

This notebook provides a simple example of convex hull visualization using D3.

D3 Graph Methods

See accompanying d3_lib.py and the js and css folders.


In [1]:
%matplotlib inline
from IPython.core.display import HTML
import d3_lib

In [2]:
HTML(d3_lib.set_styles(['basic_axis','3d_viewer']))


Out[2]:

In [3]:
HTML('<script src="lib/d3/d3.min.js"></script>')


Out[3]:

In [4]:
def points_d3(points):
    return [ {"x": d[0], "y": d[1], "z": d[2]} for d in points ]

def triangles_d3(points,triangles_vertices):
    triangles = []
    for tv in triangles_vertices:
        triangles.append( {"x1": points[tv[0]][0], 
                           "y1": points[tv[0]][1], 
                           "z1": points[tv[0]][2], 
                           "x2": points[tv[1]][0], 
                           "y2": points[tv[1]][1], 
                           "z2": points[tv[1]][2], 
                           "x3": points[tv[2]][0], 
                           "y3": points[tv[2]][1], 
                           "z3": points[tv[2]][2] } )
    
    return triangles

def graph_points_triangles(objs):
    data = []
    for obj in objs:
        points, triangles_vertices = obj[0], obj[1]
        data.append( {"points": points_d3(points), 
                      "triangles": triangles_d3(points, triangles_vertices)} )
    return HTML(d3_lib.draw_graph('3d_viewer',{'data':data}))

Meshing and Volume Calculations


In [5]:
import numpy as np
import random
from scipy.spatial import ConvexHull

In [6]:
def compute_mesh(points):
    hull = ConvexHull(points)
    indices = hull.simplices
    return indices, hull.vertices

Example: Randomly Sampled Points on a Cylinder


In [7]:
def cylinder_points_and_hull_given_sample_size(sample_size):
    points = []
    for i in range(sample_size/2):
        x = random.uniform(-1,1)
        z = random.uniform(0,1)
        s = (-1.0, 1.0)[random.uniform(0,1) < 0.5]
        y = s * (1 - x**2) ** (0.5)
        points.append(np.array([x,y,z]))
    for z in range(0,2):
        for i in range(n/4):
            x = random.uniform(-1,1)
            s = (-1.0, 1.0)[random.uniform(0,1) < 0.5]
            y = s * random.uniform(0,1) * (1 - x**2) ** (0.5)
            points.append(np.array([x,y,z]))
    points = np.array(points)
    triangles_vertices, hull_points = compute_mesh(points)
    return points, hull_points, triangles_vertices

In [8]:
random.seed(42)
n = 100
points, hull_vertices, triangles_vertices = cylinder_points_and_hull_given_sample_size(n)
points[:3]


Out[8]:
array([[ 0.2788536 ,  0.96033363,  0.02501076],
       [-0.55357852, -0.83279698,  0.73647121],
       [ 0.78435914,  0.62030698,  0.08693883]])

In [9]:
triangles_vertices[:3]


Out[9]:
array([[42, 77, 99],
       [ 4, 69, 99],
       [ 4, 42, 99]], dtype=int32)

In [10]:
graph_points_triangles([[points, triangles_vertices]])


Out[10]: