Python List vs NumPy Array Input Compatibility in pybind11-rdp: A Complete Guide

The pybind11-rdp library accepts both Python lists and NumPy arrays interchangeably by converting all inputs to NumPy ndarrays via np.asarray before passing them to the underlying C++ Eigen bindings.

The cubao/pybind11-rdp package implements the Ramer-Douglas-Peucker (RDP) algorithm with a high-performance C++ backend wrapped for Python. Understanding Python list vs NumPy array input compatibility is essential for writing flexible, efficient coordinate simplification code. The library seamlessly handles both input types through a thin Python wrapper that normalizes data before it reaches the C++ layer.

How the Python Wrapper Normalizes Input Types

The compatibility layer resides in src/pybind11_rdp/__init__.py, where the public API functions rdp(), rdp_rec(), and rdp_iter() preprocess all inputs. Each function calls np.asarray() to convert user-provided sequences into contiguous double-precision arrays before invoking the C++ bindings.

Specifically:

  • Lines 36-39 handle conversion for rdp_rec()
  • Lines 60-64 handle conversion for rdp_iter()
  • Lines 89-94 handle conversion for the unified rdp() entry point

This design means any array-like object—including native Python lists, tuples, or nested sequences—automatically becomes a NumPy ndarray with dtype=np.float64. The wrapper reshapes the data into the required (N, 2) or (N, 3) matrix format expected by the C++ implementation.

The C++ Eigen Interface

On the C++ side in src/main.cpp, the bindings receive data as Eigen matrix references rather than raw Python objects. The implementation defines two overloads:

  • Lines 15-23 accept 3-column matrices (Eigen::Ref<const RowVectors>)
  • Lines 25-33 accept 2-column matrices (Eigen::Ref<const RowVectorsNx2>)

Because the Python wrapper always passes a NumPy ndarray, the C++ layer sees a contiguous block of memory compatible with Eigen's Map semantics. This zero-copy mapping ensures high performance regardless of whether the original input was a Python list or a NumPy array.

Supported Input Types and Conversion Behavior

The following table details how different input types are processed before reaching the C++ algorithm:

Input Type Python Wrapper Action C++ Receives
Python list of lists/tuples np.asarray builds float64 array, preserving nesting order Eigen::Ref<const RowVectors> (or RowVectorsNx2) referencing contiguous data
NumPy ndarray np.asarray returns original object unchanged Same Eigen reference type as above
Other array-like objects (e.g., pandas DataFrame values) np.asarray attempts conversion; succeeds if result is 2-D float array Same as above (requires shape (N,2) or (N,3))

If the supplied data cannot be cast to a 2-D float64 array—for example, if inner lists have mismatched lengths—NumPy raises a ValueError before the C++ layer executes.

Practical Code Examples

The following examples demonstrate Python list vs NumPy array input compatibility using the rdp() function:

import numpy as np
from pybind11_rdp import rdp

# Example 1 – plain Python list (2-D points)

points_list = [[0, 0], [1, 0.1], [2, -0.1], [3, 5]]
simplified = rdp(points_list, epsilon=0.5)
print("simplified (list input):", simplified)

# Example 2 – NumPy ndarray (3-D points)

points_array = np.array([[0, 0, 0],
                         [1, 0.1, 0],
                         [2, -0.1, 0],
                         [3, 5, 0]], dtype=np.float64)
simplified = rdp(points_array, epsilon=0.5, algo="rec")
print("simplified (ndarray input):", simplified)

# Example 3 – request the keep-mask instead of coordinates

mask = rdp(points_list, epsilon=0.5, return_mask=True)
print("mask:", mask)

All three calls succeed because the wrapper transparently converts inputs to NumPy arrays before invoking the C++ implementation.

Error Handling and Validation

When working with heterogeneous input data, the library relies on NumPy's strict casting rules. Malformed inputs—such as jagged lists or non-numeric sequences—trigger a ValueError during the np.asarray() call in the Python wrapper. This prevents undefined behavior in the C++ layer and provides clear error messages at the Python level.

The wrapper requires inputs to resolve to either:

  • Shape (N, 2) for 2-D coordinate simplification
  • Shape (N, 3) for 3-D coordinate simplification

Any other dimensionality raises a standard NumPy reshape error before reaching the Eigen bindings in src/main.cpp.

Summary

  • Universal Input Support: The pybind11_rdp API accepts Python lists, tuples, and NumPy arrays through automatic np.asarray conversion in src/pybind11_rdp/__init__.py.
  • Zero-Copy Performance: C++ bindings use Eigen::Ref to map NumPy memory directly without copying, ensuring high performance regardless of input type.
  • Strict Validation: Input arrays must convert to 2-D float64 with shape (N,2) or (N,3); otherwise, NumPy raises ValueError before C++ execution.
  • Implementation Files: Key logic resides in src/pybind11_rdp/__init__.py (Python wrapper) and src/main.cpp (C++ Eigen bindings).

Frequently Asked Questions

Does pybind11-rdp accept Python lists or only NumPy arrays?

Both input types are fully supported. The library uses np.asarray() in the Python wrapper to convert lists, tuples, and other sequences into NumPy ndarrays before passing them to the C++ implementation. This conversion happens automatically in the rdp(), rdp_rec(), and rdp_iter() functions.

What data types does pybind11-rdp expect for coordinate inputs?

The wrapper forces dtype=np.float64 (double precision). While the input can be any array-like object, the np.asarray() call without explicit dtype specification creates a float64 array by default when given Python floats. The C++ Eigen bindings expect this specific memory layout for optimal performance.

How does the library handle pandas DataFrame inputs?

Pandas DataFrames work if converted to 2-D array values first. Passing df.values or any attribute that yields a 2-D array-like structure allows np.asarray to create the required matrix. The wrapper treats these objects identically to standard NumPy arrays once converted.

What happens if I pass a malformed list to the rdp function?

NumPy raises a ValueError before the C++ code executes. If inner lists have inconsistent lengths or contain non-numeric data, the np.asarray() call in src/pybind11_rdp/__init__.py fails with a descriptive error message. This prevents crashes in the underlying C++ RDP algorithm.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →