Point Cloud SurfaceΒΆ

../../_images/point_cloud.png

Surfaces of constant value within the point cloud use the cloudsurf static method of the Surface3DCollection class. In the above example, the point cloud is generated with the rand_point_cloud function, which is listed at the end. The function smoothes a set of random points, in this case shown below:

../../_images/point_cloud_points.png
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm,colors,colormaps
import s3dlib.surface as s3d

from example_data import rand_point_cloud

# 1. Get data to examine ...........................................

cloud, minc, maxc, __, __ = rand_point_cloud(50,seed=6)
domain,cmap = [-6,6], 'jet'
xyz, colors_a, __ = s3d.get_points_from_cloud(cloud,domain,cmap,0.5)

# 2. Setup and map surface .........................................

level = 0.25
value = minc + (maxc-minc)*level    
color = colormaps[cmap](level)    
surface = s3d.Surface3DCollection.cloudsurf(cloud,domain,value,color=color)
surface.evert().triangulate(2)

vE,iE = [ [-6,-6,6], [6,-6,6], [6,6,6], [6,-6,-6] ], [ [0,1,2],[1,3]]

# 3. Construct figures, add surfaces, and plot ....................
fig = plt.figure(figsize=(10,4))
# ....................
title = 'surface of\nconstant value = {:.2f}'.format(value)
fig.text(.27,0.9,title,ha='center')
ax_surf = fig.add_subplot(121, projection='3d', aspect='equal',proj_type='ortho')
ax_surf.set(xlim=domain, ylim=domain, zlim=domain,  
    xlabel='x',ylabel='y',zlabel='z')
ax_surf.add_collection3d(surface.shade(flat=False).hilite(.5,focus=2,flat=False))
ax_surf.add_collection3d( s3d.ColorLine3DCollection(vE,iE,color='0.6',lw=1) )
# ....................
fig.text(.7,0.9,"point cloud",ha='center')
ax_pnts = fig.add_subplot(122, projection='3d', aspect='equal',proj_type='ortho')
ax_pnts.set(xlim=domain, ylim=domain, zlim=domain,  
    xlabel='x',ylabel='y',zlabel='z')
ax_pnts.scatter(*xyz, c=colors_a, marker='.', s=1)
ax_pnts.add_collection3d( s3d.ColorLine3DCollection(vE,iE,color='0.6',lw=1) )
# ....................
norm = colors.Normalize(np.min(cloud),np.max(cloud) )
scmp = cm.ScalarMappable(norm=norm,cmap=cmap)
cbar = plt.colorbar(scmp, ax=ax_pnts,  shrink=0.8, pad=.1 )
cbar.set_label('cloud values', rotation=270, labelpad = 15)

fig.tight_layout(pad=3)
plt.show()

The random points and values used for the point cloud are accessed by:

npnts,cmap = 50, 'jet'
cloud, minc, maxc, pnts, vals = rand_point_cloud(npnts,seed=6)

The points were used for a Matplotlib scatter plot, along with the values for the color bar:

ax.scatter(*pnts.T, c=colormaps[cmap](vals), s=50, edgecolor='k')
norm = colors.Normalize(np.min(vals),np.max(vals) )
scmp = cm.ScalarMappable(norm=norm,cmap=cmap)
cbar = plt.colorbar(scmp, ax=ax,  shrink=0.8, pad=.15 )
cbar.set_label('point values', rotation=270, labelpad=15)

The rand_point_cloud function to create the point cloud from random points is:

import numpy as np

def rand_point_cloud(nPoints=50, N=None, spred=None, seed=None) :
    if seed is not None : np.random.seed(seed)
    N = 30 if N is None else N
    spred = 4 if spred is None else spred
    Nj = (N+1)*1j
    xyz = np.mgrid[-1:1:Nj,-1:1:Nj, -1:1:Nj ]
    rvals = np.random.rand(4,nPoints)
    bxyz = ( 1-2*rvals[:3].T )
    Ro = rvals[3::][0]
    dens = np.zeros(xyz.T.shape[:3])
    A = -0.223*spred**2
    for i,org in enumerate(bxyz) :
        diff = (xyz.T - org)
        R = np.linalg.norm(diff,axis=3)
        dens = dens + np.exp(A*(R/Ro[i])**2)
    return dens.T, np.min(dens), np.max(dens), bxyz, Ro