Search code examples
pythonnumpypointsurfacepolynomials

Deleting points above a surface


Given a set of 3D coordinates and its corresponding 2nd-order polynomial surface, I want to remove all points above the surface. The code snippet below shows an example of the fitted surface and points in 3D space.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression


np.random.seed(10)
x = np.random.rand(10)
y = np.random.rand(10)
z = np.random.rand(10)
X = np.column_stack((x, y))

poly = PolynomialFeatures(degree=2)
X_poly = poly.fit_transform(X)
model = LinearRegression()
model.fit(X_poly, z)

xi, yi = np.meshgrid(np.linspace(np.min(x), np.max(x), 10),
                     np.linspace(np.min(y), np.max(y), 10))

X_grid = np.column_stack((xi.flatten(), yi.flatten()))
X_grid_poly = poly.transform(X_grid)
z_grid = model.predict(X_grid_poly)
zi = np.reshape(z_grid, xi.shape)


fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(projection='3d')
ax.scatter(x,y,z, c='r', s=20)
ax.plot_surface(xi,yi,zi)
plt.show()

enter image description here

How can I remove all points above the fitted surface?


Solution

  • You should compare the z-coordinates of your original points with the corresponding z-coordinates predicted by the model at the x, y coordinates. If the original z-coordinate is greater than the predicted z-coordinate, you can remove it.

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.preprocessing import PolynomialFeatures
    from sklearn.linear_model import LinearRegression
    
    
    np.random.seed(10)
    x = np.random.rand(10)
    y = np.random.rand(10)
    z = np.random.rand(10)
    X = np.column_stack((x, y))
    
    poly = PolynomialFeatures(degree=2)
    X_poly = poly.fit_transform(X)
    model = LinearRegression()
    model.fit(X_poly, z)
    
    xi, yi = np.meshgrid(np.linspace(np.min(x), np.max(x), 10),
                         np.linspace(np.min(y), np.max(y), 10))
    
    X_grid = np.column_stack((xi.flatten(), yi.flatten()))
    X_grid_poly = poly.transform(X_grid)
    z_grid = model.predict(X_grid_poly)
    zi = np.reshape(z_grid, xi.shape)
    
    z_pred = model.predict(poly.transform(X))
    mask = z <= z_pred
    x_filtered, y_filtered, z_filtered = x[mask], y[mask], z[mask]
    
    fig = plt.figure(figsize=(10,10))
    ax = fig.add_subplot(projection='3d')
    ax.scatter(x_filtered, y_filtered, z_filtered, c='r', s=20)
    ax.plot_surface(xi,yi,zi)
    plt.show()