Traversing Geometric network

1759
4
02-13-2017 04:22 AM
MatejSkerjanc
Occasional Contributor

Hello guys and gals

I am trying to traverse geometric network and getting a single property out of every feature on the way. My starting point is certain IFeature which i cast into ISimpleJunctionFeature and use it in IForwardStarGEN.FindAdjacent which  provides me only with number of adjacent elements. I then use IForwardStarGEN.QueryAdjacentEdge etc. and i get

which in turn getse me IFeature, the property i needed class id etc. But how can i continue the path down the geometric network? I assume i need a recursion, but I seem to be stuck and there seems to be no examples on the web whatsoever, plus the documentation is a bit shoddy.

Thank you for any hints

Best regards,

Matej

0 Kudos
4 Replies
DuncanHornby
MVP Notable Contributor

You say "...how can I continue the path down the geometric network". From your description it sounds like you were starting at a location and then trying to traverse downstream, say a river network? Well a better way would be to SOLVE the routing problem then process the returned edges. You solve network tracing problems with the ITraceFlowSolver interface. The FindPath method returns an enumerator over the edges that make up the route. From that you can drill down to the individual features and query any associated attributes.

0 Kudos
MatejSkerjanc
Occasional Contributor

Sounds like I've missed a step or two, thank you for nudging me to the right direction.

best regards,

Matej

DuncanHornby
MVP Notable Contributor

Matej,

I can go one better, here is some old VBA code I had developed to create a route between 2 points on a river network. This will certainly help you in understand the steps as it's not immediately obvious what the sequence is!

Some of it may not be relevant to you as this function is trying to return a polyline.

Public Function Generate_route_between_2_points(theStartPoint As IPoint, theEndpoint As IPoint) As ICurve
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Description:                                                                     '
    ' This public function attempts to calculate the route along the network between   '
    ' the 2 points supplied to it. If it fails (due to snap tolerance) then a NULL     '
    ' geometry is returned. It returns a geometry of type ICurve.                      '
    '                                                                                  '
    ' Updated on 14/5/2003
                '
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Show_message_in_StatusBar "Tracing network..."
    
    '''''''''''''''''''''''''
    ' Define an empty curve '
    '''''''''''''''''''''''''
    Dim anEmptyCurve As ICurve
    Set anEmptyCurve = Nothing
    
    ''''''''''''''''''''''''''''''
    ' Get handle on featureclass '
    ''''''''''''''''''''''''''''''
    Dim pMXDocument As IMxDocument
    Set pMXDocument = ThisDocument
    Dim pmap As IMap
    Set pmap = pMXDocument.FocusMap
    Dim pLayer As ILayer
    Dim pFeatureLayer As IFeatureLayer
    Set pFeatureLayer = FindLayer("Rivers")
    
    '''''''''''''''''''''''''
    ' Get handle on network '
    '''''''''''''''''''''''''
    Dim pFeatureClass As IFeatureClass
    Set pFeatureClass = pFeatureLayer.FeatureClass
    Dim pFeatureDataset As IFeatureDataset
    Set pFeatureDataset = pFeatureClass.FeatureDataset
    Dim pNetworkCollection As INetworkCollection
    Set pNetworkCollection = pFeatureDataset
    Dim pGeometricNetWork As IGeometricNetwork
    Set pGeometricNetWork = pNetworkCollection.GeometricNetwork(0)
    Dim pNetwork As INetwork
    Set pNetwork = pGeometricNetWork.Network
    
    '''''''''''''''''''''''''''''''''''
    ' Test to see if network is Valid '
    '''''''''''''''''''''''''''''''''''
    If pNetwork.status <> esriNSValidNetwork Then
        MsgBox "Network is not valid! Bailing out now to stop system crash.", vbCritical, "Fatal Error!"
        End
    End If
    
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Point to EID - Find nearest edge to point within 100 map units. Note that the '
    ' returned point "theFirstLocation" is used later for identifying the sub curve '
    ' of the traced route.                                                          '
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Dim pPointToEID As IPointToEID
    Set pPointToEID = New PointToEID
    Dim nearestEdgeEID As Long
    Dim theFirstLocation As IPoint
    Dim aPercentage As Double
    With pPointToEID
        .SnapTolerance = 100
        Set .SourceMap = pmap
        Set .GeometricNetwork = pGeometricNetWork
        .GetNearestEdge theStartPoint, nearestEdgeEID, theFirstLocation, aPercentage
    End With
    
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Check to see if theStartPoint selected an edge feature, if not return a NULL shape '
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    If theFirstLocation Is Nothing Then
        Set Generate_route_between_2_points = anEmptyCurve
        Exit Function
    End If
    
    '
    ' Convert the EID to a feature class ID, feature ID, and sub ID
    '
    Dim lFCID As Long, lFID As Long, lSubID As Long
    Dim pNetElements As INetElements
    Set pNetElements = pNetwork
    pNetElements.QueryIDs nearestEdgeEID, esriETEdge, lFCID, lFID, lSubID
    
    
    '
    ' Now create the flag that will be used by the tracesolver
    '
    Dim pNetFlag As INetFlag
    Set pNetFlag = New EdgeFlag
    With pNetFlag
        .UserClassID = lFCID
        .UserID = lFID
        .UserSubID = lSubID
    End With
    
    '
    ' Now do it all again with the second point!
    '
    Set pPointToEID = New PointToEID
    Dim theSecondLocation As IPoint
    With pPointToEID
        .SnapTolerance = 100
        Set .SourceMap = pmap
        Set .GeometricNetwork = pGeometricNetWork
        .GetNearestEdge theEndpoint, nearestEdgeEID, theSecondLocation, aPercentage
    End With
    
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Check to see if theEndPoint selected an edge feature, if not return a NULL shape '
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    If theSecondLocation Is Nothing Then
        Set Generate_route_between_2_points = anEmptyCurve
        Exit Function
    End If
    
    Set pNetElements = pNetwork
    pNetElements.QueryIDs nearestEdgeEID, esriETEdge, lFCID, lFID, lSubID
    Dim anotherpNetFlag As INetFlag
    Set anotherpNetFlag = New EdgeFlag
    With anotherpNetFlag
        .UserClassID = lFCID
        .UserID = lFID
        .UserSubID = lSubID
    End With
    ''''''''''''''''''''''''''''''''''''''''
    ' Establish a trace flow solver object '
    ''''''''''''''''''''''''''''''''''''''''
    Dim pTraceFlowSolver As ITraceFlowSolver
    Set pTraceFlowSolver = New TraceFlowSolver
    Dim pNetSolver As INetSolver
    Set pNetSolver = pTraceFlowSolver
    Set pNetSolver.SourceNetwork = pNetwork
    
    ''''''''''''''''''''''''''''''
    ' Ensure solver uses weights '
    ''''''''''''''''''''''''''''''
    Dim pNetSolverWeights As INetSolverWeights
    Set pNetSolverWeights = pTraceFlowSolver
    Dim pNetWeight As INetWeight
    Dim pNetSchema As INetSchema
    Set pNetSchema = pNetwork
    Set pNetWeight = pNetSchema.WeightByName("Length_Weight")
    Set pNetSolverWeights.FromToEdgeWeight = pNetWeight
    Set pNetSolverWeights.ToFromEdgeWeight = pNetWeight
    
    
    '''''''''''''''''''''''''''''''''''
    ' Load trace solver with netflags '
    '''''''''''''''''''''''''''''''''''
    Dim arrayOfEdgeFlags(2) As IEdgeFlag
    Set arrayOfEdgeFlags(0) = pNetFlag
    Set arrayOfEdgeFlags(1) = anotherpNetFlag
    pTraceFlowSolver.PutEdgeOrigins 2, arrayOfEdgeFlags(0)
    
    '''''''''''''
    ' Run trace '
    '''''''''''''
    Dim pEnumJuncIDs As IEnumNetEID
    Dim pEnumEdgeIDs As IEnumNetEID
    Dim pSegs(1) As Variant
    pTraceFlowSolver.FindPath esriFMConnected, esriSPObjFnMinSum, pEnumJuncIDs, pEnumEdgeIDs, 1, pSegs(0)
    
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' In ArcView a path could be created without any cost, ie a zero length path. Not '
    ' sure if ArcMap does the same thing so test here to see if the generated path    '
    ' actually has an associated cost (more than 0 segments).  If it does not, return '
    ' a NULL ICurve.                                                                  '
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    If pSegs(0) < 1 Then
        Set Generate_route_between_2_points = anEmptyCurve
        Exit Function
    End If
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' FindPath has returned the enumerate pEnumEdgeIDs which we will now use to get the '
    ' features and build a long polyline                                                '
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Dim pEIDInfo As IEIDInfo
    Dim pEnumEIDInfo As IEnumEIDInfo
    Dim pEIDHelper As IEIDHelper
 
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Create a new object of EIDHelper and set some propertise '
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Set pEIDHelper = New EIDHelper
    Set pEIDHelper.GeometricNetwork = pGeometricNetWork
    Set pEIDHelper.OutputSpatialReference = Nothing
    pEIDHelper.ReturnFeatures = True
    
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Now create an enumerate object from EIDHelper and make sure it's reset '
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Set pEnumEIDInfo = pEIDHelper.CreateEnumEIDInfo(pEnumEdgeIDs)
    pEnumEIDInfo.Reset
    
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Loop through pEnumEIDInfo getting the features of the individual elements  '
    ' that make up the route and union them into a single geometry (polyline).   '
    ' This section of code was updated on 14/5/2003 to improve speed of          '
    ' constructing polyline from trace on network.  Previous code used to loop   '
    ' throught each network element merging them together one by one, we now use '
    ' the more efficient GeometryBag and topological operator constructUnion.    '
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    
    Dim pGeometryCollection As IGeometryCollection
    Set pGeometryCollection = New GeometryBag
    Dim pTopologicalOperator As ITopologicalOperator
    Dim pFeature As IFeature
    Dim pGeometry As IGeometry
    
    '''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Now loop through adding them to the geometrybag '
    ' via it's interface of geometry collection.      '
    '''''''''''''''''''''''''''''''''''''''''''''''''''
    Show_message_in_StatusBar "Turning trace into polyline..."
    For aCounter = 1 To pEnumEIDInfo.count
        Set pEIDInfo = pEnumEIDInfo.Next
        Set pFeature = pEIDInfo.Feature
        Set pGeometry = pFeature.ShapeCopy
        pGeometryCollection.AddGeometry pGeometry
    Next aCounter
    
    '''''''''''''''''''''''''''''''''''''''''''''''
    ' Having add the geometries to the collection '
    ' we now union them into a single polyline.   '
    '''''''''''''''''''''''''''''''''''''''''''''''
    Set pTopologicalOperator = New Polyline
    pTopologicalOperator.ConstructUnion pGeometryCollection
    
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' This new line is constructed from all the edges that it traced along, this includes '
    ' the full length of the edge that the flag was on.  We do not want this, we want the '
    ' distance travelled between the 2 points                                             '
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    
    Dim pCurve As ICurve
    Dim pNewCurve As ICurve
    Dim aDummyPoint As IPoint
    Dim bRight As Boolean
    Dim distanceAlongCurve As Double
    Dim distanceFromCurve As Double
    Dim FirstPointAlong As Double
    Dim SecondPointAlong As Double
    Set pCurve = pTopologicalOperator
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Query curve to find distance along curve for theFirstLocation, unfortunately also '
    ' need to supply other variables as these are required                              '
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    pCurve.QueryPointAndDistance esriNoExtension, theFirstLocation, False, aDummyPoint, distanceAlongCurve, distanceFromCurve, bRight
    FirstPointAlong = distanceAlongCurve
    
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Query curve to find distance along curve for theSecondLocation, unfortunately also '
    ' need to supply other variables as these are required                               '
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    pCurve.QueryPointAndDistance esriNoExtension, theSecondLocation, False, aDummyPoint, distanceAlongCurve, distanceFromCurve, bRight
    SecondPointAlong = distanceAlongCurve
    '''''''''''''''''''''''
    ' Construct sub curve '
    '''''''''''''''''''''''
    pCurve.GetSubcurve FirstPointAlong, SecondPointAlong, False, pNewCurve
    
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Test if the final curve has any length, just to be on the safe side.... '
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    If pNewCurve.Length > 0 Then
        Set Generate_route_between_2_points = pNewCurve
    Else
        Set Generate_route_between_2_points = anEmptyCurve
    End If
End Function‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
MatejSkerjanc
Occasional Contributor

Thank you again, once im back to project regarding traversing I'll use this excerpt.

0 Kudos