Automatisation de la résolution des conflits et workflows de généralisation avec le géotraitement

Comme la généralisation de données implique beaucoup de tâches répétitives et fastidieuses, elle se prête à l’automatisation. Toutefois, la nature contextuelle et subjective de la généralisation la rend difficile à automatiser. Le cerveau humain est capable d’établir des priorités et de faire en même temps des concessions en fonction du contexte. En revanche, il est beaucoup plus difficile d’indiquer à un ordinateur de faire la même chose avec une série de commandes discrètes.

L’environnement de géotraitement dans ArcGIS est idéal pour établir une structure de généralisation. Il permet, en effet, de gérer la transformation de données au cours d’étapes isolées distinctes s’appuyant sur des variables de données, d’échelle et spécifiques au produit. Ces étapes peuvent être logiquement reliées entre elles ou même répétées sous forme de boucle dans des scripts ou des modèles pour créer un workflow complexe. Ce dernier peut être appliqué à une plage de données afin de produire des bases de données multi-échelles pour l’impression ou l’affichage à l’écran. Les tâches peuvent être aisément répétées en séquences et appliquées à différents groupes d’entités ou avec différents paramètres combinés de plusieurs manières. Des workflows entiers peuvent être automatisés ou subdivisés en plus petits morceaux après avoir été mis à jour manuellement ou vérifiés.

Combinaison des tâches de généralisation en workflows cartographiques

Le processus de création d’une carte à une plus petite échelle que celle pour laquelle les données étaient prévues commence par une évaluation de l’échelle cible, des caractéristiques d’affichage, symbologie comprise, et de l’utilisation prévue ou sous-jacente de la carte. Puis, des opérations sont effectuées pour limiter le nombre total d’entités sans nuire à la connectivité ou au caractère du jeu de données. Il convient enfin de réduire le niveau de complexité de chaque entité en supprimant des sommets ou d’autres détails d’entités. Cela peut concerner également les attributs d’entité en combinant des sous-catégories similaires d’entités qui seront affichées avec le même symbole. Une fois que la carte est produite et que les données sont affichées avec leur symbologie finale à l’échelle finale, les conflits graphiques peuvent être détectés et résolus.

L’organigramme suivant présente une version simplifiée d’un workflow de généralisation et identifie les outils clés de la boîte à outils Cartographie permettant de généraliser les données pour les afficher à une plus petite échelle.

Diagramme du processus de généralisation
Affichage simplifié des processus et outils de géotraitement correspondants utilisés pour généraliser des données pour un affichage cartographique.

Il est important de comprendre que la plupart des outils de géotraitement génèrent, en général, de nouvelles données en sortie, exploitables à leur tour par d’autres outils. Cela n’est pas le cas des cartographes, qui suivent, en principe, un processus caractérisé par l’amélioration successive des couches d’entités déjà établies dans une carte. La symbologie, les propriétés de couche et les relations de masquage sont déjà définies. Il est donc préférable de modifier les couches en entrée lors de la résolution des conflits et de la généralisation pour ne pas perdre ces informations. Pour cette raison, certains des outils de la boîte à outils Cartographie modifient les données en entrée dans les couches symbolisées au lieu de créer des données.

Liaison d’outils de généralisation dans ModelBuilder

Les outils de généralisation ont recours à des entrées à valeurs multiples, c’est-à-dire, à une liste d’une ou plusieurs classes d’entités. Beaucoup d’outils de géotraitement acceptent les valeurs multiples (comme l’outil Agréger), mais les outils de généralisation sont un peu différents, car ils produisent également des valeurs multiples en sortie. Par conséquent, vous devez maîtriser quelques techniques de ModelBuilder pour produire le modèle désiré. Ces techniques sont abordées ci-dessous.

Liaison d’outils avec plusieurs entrées et sorties

Les outils Éclaircir le réseau routier, Résoudre des conflits de routes et Résoudre des conflits de construction produisent des valeurs multiples en sortie. Cela signifie que seuls les outils qui acceptent des entrées à valeurs multiples peuvent utiliser directement les valeurs en sortie de ces outils. Par exemple, si trois couches sont utilisées en tant qu’entrées pour l’outil Éclaircir le réseau routier, et que vous souhaitez utiliser ces trois mêmes couches en tant qu’entrées pour l’outil Résoudre des conflits de routes après qu’elles ont été affinées, vous pouvez lier directement les valeurs en sortie de l’outil Éclaircir le réseau routier à l’outil Résoudre des conflits de routes.

Modèle contenant plusieurs entrées pour généralisation
Entrées multiples liées à l’outil Résoudre des conflits de routes via l’outil Éclaircir le réseau routier.

Vous pouvez utiliser l’outil Recueillir des valeurs pour ajouter plus de couches à une valeur multiple. L’exemple suivant montre l’ajout de deux couches supplémentaires à la sortie de l’outil Éclaircir le réseau routier pour créer l’entrée de l’outil Résoudre des conflits de routes.

Modèle utilisant l’outil Recueillir des valeurs
Ce modèle utilise l’outil Recueillir des valeurs pour ajouter des entrées supplémentaires à une sortie à valeurs multiples à partir de l’outil Éclaircir le réseau routier avant de les lier à l’outil Résoudre des conflits de routes.

Liaison de plusieurs sorties à une entrée unique

Pour lier des outils qui ont une sortie à valeurs multiples à un outil qui accepte une seule entrée, utilisez l’outil Ajouter pour fusionner plusieurs classes d’entités. L’ajout de plusieurs couches de routes en entrée traitées par l’outil Éclaircir le réseau routier en vue de les utiliser comme entrée pour l’outil Fusionner des chaussées séparées (lequel accepte une seule entrée) constitue un bon exemple de ce processus.

Modèle utilisant l’outil Ajouter
Ce modèle utilise l’outil Ajouter pour combiner plusieurs sorties dans une seule entrée.

Liaison de plusieurs entrées de façon individuelle

Dans certains cas, il peut être judicieux de transférer plusieurs sorties, une à une, d’un outil à un autre. C’est le cas, si vous ne souhaitez pas que toutes les sorties du premier outil participent au deuxième outil ou si vous souhaitez définir des paramètres spécifiques pour chaque entrée dans le deuxième outil. Par exemple, l’outil Résoudre des conflits de construction permet de contrôler totalement la manière dont chaque couche en entrée est définie en tant qu’interruption. Dans ce cas, utilisez le même ensemble de couches en tant qu’entrées pour les deux outils, mais définissez la sortie du premier outil comme condition préalable pour le deuxième outil afin d’appliquer l’ordre de traitement correct, comme illustré ci-dessous. Cette approche est uniquement applicable lorsque le premier outil (Résoudre des conflits de routes, par exemple) modifie des couches en entrée au lieu de créer de nouvelles couches en sortie.

Pour en savoir plus sur l’utilisation des conditions préalables dans ModelBuilder

Dans l’exemple ci-dessous, les trois couches de transport sont utilisées comme entrées pour les deux outils. Cela est possible, car ces couches sont modifiées par l’outil Résoudre des conflits de routes ; aucune nouvelle classe d’entités en sortie n’est créée. La sortie de l’outil Résoudre des conflits de routes est utilisée comme condition préalable à l’exécution de l’outil Résoudre des conflits de construction. Autrement dit, l’outil Résoudre des conflits de construction ne démarrera qu’une fois l’exécution de l’outil Résoudre des conflits de routes terminée.

Modèle utilisant une condition préalable
La sortie de l’outil Résoudre des conflits de routes est définie comme une condition préalable à l’exécution de l’outil Résoudre des conflits de construction afin de garantir le respect de l’ordre de traitement.

Entrées symbolisées

Pour lier des outils qui acceptent uniquement des couches symbolisées, vous devez utiliser l’outil Générer une couche et l’outil Appliquer la symbologie d’une couche pour préparer une couche en sortie à des fins de liaison dans ModelBuilder ainsi que dans des environnements de script.

Modèle ayant une couche symbolisée en entrée
Ce modèle utilise l’outil Générer une couche d’entités et l’outil Appliquer la symbologie d’une couche pour transmettre des informations de symbole entre les outils.

Exemple de script Python pour préparer des données pour un affichage à une plus petite échelle

Exemple de workflow de la boîte à outils Cartographie (script autonome)

Ce script autonome exécute un workflow basé sur certains outils de la boîte à outils Cartographie pour généraliser des données à l’échelle 1:25 000 et résoudre les conflits graphiques en vue d’afficher les données à l’échelle 1:50 000.

# Name: cartography_workflow_script.py
# Description: Process features in order to resolve graphic conflicts when
# changing scales from 25K to 50K.
#
# Tools used = Aggregate Polygons, Align Marker To Stroke Or Fill, Apply
#              Symbology From Layer, Create Overpass, Create Underpass, Calculate
#              Line Caps, Eliminate Polygon Part, Make Feature Layer, Merge
#              Divided Roads, Propagate Displacement, Resolve Building Conflicts
#              Resolve Road Conflicts, Select, Select Layer By Attribute, Set
#              Control Point At Intersect, Set Control Point By Angle, Simplify 
#              Building, Simplify Line, Simplify Polygon, Smooth Line, Smooth 
#              Polygon, Thin Road Network
# Minimum ArcGIS Pro version = 2.1
#
# The geodatabase used in this workflow is assumed to be in c:\data
# - please replace this path to your machine specific folder.


# Import system modules
import arcpy

# Start the processing
arcpy.env.workspace = "C:/data/cartography.gdb"

# The data was captured at a scale of 1:24000, and this workflow will produce
# data appropriate for a scale of 1:50000.
# Most of the geoprocessing tools in this workflow require a reference scale
arcpy.env.referenceScale = "50000"
arcpy.env.cartographicCoordinateSystem = ""

###############
# HYDROGRAPHY #
###############

# A subset of linear features (rivers/streams) will be processed
# for simplification and smoothing
# A subset of polygonal features (reservoirs/lakes) will be processed
# for simplification and smoothing

# The workspace is set to the hydrography feature dataset
arcpy.env.workspace = "C:/data/cartography.gdb/hydrography"

# Linear hydrographic features
arcpy.MakeFeatureLayer_management("streamnetwork", "streamlayer", "", "", "")

# A selection is made for features which are rivers/streams
arcpy.SelectLayerByAttribute_management("streamlayer", "NEW_SELECTION",
                                        '"FCsubtype" = 1')

# In order to reduce the complexity from the streams, vertices are removed using
# the Simplify Line tool
arcpy.SimplifyLine_cartography("streamlayer", "streams_simplified",
                               "BEND_SIMPLIFY", "100 meters", "RESOLVE_ERRORS")

# In order to reduce the amount or severity of sharp angles, Smooth Line is used
# to improve the shape of the streams
arcpy.SmoothLine_cartography("streams_simplified", "streams",
                             "BEZIER_INTERPOLATION", "#", "0", 'FLAG_ERRORS')

# Some of the processed features are intermittent rivers or streams and are
# symbolized as dashed lines. The dashes can be centered around corners to 
# improve the look of the features. The corners are identified as vertices which 
# will be flagged as control points. Symbology from an existing layer containing
# dashed line symbols is then applied. 

# A new feature layer is created from the streams data to be used as input 
# when setting control points. 
arcpy.MakeFeatureLayer_management("streams", "streamslayer", "", "", "")

# Dashed line symbology from an existing layer is applied to the new streams 
# feature layer 
arcpy.ApplySymbologyFromLayer_management("streamslayer",
                                         "C:/data/stream_symbols.lyrx")

# The dashes in the stream symbol will be placed at control points created
# anywhere an angle is less than (or equal to) 130 degrees.
arcpy.SetControlPointByAngle_cartography("streamslayer", "130")

# Polygonal hydrographic features
# A selection is made to create a new feature class for reservoirs.
arcpy.Select_analysis("openwater", "reservoirs", '"FCsubtype" = 4')

# A selection is made to create a separate feature class for processing in order
# to generate lakes.
arcpy.Select_analysis("openwater", "water_select", '"FCsubtype" <> 4')

# In order to reduce the complexity from the lakes, vertices are removed using
# the Simplify Line tool.
arcpy.SimplifyPolygon_cartography("water_select", "water_simplified", 
                                  "BEND_SIMPLIFY", "100 meters", "0",
                                  "RESOLVE_ERRORS")

# In order to reduce the amount (or severity) of sharp angles, Smooth Line is
# used to improve the shape of the lakes.
arcpy.SmoothPolygon_cartography("water_simplified", "lakes",
                                "BEZIER_INTERPOLATION", "0", "", "FLAG_ERRORS")


#############
# RAILROADS #
#############

# Set the workspace to the transportation feature dataset
arcpy.env.workspace = "C:/data/cartography.gdb/transportation"
# In order to reduce the complexity from the railroads, vertices are removed 
# using the Simplify Line tool.
arcpy.SimplifyLine_cartography("railnetwork", "rail_simplified",
                               "BEND_SIMPLIFY", "100 meters", "RESOLVE_ERRORS")

# The Merge Divided Roads tool requires symbolized features, so a feature layer
# is created using the simplified rail features, and then pre-made symbology is 
# applied from an existing feature layer.

# A feature layer is created from the simplified rail features. 
arcpy.MakeFeatureLayer_management("rail_simplified", "railwaylayer", "", "", "")

# Apply the symbology from an existing layer
arcpy.ApplySymbologyFromLayer_management("railwaylayer",
                                         "C:/data/rail_symbols.lyrx")

# The Merge Divided Roads tool will be used to generates single line railroad
# features in place of multiple divided railroad lanes.
arcpy.MergeDividedRoads_cartography("railwaylayer", "level", "25 Meters",
                                    "railways")

# Symbolized features are required when adding control points, so a new feature
# layer is created from the output of the MergeDivvidedRoads tool.
arcpy.MakeFeatureLayer_management("railways", "railwayslayer", "", "", "")

# Pre-made railway symbology from an existing layer is applied to the 
# new railway feature layer.
arcpy.ApplySymbologyFromLayer_management("railwayslayer", 
                                         "C:/data/rail_symbols.lyrx")

# The tick marks in railroad symbol (markers) will be placed at control points
# created anywhere an angle is less than (or equal to) 130 degrees.
arcpy.SetControlPointByAngle_cartography("railwayslayer", "130")


###########
# LANDUSE #
###########

# Set the workspace to the landuse feature dataset
arcpy.env.workspace = "C:/data/cartography.gdb/landuse"
# The polygons which represent landcover have holes in them where buildings are
# located. The holes need to be removed so they will not appear after buildings
# have moved. In this example, any hole which is less than 50 percent of the 
# feature's area will be removed.
arcpy.EliminatePolygonPart_management("cultural", "urban_area", "PERCENT", "0",
                                      "50", "CONTAINED_ONLY")


##############
# BOUNDARIES #
##############

# The boundary features have dashed outlines which are not in phase with each
# other on shared edges between features. To make the dashed outlines in phase
# with each other, control points are added wherever features 
# share coincident vertices.
arcpy.SetControlPointAtIntersect_cartography("C:/data/boundaries.lyrx", 
                                             "C:/data/boundaries.lyrx")


#########
# ROADS #
#########

# Set the workspace to the transportation feature dataset
arcpy.env.workspace = "C:/data/cartography.gdb/transportation"
# Linear features

# Roads which are dead ends (or cul-de-sacs) should have their Line ending
# property set to BUTT.
arcpy.CalculateLineCaps_cartography("C:/data/road_symbols.lyrx", "BUTT",
                                    "CASED_LINE_DANGLE")

# Thin Road Network identifies a subset of road segments that can be removed from
# the display to create a simplified road network that retains the connectivity 
# and general character of the input collection. Features are flagged for removal
# when their attribute value in the "invisible" field equals one. A layer
# definition query can be used to display the resulting simplified feature class.
arcpy.ThinRoadNetwork_cartography("roadnetwork", "500 meters", "invisible",
                                  "level")

# The Merge Divided Roads tool will be used to generates single line road
# features in place of multiple divided road lanes.
arcpy.MergeDividedRoads_cartography("C:/data/road_symbols.lyrx", "level",
                                    "25 meters", "roads")

# The Resolve Road Conflicts tool requires symbolized features, so a feature
# layer is created from the roads features so that pre-made
# symbology can the be applied to the new roads feature layer.
arcpy.MakeFeatureLayer_management("roads", "roadslayer", "", "", "")

# Pre-made symbology from an existing layer is applied to the roads feature 
# layer.
arcpy.ApplySymbologyFromLayer_management("roadslayer",
                                         "C:/data/road_symbols.lyrx")

# The Resolve Road Conflicts tool does not produce output road layers but instead
# alters the source feature classes of the input road layers. The Resolve Road
# Conflicts tool adjusts line features to ensure that they are graphically
# distinguishable when symbolized at output scale.
arcpy.ResolveRoadConflicts_cartography
("roadslayer", "level", "C:/data/cartography.gdb/buildings/displacement")

# The dashes in the road symbols will be placed at control points created
# anywhere an angle is less than (or equal to) 130 degrees.
arcpy.SetControlPointByAngle_cartography("roadslayer", "130")

# Create bridges
# The Create Overpass tool will create a bridge for the roads and a mask for the
# streams wherever a road goes over a steam.
arcpy.CreateOverpass_cartography("roadslayer", "streamslayer", "2 points",
                                 "1 points", "over_mask_fc", "over_mask_rc",
                                 '"BridgeCategory" = 1', "bridges",
                                 "ANGLED", "1 points")

# Create tunnels
# The Create Overpass tool will create a tunnel for the railroads and a mask for
# the railroads wherever a railroad goes under a road.
arcpy.CreateUnderpass_cartography("roadslayer", "railwayslayer", "2 points",
                                  "1 points", "under_mask_fc", "under_mask_rc",
                                  '"RelationshipToSurface" = 3', "tunnels",
                                  "ANGLED", "1 points")


#############
# BUILDINGS #
#############

# Set the workspace to the buildings feature dataset
arcpy.env.workspace = "C:/data/cartography.gdb/buildings"
# Point features

# When the road features were adjusted by the Resolve Road Conflicts tool, the
# spatial relationship with nearby buildings was affected. A displacement feature
# class was created by that tool in order to record the change applied to the
# roads. This information can be used by the Propagate Displacement tool to apply
# the same change to the point buildings.

# The road displacement is propagated to the point buildings
arcpy.PropagateDisplacement_cartography("point_bldg", "displacement", "AUTO")

# Point buildings will be rotated against nearby linear roads
# The Align Markers To Stroke Or Fill tool can do this with symbolized features.

# A feature layer is made for point buildings
arcpy.MakeFeatureLayer_management("point_bldg", "bldglayer", "", "", "")

# Symbology is applied from an existing layer.
arcpy.ApplySymbologyFromLayer_management("bldglayer", 
                                         "C:/data/bldg_symbols.lyrx")

# The Align Marker to Stroke Or Fill tool is used to align point buildings to
# face road features within 5 points of the buildings
arcpy.AlignMarkerToStrokeOrFill_cartography("bldglayer", "roadslayer",
                                            "5 points", "PERPENDICULAR")

# Polgyonal features
# When the road features were adjusted by the Resolve Road Conflicts tool, the
# spatial relationship with nearby buildings was affected. A displacement
# feature class was created by that tool in order to record the change applied
# to the roads. This information can be used by the Propagate Displacement tool
# to apply the same change to the polygonal buildings.

# The road displacement is propagated to polygon buildings
arcpy.PropagateDisplacement_cartography("footprints", "displacement", "SOLID")

# A selection is made to create a feature class with buildings larger than
# a minimum size
# The small buildings are not appropriate at the new map scale of 1:50,000
arcpy.Select_analysis("footprints", "buildings_select", '"Shape_Area" > 100')

# There is a need to create better spacing between polygon buildings and combine
# them when they share edges or are very close together
# The Aggregate Polygons tool is used to accomplish this task
arcpy.AggregatePolygons_cartography("buildings_select", "large_buildings",
                                    "20 meters", "", "", "ORTHOGONAL")

# In order to reduce the complexity of the buildings, indentations, extensions
# and extra vertices are removed using the Simplify Building tool.
# Buildings require less visible detail at the new scale of 1:50,000.
arcpy.SimplifyBuilding_cartography("large_buildings", "area_bldg", "20 meters",
                                   "0 unknown", "CHECK_CONFLICTS")

# All buildings require further improvements to achieve better spacing between
# themselves and other nearby features. At the new scale of 1:50,000 the
# symbolized buildings may overlap other features and create a visually congested
# map. To improve the visual congestion, the Resolve Building Conflicts tool is
# used. Buildings are improved in the context of their surrounding features.
# These features are considered barriers to buildings. The Resolve Building
# Conflicts tool requires symbolized features and has several options available
# to improve the buildings. Options include: moving or resizing the buildings,
# orienting or snapping the buildings to nearby features, as well as making the
# buildings invisible. Buildings from multiple feature classes can be used as
# inputs to the tool. Barriers from multiple feature classes can be used as
# inputs to the tool. For each barrier, the option is available to specify a snap
# or orient action for the buildings when they are within a specified distance.
# For each barrier, the option is available to specify a minimum distance for
# buildings to maintain between them.

# A feature layer is made for the polygon buildings
arcpy.MakeFeatureLayer_management("area_bldg", "footprintlayer", "", "", "")

# Pre-made symbology is applied from an existing layer.
arcpy.ApplySymbologyFromLayer_management("footprintlayer",
                                         "C:/data/footprint_symbols.lyrx")

# The Resolve Building Conflicts tool is run with point and polygon buildings
# against roads, streams and railroads. The buildings will be moved away from
# streams and railroads until they reach a minimum distance. The buildings
# within a maximum distance from the roads will be rotated. Further movement
# and rotation may still be required by the tool in order to resolve any
# remaining graphic conflict.
arcpy.ResolveBuildingConflicts_cartography("footprintlayer; bldglayer", "invisible",
                                           "'roadslayer' 'true' '5 meters';'streamslayer' 'false' '5 meters';'railwayslayer' 'false' '10 meters'",
                                           "10 meters", "20 meters", "level")

Rubriques connexes