AutoCAD Civil 3D Customization

AutoCAD Civil 3D Customization

Valued Mentor
Posts: 607
Registered: ‎10-01-2006
Message 1 of 4 (126 Views)

Drainage Network Anaylsis with BW-tree alogthirm or simpler

126 Views, 3 Replies
05-02-2014 07:49 PM



I am trying to extend some earlier code I have written to quickly design drainage works in Civil3d without going outside the program.


The reason I want to do this is when initally designing a new  network we do not need a full blown SSA analysis or storm sewer analysis besides neither of these programs import and export process have ever worked well in the metric world or us anyway.


So what I do at the moment is have  parcels with userdefined properties for all my catchment drainage information and use area label expressions to calculate out my flows from each catchment.  I link these parcels to structures by changing the name of the parcel to the strucutre it is going to and just adding a counter along the lines of -(1) to the end of the name of each addition parcel that needs to drain to the same structure.


This gives me a nice table of data in the toolspace vista for the parcels for all the catchment data and flows as per the image below. The last colum being named test but is actually the flow in l/s for the wastewater in this image.



On the pipes in the network I have expressions that calculate the basic flow capacity of each pipe using manning or cole-brook white equation and display that data in a pipe label.


So at the moment to check the cumvlative flow at each structure I just right click and copy the Parcel (Catchment) data from the toolspace vista and paste it into excel and then if all the catchments are labelled sequencially tally up the flows above a certain structure number. Then jump back into civi3d and check the pipe capacity in that location is ok.


Now what I want to do is eliminate this step with some code that  does this for me. Basically I am wanting to load the drainage network layout data in to some kind of class that I can quickly search and do some of the basic things SSA does like.


1.  Highlight all pipes and structures connected to this structure upstream.

2. Highlight all the parcels catchments connected above this point.

3. Accumalate all the catchment flows from parcels above a certain point and assign it to a property of the structures out going pipe so it can be seen in a pipe label.


Now I have done some googling and it looks like a BW-tree alogthirm is the sort of thing I need. Has any one done something along these lines in Civil3d or using functionalility build into the Civil3d the API. From memory I few years ago the only thing you could find was the shortest path.


Any thoughts and suggestions appriciated.




Justin Ralston




Justin Ralston
*Expert Elite*
Posts: 4,322
Registered: ‎07-22-2003
Message 2 of 4 (108 Views)

Re: Drainage Network Anaylsis with BW-tree alogthirm or simpler

05-04-2014 09:48 AM in reply to: ralstogj
Justin, this is something I have looked into as well, for different purposes. Due to my work schedule I've not been able to pursue it, so my current routine only works from upstream to downstream. I hope to be able to spend more time on this in the near future.
Jeff_M, also a frequent Swamper
Valued Mentor
Posts: 607
Registered: ‎10-01-2006
Message 3 of 4 (104 Views)

Re: Drainage Network Anaylsis with BW-tree alogthirm or simpler

05-04-2014 02:37 PM in reply to: Jeff_M



Thanks for the reply this should be reasonable easy without having to reinvent the wheel.


Since posting this on Saturday moring I have done some more research over the weekend and think the name of the alogthrim we are after in a class is a N-ary tree as  from each outlet in the drianage system you have a tree that can have multipile childern. Althrough in each drawing you may have multipile trees.


I did find that the C# Cookbook has an example of an N-ary tree and you can download the code examples from the book here.


Now just how you load the drainage network data into the tree and search and find paths in it is another problem.


Maybe one of the Autodesk Infrastrucutre Modeeling Devblog guys like Augusto or Partha may like to take on the challenge and help us out with an example and a blog post which would make interesting reading.




Justin Ralston
ADN Support Specialist
Posts: 349
Registered: ‎04-30-2009
Message 4 of 4 (81 Views)

Re: Drainage Network Anaylsis with BW-tree alogthirm or simpler

05-08-2014 01:53 PM in reply to: ralstogj

Hi Justin,


This sounds interesting and tricky... :smileyhappy:


Playing with Pipe Networks can take some cool directions, like this and a sample I did for AU2010 (CP322) that you can find below.


This AU sample may help on your point #1 and get started on point #2, although the Parcel API requires some COM objects, but it's there. The #3 seems more a result of the first two points... am I right?


Finally, the image you send is a little difficult to read, can you submit as an attachment (in full resolution)? Will give some extra thinking time :smileyhappy:








Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.EditorInput

Imports Autodesk.Civil.ApplicationServices
Imports Autodesk.Civil.PipeNetwork.DatabaseServices
Imports Autodesk.Civil.PipeNetwork.DatabaseServices.Styles

Imports Autodesk.AutoCAD.GraphicsInterface
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry

''' <summary>
''' Show the pipe network flow based on Pipe.FlowDirection and Pipe/Structure connections.
''' How to use: run 'SHOWFLOW' command, mouse over a pipe/structure, it will appear some
''' arrows (FlowDirection to one structure to another) or lines (FlowDirection bidirectional)
''' </summary>
''' <remarks></remarks>
Public Class ShowPipeNetworkFlow
    <CommandMethod("showFlow")> _
    Public Sub showFlowDirection()
        Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor

        'start the point monitor
        AddHandler ed.PointMonitor, New PointMonitorEventHandler(AddressOf pointMonitorFlowDirection)

        'trick to let the point monitor running
        ed.GetPoint("Click on screen to exit")

        'finish the point monitor
        RemoveHandler ed.PointMonitor, AddressOf pointMonitorFlowDirection
    End Sub

    Private geo As ViewportGeometry
    Private trans As Transaction

    Public Sub pointMonitorFlowDirection(ByVal sender As Object, ByVal e As PointMonitorEventArgs)
        'get the entity over the aperture
        Dim pickEnts As FullSubentityPath() = e.Context.GetPickedEntities()
        If (pickEnts.Length = 0) Then Return

        Dim entIds As ObjectId() = pickEnts(0).GetObjectIds()
        If (entIds.Length = 0) Then Return

        Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database
            trans = db.TransactionManager.StartTransaction

            'is it a pipe or structure?
            Dim p As Part = TryCast(trans.GetObject(entIds(0), OpenMode.ForRead), Part)
            If (p Is Nothing) Then
                trans.Commit() 'faster than abort
            End If

            'store the curret draw context (will be used later)
            geo = e.Context.DrawContext.Geometry

            If (p.Domain = DomainType.Pipe) Then
                NextPipe(p, e.Context.RawPoint)
            End If

            trans.Commit() 'faster than abort
            'always dispose
            'as we store and reuse the transaction, we cannot use the Using keyword here
            'so it is required an explicit dispose
        End Try
    End Sub

    Public Sub NextPipe(ByVal p As Pipe, ByVal drawFlowFrom As Point3d)
        'get the base curve that represents this pipe
        'unfortunatelly the Pipe.BaseCurve property is not working yet,
        'therefore this is not working for curved pipes.
        'let's create a base LINE
        Dim baseCurve As Curve
        If p.FlowDirection = FlowDirectionType.StartToEnd Then
            baseCurve = New Line(p.StartPoint, p.EndPoint)
            baseCurve = New Line(p.EndPoint, p.StartPoint)
        End If

        'get the length of the curve
        Dim length As Double = baseCurve.GetDistanceAtParameter(baseCurve.EndParam)
        'determine where start drawing the arrows, close to the mouse cursor (aperture)
        Dim startLength As Double = baseCurve.GetDistAtPoint(baseCurve.GetClosestPointTo(drawFlowFrom, False))
        'if this pipe is bidirectional, then start at 0 (ignore line above)
        If (p.FlowDirection = FlowDirectionType.Bidirectional) Then startLength = 0.0

        'iterate through the pipe length
        For i As Double = startLength To length Step 2.0
            Dim pointOverPipe As Point3d = baseCurve.GetPointAtDist(i)
            Dim directionAtPoint As Vector3d = baseCurve.GetFirstDerivative(pointOverPipe)
            Select Case p.FlowDirection
                Case FlowDirectionType.Bidirectional
                    DrawLineAtPoint(geo, pointOverPipe, directionAtPoint)
                Case FlowDirectionType.StartToEnd
                    DrawArrowAtPoint(pointOverPipe, directionAtPoint)
                Case FlowDirectionType.EndToStart
                    DrawArrowAtPoint(pointOverPipe, directionAtPoint)
            End Select

        'determine the next structure, following the flow
        Select Case p.FlowDirection
            Case FlowDirectionType.Bidirectional 'both directions
                NextStruct(trans.GetObject(p.EndStructureId, OpenMode.ForRead))
                NextStruct(trans.GetObject(p.StartStructureId, OpenMode.ForRead))
            Case FlowDirectionType.StartToEnd
                NextStruct(trans.GetObject(p.EndStructureId, OpenMode.ForRead))
            Case FlowDirectionType.EndToStart
                NextStruct(trans.GetObject(p.StartStructureId, OpenMode.ForRead))
        End Select
    End Sub

    Public Sub DrawArrowAtPoint(ByVal p As Point3d, ByVal v As Vector3d)
        v = v.MultiplyBy(1 / v.Length) 'turn into unit length vector
        'directions of the arrow
        Dim leftSide As Vector3d = v.RotateBy(2 * Math.PI / 3, Vector3d.ZAxis)
        Dim rightSide As Vector3d = v.RotateBy(4 * Math.PI / 3, Vector3d.ZAxis)
        'draw the arrow
        geo.WorldLine(p, p.Add(leftSide))
        geo.WorldLine(p, p.Add(rightSide))
    End Sub

    Public Sub DrawLineAtPoint(ByVal geo As ViewportGeometry, ByVal p As Point3d, ByVal v As Vector3d)
        v = v.MultiplyBy(1 / v.Length) 'turn into unit length vector
        'two perpendicular vectos
        Dim leftSide As Vector3d = v.RotateBy(Math.PI / 2, Vector3d.ZAxis)
        Dim rightSide As Vector3d = v.RotateBy(3 * Math.PI / 2, Vector3d.ZAxis)
        'draw the line
        geo.WorldLine(p.Add(rightSide), p.Add(leftSide))
    End Sub

    Public Sub NextStruct(ByVal s As [Structure])
        'find the next pipe for each connected pipe
        For pIndex As Integer = 0 To s.ConnectedPipesCount - 1
            Dim p As Pipe = trans.GetObject(s.ConnectedPipe(pIndex), OpenMode.ForRead)

            'determine where will flow from this pipe
            'these 2 'ifs' could be one, but left as two to understanding it better
            If p.StartStructureId.Equals(s.ObjectId) And p.FlowDirection = FlowDirectionType.StartToEnd Then
                NextPipe(p, s.Location)
            ElseIf p.EndStructureId.Equals(s.ObjectId) And p.FlowDirection = FlowDirectionType.EndToStart Then
                NextPipe(p, s.Location)
            End If
    End Sub
End Class


Augusto Goncalves
Autodesk Developer Network
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.