通过地理处理自动化冲突解决和制图综合的工作流
概化数据涉及许多重复的劳动密集型任务,因此,将其实现自动化是一种理想的选择。然而,制图综合的关联性和主观性使其难以实现自动化。人脑非常善于考虑事情的先后顺序并同时根据情境做出调整。而通过一系列离散命令指示计算机执行此操作则会困难得多。
ArcGIS 中的地理处理环境非常适于建立制图综合框架,因为其能够按照特定于数据、比例和产品的变量指示的独立步骤来管理数据的变换。这些独立步骤可根据逻辑链接在一起,甚至在脚本或模型中形成循环,创建可应用于一系列数据的复杂工作流,从而生成用于打印或屏幕显示的多比例数据库。由此可以轻松地在不同的要素组上或以多种方式组合的不同参数按顺序重复任务。可以自动处理完整工作流,或者通过手动编辑过程中或编辑期间进行的验证将其细分成更小的工作流。
将制图综合任务合并到制图工作流
如果要制作其比例小于预期数据比例的地图,首先要了解目标比例、显示规范(包括符号系统)和地图的根本目的或意图。然后,执行相应操作,在不影响数据集的连通性或特征的情况下减少要素的总个数。接下来,通过移除折点或其他要素细节减少各要素的复杂性。其中也可能包括通过将相似的要显示的要素子类和相同的符号进行合并,来简化要素属性的复杂性。开始地图创建后,数据以其最终比例的最终符号系统显示,图形冲突可得到检测和解决。
以下流程图显示的是简化版本的制图综合工作流,并标识了制图工具箱中可支持概化数据以较小比例显示的一些关键工具。
大多数地理处理工具通常都能生成新的输出数据,然后这些输出数据可用作后续工具的输入,了解这一点非常重要。比较而言,制图人员通常遵循一种特定的工作流,该工作流通过逐渐改进已在地图文档中创建的要素图层进行表征。符号系统、图层属性和掩膜关系已经定义,因此最好在冲突解决和制图综合操作执行期间修改输入图层,以免丢失相关信息。因此,“制图”工具箱中的一些工具可修改符号化图层中的输入数据,而不创建数据。当与制图表达共同使用时,此方法特别易于管理而且功能强大。
使用制图表达支持制图综合
制图表达是地理数据库要素类的属性,可支持要素几何的不同显示。要素类可有多个与其关联的制图表达,因此支持相同数据的多种显示。制图表达对制图综合具有非常重要的作用,但是您必须了解,无论有多少制图表达与要素类相关联,所创建的单个要素类只是与特定比例(或小比例范围)相对应。一般倾向认为,能够使用制图表达支持一组要素的多种显示意味着制图表达可用来以不同的比例绘制相同的要素。如果要对比例进行一些小的更改,可通过微调某些制图表达要素的形状或通过隐藏一些制图表达要素来实现。但是,即使通过制图表达,也仍然只是存在一对一的关系;每个要素都可以有一个或多个不同的显示,但是要素不能被合并到新要素中。例如,单凭使用制图表达显示则不能将一组离散建筑物作为建筑区域进行建模。要真正地支持多比例制图,必须正确处理要素,才能确保合理的要素密度和细节,并避免符号化冲突。制图综合和图形冲突工具集中的工具可帮助您实现这一目标。
制图表达有两个编辑行为设置。编辑设置是制图表达的属性,并在对要素类创建制图表达时建立。
- 将对几何的更改存储为制图表达覆盖。这是默认设置。这意味着对要素几何的修改将存储在要素类属性表中单独的 BLOB 字段中,其仅能由当前的制图表达访问。存储在 Shape 字段的要素基础几何将保持不变。
- 更改支持要素的几何。使用该设置,修改要素几何时会修改要素类的实际 Shape 字段,因此将影响与要素类关联的其他制图表达。
有些制图综合工具可以修改其输入图层;不会创建新的数据集。这被称为输入/输出派生数据。强烈建议使用的图层指向具有将对几何的更改存储为制图表达覆盖设置的制图表达,尤其是在使用图形冲突工具(解决道路冲突、传递位移或解决建筑物冲突)时,因为这些工具可修改输入图层的几何。使用此设置,这些工具对要素所做的修改将在制图表达中存储为覆盖,并且原始几何保持不变。这种处理方式的优势是要素的原始形状易于(在 Shape 字段中)进行直观地比较,或者在结果不合适时也可恢复。
如果使用的图层指向具有更改支持要素的几何设置的制图表达,并将此图层输入到图形冲突工具中,则这些工具所做的更改将覆盖 Shape 字段中的原始要素几何。同样,如果使用的图层没有引用某个制图表达(即使输入要素类中存在一个或多个制图表达),原始几何将丢失。如果使用这些处理模式中的任一种,则强烈建议您开始处理前备份输入要素类。
在相当大的比例范围内概化数据时,制图表达也很有优势。理想情况下,概化过程应该能够直接处理比例值大幅减小的情况,但中间比例通常是必需的。为中间比例显示准备数据来连接过渡过程可能会夸大不精确性,因为从显示上删除详细的数据时进行的决策会有所不同。例如,考虑大比例地图上 A 发生的移动与要素 B 相适应。但在小比例地图上,要素 B 不再出现,因此没有简单的办法可以查看 A 已发生位移或决定其来自何处。在这种情况下,暂时不必要的不精确性将被传递到下一个小比例。制图表达覆盖有助于解决这种问题,因为这时您可以非常直观地快速确定要素的起始位置,并且可以根据需要进行恢复。
链接模型构建器中的制图综合工具
制图综合工具使用多值输入,即一个或多个要素类的列表。许多地理处理工具接受多值(例如联合工具),但是制图综合工具却有点不同,它们还输出多值。您需要了解一些“模型构建器”技术以生成想要的模型。下面将对这些技术进行讨论。
链接具有多个输入和输出的工具
细化道路网、解决道路冲突和解决建筑物冲突工具可输出多值。这意味着只有接受多值输入的工具才能直接使用这些工具的输出。例如,如果三个图层用作细化道路网工具的输入,并且希望细化这三个图层后,使用这三个图层作为解决道路冲突工具的输入,则可以直接将细化道路网工具的输出与解决道路冲突工具链接。
可以使用收集值工具将更多图层添加到多值。以下示例显示了向细化道路网的输出中再添加两个图层,为解决道路冲突创建输入。
将多个输出链接至单个输入
要将有多值输出的工具链接至接受单个输入的工具,请使用追加工具将多个要素类合并到一起。此工作流的一个示例是通过追加工具将细化道路网工具处理的多个道路输入图层的结果进行合并,然后作为合并分开的道路工具的输入,该工具仅接受单个输入。
分别链接多个输入
在某些情况下,希望将工具中的多个输出分别传递到其他工具。如果您不希望第一个工具的所有输出参与第二个工具,或者如果您希望为第二个工具中的每个输入设置特定的参数,就会出现这种情形。例如,解决建筑物冲突工具允许完全控制将各输入图层定义为障碍的方式。在这些情况下,使用相同的一组图层同时作为两个工具的输入,但是将第一个工具的输出设置为第二个工具的前提条件来强制处理的正确顺序,如下图所示。此方法仅在第一种工具(如解决道路冲突工具)修改输入图层而不是创建新的输出图层时才适用。
在以下示例中,三个交通图层同时用作两个工具的输入。这是可行的,因为这些图层由解决道路冲突工具修改,并且不创建新的输出要素类。解决道路冲突工具的输出用作解决建筑物冲突工具进行处理的前提条件,以确保解决道路冲突工具在解决建筑物冲突工具开始前完成处理。
为小比例显示准备数据的 Python 脚本示例
此独立脚本完成一个示例工作流,方法是使用“制图”工具箱中的多个工具概化 1:25,000 比例的数据,并解决以 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 # Representation Control Point At Intersect, Set Representation # Control Point By Angle, Simplify Building,Simplify Line, Simplify # Polygon, Smooth Line, Smooth Polygon, Thin Road Network # Minimum ArcGIS version = 10 # # 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, sys, os from arcpy import env # Start the processing 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 env.referenceScale = "50000" 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 procesed # for simplification and smoothing # The workspace is set to the hydrography feature dataset 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. When symbolized with representations, 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 representation control # points. Representation symbology is applied to a feature layer in order to be # processed for control points. # To place dashes at corners, representation symbology needs to be used by # the feature layer. arcpy.MakeFeatureLayer_management("streams", "streamslayer", "", "", "") # Representation symbology is applied to a feature layer in order to be # processed for control points. arcpy.ApplySymbologyFromLayer_management("streamslayer", "C:/data/stream_symbols.lyr") # 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.SetRepresentationControlPointByAngle_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 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 pre-made # symbology is provided to the feature layer. arcpy.MakeFeatureLayer_management("rail_simplified", "railwaylayer", "", "", "") # In this workflow, the symbology being applied is Representations arcpy.ApplySymbologyFromLayer_management("railwaylayer", "C:/data/rail_symbols.lyr") # 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") # To place markers at corners, representation symbology needs to be used by # the feature layer. arcpy.MakeFeatureLayer_management("railways", "railwayslayer", "", "", "") # Representation symbology is applied to a feature layer in order to be # processed for control points. arcpy.ApplySymbologyFromLayer_management("railwayslayer", "C:/data/rail_symbols.lyr") # 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.SetRepresentationControlPointByAngle_cartography("railwayslayer", "130") ########### # LANDUSE # ########### # Set the workspace to the landuse feature dataset 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, representation control points are added wherever features # share coincident vertices. The control points are then added to the features # symbolized with Representations. arcpy.SetRepresentationControlPointAtIntersect_cartography ("C:/data/boundaries.lyr", "C:/data/boundaries.lyr") ######### # ROADS # ######### # Set the workspace to the transportation feature dataset 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.lyr", "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.lyr", "level", "25 meters", "roads") # The Resolve Road Conflicts tool requires symbolized features, so pre-made # symbology is provided to the feature layer. arcpy.MakeFeatureLayer_management("roads", "roadslayer", "", "", "") # In this workflow, the symbology being applied is Representations arcpy.ApplySymbologyFromLayer_management("roadslayer", "C:/data/road_symbols.lyr") # 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.SetRepresentationControlPointByAngle_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 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 features symbolized # with Representations. # A feature layer is made for point buildings arcpy.MakeFeatureLayer_management("point_bldg", "bldglayer", "", "", "") # The symbology is switched to Representations arcpy.ApplySymbologyFromLayer_management("bldglayer", "C:/data/bldg_symbols.lyr") # 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", "", "", "") # The symbology is switched to Representations arcpy.ApplySymbologyFromLayer_management("footprintlayer", "C:/data/footprint_symbols.lyr") # 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")