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

データのジェネラライズは、多大な労力を必要とする多くの反復的なタスクを含んでいるため、自動化に最適な候補になります。 ただし、ジェネラライズの状況に依存する主観的性質は、自動化を困難にします。 人間の脳は、状況に依存する譲歩を、優先順位をつけて同時に行うことが得意です。 それと同じことを、一連の個別コマンドでコンピューターに遂行させることのほうがはるかに困難です。

ArcGIS のジオプロセシング環境は、データ、縮尺、および製品に固有に変数によって指示される明確な分離したステップでデータの変換を管理できるため、ジェネラライズ フレームワークを確立するのによく適しています。 これらのステップは、スクリプトまたはモデル内で論理的に一緒に連結されたり、ループすることもでき、ある範囲のデータに適用できる複雑なワークフローを作成し、印刷または画面表示用の複数縮尺データベースを生成します。 フィーチャの異なるグループに対して、タスクを簡単に連続的に繰り返すことができ、さまざまな方法で組み合わせた異なるパラメーターを使用することもできます。 ワークフロー全体を自動化または細分化し、手動で編集しながら整合チェックできます。

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

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

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

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

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

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

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

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

[道路網の間引き (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)] ツールに複数の入力をチェーニングします。

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

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

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

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

[アペンド (Append)] ツールを使用するモデル
このモデルが、[アペンド (Append)] ツールを使用して、複数の出力を単一入力に連結します。

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

場合によっては、ツールからの複数の出力を別のツールに個別に渡す必要があることがあります。 これは、1 番目のツールからの出力の一部を 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)] ツールを開始できるようになります。

前提条件を使用するモデル
処理順序を適用するため、[道路の競合を解決 (Resolve Road Conflicts)] ツールの出力が、[建物の競合を解決 (Resolve Building Conflicts)] ツールの前提条件として設定されます。

入力のシンボル表示

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

シンボル表示されたレイヤーを入力として使用するモデル
このモデルは、[フィーチャ レイヤーの作成 (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")

関連トピック