Distinguishing lines that intersect from lines that touch?

For a single feature at a time, you can do this pretty easily interactively using the normal Select By Location dialog, using the following key as a guide to the spatial relationship types for line on line overlays (from Select by Location: graphic examples):

image
(source: arcgis.com)

Select line using line

INTERSECT              A, C, D, E, F, G, H, I, J

CONTAINS               G, H

COMPLETELY_CONTAINS    G

CONTAINS_CLEMENTINI    G, H

WITHIN                 F, H

COMPLETELY_WITHIN      F

WITHIN_CLEMENTINI      F, H

ARE_IDENTICAL_TO       H

BOUNDARY_TOUCHES       C, E

The relevant relationship types in this case are INTERSECT and BOUNDARY_TOUCHES. As you can see from the diagram above, you can use BOUNDARY_TOUCHES to select the features that touch an endpoint of the line. If exactly two features are selected then you have your Case 1. If a feature is not touched by any other features but only intersected by them, then BOUNDARY_TOUCHES will select nothing. INTERSECT will select all features that intersect regardless of whether they touch at an endpoint or not. So if you know there are no features touching endpoints, but you find there are features intersecting, then you have your Case 2.

To automate the process you can use the following Python script (implement as a script tool if desired) to calculate the number of touches and intersections for each feature in a feature class or layer:

import arcpy

################################ Configuration #################################
numTouchesField = "NUM_TOUCHES"
numIntersectionsField = "NUM_INTERSECTIONS"
################################################################################

def countTouches(layer, feature):
    """Returns the number of times the boundary of a feature touches other
    features in the same feature layer."""
    return countSpatialRelation(layer, feature, "BOUNDARY_TOUCHES")

def countIntersections(layer, feature):
    """Returns the number of times a feature intersects other features in the
    same feature layer."""
    return countSpatialRelation(layer, feature, "INTERSECT") - 1 # Subtract 1 because the feature will always intersect its clone in the feature layer

def countSpatialRelation(layer, feature, relation):
    """Returns the number of times a feature meets the specified spatial
    relationship with other features in the same feature layer."""
    arcpy.SelectLayerByLocation_management(layer, relation, feature)
    count = int(arcpy.GetCount_management(layer).getOutput(0))
    return count

def addField(table, fieldName, fieldType):
    """Adds a fields of the given name and type to a table, unless a field with
    the same name already exists."""
    desc = arcpy.Describe(table)
    fieldInfo = desc.fieldInfo
    fieldIndex = fieldInfo.findFieldByName(fieldName)
    if fieldIndex == -1:
        # Field does not exist, add it
        arcpy.AddField_management(table, fieldName, fieldType)

def countTouchesAndIntersections(layer):
    """Adds and populates fields describing the number of times each feature
    touches and intersects other features in the feature layer."""
    addField(layer, numTouchesField, "LONG")
    addField(layer, numIntersectionsField, "LONG")
    desc = arcpy.Describe(layer)
    shapeField = desc.shapeFieldName
    rows = arcpy.UpdateCursor(layer)
    for row in rows:
        feature = row.getValue(shapeField)
        row.setValue(numTouchesField, countTouches(layer, feature))
        row.setValue(numIntersectionsField, countIntersections(layer, feature))
        rows.updateRow(row)
    del row, rows

if __name__ == "__main__":
    layer = arcpy.MakeFeatureLayer_management(arcpy.GetParameterAsText(0))
    countTouchesAndIntersections(layer)

Once that has run, you can easily query for the features that touch exactly twice and intersect exactly twice (Case 1), and those that touch 0 times and intersect exactly twice (Case 2).

Example definition queries:

  • Case 1 (Touches twice, intersects twice): "NUM_TOUCHES" = 2 AND "NUM_INTERSECTIONS" = 2
  • Case 2 (Touches none, intersects twice): "NUM_TOUCHES" = 0 AND "NUM_INTERSECTIONS" = 2

See the below screenshot for an illustration of the instances of the two cases being found: ArcMap screenshot showing various line intersection/touch relationships

Note that with real world data, normally street segments are broken up at intersections, and dangles only occur when roads pass over one another as at an interchange or bridge. So normally you have the same number of features intersecting as touching.

For the more general case, you might want to look for any dangles by checking whether "NUM_INTERSECTIONS" > "NUM_TOUCHES".


Split Line At Vertices (Data Management)

"Creates a feature class containing lines that are generated by splitting input lines or polygon boundaries at their vertices"

Keep Attribution.

enter image description here

http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//00170000003z000000