Ok, I have results for 3 methods of building the requested surface.
The first is directly in Civil 3D. It’s seven clicks and some typing, and will produce a workflow that will be editable by everyone else after the fact, and maintains some degree of association over time. Surface section of prospector, new surface, definition, contours, add, name it, select and hit return.
Second and third were developed with this graph:
Both of these push a polygon for each triangle of the tessellation, not surfaces. As such you won’t be able to project onto them or whatnot. If you wanted to convert to surfaces you could, but the built in tools don’t allow it. Also any change in the curves would break the tessellation so you’d have to delete everything and build it over again or manage your element bindings (and if users don’t know Civil 3D they won’t learn enough Dynamo for managing bindings). As such using the Civil 3D tools is my recommended workflow.
the Python node's contents
########################################
############## Properties ##############
########################################
__author__ = 'Jacob Small'
__version__ = '0.1.0'
__description__ = "Uses Dynamo's display pipeline to tessellate a surface into triangles"
__DynamoBuilds__ = "4.1"
__ReleaseNotes__ = "POC only, not for production use"
__Dependancies__ = "none"
__Copyright__ = "2026, Autodesk Inc."
__license__ = "Apache 2"
########################################
### Configure the Python environment ###
########################################
### standard imports ###
import sys #add the sys class to the Python environment so we can work with the sys objects
import clr #add the CLR (common language runtime) class to the Python environment so we can work with .net libraries
### basic Dynamo imports ###
clr.AddReference('ProtoGeometry') #add the Dynamo geometry library to the CLR
from Autodesk.DesignScript import Geometry as DG #add the Dynamo geometry class using the alias DG, to ensure no overlap between class calls in Revit or Dynamo
import Dynamo.Visualization as DV #import the Dynamo visualization class so we can use it to tessellate
#########################################
###### Global variables and inputs ######
#########################################
srfs = IN[0] #data from the IN[0] port of the Dynamo environment
if not isinstance(srfs, list): srfs = [srfs] #ensure the surfaces are a list
srfs = [i for i in srfs if isinstance(i, DG.Surface)] #remove any non surfaces from the input list
srfsOut = IN[1] #boolean control for returning surfaces (if true) or polygons (if false)
if not srfsOut: srfsOut == False #enforce a false value for srfsOut if none provided
OUT = [] #set OUT to an empty list into which we'll append the results
#########################################
############## Code begins ##############
#########################################
for srf in srfs: #for each surface
### extract basic properties of the surface ###
nrml = srf.NormalAtParameter(0.5,0.5) #the normal of the surface
perim = DG.PolySurface.ByJoinedSurfaces([i.Extrude(nrml) for i in srf.PerimeterCurves()]) #the perimeter curves of the surface as a polysurface
### build the render package to tessellate the Dynamo geometry ###
renderPackageFactory = DV.DefaultRenderPackageFactory() #buld a render package factor
renderPackage = renderPackageFactory.CreateRenderPackage() #create the render package
tessellationParams = renderPackageFactory.TessellationParameters #get the tessellation parameters
tessellate = srf.Tessellate(renderPackage, tessellationParams) #tessellate the surface
### get the verticies from the tessellation results
verts = list(renderPackage.MeshVertices) #get the verticies from the tessellation in the render package
verts = [verts[i:i+3] for i in range(0, len(verts), 3)] #slice the tessellation into tripples
verts = [DG.Point.ByCoordinates(i[0],i[1],i[2]) for i in verts] #generate points from the tripples
### convert the verticies into triangles
tris = [verts[i:i+3] for i in range(0, len(verts), 3)] #slice the verts into tripples
tris = [DG.Polygon.ByPoints(i) for i in tris] #generate polygons from the tripples
if srfsOut: tris = [i.Patch() for i in tris] #generate surfaces from the polygons if srfsOut is True
OUT.append(tris) #append the tris list to the OUT list so it is returned to the Dynamo environment after the Python finishes executing
if len(srfs) == 1: OUT = OUT[0] #set OUT to the first item in the list if only one item was processed
The output of the mesh resulted in this:
Elevation and extents wise this is closer than what C3D produced, but it isn’t something you can edit readily, and things fall apart at the ends - perhaps a geometry scaling bug, a geometry accuracy issue on the mesh, or a bug with Civil 3D conversion.
The output of the tessellation resulted in this:
As far as I can tell, every end point of the result falls on one of the two source curves or midway between the two, so it would be the most accurate of the three.
That said, the built in tools in Civil are going to be a better option here - it isn’t THAT much to learn and they’ll have to spend awhile learning the limits of the Dynamo workaround and deal with that fallout as well.