Python - Change Surface Breakline set name

Hi All,

I want to change the Breakline set name. Below code is what i have so far. I think i have the wrong object “Surface” instead of “TinSurface”. “TinSurface” class has a property “BreaklinesDefinition”. But i can’'t find how the get the “TinSurface” object, thats where the problem starts.

https://help.autodesk.com/view/CIV3D/2023/ENU/?guid=5897aaea-ff18-097a-ffda-25e84385826d
and i found this C# code (Add/Modify BreaklineSet with own description):

public void AddBreaklinesBySset()
        {
            Surface surf = new Surface();
            surf.SelectTinSurface();
            ObjectIdCollection coll = Selection.SsetFilter("Layer1", "LWPOLYLINE");
            surf.Tinsurface.BreaklinesDefinition.AddStandardBreaklines(coll, 10, 5, 5, 0);

            SurfaceDefinitionBreaklines brkdefs = surf.Tinsurface.BreaklinesDefinition;
            SurfaceOperationAddBreakline brklines = brkdefs[0];
            brklines.Description = "Test";
        }
import System
import clr

clr.AddReference('AcMgd')
clr.AddReference('AcDbMgd')
clr.AddReference('AeccDbMgd')

from ctypes import *

from Autodesk.AutoCAD.ApplicationServices import *
from Autodesk.AutoCAD.DatabaseServices import *

from Autodesk.Civil.ApplicationServices import *
from Autodesk.Civil.DatabaseServices import *
from Autodesk.Civil import *

adoc = Application.DocumentManager.MdiActiveDocument
def AddSurfaceDescription(surface):

    global adoc

    try:
        with adoc.LockDocument():
            with adoc.Database as db:
                with db.TransactionManager.StartTransaction() as t:
                    surfId = surface.InternalObjectId
                    print("surfId:" + str(surfId))
                    surf = surfId.GetObject(OpenMode.ForWrite)
                    #print(dir(surf))
                    print("-AddSurfaceDescription")
                    brkdefs = surf.BreaklinesDefinition
                    print(dir(brkdefs))
                    print("Count: " + str(brkdefs.Count)) **// It gives me a count**

                    #brkdefs[brkdefs.Count - 1].Description = "Test"
                    t.Commit()
                    #pass
                    print("The process AddSurfaceDescription Completed")
                    return surface
    except:
        print("The process AddSurfaceDescription failed")
        t.Dispose()
        return "The process failed"
    #return surface

OUT = AddSurfaceDescription(IN[0])

Thanks in advance.

Hi @JPS,

Are you trying to change the descriptions for all of the breakline sets or just a single one? If just a single, how do you envision the process of choosing which breakline set to change?

Hi @mzjensen ,

Need to change the descriptions for all of the breakline sets. I tried to do this is one python script but couldn’t get it working. I hope that the order of adding breaklines to a surface in different sets, will be same as reading the sets in a second script.

OK. Also, just to clarify…are you trying to change the descriptions for breakline sets that have already been created outside of your script? It’s only possible to set the description for an instance of a SurfaceOperationAddBreakline object, which can only be instantiated by creating/adding a new breakline set.

Hi @mzjensen,

I have tried both options, inside and outside of the script. Below a part of the python code, trying to do this in one script:

print(“-AddStandardBreaklines”)
surf.BreaklinesDefinition.AddStandardBreaklines(breaklineEntities, 10, 5, 5, 0)
print(“-Change Surface Description”)
surf.Description = “Description Test”
print(“-Change Breaklinesets Description”)
brkdefs = surf.BreaklinesDefinition ===> After this the code doesn’t work.
print(brkdefs)
print("Count: " + str(brkdefs.Count))
#brklines = brkdefs[0]
#print(brklines)

surf.Rebuild()
t.Commit()
#pass
print(“The process AddSurfaceBreaklines Completed”)

brkdefs = surf.BreaklinesDefinition, I think this is where things go wrong.

I’m out of options.

Hi @mzjensen,

I also found this code:

Database db = Application.DocumentManager.MdiActiveDocument.Database;
using (Transaction trans = db.TransactionManager.StartTransaction())
{
TinSurface tinSurface = trans.GetObject(surfaceId, OpenMode.ForWrite) as TinSurface;
for (int b = 0; b < tinSurface.BreaklinesDefinition.Count; b++)
{
SurfaceOperationAddBreakline operation = tinSurface.BreaklinesDefinition[b];

// the RemoveAt will act at this level
ed.WriteMessage(“\n{0}”, operation.Description);

foreach (SurfaceBreakline breakline in operation)
{
// this level don’t have a Remove method…
ed.WriteMessage(“\n\t{0}”, breakline.Description);
}
}
//tinSurface.BreaklinesDefinition.RemoveAt(…);
//tinSurface.Rebuild();
//trans.Commit();
}

Sorry to keep asking, but I still have the same question. What is your goal?

  1. Add new breakline definitions to a surface and set their descriptions
  2. Change the descriptions for existing breakline sets

They are different problems.

No problem, is seems i’m not clear enough.
Option 2 is the better option. Then i can use the “TinSurfaceExtensions.AddStandardBreaklines” node add the featureline to create the surface.

Based on what you describe, it sounds like you have an empty surface and are trying to add breaklines to the surface while including breakline descriptions in the surface definition. If that’s true, then this would be the workflow for Option 2:

  1. Add feature lines as breaklines to a surface using TinSurfaceExtensions.AddStandardBreaklines (Civil 3D Toolkit package)
  2. Remove the breaklines from the surface (Python)
  3. Add the breaklines to the surface and set descriptions (Python)

Removing the breaklines (step 2) is necessary because…

So essentially you would be adding the breaklines, removing the breaklines, and then readding them again with descriptions. I think it would be more efficient to do Option 1, do you agree?

I agree, yes then option 1 is more efficient.

Here are the steps to do it in a Python node. This is just pseudocode, meaning it is only intended to show the general outline and will not work if copied and pasted.

dynamoSurf = IN[0]
featureLines = IN[1]
midOrdinateDist = IN[2]
maxDist = IN[3]
weedDist = IN[4]
weedAngle = IN[5]
desc = IN[6]

start transaction
  # Unwrap the Dynamo surface object to get internal surface object
  civilSurf = dynamoSurf.InternalDBObject
  # Upgrade the object's OpenMode status so that it is write-enabled
  civilSurf.UpgradeOpen()
  # Get the collection of breakline definitions
  brkLineDefs = civilSurf.BreaklinesDefinition
  # Create an empty Object ID collection
  oids = ObjectIdCollection()
  # Loop through each feature line and collect the Object IDs
  for fl in featureLines:
    oids.Add(fl.InternalObjectID)
  # Create new breakline definitions
  brkLineSet = brkLineDefs.AddStandardBreaklines(oids, midOrdinateDist, maxDist, weedDist, weedAngle)
  # Set breakline definition description
  brkLineSet.Description = desc
commit transaction

return dynamoSurf

Documentation:
TINSurface class properties
BreaklinesDefinition property
SurfaceDefinitionBreaklines.AddStandardBreaklines() method
SurfaceBreakline class

2 Likes

Many thanks. So stupid I didn’t see this. The solution is very simple. I owe you a beer :beer:. (I’ve had to program this in VB.NET many times)

with db.TransactionManager.StartTransaction() as t:
      surfId = surface.InternalObjectId
      surf = surfId.GetObject(OpenMode.ForWrite)

Last question:
What is the diffence between"UpgradeOpen" and “OpenMode.ForWrite”? Both do work.

See here.