ジオプロセシングによる競合解決/ジェネラライズ ワークフローの自動化

データのジェネラライズでは、手間のかかる反復タスクを多数実行します。そのため、自動化を施すのが理想的です。ただし、ジェネラライズは本質的に状況依存型であり主観的であることから自動化が困難になっています。人間の頭脳は、優先順位付けと状況認知との同時履行を得意としています。それと同じことを、一連の個別コマンドでコンピューターに遂行させることのほうがはるかに困難です。

ArcGIS のジオプロセシング環境は、ジェネラライズ フレームワークの確立によく適しています。これは、データ、縮尺、および製品固有の変数を使用して、互いに独立した手順でデータ変換を処理することができるためです。これらの手順は論理的に連結でき、スクリプトまたはモデル内でループさせて複合ワークフローを作成することもできます。この複合ワークフローを一連のデータに適用して、印刷用または画面表示用のマルチスケール データベースを生成できます。さまざまなフィーチャ グループに対してタスクを連続して容易に反復実行することも、その際に複数のパラメーターを数通りに組み合わせて指定することもできます。ワークフロー全体を自動化または細分化し、手動で編集しながら整合チェックできます。

ジェネラライズ タスクの結合によるカートグラフィック ワークフローの生成

データの既定の縮尺よりも小さい縮尺でマップを作成する工程は、ターゲット縮尺、表示仕様 (たとえば、シンボル)、マップの根本的な目的や意図について理解することから始まります。それに続いて、データセットの接続性や特性に影響をおよぼさずに、フィーチャの全体的な数を減らすための操作を実行します。次に、頂点または他のフィーチャの詳細を除去して、個々のフィーチャの複雑さを軽減します。また、フィーチャ属性の複雑さを軽減するには、フィーチャの類似サブカテゴリ同士を組み合わせて同じシンボルを表示に使う方法もあります。マップの作成を開始した後は、データが最終的なシンボルと一緒に最終的な縮尺で表示されるようになり、シンボル表現の競合の検出と解決が可能になります。

次のフローチャートは、ジェネラライズ ワークフローの簡易バージョンを図示したもので、[カートグラフィ] ツールボックスのツールの中から、データをジェネラライズして縮尺を縮小しながら表示を調整するうえで補助になる主なツールも挙げてあります。

工程の概要図と対応するジオプロセシング ツール (カートグラフィックス表示用データのジェネラライズに使用)
工程の概要図と対応するジオプロセシング ツール (カートグラフィックス表示用データのジェネラライズに使用)

ほとんどのジオプロセシング ツールは通常、出力として新しいデータを生成します。この出力は、以降に実行するツールの入力として使用できます。このことは重要ですので念頭に置いてください。これとは対照的に、地図製作者は、マップ ドキュメント内にすでに確立されているフィーチャ レイヤーの段階的な改良を特徴とするワークフローを利用するのが一般的です。シンボル、レイヤー プロパティ、およびマスキング リレーションシップはすでに定義されているので、入力レイヤーを変更することのほうが望ましいといえます。変更なら、競合解決およびジェネラライズの操作の実行後も、この情報が失われる心配はありません。この理由から、[カートグラフィ] ツールボックスの一部のツールは、データを作成せずに、シンボル表示されたレイヤー内の入力データを変更できるようになっています。

ModelBuilder のジェネラライズ ツールのチェーニング

[ジェネラライズ] ツールには、複数値の入力 (1 つまたは複数のフィーチャクラスのリスト) が利用されます。ジオプロセシング ツール (たとえば、[ユニオン (Union)] ツール) は複数値を受け入れるものが大半を占めていますが、[ジェネラライズ] ツールは複数値の出力も行うという点で特異的です。このため、望みのモデルを生成するには、ModelBuilder の手法を 2 ~ 3 覚える必要があります。これらの方法については、この後で説明します。

複数の入/出力によるツールのチェーニング

[道路網の間引き (Thin Road Network)] ツール、[道路の競合を解決 (Resolve Road Conflicts)] ツール、および [建物の競合を解決 (Resolve Building Conflicts)] ツールの場合、出力は複数値です。つまり、これらのツールの出力を直接使えるのは、複数値の入力を受け入れるツールだけです。たとえば、3 つのレイヤーを [道路網の間引き (Thin Road Network)] ツールへの入力として使用した場合、間引き後に同じ 3 つのレイヤーを [道路の競合を解決 (Resolve Road Conflicts)] ツールへの入力としても使用したいときは、[道路網の間引き (Thin Road Network)] ツールの出力を [道路の競合を解決 (Resolve Road Conflicts)] ツールに直接チェーニングするという方法が有効です。

[道路網の間引き (Thin Road Network)] ツールから [道路の競合を解決 (Resolve Road Conflicts)] ツールに複数の入力をチェーニングします。
[道路網の間引き (Thin Road Network)] ツールから [道路の競合を解決 (Resolve Road Conflicts)] ツールに複数の入力をチェーニングします。

別途にレイヤーを複数値に追加するには、[値の収集] ツールを使用します。下の例は、別途 2 つのレイヤーを [道路網の間引き (Thin Road Network)] の出力に追加して、[道路の競合を解決 (Resolve Road Conflicts)] への入力を作成する方法を示しています。

[値の収集] ツールを使用して、別途の入力を [道路網の間引き (Thin Road Network)] ツールからの複数値の出力に追加してから、[道路の競合を解決 (Resolve Road Conflicts)] ツールにチェーニングさせます。
[値の収集] ツールを使用して、別途の入力を [道路網の間引き (Thin Road Network)] ツールからの複数値の出力に追加してから、[道路の競合を解決 (Resolve Road Conflicts)] ツールにチェーニングさせます。

複数の出力を単一入力にチェーニング

複数値を出力するツールを単一入力の可能なツールにチェーニングさせるには、[アペンド (Append)] ツールを使用して、複数のフィーチャクラスをマージします。このワークフローの例では、[道路網の間引き (Thin Road Network)] ツールで処理された複数の道路入力レイヤーをアペンドして、単一入力だけを受け入れる [道路のマージ (Merge Divided Roads)] ツールへの入力として使用しています。

[アペンド (Append)] ツールを使用して、複数の出力を単一入力に連結
[アペンド (Append)] ツールを使用して、複数の出力を単一入力に連結

複数の入力の個別チェーニング

場合によっては、あるツールからの複数出力を個別に別のツールに渡したいことがあります。たとえば、最初のツールからの出力の一部だけを 2 番目のツールに使用したい場合や、2 番目のツールで入力ごとに特定のパラメーターを設定したい場合などです。たとえば、[建物の競合を解決 (Resolve Building Conflicts)] ツールを使用すると、各入力レイヤーをバリアとして定義する方法を十分に制御できます。これらの例では、両方のツールへの入力と同じレイヤーのセットを使用しますが、最初のツールの出力を 2 番目のツールの前提条件として設定し、正しい処理順序が適用されるようにします (下の図を参照)。この手法を適用すると望ましいのは、最初のツール (たとえば [道路の競合を解決 (Resolve Road Conflicts)] ツールなど) で、新しい出力レイヤーの作成は行わずに、入力レイヤーが変更可能な場合です。

ModelBuilder での事前条件の使用方法の詳細

下の例では、3 つのトランスポート レイヤーを、両方のツールへの入力として使用しています。これが可能になっている理由は、これらのレイヤー [道路の競合を解決 (Resolve Road Conflicts)] で変更され、新しい出力フィーチャクラスは作成されないためです。[道路の競合を解決 (Resolve Road Conflicts)] ツールの出力を [建物の競合を解決 (Resolve Building Conflicts)] ツールを処理するための前提条件として使用することによって、[道路の競合を解決 (Resolve Road Conflicts)] ツールの処理が完了してから、[建物の競合を解決 (Resolve Building Conflicts)] ツールを開始できるようになります。

あるツールの出力を別のツールの前提条件として設定し、正しい処理順序が適用されるようにします。

入力のシンボル表示

シンボル表示されたレイヤーだけを受け入れるツール同士をチェーニングさせるには、[フィーチャ レイヤーの作成 (Make Feature Layer)] ツールと [レイヤーのシンボル情報を適用 (Apply Symbology From Layer)] ツールを使用して、ModelBuilder およびスクリプト環境でのチェーニング用途に合わせて出力レイヤーを準備する必要があります。

[フィーチャ レイヤーの作成 (Make Feature Layer)] ツールと [レイヤーのシンボル情報を適用 (Apply Symbology From Layer)] ツールを使用して、ツール間でシンボル情報を受け渡します。
[フィーチャ レイヤーの作成 (Make Feature Layer)] ツールと [レイヤーのシンボル情報を適用 (Apply Symbology From Layer)] を使用して、ツール間でシンボル情報を受け渡します。

縮尺を縮小しながらデータの表示を調整する 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
#              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")

関連トピック