Comment appliquer automatiquement le théorème des quatre couleurs dans une carte polygonale dans ArcGIS / ArcToolBox?

19

J'ai besoin d'appliquer le théorème des quatre couleurs dans une forme polygonale d'une manière que je n'ai pas besoin de choisir manuellement chaque couleur à mettre dans chaque région. Je souhaite savoir s'il existe une extension, un plug-in, un script ou une base de données qui peuvent être utilisés avec ArcGIS et ArcToolBox pour le faire mathématiquement ou par programme, donc je pourrais l'utiliser pour l'instant avec chaque carte que je viens de créer.

entrez la description de l'image ici entrez la description de l'image ici entrez la description de l'image ici

Please_Dont_Bully_Me_SO_Lords
la source
1
Je voudrais également savoir s'il existe cette fonctionnalité dans d'autres systèmes autres qu'ArcGIS, comme QuantumGIS ...
Please_Dont_Bully_Me_SO_Lords
2
J'ai posté une solution sous-optimale sur SIG (avec du Rcode de travail ) et une solution optimale (qui utilisera trois ou même deux couleurs si elles peuvent fonctionner) sur Mathematica . Cette solution est récursive; la réponse à mon message donne une solution de programmation linéaire. Manifold GIS possède depuis longtemps un algorithme à cinq couleurs intégré (quatre couleurs est difficile à faire; cinq couleurs est relativement simple à réaliser.)
whuber
Si vous n'avez pas de "code jusqu'à présent", ma recommandation ArcGIS for Desktop serait de commencer par l' outil Polygon Neighbors pour obtenir un tableau répertoriant tous les voisins de chaque polygone.
PolyGeo
@PolyGeo: merci pour les outils (je ne le savais pas) mais je n'ai pas pu l'utiliser pour résoudre mon problème
radouxju

Réponses:

12

Tout d'abord, merci pour toutes les réponses et commentaires. Malheureusement, les outils existants n'étaient pas entièrement compatibles avec les dernières versions de QGIS et d'ArcGIS. J'ai donc fait ma propre solution en utilisant l'outil indiqué par @polygeo, le plugin QGIS de @Alexandre et le nom de l'algorithme (carte en quatre couleurs) de @Jens.

Voici mon code pour les personnes intéressées (pour ArcGIS mais la deuxième partie pourrait également être utilisée dans 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)

Notez que l'algorithme ne garantit pas que seules 4 couleurs sont utilisées: bien qu'il ait été prouvé que la solution existe, la "force brute" est nécessaire pour y parvenir. Dans mon cas, j'ai 7 couleurs, ce qui est assez petit. Le script pourrait avoir une boucle supplémentaire jusqu'à ce que la solution soit trouvée, mais je dois le faire pour des centaines de cartes et 7 couleurs est OK.

radouxju
la source
2
C'est génial - merci beaucoup de le partager. J'ai remarqué dans ArcGIS 10.2 que les noms de champs sur la table de sortie PolygonNeighbors ont légèrement changé - les champs s'appellent maintenant src_OBJECT et nbr_OBJECT
Stephen Lead
Ce script est-il optimal, c'est-à-dire qu'il garantit qu'un minimum de couleurs serait utilisé?
Sous le radar le
1
D'après ce que j'ai compris, une force brute est nécessaire. Comme mentionné dans mon article, vous devez l'exécuter plusieurs fois pour avoir une chance d'atteindre les 4 couleurs.
radouxju
Fonctionne toujours très bien! Peut-être que les noms des champs src_ * et nbr_ * dépendent du type d'entrée. Je l'ai exécuté maintenant avec une entrée fc de géodatabase et Desktop 10.5 et ils ont été nommés src_OBJECTID et nbr_OBJECTID. Le script peut être ajusté pour répertorier les champs commençant par src et nbr, de sorte que le type d'entrée (ou la version d'ArcGIS) n'a pas d'importance.
BERA
3

Si vous utilisez QGIS, je pense que ce dont vous avez besoin est le plugin Coloration d'une carte .

Malheureusement, le plugin n'est disponible que pour la version QGIS 1.8, mais vous pouvez toujours télécharger et voir comment le code fonctionne!

Alexandre Neto
la source
3

Il s'agit d'une adaptation de la réponse de @ radouxju en fonction. Il ajoutera un champ de couleur à la couche d'entités en entrée et calculera. Cela devrait fonctionner indépendamment des terminaisons de nom de champ de PolygonNeighbors (elles semblent être différentes pour les différents utilisateurs / entrées / versions d'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')

entrez la description de l'image ici

BERA
la source