Attaching geo-location data to an AutoCAD drawing using .NET

AutoCAD's geo-location API is a topic I've been meaning (and even promising) to cover for some time now. So here we are. 🙂

The below code sample is based on one shown at ADN's DevDays tour at the end of 2013 – for the AutoCAD 2014 release – but the API ended up not being fully usable (at least as far as I recall: someone should jump in and correct me if I have this wrong) until the 2015 release.

I've taken the opportunity to use Editor.Command() to call a couple of commands synchronously – to turn on the GEOMAP information and to zoom to a circle that we create around our location – now that this particular API is available.

Here's the C# code implementing the IGR command:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.Geometry;

using Autodesk.AutoCAD.Runtime;

 

namespace GeoLocationAPI

{

  public class Commands

  {

    [CommandMethod("IGR")]

    public void InsertGeoRef()

    {

      var doc = Application.DocumentManager.MdiActiveDocument;

      if (doc == null)

        return;

      var ed = doc.Editor;

      var db = doc.Database;

      var msId = SymbolUtilityServices.GetBlockModelSpaceId(db);

 

      // Check whether the drawing already has geolocation data

 

      bool hasGeoData = false;

      try

      {

        var gdId = db.GeoDataObject;

        hasGeoData = true;

      }

      catch { }

 

      if (hasGeoData)

      {

        // Report and return: could also open the object for

        // write and modify its properties, of course

 

        ed.WriteMessage("\nDrawing already has geo-location data!");

        return;

      }

 

      // Let's create some geolocation data for this drawing,

      // using a handy method to add it to the modelspace

      // (it gets added to the extension dictionary)

 

      var data = new GeoLocationData();

      data.BlockTableRecordId = msId;

      data.PostToDb();

 

      // We're going to define our geolocation in terms of

      // latitude/longitude using the Mercator projection

      // http://en.wikipedia.org/wiki/Mercator_projection

 

      data.CoordinateSystem = "WORLD-MERCATOR";

      data.TypeOfCoordinates = TypeOfCoordinates.CoordinateTypeGrid;

 

      // Use the lat-long for La Tene, my local "beach"

      // (it's on a lake, after all :-)     

 

      var geoPt = new Point3d(7.019438, 47.005247, 0);

 

      // Transform from a geographic to a modelspace point

      // and add the information to our geolocation data

 

      var wcsPt = data.TransformFromLonLatAlt(geoPt);

      data.DesignPoint = wcsPt;

      data.ReferencePoint = geoPt;

 

      // Let's launch the GEOMAP command to show our geographic

  
0;   // overlay

 

      ed.Command("_.GEOMAP", "_AERIAL");

 

      // Now we'll add a circle around our location

      // and that will provide the extents for our zoom

 

      using (var tr = db.TransactionManager.StartTransaction())

      {

        var ms =

          tr.GetObject(msId, OpenMode.ForWrite) as BlockTableRecord;

        if (ms != null)

        {

          // Add a red circle of 7K units radius

          // centred on our point

 

          var circle = new Circle(wcsPt, Vector3d.ZAxis, 7000);

          circle.ColorIndex = 1;

          ms.AppendEntity(circle);

          tr.AddNewlyCreatedDBObject(circle, true);

        }

        tr.Commit();

      }

 

      // And we'll zoom to the circle's extents

 

      ed.Command("_.ZOOM", "_OBJECT", "_L", "");

    }

  }

}

When we run the code, we will see our geographic location gets set to that of La Tene (a place close to my home that I've mentioned before) and a circle is created with a radius of 7,000 units (maybe that's 7km? it looks about right) around our location:

GeoLocation in action

In case you're wondering, the choice of 7000 was arbitrary: it made the map look good with the fields of oilseed rape at the upper left (setting a larger radius caused a different, less colourful set of imagery to be loaded).

A quick word of warning about the TransformFromLonLatAlt() method: it assumes the Point3d passed in has longitude, latitude, altitude in the x, y, z fields in that order. I made the mistake of copying the lat-long values directly across from Google Maps (not realising I needed long-lat), and found that AutoCAD zoomed into a location about 1km inside Ethiopia's border with Somalia. Seems like the kind of thing someone could make a fun activity out of: send a letter to the address on the "opposite" side of the planet of your own (except it isn't opposite, of course, but I honestly don't know the best way to describe what happens when you swap latitude with longitude).

There's more I want to do with the geo-location API inside AutoCAD: I want to be able to clip an image and access/modify its properties programmatically, for instance. We'll take a look at that in an upcoming post. Also, do let me know if you have additional geo-location tasks you'd like to see performed, and I'll see what's possible.

5 responses to “Attaching geo-location data to an AutoCAD drawing using .NET”

  1. Hi, i got the following error when try to use your code:

    'Autodesk.AutoCAD.EditorInput.Editor' does not contain a definition for 'Command' and no extension method 'Command' accepting a first argument of type 'Autodesk.AutoCAD.EditorInput.Editor' could be found

    The references used are from AutoCAD 2012.

    1. This code will probably only work from AutoCAD 2015 onwards (it may work with 2014, but I suspect not). It definitely won't work with 2012-2013.

      Kean

      1. Kean,
        How could you use the API to remove the geographic location data from a drawing?
        Stacy

        1. Stacy,

          Have you tried opening db.GeoDataObject for write and then erasing it? I haven't tried this myself, mind - just a quick suggestion off the top of my head.

          Please let me know if it works,

          Kean

          1. The erase method works. Thank you!

Leave a Reply to Kean Walmsley Cancel reply

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