Civil 3D Tin Volume Surface Color Range

I haven’t used the code yet but from the images there is a function working on a given surface and the surface is hardcoded into the output, meaning that the function is being called by “Surface1” (see the last line) No inputs defined in the code but you should be able to modify this so it is done with any surface you define

1 Like

Can you post full snippets of your code? or the txt file of the full finalized code. Thanks!

Reviving this old thread here. What node is plugging into the Python node? Can anyone post a screenshot of their full node tree that goes with this code.

1 Like

All that’s going into the python node is a surface name:
Capture

1 Like

Sorry, I’ve been away from the forum for a while. Work has just been too busy. Here is a txt of the code:
surface color ranges.txt (2.4 KB)

2 Likes

I’d like a step-by-step as well, haha… Dynamo and Python-in-Dynamo has been mostly a self-teaching process (with great help from the reference material and advice mainly from this forum). There just isn’t a lot out there with respect to Civil 3D.
As for the Python node in question, it simply needs a surface name (String) as the input. See my reply to dylanlisec below.

Ok, so I took the basic code that @jameshitt provided and switched a few things around. The biggest change was separating the color scheme for cut and fill (red and green) volumes. There are now three inputs for the user, the surface, the size of the elevation step of the color bands, and the survey precision. This allows for an element of “play” depending how accurate the surveyor is willing to say the survey is.

I also started getting into exporting the color scale of the volume surface to excel. This would allow the user to bring the excel table back to CAD to use in sheetspace exhibits as a legend. The tricky thing is, I’m not sure how to approach creating the color portion of the legend. Right now I’m using a VBA module called myRGB provided at the link here. This isn’t really that automated. In the meantime I’ll be trying to figure out how to get a table directly into the modelspace with the correct colors.

Volume Surface Color Banding.txt (4.1 KB)
Volume Surface.dyn (21.1 KB)
myRGB.txt (546 Bytes)


HI
TRY

# Load the Python Standard and DesignScript Libraries
import sys
import clr
import math

# Add Assemblies for AutoCAD and Civil3D
clr.AddReference('AcMgd')
clr.AddReference('AcCoreMgd')
clr.AddReference('AcDbMgd')
clr.AddReference('AecBaseMgd')
clr.AddReference('AecPropDataMgd')
clr.AddReference('AeccDbMgd')

# Import references from AutoCAD
from Autodesk.AutoCAD.Runtime import *
from Autodesk.AutoCAD.ApplicationServices import *
from Autodesk.AutoCAD.EditorInput import *
from Autodesk.AutoCAD.DatabaseServices import *
from Autodesk.AutoCAD.Geometry import *
from Autodesk.AutoCAD.Colors import *

from System import Array

# Import references from Civil3D
from Autodesk.Civil.ApplicationServices import *
from Autodesk.Civil.DatabaseServices import *

# The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN[0]
interval = IN[1]
surveyprecision = IN[2]

adoc = Application.DocumentManager.MdiActiveDocument
cdoc = CivilApplication.ActiveDocument
editor = adoc.Editor

def set_surface_analysis(surface_name,interval,surveyprecision):
	
	global adoc
	global cdoc

	with adoc.LockDocument():
		with adoc.Database as db:

			with db.TransactionManager.StartTransaction() as t:
            	# Place your code below
           		# 
            	#
				bt = t.GetObject(db.BlockTableId, OpenMode.ForWrite)
				btr = t.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite)
			
				surface = None
				for oid in cdoc.GetSurfaceIds():
					obj = t.GetObject(oid, OpenMode.ForRead)
					if obj.Name == surface_name:
						surface = obj
						break
					
				if surface is None:
					return False
				
				gp = surface.GetGeneralProperties()
				minel = gp.MinimumElevation
				maxel = gp.MaximumElevation
				#minelf = minel - (minel - (math.floor(minel / interval) * interval))
				minelf = int(minel)
				maxelc = int(maxel)
				#maxelc = ((math.ceil(maxel / interval) * interval) - maxel) + maxel
				minelfn = int(minelf)
				maxelcn = int(maxelc)
				
				upperprecision = 0 + surveyprecision
				lowerprecision = 0 - surveyprecision
				saed = []
			
				#interval = .5
				
				redsteps = int(((lowerprecision - minelf) / interval)+1)
				greensteps = int(((maxelc - upperprecision) / interval)+1)
				
				i = 0
				n = 0
				upperbound = 0
				lowerbound = 0
				table = []
				while upperbound >= minelf:
						lowerbound = lowerprecision - interval - i
						upperbound = lowerbound+interval
						g = ((250/redsteps)*n)
						b = ((250/redsteps)*n)
						saed.append(SurfaceAnalysisElevationData(lowerbound, upperbound, Color.FromRgb(250,g,b)))
						i += interval
						n += 1
						table.append([int(lowerbound),int(upperbound),250,g,b])

				else:
					i = 0
					n = 0
					while lowerbound <= maxelc:
						lowerbound = upperprecision + i
						upperbound = lowerbound + interval
						r = ((250/greensteps)*n)
						b = ((250/greensteps)*n)
						saed.append(SurfaceAnalysisElevationData(lowerbound, upperbound, Color.FromRgb(r,250,b)))
						i += interval
						n += 1
						table.append([int(lowerbound),int(upperbound),r,250,b])
						
				
				saed.append(SurfaceAnalysisElevationData(lowerprecision, 0, Color.FromRgb(255,190,92)))
				table.append([int(lowerprecision),0,255,190,92])
				
				saed.append(SurfaceAnalysisElevationData(0, upperprecision, Color.FromRgb(236,247,29)))
				table.append([0,int(upperprecision),263,247,29])
				sorttable = table.sort()
				
				surface.Analysis.SetElevationData(Array[SurfaceAnalysisElevationData](saed))
			
			
            	# Commit before end transaction
				t.Commit()
	
	return table

# Assign your output to the OUT variable.
OUT = set_surface_analysis(IN[0],IN[1],IN[2])

FOR EXPORT TO EXCEL SEE THIS IS

1 Like

Hi,

I am new to python and how to apply this code to the surface.

Is there an updated version of this code that works in the new 2024 Dynamo/CPython3 ?

Sorry, there is no update ALL
CAN YOU Continuation By code conversion

# Load the Python Standard and DesignScript Libraries
import sys
import clr
import math

# Add Assemblies for AutoCAD and Civil3D
clr.AddReference('AcMgd')
clr.AddReference('AcCoreMgd')
clr.AddReference('AcDbMgd')
clr.AddReference('AecBaseMgd')
clr.AddReference('AecPropDataMgd')
clr.AddReference('AeccDbMgd')

# Import references from AutoCAD
from Autodesk.AutoCAD.Runtime import *
from Autodesk.AutoCAD.ApplicationServices import *
from Autodesk.AutoCAD.EditorInput import *
from Autodesk.AutoCAD.DatabaseServices import *
from Autodesk.AutoCAD.Geometry import *
from Autodesk.AutoCAD.Colors import *

from System import Array

# Import references from Civil3D
from Autodesk.Civil.ApplicationServices import *
from Autodesk.Civil.DatabaseServices import *

# The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN[0]
interval = IN[1]
surveyprecision = IN[2]

adoc = Application.DocumentManager.MdiActiveDocument
cdoc = CivilApplication.ActiveDocument
editor = adoc.Editor

def set_surface_analysis(surface_name,interval,surveyprecision):
        global adoc
        global cdoc


        outputD = {}
        output = []

        with adoc.LockDocument():
                with adoc.Database as db:
                        with db.TransactionManager.StartTransaction() as t:
                                 bt = t.GetObject(db.BlockTableId, OpenMode.ForWrite)
                                 btrID = bt.get_Item("*Model_Space")
                                 btr = t.GetObject(btrID, OpenMode.ForWrite)
                                 
                                 #sampleLineId = sampleLines[0].InternalObjectId
                                 #obj = t.GetObject(sampleLineId, OpenMode.ForWrite)
                                 surface = None
                                 for oid in cdoc.GetSurfaceIds():
                                     obj = t.GetObject(oid, OpenMode.ForRead)
                                     if obj.Name == surface_name:
                                        surface = obj
                                        break
                                 if surface is None:
                                    return False
                                    
                                 gp = surface.GetGeneralProperties()
                                 minel = gp.MinimumElevation
                                 maxel = gp.MaximumElevation
                                 
                                 output.append([minel , maxel ])
                                 
                                 
                                 t.Commit()

                             
        return output

OUT = set_surface_analysis(IN[0],IN[1],IN[2])

1 Like

Thank You for sending this. I see that your code states the minimum and maximum value for a volume surface. I am seeking to set the elevation ranges in the Surface Properties > Analysis Tab and then set those ranges to particular RGB color values. Do you know of any ways I could modify the code you provided to accomplish this?

use Visual Studio Code

00

1 Like

I noticed in the Civil 3D API documentation they have a class called:

SurfaceAnalysisElevationData.Scheme Property

Gets or sets the color value for the elevation range. This is an AutoCAD Color object.
With an example in C#:
public Color Scheme { get; set; }

How would we convert this to code in the Python node in Dynamo?

https://help.autodesk.com/view/CIV3D/2024/ENU/?guid=41b4d8dc-3aa3-b45a-b8fa-da0593621c6a

I didn’t understand you well
Can you explain more? What you want to do


In Civil 3D, surfaces can display elevations as colors. If you right click on a surface and select “Surface Properties” > Analysis Tab > Elevations you can find the elevations as shown in the included image. Instead of adjusting these colors using the surface properties graphical user interface window, I want to use a Python node in Dynamo to adjust these color values. I was hoping to use the SurfaceAnalysisElevationData.Scheme Property from the Civil 3D 2024 API. Found here:
https://help.autodesk.com/view/CIV3D/2024/ENU/?guid=41b4d8dc-3aa3-b45a-b8fa-da0593621c6a
My question is:
What is the correct way to implement the API property (explained at the link above) into a Dynamo Python node?
Or in other words:
What is the correct Python code to adjust a Civil 3D surface color range using the API?

like this , but it is not change color range I do not know the reason

1 Like

I use the Camber Surface.ElevationAnalysis node, works like a charm.

This accomplishes what I need. Thanks!

Thank You! This provides me with an option to accomplish what I need.