@@ -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) {
0 commit comments