Is there a way to get surfaces volumes from Dynamo?

Hello, I’m trying to create a script that adjust the length of a corridor based on a target volume.
First I was trying to get the volume from a TIN surface, but I had no luck getting that.
Then I thought of creating a solid from the surfaces (existing and proposed) but there is not a “Extract solid from surface” node.
Thanks,

Hi,
you can get solids and volume of the corridor like that:

1 Like

@jduran you could create the solids between surfaces in Dynamo and then extract the volume.
You have to create a watertight solid using the surfaces from the TIN and creating the necessary lateral faces to connect them.
It’s not always straight forward as the surfaces may intersect in multiple places but it can be done.

Hi,
Could it possible to write a node that provides volumes using API (API?

thanks

1 Like

Thanks for your reply, but I’m getting a “empty list” error

@jduran did you extract the solids from the corridor in Civil 3D before running Dynamo?

I didn’t, That’s the issue :slight_smile:

With a Great help from Paolo I Manage to create this Python Scrypt to get the surface volume:

#Get net Volume from volume surface

__author__ = 'Jesus A Duran - jduran@moffattnichol.com'
__version__ = '1.0.0'

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

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

# Create an alias to the Autodesk.AutoCAD.ApplicationServices.Application class
import Autodesk.AutoCAD.ApplicationServices.Application as acapp

# 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 *

# Import references for PropertySets
from Autodesk.Aec.PropertyData import *
from Autodesk.Aec.PropertyData.DatabaseServices import *

# 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

adoc = acapp.DocumentManager.MdiActiveDocument
ed = adoc.Editor
   
def get_tinvolumesurface_Vol(vs_name):
	global adoc
	
	vsid = None
	
	output = {}
	
	with adoc.LockDocument():
		with adoc.Database as db:
			with db.TransactionManager.StartTransaction() as t:
				bt = t.GetObject(db.BlockTableId, OpenMode.ForWrite)
				btr = t.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite)
				
				for oid in btr:
					obj = t.GetObject(oid, OpenMode.ForRead)
					if isinstance(obj, TinVolumeSurface):
						if obj.Name == vs_name:
							vsid = oid
					if vsid is not None:
						break
				
				if vsid is None:
					return "Surface not found"

				vs = t.GetObject(vsid, OpenMode.ForRead)
				props = vs.GetVolumeProperties()
				
				for a in dir(props):
					try:
						output[a] = getattr(props, a)
					except:
						pass
				t.Commit()
	return output["UnadjustedNetVolume"]/27 #Converting to Cu. Yards

OUT = get_tinvolumesurface_Vol(IN[0])

Find the attached Dynamo file, you’ll have to change the “VOL-PG-FILL” for the name of the volume surface you want to get data from.

If you don’t have the volume surface created and you want dynamo to do it, check this Paolo script:
https://forum.dynamobim.com/t/getting-surface-information-from-c3d-using-python/44258/6?u=jduran

Get_Surface Vol.dyn (5.9 KB)

1 Like

You can fix this Eror ?

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)

I tried but still got the error. Can you help me fix the error?
Thank you!

import sys
import clr


# Load the Python Standard and DesignScript Libraries
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 *

# 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

adoc = Application.DocumentManager.MdiActiveDocument
editor = adoc.Editor

def get_tinvolumesurface_Vol(vs_name):
        global adoc

        vsid = None

        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)

                                 for oid in btr:
                                        obj = t.GetObject(oid, OpenMode.ForWrite)
                                        if isinstance(obj, TinVolumeSurface):
                                                if obj.Name == vs_name:
                                                        vsid = oid
                                        if vsid is not None:
                                                break

                                 if vsid is None:
                                        return "Surface not found"

                                vs = t.GetObject(vsid, OpenMode.ForWrite)
                                props = vs.GetVolumeProperties()

                                for a in dir(props):
                                        try:
                                                output[a] = getattr(props, a)
                                        except:
                                                pass
                                t.Commit()
        return output

OUT = get_tinvolumesurface_Vol(IN[0])```

There is an issue with the indentation. Try backspacing the code and using tab to get to the correct indentations.

I tried but still got the error.

This works for me:
VolumeSurface.dyn (7.4 KB)

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

# 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 *

# 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.
vs_name = IN[0]

adoc = Application.DocumentManager.MdiActiveDocument
editor = adoc.Editor

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)
            
            for oid in btr:
                obj = t.GetObject(oid, OpenMode.ForWrite)
                
                if isinstance(obj, TinVolumeSurface) and obj.Name == vs_name:
                    volumeSurface = obj
            
            props = volumeSurface.GetVolumeProperties()
            
            
            adjustedCutVolume = "Adjusted Cut Volume = " + str(props.AdjustedCutVolume)
            adjustedFillVolume = "Adjusted Fill Volume = " + str(props.AdjustedFillVolume)
            adjustedNetVolume = "Adjusted Net Volume = " + str(props.AdjustedNetVolume)
            
                    
            
            # 
            #

            # Commit before end transaction
            t.Commit()
            pass

# Assign your output to the OUT variable.
OUT = adjustedCutVolume, adjustedFillVolume, adjustedNetVolume

If you just want the integers and not strings then you can just remove the string addition and the “str()” command. If you add dir(props) to “OUT”, you can see all available properties.

2 Likes

Thank you very much !

1 Like

FYI there are nodes for this in the Camber package starting in v4.0.0.

4 Likes

como obtener el volumen de una superficie, a una elevación definida?

Please edit with google translate to english.

1 Like

how to obtain the volume of a surface, at a defined elevation? could this be done with dynamo?
the normal thing is to compare 2 surfaces, but if after that, that total surface volume, I would like to know the volume at an elevation that I indicate. it could be using a flat surface that I could move in elevation “Z”, but to obtain the volume at that elevation level of that third surface (I leave image for better understanding).

Looks like you need to create a trimmed version of surface 2 and trimmed version of surface 3 and paste those into a surface 4. And compare that with surface 1 as a volume surface.

I see your intent is to create a combined surface that takes the lower elevation triangles. Next time im at my computer I can see if there is a way to achieve this.