diff --git a/rdp/rdp.go b/rdp/rdp.go index 86be545..a8c421a 100644 --- a/rdp/rdp.go +++ b/rdp/rdp.go @@ -1,7 +1,9 @@ // Package rdp host the implementation of [Ramer–Douglas–Peucker algorithm](https://w.wiki/B6U3) algorithm. package rdp -import "math" +import ( + "math" +) // Point represents coordinates in 2D plane. type Point struct { @@ -15,6 +17,10 @@ type Point struct { // Note: The resulting slice is a reslice of given points (it shares the same underlying array) for efficiency. // It works similar to append, so the input points should not be used after this call, use only the returned value. func Simplify(points []Point, epsilon float64) []Point { + if epsilon <= 0 { + return points + } + if len(points) <= 2 { return points } @@ -34,16 +40,10 @@ func Simplify(points []Point, epsilon float64) []Point { } } - if maxDist <= epsilon { + if maxDist <= epsilon || index == 0 || index == len(points)-1 { return append(points[:0], first, last) } - // Move index to avoids infinite recursive as slice input - // for next operation is never changed if we keep it as is. - if index == 0 || index == len(points) { - index++ - } - left, right := points[:index], points[index:] return append(Simplify(left, epsilon), Simplify(right, epsilon)...) @@ -59,7 +59,7 @@ func perpendicularDistance(p, start, end Point) float64 { // Standard Form: Ax + Bx + C = 0 A := end.Y - start.Y B := start.X - end.X - C := (end.X * start.Y) - (start.X * end.Y) + C := start.Y*(end.X-start.X) - (end.Y-start.Y)*start.X // d = | Ax + By + C = 0 | / ✓(A²+B²) return math.Abs(A*p.X+B*p.Y+C) / math.Sqrt(A*A+B*B) diff --git a/rdp/rdp_test.go b/rdp/rdp_test.go index b0404a5..2ce636d 100644 --- a/rdp/rdp_test.go +++ b/rdp/rdp_test.go @@ -22,6 +22,18 @@ func TestSimplify(t *testing.T) { points []Point expect []Point }{ + { + name: "no point is removed", + epsilon: 0, + points: []Point{ + {X: 0.0, Y: 0.0}, + {X: 0.1, Y: 0.2}, + }, + expect: []Point{ + {X: 0.0, Y: 0.0}, + {X: 0.1, Y: 0.2}, + }, + }, { name: "one points", epsilon: 0.1, @@ -111,6 +123,22 @@ func TestPerpendicularDistance(t *testing.T) { d: 6.708, // euclidean((5,6), (2,0)) prec: 1000, }, + { + name: "same as start, distance should be zero", + p: Point{X: 45.897662518545985, Y: 6.801717197522521}, + start: Point{X: 45.897662518545985, Y: 6.801717197522521}, + end: Point{X: 45.89766209945083, Y: 6.8017197120934725}, + d: 0, + prec: 1000, + }, + { + name: "same as end, distance should be zero", + p: Point{X: 45.89766209945083, Y: 6.8017197120934725}, + start: Point{X: 45.897662518545985, Y: 6.801717197522521}, + end: Point{X: 45.89766209945083, Y: 6.8017197120934725}, + d: 0, + prec: 1000, + }, } for i, tc := range tt {