Skip to content

Project Point Cloud to Plane Defined by Point Normal

SUMMARY

Project Point Cloud to Plane Defined by Point Normal orthogonally projects every point of a 3D point cloud onto a plane defined by a point and a normal vector.

Each point is moved to its closest point on the plane that passes through point with normal plane_normal. This is equivalent to project_point_cloud_to_plane — the same orthogonal projection, just specifying the plane geometrically (a point + normal) instead of via [a, b, c, d] coefficients.

Use this Skill when you want to flatten a point cloud onto a plane you already have as a point and normal vector, e.g. from a plane-fitting or centroid/normal estimation step.

The Skill

python
from telekinesis import vitreous

projected_point_cloud = vitreous.project_point_cloud_to_plane_defined_by_point_normal(
    point_cloud=point_cloud,
    point=[0.0, 0.0, 0.0],
    plane_normal=[0.0, 0.0, 1.0],
    add_white_noise=False,
    white_noise_standard_deviation=0.0,
)
API Reference
Full parameter and return type documentation for project_point_cloud_to_plane_defined_by_point_normal.
View Reference →

Data Transfer Notice

There is no longer a fixed limit of 1 million points per request. However, very large datasets may result in slower data transfer and processing times. We are continuously optimizing performance as part of our beta program, with ongoing improvements to enhance speed and reliability.

Example

Raw Pointcloud

Unprocessed point cloud. Plane for projection visualized in green.

Projected Pointcloud

Flattened pointcloud.

The Code

python
"""
Demonstrates projecting a point cloud onto a plane defined by a point and normal.
"""

from loguru import logger
import rerun as rr

from telekinesis import vitreous, datatypes


def project_point_cloud_to_plane_defined_by_point_normal_example():
    """
    Projects points onto a plane defined by a point and normal (alternative parameterization).

    Same as plane projection but using point+normal instead of coefficients.
    """
    # ===================== Load Data ==========================================
    point_cloud_url = (
        "https://assets.telekinesis.ai/examples/v1/point_clouds/engine_parts_0.ply"
    )
    point_cloud = datatypes.PointCloud.from_url(url=point_cloud_url, use_cache=True)

    # ===================== Run Skill ==========================================
    projected_point_cloud = (
        vitreous.project_point_cloud_to_plane_defined_by_point_normal(
            add_white_noise=False,
            white_noise_standard_deviation=1e-6,
            point_cloud=point_cloud,
            point=[0.0, 0.0, 0.0],
            plane_normal=[0.0, 0.0, 1.0],
        )
    )

    # ===================== Log ================================================
    logger.success(f"Projected {point_cloud} to plane defined by point and normal")
    logger.success(f"Results: {projected_point_cloud}")
    logger.info(
        f"Projected point cloud positions shape: {projected_point_cloud.positions.shape}"
    )
    logger.info(
        f"Projected point cloud has normals shape: "
        f"{projected_point_cloud.normals.shape if projected_point_cloud.has_normals else None}"
    )
    logger.info(
        f"Projected point cloud has colors shape: "
        f"{projected_point_cloud.colors.shape if projected_point_cloud.has_colors else None}"
    )

    # ===================== Visualization  (Optional) ===========================
    rr.init("project_point_cloud_to_plane_defined_by_point_normal_example", spawn=True)
    datatypes.visualize(point_cloud, entity_path="/1-input_point_cloud")
    datatypes.visualize(projected_point_cloud, entity_path="/2-filtered_point_cloud")


if __name__ == "__main__":
    project_point_cloud_to_plane_defined_by_point_normal_example()

Runnable examples are available in the Telekinesis examples repository.

Follow the README in that repository to set up the environment, run this specific example with:

bash
cd telekinesis-examples
python examples/point_cloud/project_point_cloud_to_plane_defined_by_point_normal.py

Parameter Configuration

These parameters are passed directly to the plane-projection service and control which plane (given as a point + normal) the cloud is projected onto, and whether synthetic noise is added to the result.

KeyTypeDefaultDescription
point_clouddatatypes.PointCloudrequiredThe point cloud to project
pointdatatypes.Vector3D | np.ndarray | list[float]requiredAny 3D point [x, y, z], in meters, that lies on the plane — defines the plane's position in space
plane_normaldatatypes.Vector3D | np.ndarray | list[float]requiredThe plane's normal direction [x, y, z], perpendicular to its surface — should be a unit vector. Defines the plane's orientation
add_white_noisedatatypes.Bool | boolFalseWhether to add random Gaussian noise to the projected points, e.g. to simulate measurement uncertainty when generating synthetic test data
white_noise_standard_deviationdatatypes.Float | float | int0.0Standard deviation, in meters, of the Gaussian noise added when add_white_noise is True; ignored otherwise

Returns

TypeDescription
datatypes.PointCloudA point cloud with every point moved onto the plane. Use .positions for the projected (N, 3) position array.

Raises

ExceptionCondition
TypeErrorA parameter's value does not match its expected type (see the Parameter Configuration table above)
ValueErrorpoint or plane_normal does not have exactly 3 elements
ConfigurationErrorThe TELEKINESIS_API_KEY environment variable is not set
SerializationErrorThe request input failed to serialize, or the response failed to deserialize
RequestTimeoutErrorThe request to the Vitreous service timed out
TransportErrorA network failure occurred before a response was received
ClientErrorThe Vitreous service rejected the request due to invalid input, invalid data, or another unexpected 4xx response
AuthenticationErrorThe API key was rejected as invalid or expired
AuthenticationServiceErrorThe authentication service was unavailable
ServerErrorThe Vitreous service returned a 5xx or otherwise unexpected error response

How to Tune the Parameters

point

  • Controls: A point that lies on the target plane, fixing the plane's position in space.
  • Units: Meters
  • Default: required, no default
  • Any point on the plane works — a natural choice is the centroid of a segmented planar region (e.g. via calculate_point_cloud_centroid)

plane_normal

  • Controls: The plane's orientation — the direction perpendicular to its surface.
  • Units: Dimensionless (unit vector)
  • Default: required, no default
  • Normalize to unit length before passing it in; an un-normalized vector still points the right direction but is not a valid unit normal
  • Often obtained from plane segmentation/estimation (e.g. the [a, b, c] part of segment_point_cloud_using_plane's output)

add_white_noise

  • Controls: Whether Gaussian noise is added to the projected points after they are moved onto the plane.
  • Units: Boolean
  • Default: False
  • Keep False for exact, deterministic projection
  • Set True only to synthesize noisy test data

white_noise_standard_deviation

  • Controls: The spread of the Gaussian noise added when add_white_noise=True. Ignored when add_white_noise=False.
  • Units: Meters
  • Default: 0.0
  • Increase → more variation around the projected plane position
  • Decrease → projected points stay closer to the exact plane
  • Typical range: 0.0–0.01 meters — use 0.001–0.005 for small variation, 0.005–0.01 for larger variation

TIP

Keep add_white_noise=False for exact projection. Make sure plane_normal is normalized, and pick a point that actually lies on the intended plane — e.g. from calculate_point_cloud_centroid on a segmented planar region.

Where to Use the Skill

Common pipelines include:

  • Planar surface alignment – flattening scanned parts onto a known reference plane before inspection
  • Ground/wall plane flattening – reducing floor or wall scans to a true 2D-in-3D representation for mobile robot mapping
  • 2D feature extraction – standardizing near-planar surfaces for downstream shape or area analysis
  • Registration preparation – aligning point clouds onto a common plane before registration or segmentation

Alternative Skills

Skillvs. Project Point Cloud to Plane (Point + Normal)
project_point_cloud_to_planeProjects onto the exact same kind of plane, just specified by [a, b, c, d] coefficients instead of a point + normal. Use whichever parameterization you already have on hand — the two are otherwise equivalent.

When Not to Use the Skill

Do not use Project Point Cloud to Plane (Point + Normal) when:

  • You have [a, b, c, d] plane coefficients instead — use project_point_cloud_to_plane directly rather than converting
  • You need to preserve full 3D structure — projection flattens the cloud onto the plane, discarding out-of-plane detail
  • You need a non-orthogonal projection — this Skill only performs orthogonal (closest-point) projection
  • point doesn't actually lie on the intended plane, or plane_normal isn't normalized — the projection will still run, but onto a different plane than you intended

TIP

If you don't have a point and normal yet, segment the plane first (segment_point_cloud_using_plane), then derive a point (e.g. calculate_point_cloud_centroid on the segmented points) and normal from that result.