Exposing a RESTful web service for use inside AutoCAD using the ASP.NET Web API – Part 2

In the last post, we looked at the core technology we're going to use to expose our web-service, along with the basic project set-up. In today's post, we're going to flesh out this project and see the web-service in action.

At this point, I should point out that I've switched back across for VS2010 for the purposes of this post (and its immediate successors), as it really will simplify the eventual integration with Windows Azure.

Before we dive into the implementation of our web-service, here are a few words on what we're after…

We want to implement two web-service APIs:

  1. One that will provide the circles representing an Apollonian gasket (in 2D)
  2. One that will provide the spheres representing an Apollonian packing (in 3D)

Both of these services will take a radius (for the enclosing circle/sphere) and a "level" (i.e. the number of times we should recurse to create our fractal geometry).

They should be accessible via a simple URL – as we're talking REST rather than SOAP – for example, with a provisional domain name:

http://myapollonianservice.com/circles/5/3 should return the circles enclosed in an outer circle of radius 5, recursing through 3 levels.

http://myapollonianservice.com/spheres/10/4 should return the spheres enclosed in an outer sphere of radius 10, recursing through 4 levels.

The results should be returned as JSON containing the circle/sphere definitions. These will simply be records containing fields for the center (X, Y, [Z] and radius (or curvature, for circles), and also the "level" of each circle/sphere, so we can colorise appropriately).

Our Web API solution structureLet's take a look at the structure of our boilerplate solution…

There are two projects: a C# project called ApollonianPackingWebApi that acts as the main entry-point into our code, but is very shallow. It exists to call through into the F# project, ApollonianPackingWebAppApi, where our application logic is all defined.

It's the code in this latter project that we care about, particularly that contained in two files: Global.fs and ValuesControllers.fs file.

The standard Global.fs contains the below code which defines the way the REST API's URL structure translates into calls into the project's code:

namespace FsWeb

 

open System

open System.Web

open System.Web.Mvc

open System.Web.Routing

open System.Web.Http

open System.Data.Entity

 

type Route = { controller : string

               action : string

               id : UrlParameter }

 

type MapHttpRouteSettings = { id : obj }

 

type Global() =

  inherit System.Web.HttpApplication()

 

  static member RegisterGlobalFilters(filters:GlobalFilterCollection) =

    filters.Add(new HandleErrorAttribute())

 

  static member RegisterRoutes(routes:RouteCollection) =

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}")

 

    routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", {id = RouteParameter.Optional}) |> ignore

 

    routes.MapRoute("Default",

                    "{controller}/{action}/{id}",

                    { controller = "Home"; action = "Index"

                      id = UrlParameter.Optional } )

 

  member this.Start() =

    AreaRegistration.RegisterAllAreas()

 

    Global.RegisterGlobalFilters(GlobalFilters.Filters)

    Global.RegisterRoutes(RouteTable.Routes)

The actual "intelligence" of the app is contained in ValuesControllers.fs:

namespace FsWeb.Controllers

 

open System.Web

open System.Web.Mvc

open System.Net.Http

open System.Web.Http

 

type ValuesController() =

  inherit ApiController()

 

  // GET /api/values

  member x.Get() = [| "value1"; "value2" |] |> Array.toSeq

  // GET /api/values/5

  member x.Get (id:int) = "value"

  // POST /api/values

  member x.Post (value:string) = ()

  // PUT /api/values/5

  member x.Put (id:int) (value:string) = ()

  // DELETE /api/values/5

  member x.Delete (id:int) = ()

This should be familiar if you've spent time looking at the introductory blog post I pointed to, last time.

Now for the changes we want to make… Let's start with Globals.fs, which is being adjusted to have "rad" and "steps" parameters registered for our API controller(s).

namespace FsWeb

 

open System.Web.Mvc

open System.Web.Routing

open System.Web.Http

 

type Route =

  { controller : string

    action : string

    rad : UrlParameter

    steps : UrlParameter }

 

type MapHttpRouteSettings =

  { rad : obj

    steps : obj }

 

type Global() =

  inherit System.Web.HttpApplication()

 

  static member RegisterGlobalFilters(gfc:GlobalFilterCollection) =

    gfc.Add(new HandleErrorAttribute())

 

  static member RegisterRoutes(rc:RouteCollection) =

    rc.IgnoreRoute("{resource}.axd/{*pathInfo}")

 

    rc.MapHttpRoute(

      "DefaultApi",

      "api/{controller}/{rad}/{steps}",

      { rad = RouteParameter.Optional

        steps = RouteParameter.Optional }) |> ignore

 

    rc.MapRoute(

      "Default",

      "{controller}/{action}/{rad}/{steps}",

      { controller = "Home"

        action = "Index"

        rad = UrlParameter.Optional

        steps = UrlParameter.Optional } )

 

  member this.Start() =

    AreaRegistration.RegisterAllAreas()

 

    Global.RegisterGlobalFilters(GlobalFilters.Filters)

    Global.RegisterRoutes(RouteTable.Routes)

 

The ValuesController.fs file is actually being replaced with two files: CirclesController.fs and SpheresController.fs.

Here's CirclesController.cs, which simply calls into the CirclePackingFull.fs file copied directly from our previous project (where the code ran directly inside AutoCAD):

namespace FsWeb.Controllers

 

open System.Web.Http

 

type Circle (X, Y, Curvature, Level) =

  member this.x = X

  member this.y = Y

  member this.k = Curvature

  member this.l = Level

 

type CirclesController() =

  inherit ApiController()   

 

  // GET /api/values/rad/steps

  member x.Get(rad:double, steps:int) =

    CirclePackingFullFs.Packer.ApollonianGasket rad steps |>

      List.map (fun ((a,b,c),d) -> new Circle(a,b,c,d)) |>

      List.toSeq

 

And here's SpheresController.fs, which calls into the analogous SpherePackingInversion.fs file (the code from this post):

namespace FsWeb.Controllers

 

open System.Web.Http

 

type Sphere (X, Y, Z, Radius, Level) =

  member this.x = X

  member this.y = Y

  member this.z = Z

  member this.r = Radius

  member this.l = Level

 

type SpheresController() =

  inherit ApiController()   

 

  // GET /api/values/rad/steps

  member x.Get(rad:double, steps:int) =

    SpherePackingInversionFs.Packer.ApollonianGasket steps 0.01 false

      |>

      List.map

        (fun ((a,b,c,d),e) -> new Sphere(a*rad,b*rad,c*rad,d*rad,e))

        |>

        List.toSeq

Now it should just be a matter of building the app and starting Internet Explorer from the debugger, which shows the default web-page provided in the boilerplate project:

Our base web page

To test our APIs, we can extend the URL shown in the address bar to try them both:

http://localhost:64114/api/circles/5/3

and

http://localhost:64114/api/spheres/10/4

Here is the JSON data – returned as plain text from the API – for the first call:

[{"Curvature":0.43094010767585034,"Level":3,"X":5,"Y":7.6794919243112272},{"Curvature":0.43094010767585034,"Level":3,"X":7.3205080756887728,"Y":3.6602540378443873},{"Curvature":0.43094010767585034,"Level":3,"X":2.6794919243112272,"Y":3.6602540378443873},{"Curvature":2.7856406460551022,"Level":2,"X":4.9999999999999991,"Y":5},{"Curvature":6.8641016151377556,"Level":1,"X":5.4370564668483263,"Y":5.2523346687859487},{"Curvature":12.66632301492381,"Level":0,"X":5.6315960828232612,"Y":5.3646521684371233},{"Curvature":19.730424630061563,"Level":0,"X":5.4054651711758446,"Y":5.0585238564313482},{"Curvature":19.730424630061563,"Level":0,"X":5.2534157319849024,"Y":5.321881210372414},{"Curvature":6.8641016151377556,"Level":1,"X":4.9999999999999991,"Y":4.4953306624281035},{"Curvature":12.66632301492381,"Level":0,"X":4.9999999999999982,"Y":4.2706956631257533},{"Curvature":19.730424630061563,"Level":0,"X":4.8479505608090578,"Y":4.6195949331962387},{"Curvature":19.730424630061563,"Level":0,"X":5.15204943919094,"Y":4.6195949331962387},{"Curvature":6.8641016151377556,"Level":1,"X":4.5629435331516728,"Y":5.2523346687859487},{"Curvature":12.66632301492381,"Level":0,"X":4.3684039171767388,"Y":5.3646521684371242},{"Curvature":19.730424630061563,"Level":0,"X":4.7465842680150976,"Y":5.3218812103724131},{"Curvature":19.730424630061563,"Level":0,"X":4.5945348288241563,"Y":5.0585238564313491},{"Curvature":0.8928203230275511,"Level":1,"X":8.3601385660969356,"Y":6.93997690565051},{"Curvature":3.7094010767585033,"Level":0,"X":7.156682395474709,"Y":6.2451611615838516},{"Curvature":1.8165807537309524,"Level":0,"X":9.4038779908734238,"Y":5.6356450358772605},{"Curvature":1.8165807537309524,"Level":0,"X":7.7524237442958892,"Y":8.496047697324931},{"Curvature":0.8928203230275511,"Level":1,"X":4.9999999999999982,"Y":1.1200461886989812},{"Curvature":3.7094010767585033,"Level":0,"X":5,"Y":2.509677676832299},{"Curvature":1.8165807537309524,"Level":0,"X":3.3485457534224632,"Y":0.86830726679781078},{"Curvature":1.8165807537309524,"Level":0,"X":6.6514542465775328,"Y":0.86830726679781056},{"Curvature":0.8928203230275511,"Level":1,"X":1.6398614339030615,"Y":6.9399769056505116},{"Curvature":1.8165807537309524,"Level":0,"X":2.2475762557041086,"Y":8.4960476973249328},{"Curvature":3.7094010767585033,"Level":0,"X":2.8433176045252893,"Y":6.2451611615838525},{"Curvature":1.8165807537309524,"Level":0,"X":0.59612200912657454,"Y":5.6356450358772623}]

And here's the JSON for the second:

[{"Level":2,"Radius":1.0102051443364382,"X":0,"Y":0,"Z":0},{"Level":3,"Radius":0.89897948556635621,"X":1.9070234711746936,"Y":-1.9070234711746936,"Z":-1.9070234711746936},{"Level":4,"Radius":0.73674517520435534,"X":-1.5628725281804123,"Y":1.5628725281804123,"Z":-4.6886175845412374},{"Level":5,"Radius":0.28271609708738882,"X":-0.599731408203261,"Y":0.599731408203261,"Z":-1.7991942246097827},{"Level":5,"Radius":0.67576886917362144,"X":0,"Y":0,"Z":-5.7340889988891917},{"Level":5,"Radius":0.54135422270335332,"X":-5.7419286284627038,"Y":-3.4451571770776228,"Z":1.1483857256925409},{"Level":5,"Radius":0.54135422270335332,"X":3.4451571770776228,"Y":5.7419286284627038,"Z":1.1483857256925409},{"Level":4,"Radius":0.73674517520435534,"X":-1.5628725281804123,"Y":-4.6886175845412374,"Z":1.5628725281804123},{"Level":5,"Radius":0.28271609708738882,"X":-0.599731408203261,"Y":-1.7991942246097827,"Z":0.599731408203261},{"Level":5,"Radius":0.67576886917362144,"X":0,"Y":-5.7340889988891917,"Z":0},{"Level":5,"Radius":0.54135422270335332,"X":-5.7419286284627038,"Y":1.1483857256925409,"Z":-3.4451571770776228},{"Level":5,"Radius":0.54135422270335332,"X":3.4451571770776228,"Y":1.1483857256925409,"Z":5.7419286284627038},{"Level":4,"Radius":0.73674517520435534,"X":4.6886175845412374,"Y":1.5628725281804123,"Z":1.5628725281804123},{"Level":5,"Radius":0.28271609708738882,"X":1.7991942246097827,"Y":0.599731408203261,"Z":0.599731408203261},{"Level":5,"Radius":0.67576886917362144,"X":5.7340889988891917,"Y":0,"Z":0},{"Level":5,"Radius":0.54135422270335332,"X":-1.1483857256925409,"Y":5.7419286284627038,"Z":-3.4451571770776228},{"Level":5,"Radius":0.54135422270335332,"X":-1.1483857256925409,"Y":-3.4451571770776228,"Z":5.7419286284627038},{"Level":3,"Radius":0.89897948556635621,"X":-1.9070234711746936,"Y":1.9070234711746936,"Z":-1.9070234711746936},{"Level":4,"Radius":0.73674517520435534,"X":1.5628725281804123,"Y":-1.5628725281804123,"Z":-4.6886175845412374},{"Level":5,"Radius":0.28271609708738882,"X":0.599731408203261,"Y":-0.599731408203261,"Z":-1.7991942246097827},{"Level":5,"Radius":0.54135422270335332,"X":-3.4451571770776228,"Y":-5.7419286284627038,"Z":1.1483857256925409},{"Level":5,"Radius":0.54135422270335332,"X":5.7419286284627038,"Y":3.4451571770776228,"Z":1.1483857256925409},{"Level":4,"Radius":0.73674517520435534,"X":-4.6886175845412374,"Y":-1.5628725281804123,"Z":1.5628725281804123},{"Level":5,"Radius":0.28271609708738882,"X":-1.7991942246097827,"Y":-0.599731408203261,"Z":0.599731408203261},{"Level":5,"Radius":0.54135422270335332,"X":1.1483857256925409,"Y":-5.7419286284627038,"Z":-3.4451571770776228},{"Level":5,"Radius":0.67576886917362144,"X":-5.7340889988891917,"Y":0,"Z":0},{"Level":5,"Radius":0.54135422270335332,"X":1.1483857256925409,"Y":3.4451571770776228,"Z":5.7419286284627038},{"Level":4,"Radius":0.73674517520435534,"X":1.5628725281804123,"Y":4.6886175845412374,"Z":1.5628725281804123},{"Level":5,"Radius":0.28271609708738882,"X":0.599731408203261,"Y":1.7991942246097827,"Z":0.599731408203261},{"Level":5,"Radius":0.54135422270335332,"X":5.7419286284627038,"Y":-1.1483857256925409,"Z":-3.4451571770776228},{"Level":5,"Radius":0.67576886917362144,"X":0,"Y":5.7340889988891917,"Z":0},{"Level":5,"Radius":0.54135422270335332,"X":-3.4451571770776228,"Y":-1.1483857256925409,"Z":5.7419286284627038},{"Level":3,"Radius":0.89897948556635621,"X":-1.9070234711746936,"Y":-1.9070234711746936,"Z":1.9070234711746936},{"Level":4,"Radius":0.73674517520435534,"X":1.5628725281804123,"Y":-4.6886175845412374,"Z":-1.5628725281804123},{"Level":5,"Radius":0.28271609708738882,"X":0.599731408203261,"Y":-1.7991942246097827,"Z":-0.599731408203261},{"Level":5,"Radius":0.54135422270335332,"X":-3.4451571770776228,"Y":1.1483857256925409,"Z":-5.7419286284627038},{"Level":5,"Radius":0.54135422270335332,"X":5.7419286284627038,"Y":1.1483857256925409,"Z":3.4451571770776228},{"Level":4,"Radius":0.73674517520435534,"X":-4.6886175845412374,"Y":1.5628725281804123,"Z":-1.5628725281804123},{"Level":5,"Radius":0.28271609708738882,"X":-1.7991942246097827,"Y":0.599731408203261,"Z":-0.599731408203261},{"Level":5,"Radius":0.54135422270335332,"X":1.1483857256925409,"Y":-3.4451571770776228,"Z":-5.7419286284627038},{"Level":5,"Radius":0.54135422270335332,"X":1.1483857256925409,"Y":5.7419286284627038,"Z":3.4451571770776228},{"Level":4,"Radius":0.73674517520435534,"X":1.5628725281804123,"Y":1.5628725281804123,"Z":4.6886175845412374},{"Level":5,"Radius":0.28271609708738882,"X":0.599731408203261,"Y":0.599731408203261,"Z":1.7991942246097827},{"Level":5,"Radius":0.54135422270335332,"X":5.7419286284627038,"Y":-3.4451571770776228,"Z":-1.1483857256925409},{"Level":5,"Radius":0.54135422270335332,"X":-3.4451571770776228,"Y":5.7419286284627038,"Z":-1.1483857256925409},{"Level":5,"Radius":0.67576886917362144,"X":0,"Y":0,"Z":5.7340889988891917},{"Level":3,"Radius":0.89897948556635621,"X":1.9070234711746936,"Y":1.9070234711746936,"Z":1.9070234711746936},{"Level":4,"Radius":0.73674517520435534,"X":4.6886175845412374,"Y":-1.5628725281804123,"Z":-1.5628725281804123},{"Level":5,"Radius":0.28271609708738882,"X":1.7991942246097827,"Y":-0.599731408203261,"Z":-0.599731408203261},{"Level":5,"Radius":0.54135422270335332,"X":-1.1483857256925409,"Y":3.4451571770776228,"Z":-5.7419286284627038},{"Level":5,"Radius":0.54135422270335332,"X":-1.1483857256925409,"Y":-5.7419286284627038,"Z":3.4451571770776228},{"Level":4,"Radius":0.73674517520435534,"X":-1.5628725281804123,"Y":4.6886175845412374,"Z":-1.5628725281804123},{"Level":5,&
quot;Radius":0.28271609708738882,"X":-0.599731408203261,"Y":1.7991942246097827,"Z":-0.599731408203261},{"Level":5,"Radius":0.54135422270335332,"X":3.4451571770776228,"Y":-1.1483857256925409,"Z":-5.7419286284627038},{"Level":5,"Radius":0.54135422270335332,"X":-5.7419286284627038,"Y":-1.1483857256925409,"Z":3.4451571770776228},{"Level":4,"Radius":0.73674517520435534,"X":-1.5628725281804123,"Y":-1.5628725281804123,"Z":4.6886175845412374},{"Level":5,"Radius":0.28271609708738882,"X":-0.599731408203261,"Y":-0.599731408203261,"Z":1.7991942246097827},{"Level":5,"Radius":0.54135422270335332,"X":3.4451571770776228,"Y":-5.7419286284627038,"Z":-1.1483857256925409},{"Level":5,"Radius":0.54135422270335332,"X":-5.7419286284627038,"Y":3.4451571770776228,"Z":-1.1483857256925409},{"Level":1,"Radius":4.4948974278317806,"X":-3.1783724519578227,"Y":3.1783724519578227,"Z":3.1783724519578227},{"Level":2,"Radius":2.8989794855663567,"X":4.09977610552932,"Y":-4.09977610552932,"Z":-4.09977610552932},{"Level":3,"Radius":0.69693845669906873,"X":0.98561981760319706,"Y":-0.98561981760319706,"Z":-0.98561981760319706},{"Level":4,"Radius":0.59531041938993878,"X":-1.6837921378465335,"Y":1.6837921378465335,"Z":-3.367584275693067},{"Level":5,"Radius":0.361050735467887,"X":-1.0212056936069329,"Y":1.0212056936069329,"Z":-2.0424113872138658},{"Level":5,"Radius":0.51954937761543474,"X":0.73475377614624837,"Y":-0.73475377614624837,"Z":-5.1432764330237379},{"Level":5,"Radius":0.46089451836521378,"X":-5.2144262295640074,"Y":-2.6072131147820037,"Z":1.3036065573910018},{"Level":5,"Radius":0.46089451836521378,"X":2.6072131147820037,"Y":5.2144262295640074,"Z":1.3036065573910018},{"Level":4,"Radius":0.59531041938993878,"X":-1.6837921378465335,"Y":-3.367584275693067,"Z":1.6837921378465335},{"Level":5,"Radius":0.361050735467887,"X":-1.0212056936069329,"Y":-2.0424113872138658,"Z":1.0212056936069329},{"Level":5,"Radius":0.51954937761543474,"X":0.73475377614624837,"Y":-5.1432764330237379,"Z":-0.73475377614624837},{"Level":5,"Radius":0.46089451836521378,"X":-5.2144262295640074,"Y":1.3036065573910018,"Z":-2.6072131147820037},{"Level":5,"Radius":0.46089451836521378,"X":2.6072131147820037,"Y":1.3036065573910018,"Z":5.2144262295640074},{"Level":4,"Radius":0.59531041938993878,"X":3.367584275693067,"Y":1.6837921378465335,"Z":1.6837921378465335},{"Level":5,"Radius":0.361050735467887,"X":2.0424113872138658,"Y":1.0212056936069329,"Z":1.0212056936069329},{"Level":5,"Radius":0.51954937761543474,"X":5.1432764330237379,"Y":-0.73475377614624837,"Z":-0.73475377614624837},{"Level":5,"Radius":0.46089451836521378,"X":-1.3036065573910018,"Y":5.2144262295640074,"Z":-2.6072131147820037},{"Level":5,"Radius":0.46089451836521378,"X":-1.3036065573910018,"Y":-2.6072131147820037,"Z":5.2144262295640074},{"Level":3,"Radius":2.139387691339814,"X":-1.5127755441334152,"Y":1.5127755441334152,"Z":-7.5638777206670751},{"Level":4,"Radius":0.37775486824598364,"X":-0.2671130289629659,"Y":0.2671130289629659,"Z":-1.3355651448148294},{"Level":5,"Radius":0.34576134060244468,"X":1.2224509430607009,"Y":-1.2224509430607009,"Z":-2.6893920747335427},{"Level":5,"Radius":0.31876398046728993,"X":-2.9302022384236803,"Y":-2.479401894050806,"Z":1.5778012053050583},{"Level":5,"Radius":0.31876398046728993,"X":2.479401894050806,"Y":2.9302022384236803,"Z":1.5778012053050583},{"Level":4,"Radius":1.4037600977966975,"X":-6.94825799017795,"Y":-4.96304142155568,"Z":0.992608284311136},{"Level":5,"Radius":0.19716227375982742,"X":-0.97590346538812722,"Y":-0.6970739038486623,"Z":0.13941478076973246},{"Level":5,"Radius":1.0445812551367069,"X":-0.7386304890075206,"Y":-8.1249353790827268,"Z":-3.6931524450376023},{"Level":5,"Radius":1.1978243827074595,"X":-8.469897436830351,"Y":-1.6939794873660703,"Z":-1.6939794873660703},{"Level":5,"Radius":0.83175965498126991,"X":2.9407144617731955,"Y":4.1170002464824735,"Z":7.6458576006103094},{"Level":4,"Radius":1.4037600977966975,"X":4.96304142155568,"Y":6.94825799017795,"Z":0.992608284311136},{"Level":5,"Radius":0.19716227375982742,"X":0.6970739038486623,"Y":0.97590346538812722,"Z":0.13941478076973246},{"Level":5,"Radius":1.0445812551367069,"X":8.1249353790827268,"Y":0.7386304890075206,"Z":-3.6931524450376023},{"Level":5,"Radius":1.1978243827074595,"X":1.6939794873660703,"Y":8.469897436830351,"Z":-1.6939794873660703},{"Level":5,"Radius":0.83175965498126991,"X":-4.1170002464824735,"Y":-2.9407144617731955,"Z":7.6458576006103094},{"Level":3,"Radius":2.139387691339814,"X":-1.5127755441334152,"Y":-7.5638777206670751,"Z":1.5127755441334152},{"Level":4,"Radius":0.37775486824598364,"X":-0.2671130289629659,"Y":-1.3355651448148294,"Z":0.2671130289629659},{"Level":5,"Radius":0.34576134060244468,"X":1.2224509430607009,"Y":-2.6893920747335427,"Z":-1.2224509430607009},{"Level":5,"Radius":0.31876398046728993,"X":-2.9302022384236803,"Y":1.5778012053050583,"Z":-2.479401894050806},{"Level":5,"Radius":0.31876398046728993,"X":2.479401894050806,"Y":1.5778012053050583,"Z":2.9302022384236803},{"Level":4,"Radius":1.4037600977966975,"X":-6.94825799017795,"Y":0.992608284311136,"Z":-4.96304142155568},{"Level":5,"Radius":0.19716227375982742,"X":-0.97590346538812722,"Y":0.13941478076973246,"Z":-0.6970739038486623},{"Level":5,"Radius":1.0445812551367069,"X":-0.7386304890075206,"Y":-3.6931524450376023,"Z":-8.1249353790827268},{"Level":5,"Radius":0.83175965498126991,"X":2.9407144617731955,"Y":7.6458576006103094,"Z":4.1170002464824735},{"Level":4,"Radius":1.4037600977966975,"X":4.96304142155568,"Y":0.992608284311136,"Z":6.94825799017795},{"Level":5,"Radius":0.19716227375982742,"X":0.6970739038486623,"Y":0.13941478076973246,"Z":0.97590346538812722},{"Level"
:5,"Radius":1.0445812551367069,"X":8.1249353790827268,"Y":-3.6931524450376023,"Z":0.7386304890075206},{"Level":5,"Radius":0.83175965498126991,"X":-4.1170002464824735,"Y":7.6458576006103094,"Z":-2.9407144617731955},{"Level":5,"Radius":1.1978243827074595,"X":1.6939794873660703,"Y":-1.6939794873660703,"Z":8.469897436830351},{"Level":3,"Radius":2.139387691339814,"X":7.5638777206670751,"Y":1.5127755441334152,"Z":1.5127755441334152},{"Level":4,"Radius":0.37775486824598364,"X":1.3355651448148294,"Y":0.2671130289629659,"Z":0.2671130289629659},{"Level":5,"Radius":0.34576134060244468,"X":2.6893920747335427,"Y":-1.2224509430607009,"Z":-1.2224509430607009},{"Level":5,"Radius":0.31876398046728993,"X":-1.5778012053050583,"Y":2.9302022384236803,"Z":-2.479401894050806},{"Level":5,"Radius":0.31876398046728993,"X":-1.5778012053050583,"Y":-2.479401894050806,"Z":2.9302022384236803},{"Level":4,"Radius":1.4037600977966975,"X":-0.992608284311136,"Y":6.94825799017795,"Z":-4.96304142155568},{"Level":5,"Radius":0.19716227375982742,"X":-0.13941478076973246,"Y":0.97590346538812722,"Z":-0.6970739038486623},{"Level":5,"Radius":1.0445812551367069,"X":3.6931524450376023,"Y":0.7386304890075206,"Z":-8.1249353790827268},{"Level":5,"Radius":0.83175965498126991,"X":-7.6458576006103094,"Y":-2.9407144617731955,"Z":4.1170002464824735},{"Level":4,"Radius":1.4037600977966975,"X":-0.992608284311136,"Y":-4.96304142155568,"Z":6.94825799017795},{"Level":5,"Radius":0.19716227375982742,"X":-0.13941478076973246,"Y":-0.6970739038486623,"Z":0.97590346538812722},{"Level":5,"Radius":1.0445812551367069,"X":3.6931524450376023,"Y":-8.1249353790827268,"Z":0.7386304890075206},{"Level":5,"Radius":0.83175965498126991,"X":-7.6458576006103094,"Y":4.1170002464824735,"Z":-2.9407144617731955},{"Level":1,"Radius":4.4948974278317806,"X":3.1783724519578227,"Y":-3.1783724519578227,"Z":3.1783724519578227},{"Level":2,"Radius":2.8989794855663567,"X":-4.09977610552932,"Y":4.09977610552932,"Z":-4.09977610552932},{"Level":3,"Radius":0.69693845669906873,"X":-0.98561981760319706,"Y":0.98561981760319706,"Z":-0.98561981760319706},{"Level":4,"Radius":0.59531041938993878,"X":1.6837921378465335,"Y":-1.6837921378465335,"Z":-3.367584275693067},{"Level":5,"Radius":0.361050735467887,"X":1.0212056936069329,"Y":-1.0212056936069329,"Z":-2.0424113872138658},{"Level":5,"Radius":0.51954937761543474,"X":-0.73475377614624837,"Y":0.73475377614624837,"Z":-5.1432764330237379},{"Level":5,"Radius":0.46089451836521378,"X":-2.6072131147820037,"Y":-5.2144262295640074,"Z":1.3036065573910018},{"Level":5,"Radius":0.46089451836521378,"X":5.2144262295640074,"Y":2.6072131147820037,"Z":1.3036065573910018},{"Level":4,"Radius":0.59531041938993878,"X":-3.367584275693067,"Y":-1.6837921378465335,"Z":1.6837921378465335},{"Level":5,"Radius":0.361050735467887,"X":-2.0424113872138658,"Y":-1.0212056936069329,"Z":1.0212056936069329},{"Level":5,"Radius":0.46089451836521378,"X":1.3036065573910018,"Y":-5.2144262295640074,"Z":-2.6072131147820037},{"Level":5,"Radius":0.51954937761543474,"X":-5.1432764330237379,"Y":0.73475377614624837,"Z":-0.73475377614624837},{"Level":5,"Radius":0.46089451836521378,"X":1.3036065573910018,"Y":2.6072131147820037,"Z":5.2144262295640074},{"Level":4,"Radius":0.59531041938993878,"X":1.6837921378465335,"Y":3.367584275693067,"Z":1.6837921378465335},{"Level":5,"Radius":0.361050735467887,"X":1.0212056936069329,"Y":2.0424113872138658,"Z":1.0212056936069329},{"Level":5,"Radius":0.46089451836521378,"X":5.2144262295640074,"Y":-1.3036065573910018,"Z":-2.6072131147820037},{"Level":5,"Radius":0.51954937761543474,"X":-0.73475377614624837,"Y":5.1432764330237379,"Z":-0.73475377614624837},{"Level":5,"Radius":0.46089451836521378,"X":-2.6072131147820037,"Y":-1.3036065573910018,"Z":5.2144262295640074},{"Level":3,"Radius":2.139387691339814,"X":1.5127755441334152,"Y":-1.5127755441334152,"Z":-7.5638777206670751},{"Level":4,"Radius":0.37775486824598364,"X":0.2671130289629659,"Y":-0.2671130289629659,"Z":-1.3355651448148294},{"Level":5,"Radius":0.34576134060244468,"X":-1.2224509430607009,"Y":1.2224509430607009,"Z":-2.6893920747335427},{"Level":5,"Radius":0.31876398046728993,"X":-2.479401894050806,"Y":-2.9302022384236803,"Z":1.5778012053050583},{"Level":5,"Radius":0.31876398046728993,"X":2.9302022384236803,"Y":2.479401894050806,"Z":1.5778012053050583},{"Level":4,"Radius":1.4037600977966975,"X":-4.96304142155568,"Y":-6.94825799017795,"Z":0.992608284311136},{"Level":5,"Radius":0.19716227375982742,"X":-0.6970739038486623,"Y":-0.97590346538812722,"Z":0.13941478076973246},{"Level":5,"Radius":1.1978243827074595,"X":-1.6939794873660703,"Y":-8.469897436830351,"Z":-1.6939794873660703},{"Level":5,"Radius":1.0445812551367069,"X":-8.1249353790827268,"Y":-0.7386304890075206,"Z":-3.6931524450376023},{"Level":5,"Radius":0.83175965498126991,"X":4.1170002464824735,"Y":2.9407144617731955,"Z":7.6458576006103094},{"Level":4,"Radius":1.4037600977966975,"X":6.94825799017795,"Y":4.96304142155568,"Z":0.992608284311136},{"Level":5,"Radius":0.19716227375982742,"X":0.97590346538812722,"Y":0.6970739038486623,"Z":0.13941478076973246},{"Level":5,"Radius":1.1978243827074595,"X":8.469897436830351,"Y":1.6939794873660703,"Z":-1.6939794873660703},{"Level":5,"Radius":1.0445812551367069,"X":0.7386304890075206,"Y":8.1249353790827268,"Z":-3.6931524450376023},{"Level":5,"Radius":0.83175965498126991,"X":-2.9407144617731955,"Y":-4.1170002464824735,"Z":7.6458576006103094},{"Level":3,"Radius":2.139387691339814,"X":-7.5638777206670751,"Y":-1.5127755441334152,"Z":1.5127755441334152},{"Level":4,"Radius":0.37775486824598364,"X":-1.3355651448148294,"Y":-0.2671130289629659,"Z":0.2671130289629659},{"Level"
;:5,"Radius":0.31876398046728993,"X":1.5778012053050583,"Y":-2.9302022384236803,"Z":-2.479401894050806},{"Level":5,"Radius":0.34576134060244468,"X":-2.6893920747335427,"Y":1.2224509430607009,"Z":-1.2224509430607009},{"Level":5,"Radius":0.31876398046728993,"X":1.5778012053050583,"Y":2.479401894050806,"Z":2.9302022384236803},{"Level":4,"Radius":1.4037600977966975,"X":0.992608284311136,"Y":-6.94825799017795,"Z":-4.96304142155568},{"Level":5,"Radius":0.19716227375982742,"X":0.13941478076973246,"Y":-0.97590346538812722,"Z":-0.6970739038486623},{"Level":5,"Radius":1.0445812551367069,"X":-3.6931524450376023,"Y":-0.7386304890075206,"Z":-8.1249353790827268},{"Level":5,"Radius":0.83175965498126991,"X":7.6458576006103094,"Y":2.9407144617731955,"Z":4.1170002464824735},{"Level":4,"Radius":1.4037600977966975,"X":0.992608284311136,"Y":4.96304142155568,"Z":6.94825799017795},{"Level":5,"Radius":0.19716227375982742,"X":0.13941478076973246,"Y":0.6970739038486623,"Z":0.97590346538812722},{"Level":5,"Radius":0.83175965498126991,"X":7.6458576006103094,"Y":-4.1170002464824735,"Z":-2.9407144617731955},{"Level":5,"Radius":1.0445812551367069,"X":-3.6931524450376023,"Y":8.1249353790827268,"Z":0.7386304890075206},{"Level":5,"Radius":1.1978243827074595,"X":-1.6939794873660703,"Y":1.6939794873660703,"Z":8.469897436830351},{"Level":3,"Radius":2.139387691339814,"X":1.5127755441334152,"Y":7.5638777206670751,"Z":1.5127755441334152},{"Level":4,"Radius":0.37775486824598364,"X":0.2671130289629659,"Y":1.3355651448148294,"Z":0.2671130289629659},{"Level":5,"Radius":0.31876398046728993,"X":2.9302022384236803,"Y":-1.5778012053050583,"Z":-2.479401894050806},{"Level":5,"Radius":0.34576134060244468,"X":-1.2224509430607009,"Y":2.6893920747335427,"Z":-1.2224509430607009},{"Level":5,"Radius":0.31876398046728993,"X":-2.479401894050806,"Y":-1.5778012053050583,"Z":2.9302022384236803},{"Level":4,"Radius":1.4037600977966975,"X":6.94825799017795,"Y":-0.992608284311136,"Z":-4.96304142155568},{"Level":5,"Radius":0.19716227375982742,"X":0.97590346538812722,"Y":-0.13941478076973246,"Z":-0.6970739038486623},{"Level":5,"Radius":1.0445812551367069,"X":0.7386304890075206,"Y":3.6931524450376023,"Z":-8.1249353790827268},{"Level":5,"Radius":0.83175965498126991,"X":-2.9407144617731955,"Y":-7.6458576006103094,"Z":4.1170002464824735},{"Level":4,"Radius":1.4037600977966975,"X":-4.96304142155568,"Y":-0.992608284311136,"Z":6.94825799017795},{"Level":5,"Radius":0.19716227375982742,"X":-0.6970739038486623,"Y":-0.13941478076973246,"Z":0.97590346538812722},{"Level":5,"Radius":0.83175965498126991,"X":4.1170002464824735,"Y":-7.6458576006103094,"Z":-2.9407144617731955},{"Level":5,"Radius":1.0445812551367069,"X":-8.1249353790827268,"Y":3.6931524450376023,"Z":0.7386304890075206},{"Level":1,"Radius":4.4948974278317806,"X":3.1783724519578227,"Y":3.1783724519578227,"Z":-3.1783724519578227},{"Level":2,"Radius":2.8989794855663567,"X":-4.09977610552932,"Y":-4.09977610552932,"Z":4.09977610552932},{"Level":3,"Radius":0.69693845669906873,"X":-0.98561981760319706,"Y":-0.98561981760319706,"Z":0.98561981760319706},{"Level":4,"Radius":0.59531041938993878,"X":1.6837921378465335,"Y":-3.367584275693067,"Z":-1.6837921378465335},{"Level":5,"Radius":0.361050735467887,"X":1.0212056936069329,"Y":-2.0424113872138658,"Z":-1.0212056936069329},{"Level":5,"Radius":0.46089451836521378,"X":-2.6072131147820037,"Y":1.3036065573910018,"Z":-5.2144262295640074},{"Level":5,"Radius":0.51954937761543474,"X":-0.73475377614624837,"Y":-5.1432764330237379,"Z":0.73475377614624837},{"Level":5,"Radius":0.46089451836521378,"X":5.2144262295640074,"Y":1.3036065573910018,"Z":2.6072131147820037},{"Level":4,"Radius":0.59531041938993878,"X":-3.367584275693067,"Y":1.6837921378465335,"Z":-1.6837921378465335},{"Level":5,"Radius":0.361050735467887,"X":-2.0424113872138658,"Y":1.0212056936069329,"Z":-1.0212056936069329},{"Level":5,"Radius":0.46089451836521378,"X":1.3036065573910018,"Y":-2.6072131147820037,"Z":-5.2144262295640074},{"Level":5,"Radius":0.51954937761543474,"X":-5.1432764330237379,"Y":-0.73475377614624837,"Z":0.73475377614624837},{"Level":5,"Radius":0.46089451836521378,"X":1.3036065573910018,"Y":5.2144262295640074,"Z":2.6072131147820037},{"Level":4,"Radius":0.59531041938993878,"X":1.6837921378465335,"Y":1.6837921378465335,"Z":3.367584275693067},{"Level":5,"Radius":0.361050735467887,"X":1.0212056936069329,"Y":1.0212056936069329,"Z":2.0424113872138658},{"Level":5,"Radius":0.46089451836521378,"X":5.2144262295640074,"Y":-2.6072131147820037,"Z":-1.3036065573910018},{"Level":5,"Radius":0.46089451836521378,"X":-2.6072131147820037,"Y":5.2144262295640074,"Z":-1.3036065573910018},{"Level":5,"Radius":0.51954937761543474,"X":-0.73475377614624837,"Y":-0.73475377614624837,"Z":5.1432764330237379},{"Level":3,"Radius":2.139387691339814,"X":1.5127755441334152,"Y":-7.5638777206670751,"Z":-1.5127755441334152},{"Level":4,"Radius":0.37775486824598364,"X":0.2671130289629659,"Y":-1.3355651448148294,"Z":-0.2671130289629659},{"Level":5,"Radius":0.31876398046728993,"X":-2.479401894050806,"Y":1.5778012053050583,"Z":-2.9302022384236803},{"Level":5,"Radius":0.34576134060244468,"X":-1.2224509430607009,"Y":-2.6893920747335427,"Z":1.2224509430607009},{"Level":5,"Radius":0.31876398046728993,"X":2.9302022384236803,"Y":1.5778012053050583,"Z":2.479401894050806},{"Level":4,"Radius":1.4037600977966975,"X":-4.96304142155568,"Y":0.992608284311136,"Z":-6.94825799017795},{"Level":5,"Radius":0.19716227375982742,"X":-0.6970739038486623,"Y":0.13941478076973246,"Z":-0.97590346538812722},{"Level":5,"Radius":1.1978243827074595,"X":-1.6939794873660703,"Y":-1.6939794873660703,"Z":-8.469897436830351},{"Level"
;:5,"Radius":1.0445812551367069,"X":-8.1249353790827268,"Y":-3.6931524450376023,"Z":-0.7386304890075206},{"Level":5,"Radius":0.83175965498126991,"X":4.1170002464824735,"Y":7.6458576006103094,"Z":2.9407144617731955},{"Level":4,"Radius":1.4037600977966975,"X":6.94825799017795,"Y":0.992608284311136,"Z":4.96304142155568},{"Level":5,"Radius":0.19716227375982742,"X":0.97590346538812722,"Y":0.13941478076973246,"Z":0.6970739038486623},{"Level":5,"Radius":1.1978243827074595,"X":8.469897436830351,"Y":-1.6939794873660703,"Z":1.6939794873660703},{"Level":5,"Radius":0.83175965498126991,"X":-2.9407144617731955,"Y":7.6458576006103094,"Z":-4.1170002464824735},{"Level":5,"Radius":1.0445812551367069,"X":0.7386304890075206,"Y":-3.6931524450376023,"Z":8.1249353790827268},{"Level":3,"Radius":2.139387691339814,"X":-7.5638777206670751,"Y":1.5127755441334152,"Z":-1.5127755441334152},{"Level":4,"Radius":0.37775486824598364,"X":-1.3355651448148294,"Y":0.2671130289629659,"Z":-0.2671130289629659},{"Level":5,"Radius":0.31876398046728993,"X":1.5778012053050583,"Y":-2.479401894050806,"Z":-2.9302022384236803},{"Level":5,"Radius":0.34576134060244468,"X":-2.6893920747335427,"Y":-1.2224509430607009,"Z":1.2224509430607009},{"Level":5,"Radius":0.31876398046728993,"X":1.5778012053050583,"Y":2.9302022384236803,"Z":2.479401894050806},{"Level":4,"Radius":1.4037600977966975,"X":0.992608284311136,"Y":-4.96304142155568,"Z":-6.94825799017795},{"Level":5,"Radius":0.19716227375982742,"X":0.13941478076973246,"Y":-0.6970739038486623,"Z":-0.97590346538812722},{"Level":5,"Radius":1.0445812551367069,"X":-3.6931524450376023,"Y":-8.1249353790827268,"Z":-0.7386304890075206},{"Level":5,"Radius":0.83175965498126991,"X":7.6458576006103094,"Y":4.1170002464824735,"Z":2.9407144617731955},{"Level":4,"Radius":1.4037600977966975,"X":0.992608284311136,"Y":6.94825799017795,"Z":4.96304142155568},{"Level":5,"Radius":0.19716227375982742,"X":0.13941478076973246,"Y":0.97590346538812722,"Z":0.6970739038486623},{"Level":5,"Radius":0.83175965498126991,"X":7.6458576006103094,"Y":-2.9407144617731955,"Z":-4.1170002464824735},{"Level":5,"Radius":1.1978243827074595,"X":-1.6939794873660703,"Y":8.469897436830351,"Z":1.6939794873660703},{"Level":5,"Radius":1.0445812551367069,"X":-3.6931524450376023,"Y":0.7386304890075206,"Z":8.1249353790827268},{"Level":3,"Radius":2.139387691339814,"X":1.5127755441334152,"Y":1.5127755441334152,"Z":7.5638777206670751},{"Level":4,"Radius":0.37775486824598364,"X":0.2671130289629659,"Y":0.2671130289629659,"Z":1.3355651448148294},{"Level":5,"Radius":0.31876398046728993,"X":2.9302022384236803,"Y":-2.479401894050806,"Z":-1.5778012053050583},{"Level":5,"Radius":0.31876398046728993,"X":-2.479401894050806,"Y":2.9302022384236803,"Z":-1.5778012053050583},{"Level":5,"Radius":0.34576134060244468,"X":-1.2224509430607009,"Y":-1.2224509430607009,"Z":2.6893920747335427},{"Level":4,"Radius":1.4037600977966975,"X":6.94825799017795,"Y":-4.96304142155568,"Z":-0.992608284311136},{"Level":5,"Radius":0.19716227375982742,"X":0.97590346538812722,"Y":-0.6970739038486623,"Z":-0.13941478076973246},{"Level":5,"Radius":0.83175965498126991,"X":-2.9407144617731955,"Y":4.1170002464824735,"Z":-7.6458576006103094},{"Level":5,"Radius":1.0445812551367069,"X":0.7386304890075206,"Y":-8.1249353790827268,"Z":3.6931524450376023},{"Level":4,"Radius":1.4037600977966975,"X":-4.96304142155568,"Y":6.94825799017795,"Z":-0.992608284311136},{"Level":5,"Radius":0.19716227375982742,"X":-0.6970739038486623,"Y":0.97590346538812722,"Z":-0.13941478076973246},{"Level":5,"Radius":0.83175965498126991,"X":4.1170002464824735,"Y":-2.9407144617731955,"Z":-7.6458576006103094},{"Level":5,"Radius":1.0445812551367069,"X":-8.1249353790827268,"Y":0.7386304890075206,"Z":3.6931524450376023},{"Level":1,"Radius":4.4948974278317806,"X":-3.1783724519578227,"Y":-3.1783724519578227,"Z":-3.1783724519578227},{"Level":2,"Radius":2.8989794855663567,"X":4.09977610552932,"Y":4.09977610552932,"Z":4.09977610552932},{"Level":3,"Radius":0.69693845669906873,"X":0.98561981760319706,"Y":0.98561981760319706,"Z":0.98561981760319706},{"Level":4,"Radius":0.59531041938993878,"X":3.367584275693067,"Y":-1.6837921378465335,"Z":-1.6837921378465335},{"Level":5,"Radius":0.361050735467887,"X":2.0424113872138658,"Y":-1.0212056936069329,"Z":-1.0212056936069329},{"Level":5,"Radius":0.46089451836521378,"X":-1.3036065573910018,"Y":2.6072131147820037,"Z":-5.2144262295640074},{"Level":5,"Radius":0.46089451836521378,"X":-1.3036065573910018,"Y":-5.2144262295640074,"Z":2.6072131147820037},{"Level":5,"Radius":0.51954937761543474,"X":5.1432764330237379,"Y":0.73475377614624837,"Z":0.73475377614624837},{"Level":4,"Radius":0.59531041938993878,"X":-1.6837921378465335,"Y":3.367584275693067,"Z":-1.6837921378465335},{"Level":5,"Radius":0.361050735467887,"X":-1.0212056936069329,"Y":2.0424113872138658,"Z":-1.0212056936069329},{"Level":5,"Radius":0.46089451836521378,"X":2.6072131147820037,"Y":-1.3036065573910018,"Z":-5.2144262295640074},{"Level":5,"Radius":0.46089451836521378,"X":-5.2144262295640074,"Y":-1.3036065573910018,"Z":2.6072131147820037},{"Level":5,"Radius":0.51954937761543474,"X":0.73475377614624837,"Y":5.1432764330237379,"Z":0.73475377614624837},{"Level":4,"Radius":0.59531041938993878,"X":-1.6837921378465335,"Y":-1.6837921378465335,"Z":3.367584275693067},{"Level":5,"Radius":0.361050735467887,"X":-1.0212056936069329,"Y":-1.0212056936069329,"Z":2.0424113872138658},{"Level":5,"Radius":0.46089451836521378,"X":2.6072131147820037,"Y":-5.2144262295640074,"Z":-1.3036065573910018},{"Level":5,"Radius":0.46089451836521378,"X":-5.2144262295640074,"Y":2.6072131147820037,"Z":-1.3036065573910018},{"Level":5,&q
uot;Radius":0.51954937761543474,"X":0.73475377614624837,"Y":0.73475377614624837,"Z":5.1432764330237379},{"Level":3,"Radius":2.139387691339814,"X":7.5638777206670751,"Y":-1.5127755441334152,"Z":-1.5127755441334152},{"Level":4,"Radius":0.37775486824598364,"X":1.3355651448148294,"Y":-0.2671130289629659,"Z":-0.2671130289629659},{"Level":5,"Radius":0.31876398046728993,"X":-1.5778012053050583,"Y":2.479401894050806,"Z":-2.9302022384236803},{"Level":5,"Radius":0.31876398046728993,"X":-1.5778012053050583,"Y":-2.9302022384236803,"Z":2.479401894050806},{"Level":5,"Radius":0.34576134060244468,"X":2.6893920747335427,"Y":1.2224509430607009,"Z":1.2224509430607009},{"Level":4,"Radius":1.4037600977966975,"X":-0.992608284311136,"Y":4.96304142155568,"Z":-6.94825799017795},{"Level":5,"Radius":0.19716227375982742,"X":-0.13941478076973246,"Y":0.6970739038486623,"Z":-0.97590346538812722},{"Level":5,"Radius":1.1978243827074595,"X":1.6939794873660703,"Y":1.6939794873660703,"Z":-8.469897436830351},{"Level":5,"Radius":0.83175965498126991,"X":-7.6458576006103094,"Y":-4.1170002464824735,"Z":2.9407144617731955},{"Level":5,"Radius":1.0445812551367069,"X":3.6931524450376023,"Y":8.1249353790827268,"Z":-0.7386304890075206},{"Level":4,"Radius":1.4037600977966975,"X":-0.992608284311136,"Y":-6.94825799017795,"Z":4.96304142155568},{"Level":5,"Radius":0.19716227375982742,"X":-0.13941478076973246,"Y":-0.97590346538812722,"Z":0.6970739038486623},{"Level":5,"Radius":1.1978243827074595,"X":1.6939794873660703,"Y":-8.469897436830351,"Z":1.6939794873660703},{"Level":5,"Radius":0.83175965498126991,"X":-7.6458576006103094,"Y":2.9407144617731955,"Z":-4.1170002464824735},{"Level":5,"Radius":1.0445812551367069,"X":3.6931524450376023,"Y":-0.7386304890075206,"Z":8.1249353790827268},{"Level":3,"Radius":2.139387691339814,"X":-1.5127755441334152,"Y":7.5638777206670751,"Z":-1.5127755441334152},{"Level":4,"Radius":0.37775486824598364,"X":-0.2671130289629659,"Y":1.3355651448148294,"Z":-0.2671130289629659},{"Level":5,"Radius":0.31876398046728993,"X":2.479401894050806,"Y":-1.5778012053050583,"Z":-2.9302022384236803},{"Level":5,"Radius":0.31876398046728993,"X":-2.9302022384236803,"Y":-1.5778012053050583,"Z":2.479401894050806},{"Level":5,"Radius":0.34576134060244468,"X":1.2224509430607009,"Y":2.6893920747335427,"Z":1.2224509430607009},{"Level":4,"Radius":1.4037600977966975,"X":4.96304142155568,"Y":-0.992608284311136,"Z":-6.94825799017795},{"Level":5,"Radius":0.19716227375982742,"X":0.6970739038486623,"Y":-0.13941478076973246,"Z":-0.97590346538812722},{"Level":5,"Radius":0.83175965498126991,"X":-4.1170002464824735,"Y":-7.6458576006103094,"Z":2.9407144617731955},{"Level":5,"Radius":1.0445812551367069,"X":8.1249353790827268,"Y":3.6931524450376023,"Z":-0.7386304890075206},{"Level":4,"Radius":1.4037600977966975,"X":-6.94825799017795,"Y":-0.992608284311136,"Z":4.96304142155568},{"Level":5,"Radius":0.19716227375982742,"X":-0.97590346538812722,"Y":-0.13941478076973246,"Z":0.6970739038486623},{"Level":5,"Radius":0.83175965498126991,"X":2.9407144617731955,"Y":-7.6458576006103094,"Z":-4.1170002464824735},{"Level":5,"Radius":1.1978243827074595,"X":-8.469897436830351,"Y":1.6939794873660703,"Z":1.6939794873660703},{"Level":5,"Radius":1.0445812551367069,"X":-0.7386304890075206,"Y":3.6931524450376023,"Z":8.1249353790827268},{"Level":3,"Radius":2.139387691339814,"X":-1.5127755441334152,"Y":-1.5127755441334152,"Z":7.5638777206670751},{"Level":4,"Radius":0.37775486824598364,"X":-0.2671130289629659,"Y":-0.2671130289629659,"Z":1.3355651448148294},{"Level":5,"Radius":0.31876398046728993,"X":2.479401894050806,"Y":-2.9302022384236803,"Z":-1.5778012053050583},{"Level":5,"Radius":0.31876398046728993,"X":-2.9302022384236803,"Y":2.479401894050806,"Z":-1.5778012053050583},{"Level":5,"Radius":0.34576134060244468,"X":1.2224509430607009,"Y":1.2224509430607009,"Z":2.6893920747335427},{"Level":4,"Radius":1.4037600977966975,"X":4.96304142155568,"Y":-6.94825799017795,"Z":-0.992608284311136},{"Level":5,"Radius":0.19716227375982742,"X":0.6970739038486623,"Y":-0.97590346538812722,"Z":-0.13941478076973246},{"Level":5,"Radius":0.83175965498126991,"X":-4.1170002464824735,"Y":2.9407144617731955,"Z":-7.6458576006103094},{"Level":5,"Radius":1.0445812551367069,"X":8.1249353790827268,"Y":-0.7386304890075206,"Z":3.6931524450376023},{"Level":4,"Radius":1.4037600977966975,"X":-6.94825799017795,"Y":4.96304142155568,"Z":-0.992608284311136},{"Level":5,"Radius":0.19716227375982742,"X":-0.97590346538812722,"Y":0.6970739038486623,"Z":-0.13941478076973246},{"Level":5,"Radius":0.83175965498126991,"X":2.9407144617731955,"Y":-4.1170002464824735,"Z":-7.6458576006103094},{"Level":5,"Radius":1.0445812551367069,"X":-0.7386304890075206,"Y":8.1249353790827268,"Z":3.6931524450376023}]

The Circle and Sphere types have effectively been translated (via the names of their constructor arguments rather than their internal members, which is a little confusing) into the JSON text format.

That's all it took to expose our local web-service using the ASP.NET Web API - and that's with the "overhead" of needing a separate project for our (actually pretty simple) F# code. This is really a quantum leap forwards in terms of reducing the effort required to expose a RESTful web-service. It's also now relatively straightforward to move a local web-service such as this to be hosted in the cloud.

But let's not get ahead of ourselves: in the next post in this series, we'll look at approaches for consuming the data returned from calling these APIs and generating equivalent geometry inside AutoCAD.

  1. Scott McFarlane Avatar
    Scott McFarlane

    I think an important but perhaps less obvious lesson here isn’t so much that you can consume a web service from an AutoCAD program, but how you can separate the concerns of your application into those that are dependent on the AutoCAD API, and those that are not. And whether you actually use a remote web service or not, just shifting your thought process into a “service-oriented” mode will usually result in a better design, with more loosely coupled, reusable components.

    When I really pay attention to it, I’m always surprised at how little of the code in my AutoCAD programs is actually dependent on the AutoCAD API. Even more separation can be achieved through simple abstractions (like your Circle and Sphere classes). Having most of your program logic in non-AutoCAD-dependent components has significant advantages. Those components are more reusable (say, by a program that is like AutoCAD but not – if such a thing exists), they are easier to maintain (they don’t need to be changed or recompiled for new AutoCAD releases), and they can be unit tested inside of Visual Studio. Oh, and of course, they can more easily be migrated into web services later.

  2. Kean Walmsley Avatar

    An excellent comment, Scott (I'm happy to see a comment from "Mr. Business Logic" himself 😉

    I'll try to remember to highlight this area at some point in the series (although I don't have much by way of hard and fast rules or advice to offer - a lot of those decisions depend on the context).

    Thanks!

    Kean

  3. In CirclesController.fs following error is coming

    "The namespace or module 'CirclePackingFullFs' is not defined"

    error is coming. I have no idea about F#. I added the powerpack of F# with Powerpack.Paralel,Seq. But the line

    member x.Get(rad:double, steps:int) =
    CirclePackingFullFs.Packer.ApollonianGasket rad steps |>
    List.map (fun ((a,b,c),d) -> new Circle(a,b,c,d)) |>
    List.toSeq

    shows error under CirclePackingFullFs. Please help.

  4. You need to make sure the CirclePackingFull.fs file is copied across - and added into your project - from this project:

    through-the-interface.typepad.com/files/CircleAndSpherePacking.zip

    I hope this helps,

    Kean

  5. Thanx Kean, for your prompt replay.

    Your project download from the above link, is working just fine. But that is not a MVC structured project as you discussed in this article. When I am trying to call the F# project as webservice as you suggested, with the suggested F#C# template "CirclesController.fs" is showing the above erroe. Actually this file does not exists in the project you referred. I am stuck in this minor error for last two days, please help

  6. You need to copy the file across from the project I just provided into the one you've created, as described in the post.

    Kean

Leave a Reply

Your email address will not be published. Required fields are marked *