5. operations on coordinates, scalar fields, colors, meshes with Numpy

5.1. Read, modify or create cloud coordinates with Numpy

There are two ways to access the cloud coordinates from Numpy.

  • If you want to modify the data in place, without copy, use toNpArray()

  • if you prefer to copy the scalar field data, use toNpArrayCopy()


cloud = cc.loadPointCloud(getSampleCloud(5.0))

coords = cloud.toNpArrayCopy()
if coords.shape != (cloud.size(), 3):
    raise RuntimeError

The above code snippet is from test004.py.

You can fill the cloud coordinates with coordsFromNPArray_copy().

  • The array should have a shape (numberOfPoints,3).

  • WARNING Be sure to have an array data in C-style contiguous order. For instance, a transpose operation do not reorder the data in memory. Check the boolean array.flags array.flags['C_CONTIGUOUS'] and, if False, reorder with array.copy(order='C').

  • The cloud memory is reserved /resized automatically.

See below An example of point cloud with scalar field created from Numpy arrays.

5.2. Read, modify or create a scalar field with Numpy

There are two ways to access to the scalar field data from Numpy.

  • If you want to modify the data in place, without copy, use toNpArray()


dic = cloud1.getScalarFieldDic()
sf1 = cloud1.getScalarField(dic['Coord. Z'])
max1 = sf1.getMax()
asf1 = sf1.toNpArray()   # access to Numpy array, without copy
asf1[0] = 2*max1         # modification in place
sf1.computeMinAndMax()

The above code snippet is from test002.py.

You can fill a cloud scalar field with fromNpArrayCopy(). The method checks if the scalar field and the array have the same size, before copy.

See below An example of point cloud with scalar field created from Numpy arrays.

5.3. An example of point cloud with scalar field created from Numpy arrays


# --- generate a set of coords and a scalar field

npts = 10000000
phi = 2*np.pi*np.random.random((npts))
theta = 2*np.pi*np.random.random((npts))
r = 5 + 0.3*np.sin(2*2*np.pi*phi + 3*2*np.pi*theta)
x = np.float32(r*np.sin(phi)*np.cos(theta))
y = np.float32(r*np.sin(phi)*np.sin(theta))
z = np.float32(r*np.cos(phi))
coords = np.column_stack((x,y,z))
dr = np.float32(np.sqrt(x*x + y*y + z*z) -5)

# --- create the pointCloud, add the scalar field

cl = cc.ccPointCloud("boule")
cl.coordsFromNPArray_copy(coords)
cl.addScalarField("delta")
sf = cl.getScalarField(0)
sf.fromNpArrayCopy(dr)

# --- save the point cloud

res = cc.SavePointCloud(cl, os.path.join(dataDir, "boule.bin"))

The above code snippet is from test017.py.

5.4. Access to the indexes of triangles nodes in a mesh

In a mesh, the array of triangles indexes has a shape(number of triangles, 3), with indexes corresponding to the indexes of nodes in the associated cloud.

The method IndexesToNpArray() gives access to the array without copy. the corresponding nodes coordinates are given by the method toNpArray() from the associated cloud (getAssociatedCloud(). The method IndexesToNpArray_copy() creates a copy of the array of indexes.


# --- access to the numpy array of node indexes (one row per triangle)
d = mesh1.IndexesToNpArray()
if d.shape != (19602, 3):
    raise RuntimeError
if d.dtype != np.dtype('uint32'):
    raise RuntimeError

d2 = mesh1.IndexesToNpArray_copy()
if d2.shape != (19602, 3):
    raise RuntimeError
if d2.dtype != np.dtype('uint32'):
    raise RuntimeError

The above code snippet is from test011.py.

5.5. Access to the array of colors in cloud

The colors are stored in an array of shape(number of nodes, 4), the four components are R, G, B and alpha, each stored in a 8bits integer.

The method colorsToNpArray() gives access to the array of colors without copy, the method colorsToNpArrayCopy() creates a copy of the array.


cola = cloud.colorsToNpArray()
if not cola.shape == (1000000, 4):
    raise RuntimeError
if not cola.dtype == 'uint8':
    raise RuntimeError

colaCopy = cloud.colorsToNpArrayCopy()
if not colaCopy.shape == (1000000, 4):
    raise RuntimeError
if not colaCopy.dtype == 'uint8':
    raise RuntimeError

The above code snippet is from test029.py.