¿Cómo aplicar el teorema de los cuatro colores en un mapa de polígonos en ArcGIS / ArcToolBox automáticamente?

19

Necesito aplicar el teorema de los cuatro colores en una forma poligonal de manera que no necesite elegir manualmente cada color para colocar en cada región. Deseo saber si hay alguna extensión, complemento, secuencia de comandos o base de datos que pueda usarse con ArcGIS y ArcToolBox para hacerlo matemáticamente o programáticamente, por lo que podría usarlo por ahora con cada mapa que creé.

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Please_Dont_Bully_Me_SO_Lords
fuente
1
También me gustaría saber si existe esta funcionalidad en otros sistemas que no sean ArcGIS, como QuantumGIS ...
Please_Dont_Bully_Me_SO_Lords
2
Publiqué una solución subóptima en GIS (con Rcódigo de trabajo ) y una solución óptima (que usará tres o incluso dos colores si se puede encontrar que funcionan) en Mathematica . Esa solución es recursiva; La respuesta a mi publicación da una solución de programación lineal. El SIG múltiple ha tenido incorporado un algoritmo de cinco colores (cuatro colores es difícil de hacer; cinco colores es relativamente simple de lograr)
Whuber
Si no tiene un "código hasta ahora", mi recomendación de ArcGIS for Desktop sería comenzar con la herramienta Vecinos poligonales para obtener una tabla que enumere todos los vecinos de cada polígono.
PolyGeo
@PolyGeo: gracias por las herramientas (no lo sabía) pero no pude usarlo para resolver mi problema
radouxju

Respuestas:

12

En primer lugar, gracias por todas las respuestas y comentarios. Desafortunadamente, las herramientas existentes no eran totalmente compatibles con las últimas versiones de QGIS y ArcGIS. Por lo tanto, hice mi propia solución utilizando la herramienta indicada por @polygeo, el complemento QGIS de @Alexandre y el nombre del algoritmo (mapa de cuatro colores) de @Jens.

Aquí está mi código para los interesados ​​(para ArcGIS, pero la segunda parte también podría usarse en QGIS).

arcpy.MakeFeatureLayer_management(fc, fc[:-4]+ "_lyr" )
try:
    arcpy.AddField_management(fc[:-4] + "_lyr", "color", "SHORT")
except:
    print "field alread exists"   
arcpy.CalculateField_management(fc[:-4] + "_lyr", "color",  "10" , "PYTHON")

arcpy.PolygonNeighbors_analysis(fc[:-4] + "_lyr", fc[:-4] + "_tb.dbf" )
graph = []
cursor=arcpy.da.SearchCursor( fc[:-4] + "_tb.dbf" , ("src_FID","nbr_FID") )
for row in cursor:
    graph.append(row)


pols = arcpy.da.UpdateCursor(fc[:-4] + "_lyr", ("OID@","color"))
colored = []
for pol in pols:
    nbrs = [ second for first, second in graph if first == pol[0]]
    usedcolors = []
    for nbr in nbrs:
        usedcolors += [second for first, second in colored if first == nbr]
    pol[1]=[color for color in range(10) if color not in usedcolors][0]
    colored.append(pol)
    pols.updateRow(pol)

Tenga en cuenta que el algoritmo no garantiza que solo se usen 4 colores: aunque se ha demostrado que la solución existe, la "fuerza bruta" es necesaria para lograrlo. En mi caso, obtuve 7 colores que son lo suficientemente pequeños. El script podría tener un bucle adicional hasta que se encuentre la solución, pero necesito hacerlo para cientos de mapas y 7 colores está bien.

radouxju
fuente
2
Esto es genial, muchas gracias por compartirlo. Noté que en ArcGIS 10.2 los nombres de campo en la tabla de salida de PolygonNeighbours han cambiado ligeramente: los campos ahora se llaman src_OBJECT y nbr_OBJECT
Stephen Lead
¿Es óptimo este script, es decir, garantiza que se utilizará un mínimo de colores?
Debajo del radar
1
Por lo que entendí, se necesita fuerza bruta. Como mencioné en mi publicación, debe ejecutarlo varias veces para tener la oportunidad de alcanzar los 4 colores.
radouxju
Todavía funciona muy bien! Tal vez los nombres de campo src_ * y nbr_ * dependen del tipo de entrada. Lo ejecuté ahora con una entrada de geodatabase fc y Desktop 10.5 y se llamaron src_OBJECTID y nbr_OBJECTID. El script podría ajustarse para enumerar los campos que comienzan con src y nbr, por lo que el tipo de entrada (o la versión de ArcGIS) no importa.
BERA
3

Si está utilizando QGIS, creo que lo que necesita es el complemento Colorear un mapa .

Desafortunadamente, el complemento solo está disponible para la versión QGIS 1.8, ¡pero siempre puedes descargar y ver cómo funciona el código!

Alexandre Neto
fuente
3

Esta es una adaptación de la respuesta de @ radouxju en una función. Agregará un campo de color a la capa de entidades de entrada y calculará. Debería funcionar independientemente de las terminaciones de nombre de campo de PolygonNeighbours (parecen ser diferentes para diferentes usuarios / entradas / versiones de arcgis (?))

def color_me(feature_layer):
    import arcpy
    try:
        arcpy.AddField_management(feature_layer, 'color', 'SHORT')
    except:
        print 'field alread exists'   

    arcpy.CalculateField_management(feature_layer, 'color',  '10' , 'PYTHON')

    arcpy.PolygonNeighbors_analysis(feature_layer, r'in_memory\neighbor_table' )
    graph = []
    neighbor_fields = [f.name for f in arcpy.ListFields(r'in_memory\neighbor_table') if f.name.startswith(('src', 'nbr'))]
    cursor=arcpy.da.SearchCursor(r'in_memory\neighbor_table' , neighbor_fields)
    for row in cursor:
        graph.append(row)

    pols = arcpy.da.UpdateCursor(feature_layer, ('OID@','color'))
    colored = []

    for pol in pols:
        nbrs = [ second for first, second in graph if first == pol[0]]
        usedcolors = []
        for nbr in nbrs:
            usedcolors += [second for first, second in colored if first == nbr]
        pol[1]=[color for color in range(10) if color not in usedcolors][0]
        colored.append(pol)
        pols.updateRow(pol)
    arcpy.Delete_management(r'in_memory\neighbor_table')

ingrese la descripción de la imagen aquí

BERA
fuente