Set Flow by Digitized Direction
clsFlowDirectionSolver.cls

' Copyright 2008 ESRI
' 
' All rights reserved under the copyright laws of the United States
' and applicable international laws, treaties, and conventions.
' 
' You may freely redistribute and use this sample code, with or
' without modification, provided you include the original copyright
' notice and use restrictions.
' 
' See use restrictions at <your ArcGIS install location>/developerkit/userestrictions.txt.
' 




'The Set Flow by Digitized Direction command sets the flow direction for the
'current geometric network according to the digitized direction of the features.
'For each feature, the flow direction is set along the digitized direction of the
'feature. In order to be able to set the flow direction, an edit session is
'required. The command will be enabled if any of the features in the current
'geometric network have flow direction that is not along their digitized direction.

Option Explicit

Implements ICommand

'declare a module-level variable to hold a reference to the ArcMap application
Private m_pApplication As esriFramework.IApplication
'declare a module-level variable to hold a reference to the Utility Network
'Analysis extension
Private m_pUtilityNetworkAnalysisExt As esriEditorExt.IUtilityNetworkAnalysisExt
'declare a module-level variable to hold a reference to  the Editor extension
Private m_pEditor As esriEditor.IEditor

Private Property Get ICommand_Bitmap() As esriSystem.OLE_HANDLE
  ICommand_Bitmap = frmResources.Picture
End Property

Private Property Get ICommand_Caption() As String
  ICommand_Caption = "Set Flow by Digitized Direction"
End Property

Private Property Get ICommand_Category() As String
  ICommand_Category = "Developer Samples"
End Property

Private Property Get ICommand_Checked() As Boolean
  ICommand_Checked = False
End Property

Private Property Get ICommand_Enabled() As Boolean
'enable the button if there is an edit session, and if any of the features
'in the current network have flow direction other than along their
'digitized direction

  Dim pUtilityNetwork As esriGeoDatabase.IUtilityNetwork   'holds a reference to the current network
  Dim pEdgeEIDs As esriGeoDatabase.IEnumNetEID   'stores a list of edge EID's
  Dim eFlowDirection As esriGeoDatabase.esriFlowDirection    'flow direction value
  Dim lngEdgeEIDCount As Long   'stores the number of edge EID's in the network
  Dim lngEdgeEID As Long    'stores the current edge EID
  Dim i As Long   'loop iterator
  
  'by default, disable the command
  ICommand_Enabled = False
  
  'if there is not a current edit session, then disable the command
  If m_pEditor.EditState <> esriStateEditing Then Exit Sub
  
  'check to see if the flow direction is properly set
  'get a reference to the IUtilityNetwork interface for the current network
  Set pUtilityNetwork = GetCurrentNetwork
  'get a list of edge EIDs for the current network
  Set pEdgeEIDs = GetCurrentEIDs(esriETEdge)
  
  'for each edge EID, determine if the flow direction is set correctly
  'reset the enumeration of edge EID's so that the next one returned
  'is the first one in the list
  pEdgeEIDs.Reset
  'determine the number of edge EID's in the enumeration
  lngEdgeEIDCount = pEdgeEIDs.Count
  For i = 0 To lngEdgeEIDCount - 1
    'get the next edge EID
    lngEdgeEID = pEdgeEIDs.Next
    'check the flow direction for this edge
    eFlowDirection = pUtilityNetwork.GetFlowDirection(lngEdgeEID)
    'if the flow direction is not with the digitized direction, then
    'enable the command
    If Not eFlowDirection = esriFDWithFlow Then
      ICommand_Enabled = True
      'exit the property, since only one edge needs to have incorrect flow
      'direction in order to enable the command
      Exit Property
    End If
  Next i  'next Edge EID
      
End Property

Private Property Get ICommand_HelpContextID() As Long

End Property

Private Property Get ICommand_HelpFile() As String

End Property

Private Property Get ICommand_Message() As String
  ICommand_Message = "Set flow direction by the digitized direction of each edge."
End Property

Private Property Get ICommand_Name() As String
  ICommand_Name = "MyFlowDirectionSolver.clsFDSolver"
End Property

Private Sub ICommand_OnClick()
'set flow direction using the digitized direction
  
  Dim pUtilityNetwork As esriGeoDatabase.IUtilityNetwork   'holds a reference to the current network
  Dim pEdgeEIDs As esriGeoDatabase.IEnumNetEID   'stores a list of edge EID's
  Dim pMxDocument As esriArcMapUI.IMxDocument   'holds a reference to the ArcMap document
  Dim pActiveView As esriCarto.IActiveView   'hold a reference to the current view in ArcMap
  Dim lngEdgeEIDCount As Long   'stores the number of edge EID's in the network
  Dim lngEdgeEID As Long    'stores the current edge EID
  Dim i As Long   'loop iterator
  
  'get a reference to the current network
  Set pUtilityNetwork = GetCurrentNetwork
  
  'create an edit operation enabling an undo for this operation
  m_pEditor.StartOperation
  
  'get a list of the EID's for edges in the network
  Set pEdgeEIDs = GetCurrentEIDs(esriETEdge)
  
  'set the flow direction for each edge in the network
  'reset the enumeration
  pEdgeEIDs.Reset
  'determine the number of edges in the enumeration
  lngEdgeEIDCount = pEdgeEIDs.Count
  For i = 0 To lngEdgeEIDCount - 1
    'get the next edge EID
    lngEdgeEID = pEdgeEIDs.Next
    'set the flow direction for this edge
    pUtilityNetwork.SetFlowDirection lngEdgeEID, esriFDWithFlow
  Next i
  'stop
  
  'stop the edit operation and specify the name of this edit operation
  m_pEditor.StopOperation "Set Flow Direction"
  
  'refresh the display to update the flow direction arrows
  'obtain a reference to the ArcMap document
  Set pMxDocument = m_pApplication.Document
  'obtain a reference to the current view
  Set pActiveView = pMxDocument.ActiveView
  'refresh the graphics layer to refresh the flow direction arrows
  pActiveView.PartialRefresh esriViewGraphics, Nothing, Nothing
  
End Sub

Private Sub ICommand_OnCreate(ByVal hook As Object)
  
  Dim pUID_UNA As New esriSystem.UID
  Dim pUID_Editor As New esriSystem.UID
  
  'set a reference to the application
  Set m_pApplication = hook
  'obtain a reference to the Utility Network Analysis extension
  pUID_UNA = "esriEditorExt.UtilityNetworkAnalysisExt"
  Set m_pUtilityNetworkAnalysisExt = m_pApplication.FindExtensionByCLSID(pUID_UNA)
  'obtain a reference to the Editor extension
  pUID_Editor = "esriEditor.Editor"
  Set m_pEditor = m_pApplication.FindExtensionByCLSID(pUID_Editor)
  
End Sub

Private Property Get ICommand_Tooltip() As String
  ICommand_Tooltip = "Set flow direction by digitized direction."
End Property

Private Function GetCurrentEIDs(eElementType As esriGeoDatabase.esriElementType) As esriGeoDatabase.IEnumNetEID
'return an enumeration of network EID's of network elements of the given
'type for the current network
  Dim pNetwork As esriGeoDatabase.INetwork   'holds a reference to the current network
  Dim pEnumNetEID As esriGeoDatabase.IEnumNetEID   'stores a list of network EID's
  
  'get a reference to the current network
  Set pNetwork = GetCurrentNetwork
  
  'get a list of the EID's for edges in the network
  Set pEnumNetEID = pNetwork.CreateNetBrowser(eElementType)
  'return the enumeration
  Set GetCurrentEIDs = pEnumNetEID
  
End Function

Private Function GetCurrentNetwork() As esriGeoDatabase.INetwork
'return a reference to the current network

  Dim pNetworkAnalysisExt As esriEditorExt.INetworkAnalysisExt
    'holds a reference to the Utility Network Analysis extension
    '(INetworkAnalysisExt interface)
  Dim pGeometricNetwork As esriGeoDatabase.IGeometricNetwork   'references the current geometric network
  Dim pNetwork As esriGeoDatabase.INetwork   'reference the current network object
  
  'get a reference to the current network
  'QI for the INetworkAnalysisExt interface using IUtilityNetworkAnalysisExt
  Set pNetworkAnalysisExt = m_pUtilityNetworkAnalysisExt
  'get a reference to the current geometric network
  Set pGeometricNetwork = pNetworkAnalysisExt.CurrentNetwork
  'get a reference to the network object
  Set pNetwork = pGeometricNetwork.Network
  
  'return the Network object
  Set GetCurrentNetwork = pNetwork
  
End Function