Fsharp.Gdal


Gdal type provider

This is a starting point in developing a type provider for geospatial data files managed with the gdal library

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
open FSharp.Gdal

open OSGeo
open OSGeo.GDAL
open OSGeo.OGR

open Deedle
open FSharp.Data
open FSharp.Charting

The shape file itinerari.shp contains the foot paths to the main peaks in the Val Grande National Park.

To get the data from a file we can just call the type provider constructor giving the file path as the type parameter of the provider. Internally the provider calls the logic needed to configure the gdal library on the system and to initialize all the gdal data providers:

1: 
let vLayer = new OgrTypeProvider<"G:/Data/itinerari.shp">()

The type provider provides two properties:

Values which we can convert directly to a deedle frame to explore immediately the data in the vector:

1: 
let fmData = vLayer.Values |> Frame.ofValues

ID

CODE

SUBCODE

...

DESCEND

DISLIVELLO

Geometry

0

1

1

...

285

1180

OSGeo.OGR.Geometry

1

4

4

...

728

1556

OSGeo.OGR.Geometry

2

2

2

b

...

1717

0

OSGeo.OGR.Geometry

3

3

3

...

526

619

OSGeo.OGR.Geometry

4

5

5

...

319

1376

OSGeo.OGR.Geometry

5

6

6

...

480

1543

OSGeo.OGR.Geometry

6

12

12

...

836

847

OSGeo.OGR.Geometry

7

7

7

...

441

1796

OSGeo.OGR.Geometry

...

...

...

...

...

...

...

...

14

15

15

...

311

1093

OSGeo.OGR.Geometry

15

16

16

b

...

639

1482

OSGeo.OGR.Geometry

16

17

17

a

...

610

1157

OSGeo.OGR.Geometry

17

17

17

b

...

1010

1331

OSGeo.OGR.Geometry

and Features which we can iterate to get, for each feature, attributes and geometry converted in dinamically created types that match the type of geometry and attributes and come up directly with the intellisense in the iteractive editor:

1: 
2: 
3: 
for feat in vLayer.Features do
    printfn "Geomtry type = %A\tID = %i\tTITLE = %s\t" 
        (feat.Geometry.GetGeometryType()) feat.ID feat.TITLE
Geomtry type = wkbLineString	ID = 1	TITLE = Cima Sasso	
Geomtry type = wkbLineString	ID = 4	TITLE = Pizzo Proman	
Geomtry type = wkbLineString	ID = 2	TITLE = Monte Faie	
Geomtry type = wkbLineString	ID = 3	TITLE = Cima Corte Lorenzo	
Geomtry type = wkbLineString	ID = 5	TITLE = Cima Saler	
Geomtry type = wkbLineString	ID = 6	TITLE = Pizzo delle Pecore	
Geomtry type = wkbLineString	ID = 12	TITLE = Cima Pedum	
Geomtry type = wkbLineString	ID = 7	TITLE = Punta Pozzolo	
Geomtry type = wkbLineString	ID = 8	TITLE = Pizzo Tignolino	
Geomtry type = wkbLineString	ID = 9	TITLE = Monte Togano	
Geomtry type = wkbLineString	ID = 10	TITLE = Pizzo Nona	
Geomtry type = wkbLineString	ID = 11	TITLE = Cima della Laurasca	
Geomtry type = wkbLineString	ID = 13	TITLE = Cimone di Cortechiuso	
Geomtry type = wkbLineString	ID = 14	TITLE = Monte Torrione	
Geomtry type = wkbLineString	ID = 15	TITLE = La Piota	
Geomtry type = wkbLineString	ID = 16	TITLE = Monte Zeda da Falmenta	
Geomtry type = wkbLineString	ID = 17	TITLE = Pizzo Marona dall'Alpe Pala	
Geomtry type = wkbLineString	ID = 17	TITLE = Pizzo Marona da Cicogna

We can also graphically visualize the features geometries using the plot function which is described in the Plot Geometries appendix:

1: 
2: 
3: 
4: 
5: 
6: 
7: 
let footPaths = new OGR.Geometry(OGR.wkbGeometryType.wkbMultiLineString)

for feat in vLayer.Features do
    let _ = footPaths.AddGeometry(feat.Geometry)
    ()

footPaths |> plot

With the deedle frame and gdal methods at hand we can do some calculations based on geometries. The data file contains hiking paths in the Big Valley and we can for example get the lenght of each with the gdal library methods and use the deedle functions to aggregate them.

1: 
2: 
3: 
4: 
5: 
6: 
let fmLengths = 
    vLayer.Features
    |> Seq.mapi (fun i feat -> i, "Length", feat.Geometry.Length())
    |> Frame.ofValues

let fmWithLengths = fmData.Join(fmLengths)

ID

CODE

SUBCODE

...

DISLIVELLO

Geometry

Length

0

1

1

...

1180

OSGeo.OGR.Geometry

5417

1

4

4

...

1556

OSGeo.OGR.Geometry

9408

2

2

2

b

...

0

OSGeo.OGR.Geometry

1,087E+04

3

3

3

...

619

OSGeo.OGR.Geometry

4960

4

5

5

...

1376

OSGeo.OGR.Geometry

5198

5

6

6

...

1543

OSGeo.OGR.Geometry

7861

6

12

12

...

847

OSGeo.OGR.Geometry

8060

7

7

7

...

1796

OSGeo.OGR.Geometry

7393

...

...

...

...

...

...

...

...

14

15

15

...

1093

OSGeo.OGR.Geometry

6286

15

16

16

b

...

1482

OSGeo.OGR.Geometry

9070

16

17

17

a

...

1157

OSGeo.OGR.Geometry

8288

17

17

17

b

...

1331

OSGeo.OGR.Geometry

9117

And just to do an aggregation:

1: 
2: 
3: 
let sumLenghts = fmWithLengths.Sum()?Length

printf "sumLenghts = %f" sumLenghts
sumLenghts = 138959.383896
Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
namespace FSharp.Gdal
namespace OSGeo
namespace OSGeo.GDAL
namespace OSGeo.OGR
namespace Deedle
Multiple items
namespace FSharp.Data

--------------------
namespace Microsoft.FSharp.Data
namespace FSharp.Charting
val vLayer : OgrTypeProvider<...>

Full name: Gdal-type-provider.vLayer
type OgrTypeProvider

Full name: FSharp.Gdal.OgrTypeProvider
val fmData : Frame<int,string>

Full name: Gdal-type-provider.fmData
property OgrTypeProvider<...>.Values: List<int * string * obj>
Multiple items
module Frame

from Deedle

--------------------
type Frame =
  static member ReadReader : reader:IDataReader -> Frame<int,string>
  static member CustomExpanders : Dictionary<Type,Func<obj,seq<string * Type * obj>>>
  static member NonExpandableInterfaces : List<Type>
  static member NonExpandableTypes : HashSet<Type>

Full name: Deedle.Frame

--------------------
type Frame<'TRowKey,'TColumnKey (requires equality and equality)> =
  interface IDynamicMetaObjectProvider
  interface INotifyCollectionChanged
  interface IFsiFormattable
  interface IFrame
  new : names:seq<'TColumnKey> * columns:seq<ISeries<'TRowKey>> -> Frame<'TRowKey,'TColumnKey>
  new : rowIndex:IIndex<'TRowKey> * columnIndex:IIndex<'TColumnKey> * data:IVector<IVector> * indexBuilder:IIndexBuilder * vectorBuilder:IVectorBuilder -> Frame<'TRowKey,'TColumnKey>
  member AddColumn : column:'TColumnKey * series:ISeries<'TRowKey> -> unit
  member AddColumn : column:'TColumnKey * series:seq<'V> -> unit
  member AddColumn : column:'TColumnKey * series:ISeries<'TRowKey> * lookup:Lookup -> unit
  member AddColumn : column:'TColumnKey * series:seq<'V> * lookup:Lookup -> unit
  ...

Full name: Deedle.Frame<_,_>

--------------------
new : names:seq<'TColumnKey> * columns:seq<ISeries<'TRowKey>> -> Frame<'TRowKey,'TColumnKey>
new : rowIndex:Indices.IIndex<'TRowKey> * columnIndex:Indices.IIndex<'TColumnKey> * data:IVector<IVector> * indexBuilder:Indices.IIndexBuilder * vectorBuilder:Vectors.IVectorBuilder -> Frame<'TRowKey,'TColumnKey>
static member Frame.ofValues : values:seq<'R * 'C * 'V> -> Frame<'R,'C> (requires equality and equality)
val feat : OgrTypeProvider<...>.Feature
property OgrTypeProvider<...>.Features: System.Collections.Generic.IEnumerable<OgrTypeProvider<...>.Feature>
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
property OgrTypeProvider<...>.Feature.Geometry: Geometry
Geometry.GetGeometryType() : wkbGeometryType
property OgrTypeProvider<...>.Feature.ID: int
property OgrTypeProvider<...>.Feature.TITLE: string
val footPaths : Geometry

Full name: Gdal-type-provider.footPaths
Multiple items
type Geometry =
  new : type:wkbGeometryType -> Geometry + 2 overloads
  member AddGeometry : other:Geometry -> int
  member AddGeometryDirectly : other_disown:Geometry -> int
  member AddPoint : x:float * y:float * z:float -> unit
  member AddPoint_2D : x:float * y:float -> unit
  member Area : unit -> float
  member AssignSpatialReference : reference:SpatialReference -> unit
  member Boundary : unit -> Geometry
  member Buffer : distance:float * quadsecs:int -> Geometry
  member Centroid : unit -> Geometry
  ...

Full name: OSGeo.OGR.Geometry

--------------------
Geometry(type: wkbGeometryType) : unit
Geometry(cPtr: nativeint, cMemoryOwn: bool, parent: obj) : unit
Geometry(type: wkbGeometryType, wkt: string, wkb: int, wkb_buf: nativeint, gml: string) : unit
type wkbGeometryType =
  | wkbUnknown = 0
  | wkbPoint = 1
  | wkbLineString = 2
  | wkbPolygon = 3
  | wkbMultiPoint = 4
  | wkbMultiLineString = 5
  | wkbMultiPolygon = 6
  | wkbGeometryCollection = 7
  | wkbNone = 100
  | wkbLinearRing = 101
  ...

Full name: OSGeo.OGR.wkbGeometryType
field wkbGeometryType.wkbMultiLineString = 5
Geometry.AddGeometry(other: Geometry) : int
val plot : g:Geometry -> ChartTypes.GenericChart

Full name: Plot-geometries.plot


 Plots a geometry at a zoom of 80%
val fmLengths : Frame<int,string>

Full name: Gdal-type-provider.fmLengths
module Seq

from Microsoft.FSharp.Collections
val mapi : mapping:(int -> 'T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.mapi
val i : int
Geometry.Length() : float
val fmWithLengths : Frame<int,string>

Full name: Gdal-type-provider.fmWithLengths
member Frame.Join : otherFrame:Frame<'TRowKey,'TColumnKey> -> Frame<'TRowKey,'TColumnKey>
member Frame.Join : colKey:'TColumnKey * series:Series<'TRowKey,'V> -> Frame<'TRowKey,'TColumnKey>
member Frame.Join : otherFrame:Frame<'TRowKey,'TColumnKey> * kind:JoinKind -> Frame<'TRowKey,'TColumnKey>
member Frame.Join : colKey:'TColumnKey * series:Series<'TRowKey,'V> * kind:JoinKind -> Frame<'TRowKey,'TColumnKey>
member Frame.Join : otherFrame:Frame<'TRowKey,'TColumnKey> * kind:JoinKind * lookup:Lookup -> Frame<'TRowKey,'TColumnKey>
member Frame.Join : colKey:'TColumnKey * series:Series<'TRowKey,'V> * kind:JoinKind * lookup:Lookup -> Frame<'TRowKey,'TColumnKey>
val sumLenghts : float

Full name: Gdal-type-provider.sumLenghts
static member FrameExtensions.Sum : frame:Frame<'R,'C> -> Series<'C,float> (requires equality and equality)
val printf : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printf
namespace Fsharp.Gdal
F# Project
Fork me on GitHub