Skip to content

Expose Poisson reconstruction parameters#7430

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

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

Conversation

@Chevi-Koren
Copy link

Expose Poisson reconstruction parameters

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) - for advanced users working with confidence-weighted normals
  • 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.

The exposed parameters are intended for advanced users who require fine-grained control over Poisson reconstruction behavior.

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 5 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 5 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
  4. confidence (default: 0.0)

    • Exponent for normal length-based confidence weighting
    • When 0, all normals are weighted equally (standard behavior)
    • Positive values give more weight to normals with higher confidence (encoded via normal magnitude)
    • Exposed primarily for advanced users working with confidence-weighted normals
  5. exact_interpolation (default: false)

    • When true, uses exact point interpolation constraints
    • May improve accuracy but increases computational cost

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:

# Old code - still works identically
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,          # Increase data fidelity
    full_depth=7,              # More stability in sparse regions
    samples_per_node=2.0,      # Suppress noise
    exact_interpolation=True)  # Exact constraints

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

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
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

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.

/// \param point_weight Importance of point interpolation constraints (2.0 * FEM degree).
/// \param confidence Confidence exponent for normal length-based weighting (0 = no weighting).
/// \param exact_interpolation If true, use exact point interpolation constraints.
/// \return The estimated TriangleMesh, and per vertex density values that
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 \\return Doxygen sentence is now incomplete (it ends with 'values that'). Add the missing continuation (e.g., 'can be used to trim the mesh.') so generated docs remain readable.

Suggested change
/// \return The estimated TriangleMesh, and per vertex density values that
/// \return The estimated TriangleMesh, and per vertex density values that can be used to trim the mesh.

Copilot uses AI. Check for mistakes.
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
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?

- Removed advanced parameters (confidence, exact_interpolation)
- Kept essential parameters (full_depth, samples_per_node, point_weight)
- Added detailed documentation for each parameter
- Fixed all code review feedback from maintainers
- Updated tests and applied style formatting
- All changes fully backward compatible
@Chevi-Koren
Copy link
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

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose arguments of CreateFromPointCloudPoisson

2 participants