Is there a node similar to the PVIandRadius node?

Hello, is there any node similar to PVIandRadius or do you have maybe the Python code to use it momentarily civil 3d 2025?

@zachri.jensen and @hosneyalaa Please could you help me with this?

I’m not trying this before
Try AddFreeCircularCurveByPVIAndRadius Method by python code

https://help.autodesk.com/view/CIV3D/2025/ENU/?guid=fee99593-3c87-5093-dec2-464e116b603f

Can anyone help with the code in CPython?


Example.dyn (88.7 KB)

Intro-1.dwg (2.4 MB)

# 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 *
import Autodesk.Civil.DatabaseServices as civdbs

# The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN

# Get the active document
adoc = Application.DocumentManager.MdiActiveDocument
editor = adoc.Editor
civdoc = CivilApplication.ActiveDocument

# Input parameters
profile = IN[0]  # Profile object
attach_point = IN[1]  # PVI index to attach the curve
curve_length = IN[2]  # Length of the circular curve

def AddFreeCircularCurve(profile, attach_point, curve_length):
    with adoc.LockDocument():
        with adoc.Database as db:
            with db.TransactionManager.StartTransaction() as t:
                try:
                    # Get the profile object
                    profileId = profile.InternalObjectId
                    profileObj = t.GetObject(profileId, OpenMode.ForWrite)
                    
                    # Get PVIs collection
                    pvis = profileObj.PVIs
                    
                    if attach_point >= pvis.Count - 1:
                        raise Exception("Attach point must be less than the total number of PVIs")
                    
                    # Get the PVI points we'll work with
                    pvi1 = pvis.GetPVIAt(attach_point)
                    pvi2 = pvis.GetPVIAt(attach_point + 1)
                    
                    # Calculate grade between points
                    grade = (pvi2.Elevation - pvi1.Elevation) / (pvi2.Station - pvi1.Station)
                    
                    # Calculate curve parameters
                    halfLength = curve_length / 2.0
                    startStation = pvi1.Station + halfLength
                    endStation = pvi2.Station - halfLength
                    
                    # Add the circular curve
                    curveParams = civdbs.ProfileCurveParameters()
                    curveParams.CurveType = civdbs.ProfileCurveType.Parabolic
                    curveParams.Length = curve_length
                    
                    profileObj.AddVerticalCurve(attach_point, curveParams)
                    
                    t.Commit()
                    return profileObj
                    
                except Exception as ex:
                    editor.WriteMessage("\nError: " + str(ex))
                    return None

# Execute the function
result = AddFreeCircularCurve(profile, attach_point, curve_length)

# Assign your output to the OUT variable
OUT = result

any ideas regarding this please
@hosneyalaa
@zachri.jensen
@Anton_Huizinga

This line is wrong
there is no Method AddVerticalCurve()

# 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 *
import Autodesk.Civil.DatabaseServices as civdbs
# The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN
# Get the active document
adoc = Application.DocumentManager.MdiActiveDocument
editor = adoc.Editor
civdoc = CivilApplication.ActiveDocument
# Input parameters
profile = IN[0]  # Profile object
attach_point = IN[1]  # PVI index to attach the curve
curve_length = IN[2]  # Length of the circular curve

def AddFreeCircularCurve(profile, attach_point, curve_length):
    with adoc.LockDocument():
        with adoc.Database as db:
            with db.TransactionManager.StartTransaction() as t:
                try:
                    # Get the profile object
                    profileId = profile.InternalObjectId
                    profileObj = t.GetObject(profileId, OpenMode.ForWrite)
                    
                    # Get PVIs collection
                    pvis = profileObj.PVIs
                    
                    if attach_point >= pvis.Count - 1:
                        raise Exception("Attach point must be less than the total number of PVIs")
                    
                    # Get the PVI to attach the curve to
                    attachPVI = pvis.GetPVIAt(attach_point)
                    
                    # Add the circular curve using the correct method
                    curve = profileObj.AddFreeCircularCurveByPVIAndLength(attachPVI, curve_length)
                    
                    t.Commit()
                    return profileObj
                    
                except Exception as ex:
                    editor.WriteMessage("\nError: " + str(ex))
                    return None

# Execute the function
result = AddFreeCircularCurve(profile, attach_point, curve_length)
# Assign your output to the OUT variable
OUT = result

I can’t get it to work

TRY

# Add the circular curve using the correct method
                    profileObj.Entities.AddFreeCircularCurveByPVIAndLength(attachPVI, curve_length)
                    
                    t.Commit()
                    return profileObj

I have tried but it still does not work

I find it incredible that with the number of experts on this forum, no one is able to give you an answer. Great work, I’m trying to fix the error, but I can’t seem to…
PPEE_Alignment_ONLY_DesingProf_v1.dyn (137.6 KB)

import sys
import clr

clr.AddReference('AcMgd')
clr.AddReference('AcCoreMgd')
clr.AddReference('AcDbMgd')
clr.AddReference('AecBaseMgd')
clr.AddReference('AecPropDataMgd')
clr.AddReference('AeccDbMgd')

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.Runtime import Exception as AcadException, ErrorStatus

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

dataEnteringNode = IN

adoc = Application.DocumentManager.MdiActiveDocument
editor = adoc.Editor
civdoc = CivilApplication.ActiveDocument

profile_lists = IN[0]  # Lista de perfiles
attach_points_lists = IN[1]  # Lista de listas de PVIs (estaciones y elevaciones)
curve_length = IN[2]  # Longitud de las curvas circulares

def find_pvi_index(profileObj, target_station, target_elevation):
    """Buscar el índice del PVI basado en estación y elevación."""
    pvis = profileObj.PVIs
    for idx in range(pvis.Count):
        pvi = pvis[idx]
        if abs(pvi.Station - target_station) < 1e-3 and abs(pvi.Elevation - target_elevation) < 1e-3:
            return idx
    return None

def AddFreeCircularCurve(profile, pvi_point, curve_length):
    with adoc.LockDocument():
        db = adoc.Database
        with db.TransactionManager.StartTransaction() as t:
            try:
                if hasattr(profile, 'InternalObjectId'):
                    profileId = profile.InternalObjectId
                else:
                    profileId = profile

                profileObj = t.GetObject(profileId, OpenMode.ForWrite)

                editor.WriteMessage("\nDEBUG: Procesando profileId = {0}".format(profileId))

                pvis = profileObj.PVIs
                if pvis.Count < 3:
                    editor.WriteMessage("\nADVERTENCIA: Perfil con menos de 3 PVIs, no se agregan curvas.")
                    return None

                # Acceder a las propiedades estación y elevación del attach_point
                target_station = pvi_point.Station
                target_elevation = pvi_point.Elevation

                idx = find_pvi_index(profileObj, target_station, target_elevation)

                if idx is None:
                    editor.WriteMessage("\nERROR: No se encontró el PVI con estación {0} elevación {1}".format(target_station, target_elevation))
                    return None

                if idx == 0 or idx == pvis.Count - 1:
                    editor.WriteMessage("\nADVERTENCIA: No se puede colocar curva en primer o último PVI. Se omite.")
                    return None

                pvi_to_attach = pvis[idx]

                editor.WriteMessage("\nDEBUG: Adjuntando curva en idx={0}, estación={1}, elevación={2}".format(idx, pvi_to_attach.Station, pvi_to_attach.Elevation))

                # Insertar la curva
                profileObj.Entities.AddFreeCircularCurveByPVIAndLength(pvi_to_attach, curve_length)

                t.Commit()
                return profileObj

            except Exception as ex:
                editor.WriteMessage("\n[AddFreeCircularCurve] Error: {0}\n".format(ex))
                return None

results = []

# Procesar todos los perfiles
for profile_list, attach_points_list in zip(profile_lists, attach_points_lists):
    for profile, attach_points in zip(profile_list, attach_points_list):
        for pvi_point in attach_points:
            result = AddFreeCircularCurve(profile, pvi_point, curve_length)
            results.append(result)

OUT = results

@manuel.lozanomASTWU could you fix it for civil 2025, I tried with the code you left but it doesn’t work.

I use this code for multiple profiles at my regular job, in version 2025.1. I just wanted to show you the way

Example (1).dyn (25.1 KB)

Maybe it’s my mistake but in civil 2025 the code does not work.

The file I am using as a test is the same as the one I attached in my previous posts


Sorry a
I’m not a expert. It’s civil 3d 2025 but with my code in your dwg… just wanted to show you the way

Blockquote