How to split CableTray?

I use node Element.Split of dynaMEP,but isn’t working. Didn’t anyone face same issue?

Hi @leo25010278 you could try something here and see if it could be better. and should work with ironpython2 and 3 as well

import clr

clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Electrical import CableTray

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

def to_list(x):
    return x if isinstance(x, list) else [x]

def to_xyz(p):
    if isinstance(p, XYZ):
        return p
    try:
        return p.ToXyz()
    except:
        return None

def copy_size_params(src, dst):
    for bip in (BuiltInParameter.RBS_CABLETRAY_WIDTH_PARAM,
                BuiltInParameter.RBS_CABLETRAY_HEIGHT_PARAM):
        ps, pd = src.get_Parameter(bip), dst.get_Parameter(bip)
        if ps and pd and (not pd.IsReadOnly):
            try:
                pd.Set(ps.AsDouble())
            except:
                pass

def split_tray_multiple(tray, split_pts_xyz, tol=1e-6):
    loc = tray.Location
    if not isinstance(loc, LocationCurve):
        return [tray]

    curve = loc.Curve
    connector_pts = []
    try:
        for c in tray.ConnectorManager.Connectors:
            connector_pts.append(c.Origin)
    except:
        pass

    pts = []
    for p in split_pts_xyz:
        if p is None:
            continue
        proj = curve.Project(p)
        if proj is None:
            continue
        t_norm = curve.ComputeNormalizedParameter(proj.Parameter)
        if 1e-6 < t_norm < 1 - 1e-6:
            split_pt = proj.XYZPoint
            if not any(split_pt.DistanceTo(cp) < tol for cp in connector_pts):
                pts.append(split_pt)

    if not pts:
        return [tray]

    pts.sort(key=lambda p: curve.Project(p).Parameter)

    segments = []
    current_tray = tray

    TransactionManager.Instance.EnsureInTransaction(doc)
    for pt in pts:
        loc_seg = current_tray.Location
        curve_seg = loc_seg.Curve
        proj = curve_seg.Project(pt)
        if proj is None:
            continue
        split_pt = proj.XYZPoint

        new_tray = CableTray.Create(
            doc,
            current_tray.GetTypeId(),
            split_pt,
            curve_seg.GetEndPoint(1),
            current_tray.LevelId
        )
        copy_size_params(current_tray, new_tray)
        loc_seg.Curve = Line.CreateBound(curve_seg.GetEndPoint(0), split_pt)

        try:
            for conn in current_tray.ConnectorManager.Connectors:
                for ref in conn.AllRefs:
                    if ref.Owner.Id != current_tray.Id:
                        conn.ConnectTo(ref)
        except:
            pass

        segments.append(current_tray)
        current_tray = new_tray

    try:
        for conn in current_tray.ConnectorManager.Connectors:
            for ref in conn.AllRefs:
                if ref.Owner.Id != current_tray.Id:
                    conn.ConnectTo(ref)
    except:
        pass

    segments.append(current_tray)
    TransactionManager.Instance.TransactionTaskDone()
    return segments

trays_in = to_list(IN[0])
pts_in = IN[1]
delete_original = IN[2] if len(IN) > 2 and isinstance(IN[2], bool) else False
pts_xyz = [to_xyz(p) for p in to_list(pts_in)]

all_segments = []
for tray in trays_in:
    tray_unwrapped = UnwrapElement(tray)
    segs = split_tray_multiple(tray_unwrapped, pts_xyz)
    if delete_original:
        try:
            doc.Delete(tray_unwrapped.Id)
        except:
            pass
    all_segments.extend(segs)

OUT = all_segments

1 Like

God! Thank you very much!

1 Like