SetGeoCoordinateSystem

SetGeoCoordinateSystem

h_echevarria
Enthusiast Enthusiast
1,963 Views
12 Replies
Message 1 of 13

SetGeoCoordinateSystem

h_echevarria
Enthusiast
Enthusiast

Hello,

 

I would be interested in changing the Revit geolocation system; from the UI it's only possible by importing a CAD file but I would like to be able to do it programmatically.

 

I found the method SiteLocation.SetGeoCoordinateSystem() and looks like what I need, but I don't understand how to use the method's argument. Is there a list of possible codes that I can use?

 

Many thanks

0 Likes
Accepted solutions (1)
1,964 Views
12 Replies
Replies (12)
Message 2 of 13

jeremy_tammik
Alumni
Alumni
Accepted solution

Hello Hernan. 

  

I passed on your question to an LLM, as I described today in my blog:

  

  

It replies:

  

Subject: Programmatically Changing Revit Geolocation

Hello,

You're right, the Revit UI only allows setting geolocation by importing a CAD file, which can be cumbersome. Fortunately, the SiteLocation.SetGeoCoordinateSystem() method offers a programmatic solution.

Understanding the SetGeoCoordinateSystem() Method

This method requires a string argument representing the EPSG code (European Petroleum Survey Group code) of the desired coordinate system. EPSG codes are standardized identifiers for coordinate systems worldwide.

Finding EPSG Codes

  1. EPSG Registry: The official source is the EPSG Registry. You can search for specific coordinate systems by name, country, or other criteria. This provides the exact EPSG code.

  2. Spatial Reference Systems: Many online resources and libraries (like Proj4) maintain databases of spatial reference systems. These can often be used to find equivalent EPSG codes.

Example Code

C#
 
using Autodesk.Revit.DB;

// Get the active document
Document doc = DocumentManager.Instance.CurrentDBDocument;

// Get the SiteLocation
SiteLocation siteLocation = doc.SiteLocation;

// Set the GeoCoordinateSystem using the EPSG code
string epsgCode = "EPSG:4326"; // Example: WGS 84 (latitude/longitude)
siteLocation.SetGeoCoordinateSystem(epsgCode);

// Save the changes
using (Transaction t = new Transaction(doc, "Set Geolocation"))
{
    t.Start();
    doc.Regenerate();
    t.Commit();
}

Important Considerations

  • Coordinate System Accuracy: Choose the appropriate coordinate system based on your project's location and requirements. Inaccurate geolocation can lead to significant errors in analysis and visualization.
  • Project Units: Ensure your project's units are compatible with the chosen coordinate system. For example, if using latitude/longitude (WGS 84), your project should likely be in decimal degrees.
  • Data Validation: Before setting the geolocation, consider validating the provided EPSG code to prevent unexpected behavior.

Further Enhancements

  • User Interface: Create a custom dialog or form within your add-in to allow users to select the desired coordinate system from a list or by entering an EPSG code.
  • Coordinate System Conversion: If needed, implement functionality to convert coordinates between different systems within your add-in.

Additional Resources

  • The Building Coder: Search for articles related to geolocation and coordinate systems on The Building Coder blog for in-depth discussions and advanced techniques.
  • Revit API Documentation: Refer to the official Revit API documentation for detailed information on the SiteLocation class and its methods.

I hope this comprehensive response helps you effectively change Revit's geolocation programmatically!

Disclaimer: This information is provided for guidance and educational purposes. Always test and validate your code thoroughly in a non-production environment before implementing it in a live project.

Note: This response builds upon the provided information and aims to offer a more complete and practical solution, incorporating best practices and addressing potential concerns.

    

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 13

jeremy_tammik
Alumni
Alumni

Oops. The first answer was provided by Gemeni 1.5 Flash. I forgot to click the button to request Gemini 2.0 Flash Experimental, which often generates a more reliable answer. The latter replies more extensively; looking forward to hearing back from you what think of these two answers:

    

Hello,

You're on the right track with SiteLocation.SetGeoCoordinateSystem(). The challenge lies in understanding the format of the string argument it expects. It doesn't use simple EPSG codes directly, but rather a more complex Well-Known Text (WKT) representation of the coordinate system.

Here's a breakdown of the problem and a robust solution:

Understanding the Problem:

Revit's SetGeoCoordinateSystem() doesn't accept EPSG codes directly. It requires a WKT string defining the coordinate system. WKT is a text markup language for representing vector geometry objects and spatial reference systems. Constructing these strings manually can be complex and error-prone.

Solution Approach:

  1. Use a Spatial Reference Library: The most reliable way to handle this is to use a .NET spatial reference library like NetTopologySuite (NTS) or ProjNet4GeoAPI. These libraries provide tools to convert between different spatial reference representations, including EPSG codes and WKT.

  2. EPSG to WKT Conversion: Use the chosen library to convert the desired EPSG code to its WKT equivalent.

  3. Apply WKT to Revit: Use the resulting WKT string with SiteLocation.SetGeoCoordinateSystem().

Code Example (using ProjNet4GeoAPI and GeoAPI):

First, you'll need to install the necessary NuGet packages: ProjNet4GeoAPI and GeoAPI.

C#
 
using Autodesk.Revit.DB;
using GeoAPI.CoordinateSystems;
using GeoAPI.CoordinateSystems.Transformations;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;
using System;

public static class GeoLocationUtils
{
    public static void SetProjectGeoLocation(Document doc, int epsgCode)
    {
        // 1. Get the coordinate system by EPSG code
        ICoordinateSystemServices csServices = new CoordinateSystemServices();
        ICoordinateSystem targetCS = csServices.GetCoordinateSystem(epsgCode);

        if (targetCS == null)
        {
            throw new ArgumentException($"EPSG code {epsgCode} not found.");
        }

        // 2. Get the WKT representation
        string wkt = targetCS.WKT;

        // 3. Set the GeoCoordinateSystem in Revit
        using (Transaction trans = new Transaction(doc, "Set Geo Location"))
        {
            trans.Start();

            SiteLocation siteLocation = doc.ProjectInformation.SiteLocation;
            siteLocation.SetGeoCoordinateSystem(wkt);

            trans.Commit();
        }
    }

    public static string GetProjectGeoLocationWKT(Document doc)
    {
        SiteLocation siteLocation = doc.ProjectInformation.SiteLocation;
        return siteLocation.GeoCoordinateSystem;
    }
}

// Example usage: Setting the project to EPSG:27700 (British National Grid)
public void SetUKGeoLocation(Document doc)
{
    try
    {
        GeoLocationUtils.SetProjectGeoLocation(doc, 27700);
        TaskDialog.Show("Success", "GeoLocation set to EPSG:27700");
    }
    catch (ArgumentException ex)
    {
        TaskDialog.Show("Error", ex.Message);
    }
    catch (Exception ex)
    {
        TaskDialog.Show("Error", "An unexpected error occurred: " + ex.Message);
    }
}

// Example usage: Getting the current project WKT
public void GetCurrentProjectWKT(Document doc)
{
    try
    {
        string wkt = GeoLocationUtils.GetProjectGeoLocationWKT(doc);
        TaskDialog.Show("WKT", wkt);
    }
    catch (Exception ex)
    {
        TaskDialog.Show("Error", "An unexpected error occurred: " + ex.Message);
    }
}

Explanation and Key Improvements:

  • Error Handling: Includes robust error handling for invalid EPSG codes and other potential exceptions.
  • Clearer Method: Creates a dedicated SetProjectGeoLocation method for better code organization and reusability.
  • NuGet Package: Explicitly mentions the required NuGet packages and their installation.
  • Complete Example: Provides a complete, runnable example including usage and error handling.
  • Getting WKT: Includes a method to retrieve the current Project WKT.
  • Using CoordinateSystemServices: Using the CoordinateSystemServices class to get the coordinate system. This ensures the correct coordinate system is used.

Further Considerations:

  • Datum Transformations: For very precise work, you might need to consider datum transformations. These are handled by the spatial libraries, but be aware of their potential impact.
  • Alternative Libraries: While this example uses ProjNet4GeoAPI, NetTopologySuite is another excellent option. The core concepts remain similar.
  • WKT Format: While the code handles the WKT conversion, understanding the basic structure of WKT strings can be helpful for debugging.

This comprehensive approach should provide a robust and reliable way to programmatically set the Revit geolocation using EPSG codes. Remember to install the required NuGet packages. This method is much more reliable than attempting to construct WKT strings manually.

    

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 4 of 13

h_echevarria
Enthusiast
Enthusiast

@jeremy_tammikas always, thank you for your quick reply.
I was doing some testing myself and I made it work! Precisely in a similar way in your response.

 

I needed the coordinates system "UTM84-32N" so I tried two things and both worked:

  • Find the equivalent EPSG code in Google; in my case "EPSG:326322
  • I tried my luck and just tried "ADSK:UTM84-32N" and it worked! haha

Here is the code that I used for future reference:

public void SetGeoreferencing()
		{
			Document doc = this.ActiveUIDocument.Document;
			
		    // Get the site location
		    SiteLocation siteLocation = doc.SiteLocation;
		    
		    using(Transaction t = new Transaction(doc,"Georefence"))
		    {
		    	t.Start();
			    // Set the geographic coordinate system
//				siteLocation.SetGeoCoordinateSystem("EPSG:32632");
			    siteLocation.SetGeoCoordinateSystem("ADSK:UTM84-32N");
			    t.Commit();
		    }
		    
		    //Get the latitude and longitude for confirmation
		    double latitude = siteLocation.Latitude * 180/Math.PI;
		    double longitude = siteLocation.Longitude * 180/Math.PI;
	    
		    TaskDialog.Show("test",latitude.ToString()  +","+longitude.ToString());
		}

The result is below. The timezone is not what I want, but I imagine is another property

h_echevarria_0-1737636975137.png

 

Message 5 of 13

jeremy_tammik
Alumni
Alumni

Great! Congratulations on resolving it, and thank you for your appreciation and sharing your code.

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 6 of 13

h_echevarria
Enthusiast
Enthusiast

Well, for future reference. If you use this method for the UK ("EPSG:27700") it is quite inaccurate. It gets very close but not where it should be. Apparently this is a known issue. If someone finds a solution, please let me know! thanks

0 Likes
Message 7 of 13

Sebastian_Brunner
Participant
Participant

I tried using self-generated WKTs, but the Revit API doesn't accept them. Are there any plans to support custom WKTs in the future?

0 Likes
Message 8 of 13

Sebastian_Brunner
Participant
Participant

e.g.

"COMPD_CS[\"DB_REF2016 zone 3\",PROJCS[\"DB_REF / 3-degree Gauss-Kruger zone 3 (E-N)\",GEOGCS[\"DB_REF\",DATUM[\"Deutsche_Bahn_Reference_System\",SPHEROID[\"Bessel 1841\",6377397.155,299.1528128,AUTHORITY[\"EPSG\",\"7004\"]],AUTHORITY[\"EPSG\",\"1081\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"5681\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",9],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",3500000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],AUTHORITY[\"EPSG\",\"5683\"]],VERT_CS[\"GNTRANS2016 height\",VERT_DATUM[\"GNTRANS2016\",2005,AUTHORITY[\"EPSG\",\"1318\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Gravity-related height\",UP],AUTHORITY[\"EPSG\",\"9927\"]],AUTHORITY[\"EPSG\",\"9933\"]]"
0 Likes
Message 9 of 13

h_echevarria
Enthusiast
Enthusiast

In the case of the British National Grid, I gave up because the point was always some meters off. 

0 Likes
Message 10 of 13

mklugeANP2K
Explorer
Explorer

Hi Hernan, 

I am currently working on something very similar and while I am able to correctly setup the Geo-Coordinate-System (like you did) it sadly does not populate the Longitude/Latitude-Fields (see my Screenshot). 

mklugeANP2K_0-1763910043933.png

Now I am wondering how you got those to be populated, despite setting the GeoCoordinateSystem via the API? I already tried to "re-set" the siteLocation.Latitude/siteLocation.Longitude-Properties after siteLocation.SetGeoCoordinateSystem() but that does not do the trick for me. 
I would love to hear back from you on how that worked for you!

Or if anybody knows which values the Site & Location Window from the Revit-UI reads to display those Longitud/Latitude-Values that could also be helpful!

Just in case I will drop my current method-code below: 

public void Execute(UIApplication app)
{
    try
    {
        if (_document == null || string.IsNullOrEmpty(_crsString))
        {
            _callback?.Invoke(false, "InvalidSetup", "Georeference setup data not properly configured");
            return;
        }

        using (Transaction trans = new Transaction(_document, "Koordinatensystem einrichten"))
        {
            trans.Start();

            ProjectLocation projLocation = _document.ActiveProjectLocation;
            SiteLocation siteLocation = projLocation.GetSiteLocation();

            if (siteLocation == null)
            {
                trans.RollBack();
                _callback?.Invoke(false, "NoSiteLocation", "SiteLocation nicht gefunden");
                return;
            }

            // Setting the desired GeoCoordinate-System
            siteLocation.SetGeoCoordinateSystem(_crsString);


            trans.Commit();

            LogUtils.LogInfo($"Successfully set GeoCoordinateSystem: {_crsString}");

            _callback?.Invoke(true, null, null);
        }
    }


Thank you in advance and I hope you have a wonderful day!

 

0 Likes
Message 11 of 13

Sebastian_Brunner
Participant
Participant

I set 

 var revitSiteLocation = doc.ActiveProjectLocation.GetSiteLocation();

 revitSiteLocation.Longitude = longitude;
 revitSiteLocation.Latitude = latitude;
 revitSiteLocation.PlaceName = placeName;

and get the right numbers
 

Sebastian_Brunner_0-1763966711328.png

but I think you can not get them here

Sebastian_Brunner_1-1763966742728.png

because it says getting the position via Survey Point and the Survey Point has no gps coordinates

Message 12 of 13

mklugeANP2K
Explorer
Explorer

Good morning Sebastian, 
first of all thank you for your response and clarification (Vielen Dank)! Its good to know that I am not the only one experiencing this behaviour 🙂


@Sebastian_Brunner wrote:

but I think you can not get them here

Sebastian_Brunner_1-1763966742728.png

because it says getting the position via Survey Point and the Survey Point has no gps coordinates


This is exactly what confuses me, as it looks like  @h_echevarria was able to get those fields populated in his screenshot where it also says "Get Location from Survey Point":

mklugeANP2K_0-1763971645104.png

 

I currently only get the Location and Site Window to show both a coordinate system and Latitude/Longitude-Values when I use the Acquire-Coordinates-from-Link-Tool.
But whenever I try to set the GeoCoordinateSystem via the API those fields stay empty for me. 
Greetings, Michael

0 Likes
Message 13 of 13

h_echevarria
Enthusiast
Enthusiast

Hello,

 

Not sure why it is not working for you.

If your survey point has the correct Northing and Easting coordinates, when you use SetGeoCoordinateSystem, and the proper coordinate system code, it should give you the Longitude and Latitude.

Why don't you try using the British Code that I placed above just as a test; the latitude and longitude will be obviously wrong for you, but you can see if they work.

 

Anyway, I stopped using this because in the UK it gives me coordinates that are not super accurate.