Looping through a function for multiple inputs in a list

I’m looking for a bit of help in repeating a function for a different object each time.

I’ve essentially been messing around trying Python and the C3D API. I have successfully created a python script which creates an alignment from a selected polyline using the code below. However, I’m having trouble inputting multiple Polylines from a list and looping through these to create multiple alignments. The code I have attached below works but only creates one alignment before returning an error.

Any help with this one would be really appreciated !

# 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 (global variables).

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


def MultipleAlignFromOb(Pl):

#Lock the document down
with adoc.LockDocument():
    #provide access to the drawing database and set it to db
    with adoc.Database as db:
        #from the drawing database open a transaction and set it as t
        with db.TransactionManager.StartTransaction() as t:
            # Place your code below
            # assign bt to grabbing the block table id and ask to write to it           
            bt = t.GetObject(db.BlockTableId, OpenMode.ForWrite)
            #assign btr to grabbing the block tablre record from block table model space and ask to write to it
            btr = t.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite)
            
            #for the object ID(Polyline) inside the block table record
            for Pl in btr:
                #retreive all objects from the transaction and ask to read them. Set it to ObID
				ObID = t.GetObject(Pl, OpenMode.ForRead)
				
            CivilDocument = CivilApplication.ActiveDocument
            
            
            plops = PolylineOptions()
            plops.AddCurvesBetweenTangents = False
            plops.EraseExistingEntities = False
            plops.PlineId = Pl
            
            
            Alignment.Create(CivilDocument, plops, "New Alignment", "", "0", "Design Style LWT", "Standard")
            # Commit before end transaction
            #t.Commit()
            t.Commit()
            pass
return MultipleAlignFromOb

Pl = IN[0]
# Assign your output to the OUT variable.
OUT = [MultipleAlignFromOb(Pl) for i in zip(Pl)]

Hi Elliot,

i dont know much about the c3d APi but it might be this part in the code

 #for the object ID(Polyline) inside the block table record
        for Pl in btr:
            #retreive all objects from the transaction and ask to read them. Set it to ObID
			ObID = t.GetObject(Pl, OpenMode.ForRead)
			
        CivilDocument = CivilApplication.ActiveDocument
        
        
        plops = PolylineOptions()
        plops.AddCurvesBetweenTangents = False
        plops.EraseExistingEntities = False
        plops.PlineId = Pl
        
        
        Alignment.Create(CivilDocument, plops, "New Alignment", "", "0", "Design Style LWT", "Standard")
        # Commit before end transaction
        #t.Commit()
        t.Commit()

you run a for loop to get a Pl item and then outside the for loop you add the Pl item in the plops object and try to create a new object. Pl will be only one item at that point ( the last one from the for loop), also you add the Pl as argument for the plops.PlineId, you might need to ad the ObID there.

if you want to process them all try:

 #for the object ID(Polyline) inside the block table record
        CivilDocument = CivilApplication.ActiveDocument
        for Pl in btr: #startloop itterate over all Polylines
            #retreive all objects from the transaction and ask to read them. Set it to ObID
			ObID = t.GetObject(Pl, OpenMode.ForRead)
            plops = PolylineOptions()
            plops.AddCurvesBetweenTangents = False
            plops.EraseExistingEntities = False
            plops.PlineId = Pl #might need ObID  instead of the Pl object**
            Alignment.Create(CivilDocument, plops, "New Alignment", "", "0", "Design Style LWT", "Standard")
        # Commit before end transaction
        #t.Commit()
        t.Commit()
1 Like

Thanks for your help Martin - that makes sense now.

However, I have amended my code to your suggestion above and changed the Polyline object to ObID and I’m now receiving the error below which seams to recognise the ObjectID as a Site ID rather than an ObjectID. I appreciate this is probably more a C3D API orientated question now so perhaps @Paolo_Emilio_Serra1 may be able to help out with this one !

Cheers!

@elliotgr2010 the Python syntax may be correct but the logic is off, this can be dangerous as you can compromise your documents. In the future try to have a better understanding.
At line 47 you are looping through the Block Table Record and you are processing each ObjectId you encounter…what happened is that you found a Site and passed its ObjectId to create an Alignment instead of the one associated to a Polyline in the drawing (the logic you implemented is not even considering the input that you are passing to the Python Script node!).
Also, if you want to run this on multiple Polylines, make sure the Alignment name is unique.

Thanks a lot for your reply @Paolo_Emilio_Serra1 ! I’m still struggling to get my head around looping through objects in the block table record to get the polyline objects. My code below works but only creates a single alignment before returning the error below.(i’m aware the alignment name needs input from a list to avoid duplicates). Now I’m assuming that’s because it’s looping through the btr and finding a different object that’s not a polyline on the second iteration ? I’m completely stumped as to how to iterate through this correctly and obtain the object id for the second (or more) polyline objects. Hopefully this makes sense but any explanation/help with this would be more than appreciated !

    # 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 (global variables).
Polyline = IN[0]

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

def createalignments(Polyline):


    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 Polyline in btr:
                    t.GetObject(Polyline, OpenMode.ForRead)
                   
                    
                CivilDocument = CivilApplication.ActiveDocument
                
                plops = PolylineOptions()
                plops.AddCurvesBetweenTangents = False
                plops.EraseExistingEntities = False
                plops.PlineId = Polyline
                
                Alignment.Create(CivilDocument, plops, "New Alignment", "", "0", "Design Style LWT", "Standard")
                t.Commit()
                pass             
    return

i = 0
sizeofList = len(Polyline) 
while i < sizeofList :
    OUT = createalignments(Polyline[i]) 
    i += 1
pass

You don’t need to loop if you are passing the Polylines that you want to process as inputs!