Copy Alignment

Hi,

I’m trying to make a copy of an offset alignment. I’ve already handled the lines and the curves between them, but I’m not sure how to deal with the spirals yet.

import clr
import traceback

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

import Autodesk.AutoCAD.ApplicationServices as acApp
import Autodesk.AutoCAD.DatabaseServices as db
import Autodesk.AutoCAD.Geometry as geo
import Autodesk.Civil as civil
import Autodesk.Civil.ApplicationServices as civilApp
import Autodesk.Civil.DatabaseServices as civilDb

doc = acApp.Application.DocumentManager.MdiActiveDocument
civilDoc = civilApp.CivilApplication.ActiveDocument
acDb = doc.Database

input_alignment_name = IN[0]
target_alignment = IN[1]

def to_point3d(p2d):
    return geo.Point3d(p2d.X, p2d.Y, 0)

def get_alignment_by_name(name, tr):
    alignment_ids = civilDoc.GetAlignmentIds()
    for id in alignment_ids:
        alignment = tr.GetObject(id, db.OpenMode.ForRead)
        if alignment.Name == name:
            return alignment
    return None

def clear_alignment_entities(alignment, tr):
    count = alignment.Entities.Count
    for i in reversed(range(count)):
        alignment.Entities.RemoveAt(i)

def copy_alignment_entities(source_alignment, target_alignment, tr):
    unsupported_types = []
    entityid_type_log = []

    for i in range(source_alignment.Entities.Count):
        ent = source_alignment.Entities[i]

        prev_ent = source_alignment.Entities[i - 1] if i > 0 else None
        next_ent = source_alignment.Entities[i + 1] if i < source_alignment.Entities.Count - 1 else None

        if isinstance(ent, civilDb.AlignmentLine):
            target_alignment.Entities.AddFixedLine(
                to_point3d(ent.StartPoint),
                to_point3d(ent.EndPoint)
            )

        elif isinstance(ent, civilDb.AlignmentArc):
            if isinstance(prev_ent, civilDb.AlignmentLine) and isinstance(next_ent, civilDb.AlignmentLine):
                try:
                    target_alignment.Entities.AddFixedCurve(
                        to_point3d(ent.StartPoint),
                        to_point3d(ent.EndPoint),
                        ent.Radius,
                        ent.Clockwise
                    )
                except Exception as ex:
                    unsupported_types.append(f"{ent.GetType().Name} (error: {str(ex)})")

            elif isinstance(prev_ent, civilDb.AlignmentSpiral) and isinstance(next_ent, civilDb.AlignmentSpiral):
                try:
                    prev_id = ent.EntityBefore
                    next_id = ent.EntityAfter

                    spiral1_param = prev_ent.A
                    spiral2_param = next_ent.A
                    radius = ent.Radius
                    sp_type = civilDb.SpiralParamType.AValue
                    spiral_def = prev_ent.SpiralDefinition

                    target_alignment.Entities.AddFreeSCS(
                        prev_id,
                        next_id,
                        spiral1_param,
                        spiral2_param,
                        sp_type,
                        radius,
                        spiral_def
                    )
                except Exception as ex:
                    unsupported_types.append(f"Error AddFreeSCS: {str(ex)}")

            else:
                unsupported_types.append("Arc ignored - not between tangents or spirals")

        else:
            unsupported_types.append(ent.GetType().Name)

    if unsupported_types:
        notice = "Entities not copied: " + ", ".join(set(unsupported_types))
    else:
        notice = "All entities copied successfully."

    return notice, entityid_type_log

tr = acDb.TransactionManager.StartTransaction()
try:
    original_alignment = get_alignment_by_name(input_alignment_name, tr)
    destination_alignment = tr.GetObject(target_alignment.InternalObjectId, db.OpenMode.ForWrite)

    if original_alignment and destination_alignment:
        clear_alignment_entities(destination_alignment, tr)
        notice, entity_types = copy_alignment_entities(original_alignment, destination_alignment, tr)
        OUT = f"Alignment '{destination_alignment.Name}' successfully updated.\n{notice}"
    else:
        OUT = "Original or destination alignment not found."

    tr.Commit()
except Exception as e:
    OUT = f"Error executing script:\n{traceback.format_exc()}"
finally:
    tr.Dispose()

I get the following error:
Entities not copied: AlignmentSpiral
Error AddFreeSCS: No method matches given arguments for AddFreeSCS:
(<class 'int'>, <class 'int'>, <class 'float'>, <class 'float'>, <class 'int'>, <class 'float'>, <class 'int'>)

Hi @ADemski,

Have you considered just using the Object.Copy node?

2 Likes

Hi @zachri.jensen
Unfortunately, it doesn’t work for what I need.
I need to create parallel segments of an alignment and then edit some of its parameters — for example, adjusting the lengths of the spiral sections.
If I use Civil 3D’s “Create Offset Alignment” tool, I can’t edit these parameters. Even if I change the alignment type, even if I set “Update Mode” to “Manual.”
And if I use the “Object.Copy” node on this offset alignment, it still doesn’t let me edit it.

So I thought about reading that offset alignment and then creating a new alignment identical to it, but one that I can actually edit.

try used the
[Alignment.CreateOffsetAlignment Method ]

If you create the offset alignment and then change it’s type to something else (say, Centerline), then the geometry should be editable. Is that not what you’re seeing?

What I’m saying is that even after changing to centerline, I still can’t edit it. In the image I sent, if I click on the length ‘99.365’ in the table, I can’t edit it like I would in a normal alignment.