Skip to content

Commit 4d8660b

Browse files
handle degenerate case (#14)
* not ready * just merge into master --------- Co-authored-by: TANG ZHIXIONG <zhixiong.tang@momenta.ai>
1 parent 4c277e0 commit 4d8660b

File tree

5 files changed

+55
-2
lines changed

5 files changed

+55
-2
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ test_in_linux:
3535

3636
PYTHON ?= python3
3737
python_install:
38-
$(PYTHON) setup.py install
38+
$(PYTHON) setup.py install --force
3939
python_build:
4040
$(PYTHON) setup.py bdist_wheel
4141
python_sdist:

docs/about/release-notes.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ To upgrade `pybind11-rdp` to the latest version, use pip:
1010
pip install -U pybind11-rdp
1111
```
1212

13+
## Version 0.1.4 (2023-07-28)
14+
15+
* Handle degenerate case, related to <https://github.com/mapbox/geojson-vt/issues/104>
16+
* How to test? Use `ulimit -s 100 && python3 test.py`?
17+
18+
## Version 0.1.3 (2023-07-28)
19+
20+
* Update docs, update packaging
21+
1322
## Version 0.1.2 (2023-03-02)
1423

1524
* Identical API to rdp, notice difference

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def build_extension(self, ext):
122122
# logic and declaration, and simpler if you include description/version in a file.
123123
setup(
124124
name="pybind11_rdp",
125-
version="0.1.3",
125+
version="0.1.4",
126126
author="tzx",
127127
author_email="dvorak4tzx@gmail.com",
128128
url="https://github.com/cubao/pybind11-rdp",

src/main.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,22 @@ void douglas_simplify(const Eigen::Ref<const RowVectors> &coords,
5858
LineSegment line(coords.row(i), coords.row(j));
5959
double max_dist2 = 0.0;
6060
int max_index = i;
61+
int mid = i + (j - i) / 2;
62+
int min_pos_to_mid = j - i;
6163
for (int k = i + 1; k < j; ++k) {
6264
double dist2 = line.distance2(coords.row(k));
6365
if (dist2 > max_dist2) {
6466
max_dist2 = dist2;
6567
max_index = k;
68+
} else if (dist2 == max_dist2) {
69+
// a workaround to ensure we choose a pivot close to the middle of
70+
// the list, reducing recursion depth, for certain degenerate inputs
71+
// https://github.com/mapbox/geojson-vt/issues/104
72+
int pos_to_mid = std::fabs(k - mid);
73+
if (pos_to_mid < min_pos_to_mid) {
74+
min_pos_to_mid = pos_to_mid;
75+
max_index = k;
76+
}
6677
}
6778
}
6879
if (max_dist2 <= epsilon * epsilon) {
@@ -88,11 +99,22 @@ void douglas_simplify_iter(const Eigen::Ref<const RowVectors> &coords,
8899
LineSegment line(coords.row(i), coords.row(j));
89100
double max_dist2 = 0.0;
90101
int max_index = i;
102+
int mid = i + (j - i) / 2;
103+
int min_pos_to_mid = j - i;
91104
for (int k = i + 1; k < j; ++k) {
92105
double dist2 = line.distance2(coords.row(k));
93106
if (dist2 > max_dist2) {
94107
max_dist2 = dist2;
95108
max_index = k;
109+
} else if (dist2 == max_dist2) {
110+
// a workaround to ensure we choose a pivot close to the middle
111+
// of the list, reducing recursion depth, for certain degenerate
112+
// inputs https://github.com/mapbox/geojson-vt/issues/104
113+
int pos_to_mid = std::fabs(k - mid);
114+
if (pos_to_mid < min_pos_to_mid) {
115+
min_pos_to_mid = pos_to_mid;
116+
max_index = k;
117+
}
96118
}
97119
}
98120
if (max_dist2 <= epsilon * epsilon) {

tests/test_basic.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import os
22
import sys
3+
import time
34

5+
import numpy as np
46
import pytest
57

68
from pybind11_rdp import LineSegment, rdp
@@ -23,6 +25,26 @@ def test_rdp():
2325
assert rdp([[0, 0], [5, 1 - 1e-3], [10, 0]], epsilon=1).shape == (2, 2)
2426

2527

28+
def test_degenerate_case():
29+
# https://github.com/mapbox/geojson-vt/issues/104
30+
coords = []
31+
for _ in range(14000):
32+
coords.extend(
33+
[
34+
[0.0, 0.0],
35+
[1.0, 0.0],
36+
[1.0, 1.0],
37+
[0.0, 1.0],
38+
]
39+
)
40+
coords = np.array(coords)
41+
tick = time.time()
42+
ret = rdp(coords, 2e-15, algo="recursive")
43+
tock = time.time()
44+
print(tock - tick, "secs") # 4 sec
45+
assert len(ret) == len(coords)
46+
47+
2648
def pytest_main(dir: str, *, test_file: str = None):
2749
os.chdir(dir)
2850
sys.exit(

0 commit comments

Comments
 (0)