1

I have two shapefiles. First of them, there is about 115 000 points (clients and their field size) All together there is about 16 226 different clients. In the other shapefile I have calculated the median point for all the clients. Now, I want to calculate the distance from each client field to its corresponding median point. How can i do it in Model Builder?? Doing it one by one takes a lot of time.

I really hope someone can help me.

2 Answers 2

2

Since you have two shapefiles (one contains median point for each client and another contains source position points), Generate Near Table GP tool might be a good candidate for finding out the distance from each median point to the points around. The only thing left is to iterate over each client's median point without taking into considerations others. We have to select and use only one client per iteration. For me, a Python solution is easier than ModelBuilder based one.

This code should work for 10.0 unless I have missed something. You would need to create a script tool and update paths to the data. You can save the code below in a .py file and then use any text editor to edit the file).

To make it easier to understand the workflow, I've attached a picture. Red points are in one feature class and represent median points, blacks and greens represent source points in another feature class (each have a field ClientID, symbology is based on ClientID, labels are just ObjectIDs).

enter image description here

import arcpy
arcpy.env.workspace = r"C:\GIS\Temp\test.gdb"
arcpy.env.overwriteOutput = True

source_pnts = r"C:\GIS\Temp\test.gdb\source_pnts"
median_pnts = r"C:\GIS\Temp\test.gdb\median_pnts"
iter_neartable = r"NearTableTemp"
sum_neartable = r"NearTableAllClients"

fieldname = "ClientID"
search_cursor = arcpy.SearchCursor(median_pnts,"", "", fieldname)
counter = 0
for row in search_cursor:
    #print row.ClientID
    median_pnts_lyr = arcpy.MakeFeatureLayer_management(median_pnts,"OneClientOnlyMedian","""ClientID = {}""".format(row.getValue(fieldname)))
    print int(arcpy.GetCount_management(median_pnts_lyr).getOutput(0))
    source_pnts_lyr = arcpy.MakeFeatureLayer_management(source_pnts,"OneClientOnlySource","""ClientID = {}""".format(row.getValue(fieldname)))
    print int(arcpy.GetCount_management(source_pnts_lyr).getOutput(0))

    iteration_table = arcpy.GenerateNearTable_analysis(median_pnts_lyr,source_pnts_lyr,iter_neartable, "#","NO_LOCATION","NO_ANGLE","ALL","0","PLANAR")
    if counter == 0:
        arcpy.CopyRows_management(iteration_table,sum_neartable)
        arcpy.TruncateTable_management(sum_neartable)
        arcpy.Append_management(iteration_table,sum_neartable,"NO_TEST")
        counter = counter + 1
    else:
        arcpy.Append_management(iteration_table,sum_neartable,"NO_TEST")
5
  • I tried this but it takes account other clients mean centers too, because some are near to each other. I need to classify source points by client number, but no distance tool have case field option to do this.
    – Kristin
    May 7, 2014 at 14:46
  • Ah, I got it. Would you consider an arcpy (Python) based solution? Is it just a one time job? May 7, 2014 at 14:50
  • I never used arcpy solution but yes this is one time job.
    – Kristin
    May 7, 2014 at 14:51
  • I'll publish some code you could run in a while then :) May 7, 2014 at 14:53
  • Start with a test sample data first to see that you get expected results! May 7, 2014 at 15:30
0

I had to come up with a solution for something very similar to this just last week. This is in essence what I did:

Steps

  1. Add distance field to your client dataset (the one with 115,000 points)
  2. Get the spatial reference of your data
  3. Open a search cursor on the mean point, get the X and Y
  4. Open an update cursor on the client points. Loop through each point and get the X and Y of the client. Create a table in memory that will hold the xy fields of both the current client and the mean point. Insert the xy data into the table. Note: this table will only have 1 record each time.
  5. Create an XY line using the newly created table. This will create a line from the current client to the mean point based on the x and y values, the distance type, and your spatial reference.
  6. Open another search cursor on the new xy line, read the shape length and insert it back into the client dataset.

    import arcpy
    
    def Delete(name):
        if arcpy.Exists(str(name) +'.shp'):
            arcpy.Delete_management(str(name) +'.shp')
        if arcpy.Exists(name):
            arcpy.Delete_management(name)
    
    def CalculateDistance(mean, clients):
        desc = arcpy.Describe(clients)
        spatialRef = desc.SpatialReference
        with arcpy.da.SearchCursor(mean,['SHAPE@X','SHAPE@Y']) as SC:
            for mean_row in SC:
                mean_x = mean_row[0]
                mean_y = mean_row[1]
                with arcpy.da.UpdateCursor(clients,['SHAPE@X','SHAPE@Y','distance_to_mean']) as UC:
                    for client_row in UC:
    
                        client_x = client_row[0]
                        client_y = client_row[1]
    
                        mem_table = "in_memory//table"
                        Delete(mem_table)
                        table = arcpy.CreateTable_management("in_memory","table")
                        arcpy.AddField_management(table,"client_x", "DOUBLE")
                        arcpy.AddField_management(table,"client_y", "DOUBLE")
                        arcpy.AddField_management(table,"mean_x", "DOUBLE")
                        arcpy.AddField_management(table,"mean_y", "DOUBLE")
    
                        with arcpy.da.UpdateCursor(table,['client_x','client_y','mean_x','mean_y']) as UC2:
                            for tableRow in UC2:
                                tableRow[0] = client_x
                                tableRow[1] = client_y
                                tableRow[2] = mean_x
                                tableRow[3] = mean_y
                                UC2.updateRow(tableRow)
    
                        mem_line = "in_memory//xy_line"
    
                        Delete(mem_line)
    
                        xy_line = arcpy.XYToLine_management(table,mem_line,'SHAPE@X','SHAPE@Y','mean_x','mean_y',"GEODESIC","ID_FIELD",spatialRef)
    
                        with arcpy.da.SearchCursor(xy_line,["SHAPE@LENGTH"]) as SC2:
                            for row in SC2:
                                client_row[2] = row[0]
    
    
    
    
    
    mean_point = your mean point dataset
    
    client_points = your client points dataset
    # add distance field to client points
    arcpy.AddField_management(client_points,"distance_to_mean","DOUBLE")
    
    CalculateDistance(mean_point, client_points)
    

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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