Как автоматически применить теорему о четырех цветах на карте многоугольника в ArcGIS / ArcToolBox?

19

Мне нужно применить теорему о четырех цветах в многоугольной форме так, чтобы мне не нужно было выбирать вручную каждый цвет для размещения в каждой области. Я хотел бы знать, есть ли какое-либо расширение, плагин, сценарий или база данных, которые могут использоваться с ArcGIS и ArcToolBox, чтобы делать это математически или программно, поэтому я мог бы использовать это сейчас на каждой карте, которую я создаю.

введите описание изображения здесь введите описание изображения здесь введите описание изображения здесь

Please_Dont_Bully_Me_SO_Lords
источник
1
Я также хотел бы знать, есть ли эта функциональность в других системах, кроме ArcGIS, таких как QuantumGIS ...
Please_Dont_Bully_Me_SO_Lords
2
Я опубликовал неоптимальное решение для ГИС (с рабочим Rкодом) и оптимальное решение (которое будет использовать три или даже два цвета, если они могут работать) в Mathematica . Это решение рекурсивно; ответ на мой пост дает линейное решение программирования. В ГИС-коллектор уже давно встроен пятицветный алгоритм. (
Четырехцветное
Если у вас пока нет «кода», я бы порекомендовал ArcGIS for Desktop начать с инструмента Соседи многоугольника , чтобы получить таблицу со списком всех соседей каждого многоугольника.
PolyGeo
@PolyGeo: спасибо за инструменты (я не знал это), но я не мог использовать их, чтобы решить мою проблему
Радучжу

Ответы:

12

Прежде всего, спасибо за все ответы и комментарии. К сожалению, существующие инструменты не были полностью совместимы с последними версиями QGIS и ArcGIS. Поэтому я сделал свое собственное решение, используя инструмент, обозначенный @polygeo, плагин QGIS от @Alexandre и название алгоритма (четырехцветная карта) от @Jens.

Вот мой код для интересующихся (для ArcGIS, но вторую часть можно использовать и в 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)

Обратите внимание, что алгоритм не гарантирует, что используются только 4 цвета: хотя было доказано, что решение существует, "грубая сила" необходима для его достижения. В моем случае я получил 7 цветов, что достаточно мало. Сценарий может иметь дополнительный цикл, пока не будет найдено решение, но мне нужно сделать это для сотен карт, и 7 цветов в порядке.

radouxju
источник
2
Это великолепно - большое спасибо за то, что поделились им. В ArcGIS 10.2 я заметил, что имена полей в выходной таблице PolygonNeighbors немного изменились - теперь поля называются src_OBJECT и nbr_OBJECT
Стивен Лид
Является ли этот сценарий оптимальным, т.е. обеспечивает ли он использование минимального количества цветов?
ниже радара
1
Насколько я понял, нужна грубая сила. Как уже упоминалось в моем посте, вы должны запустить его несколько раз, чтобы иметь возможность достичь 4 цветов.
Radouxju
Все еще прекрасно работает! Возможно, имена полей src_ * и nbr_ * зависят от типа ввода. Я запустил его сейчас с использованием входных данных базы геоданных и рабочего стола 10.5, и они назывались src_OBJECTID и nbr_OBJECTID. Сценарий можно настроить так, чтобы он отображал поля, начинающиеся с src и nbr, поэтому тип ввода (или версия ArcGIS) не имеет значения.
BERA
4

Существует пример разработчика VB6 и инструмент геообработки ArcGIS 9.x, но из комментариев к этой идее ArcGIS они не работают на 10.0+.

Возможно, кому-то будет интересно его портировать.

Решение QGIS под названием TopoColour дается в комментариях к этому связанному вопросу: Цветные полигоны, так что каждый из них отличается от своих соседей.

blah238
источник
3

Если вы используете QGIS, я считаю, что вам нужен плагин « Раскраска карты» .

К сожалению, плагин доступен только для версии QGIS 1.8, но вы всегда можете скачать и посмотреть, как работает код!

Александр Нето
источник
3

Это адаптация ответа @ radouxju в функцию. Это добавит поле цвета к входному объектному слою и вычислит. Он должен работать независимо от окончаний имен полей PolygonNeighbors (они кажутся разными для разных версий пользователей / входов / 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')

введите описание изображения здесь

BERA
источник