Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I have a point and polyline shapefile and want to split lines using points -- want to emulate the precise functionality of Split Line at Point tool (Data Management). I have ArcGIS 10.1 Basic level license and don't want to use third party tools -- want to achieve this by using Basic level license geoprocessing tools available within ArcGIS 10.1. Any suggestions would be very much appreciative.

share|improve this question
1  
Would you be able to edit your Question to indicate whether it is the precise functionality of the Split Line at Point (Data Management) tool that you are trying to emulate or just a subset of it, please? I suspect a diagram would help make what you are after clear. –  PolyGeo Jun 10 at 6:05
1  
Without writing a 3rd party python (or other) tool and using a basic license... not possible. You have to be flexible here somewhere. Unless I'm completely misunderstanding your question; I'm with PolyGeo a diagram might help. –  Michael Miles-Stimson Jun 10 at 6:07
    
@MichaelMiles-Stimson: I can make use of a python code and merge it with my pythonaddins code. Total use of a 3rd party tool is not feasible. –  Ibe Jun 10 at 6:11
    
So by 3rd party means no ET GeoWizards, OGR or Hawth's tools etc.. and does not mean no code at all. Sorry, my misunderstanding, I thought you wanted to do it all in model builder or similar. –  Michael Miles-Stimson Jun 10 at 6:14
    
What about these two links? Can they help a tad? First link Second link –  Eugene Kluichnikov Jun 10 at 7:16

2 Answers 2

Without coding, there is a workaround using linear referencing, but it is not straightforward:

  • create routes

  • locate feature along route

  • create linear route layer events based on the locations

  • Optional: get the attributes back using a join

Just for fun, there is another workaround, but it might modify your geometry a little bit

  • Spatial join with your point and line

  • add a very small value (just above the tolerance of your data) to the distance field.

  • create a buffer around the points

  • union your lines and buffers

  • delete the diminutive segments

  • use integrate to rebuild the topology (this is the stage that will modify your geometry)

share|improve this answer

I have taken a slightly different approach than @radouxju. Here is an arcpy based solution I've written really quickly that will split your lines at points. It requires having two feature classes and each of them should have a unique ID field (to uniquely identify each point and each line).

The script logic is as follows: create several dictionaries to store pointID and lineID and each feature geometry in arcpy.Geometry() instance >> evaluate whether a point is located on the line and if yes, split it. I have not built in yet the searching algorithm that will look around for the closest point yet. The output child lines will inherit all the attributes their parents have (no attribute splitting logic exists either). The output feature class will contain only those lines which had points located on them. You can use simple Select By Location to select and merge with the rest of lines if needed.

The script uses heavily arcpy.Geometry() methods which turned out to be really fast and powerful. For instance, symmetrical difference method that can be initiated on a geometry object in any license, is exposed as a GP tool only in ArcGIS Desktop Advanced.

The geometry of output lines will be practically identical to the source ones. The point located on a line will be buffered and then the result polygon is used to intersect the line and then resulted sublines are integrated to share the same vertex. The smaller buffer zone you create, the more precise the output splitted lines will be with the respect to the source line geometry. Running a buffer of just several cm zone will be more than enough for most applications (unless you are dealing with submillimeter precision data used in civil engineering for constructing bridges or something).

import arcpy
arcpy.env.overwriteOutput = True

line_fc = r"C:\GIS\Temp\test.gdb\Lines"
point_fc = r"C:\GIS\Temp\test.gdb\Points"
point_fc_desc = arcpy.Describe(point_fc)
in_spatial_reference = point_fc_desc.spatialReference

#can use CopyFeatures to write the geometries to disk when troubleshooting
#buffered_point_fc = r"C:\GIS\Temp\test.gdb\PointsBuffered"
#intersected_line_fc = r"C:\GIS\Temp\test.gdb\LineIntersected"
#symmetrical_difference_line_fc = r"C:\GIS\Temp\test.gdb\LineIntersectedSymmDiff"
single_part_splitted_lines = r"C:\GIS\Temp\test.gdb\SplittedLines"
total_splitted_lines = r"C:\GIS\Temp\test.gdb\TotalSplittedLines"
total_splitted_lines_attributed = r"C:\GIS\Temp\test.gdb\TotalSplittedLinesAttributed"

arcpy.TruncateTable_management(total_splitted_lines)

#--- reference dictionaries ----------------#
points_id_geometry_dict = {} #{pointID: pointGeometry}
lines_id_geometry_dict = {} #{lineID: lineGeometry}

search_cursor = arcpy.da.SearchCursor(point_fc,["PointID","SHAPE@"])
for point_feature in search_cursor:
    points_id_geometry_dict[point_feature[0]] = point_feature[1]
del search_cursor

search_cursor = arcpy.da.SearchCursor(line_fc,["LineID","SHAPE@"])
for line_feature in search_cursor:
    lines_id_geometry_dict[line_feature[0]] = line_feature[1]
del search_cursor
#-------------------------------------------#

points_list =[]
lines_list = []

dictionary_lines_points = {} #{lineID: pointID} or {lineID: (pointID, pointID,...)}

point_cursor = arcpy.da.SearchCursor(point_fc,["SHAPE@","PointID"])
line_cursor = arcpy.da.SearchCursor(line_fc,["SHAPE@","LineID"])

for point in point_cursor:
    point_geom_and_id = [point[0],point[1]]
    points_list.append(point_geom_and_id)

for line in line_cursor:
    line_geom_and_id = [line[0],line[1]]
    lines_list.append(line_geom_and_id)

del point_cursor
del line_cursor

for line in lines_list:
    for point in points_list:
        if line[0].contains(point[0]): #finding what points are on what lines
            print "LineID:", line[1], "PointID:", point[1]
            if not line[1] in dictionary_lines_points: #handling situations when multiple points are on the same line
                dictionary_lines_points[line[1]] = point[1] #lineid is key, point ids is value (can be a tuple)
            else:
                dictionary_lines_points[line[1]] = (dictionary_lines_points[line[1]],point[1]) #making tuple for "" line: (point ids) ""

for key_line in dictionary_lines_points.keys(): #iterating each line in the line_fc
    pointID = dictionary_lines_points.get(key_line) #getting what PointID have match to lineID

    if not isinstance(pointID,tuple):
        input_point_geom_object = points_id_geometry_dict.get(pointID) #obtain point geometry based on pointID
        multipoints = input_point_geom_object
    else:
        merged_point_geometries = arcpy.Array() #constructing a multipoint (if multiple points are on the same line)
        for pointID_element in pointID:
            input_point_geom_object = points_id_geometry_dict.get(pointID_element)
            merged_point_geometries.add(input_point_geom_object.centroid) #creating array of points
            multipoints = arcpy.Multipoint(merged_point_geometries,in_spatial_reference)

    line_geometry_object = lines_id_geometry_dict.get(key_line) #obtain line geometry based on LineID

    buffered_point = multipoints.buffer(0.1) #same units as the geometry
    intersected_line = buffered_point.intersect(line_geometry_object,2) #2 - polyline returned
    symmetrical_difference_line = intersected_line.symmetricDifference(line_geometry_object)
    arcpy.MultipartToSinglepart_management(symmetrical_difference_line,single_part_splitted_lines)
    arcpy.Integrate_management(single_part_splitted_lines,"0.1 Meters")
    arcpy.Append_management(single_part_splitted_lines,total_splitted_lines,"NO_TEST")
    arcpy.Delete_management(single_part_splitted_lines)

    arcpy.SpatialJoin_analysis(target_features=total_splitted_lines,
                               join_features=line_fc,
                               out_feature_class=total_splitted_lines_attributed,
                               join_operation="JOIN_ONE_TO_ONE",join_type="KEEP_ALL",
                               match_option="INTERSECT",search_radius="#",distance_field_name="#")

##TODO
#iterate through line features that did not have any points located on them (distanceTo geometry method / select by location)
#if there are any points located within the search distance >> move them on line and run the logic >> append to the output fc
#if no point features are located within the search distance >> append them directly to the output fc
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.