Pipe Diversion Around an Obstacle

Hi,

You can also split the original pipe and rotate the elements that make up the slope.

Here’s an example; you need to add the calculations for the cut points.

import clr
import sys
import System
#import net library
from System import Array
from System.Collections.Generic import List, IList, Dictionary, HashSet
#
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS

#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
#import specify namespace
from Autodesk.Revit.DB.Plumbing import *
from Autodesk.Revit.DB.Mechanical import *

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

#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

import math


def find_intersection(elemCurveA, elemCurveB):
    curveA = elemCurveA.Location.Curve
    curveB = elemCurveB.Location.Curve
    curveA.MakeUnbound()
    curveB.MakeUnbound()
    interResult = curveA.Intersect(curveB, CurveIntersectResultOption.Detailed)
    if interResult.Result == SetComparisonResult.Overlap:
        overlap_pt : CurveOverlapPoint  = interResult.GetOverlaps()[0]
        pt = overlap_pt.Point
        return pt
    return None
    
def move_nearest_connector(elemCurveA, pt):
    all_con = [con for con in elemCurveA.ConnectorManager.Connectors]
    all_con.sort(key = lambda c : c.Origin.DistanceTo(pt))
    con = all_con[0]
    con.Origin = pt
    return con

#Preparing input from dynamo to revit
elemA : DB.MEPCurve = UnwrapElement(IN[0])
elemB : DB.MEPCurve = UnwrapElement(IN[1])
angle = IN[2] * 0.0174533

array_pts = []
outIds = []
out = []

curveA : DB.Curve = elemA.Location.Curve
vectA = curveA.Direction
curveB : DB.Curve = elemB.Location.Curve
vectUp = XYZ(0,0,1.5) # vector offset up


interResult = curveA.Intersect(curveB, CurveIntersectResultOption.Detailed)
# compute the points to split
if interResult.Result == SetComparisonResult.Overlap:
    overlap_pt : CurveOverlapPoint  = interResult.GetOverlaps()[0]
    para1 = overlap_pt.FirstParameter
    pt = overlap_pt.Point
    for i in [-1.8, -0.9, 0.9, 1.8]:
        ptx = curveA.Evaluate(para1 + i, False)
        array_pts.append(ptx)
    
    TransactionManager.Instance.EnsureInTransaction(doc)
    # split at points
    array_pts.sort(key = lambda p : p.DistanceTo(curveA.GetEndPoint(0)) )
    pta, ptb, ptc, ptd = array_pts
    elemId = elemA.Id
    outIds.append(elemId)
    #
    for pt in array_pts:
        newfam = None
        try:
                newId = MechanicalUtils.BreakCurve(doc, elemId, pt)
        except Exception as ex:
                print(ex)
                newId = PlumbingUtils.BreakCurve(doc, elemId, pt)
        #
        doc.Regenerate()
        outIds.append(newId)
    #
    new_elems = [doc.GetElement(xId) for xId in outIds]
    new_elems.sort(key = lambda e : e.Location.Curve.GetEndPoint(0).DistanceTo(curveA.GetEndPoint(0)) )
    new_elems_up_ids = List[ElementId]([x.Id for x in new_elems[1:4]])
    # move up
    ElementTransformUtils.MoveElements(doc, new_elems_up_ids, vectUp)
    # rotate 45 degrees
    elemR1 = new_elems[1]
    elemR2 = new_elems[2]
    elemR3 = new_elems[3]
    #
    axis1 = DB.Line.CreateUnbound(ptc + vectUp, vectA.CrossProduct(XYZ.BasisZ))
    axis2 = DB.Line.CreateUnbound(ptb + vectUp, vectA.CrossProduct(XYZ.BasisZ))
    
    ElementTransformUtils.RotateElement(doc, elemR1.Id, axis1, -angle + math.pi)
    ElementTransformUtils.RotateElement(doc, elemR3.Id, axis2, angle + math.pi)
    # find intersection projection
    ptI1 = find_intersection(new_elems[0], elemR1)
    ptI2 = find_intersection(new_elems[-1], elemR3)
    # conect all
    for elem1, elem2, pt_interconect in [
                                        [new_elems[0], elemR1, ptI1], # pair 1
                                        [new_elems[-1], elemR3, ptI2], # pair 2
                                        [elemR1, elemR2, ptc + vectUp], # pair 3
                                        [elemR2, elemR3, ptb + vectUp] # pair 4
                                    ]:
                                        
        con1 = move_nearest_connector(elem1, pt_interconect)
        con2 = move_nearest_connector(elem2, pt_interconect)
        elbow = doc.Create.NewElbowFitting(con1, con2)
        out.append(elbow)
    #
    TransactionManager.Instance.TransactionTaskDone()
    
OUT = out