Jak automatycznie zastosować twierdzenie o czterech kolorach na mapie wielokątów w ArcGIS / ArcToolBox?

19

Muszę zastosować twierdzenie o czterech kolorach w kształcie wielokąta w taki sposób, że nie muszę ręcznie wybierać każdego koloru, aby umieścić go w każdym regionie. Chciałbym wiedzieć, czy istnieje jakieś rozszerzenie, wtyczka, skrypt lub baza danych, które mogą być używane z ArcGIS i ArcToolBox do robienia tego matematycznie lub programowo, więc na razie mogę go używać z każdą mapą, którą stworzę.

wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj

Please_Dont_Bully_Me_SO_Lords
źródło
1
Chciałbym również wiedzieć, czy jest taka funkcjonalność w systemach innych niż ArcGIS, takich jak QuantumGIS ...
Please_Dont_Bully_Me_SO_Lords
2
Zamieściłem nieoptymalne rozwiązanie na GIS (z działającym Rkodem) i optymalne rozwiązanie (które wykorzysta trzy lub nawet dwa kolory, jeśli można je znaleźć) na Mathematica . To rozwiązanie jest rekurencyjne; odpowiedź na mój post daje liniową rozwiązanie programowania. W kolektorze GIS od dawna wbudowany jest pięciokolorowy algorytm. (Czterokolorowe jest trudne do wykonania; pięciokolorowe jest stosunkowo łatwe do osiągnięcia.)
whuber
Jeśli nie masz jeszcze „kodu”, moim zaleceniem ArcGIS dla komputerów stacjonarnych byłoby uruchomienie narzędzia Polygon Neighbours , aby uzyskać tabelę z listą wszystkich sąsiadów każdego wielokąta.
PolyGeo
@PolyGeo: dzięki za narzędzia (nie wiedziałem o tym), ale nie mogłem użyć go do rozwiązania mojego problemu
radouxju

Odpowiedzi:

12

Przede wszystkim dziękuję za wszystkie odpowiedzi i komentarze. Niestety istniejące narzędzia nie były w pełni kompatybilne z najnowszymi wersjami QGIS i ArcGIS. Dlatego stworzyłem własne rozwiązanie za pomocą narzędzia wskazanego przez @polygeo, wtyczki QGIS od @Alexandre i nazwy algorytmu (mapa czterech kolorów) od @Jens.

Oto mój kod dla zainteresowanych (dla ArcGIS, ale druga część może być również wykorzystana w 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)

Zauważ, że algorytm nie gwarantuje, że zostaną użyte tylko 4 kolory: chociaż udowodniono, że istnieje rozwiązanie, do jego osiągnięcia konieczna jest „brutalna siła”. W moim przypadku mam 7 kolorów, które są wystarczająco małe. Skrypt może mieć dodatkową pętlę, dopóki nie zostanie znalezione rozwiązanie, ale muszę to zrobić dla setek map i 7 kolorów jest w porządku.

radouxju
źródło
2
To jest genialne - wielkie dzięki za udostępnienie. Zauważyłem w ArcGIS 10.2, że nazwy pól w tabeli wyjściowej PolygonNeighbors nieznacznie się zmieniły - pola nazywają się teraz src_OBJECT i nbr_OBJECT
Stephen Lead
Czy ten skrypt jest optymalny, tzn. Czy zapewnia użycie minimalnej liczby kolorów?
Poniżej radaru
1
O ile rozumiem, potrzebna jest surowa siła. Jak wspomniano w moim poście, musisz uruchomić go kilka razy, aby mieć szansę na osiągnięcie 4 kolorów.
radouxju
Nadal działa świetnie! Może nazwy pól src_ * i nbr_ * zależą od typu danych wejściowych. Uruchomiłem go teraz z wejściem geobazy fc i Desktopem 10.5 i nazwano je src_OBJECTID i nbr_OBJECTID. Skrypt można dostosować tak, aby wyświetlał pola zaczynające się od src i nbr, więc typ danych wejściowych (lub wersja ArcGIS) nie ma znaczenia.
BERA
3

Jeśli używasz QGIS, uważam, że potrzebujesz wtyczki Kolorowanie mapy .

Niestety wtyczka jest dostępna tylko dla wersji QGIS 1.8, ale zawsze możesz pobrać i zobaczyć, jak działa kod!

Alexandre Neto
źródło
3

Jest to dostosowanie odpowiedzi @ radouxju do funkcji. Doda to pole koloru do wejściowej warstwy obiektów i obliczy. Powinno działać niezależnie od zakończeń nazw pól w PolygonNeighbors (wydają się być różne dla różnych użytkowników / wersji wejściowych / wersji 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')

wprowadź opis zdjęcia tutaj

BERA
źródło