In this section:
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
The polyline feature will now become two features.
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.
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.
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.
The first member of ICommand to be called will be OnCreate. Store references to the Application and Editor objects in this member.
Privatem_pAppAsesriFramework.IApplicationPrivatem_pEditorAsesriEditor.IEditorPrivatem_pEditLayersAsesriEditor.IEditLayersPrivate SubICommand_OnCreate(ByValhookAs Object)DimpUIDAs NewesriSystem.UIDSetm_pApp = hook pUID = "esriEditor.Editor"Setm_pEditor = m_pApp.FindExtensionByCLSID(pUID)Setm_pEditLayers = m_pEditorEnd 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.
Privatem_bEnabledAs BooleanPrivate Property GetICommand_Enabled()As BooleanICommand_Enabled = m_bEnabled' Check private memberEnd 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.
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.)
Private WithEventsEditorEventsAsesriEditor.Editor
Private SubICommand_OnCreate(ByValhookAsObject) ...If Notm_pEditorIs Nothing ThenSetm_pEditLayers = m_pEditor' Respond to IEditEvents interface.SetEditorEvents = m_pEditorEnd If End Sub
Private SubSetEnabledStatus()' Assume tool should not be enabledm_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.Ifm_pEditLayers.CurrentLayerIs Nothing Then Exit Sub'Only enable the tool when one polyline feature is selectedIfm_pEditor.SelectionCount = 1Then DimpEnumFeatAsesriGeodatabase.IEnumFeatureSetpEnumFeat = m_pEditor.EditSelection pEnumFeat.ResetDimpFeatureAsesriGeodatabase.IFeatureSetpFeature = pEnumFeat.NextIfpFeature.Shape.IsEmptyThen Exit Sub IfpFeature.Shape.GeometryType = esriGeometryPolylineThenm_bEnabled =True Exit Sub End If End If End Sub
Private SubEditorEvents_OnSelectionChanged() SetEnabledStatusEnd Sub
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.
Private SubITool_OnMouseDown(ByValButtonAs Long,ByValShiftAs Long,ByValXAs Long,ByValYAs Long)DimbInOperationAs BooleanDimpLineSymbolAsesriDisplay.ISimpleLineSymbolSetpLineSymbol =NewesriDisplay.SimpleLineSymbolDimpRubberLineAsesriDisplay.IRubberBandSetpRubberLine =NewesriDisplay.RubberLineDimpPolylineAsesriGeometry.IPolylineSetpPolyline = pRubberLine.TrackNew(m_pEditor.Display, pLineSymbol)IfpPolylineIs Nothing Then Exit Sub IfpPolyline.GeometryType = esriGeometryType.esriGeometryNullThen Exit Sub SetpPolyline.SpatialReference = m_pEditor.Map.SpatialReference
DimpEnumFeatureAsesriGeoDatabase.IEnumFeatureSetpEnumFeature = m_pEditor.EditSelection pEnumFeature.ResetDimpFeatureAsesriGeoDatabase.IFeatureSetpFeature = pEnumFeature.NextDimpFeatureEditAsesriGeoDatabase.IFeatureEditSetpFeatureEdit = pFeature
DimpPointResultAsIPointSetpPointResult = GetIntersection(pFeature.Shape, pPolyline)IfpPointResultIs Nothing Then Exit Sub
DimpActiveViewAsesriCarto.IActiveViewSetpActiveView = m_pEditor.Map pActiveView.PartialRefresh esriViewGeoSelection,Nothing,Nothingm_pEditor.Map.ClearSelectionDimpInvalidAreaAsesriGeoDatabase.IInvalidAreaSetpInvalidArea =NewesriCarto.InvalidAreaSetpInvalidArea.Display = m_pEditor.Display pInvalidArea.Add pFeatureEdit
OnMouseDown Part 2: the edit operation
Now you can begin to perform the actual edit operation.
m_pEditor.StartOperation
bInOperation = TrueDimpSplitSetAsesriSystem.ISetSetpSplitSet = pFeatureEdit.Split(pPointResult) pSplitSet.Reset
DimpFeatureSplitAsesriGeoDatabase.IFeatureSetpFeatureSplit = pSplitSet.NextDo While NotpFeatureSplitIs NothingFlashGeometry pFeatureSplit.ShapeSetpFeatureSplit = pSplitSet.NextLoop
For the full details of the FlashGeometry function, see the sample project code.
' Stop the operationm_pEditor.StopOperation "Split polyline" bInOperation =FalsepInvalidArea.Invalidate esriAllScreenCaches
Private SubITool_OnMouseDown(ByValButtonAs Long,ByValShiftAs Long,ByValXAs Long,ByValYAs Long)On Error GoToErrorHandler: ...Exit Sub' Exit sub to avoid error handlerErrorHandler:IfbInOperationThenm_pEditor.AbortOperation MsgBox "Split failed"End Sub
GetIntersection function
Finally, add the GetIntersection function that you called from the OnMouseDown member.
Private FunctionGetIntersection(ByValpIntersectAsesriGeometry.IGeometry,ByValpOtherAsesriGeometry.IPolyline)AsesriGeometry.IGeometryDimpCloneAsICloneSetpClone = pIntersect.SpatialReferenceIf NotpClone.IsEqual(pOther.SpatialReference)ThenpOther.Project pIntersect.SpatialReferenceEnd If
DimpTopoOpAsesriGeometry.ITopologicalOperatorSetpTopoOp = pOther pTopoOp.Simplify
SetpTopoOp = pIntersecDimpGeomResultAsIGeometrySetpGeomResult = pTopoOp.Intersect(pOther, esriGeometry0Dimension)IfpGeomResultIs Nothing Then Exit Function
The intersect operation is performed by asking for point results, or zero-dimensional results.
If TypeOfpGeomResultIsIPointCollectionThen DimpPointCollAsesriGeometry.IPointCollectionSetpPointColl = pGeomResultIfpPointColl.PointCount >= 1Then SetpGeomResult = 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.
Go to example code
See Also Editor Commands And Tools and Difference Command Example.