Skip to content

Commit a1974a1

Browse files
authored
Merge pull request #1 from user01/feature/expose-mask-to-python
Feature/expose mask to python
2 parents d6c24e3 + 1ed8991 commit a1974a1

File tree

6 files changed

+66
-4
lines changed

6 files changed

+66
-4
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
[package]
22
name = "rdp-rust"
3-
version = "0.4.0"
3+
version = "0.5.0"
44
edition = "2018"
55
authors = ["[email protected]"]
66
license = "MIT"
77
readme = "README.md"
8+
url = "https://github.com/user01/rdp-rust"
89

910
[lib]
1011
name = "rdp_rust"

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ build:
55
test: clean install
66
cargo test --no-default-features
77
cargo bench
8-
pytest -q test_options.py --benchmark-group-by=group
8+
pytest -q test_options.py
99

1010
target/wheels/rdp_rust-*-cp37-cp37m-macosx_10_7_x86_64.whl:
1111
maturin build --release

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ array([[5., 0.],
3232
[3., 2.]])
3333
```
3434

35+
```python
36+
>>> import numpy as np
37+
>>> from rdp_rust import mask_points
38+
39+
>>> arr = np.array([5.0, 0, 4, 0, 3, 0, 3, 1, 3, 2]).reshape(5, 2)
40+
>>> mask_points(small_arr, 0.2)
41+
array([ True, False, True, False, True])
42+
```
43+
3544
## Example
3645

3746
![Demo of RDP](https://github.com/user01/rdp-rust/raw/master/rdp-demo.gif "Demo of RDP")

src/lib.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use pyo3::prelude::{pymodule, Py, PyModule, PyResult, Python};
1010
#[allow(unused_imports)]
1111
use pyo3::{IntoPy, PyObject, ToPyObject};
1212
use pyo3::exceptions;
13+
use ndarray::Array;
1314

1415
mod rdp;
1516

@@ -49,10 +50,53 @@ fn reduce_points(
4950
}
5051
}
5152

53+
/// mask_points(points, epsilon, /)
54+
/// --
55+
///
56+
/// Provide the mask for the RDP point reduction on the float64
57+
/// numpy array of points
58+
/// points must be a numpy array of n by d, where n is the number
59+
/// of points and d is the dimension.
60+
/// Epsilon (float) is the threshold where points are removed as
61+
/// irrelevant, as defined by euclidean distance in the d
62+
/// dimensional space
63+
/// Makes use of the Ramer-Douglas-Peucker algorithm
64+
/// https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
65+
#[pyfunction]
66+
fn mask_points(
67+
py: Python,
68+
points: &PyArrayDyn<f64>,
69+
epsilon: f64,
70+
) -> PyResult<Py<PyArrayDyn<bool>>> {
71+
let the_points = points.as_array().to_owned();
72+
let dims = &the_points.shape().len();
73+
if *dims != 2 {
74+
Err(
75+
exceptions::ValueError::py_err("Incorrect shape. Must be numpy floating of n points by d dimension")
76+
)
77+
} else if epsilon < 0.0 {
78+
Err(
79+
exceptions::ValueError::py_err("Epsilon must be a float greater than 0")
80+
)
81+
} else {
82+
let indices = rdp::iter(&the_points, epsilon);
83+
let result = Array::from_shape_vec(
84+
indices.len(),
85+
indices,
86+
).expect(
87+
"Unable to build"
88+
);
89+
Ok(
90+
result.into_dyn().into_pyarray(py).to_owned()
91+
)
92+
}
93+
}
94+
5295

5396
#[pymodule]
5497
fn rdp_rust(_py: Python, m: &PyModule) -> PyResult<()> {
5598
m.add_wrapped(wrap_pyfunction!(reduce_points))?;
99+
m.add_wrapped(wrap_pyfunction!(mask_points))?;
56100

57101
Ok(())
58102
}

test_options.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import numpy as np
21
import pytest
2+
3+
import numpy as np
34
import rdp_rust
45
from rdp import rdp
56

@@ -19,6 +20,13 @@ def test_basic():
1920
assert res_rs.shape == res_py.shape
2021
np.testing.assert_almost_equal(res_rs, res_py)
2122

23+
def test_basic_mask():
24+
arr = np.array([5.0, 0, 4, 0, 3, 0, 3, 1, 3, 2]).reshape(5, 2)
25+
res_rs = rdp_rust.mask_points(arr, 0.1)
26+
res_py = rdp(arr, 0.1, return_mask=True)
27+
assert res_rs.shape == res_py.shape
28+
np.testing.assert_almost_equal(res_rs, res_py)
29+
2230

2331
small_arr = np.array([5.0, 0, 4, 0, 3, 0, 3, 1, 3, 2]).reshape(5, 2)
2432
small_expected = np.array([5.0, 0, 3, 0, 3, 2.0]).reshape(3, 2)

0 commit comments

Comments
 (0)