Pressure Pipe Runs & Add Fittings

So just to bump and keep this thread alive I’ll post some progress. I found a few hours to mess around with this last night. This is actually by far the most complicated python script I’ve attempted. I didn’t expect it to be so difficult but you can’t simply pair up pipes and say add branch fitting. You have to:

1.) Break the pipe runs at the point of intersections. I was able to do do this by getting the parent alignment of the pipe runs and checking if the parameter at the intersection points is not 0 or 1. If it isn’t zero or 1, then I know the point in the loop is mid pipe run and the pipe run should be “breaked” at the given point. Here is the working code:

*EDIT: First section of code that breaks the pipes bugfixed 06/29/2022.

# 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')
clr.AddReference('AeccPressurePipesMgd')

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

# The inputs to this node will be stored as a list in the IN variables.
pipeNetworkDynamo = IN[0]
inputPoints = IN[1]

points2d = [Point2d(inputPoint.X, inputPoint.Y) for inputPoint in inputPoints]

points3d = [Point3d(inputPoint.X, inputPoint.Y, inputPoint.Z) for inputPoint in inputPoints]

adoc = Application.DocumentManager.MdiActiveDocument
editor = adoc.Editor

with adoc.LockDocument():
    with adoc.Database as db:

        with db.TransactionManager.StartTransaction() as t:
            cdoc = CivilDocument.GetCivilDocument(db)
            ppn = pipeNetworkDynamo.InternalDBObject
            ppn.UpgradeOpen()
            
            
            params = []
            
            i=0
            
            for point2d, point3d in zip(points2d, points3d):
            
            	pipeRuns = [pipeRun for pipeRun in ppn.PipeRuns]
            	
            	for pipeRun in pipeRuns:
            		#partIds = pipeRun.GetPartIds()
            		#pipes = []
            		alignmentId = pipeRun.AlignmentId
            		alignment = t.GetObject(alignmentId, OpenMode.ForWrite)
            		startPoint = alignment.StartPoint
            		endPoint = alignment.EndPoint
            		closestPointOnAlignment = alignment.GetClosestPointTo(point3d, 0)
            		
            		
            		#if closest point on the alignment is very close to the point in the loop, continue.
            		if abs(closestPointOnAlignment.X - point3d.X) < 1 and abs(closestPointOnAlignment.Y - point3d.Y) < 1:
            			param = alignment.GetParameterAtPoint(closestPointOnAlignment)
            			params.append(param)
            			
            			if param != 0 and param != 1:
            				i = i + 1
            				pipeName = "NewPipe" + str(i)
            				pipeRun.Break(point2d, pipeName)
            		

            		

                    


            t.Commit()
            pass

# Assign your output to the OUT variable.
OUT = i, pipeRuns, params, pipeName

2.) Add a fitting to the pipe intersection points. (These will not come in with a desired rotation and will not automatically connect to any pipes)
This worked for me pipe network wide:

# 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')
clr.AddReference('AeccPressurePipesMgd')

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

# The inputs to this node will be stored as a list in the IN variables.
pressurePipeNetworkDynamo = IN[0]
inputPoints = IN[1]
pressurePartsListDynamo = IN[2]

points = [Point3d(inputPoint.X, inputPoint.Y, inputPoint.Z) for inputPoint in inputPoints]

adoc = Application.DocumentManager.MdiActiveDocument
editor = adoc.Editor

with adoc.LockDocument():
    with adoc.Database as db:

        with db.TransactionManager.StartTransaction() as t:
            cdoc = CivilDocument.GetCivilDocument(db)
            ppn = pressurePipeNetworkDynamo.InternalDBObject
            ppn.UpgradeOpen()
            
            ppl = pressurePartsListDynamo.InternalDBObject
            ppl.UpgradeOpen()
            
            parts = ppl.GetParts(PressurePartDomainType.Fitting)
            
            for part in parts:
                if "tee" in part.Description:
                    partSize = part
            
            for point in points:
                fitting = ppn.AddFitting(point, partSize)
            
            
            
            t.Commit()
            pass

# Assign your output to the OUT variable.
OUT = points, partSize

3.) We have to connect the new fittings to the respective adjacent pipes. I was able to get some test code to connect one port of a single selected fitting to one port of a single selected pipe. This feels really complicated and difficult for me because you have to use “port indexes” of the pipes and fittings. I also don’t see a property for pressure pipes that allow you input a point and get back an index of a pipe (whether it is the start or end). Maybe I’ll have to get the parent alignment or geometry of a pipe / pipe run and use the parameter at point property to check if the index of the connection should be set to the start or end of the pipe, for each pipe adjacent to each fitting. A tad confusing! Here is the test code for connecting a single port to a single pipe:

# 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')
clr.AddReference('AeccPressurePipesMgd')

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

# The inputs to this node will be stored as a list in the IN variables.
pressureFittingDynamo = IN[0]
pipe1Dynamo = IN[1]


adoc = Application.DocumentManager.MdiActiveDocument
editor = adoc.Editor

with adoc.LockDocument():
    with adoc.Database as db:

        with db.TransactionManager.StartTransaction() as t:
            cdoc = CivilDocument.GetCivilDocument(db)
            pFitting = pressureFittingDynamo.InternalDBObject
            pFitting.UpgradeOpen()
            
            p1 = pipe1Dynamo.InternalDBObject
            p1.UpgradeOpen()
            
            p1Id = pipe1Dynamo.InternalObjectId
            
            pFitting.ConnectToPipe(2, p1Id, 0)
            
            
            t.Commit()
            pass

# Assign your output to the OUT variable.
OUT = pFitting.ConnectToPipe.__doc__, p1Id, type(p1Id)

@mzjensen Hey Zachri, just wondering if you have any advice on the port connection step. Would you go about it as I have described?

2 Likes