Smesh – Mesh→Point-Cloud Sensor Simulator (core skeleton)
Project description
SMesh – mesh→point cloud simulator
Sample points from a Mesh. Smesh.
Yeah, it wasn't my best day. But it sounds utterly filthy, which I enjoy.
Installation
You wouldn't guess:
pip install smesh
Optional extras for faster intersectors and LAS compression:
pip install "smesh[vtk]" # VTK-backed attribute probing & intersector
pip install "smesh[embree]" # Embree (via trimesh[ray])
pip install "smesh[laz]" # LAZ compression
Workflow Examples
| Capture | Preview | Command |
|---|---|---|
| Raw Mesh Baseline | python scripts/render_examples.py --example raw_mesh |
|
| Aerial LiDAR | smesh sample examples/configs/preview/aerial_lidar_preview.yaml |
|
| Mobile LiDAR | smesh sample examples/configs/preview/mobile_lidar_preview.yaml |
|
| Total Station | smesh sample examples/configs/preview/total_station_preview.yaml |
|
| Photogrammetry | smesh sample examples/configs/preview/photogrammetry_preview.yaml |
Each preview config runs in under a minute on CPU-only machines, producing lightweight outputs for quick inspection.
Higher fidelity counterparts live in examples/configs/ and can be regenerated by rerunning scripts/render_examples.py --full.
Want to help optimise it? Open a PR! See open TODOs.
One Scenario, Three Entry Points
The aerial preview (examples/configs/preview/aerial_lidar_preview.yaml) is reproduced below via config, pure CLI options, and the Python SDK.
Config file
smesh sample examples/configs/preview/aerial_lidar_preview.yaml
Does it all from a config file, which looks like:
type: lidar
mesh:
path: ../../meshes/preview_scene.ply
trajectory:
kind: lawnmower
altitude_m: 40.0
speed_mps: 20.0
line_spacing_m: 1.2
heading_deg: 0.0
pattern:
kind: oscillating
fov_deg: 110.0
line_rate_hz: 25.0
pulses_per_line: 600
sensor:
kind: lidar
max_range_m: 200.0
multi_return: true
beam_divergence_mrad: 0.4
num_lines: 60
noise:
kind: lidar
sigma_range_m: 0.05
sigma_angle_deg: 0.1
keep_prob: 0.99
sampler:
batch_size_rays: 20000
attributes:
- range
- incidence
- scan_angle
- intensity
- returns
- gps_time
output:
path: aerial_preview.las
format: las
seed: 101
CLI arguments (no YAML)
If you like passing around flags like a paid shill at a far-right rally, knock yourself out, but don't expect me to type them here:
mkdir -p scratch
smesh sample-lidar --mesh examples/meshes/preview_scene.ply \
--output scratch/aerial_cli.las --seed 101
Use --help if you need to.
Use SDK
If you're planning to smesh stuff from another project or smesh in a larger pipeline, you can use it like a library:
import numpy as np
from smesh import MeshScene, Sampler, SamplerConfig, AutoIntersector, LasWriter
from smesh.core.intersector import RayBundle
scene = MeshScene(mesh_path="scene.ply")
# Make a tiny fan of rays from above
M = 1000
origins = np.tile(np.array([[0,0,10.0]]), (M,1))
dirs = np.tile(np.array([[0,0,-1.0]]), (M,1))
bundle = RayBundle(origins=origins, directions=dirs, max_range=100.0, multi_hit=False, meta={"gps_time": np.arange(M)*1e-3})
sampler = Sampler(scene, intersector=AutoIntersector(), cfg=SamplerConfig())
writer = LasWriter("out.las", compress=False)
stats = sampler.run_to_writer(writer, ray_batches=[bundle])
print(stats)
Note: for VTK-backed attribute probing and fast VTK intersector, install
vtk. For Embree, installtrimesh[ray]which pullspyembree(and requires Intel Embree runtime).
If you already have a YAML scenario, you can also run it directly from Python:
from smesh.sdk import sample_from_config
result = sample_from_config("examples/configs/preview/aerial_lidar_preview.yaml")
print(result.output_path, result.stats["points"])
This is built from a bunch of components that i've smeshed together mostly with vibes so don't ask me any detailed questions. Here's what the computer said:
MeshScene(mesh IO + attribute probing via VTK)Intersector(VTK OBBTree + optional Embree viatrimesh[ray])PointBatchcontainerAttributeComputerplug-ins (range, incidence, scan angle, returns, intensity, gps time, color/normal probe, beam footprint)LasWriterwith streaming support and dynamic ExtraBytesSamplerorchestrator which glues everything together
Output writers
LasWriterstreams directly to disk batch-by-batch (compression optional).PlyWriterandNpzWriterbuffer incoming batches in memory and emit a single file whenclose()is called. Callclose()explicitly if you manage the writer yourself.
Attribute pipeline notes
The sampler now orders attribute computers based on their declared dependencies.
Custom attribute chains still work—dependencies like range_m for intensity will
be inserted automatically so long as a matching producer exists.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file smesh-0.0.5.tar.gz.
File metadata
- Download URL: smesh-0.0.5.tar.gz
- Upload date:
- Size: 47.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c53c3e19d03ec7fe876708bb9d912a4471dc57717c1a1ddace738a3e0ce10d2c
|
|
| MD5 |
d56ef2b09b72f884e29e89fa1726602b
|
|
| BLAKE2b-256 |
1b9616bd9b602b8ed52772c54d369da5e928e01d77e2f0e1e2540e03ede5c47d
|
File details
Details for the file smesh-0.0.5-py3-none-any.whl.
File metadata
- Download URL: smesh-0.0.5-py3-none-any.whl
- Upload date:
- Size: 55.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
501c2e7ed15e229c3aa71f9091a1512e490e56a6e403bccf0129bf4d7c221a1d
|
|
| MD5 |
0ae773c3951b4c16c85af2b4e6d1b93d
|
|
| BLAKE2b-256 |
3a7028674cadff91239a564becbdb4de38dc30fb20805a091ba9bce1b5533284
|