Hello guys, what i’m trying to achieve rn is exactly the topic name, batch creating volumetric surfaces between my already existing TINsurfaces. I’ve searched the forum and the closest I got from it was this post: Getting surface information from C3D using Python - #5 by jduran
but i can’t seen to do this operation for multiple inputs! any help around this issue?
Hi, are you looking for solution how to repeat one function for multiple inputs stored in a list? I hope this can help you Create Profile - #26 by Drbohlav. Or google "For Loop“ and “List Comprehensions”.
Based on the topic you mentioned in the first post I created the following:
`#Get net Volume from volume surface
__author__ = 'Stan Bouwens'
__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 *
from Autodesk.AutoCAD.BoundaryRepresentation 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, base_surf, top_surf, vs_style, boundaries):
global adoc
if not isinstance(base_surf, list):
base_surf = [base_surf]
if not isinstance(top_surf, list):
top_surf = [top_surf]
if not isinstance(vs_name, list):
vs_name = [vs_name]
base_surf_id = []
top_surf_id = []
vsid = []
vs = []
props = []
dict = {}
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)
#get surfaces based on surface handle
for oid in btr:
obj = t.GetObject(oid, OpenMode.ForRead)
if isinstance(obj, TinSurface):
for b_handle in base_surf:
if obj.Handle.ToString() == b_handle:
base_surf_id.append(oid)
for t_handle in top_surf:
if obj.Handle.ToString() == t_handle:
top_surf_id.append(oid)
if len(base_surf_id+top_surf_id) is len(base_surf+top_surf):
break
if len(base_surf_id) is 0 or len(top_surf_id) is 0:
return "Surface is not a TIN surface"
for a in list(zip(vs_name, base_surf_id , top_surf_id)):
vsid = (TinVolumeSurface.Create(a[0], a[1], a[2], vs_style))
vs.append(t.GetObject(vsid, OpenMode.ForWrite))
#create bounded volume surfaces and append properties in dictionary
for j, k in zip(vs, boundary_p3dcol_split):
j.Rebuild()
vs_props = j.GetVolumeProperties()
maintask = {'Cut': int(vs_props.AdjustedCutVolume), "Fill": int(vs_props.AdjustedFillVolume), "Net": int(vs_props.AdjustedNetVolume), "Task name":j.Name}
output.append(maintask)
#delete the volume surfaces to prevent mess in Civil3D toolspace
j.Erase()
t.Commit()
return output
OUT = get_tinvolumesurface_Vol(IN[0], IN[1], IN[2], IN[3], IN[4])
Not the most cleanest code but it is functional. It is however required to have some basic knowledge of python to start with this .
Hi @stabouw, sorry for the late reply. I used your script and adapted it for my needs (I needed the volumetric surfaces created to make solids from them, exclusively) and it works perfectly.
When I use this script to retrieve volume of a iteratively generated TinVolumeSurface based on a corridor, as the subassembly parameters of the corridor varies. I met tow problems:
“TinVolumeSurface.Create Method (surfaceName, baseSurfaceId, comparisonSurfaceId, styleId)” styleId is The ObjectId of the SurfaceStyle for the TinVolumeSurface, but I don’t know how to get a styleId.
I want to get the volume info of the generated TinVolumeSurface every time the associated corridor is updated, how can I connect these two things, the corridor updates and create & retrieve info of the TinVolumeSurface?
Thanks very much! I tried as your advice, it works.
from Autodesk.Civil.ApplicationServices import *
cdoc = CivilApplication.ActiveDocument
rst = []
for style in cdoc.Styles.SurfaceStyles:
rst.append(style)
OUT = rst
For selecting a surface style I used this Python code, the output is dictionary of all available surface styles.
"""
Copyright 2019 Autodesk, Inc. All rights reserved.
This file is part of the Civil 3D Python Module.
"""
__author__ = 'Paolo Emilio Serra - paolo.serra@autodesk.com'
__copyright__ = '2019'
__version__ = '1.0.0'
import clr
# Add Assemblies for AutoCAD and Civil 3D APIs
clr.AddReference('acmgd')
clr.AddReference('acdbmgd')
clr.AddReference('accoremgd')
clr.AddReference('AecBaseMgd')
clr.AddReference('AecPropDataMgd')
clr.AddReference('AeccDbMgd')
clr.AddReference('AeccPressurePipesMgd')
clr.AddReference('acdbmgdbrep')
clr.AddReference('System.Windows.Forms')
clr.AddReference('Civil3DNodes')
# Add standard Python references
import sys
sys.path.append('C:\Program Files\IronPython 2.7\Lib')
import os
import math
# Add references to manage arrays, collections and interact with the user
from System import *
from System.IO import *
from System.Collections.Specialized import *
from System.Windows.Forms import MessageBox
# 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 for Civil 3D
from Autodesk.Civil.ApplicationServices import *
from Autodesk.Civil.DatabaseServices import *
# Import references for Dynamo for Civil 3D
from Autodesk.Civil.DynamoNodes import Alignment as DynAlignment
adoc = acapp.DocumentManager.MdiActiveDocument
ed = adoc.Editor
civdoc = CivilApplication.ActiveDocument
def get_surface_styles():
"""
This method creates gets the alignment style names in the current document.
:return: A list of alignment style names
"""
surfacestyle_id = []
surfacestyle_name = []
output = {}
# Get the active document in the AutoCAD session:
with adoc.LockDocument():
with adoc.Database as db:
with db.TransactionManager.StartTransaction() as t:
styleCol = civdoc.Styles.SurfaceStyles
for i in styleCol:
styleObj = t.GetObject(i, OpenMode.ForRead)
surfacestyle_name.append(styleObj.AcadObject.Name)
output = dict(zip(surfacestyle_name, styleCol))
return output
# Output
OUT = get_surface_styles()
Running a dynamo script automatically is something which as far as I know cannot be done in Dynamo itself. You could probably pick up corridor updates in the Civil .NET API and then trigger the dynamo script, but I have no experience with that.
When I tried your script to get volume of a TinVolumeSurface, I encountered a problem,
I am not able to get these ID variables of “vs_name, base_surf, top_surf, vs_style”, could you give some advice?
Thanks a lot.