Through the Interface: Getting the total volume of 3D solids in an AutoCAD model using F#

May 2015

Sun Mon Tue Wed Thu Fri Sat
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30


« More fun with F# and AutoCAD: string extraction and manipulation | Main | Metaprogramming with AutoCAD - Part 1 »

November 16, 2007

Getting the total volume of 3D solids in an AutoCAD model using F#

In one of my sessions at this year's AU, "There's More to .DWG Than AutoCAD®", I'll be showing some VB.NET code that goes through and collects information about solids, presenting it in a dialog along with the sum of the various volumes. You can get the code and the results from Part 1 of the session's handout.

Just for fun, I thought I'd write some F# code to add the volumes of the 3D solid objects in the modelspace of the current drawing. I adopt a similar approach to the VB code - not caring about intersecting volumes, for instance - but obviously the code looks quite different.

I won't step through the code line-by-line, as the last post introduced the fundamental concepts that also apply here.

// Use lightweight F# syntax


(* Declare a specific namespace

  and module name


module MyNamespace.MyApplication

// Import managed assemblies

#I @"C:\Program Files\Autodesk\AutoCAD 2008"

#r "acdbmgd.dll"

#r "acmgd.dll"

open System

open System.Collections.Generic

open Autodesk.AutoCAD.Runtime

open Autodesk.AutoCAD.ApplicationServices

open Autodesk.AutoCAD.DatabaseServices

// Now we declare our command


let listWords () =

  // Let's get the usual helpful AutoCAD objects

  let doc =


  let ed = doc.Editor;

  let db = doc.Database;

  // "use" has the same effect as "using" in C#

  use tr =


  // Get appropriately-typed BlockTable and BTRs

  let bt =



    :?> BlockTable

  let ms =




    :?> BlockTableRecord

  // A function that accepts an ObjectId and returns

  // the volume of a 3D solid, if it happens to be one

  // Note the valid use of tr, as it is in scope

  let getVolume (x : ObjectId) =

    let obj = tr.GetObject(x,OpenMode.ForRead);

    match obj with

    | :? Solid3d -> (obj :?> Solid3d).MassProperties.Volume

    | _ -> 0.0

  // Use fold_left in a partial application to find

  // the sum of the contents of a list

  let sum =

    List.fold_left (fun x y -> x+y) 0.0

  // And here's where we plug everything together...

  let vol =

    Seq.untyped_to_list ms |> getVolume |> sum

  ed.WriteMessage("\nTotal volume: " + vol.ToString());

  // As usual, committing is cheaper than aborting


The only tricky thing is the use of fold_left to apply an anonymous (or lambda, for the LISPers out there) addition function across the contents of the list containing the individual volumes of the objects in the modelspace.

Here's what we see when we run the "volume" command:

Command: volume

Total volume: 15275.8711619534

This is the same result as displayed by the previous example (although presented with a few more decimal places).


TrackBack URL for this entry:

Listed below are links to weblogs that reference Getting the total volume of 3D solids in an AutoCAD model using F#:

» Getting the total volume of 3D solids in an Autocad model using F# from
You've been kicked (a good thing) - Trackback from [Read More]

blog comments powered by Disqus


10 Random Posts