SetGeoCoordinateSystem

SetGeoCoordinateSystem

h_echevarria
Contributor Contributor
654 Views
8 Replies
Message 1 of 9

SetGeoCoordinateSystem

h_echevarria
Contributor
Contributor

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)
655 Views
8 Replies
Replies (8)
Message 2 of 9

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 9

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 9

h_echevarria
Contributor
Contributor

@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 9

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 9

h_echevarria
Contributor
Contributor

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 9

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 9

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 9

h_echevarria
Contributor
Contributor

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

0 Likes