ArcGIS SDK  

Extending ArcObjects

Split at Intersection Tool Example

In this section:

  1. The case for a split at intersection tool
  2. Creating an editor tool
  3. Creating the SplitAtIntersectionTool

Split at Intersection Tool Example

Example Code Click here.

Description This project provides a custom editor tool that can be used to perform a split operation on a polyline feature, splitting the polyline at a point specified by another polyline tracked on the map using the tool. The tool will appear on the Editor toolbar.

Design Coclass SplitToolAtIntersection is a subtype of the Tool abstract class and also sinks the IEditEvents interface.

License required ArcEditor or above

Libraries Carto, Display, Editor, Framework, Geodatabase, Geometry, System, and SystemUI

Languages Visual Basic

Categories ESRI Mx Commands

Interfaces ICommand, ITool, and IEditEvents

How to use

    1. Register the SplitToolVB.dll and double-click the SplitToolVB.reg file to register to component categories.
    2. Open ArcMap, click Tools, then click Customize.
    3. In the Customize dialog box, click the Commands tab, then click on 'Extending ArcObjects' in the left-hand Categories list.
    4. In the Commands list, click the Split At Intersection tool and drag this onto the Editor toolbar. Click Close to dismiss the Customize dialog box.
    5. Add data with polyline features to ArcMap.
    6. Click Editor and click Start Editing. Make sure that the polyline layer you added is editable and is the target layer.
    7. Select a polyline feature, then click the Split At Intersection tool.
    8. Track a line onto the map that intersects the feature at the location you want to perform the split. Double-click to end the tracked line.

      The polyline feature will now become two features.


The case for a split at intersection command

The standard Editor menu provides a split command which can be used to edit a polyline feature, creating two polyline features by splitting the feature based on a click of the mouse at the desired split location.

If you are editing a polygon feature, you have a number of options for splitting a feature, including splitting the polygon based on lines and polygons. However, if you have a polyline feature that you want to split, the existing tools do not allow you to do this using a line tracked on scree. As no editor command or tool provides the operation you require, you will create a custom editor tool to meet your requirements.

This example demonstrates how to create an editor tool to split a polyline feature into two features at the location of an intersection with a tracked line.


Creating an editor tool

By reviewing the Editor object model diagram, you will see the EditTool class implements ICommand, ITool, and IEditTool. IEditTool is an interface that provides a link to the source of edit events; however, this interface is not implementable in VB.


As discussed previously in Editor Commands and Tools, a custom edit tool is created like any other tool, as a subtype of the Tool abstract class, by implementing the ICommand and ITool interfaces. Like edit commands, edit tools often sink the IEditEvents interface of the Editor, to respond to changes in the state of the Editor.



Creating the SplitAtIntersectionTool

You can solve this scenario with a custom tool. Tools are advanced commands; they additionally implement the ITool interface, which allows them to respond to mouse and keyboard events. You will create a subtype of Tool called SplitAtIntersectionTool by implementing ICommand and ITool and sinking the IEditEvents outbound interface from the Editor coclass.


Implementing ICommand

The first member of ICommand to be called will be OnCreate. Store references to the Application and Editor objects in this member.

[Visual Basic 6]
Private m_pApp As esriFramework.IApplication
Private m_pEditor As esriEditor.IEditor
Private m_pEditLayers As esriEditor.IEditLayers
  
Private Sub ICommand_OnCreate(ByVal hook As Object)
  Dim pUID As New esriSystem.UID
  Set m_pApp = hook
  pUID = "esriEditor.Editor"
  Set m_pEditor = m_pApp.FindExtensionByCLSID(pUID)
  Set m_pEditLayers = m_pEditor
End Sub

Add a member variable to your command to keep track of the Enabled status of your command, then return the value from the Enabled property. You will set this value later when implementing IEditEvents.

[Visual Basic 6]
Private m_bEnabled As Boolean
  
Private Property Get ICommand_Enabled() As Boolean
  ICommand_Enabled = m_bEnabled ' Check private member
End Property

The remaining members of ICommand should be implemented as any other standard command, Name, Category, Caption, and so on. Remember to specify a bitmap, as a tool is displayed by default using only its Bitmap. You do not need to take any action in OnClick, as you will instead be using the ITool::OnMouseDown member to perform your edit.

Implementing IEditEvents

By listening to the editor events you can control access to your tool. You should enable your tool when the end user has selected one polyline feature, by handling the OnSelectionChanged event. (Unlike the DifferenceCommand, the Editor's target layer is not important to the tool since its modifying an existing feature not creating a new one in the target layer.)

  1. Begin by sinking the default interface of the Editor coclass, IEditEvents, in your class.
    [Visual Basic 6]
    Private WithEvents EditorEvents As esriEditor.Editor
  2. Add a line to the ICommand::OnCreate method to start listening to the events.
    [Visual Basic 6]
    Private Sub ICommand_OnCreate(ByVal hook As Object)
      ...
      If Not m_pEditor Is Nothing Then
        Set m_pEditLayers = m_pEditor
        ' Respond to IEditEvents interface.
        Set EditorEvents = m_pEditor
      End If
    End Sub
  3. Create a function called SetEnabledStatus. In this function you need to verify that the user has selected a single polyline feature.
    [Visual Basic 6]
    Private Sub SetEnabledStatus()
      ' Assume tool should not be enabled
      m_bEnabled = False
      
      ' Make sure the current layer exists. When ArcMap is shutting down,
      ' the Editor fires various events, some of which we are listening to,
      ' but the Editor's properties have likely been emptied at this point.
      If m_pEditLayers.CurrentLayer Is Nothing Then Exit Sub
      
      'Only enable the tool when one polyline feature is selected
      If m_pEditor.SelectionCount = 1 Then
        
        Dim pEnumFeat As esriGeodatabase.IEnumFeature
        Set pEnumFeat = m_pEditor.EditSelection
        pEnumFeat.Reset
        
        Dim pFeature As esriGeodatabase.IFeature
        Set pFeature = pEnumFeat.Next
        If pFeature.Shape.IsEmpty Then Exit Sub
        
        If pFeature.Shape.GeometryType = esriGeometryPolyline Then
          m_bEnabled = True
          Exit Sub
        End If
      End If
    End Sub
  4. Then implement the OnSelectionChanged member of IEditEvents, and call the SetEnabledStatus function from this event handler to set the Enabled status.
    [Visual Basic 6]
    Private Sub EditorEvents_OnSelectionChanged()
      SetEnabledStatus
    End Sub

Implementing ITool

You can perform the main operation of your Tool in OnMouseDown.

OnMouseDown Part 1: calculating the intersection

In the first part of this function, you need to establish the two lines and their intersection points.

  1. First, you need to track a new line which will be used to split the existing feature. If the track operation is unsuccessful, the intersection cannot take place, so exit the function.
    [Visual Basic 6]
    Private Sub ITool_OnMouseDown(ByVal Button As Long, ByVal Shift As Long, ByVal X As Long, ByVal Y As Long)
      Dim bInOperation As Boolean
      Dim pLineSymbol As esriDisplay.ISimpleLineSymbol
      Set pLineSymbol = New esriDisplay.SimpleLineSymbol
      
      Dim pRubberLine As esriDisplay.IRubberBand
      Set pRubberLine = New esriDisplay.RubberLine
      
      Dim pPolyline As esriGeometry.IPolyline
      Set pPolyline = pRubberLine.TrackNew(m_pEditor.Display, pLineSymbol)
      If pPolyline Is Nothing Then Exit Sub
      If pPolyline.GeometryType = esriGeometryType.esriGeometryNull Then Exit Sub
      Set pPolyline.SpatialReference = m_pEditor.Map.SpatialReference
  2. Find the selected Polyline feature.
    [Visual Basic 6]
      Dim pEnumFeature As esriGeoDatabase.IEnumFeature
      Set pEnumFeature = m_pEditor.EditSelection
      pEnumFeature.Reset
      Dim pFeature As esriGeoDatabase.IFeature
      Set pFeature = pEnumFeature.Next
      Dim pFeatureEdit As esriGeoDatabase.IFeatureEdit
      Set pFeatureEdit = pFeature
  3. Next, you need to find the point where the feature and tracked line intersect. Create a function to perform the intersection; see below for details of how the intersection was performed.
  4. Now call your intersection function from the OnMouseDown member; the geometry returned will always be a point, unless the operation failed, in which case the result will be null.
    [Visual Basic 6]
      Dim pPointResult As IPoint
      Set pPointResult = GetIntersection(pFeature.Shape, pPolyline)
      If pPointResult Is Nothing Then Exit Sub
  5. Clear the current selection, and prepare to refresh the map by specifying a new Invalid area.
    [Visual Basic 6]
      Dim pActiveView As esriCarto.IActiveView
      Set pActiveView = m_pEditor.Map
      pActiveView.PartialRefresh esriViewGeoSelection, Nothing, Nothing
      m_pEditor.Map.ClearSelection
      Dim pInvalidArea As esriGeoDatabase.IInvalidArea
      Set pInvalidArea = New esriCarto.InvalidArea
      Set pInvalidArea.Display = m_pEditor.Display
      pInvalidArea.Add pFeatureEdit

OnMouseDown Part 2: the edit operation

Now you can begin to perform the actual edit operation.

  1. Start a new edit operation.
    [Visual Basic 6]
      m_pEditor.StartOperation
      bInOperation = True
  2. Perform the split operation using the IFeatureEdit::Split method.
    [Visual Basic 6]
      Dim pSplitSet As esriSystem.ISet
      Set pSplitSet = pFeatureEdit.Split(pPointResult)
      pSplitSet.Reset
  3. Iterate the results of the split operation, and display the results to the user by flashing the shape of each result shape to the display. This is done by adding a new function to your class called FlashGeometry.
    [Visual Basic 6]
      Dim pFeatureSplit As esriGeoDatabase.IFeature
      Set pFeatureSplit = pSplitSet.Next
      Do While Not pFeatureSplit Is Nothing
        FlashGeometry pFeatureSplit.Shape
        Set pFeatureSplit = pSplitSet.Next
      Loop

    For the full details of the FlashGeometry function, see the sample project code.

  4. Now the split has been performed; stop the edit operation.
    [Visual Basic 6]
      ' Stop the operation
      m_pEditor.StopOperation "Split polyline"
      bInOperation = False
      pInvalidArea.Invalidate esriAllScreenCaches
  5. You should add an error handler to OnMouseDown to stop any edit operation if there is a problem during the function.
    [Visual Basic 6]
    Private Sub ITool_OnMouseDown(ByVal Button As Long, ByVal Shift As Long, ByVal X As Long, ByVal Y As Long)
      On Error GoTo ErrorHandler:
      
      ...
      
      Exit Sub ' Exit sub to avoid error handler
    ErrorHandler:
      If bInOperation Then m_pEditor.AbortOperation
      MsgBox "Split failed"
    End Sub

GetIntersection function

Finally, add the GetIntersection function that you called from the OnMouseDown member.

  1. Start by checking that the coordinate systems of the two lines are equal, and if not, project the polyline.
    [Visual Basic 6]
    Private Function GetIntersection(ByVal pIntersect As esriGeometry.IGeometry, ByVal pOther As esriGeometry.IPolyline) As esriGeometry.IGeometry
      Dim pClone As IClone
      Set pClone = pIntersect.SpatialReference
      If Not pClone.IsEqual(pOther.SpatialReference) Then
        pOther.Project pIntersect.SpatialReference
      End If
  2. Next, ensure that the polyline that was tracked on screen is Simple (another requirement for a spatial operation).
    [Visual Basic 6]
      Dim pTopoOp As esriGeometry.ITopologicalOperator
      Set pTopoOp = pOther
      pTopoOp.Simplify
  3. Now perform the intersect operation.
    [Visual Basic 6]
      Set pTopoOp = pIntersec
      Dim pGeomResult As IGeometry
      Set pGeomResult = pTopoOp.Intersect(pOther, esriGeometry0Dimension)
      If pGeomResult Is Nothing Then Exit Function

    The intersect operation is performed by asking for point results, or zero-dimensional results.

  4. Check if there are multiple points of intersection. In this case, you can simply use the first point of intersection to perform the split.
    [Visual Basic 6]
      If TypeOf pGeomResult Is IPointCollection Then
        Dim pPointColl As esriGeometry.IPointCollection
        Set pPointColl = pGeomResult
        If pPointColl.PointCount >= 1 Then
          Set pGeomResult = pPointColl.Point(0)
        Else
          Exit Function
        End If
      End If

    If you wanted to adapt this example, you may want to perform a split into more than just two lines here, if more than one intersection is found.

 

Now you can compile the SplitAtIntersectionTool project and use it in an ArcMap edit session.

 


Back to top

Go to example code

See Also Editor Commands And Tools and Difference Command Example.