The Ramer-Douglas-Peucker path reduction algorithm

A simple implementation of the Douglas-Peucker path reduction algorithm. Use for simplifying curves, for instance in plotting coastlines. Loosely based on this implementation: http://karthaus.nl/rdp/

Tools:
``` 1: namespace DouglasPeuker
2:
3: open System
4:
5: type Point = { X: double; Y : double}
6:
7: module Reduce =
8:
9:     let private findPerpendicularDistance p p1 p2 =
10:         if (p1.X = p2.X) then
11:             Math.Abs(p.X - p1.X)
12:         else
13:             let slope = (p2.Y - p1.Y) / (p2.X - p1.X)
14:             let intercept = p1.Y - (slope * p1.X)
15:             Math.Abs(slope * p.X - p.Y + intercept) / Math.Sqrt(Math.Pow(slope, 2.) + 1.)
16:
17:     let rec Reduce epsilon (points : Point[]) =
18:         if points.Length < 3 || epsilon = 0. then
19:             points
20:         else
21:             let firstPoint = points.[0]
22:             let lastPoint = points.[points.Length - 1]
23:
24:             let mutable index = -1
25:             let mutable dist = 0.0
26:
27:             for i in 1..points.Length-1 do
28:                 let cDist = findPerpendicularDistance points.[i] firstPoint lastPoint
29:                 if (cDist > dist) then
30:                     dist <- cDist
31:                     index <- i
32:
33:             if (dist > epsilon) then
34:                 let l1 = points.[0..index]
35:                 let l2 = points.[index..]
36:                 let r1 = Reduce epsilon l1
37:                 let r2 = Reduce epsilon l2
38:                 Array.append (r1.[0..r1.Length-2]) r2
39:             else
40:                 [|firstPoint; lastPoint|]
41:
42: module Tests =
43:
44:     open FsUnit
45:     open NUnit.Framework
46:     open Reduce
47:
48:     [<TestFixture>]
49:     type ``Given the DouglasPeuker Simplify function``() =
50:
51:         let StrToPoints (s : string) =
52:             s.Split([|';'|])
53:             |> Array.map (fun p -> let xy = p.Split([|','|])
54:                                    {X = Double.Parse(xy.[0]); Y = Double.Parse(xy.[1])})
55:
56:         // Minimal cases:
57:         [<TestCase("1.0, 1.0", "1.0, 1.0", 0.5)>]
58:         [<TestCase("1.0, 1.0; 2.0, 2.0", "1.0, 1.0; 2.0, 2.0", 0.5)>]
59:         [<TestCase("1.0, 1.0; 2.0, 2.0; 3.0, 3.0", "1.0, 1.0; 3.0, 3.0", 0.5)>]
60:
61:         // Effect of varying epsilon:
62:         [<TestCase("0.0, 2.0; 1.0, 1.0; 3.0, 0.0; 5.0, 1.0", "0.0, 2.0; 1.0, 1.0; 3.0, 0.0; 5.0, 1.0", 0.1)>]
63:         [<TestCase("0.0, 2.0; 1.0, 1.0; 3.0, 0.0; 5.0, 1.0", "0.0, 2.0; 3.0, 0.0; 5.0, 1.0", 0.5)>]
64:
65:         // Tests with vertical segments:
66:         [<TestCase("10.0, 35.0; 15.0, 34.0; 15.0, 30.0; 20.0, 29.0", "10.0, 35.0; 20.0, 29.0", 10.0)>]
67:         [<TestCase("10.0, 35.0; 15.0, 34.0; 15.0, 30.0; 20.0, 29.0", "10.0, 35.0; 15.0, 34.0; 15.0, 30.0; 20.0, 29.0", 1.0)>]
68:
69:         // Tests with horizontal segments:
70:         [<TestCase("10.0, 35.0; 15.0, 35.0; 16.0, 30.0; 21.0, 30.0", "10.0, 35.0; 21.0, 30.0", 10.0)>]
71:         [<TestCase("10.0, 35.0; 15.0, 35.0; 16.0, 30.0; 21.0, 30.0", "10.0, 35.0; 15.0, 35.0; 16.0, 30.0; 21.0, 30.0", 1.0)>]
72:
73:         // Tests with vertical and horizontal segments:
74:         [<TestCase("10.0, 30.0; 30.0, 30.0; 30.0, 10.0; 50.0, 10.0", "10.0, 30.0; 50.0, 10.0", 15.0)>]
75:         // Different epsilon:
76:         [<TestCase("10.0, 30.0; 30.0, 30.0; 30.0, 10.0; 50.0, 10.0", "10.0, 30.0; 50.0, 10.0", 10.0)>]
77:
78:         // A more complex curve:
79:         [<TestCase("3.5, 21.25; 7.3, 12.0; 23.2, 3.1; 37.2, 12.07; 54.6, 18.15; 62.2, 16.45; 71.5, 9.7; 101.3, 21.1", "3.5, 21.25; 23.2, 3.1; 54.6, 18.15; 71.5, 9.7; 101.3, 21.1", 5.0)>]
80:
81:         member public this.``inputs are correctly simplified``(items : string, expected : string, epsilon) =
82:             let actual = Reduce epsilon (items |> StrToPoints)
83:             let expected = expected |> StrToPoints
84:             actual |> should equal expected```
namespace DouglasPeuker
namespace System
type Point =
{X: double;
Y: double;}

Full name: DouglasPeuker.Point

type: Point
implements: IEquatable<Point>
implements: Collections.IStructuralEquatable
implements: IComparable<Point>
implements: IComparable
implements: Collections.IStructuralComparable
Point.X: double
Multiple items
val double : 'T -> float (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.double

--------------------
type double = Double

Full name: Microsoft.FSharp.Core.double

type: double
implements: IComparable
implements: IFormattable
implements: IConvertible
implements: IComparable<float>
implements: IEquatable<float>
inherits: ValueType
Point.Y: double
val private findPerpendicularDistance : Point -> Point -> Point -> float

Full name: DouglasPeuker.Reduce.findPerpendicularDistance
val p : Point

type: Point
implements: IEquatable<Point>
implements: Collections.IStructuralEquatable
implements: IComparable<Point>
implements: IComparable
implements: Collections.IStructuralComparable
val p1 : Point

type: Point
implements: IEquatable<Point>
implements: Collections.IStructuralEquatable
implements: IComparable<Point>
implements: IComparable
implements: Collections.IStructuralComparable
val p2 : Point

type: Point
implements: IEquatable<Point>
implements: Collections.IStructuralEquatable
implements: IComparable<Point>
implements: IComparable
implements: Collections.IStructuralComparable
type Math =
class
static val PI : float
static val E : float
static member Abs : System.SByte -> System.SByte
static member Abs : int16 -> int16
static member Abs : int -> int
static member Abs : int64 -> int64
static member Abs : float32 -> float32
static member Abs : float -> float
static member Abs : decimal -> decimal
static member Acos : float -> float
static member Asin : float -> float
static member Atan : float -> float
static member Atan2 : float * float -> float
static member BigMul : int * int -> int64
static member Ceiling : decimal -> decimal
static member Ceiling : float -> float
static member Cos : float -> float
static member Cosh : float -> float
static member DivRem : int * int * int -> int
static member DivRem : int64 * int64 * int64 -> int64
static member Exp : float -> float
static member Floor : decimal -> decimal
static member Floor : float -> float
static member IEEERemainder : float * float -> float
static member Log : float -> float
static member Log : float * float -> float
static member Log10 : float -> float
static member Max : System.SByte * System.SByte -> System.SByte
static member Max : System.Byte * System.Byte -> System.Byte
static member Max : int16 * int16 -> int16
static member Max : uint16 * uint16 -> uint16
static member Max : int * int -> int
static member Max : uint32 * uint32 -> uint32
static member Max : int64 * int64 -> int64
static member Max : uint64 * uint64 -> uint64
static member Max : float32 * float32 -> float32
static member Max : float * float -> float
static member Max : decimal * decimal -> decimal
static member Min : System.SByte * System.SByte -> System.SByte
static member Min : System.Byte * System.Byte -> System.Byte
static member Min : int16 * int16 -> int16
static member Min : uint16 * uint16 -> uint16
static member Min : int * int -> int
static member Min : uint32 * uint32 -> uint32
static member Min : int64 * int64 -> int64
static member Min : uint64 * uint64 -> uint64
static member Min : float32 * float32 -> float32
static member Min : float * float -> float
static member Min : decimal * decimal -> decimal
static member Pow : float * float -> float
static member Round : float -> float
static member Round : decimal -> decimal
static member Round : float * int -> float
static member Round : float * System.MidpointRounding -> float
static member Round : decimal * int -> decimal
static member Round : decimal * System.MidpointRounding -> decimal
static member Round : float * int * System.MidpointRounding -> float
static member Round : decimal * int * System.MidpointRounding -> decimal
static member Sign : System.SByte -> int
static member Sign : int16 -> int
static member Sign : int -> int
static member Sign : int64 -> int
static member Sign : float32 -> int
static member Sign : float -> int
static member Sign : decimal -> int
static member Sin : float -> float
static member Sinh : float -> float
static member Sqrt : float -> float
static member Tan : float -> float
static member Tanh : float -> float
static member Truncate : decimal -> decimal
static member Truncate : float -> float
end

Full name: System.Math
Math.Abs(value: decimal) : decimal
Math.Abs(value: float) : float
Math.Abs(value: float32) : float32
Math.Abs(value: int64) : int64
Math.Abs(value: int) : int
Math.Abs(value: int16) : int16
Math.Abs(value: sbyte) : sbyte
val slope : double

type: double
implements: IComparable
implements: IFormattable
implements: IConvertible
implements: IComparable<float>
implements: IEquatable<float>
inherits: ValueType
val intercept : double

type: double
implements: IComparable
implements: IFormattable
implements: IConvertible
implements: IComparable<float>
implements: IEquatable<float>
inherits: ValueType
Math.Sqrt(d: float) : float
Math.Pow(x: float, y: float) : float
val Reduce : float -> Point [] -> Point []

Full name: DouglasPeuker.Reduce.Reduce
val epsilon : float

type: float
implements: IComparable
implements: IFormattable
implements: IConvertible
implements: IComparable<float>
implements: IEquatable<float>
inherits: ValueType
val points : Point []

type: Point []
implements: ICloneable
implements: Collections.IList
implements: Collections.ICollection
implements: Collections.IStructuralComparable
implements: Collections.IStructuralEquatable
implements: Collections.Generic.IList<Point>
implements: Collections.Generic.ICollection<Point>
implements: seq<Point>
implements: Collections.IEnumerable
inherits: Array
property Array.Length: int
val firstPoint : Point

type: Point
implements: IEquatable<Point>
implements: Collections.IStructuralEquatable
implements: IComparable<Point>
implements: IComparable
implements: Collections.IStructuralComparable
val lastPoint : Point

type: Point
implements: IEquatable<Point>
implements: Collections.IStructuralEquatable
implements: IComparable<Point>
implements: IComparable
implements: Collections.IStructuralComparable
val mutable index : int

type: int
implements: IComparable
implements: IFormattable
implements: IConvertible
implements: IComparable<int>
implements: IEquatable<int>
inherits: ValueType
val mutable dist : float

type: float
implements: IComparable
implements: IFormattable
implements: IConvertible
implements: IComparable<float>
implements: IEquatable<float>
inherits: ValueType
val i : int32

type: int32
implements: IComparable
implements: IFormattable
implements: IConvertible
implements: IComparable<int>
implements: IEquatable<int>
inherits: ValueType
val cDist : float

type: float
implements: IComparable
implements: IFormattable
implements: IConvertible
implements: IComparable<float>
implements: IEquatable<float>
inherits: ValueType
val l1 : Point []

type: Point []
implements: ICloneable
implements: Collections.IList
implements: Collections.ICollection
implements: Collections.IStructuralComparable
implements: Collections.IStructuralEquatable
implements: Collections.Generic.IList<Point>
implements: Collections.Generic.ICollection<Point>
implements: seq<Point>
implements: Collections.IEnumerable
inherits: Array
val l2 : Point []

type: Point []
implements: ICloneable
implements: Collections.IList
implements: Collections.ICollection
implements: Collections.IStructuralComparable
implements: Collections.IStructuralEquatable
implements: Collections.Generic.IList<Point>
implements: Collections.Generic.ICollection<Point>
implements: seq<Point>
implements: Collections.IEnumerable
inherits: Array
val r1 : Point []

type: Point []
implements: ICloneable
implements: Collections.IList
implements: Collections.ICollection
implements: Collections.IStructuralComparable
implements: Collections.IStructuralEquatable
implements: Collections.Generic.IList<Point>
implements: Collections.Generic.ICollection<Point>
implements: seq<Point>
implements: Collections.IEnumerable
inherits: Array
val r2 : Point []

type: Point []
implements: ICloneable
implements: Collections.IList
implements: Collections.ICollection
implements: Collections.IStructuralComparable
implements: Collections.IStructuralEquatable
implements: Collections.Generic.IList<Point>
implements: Collections.Generic.ICollection<Point>
implements: seq<Point>
implements: Collections.IEnumerable
inherits: Array
type Array =
class
member Clone : unit -> obj
member CopyTo : System.Array * int -> unit
member CopyTo : System.Array * int64 -> unit
member GetEnumerator : unit -> System.Collections.IEnumerator
member GetLength : int -> int
member GetLongLength : int -> int64
member GetLowerBound : int -> int
member GetUpperBound : int -> int
member GetValue : int [] -> obj
member GetValue : int -> obj
member GetValue : int64 -> obj
member GetValue : int64 [] -> obj
member GetValue : int * int -> obj
member GetValue : int64 * int64 -> obj
member GetValue : int * int * int -> obj
member GetValue : int64 * int64 * int64 -> obj
member Initialize : unit -> unit
member IsFixedSize : bool
member IsSynchronized : bool
member Length : int
member LongLength : int64
member Rank : int
member SetValue : obj * int -> unit
member SetValue : obj * int [] -> unit
member SetValue : obj * int64 -> unit
member SetValue : obj * int64 [] -> unit
member SetValue : obj * int * int -> unit
member SetValue : obj * int64 * int64 -> unit
member SetValue : obj * int * int * int -> unit
member SetValue : obj * int64 * int64 * int64 -> unit
member SyncRoot : obj
static member BinarySearch : System.Array * obj -> int
static member BinarySearch<'T> : 'T [] * 'T -> int
static member BinarySearch : System.Array * obj * System.Collections.IComparer -> int
static member BinarySearch<'T> : 'T [] * 'T * System.Collections.Generic.IComparer<'T> -> int
static member BinarySearch : System.Array * int * int * obj -> int
static member BinarySearch<'T> : 'T [] * int * int * 'T -> int
static member BinarySearch : System.Array * int * int * obj * System.Collections.IComparer -> int
static member BinarySearch<'T> : 'T [] * int * int * 'T * System.Collections.Generic.IComparer<'T> -> int
static member Clear : System.Array * int * int -> unit
static member ConstrainedCopy : System.Array * int * System.Array * int * int -> unit
static member ConvertAll<'TInput,'TOutput> : 'TInput [] * System.Converter<'TInput,'TOutput> -> 'TOutput []
static member Copy : System.Array * System.Array * int -> unit
static member Copy : System.Array * System.Array * int64 -> unit
static member Copy : System.Array * int * System.Array * int * int -> unit
static member Copy : System.Array * int64 * System.Array * int64 * int64 -> unit
static member CreateInstance : System.Type * int -> System.Array
static member CreateInstance : System.Type * int [] -> System.Array
static member CreateInstance : System.Type * int64 [] -> System.Array
static member CreateInstance : System.Type * int * int -> System.Array
static member CreateInstance : System.Type * int [] * int [] -> System.Array
static member CreateInstance : System.Type * int * int * int -> System.Array
static member Exists<'T> : 'T [] * System.Predicate<'T> -> bool
static member Find<'T> : 'T [] * System.Predicate<'T> -> 'T
static member FindAll<'T> : 'T [] * System.Predicate<'T> -> 'T []
static member FindIndex<'T> : 'T [] * System.Predicate<'T> -> int
static member FindIndex<'T> : 'T [] * int * System.Predicate<'T> -> int
static member FindIndex<'T> : 'T [] * int * int * System.Predicate<'T> -> int
static member FindLast<'T> : 'T [] * System.Predicate<'T> -> 'T
static member FindLastIndex<'T> : 'T [] * System.Predicate<'T> -> int
static member FindLastIndex<'T> : 'T [] * int * System.Predicate<'T> -> int
static member FindLastIndex<'T> : 'T [] * int * int * System.Predicate<'T> -> int
static member ForEach<'T> : 'T [] * System.Action<'T> -> unit
static member IndexOf : System.Array * obj -> int
static member IndexOf<'T> : 'T [] * 'T -> int
static member IndexOf : System.Array * obj * int -> int
static member IndexOf<'T> : 'T [] * 'T * int -> int
static member IndexOf : System.Array * obj * int * int -> int
static member IndexOf<'T> : 'T [] * 'T * int * int -> int
static member LastIndexOf : System.Array * obj -> int
static member LastIndexOf<'T> : 'T [] * 'T -> int
static member LastIndexOf : System.Array * obj * int -> int
static member LastIndexOf<'T> : 'T [] * 'T * int -> int
static member LastIndexOf : System.Array * obj * int * int -> int
static member LastIndexOf<'T> : 'T [] * 'T * int * int -> int
static member Resize<'T> : 'T [] * int -> unit
static member Reverse : System.Array -> unit
static member Reverse : System.Array * int * int -> unit
static member Sort : System.Array -> unit
static member Sort<'T> : 'T [] -> unit
static member Sort : System.Array * System.Array -> unit
static member Sort : System.Array * System.Collections.IComparer -> unit
static member Sort<'TKey,'TValue> : 'TKey [] * 'TValue [] -> unit
static member Sort<'T> : 'T [] * System.Collections.Generic.IComparer<'T> -> unit
static member Sort<'T> : 'T [] * System.Comparison<'T> -> unit
static member Sort : System.Array * int * int -> unit
static member Sort : System.Array * System.Array * System.Collections.IComparer -> unit
static member Sort<'T> : 'T [] * int * int -> unit
static member Sort<'TKey,'TValue> : 'TKey [] * 'TValue [] * System.Collections.Generic.IComparer<'TKey> -> unit
static member Sort : System.Array * System.Array * int * int -> unit
static member Sort : System.Array * int * int * System.Collections.IComparer -> unit
static member Sort<'TKey,'TValue> : 'TKey [] * 'TValue [] * int * int -> unit
static member Sort<'T> : 'T [] * int * int * System.Collections.Generic.IComparer<'T> -> unit
static member Sort : System.Array * System.Array * int * int * System.Collections.IComparer -> unit
static member Sort<'TKey,'TValue> : 'TKey [] * 'TValue [] * int * int * System.Collections.Generic.IComparer<'TKey> -> unit
static member TrueForAll<'T> : 'T [] * System.Predicate<'T> -> bool
end

Full name: System.Array

type: Array
implements: ICloneable
implements: Collections.IList
implements: Collections.ICollection
implements: Collections.IEnumerable
implements: Collections.IStructuralComparable
implements: Collections.IStructuralEquatable
val append : 'T [] -> 'T [] -> 'T []

Full name: Microsoft.FSharp.Collections.Array.append
module Tests

from DouglasPeuker
namespace FsUnit
namespace NUnit
namespace NUnit.Framework
module Reduce

from DouglasPeuker
type TestFixtureAttribute =
class
inherit System.Attribute
new : unit -> NUnit.Framework.TestFixtureAttribute
new : obj [] -> NUnit.Framework.TestFixtureAttribute
member Arguments : obj []
member Categories : System.Collections.IList
member Category : string with get, set
member Description : string with get, set
member Ignore : bool with get, set
member IgnoreReason : string with get, set
member TypeArgs : System.Type [] with get, set
end

Full name: NUnit.Framework.TestFixtureAttribute

type: TestFixtureAttribute
implements: Runtime.InteropServices._Attribute
inherits: Attribute
val StrToPoints : (string -> Point [])
val s : string

type: string
implements: IComparable
implements: ICloneable
implements: IConvertible
implements: IComparable<string>
implements: seq<char>
implements: Collections.IEnumerable
implements: IEquatable<string>
Multiple items
val string : 'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string

type: string
implements: IComparable
implements: ICloneable
implements: IConvertible
implements: IComparable<string>
implements: seq<char>
implements: Collections.IEnumerable
implements: IEquatable<string>
String.Split(separator: char []) : string []
String.Split(separator: string [], options: StringSplitOptions) : string []
String.Split(separator: char [], options: StringSplitOptions) : string []
String.Split(separator: char [], count: int) : string []
String.Split(separator: string [], count: int, options: StringSplitOptions) : string []
String.Split(separator: char [], count: int, options: StringSplitOptions) : string []
val map : ('T -> 'U) -> 'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.map
val p : string

type: string
implements: IComparable
implements: ICloneable
implements: IConvertible
implements: IComparable<string>
implements: seq<char>
implements: Collections.IEnumerable
implements: IEquatable<string>
val xy : string []

type: string []
implements: ICloneable
implements: Collections.IList
implements: Collections.ICollection
implements: Collections.IStructuralComparable
implements: Collections.IStructuralEquatable
implements: Collections.Generic.IList<string>
implements: Collections.Generic.ICollection<string>
implements: seq<string>
implements: Collections.IEnumerable
inherits: Array
type Double =
struct
member CompareTo : obj -> int
member CompareTo : float -> int
member Equals : obj -> bool
member Equals : float -> bool
member GetHashCode : unit -> int
member GetTypeCode : unit -> System.TypeCode
member ToString : unit -> string
member ToString : string -> string
member ToString : System.IFormatProvider -> string
member ToString : string * System.IFormatProvider -> string
static val MinValue : float
static val MaxValue : float
static val Epsilon : float
static val NegativeInfinity : float
static val PositiveInfinity : float
static val NaN : float
static member IsInfinity : float -> bool
static member IsNaN : float -> bool
static member IsNegativeInfinity : float -> bool
static member IsPositiveInfinity : float -> bool
static member Parse : string -> float
static member Parse : string * System.Globalization.NumberStyles -> float
static member Parse : string * System.IFormatProvider -> float
static member Parse : string * System.Globalization.NumberStyles * System.IFormatProvider -> float
static member TryParse : string * float -> bool
static member TryParse : string * System.Globalization.NumberStyles * System.IFormatProvider * float -> bool
end

Full name: System.Double

type: Double
implements: IComparable
implements: IFormattable
implements: IConvertible
implements: IComparable<float>
implements: IEquatable<float>
inherits: ValueType
Double.Parse(s: string) : float
Double.Parse(s: string, provider: IFormatProvider) : float
Double.Parse(s: string, style: Globalization.NumberStyles) : float
Double.Parse(s: string, style: Globalization.NumberStyles, provider: IFormatProvider) : float
type TestCaseAttribute =
class
inherit System.Attribute
new : obj [] -> NUnit.Framework.TestCaseAttribute
new : obj -> NUnit.Framework.TestCaseAttribute
new : obj * obj -> NUnit.Framework.TestCaseAttribute
new : obj * obj * obj -> NUnit.Framework.TestCaseAttribute
member Arguments : obj []
member Categories : System.Collections.IList
member Category : string with get, set
member Description : string with get, set
member ExpectedException : System.Type with get, set
member ExpectedExceptionName : string with get, set
member ExpectedMessage : string with get, set
member ExpectedResult : obj with get, set
member Explicit : bool with get, set
member HasExpectedResult : bool
member Ignore : bool with get, set
member IgnoreReason : string with get, set
member Ignored : bool with get, set
member MatchType : NUnit.Framework.MessageMatch with get, set
member Reason : string with get, set
member Result : obj with get, set
member TestName : string with get, set
end

Full name: NUnit.Framework.TestCaseAttribute

type: TestCaseAttribute
implements: Runtime.InteropServices._Attribute
implements: ITestCaseData
inherits: Attribute
val this : Given the DouglasPeuker Simplify function
val items : string

type: string
implements: IComparable
implements: ICloneable
implements: IConvertible
implements: IComparable<string>
implements: seq<char>
implements: Collections.IEnumerable
implements: IEquatable<string>
val expected : string

type: string
implements: IComparable
implements: ICloneable
implements: IConvertible
implements: IComparable<string>
implements: seq<char>
implements: Collections.IEnumerable
implements: IEquatable<string>
val actual : Point []

type: Point []
implements: ICloneable
implements: Collections.IList
implements: Collections.ICollection
implements: Collections.IStructuralComparable
implements: Collections.IStructuralEquatable
implements: Collections.Generic.IList<Point>
implements: Collections.Generic.ICollection<Point>
implements: seq<Point>
implements: Collections.IEnumerable
inherits: Array
Multiple items
val Reduce : float -> Point [] -> Point []

Full name: DouglasPeuker.Reduce.Reduce

--------------------
module Reduce

from DouglasPeuker
val expected : Point []

type: Point []
implements: ICloneable
implements: Collections.IList
implements: Collections.ICollection
implements: Collections.IStructuralComparable
implements: Collections.IStructuralEquatable
implements: Collections.Generic.IList<Point>
implements: Collections.Generic.ICollection<Point>
implements: seq<Point>
implements: Collections.IEnumerable
inherits: Array
val should : ('a -> #Constraints.Constraint) -> 'a -> obj -> unit

Full name: FsUnit.TopLevelOperators.should
val equal : 'a -> Constraints.EqualConstraint

Full name: FsUnit.TopLevelOperators.equal