Using the node in the title of this post to extract points by shape code so I can ultimately create solids using loft. For some reason this node does not return all the points associated with the shape code in C3D. When creating solids in C3D it does not have the same issue where points are missing. Anyone else having this issue? Images below show geometry preview in Dynamo and the assembly in C3D (getting shape in solid gray in this image)
I’m assuming you already checked this, but worth asking anyway. Is the geometry scaling set to medium?
Yes set to medium. A work around might be to get what I need from the AppliedAssemblies in Baseline using .net. Was hoping to avoid this to cut down effort on my part. This issue persists in C3D 2022 and 2023.2. Will share if the points obtained in Python are the same as what dynamo is getting.
So when using Python I’m getting all the points. I’ve included the code so no one else needs to spend 3 hours+/- of their day fumbling through this . Perhaps Autodesk can address this in a future build of Dynamo for Civil 3d? @solamour.
# Load Python standard libraries
import clr
# Add Assemblies for AutoCAD, Civil 3D and Dynamo APIs
clr.AddReference('acmgd')
clr.AddReference('acdbmgd')
clr.AddReference('accoremgd')
clr.AddReference('AecBaseMgd')
clr.AddReference('AecPropDataMgd')
clr.AddReference('AeccDbMgd')
clr.AddReference('acdbmgdbrep')
clr.AddReference('System.Windows.Forms')
clr.AddReference('ProtoGeometry')
# Add standard Python references
import sys
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 *
# Import references for Civil 3D
from Autodesk.Civil.ApplicationServices import *
from Autodesk.Civil.DatabaseServices import *
# 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 Dynamo
from Autodesk.DesignScript.Geometry import Point as DynPoint, Line as DynLine
# Declare global variables
ac_app = Application
a_doc = ac_app.DocumentManager.MdiActiveDocument
ed = a_doc.Editor
c_doc = CivilApplication.ActiveDocument
# Functions
def ex_traceback():
"""
This method writes the full Python stack trace to the AutoCAD commandline.
"""
global ed
str_1 = "\n"
str_2 = "================================================================="
import traceback
result = [str_1, str_2, str_1, traceback.format_exc(), str_2, str_1]
for r in result:
ed.WriteMessage(r)
# ed.WriteMessage(str_2)
def invalid_obj_message(obj, str_1):
"""
Formatted string for notifying user, typically used on AutoCAD/C3D
entities.
:param obj: object
:param str_1: custom message to user
"""
return "{}{}{}{}{}{}".format(
"\n", obj.GetType().Name, " (Name=",
obj.Name, "), ", str_1
)
def pts_by_shape_code_at_nearest_station(dyn_corridor, baseline_name):
"""
This method replicates what Dynamo for Civil 3D does with a similarly name method. It has been created to address
the limitations of Dynamo not getting all the Points associated with a Shape within the context of a Civil 3D
Corridor.
@param dyn_corridor: Dynamo Corridor
@param baseline_name: str
@return: None
"""
global a_doc
global ed
global c_doc
result = []
if dyn_corridor is None or baseline_name is None:
return
try:
# Get the active document in the AutoCAD session:
with a_doc.LockDocument():
with a_doc.Database as db:
with db.TransactionManager.StartTransaction() as t:
# Get the Corridor
corr = t.GetObject(dyn_corridor.InternalObjectId, OpenMode.ForRead)
# Get the Baseline by Name
# bl = corr.Baselines.Item(baseline_name)
bl_coll = corr.Baselines
bl = bl_coll.get_Item(baseline_name)
# If the Baseline isn't built
if not bl.NeedsProcessing:
ed.WriteMessage(
invalid_obj_message(
bl, "cannot be read as it is set to not be built."
)
)
return
# Get the stations
stations = bl.SortedStations()
if stations.Length <= 1:
ed.WriteMessage("Baseline only has <= 1 stations.")
return
coll_of_coll_of_pt_coll = []
# Iterate through each station
for s in stations:
# Get the AppliedAssembly
aa = bl.GetAppliedAssemblyAtStation(s)
# Get the collection of CalculatedShapes that have a particular code
cs_coll = aa.GetShapesByCode("Deck")
if cs_coll.get_Count == 0:
continue
# Declare variable
coll_of_pt_coll = [] # Collection of Point Collections
# Iterate through the CalculatedShapesCollection
for cs in cs_coll:
pt_coll = [] # Point Collection
pt_coll_strs = [] # Point Collection as str representations
# Get the CalculatedLinksCollection
cl_coll = cs.CalculatedLinks
# Iterate through each CalculatedLink
for cl in cl_coll:
# Get the CalculatedPointsCollection
cp_coll = cl.CalculatedPoints
# Iterate through each CalculatedPoint
for cp in cp_coll:
# Create a Dynamo Point and get its' string repr
pt3d = cp.XYZ # Point3d
pt = DynPoint.ByCoordinates(pt3d.X, pt3d.Y, pt3d.Z)
pt_str = str(pt)
if pt_str not in pt_coll_strs:
pt_coll.append(pt)
pt_coll_strs.append(pt_str)
coll_of_pt_coll.append(pt_coll)
coll_of_coll_of_pt_coll.append(coll_of_pt_coll)
result = coll_of_coll_of_pt_coll
except:
ex_traceback()
return result
# Output
OUT = pts_by_shape_code_at_nearest_station(IN[0], IN[1])
That seems really useful. One question: what do you refer as Dynamo Corridor? What node gives me that? Maybe I’m missing something. Hope you can help. Thanks.
hi Alex,
would you mind to share your sample dwg and script so that we can investigate into it?
DynCorridor is a Corridor object that Dynamo for C3D provides out of the box, not to be confused with a Corridor as defined in the host application (Autodesk.Civil.DatabaseServices). Sorry can’t share the sample drawing.