A Python library for ray tracing on COPC (Cloud Optimized Point Cloud) files with point clustering and geometric analysis.
pymeepcl manages multiple COPC files for efficient spatial queries using ray tracing, with a cache for loaded point data. Uses the Python bindings of copc-lib.
Manages multiple COPC files for ray tracing. Provides a unified interface for spatial queries.
Attributes:
cache: LRU cache for node point datafiles: List ofMeeFileobjectsbounds_copc,bounds_las: Combined global bounding boxes (tuple of min, max)
Methods:
trace_ray(ray, radius, return_sorted, timer, recursive): Traces a ray through all files, returns points within cylindrical radiusadd_file(filepath)/del_file(filepath): Add or remove COPC filesupdate_bounds(): Recalculate combined global bounds
Represents a single COPC file. Handles reading, indexing, and bounding box logic.
Key Methods:
intersect_global(ray, radius): Checks if ray hits the root bounding boxintersect_nodes(ray, radius): Vectorized intersection test, returns hit nodesintersect_nodes_octree(ray, radius): Recursive octree traversal (skips children of missed parents)build_index()/build_index_octree(): Construct index structures
Describes a ray using origin and direction. Direction is auto-normalized.
Attributes:
origin: Origin point as list or numpy array of shape (3,)direction: Direction vector as list or numpy array of shape (3,)
LRU cache for node point data. Keys are (filepath, node_key_string) tuples.
Attributes:
max_size: Maximum cached nodes (default: 1000)
Container for a clustered point segment and its geometric features (PCA/eigen features and shape descriptors).
Attributes:
id,points(N, 3),centroid(x, y, z)eigenvalues[λ1, λ2, λ3] descending,normal_vector- Shape descriptors:
linearity,planarity,sphericity,omnivariance equation: Plane coefficients [a, b, c, d] for ax + by + cz + d = 0
Clusters points by 1D distance along the ray. Being replaced by the methods below.
Iteratively fits planes using RANSAC via pyRANSAC-3D.
cluster_and_analyze_ransac(points, threshold=0.1, min_points=10, max_iterations=500)threshold: Max inlier distance (default: 0.1)min_points: Min points to continue fitting (default: 10)max_iterations: RANSAC iterations per plane (default: 500)- Returns list of
Segmentobjects; leftover points get id=-1
Two-stage approach: first clusters by distance gaps along the ray, then fits planes via RANSAC within each cluster.
cluster_and_analyze_sequential(points, ray, sensitivity=1, min_segment_points=20,
dif_min_threshold=0.2, ransac_threshold=0.1, ransac_max_iterations=300,
centralize=False)sensitivity: Gap threshold multiplier (higher = fewer clusters)min_segment_points: Min points per segmentdif_min_threshold: Fallback gap thresholdransac_threshold/ransac_max_iterations: RANSAC parameters for the second stagecentralize: If True, centers points before analysis (recommended for intersection calculations)- Returns list of
Segmentobjects; leftover points get id=-1
Calculates the intersection line of two planar segments and returns the result as a Ray.
calculate_plane_intersection_of_segments(segments)segments: List of exactly twoSegmentobjects with valid plane equations- Returns a
Rayalong the intersection line
Calculates intersection rays for all unique pairs of planar segments.
calculate_all_plane_intersections(segments)- Segments without a plane equation are skipped
- Returns a dict mapping
frozenset(id_a, id_b)to the intersectionRay
Extracts quality control metrics for a list of segments. Returns a list of dicts (easily converted to a pandas DataFrame).
get_segment_metrics(segments)- Metrics per segment: id, point count, linearity, planarity, sphericity, omnivariance, mean/max distance to fitted plane
from pymeepcl import MeeStruct, Ray, cluster_and_analyze_ransac
import numpy as np
# Initialize with a file or directory
struct = MeeStruct("path/to/file.copc.laz")
# or
struct = MeeStruct("path/to/directory/")
# Create a ray and trace
ray = Ray(origin=[0, 0, 0], direction=[0, 0, -1])
points = struct.trace_ray(ray, radius=0.5)
# Cluster and analyze
segments = cluster_and_analyze_ransac(points, threshold=0.1)python pymeepcl.py -i input.copc.laz -p 0 0 0 -d 0 0 -1 -r 0.5 -o output.xyz| Option | Description |
|---|---|
-i, --input |
Path to COPC file or directory |
-p, --projectioncenter |
Origin point (x y z) |
-d, --direction |
Direction vector (dx dy dz) |
-r, --radius |
Cylinder radius (default: 0.5) |
-o, --output |
Output file path (default: points.xyz) |
--no-sorted |
Don't sort points by distance along ray |
Visualization helpers for point cloud data using matplotlib, Plotly, and Open3D.
MeePlotter: Draw octree nodes and bounding boxes for debuggingdraw_ray(): Visualize a raydraw_segments(): Plot segments in different colorsdraw_segments_with_planes(): Plot segments with their fitted planes (matplotlib)draw_segments_with_planes_o3d(): Interactive 3D visualization with Plotly/Open3D, supports ray overlaysdraw_planes(): Plot planes from equation coefficientsdraw_points(): Simple point cloud scatter plotchart_from_segments(): Bar chart of point counts per segment
Generates node statistics for COPC files.
python copc_stats.py -i <input> [-o statistics_summary.csv] [-wh <dir>] [-sh]- Ray tracing with cylindrical radius filtering
- Multi-file support (tiles)
- LRU node caching
- Vectorized and recursive octree intersection tests
- Three clustering methods: distance-based, RANSAC, and sequential (hybrid)
- PCA-based geometric analysis (shape descriptors)
- Plane intersection calculations
- Segment quality metrics
- Visualization utilities (matplotlib and Plotly/Open3D)