Cluster Point Cloud Based on Density Jump
SUMMARY
Cluster Point Cloud Based on Density Jump splits a point cloud into exactly two regions at the strongest density discontinuity along a chosen axis.
It projects points onto projection_axis, estimates local point density along that projection, and cuts the cloud where density changes abruptly — often where an object's volume or thickness changes rapidly (e.g. a part's head vs. its shaft, or a filled region vs. empty space). Unlike cluster_point_cloud_using_dbscan, which can discover any number of dense clusters, this Skill always returns exactly two regions, split at one density jump.
Use this Skill when you want to split a point cloud in two at a clear density transition, for example separating stacked or partially-touching objects where distance-based clustering can't tell them apart.
The Skill
from telekinesis import vitreous
regions = vitreous.cluster_point_cloud_based_on_density_jump(
point_cloud=point_cloud,
projection_axis=[0.0, 0.0, 1.0],
num_nearest_neighbors=12,
neighborhood_radius=0.001,
is_point_cloud_linear=False,
)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 Point Cloud Input
Calculated Clusters
Clusters found based on density change.
Parameters: projection_axis = np.array([0, 0, 1.0]), num_nearest_neighbors=5, neighborhood_radius=0.05.
The Code
"""
Demonstrates splitting a point cloud into regions based on density discontinuities.
"""
from loguru import logger
import rerun as rr
from telekinesis import vitreous, datatypes
def cluster_point_cloud_based_on_density_jump_example():
"""
Splits a point cloud into regions based on density discontinuities.
Detects and splits point clouds at locations where point density changes
dramatically.
"""
# ===================== Load Data ==========================================
point_cloud_url = (
"https://assets.telekinesis.ai/examples/v1/point_clouds/mug_preprocessed.ply"
)
point_cloud = datatypes.PointCloud.from_url(url=point_cloud_url, use_cache=True)
# ===================== Run Skill ==========================================
clusters = vitreous.cluster_point_cloud_based_on_density_jump(
point_cloud=point_cloud,
num_nearest_neighbors=5,
neighborhood_radius=0.05,
is_point_cloud_linear=False,
projection_axis=[0.0, 0.0, 1.0],
)
# ===================== Log ================================================
logger.success(f"Split {point_cloud} into density-based clusters")
logger.success(f"Results: {clusters}")
logger.info(f"Number of density-based clusters: {len(clusters)}")
logger.info(f"Points per cluster: {[len(p) for p in clusters.positions]}")
logger.info(f"First cluster is a PointCloud with {len(clusters[0])} points")
# ===================== Visualization (Optional) ===========================
rr.init("cluster_point_cloud_based_on_density_jump_example", spawn=True)
datatypes.visualize(point_cloud, entity_path="/1-input_point_cloud")
datatypes.visualize(clusters, entity_path="/2-density_jump_clusters")
if __name__ == "__main__":
cluster_point_cloud_based_on_density_jump_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:
cd telekinesis-examples
python examples/point_cloud/cluster_point_cloud_based_on_density_jump.pyParameter Configuration
| Key | Type | Default | Description |
|---|---|---|---|
point_cloud | datatypes.PointCloud | required | The point cloud to split |
projection_axis | datatypes.Vector3D | np.ndarray | list[float] | required | The direction [x, y, z] to project points onto before analyzing density. Set to the point cloud's principal axis (see estimate_principal_axes) for the clearest density signal |
num_nearest_neighbors | datatypes.Int | int | 12 | The number of nearest neighbors used to estimate density at each point |
neighborhood_radius | datatypes.Float | float | int | 0.001 | The radius, in meters, of the spherical neighborhood used for density estimation |
is_point_cloud_linear | datatypes.Bool | bool | False | Whether point_cloud is approximately one-dimensional (e.g. a rod, wire, or cable) rather than a 2D surface or 3D volume |
Returns
| Type | Description |
|---|---|
datatypes.PointCloudBatch | A batch with exactly 2 entries, one per side of the density jump. Use len(...) (always 2), .positions for the list of each region's (N_i, 3) position array, or index ([0]/[1]) to get a single region as a datatypes.PointCloud. |
Raises
| Exception | Condition |
|---|---|
TypeError | A parameter's value does not match its expected type (see the Parameter Configuration table above), or (for a list projection_axis) it contains a non-numeric element |
ValueError | projection_axis does not have exactly 3 elements |
ConfigurationError | The TELEKINESIS_API_KEY environment variable is not set |
SerializationError | The request input failed to serialize, or the response failed to deserialize |
RequestTimeoutError | The request to the Vitreous service timed out |
TransportError | A network failure occurred before a response was received |
ClientError | The Vitreous service rejected the request due to invalid input, invalid data, or another unexpected 4xx response |
AuthenticationError | The API key was rejected as invalid or expired |
AuthenticationServiceError | The authentication service was unavailable |
ServerError | The Vitreous service returned a 5xx or otherwise unexpected error response |
How to Tune the Parameters
projection_axis
- Controls: The direction points are projected onto before density is analyzed.
- Units: Unitless direction vector
[x, y, z] - Default: none — required
- Set to the point cloud's principal axis (see
estimate_principal_axes) for the clearest density signal - Typical values:
[0, 0, 1]for a vertical axis,[1, 0, 0]for horizontal along X
num_nearest_neighbors
- Controls: How many nearest neighbors are used to estimate density at each point.
- Units: Points (count)
- Default:
12 - Increase → more stable, smoother density estimate, but blurs out small/sharp density changes and is slower
- Decrease → more sensitive to local variation, but noisier
- Typical range: 6–30
neighborhood_radius
- Controls: The radius of the spherical neighborhood used for density estimation.
- Units: Meters
- Default:
0.001 - Increase → considers a wider area (more robust, less locally sensitive)
- Decrease → more locally sensitive, but noisier
- Scale to your point cloud
- Typical range: 0.0001–0.01 for small objects, 0.01–0.1 for larger scenes
is_point_cloud_linear
- Controls: Which density-estimation method is used — one suited to linear structures (e.g. a rod, wire, or cable) vs. the default suited to 2D surfaces or 3D volumes.
- Units: Boolean flag
- Default:
False - Set to
Trueonly when the point cloud is approximately one-dimensional
TIP
Best practice: use estimate_principal_axes to find projection_axis rather than guessing it, then adjust neighborhood_radius to your point cloud's scale (it's in meters) before fine-tuning num_nearest_neighbors.
Where to Use the Skill
Common pipelines include:
- Stacked object separation – splitting a head from its shaft, or a top item from the one beneath it
- Layered structure analysis – separating regions of a scene that differ in thickness or fill along one axis
- Assembly part identification – isolating a component whose density profile changes sharply from its neighbor
- Conveyor belt item isolation – separating touching items where DBSCAN's distance-based grouping would merge them
Alternative Skills
| Skill | vs. Cluster Point Cloud Based on Density Jump |
|---|---|
| cluster_point_cloud_using_dbscan | Discovers an arbitrary number of dense clusters directly from the data, instead of always splitting into exactly two regions at one density jump. Use DBSCAN when objects are spatially separated; use density jump clustering when objects are closely packed or touching. |
| estimate_principal_axes | Computes the point cloud's principal directions, useful for choosing a meaningful projection_axis instead of guessing it. |
When Not to Use the Skill
Do not use Cluster Point Cloud Based on Density Jump when:
- Objects are already spatially separated - use
cluster_point_cloud_using_dbscaninstead - There's no clear density discontinuity along any axis - the algorithm may not find a meaningful split
- You need more than 2 regions - this Skill always returns exactly 2
- The point cloud has roughly uniform density - there's no density jump to detect
- You don't yet know the principal axis - run
estimate_principal_axesfirst to chooseprojection_axis
WARNING
This Skill always returns exactly 2 regions, split at the single strongest density discontinuity found. If you need more than 2 groups, or the objects aren't aligned along one dominant axis, use cluster_point_cloud_using_dbscan instead.

