F# and ArcObjects, Part 3

Using F# sequences, pipelines, and Seq.fold with ArcObjects to iterate over features and calculate the combined bounding box of an ArcGIS feature class.

Today i played a little bit with IFeature-sequences and piping data. The result was a calculator of the bounding box around all features in a feature class.

Maybe a little bit dirty, but for learning was it OK. ;-)

open System;;

#I "C:\Program Files\ArcGIS\DotNet";;
#r "ESRI.ArcGIS.System.dll";;
#r "ESRI.ArcGIS.DataSourcesGDB.dll";;
#r "ESRI.ArcGIS.Geodatabase.dll";;
#r "ESRI.ArcGIS.Geometry.dll";;

open ESRI.ArcGIS.esriSystem;;
open ESRI.ArcGIS.DataSourcesGDB;;
open ESRI.ArcGIS.Geodatabase;;
open ESRI.ArcGIS.Geometry;

let aoInitialize = new AoInitializeClass();;

let status = aoInitialize.Initialize(esriLicenseProductCode.esriLicenseProductCodeArcEditor);;

let workspacefactory = new SdeWorkspaceFactoryClass();;

let connection = "SERVER=okul;DATABASE=p*;VERSION=sde.default;INSTANCE=sde:sqlserver:okul;USER=s*;PASSWORD=g*";;

let workspace = workspacefactory.OpenFromString(connection, 0);;

let featureWorkspace = (box workspace) :?> IFeatureWorkspace;;

let featureCursorSeq (featureCursor : IFeatureCursor) = 
  let actualFeature = ref (featureCursor.NextFeature())
  seq {
    while (!actualFeature) <> null do
      yield actualFeature
      do actualFeature := featureCursor.NextFeature()
   };;

let min x y =
    if x < y then
        x
    else
        y;;

let max x y =
    if x > y then
        x
    else
        y;;

let info s (x : IEnvelope) =
    match x with
    | null -> printfn "%s is null" s
    | _ ->
        printfn "%s xMin:{%f} xMax: {%f} yMin:{%f} yMax: {%f}" s x.XMin x.XMax x.YMin x.YMax;;

let con (env1 : IEnvelope) (env2 : IEnvelope) =
    match env1 with
    | null -> env2
    | _ ->
        let env = (new EnvelopeClass()) :> IEnvelope
        env.XMin <- min env1.XMin env2.XMin
        env.XMax <- max env1.XMax env2.XMax
        env.YMin <- min env1.YMin env2.YMin
        env.YMax <- max env1.YMax env2.YMax
        info "Intermediate" env
        env
;;

let BoundingBox featureClassName = 
    let featureClass = featureWorkspace.OpenFeatureClass(featureClassName)
    let queryFilter = new QueryFilterClass()
    let featureCursor = featureClass.Search(queryFilter, true)
    let featureCursorSeq (featureCursor : IFeatureCursor) = 
      let actualFeature = ref (featureCursor.NextFeature())
      seq {
        while (!actualFeature) <> null do
          yield actualFeature
          do actualFeature := featureCursor.NextFeature()
       }

    featureCursorSeq featureCursor
    |> Seq.map (fun feature -> (!feature).Extent)
    |> Seq.fold (fun (acc : IEnvelope) a ->
        info "Intermediate" acc
        (con acc a)) null
;;

let boundingBox = BoundingBox "Praxair.SFG.BP_L_ROHR";;

info "Ende-Info:" boundingBox;;