Apply symbology based on an algorithm

1264
10
08-28-2019 01:08 PM
DaveGrolling1
New Contributor III

Been battling this problem for a long time now, so hoping someone here can shed light on a possible solution. The problem is that I have 100 points and I want to apply a color palette to the points so that no two points within 25 miles have the same color. The issue I'm trying to prevent is having points close to each other being mistaken for similarity.

I think I'm getting somewhere with running the Generate Near Table in ArcGIS Pro 2.3 which will find all near points within 25 miles. Conceptually, I'm thinking this could turn into a Python script or ModelBuilder model where a first point is selected, Color field is given a value, then it moves on to the next record, but it can't be from a list of OIDs found in the Near Table result for that next record.

To recap, I'm trying to apply, for example, 10 colors to 100 points, where no points within 25 miles of each other gets the same color applied. Some code that I've been trying to play around with:

import arcpy

# Process: Select Layer By Attribute
arcpy.SelectLayerByAttribute_management('InputPoints100', 'NEW_SELECTION',"OBJECTID = 1")

# Process: Calculate Field
arcpy.management.CalculateField("InputPoints100", "Color", '"ONE"', "ARCADE", "ONE")

arcpy.Append_management('InputPoints100', 'InputPoints_LIST', 'TEST')

################################################################# ONE ######################################################################
arcpy.SelectLayerByLocation_management('InputPoints100', 'WITHIN_A_DISTANCE', 'InputPoints100',"25 Miles", 'NEW_SELECTION', 'INVERT')

layer = "InputPoints100"
count = 1

def randomColor():

    def SelectRandomByCount (layer, count):
        import random
        layerCount = int (arcpy.GetCount_management (layer).getOutput (0))
        if layerCount < count:
            print("input count is greater than layer count")
            return
        oids = [oid for oid, in arcpy.da.SearchCursor (layer, "OID@")]
        oidFldName = arcpy.Describe (layer).OIDFieldName
        delimOidFld = arcpy.AddFieldDelimiters (layer, oidFldName)
        randOids = random.sample (oids, count)
        oidsStr = ", ".join (map (str, randOids))
        sql = "{0} IN ({1})".format (delimOidFld, oidsStr)
        arcpy.SelectLayerByAttribute_management (layer, "", sql)

    SelectRandomByCount(layer, count)

    arcpy.management.CalculateField("InputPoints100", "Color", '"ONE"', "ARCADE", "ONE")

    arcpy.Append_management('InputPoints100', 'InputPoints_LIST', 'TEST')

with arcpy.da.SearchCursor(layer,field_names = "ObjectID") as cursor:
    for row in cursor:
        randomColor()

print("Done!")‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
10 Replies
DaveGrolling1
New Contributor III

Xander Bakker‌,

This will be a solution for a current mapping application where users can search for their doctor's office where they work and view attributes and such. Doctor offices have service areas that compete for populations, so it's important that when they see office X, that it's not being confused with office Y because they are the same color. The search distance of 25 miles is not a set number, but an example to get the logic of the problem underway. We have a lot of users and we don't know the average scale at which they're using the application, but in order to clear out the 'noise', one does have to zoom in to select their office of choice.

With that said, I will back up and attempt to explain what I was trying to do in the code I originally posted above. I was thinking about dividing the data set of 1,500 points into 10 samples, one for each color in the palette. This comes out to 150 points per sample. However, it doesn't solve the problem of areas with clustering.

0 Kudos