Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 50 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ For more examples, see the [tutorials](https://heremaps.github.io/pptk/tutorial.
## Build

pptk-revived contains C++ extensions (Qt viewer, k-d tree, normal estimator)
that must be compiled before packaging. The build process is:

1. Compile C++ extensions with CMake
2. Package the compiled artifacts into a wheel
that are compiled with CMake. You don't run CMake yourself — the `setuptools`
build backend invokes it automatically while building the wheel (see the
`CMakeBuild` command in [`setup.py`](setup.py)), so a single `uv build`
produces a ready-to-install wheel.

### System requirements

Expand All @@ -101,54 +101,67 @@ that must be compiled before packaging. The build process is:
On Ubuntu/Debian:

```bash
sudo apt install build-essential cmake patchelf libtbb-dev libeigen3-dev qtbase5-dev libqt5opengl5-dev
sudo apt install build-essential cmake patchelf \
libtbb-dev libeigen3-dev qtbase5-dev libqt5opengl5-dev libgl1-mesa-dev
```

### Build with uv (recommended)
### Build a wheel

```bash
# 1. Compile C++ extensions
mkdir _cmake_build && cd _cmake_build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . -- -j$(nproc)
cd ..
uv build # compiles the C++ + packages -> dist/
uv pip install dist/pptk_revived-*.whl
```

# 2. Package into a wheel (uv detects the pre-compiled .so files and skips cmake)
uv build
> **Run build/install commands from the repository root**, never from inside
> `_cmake_build/`. The CMake build copies a `setup.py` into `_cmake_build/`, so
> running `uv build` or `pip install .` from there builds a broken, stale
> package (you'll see CMake fail with *"source directory … does not appear to
> contain CMakeLists.txt"*).

# 3. Install the wheel
uv pip install dist/pptk_revived-*.whl
This is exactly what the release CI runs (`.github/workflows/build-wheels.yml`).
Plain pip works the same way, since it uses the same backend:

```bash
pip install . # build C++ and install
python -m build # or only build the wheel + sdist into dist/
```

### Build with pip / venv
> **Forcing a recompile.** To avoid needless work, the build **skips CMake when
> the compiled artifacts already exist** in the source tree. After editing any
> C++ source, set `PPTK_FORCE_CMAKE=1` to clear the cached artifacts and rebuild
> from scratch:
>
> ```bash
> PPTK_FORCE_CMAKE=1 uv build
> ```

### Development install (editable)

```bash
# 1. Create a venv
python3 -m venv venv && source venv/bin/activate
pip install numpy

# 2. Compile C++ extensions
mkdir _cmake_build && cd _cmake_build
cmake .. -DCMAKE_BUILD_TYPE=Release -DPython3_EXECUTABLE=$(which python)
cmake --build . -- -j$(nproc)
cd ..

# 3. Package and install
python setup.py bdist_wheel
pip install dist/pptk_revived-*.whl --force-reinstall
uv sync # set up the dev env + editable install
# after changing C++ sources, force a recompile:
PPTK_FORCE_CMAKE=1 uv pip install -e .
```

### Windows
While iterating on C++ you can recompile a single target and refresh the
in-tree artifact the editable install loads, instead of rebuilding everything
(after an initial build has configured `_cmake_build/`):

```bat
mkdir _cmake_build && cd _cmake_build
cmake -G "NMake Makefiles" ..
nmake
cd ..
python setup.py bdist_wheel
pip install dist\pptk_revived-*.whl
```bash
cmake --build _cmake_build --target viewer -- -j$(nproc)
cp _cmake_build/pptk/viewer/viewer pptk/viewer/viewer
```

Available targets: `viewer`, `kdtree`, `vfuncs`, `estimate_normals` (for the
library modules, copy the resulting `.so` into the matching `pptk/<module>/`
directory).

### Windows

The same `uv build` command applies. Make sure Qt5, TBB, and Eigen are
discoverable by CMake (e.g. via `CMAKE_PREFIX_PATH`); CMake selects the Visual
Studio generator by default.

## Acknowledgements

Originally developed by [HERE Europe B.V.](https://github.com/heremaps) (Copyright 2011–2018).
Expand Down
4 changes: 2 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ def setup(app):
# built documents.
#
# The short X.Y version.
version = u'0.1'
version = u'0.3'
# The full version, including alpha/beta/rc tags.
release = u'0.1.1'
release = u'0.3.0'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
2 changes: 1 addition & 1 deletion pptk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from .colors import label_to_colors
from .ply import load_ply

__version__ = '0.1.1'
__version__ = '0.3.0'

connect = viewer.connect

Expand Down
7 changes: 6 additions & 1 deletion pptk/viewer/point_cloud.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,12 @@ class PointCloud : protected OpenGLFuncs {

// render methods
void draw(const QtCamera& camera, const SelectionBox* box = NULL) {
queryLOD(_octree_ids, camera, 0.25f);
// Coarse (interactive) LOD. Lower fudge_factor collapses octree nodes into
// large world-space centroid splats sooner; the fine pass uses 1.0f. A
// value too far below 1.0f makes points balloon during interaction and then
// visibly snap smaller once the fine pass runs. 0.5f keeps interaction fast
// while halving that size jump.
queryLOD(_octree_ids, camera, 0.5f);
if (_octree_ids.empty()) return;
draw(&_octree_ids[0], (unsigned int)_octree_ids.size(), camera, box);
}
Expand Down
9 changes: 7 additions & 2 deletions pptk/viewer/viewer.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,18 @@ class Viewer : public QWindow, protected OpenGLFuncs {
_camera.zoom(ev->angleDelta().y() / 120.0f);
_camera.save();
renderPoints();
renderPointsFine(500);
// Debounce the fine render so continuous scrolling stays on the fast coarse
// pass, but correct quickly once scrolling stops (was 500ms, which left the
// large coarse splats on screen long enough to look like a glitch).
renderPointsFine(100);
}

virtual void exposeEvent(QExposeEvent* ev) {
Q_UNUSED(ev);
renderPoints();
renderPointsFine(1000);
// Coalesce expose storms (show/uncover/move) without holding the oversized
// coarse splats for a full second after the window settles (was 1000ms).
renderPointsFine(200);
}

virtual void resizeEvent(QResizeEvent* ev) {
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "pptk-revived"
version = "0.2.0"
version = "0.3.0"
requires-python = ">=3.9"
dependencies = ["numpy<2", "pillow", "scikit-learn"]
description = "A Python package for facilitating point cloud processing."
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ def list_libs():

setup(
name='pptk-revived',
version='0.1.1',
version='0.3.0',
description='A Python package for facilitating point cloud processing.',
author='Nikolaas Steenbergen',
classifiers=[
Expand Down
Loading