f# and path reduction

Post on 10-Feb-2016

27 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

F# and Path Reduction. Kit Eason - @ kitlovesfsharp – www.kiteason.com – kit.eason@gmail.com. Norway – way too complicated!. Way, way too complicated!. Ramer–Douglas– Peucker. A record type. type Point = {Long : double; Lat : double}. Distance from line. - PowerPoint PPT Presentation

TRANSCRIPT

F# and Path ReductionKit Eason - @kitlovesfsharp – www.kiteason.com – kit.eason@gmail.com

Norway – way too complicated!

Way, way too complicated!

Ramer–Douglas–Peucker

A record type

type Point = {Long: double; Lat : double}

Distance from line

let private findPerpendicularDistance p p1 p2 = if (p1.Long = p2.Long) then abs(p.Long - p1.Long) else let slope = (p2.Lat - p1.Lat) / (p2.Long - p1.Long) let intercept = p1.Lat - (slope * p1.Long) abs(slope * p.Long - p.Lat + intercept) / sqrt((pown slope 2) + 1.)

Recursive algorithm

let rec Reduce epsilon (points : Point[]) = if points.Length < 3 || epsilon = 0. then points else let firstPoint = points.[0] let lastPoint = points.[points.Length - 1]

let mutable index = -1 let mutable dist = 0.0

for i in 1..points.Length-1 do let cDist = findPerpendicularDistance points.[i] firstPoint lastPoint if (cDist > dist) then dist <- cDist index <- i if (dist > epsilon) then let l1 = points.[0..index] let l2 = points.[index..] let r1 = Reduce epsilon l1 let r2 = Reduce epsilon l2 Array.append (r1.[0..r1.Length-2]) r2 else [|firstPoint; lastPoint|]

let rec Reduce epsilon (points : Point[]) = if points.Length < 3 || epsilon = 0. then points else let firstPoint = points.[0] let lastPoint = points.[points.Length - 1]

let mutable index = -1 let mutable dist = 0.0

for i in 1..points.Length-1 do let cDist = findPerpendicularDistance points.[i] firstPoint lastPoint if (cDist > dist) then dist <- cDist index <- i if (dist > epsilon) then let l1 = points.[0..index] let l2 = points.[index..] let r1 = Reduce epsilon l1 let r2 = Reduce epsilon l2 Array.append (r1.[0..r1.Length-2]) r2 else [|firstPoint; lastPoint|]

The data

nan nan 8.299972 54.778750 8.300778 54.778278 8.300806 54.775778 8.302417 54.775000 8.302444 54.772472 8.300778 54.771611 8.300750 54.767444nan nan 8.277417 54.764111 8.277417 54.775750 8.279083 54.776611 8.279111 54.797444

Reading the data

let private ReadData fileName = fileName |> File.ReadAllLines |> Array.breakOn (fun line -> line = "nan nan") |> Array.Parallel.map ToPoints |> FilterCount 100

Breaking into arrays

let breakOn (f : 'a -> bool) (a : array<'a>) = [| let result = ResizeArray() for x in a do if f x then yield result |> Array.ofSeq result.Clear() else result.Add(x) yield result |> Array.ofSeq |]

Converting to points

let private ToPoints (lines : array<string>) = lines |> Array.Parallel.map (fun line -> line.Split [|'\t'|]) |> Array.Parallel.map (fun items -> items |> Array.map Double.Parse) |> Array.choose (fun doubles -> match doubles with | [|long; lat|] -> Some {Long=long; Lat=lat} | _ -> None)

Eliminating tiny islands (and lakes!)

let private FilterCount minCount groups = groups |> Array.filter (fun g -> Array.length g > minCount)

Calling the RDP algorithm

let Simplify e polyLines = polyLines |> Array.Parallel.map (fun p -> p |> Reduce.Reduce e)

ε = 0

ε = 0.001

ε = 0.01

ε = 0.1

ε = 1

Out-takes

Resources

www.github.com/misterspeedy/coastline www.fsharp.org www.fsharpforfunandprofit.com Chris Smith’s “Animal Guide”

top related