Civil 3D Grid to Ground Surface Conversion - Unexpected elevation values

This is a lengthy explanation so I’ll do my best to break it down as much as I can, but in summary I was trying to develop a Dynamo graph that translates a Civil 3D surface between grid and ground coordinates using a surveyor provided combined factor.

My first attempt was one where I simply modified the surface vertices and got very fast results, but I was getting different triangulation between the two surfaces, so I abandoned that approach. Instead, I built a Python node that does the following:

  • Extract the triangles from the original surface
  • Get the XYZ of each of the three points from those triangles
  • Scale the XY of those points
  • Create 3D Faces using those scaled points
  • Add those faces to a new surface
  • Extracted the border from the original surface
  • Extracted the XYZs of the points that make up that boundary
  • Scaled the XY of those points
  • Added those scaled points to the boundary definition of the transformed surface

At this point, when I ran it on a test surface, I got the following results below.

You can see that the total number of points and triangles are identical, and the max elevation is the same, but the minimum and mean are different which is neither the desired nor the expected outcome. If all Z elevations between the two surfaces are the same, I’d expect that the min, mean, and max elevations would be exactly the same. This was performed on a surface that is included with Civil 3D.

As a second test I ran it on the surface from an actual project and again the total number of points and triangles are identical, but this time the min and max elevations are identical, but the mean is different, once again indicating that one or more points are different.

I couldn’t understand what I was doing wrong, so I then output the data XYZ data from both the original and transformed surface into text files. I then used Python to analyze the point data and the script I wrote seems to indicate that the two surfaces have the identical number of Z points and elevations. I’ve tried everything I can think of, so I wanted to have someone else review this and see if it’s related to some internal rounding issue or from an incorrect assumption I made about how the data is being generated in Dynamo (or how I used the API which I am only beginning to learn).

I’ve attached the Dynamo graph but couldn’t upload the C3D drawing, but the sample drawing I made simply used the XML file “C:\Program Files\Autodesk\AutoCAD 2021\C3D\Help\Civil Tutorials\Existing Ground Surface.xml” to do testing.

Grid to Ground Surface Transform.dyn (14.6 KB)

1 Like

Hi @steven.v.costa,

I tested this out and am getting the same results that you are. I went through the code pretty closely and can’t seem to find where the discrepancies are coming from. The only other thing I can offer is a different workflow:

  1. Create a block with the surface, making sure “Scale uniformly” is unchecked

  2. Change the X and Y scale factors for the block using the combined factor

  3. Explode the block

In my tests, the resulting surface has all the same values for min, max, and mean elevations. What I just outlined is a manual approach, but you could maybe try replicating the steps in Dynamo to create the block table record, add the surface object, scale using a coordinate system, and then explode.

1 Like

Hi @mzjensen,

Well, that is a much simpler workflow! Glad that you were able at least to verify that the python node seemed sound but I’ll give the workflow you suggested a go and see how it works out. Thanks!

1 Like

For scaling a BlockReference via Dynamo Scale Existing Block by Block Attribute

1 Like

@mzjensen I was able to work out a python node that executed what you recommended and it looks to be correct, so thanks again! I was definitely over-complicating the process. I’m going to run it by our geomatics team for verification, but strictly from a Civil 3D perspective, the surface elevations seem identical.

Thanks Paolo! Didn’t know about that node, so I ended up adding it in a Python node, but will definitely make use of that in the future.


Perhaps not as sophisticated but… if you can extract the LandXML, you can just edit the values of the coordinates and write a new file.


Wow, this is great, thank you Paolo. I’m going to try and implement this as well, but even beyond this use case, I can picture this type of workflow being extremely useful.

Glad to hear!