Skip to content

Expose Poisson reconstruction parameters#7430

Open
Chevi-Koren wants to merge 6 commits intoisl-org:mainfrom
Chevi-Koren:expose-poisson-parameters
Open

Expose Poisson reconstruction parameters#7430
Chevi-Koren wants to merge 6 commits intoisl-org:mainfrom
Chevi-Koren:expose-poisson-parameters

Conversation

@Chevi-Koren
Copy link
Copy Markdown

@Chevi-Koren Chevi-Koren commented Feb 7, 2026

Expose Poisson reconstruction parameters #7430

Expose 3 important parameters in CreateFromPointCloudPoisson that were previously hardcoded:

  • full_depth: Minimum depth for density estimation (default: 5)
  • samples_per_node: Minimum sample points per octree node (default: 1.5)
  • point_weight: Point interpolation weight (default: 4.0)

This allows fine-tuning of surface reconstruction quality and performance. All parameters have sensible defaults matching previous behavior. Fully backward compatible.

The exposed parameters are intended for users who require fine-grained control over Poisson reconstruction behavior while keeping the API simple and focused.

Fixes #7248

Type

  • Bug fix (non-breaking change which fixes an issue): Fixes #
  • New feature (non-breaking change which adds functionality). Resolves Expose arguments of CreateFromPointCloudPoisson #7248
  • Breaking change (fix or feature that would cause existing functionality to not work as expected) Resolves #

Motivation and Context

Users currently cannot fine-tune the Poisson surface reconstruction algorithm because important parameters are hardcoded in the internal Execute function. This limitation was raised in issue #7248, where users requested the ability to adjust parameters like point_weight, samples_per_node, and full_depth to optimize reconstruction quality for their specific use cases.

This PR exposes 3 key parameters that significantly affect reconstruction quality and performance, while maintaining full backward compatibility through sensible default values that match the previous hardcoded behavior.

Checklist

  • I have run python util/check_style.py --apply to apply Open3D code style to my code.
  • This PR changes Open3D behavior or adds new functionality.
    • Both C++ (Doxygen) and Python (Sphinx / Google style) documentation is updated accordingly.
    • I have added or updated C++ and / or Python unit tests OR included test results (e.g. screenshots or numbers) here.
  • I will follow up and update the code if CI fails.
  • For fork PRs, I have selected Allow edits from maintainers.

Description

Changes Made

This PR modifies the CreateFromPointCloudPoisson API to expose 3 parameters that were previously hardcoded:

  1. full_depth (default: 5)

    • Specifies the minimum depth for density estimation.
    • Below this depth, the octree is complete.
    • Higher values increase stability in sparse regions at the cost of higher memory usage.
  2. samples_per_node (default: 1.5)

    • Minimum number of sample points that should fall within an octree node.
    • Controls adaptive octree refinement based on local point density.
    • Lower values allow finer octree subdivision but may increase noise.
    • Higher values suppress noise but may lose fine details.
  3. point_weight (default: 4.0)

    • Importance of point interpolation constraints.
    • Previously calculated as 2.0 * FEM_DEGREE (where FEM_DEGREE = 2).
    • Controls the trade-off between data fidelity and surface smoothness.
    • Higher values prioritize fitting to input points over smooth surface.

Files Modified

  • cpp/open3d/geometry/TriangleMesh.h: Updated function signature with new parameters and comprehensive Doxygen documentation.
  • cpp/open3d/geometry/SurfaceReconstructionPoisson.cpp: Modified Execute and CreateFromPointCloudPoisson to accept and pass through the new parameters.
  • cpp/pybind/geometry/trianglemesh.cpp: Exposed new parameters to Python API with corresponding default values.

Backward Compatibility

Fully backward compatible — all existing code will continue to work without modifications. The new parameters have default values that exactly match the previous hardcoded behavior.

Example — existing code still works:

mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(
    pcd, depth=8)

New code — can now fine-tune:

mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(
    pcd,
    depth=8,
    point_weight=5.0,
    full_depth=7,
    samples_per_node=2.0,
)

Expose 5 important parameters in CreateFromPointCloudPoisson that were
previously hardcoded:
- full_depth: Minimum depth for density estimation (default: 5)
- samples_per_node: Minimum sample points per octree node (default: 1.5)
- point_weight: Point interpolation weight (default: 4.0)
- confidence: Normal confidence weighting exponent (default: 0.0)
- exact_interpolation: Use exact constraints (default: false)

This allows fine-tuning of surface reconstruction quality and performance.
All parameters have sensible defaults matching previous behavior.
Fully backward compatible.

Fixes isl-org#7248
@update-docs
Copy link
Copy Markdown

update-docs bot commented Feb 7, 2026

Thanks for submitting this pull request! The maintainers of this repository would appreciate if you could update the CHANGELOG.md based on your changes.

@Chevi-Koren Chevi-Koren force-pushed the expose-poisson-parameters branch from 8250778 to e8337ab Compare February 7, 2026 20:21
@Chevi-Koren
Copy link
Copy Markdown
Author

@ssheorey
Would you be able to review this PR when you have time?

@ssheorey ssheorey requested review from Copilot and ssheorey February 12, 2026 05:35
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Exposes additional Poisson surface reconstruction parameters in TriangleMesh.create_from_point_cloud_poisson across C++ and Python, enabling advanced users to fine-tune reconstruction quality/performance while keeping prior defaults.

Changes:

  • Extended C++ API signature and internal Poisson Execute plumbing to accept full_depth, samples_per_node, point_weight, confidence, and exact_interpolation.
  • Updated Python bindings to expose the new keyword arguments with backward-compatible defaults.
  • Added Python tests and a changelog entry for the new parameters.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
python/test/geometry/test_poisson_parameters.py Adds pytest coverage for new Poisson parameters and backward compatibility.
cpp/pybind/geometry/trianglemesh.cpp Exposes new Poisson parameters to Python via pybind defaults/kwargs.
cpp/open3d/geometry/TriangleMesh.h Extends the public C++ API signature and Doxygen docs for Poisson parameters.
cpp/open3d/geometry/SurfaceReconstructionPoisson.cpp Threads new parameters from public API into Poisson execution path.
CHANGELOG.md Documents the newly exposed Poisson parameters.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

XForm<Real, Dim + 1> xForm, iXForm;
xForm = XForm<Real, Dim + 1>::Identity();

// Keep hardcoded internal parameters
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is misleading now that several parameters are no longer hardcoded (they’re passed as arguments). Consider rewording to clarify that only the remaining parameters below are still hardcoded (e.g., 'Keep other internal parameters hardcoded').

Suggested change
// Keep hardcoded internal parameters
// Keep other internal parameters hardcoded

Copilot uses AI. Check for mistakes.
Comment on lines +17 to +22
pcd.points = o3d.utility.Vector3dVector(
np.random.rand(100, 3) - 0.5
)
pcd.normals = o3d.utility.Vector3dVector(
np.random.rand(100, 3) - 0.5
)
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests rely on unseeded randomness, which can make them flaky (e.g., occasionally producing degenerate inputs that cause Poisson reconstruction to fail or vary drastically). Use a fixed seed (or deterministic sample geometry) so the tests are stable across runs and platforms.

Copilot uses AI. Check for mistakes.
Comment on lines +43 to +59
@pytest.mark.parametrize("params,expected_valid", [
({"depth": 6, "full_depth": 4, "samples_per_node": 2.0,
"point_weight": 5.0, "confidence": 0.5, "exact_interpolation": True}, True),
({"depth": 6, "full_depth": 3}, True),
({"depth": 6, "full_depth": 5}, True),
({"depth": 5, "samples_per_node": 1.0}, True),
({"depth": 5, "samples_per_node": 3.0}, True),
])
def test_poisson_with_various_parameters(sample_point_cloud, params, expected_valid):
"""Test Poisson reconstruction with various parameter combinations."""
mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(
sample_point_cloud, **params
)
if expected_valid:
_assert_valid_mesh(mesh, densities)


Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected_valid is always True in the parametrization, so the conditional doesn’t add value. Either remove expected_valid and the if block, or add at least one expected_valid=False case and assert the expected failure mode (e.g., with pytest.raises) to justify the parameter.

Suggested change
@pytest.mark.parametrize("params,expected_valid", [
({"depth": 6, "full_depth": 4, "samples_per_node": 2.0,
"point_weight": 5.0, "confidence": 0.5, "exact_interpolation": True}, True),
({"depth": 6, "full_depth": 3}, True),
({"depth": 6, "full_depth": 5}, True),
({"depth": 5, "samples_per_node": 1.0}, True),
({"depth": 5, "samples_per_node": 3.0}, True),
])
def test_poisson_with_various_parameters(sample_point_cloud, params, expected_valid):
"""Test Poisson reconstruction with various parameter combinations."""
mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(
sample_point_cloud, **params
)
if expected_valid:
_assert_valid_mesh(mesh, densities)
@pytest.mark.parametrize("params", [
{"depth": 6, "full_depth": 4, "samples_per_node": 2.0,
"point_weight": 5.0, "confidence": 0.5, "exact_interpolation": True},
{"depth": 6, "full_depth": 3},
{"depth": 6, "full_depth": 5},
{"depth": 5, "samples_per_node": 1.0},
{"depth": 5, "samples_per_node": 3.0},
])
def test_poisson_with_various_parameters(sample_point_cloud, params):
"""Test Poisson reconstruction with various parameter combinations."""
mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(
sample_point_cloud, **params
)
_assert_valid_mesh(mesh, densities)

Copilot uses AI. Check for mistakes.
Comment on lines +60 to +75
def test_poisson_parameter_variation(sample_point_cloud):
"""Test that different parameters produce different results."""
# Run with default point_weight
mesh1, _ = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(
sample_point_cloud, depth=5, point_weight=4.0
)

# Run with higher point_weight (should produce different result)
mesh2, _ = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(
sample_point_cloud, depth=5, point_weight=10.0
)

# Meshes should be different (different vertex counts or positions)
# We just check they both succeeded and have positive vertex counts
assert len(mesh1.vertices) > 0
assert len(mesh2.vertices) > 0
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test name/docstring claims to validate that different parameters produce different results, but the assertions only check success. Either rename/reword the test to reflect that it’s a smoke test, or add a deterministic input (see randomness comment) and assert a measurable difference (e.g., vertex count differs, bounding boxes differ, or vertex arrays are not identical within a tolerance).

Copilot uses AI. Check for mistakes.
CHANGELOG.md Outdated
@@ -1,4 +1,5 @@
## Main
- Exposed advanced parameters (`full_depth`, `samples_per_node`, `point_weight`, `confidence`, `exact_interpolation`) for Poisson surface reconstruction in `TriangleMesh.create_from_point_cloud_poisson` (PR #XXXX) (issue #7248)
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changelog entry still contains the placeholder 'PR #XXXX'. Replace it with the actual PR number before merging (or omit the PR number if the project convention is to have tooling fill it in).

Suggested change
- Exposed advanced parameters (`full_depth`, `samples_per_node`, `point_weight`, `confidence`, `exact_interpolation`) for Poisson surface reconstruction in `TriangleMesh.create_from_point_cloud_poisson` (PR #XXXX) (issue #7248)
- Exposed advanced parameters (`full_depth`, `samples_per_node`, `point_weight`, `confidence`, `exact_interpolation`) for Poisson surface reconstruction in `TriangleMesh.create_from_point_cloud_poisson` (issue #7248)

Copilot uses AI. Check for mistakes.
@ssheorey
Copy link
Copy Markdown
Member

ssheorey commented Feb 12, 2026

Hi @Chevi-Koren thanks for submitting this useful enhancement! Please also add documentation for these parameters (C++ and Python), from the point of view of "what are they, and what is the effect of changing them from the default value?"

Also, do we need all of them? We don't want to increase complexity of using Open3D unless its necessary. Or does fiddling with them help in common situations?

@Chevi-Koren
Copy link
Copy Markdown
Author

Hi @ssheorey, thanks for the feedback!

I've addressed both of your points:

  1. Documentation

I've added comprehensive documentation for all parameters explaining what they do, how they affect reconstruction, and when to adjust them. Each parameter now includes:

  • Clear description of its purpose
  • Effect of increasing/decreasing values
  • Recommended value ranges
  • Guidance on when to use different settings

For example:

/// \param point_weight Importance of point interpolation constraints
/// (default: 4.0). Controls the trade-off between data fidelity and surface
/// smoothness. Higher values (e.g., 10.0) prioritize fitting input points
/// exactly, resulting in surfaces closer to the data. Lower values produce
/// smoother surfaces. Recommended range: 2.0-10.0.

2. API Simplification

Following your concern about complexity, I've reduced the API to expose only 3 essential parameters:

point_weight - Most important and most requested. Users commonly need to adjust this for better data fidelity.
samples_per_node - Very useful for noise control. Common use case: noisy scans need higher values (2-3) to suppress artifacts.
full_depth - Helps with sparse regions. Useful but less critical.
I removed 2 advanced parameters:

confidence - Only relevant for confidence-weighted normals (rare use case)
exact_interpolation - Computationally expensive, rarely needed in practice
This keeps the API simple while exposing the parameters that help in common situations.

Additional Changes

Fixed all code review feedback from Copilot AI
Applied code style formatting (note: some files in this commit were automatically formatted by check_style.py)
Added deterministic random seed to tests for reproducibility
All changes remain fully backward compatible

Copy link
Copy Markdown
Member

@ssheorey ssheorey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you run make apply-style please?

PREFIX assimp
URL https://github.com/assimp/assimp/archive/refs/tags/v5.4.2.zip
URL_HASH SHA256=03e38d123f6bf19a48658d197fd09c9a69db88c076b56a476ab2da9f5eb87dcc
URL_HASH SHA256=8e2673677303fdfe1a8189d1335e4f22b1ad712afa53281dc3d62d6cb1280ead
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this accidental? Download URL and hash should both be changed together.

.gitignore Outdated
docs/getting_started.rst
docs/docker.rst
docs/tensorboard.md
venv/
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not open3d related. Remove this please.

- Expose full_depth, samples_per_node, and point_weight parameters
- Add comprehensive documentation for each parameter
- Add unit tests for parameter validation
- Fully backward compatible with default values
- All style checks applied

Fixes isl-org#7430
@Chevi-Koren Chevi-Koren force-pushed the expose-poisson-parameters branch from 7041d31 to fcf9ab8 Compare February 22, 2026 12:31
@Chevi-Koren
Copy link
Copy Markdown
Author

@ssheorey Done! I've run python util/check_style.py --apply and cleaned up the PR.

I removed all unrelated files that were accidentally included:

  • .gitignore (venv/ entry)
  • 3rdparty/assimp/assimp.cmake (accidental hash change)
  • All automatic formatting changes in unrelated files

The PR now contains only the 6 files directly related to this feature:

  • CHANGELOG.md
  • cpp/open3d/geometry/SurfaceReconstructionPoisson.cpp
  • cpp/open3d/geometry/TriangleMesh.h
  • cpp/open3d/visualization/gui/PickPointsInteractor.cpp
  • cpp/pybind/geometry/trianglemesh.cpp
  • python/test/geometry/test_poisson_parameters.py

Question: The style checker modified many other files (formatting changes in files like HashMap.cpp, NanoFlannIndex.cpp, etc.). Should I include these automatic formatting fixes in this PR, or keep it focused only on the Poisson parameters feature?

@ssheorey ssheorey requested a review from Copilot February 23, 2026 19:53
if (exact_interpolation) {
// Use approximate interpolation (default behavior)
if (false) {
iInfo = FEMTree<Dim, Real>::
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are hardcoding a single path here. Please check. Revert to original code if there is no logical difference.

@ssheorey
Copy link
Copy Markdown
Member

@Chevi-Koren ensure you are using the style checker SW versions from python/requirements-style.txt different versions of clang_format or yapf will format differently and cause changes in unrelated code. Do not include that in your PR.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

"linear_fit"_a = false, "n_threads"_a = -1)
"linear_fit"_a = false, "n_threads"_a = -1,
"full_depth"_a = 5, "samples_per_node"_a = 1.5f,
"point_weight"_a = 4.0f)
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Python bindings are missing the confidence and exact_interpolation parameters that were mentioned in the PR description as being exposed. The PR description states that 5 parameters are being exposed, but only 3 are present in the Python bindings. Either add the missing parameters to match the description, or update the PR description to reflect that only 3 parameters are being exposed.

Suggested change
"point_weight"_a = 4.0f)
"point_weight"_a = 4.0f, "confidence"_a = false,
"exact_interpolation"_a = false)

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

Comment on lines +604 to +605
// Use approximate interpolation (default behavior)
if (false) {
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition if (false) creates unreachable code. If exact interpolation is not being exposed as a parameter, this entire conditional block and the unreachable code inside should be removed to improve code maintainability. If it's intended to be exposed later, consider adding a TODO comment explaining the plan.

Copilot uses AI. Check for mistakes.
Comment on lines 423 to 429
// Keep other internal parameters hardcoded
float datax = 32.f;
int base_depth = 0;
int base_v_cycles = 1;
float confidence = 0.f;
float point_weight = 2.f * DEFAULT_FEM_DEGREE;
float confidence_bias = 0.f;
float samples_per_node = 1.5f;
float cg_solver_accuracy = 1e-3f;
int full_depth = 5;
int iters = 8;
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment "Keep other internal parameters hardcoded" should be updated to clarify that confidence and exact_interpolation were also removed (not just kept hardcoded), since the code below no longer uses these variables at all. Consider revising to: "Keep other internal parameters hardcoded. confidence and exact_interpolation have been removed."

Copilot uses AI. Check for mistakes.
- Remove unreachable exact_interpolation code path (if false block)
- Update comment to clarify confidence and exact_interpolation were removed
- Simplify code to only use approximate interpolation

Addresses code review feedback from @ssheorey and Copilot AI
@Chevi-Koren
Copy link
Copy Markdown
Author

@ssheorey Fixed! Removed the dead code branch and reverted to the single approximate interpolation path, as in the original code.
The PR description has also been corrected.

@ssheorey ssheorey requested a review from benjaminum February 24, 2026 00:12
@ssheorey ssheorey added the status / to merge Looks good, merge after minor updates. label Feb 24, 2026
Copy link
Copy Markdown
Contributor

@benjaminum benjaminum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thanks @Chevi-Koren !

@ssheorey
Copy link
Copy Markdown
Member

Hi @Chevi-Koren can you please fix the CI errors? e.g.:

The build failure occurs in cpp/open3d/geometry/SurfaceReconstructionPoisson.cpp at line 682:
Code

error: use of undeclared identifier 'datax'; did you mean 'atan'?
datax, linear_fit, UIntPack<FEMSigs...>(),
^~~~~

@ssheorey ssheorey added this to the v0.20 milestone Mar 4, 2026
@Chevi-Koren
Copy link
Copy Markdown
Author

@ssheorey Hi! Yes, fixed. The datax parameter was missing - I've added:

The value 32.f matches PoissonRecon's default.

@ssheorey
Copy link
Copy Markdown
Member

@Chevi-Koren still getting CI errors. Does it work on your local machine?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status / to merge Looks good, merge after minor updates.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose arguments of CreateFromPointCloudPoisson

4 participants