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
// 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:
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.