線形参照は、属性またはイベントと線形フィーチャの位置または一部分の関連付けを自然かつ有効に実現します。線形参照は、高速道路、鉄道、公共輸送路などの輸送アプリケーション、およびガソリンや石油の流通ルートなどの公共事業アプリケーションで広く使用されています。線形参照の主なメリットは、2つのパラメータ(経度/緯度またはx/yで表すデカルト領域)のかわりに、1つのパラメータ(通常メジャーという)によって、線形フィーチャに属性およびイベントを位置付けできることです。線形フィーチャでは、開始位置および終了位置を明示的に格納しなくても、線形フィーチャに沿ってそれらの位置を指定することによって、線形フィーチャを動的に参照および作成できます。
Oracle Spatialの線形参照システム(LRS)Application Program Interface(API)は、地図製作レベルでのLRS機能をサーバー側に提供します。線形メジャー情報は、Oracle Spatialのジオメトリ構造体に直接統合されます。Oracle SpatialのLRS APIは、動的セグメントをサポートし、すべての座標系の線形参照メソッドおよびモデルに対し、サード・パーティまたは中間層アプリケーション開発の基礎として機能します。
7.7項にLRSの例を示します。ただし、この例の示す概要を理解するためにも、この章のその他の項をはじめにお読みください。
LRSファンクションおよびLRSプロシージャのリファレンス情報については、第25章を参照してください。
この章の内容は次のとおりです。
この項では、Oracle Spatialでサポートされる線形参照に関連する重要な用語および概念について説明します。
ジオメトリ・セグメントは、Oracle SpatialにおけるLRSの基本的な要素です。ジオメトリ・セグメントは、次のいずれかのジオメトリです。
線ストリング: 順序付けされ、分岐のない連続するジオメトリ(単純な道路など)
複数線ストリング: 非接続線ストリング(湖やバイパス道路によって途切れた高速道路など)
ポリゴン(開始および終了が同一の点である競技トラックや観光ツアー・ルートなど)
ジオメトリ・セグメントは、開始点および終了点の開始メジャーおよび終了メジャーを含む必要があります。また、ジオメトリ・セグメント上の対象点のメジャー(高速道路の出口など)も割り当てられます。これらのメジャーは、ユーザーによって割り当てられるか、または既存のジオメトリ・セグメントから導出されます。図7-1に、4つの線セグメントと1つの円弧で構成されるジオメトリ・セグメントの例を示します。ジオメトリ・セグメント上の点は、3つの数値(x, y, m)で表します。xおよびyは位置を示し、mはメジャーを示します(図7-1で下線が付いた値がメジャー値を表します)。
形状点は、LRSセグメント作成時に指定される点で、メジャー情報が割り当てられます。Oracle Spatialでは、線セグメントは開始点および終了点で表され、円弧は3つの点(開始点、中間点および終了点)で表されます。形状点として3つの点を指定する必要がありますが、この3つの点にメジャー情報を格納する場合は、形状点としてその他の点を指定することもできます(たとえば、高速道路の直線部分の中間にある出口などです)。
形状点は、セグメント方向(たとえば、回転やカーブなど)を示す場合やメジャー情報が格納さる対象点を識別する場合に使用できます。
形状点は、LRSの距離標または参照標とは直接関連しませんが、内部的な参照点として使用されます。形状点のメジャー情報は、SDO_LRS.DEFINE_GEOM_SEGMENTプロシージャ(第25章を参照)を使用したLRSセグメントの定義時に自動的に移入されます。
ジオメトリ・セグメント方向は、ジオメトリ・セグメントの開始点から終了点で示されます。ジオメトリ・セグメント方向は、ジオメトリの定義における頂点の順序(開始点から終了点)によって決定されます。ジオメトリ・セグメント上の点のメジャーは、常にジオメトリ・セグメント方向に増減します。
ジオメトリ・セグメント上の点のメジャーは、ジオメトリ・セグメントの開始点(値が増加する場合)または終了点(値が減少する場合)から測定された点までの(メジャー次元の)線形距離です。メジャー情報は、それらの距離と同じ位取りでなくてもかまいません。ただし、メジャーと距離の線形マッピング関係は、常に保たれる必要があります。
LRSファンクションは、メジャーのかわりにオフセットを使用して、線形フィーチャに沿って測定した距離を表す場合もあります。線形参照システムでは、Oracle SpatialのLRSがメジャーとして参照するものを表すためにオフセットを使用する場合もありますが、Oracle Spatialでは、オフセットはメジャーとは別の意味を持ちます。詳細は、7.1.5項を参照してください。
ジオメトリ・セグメント上の点のオフセットとは、点とジオメトリ・セグメント間の垂直距離です。点がセグメント方向の左側にある場合、オフセット値は正、右側にある場合は負です。また、点がジオメトリ・セグメント上にある場合、オフセットは0(ゼロ)です。
オフセットの測定単位は、ジオメトリ・セグメントに関連付けられた座標系の測定単位と同じです。測地データの場合、デフォルトの測定単位はmです。
図7-2に、点がメジャーおよびオフセット情報とともにジオメトリ・セグメント上にどのように位置付けられるかを示します。オフセットをメジャーとともに割り当てることによって、ジオメトリ・セグメント上の点のみでなく、ジオメトリ・セグメントに垂直な点を位置付けることも可能です。
ジオメトリ・セグメントにまだ割り当てられていないメジャーがある場合、距離分布に基づいて自動的に移入されます。これは、不明なメジャー(Oracle SpatialではNULL)を持つジオメトリ・セグメントに対するLRS処理の前に行われます。ジオメトリ・セグメントにLRS処理を行うと、ジオメトリ・セグメントに関連付けられたメジャー情報が戻されます。ジオメトリ・セグメント上の点のメジャーは、前後のメジャーまたは位置間の線形マッピング関係に基づいて取得できます。詳細は、図7-3および図7-4を参照してください。
メジャーは、割り当てられたメジャーの間で均等に配置されます。ただし、ジオメトリ・セグメント上の対象点に対して割り当てられるメジャーは、均等でなくてもかまいません。これによって、エラーの蓄積や不正確なデータ・ソースの問題を排除できます。
また、割り当てられたメジャーは、実際の距離を反映する必要はなく(たとえば、見積り運転時間を反映できます)、メジャーの有効範囲内の有効な値を使用できます。図7-5に、割り当てられたメジャーの値が不均等で、距離が様々な場合のメジャーの移入の例を示します。
メジャーは、必ずセグメント方向に増分的に移入されます。これによって、以降のLRS処理のパフォーマンスが向上します。
ジオメトリ・セグメントの開始メジャーおよび終了メジャーは、ジオメトリ・セグメントの線形メジャー範囲を定義します。ジオメトリ・セグメントの有効なLRSメジャーは、線形メジャー範囲内で指定する必要があります。
LRS点は、線形メジャー情報を持つジオメトリ・セグメント上の点です。有効なLRS点は、メジャー情報を持つ点ジオメトリです。
すべてのLRS点データは、SDO_ELEM_INFO_ARRAYおよびSDO_ORDINATE_ARRAYに格納する必要があり、その点のSDO_GEOMETRY定義のSDO_POINTフィールドには格納できません。
線形フィーチャは、線形セグメントの論理セットとして処理できる空間オブジェクトです。輸送アプリケーションにおける高速道路や、公共事業アプリケーションにおける流通ルートなどが、線形フィーチャの例です。線形フィーチャ、ジオメトリ・セグメントおよびLRS点の関係を、図7-6に示します。この図では、1つの線形フィーチャが3つのジオメトリ・セグメントで構成され、3つのLRS点は最初のセグメントに示されています。
LRSジオメトリが複数線ストリングまたは穴のあるポリゴンの場合、SDO_LRS.DEFINE_GEOM_SEGMENTプロシージャおよびSDO_LRS.CONVERT_TO_LRS_GEOMファンクションは、あるセグメントの終了点と、その次のセグメントの(切れ目によって分離されている)開始点に、デフォルトで同じメジャー値を割り当てます(ただし、後で各点に異なる値を割り当てることは可能です)。したがって、このようなジオメトリの場合、デフォルトでは、異なるセグメントに同じメジャー値が割り当てられることになります。このような場合、LRSサブプログラムは、指定されたメジャーを持つ最初の点を選択します(ただし、その選択によってジオメトリが無効になる場合は除きます)。
たとえば、複数線ストリングLRSジオメトリの場合に、最初のセグメントのメジャーが0から100で、2番目のセグメントのメジャーが100から150とします。SDO_LRS.LOCATE_PTファンクションを使用してメジャーが100の点を検出する場合、戻される点は最初のセグメントのメジャー100の点になります。SDO_LRS.CLIP_GEOM_SEGMENT、SDO_LRS.DYNAMIC_SEGMENTまたはSDO_LRS.OFFSET_GEOM_SEGMENTファンクションを使用してメジャー値が75から125のジオメトリ・オブジェクトを戻す場合は、2つのセグメントで構成される複数線ストリング・ジオメトリが戻されます。同じファンクションを使用してメジャー値が100から125のジオメトリ・オブジェクトを戻す場合は、最初のセグメントのメジャー値100の点は無視され、結果は、メジャー値が100から125の2番目のセグメントに沿った線ストリングになります。
Oracle SpatialのLRSデータ・モデルは、メジャー情報を点レベルでジオメトリ表現に取り込みます。メジャー情報は、Oracle Spatialモデルに直接統合されます。そのためには、Oracle Spatialのメタデータにメジャー次元を追加する必要があります。
Oracle SpatialのLRSサポートは、Spatialのメタデータおよびデータ(ジオメトリ)に影響します。例7-1に、メジャー次元がSpatialのメタデータで2次元ジオメトリにどのように追加されるかを示します。メジャー次元は、空間オブジェクト定義におけるSDO_DIM_ARRAYの最後の要素(例7-1の太字を参照)である必要があります。
例7-1 SpatialメタデータへのLRSメジャー次元の取込み
INSERT INTO user_sdo_geom_metadata
(TABLE_NAME,
COLUMN_NAME,
DIMINFO,
SRID)
VALUES(
'LRS_ROUTES',
'GEOMETRY',
SDO_DIM_ARRAY (
SDO_DIM_ELEMENT('X', 0, 20, 0.005),
SDO_DIM_ELEMENT('Y', 0, 20, 0.005),
SDO_DIM_ELEMENT('M', 0, 100, 0.005)),
NULL);
新しいメジャー次元を追加すると、ジオメトリ・セグメントやLRS点などのメジャー情報を持つジオメトリを表現することができます。図7-7に、3つの線セグメントを持つジオメトリ・セグメントの作成例を示します。
図7-7では、ジオメトリ・セグメントは次のように定義されています(メジャー値には、下線が付いています)。
SDO_GEOMETRY(3302, NULL, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), SDO_ORDINATE_ARRAY(5,10,0, 20,5,NULL, 35,10,NULL, 55,10,100))
ジオメトリ・セグメントが定義されると、既存のジオメトリ・セグメントから開始および終了メジャーが定義または導出される必要があります。ジオメトリ・セグメント上にあるすべての形状点に、符号なしのメジャーがある場合は、自動的に移入されます。
LRSファンクションで使用されるすべての点ジオメトリのSDO_GTYPEは3301になります。
LRSデータに4次元(3次元およびM次元)があり、メジャー次元以外の3次元に索引付けする必要がある場合は、空間Rツリー索引を使用してデータを索引付けし、CREATE INDEX文にPARAMETERS('sdo_indx_dims=3')を指定して、確実に最初の3次元が索引付けされるようにする必要があります。ただし、sdo_indx_dims
に3以上の値を指定すると、3次元すべてを考慮する必要があるので、1.11項でリストされる演算子のみが、索引付けされたジオメトリに対して使用できます。第19章で説明する他の演算子は使用できません。(sdo_indx_dims
キーワードのデフォルト値は2です。この値を使用すると、最初の2次元のみが索引付けされます。)たとえば、次元がX、Y、ZおよびMの場合に、X、YおよびZの各次元を索引付けし、メジャー(M)次元を索引付けしないようにするには、sdo_indx_dims=3
を指定します。追加の処理オーバーヘッドが発生し、メリットがないため、メジャー次元は空間索引に含めないでください。
CREATE INDEX文およびそのパラメータとキーワードの詳細は、第18章を参照してください。
ほとんどのLRSファンクションは、末尾に_3Dの付いた形式(DEFINE_GEOM_SEGMENT_3D、CLIP_GEOM_SEGMENT_3D、FIND_MEASURE_3D、LOCATE_PT_3Dなど)と付かない形式を持ちます。3D形式を持つファンクションについては、第25章の各ファンクションの「使用上の注意」にその旨を示します。
3D形式は、単一線ストリングおよび複数線ストリングのジオメトリでのみサポートされます。3D形式は、ジオメトリ・オブジェクトに4次元があり、4つ目の次元がメジャーである場合(X、Y、Z、Mなど)、およびファンクションに最初の3次元(X、Y、Zなど)を考慮させる場合にのみ使用する必要があります。ファンクションの標準形式(_3Dが付いていない)を4次元を持つジオメトリに対して使用すると、ファンクションは最初の2次元(XおよびYなど)のみを考慮します。
たとえば、次の形式では、クリップ操作で、指定したGEOMオブジェクトのX、YおよびZ次元が考慮されます。
SELECT SDO_LRS.CLIP_GEOM_SEGMENT_3D(a.geom, m.diminfo, 5, 10) FROM routes r, user_sdo_geom_metadata m WHERE m.table_name = 'ROUTES' AND m.column_name = 'GEOM' AND r.route_id = 1;
ただし、次の形式では、クリップ操作で、指定したGEOMオブジェクトのXおよびY次元のみが考慮され、Z次元は無視されます。
SELECT SDO_LRS.CLIP_GEOM_SEGMENT(a.geom, m.diminfo, 5, 10) FROM routes r, user_sdo_geom_metadata m WHERE m.table_name = 'ROUTES' AND m.column_name = 'GEOM' AND r.route_id = 1;
すべてのファンクションの標準形式および3D形式のパラメータは同じであり、「使用上の注意」は両方の形式に適用されます。
3D形式は、次のデータではサポートされていません。
測地データ
ポリゴン、円弧または円
この項では、Oracle SpatialのLRS APIでサポートされている線形参照処理について説明します。
メジャー情報付きのジオメトリ・セグメントを作成するには、次の2つの方法があります。
ジオメトリ・セグメントを作成し、メジャーを明示的に割り当てます。
ジオメトリ・セグメントに、開始点と終了点および他のメジャーを付けて、昇順または降順に定義します。ジオメトリ・セグメント内に不明な(割り当てられていない)メジャー(NULL値)を持つ形状点メジャーは、それらの位置および距離分布に従って自動的に移入されます。
図7-8に、ジオメトリ・セグメントを定義する方法を示します。
LRS処理を進める前に、LRSセグメントを定義する(または、LRSセグメントがすでに存在している)必要があります。指定されたメジャーからの位置を求めるために、開始、終了および他の割り当てられたメジャーが存在する必要があります。メジャー値が割り当てられない場合は、中間の形状点のメジャー情報が自動的に移入されます。
ジオメトリ・セグメントを再定義し、開始点と終了点の間で、すべての形状点の既存のメジャーを、自動計算されたメジャーに置き換えることができます。セグメントの再定義は、明示的に指定された1つ以上のメジャーにエラーが発生した場合や、メジャーを均等に割り当てなおす場合に有効です。
図7-9に、既存(以前)の指定されたメジャー値が均等ではないセグメントの再定義を示します。
図7-9に示す再定義後のセグメントでは、移入メジャーは、セグメントに沿って一定間隔になっています。
ジオメトリ・セグメントをクリップして(図7-10のaを参照)、既存のジオメトリ・セグメントから新しいジオメトリ・セグメントを作成できます。
図7-10のaでは、セグメントがより大きいセグメントの一部から作成されます。新しいセグメントは独自の開始点および終了点を持ち、方向は元の大きいセグメントと同じです。
ジオメトリ・セグメントを分割して、2つの新しいジオメトリ・セグメントを作成できます(図7-10のbを参照)。新しい各セグメントの方向は、元のセグメントと同じです。
2つのジオメトリ・セグメントを連結して、1つの新しいジオメトリ・セグメントを作成できます(図7-10のcを参照)。図7-10のcに示すジオメトリ・セグメントは続いていますが、空間的に連続していなくてもかまいません。(セグメントが空間的に続いていない場合、連結された結果は複数線ストリングになります。)2つ目のジオメトリ・セグメントのメジャーが移動するため、1つ目のセグメントの終了メジャーは、2つ目のセグメントの開始メジャーと同じになります。連結の結果のセグメントの方向は、元の2つのジオメトリと同じになります。
図7-10のクリップ、分割および連結処理でのメジャーの割当てを、図7-11に示します。メジャー情報およびセグメント方向は、一貫性が保持されます。処理の完了時に、自動的にメジャー情報とセグメントが割り当てられます。
図7-12に示すとおり、連結の結果できるジオメトリ・セグメントの方向は、必ず1つ目のセグメント(SDO_LRS.CONCATENATE_GEOM_SEGMENTSファンクションへのコールのgeom_segment1
)の方向です。
SDO_LRS.CONCATENATE_GEOM_SEGMENTSファンクションを使用して2つの接続したセグメントを明示的に連結する他に、一括連結を実行できます。一括連結では、SDO_AGGR_LRS_CONCAT空間集計ファンクションを使用して、1つの列(レイヤー)に含まれるすべての接続したジオメトリ・セグメントを連結できます。(第20章のSDO_AGGR_LRS_CONCAT空間集計ファンクションの説明および例を参照。)
ジオメトリ・セグメントに対して線形スケール変更処理を実行すると、新しいジオメトリ・セグメントを作成できます。図7-13に、ジオメトリ・セグメントのスケール変更におけるマッピング関係を示します。
通常、ジオメトリ・セグメントのスケール変更には、新しく作成したジオメトリ・セグメントのメジャーの再配置が含まれます。ただし、スケール変更係数が負の場合、メジャーがジオメトリ・セグメント方向(形状点の順序によって定義される)に増加するように、形状点の順序を逆にする必要があります。
スケール変更処理は、次の処理を任意に組み合せて実行できます。
メジャー情報の変換(シフト)。(たとえば、同じ値をMsとMeに追加してM'sとM'eを取得。)
メジャー情報の反転。(M's = Me、M'e = Ms、Mshift = 0にするなど。)
メジャー情報の簡単なスケール変更。(Mshift = 0にするなど。)
これらの処理の例については、第25章のSDO_LRS.SCALE_GEOM_SEGMENT、SDO_LRS.TRANSLATE_MEASURE、SDO_LRS.REVERSE_GEOMETRYおよびSDO_LRS.REDEFINE_GEOM_SEGMENTサブプログラムの「使用上の注意」および「例」を参照してください。
ジオメトリ・セグメントに対してオフセットを設定すると、新しいジオメトリ・セグメントを作成できます。図7-14に、ジオメトリ・セグメントのオフセット設定におけるマッピング関係を示します。
図7-14に示すオフセット設定では、結果のジオメトリ・セグメントが、元のセグメントの指定された開始および終了メジャーから5単位でオフセット設定されています。
詳細は、第25章のSDO_LRS.OFFSET_GEOM_SEGMENTファンクションの「使用上の注意」および「例」を参照してください。
ジオメトリ・セグメントでメジャーおよびオフセットで示された点の位置を検索できます(図7-15を参照)。
ジオメトリ・セグメント上の特定のメジャーには、必ず一意の位置があります。オフセットが与えられたときに、メジャーによって表現された点がジオメトリ・セグメントの形状点上にある場合、あいまいさが発生します(図7-16を参照)。
図7-16に示すとおり、ジオメトリ・セグメント上の形状点のオフセット円弧は、すべての点が形状点から等しい最短距離にある円弧です。この結果、オフセット円弧上のすべての点は、メジャーとオフセットの同じ組合せで表されます。この1対多のマッピング問題を解決するために、オフセット円弧の中間点が戻されます。
ジオメトリ・セグメントに対応する点の投影点を検索できます。投影する点は、セグメント上にあってもセグメント外にあってもかまいません。点がセグメント上にある場合は、点およびその投影点は同じです。
投影は、図7-15に示す点の位置確認の逆の処理です。点の位置確認と同様に、形状点のオフセット円弧上のすべての点が同じ投影点(形状点)、メジャーおよびオフセットを持ちます(図7-16を参照)。点に対して複数の投影点がある場合、開始点から最初の点が戻されます(図7-17の図の投影点1)。
標準の線ストリング・フォーマットからLRSフォーマットにジオメトリを変換できます。また、その逆も可能です。既存の線ストリング・データが大量にある場合、すべてのLRSセグメントを手動で作成するより、変換ファンクションを使用すると便利です。ただし、特定のアプリケーションでLRSセグメントを標準の線ストリングに変換する機能も提供しています。
ファンクションによって、次のものを変換できます。
個々の線ストリングまたは点
標準フォーマットからLRSフォーマットへの変換では、メジャー次元(デフォルトではM)が追加され、それぞれの点にメジャー情報が付けられます。LRSフォーマットから標準フォーマットへの変換では、メジャー次元およびメジャー情報が削除されます。どちらの場合も、USER_SDO_GEOM_METADATAビューの次元情報(DIMINFO)のメタデータには影響しません。
レイヤー(列にあるすべてのジオメトリ)
標準フォーマットからLRSフォーマットへの変換では、メジャー次元(デフォルトではM)が追加されますが、それぞれの点にメジャー情報は付けられません。LRSフォーマットから標準フォーマットへの変換では、メジャー次元およびメジャー情報が削除されます。どちらの場合も、USER_SDO_GEOM_METADATAビューの次元情報(DIMINFO)のメタデータは、必要に応じて変更されます。
次元情報(DIMINFO)
USER_SDO_GEOM_METADATAビューの次元情報(DIMINFO)のメタデータは、必要に応じて変更されます。たとえば、XおよびY次元(SDO_DIM_ELEMENT)を持つ標準の次元配列をLRS次元配列に変換すると、M次元(SDO_DIM_ELEMENT)が追加されます。
図7-18に、SDO_LRS.CONVERT_TO_LRS_GEOMファンクションを使用して、標準線ストリングをLRS線ストリングに変換する場合のメジャー情報の追加を示します。図7-18では、メジャー次元値に下線が付いています。
点ジオメトリを変換すると、戻されるジオメトリのSDO_POINT属性(2.2.3項を参照)に次のように影響します。
標準の点をLRS点に変換すると、入力ジオメトリのSDO_POINT属性情報が結果のジオメトリのSDO_ELEM_INFOおよびSDO_ORDINATES属性(2.2.4項および2.2.5項を参照)の設定に使用され、結果のジオメトリのSDO_POINT属性がNULLに設定されます。
LRS点を標準の点に変換すると、入力ジオメトリのSDO_ELEM_INFOおよびSDO_ORDINATES属性(2.2.4項および2.2.5項を参照)の情報が結果のジオメトリのSDO_POINT属性情報の設定に使用され、結果のジオメトリのSDO_ELEM_INFOおよびSDO_ORDINATES属性がNULLに設定されます。
変換ファンクションについては、第25章の表25-3を参照してください。各変換ファンクションのリファレンス情報については、第25章を参照してください。
多くのLRSファンクションでは、許容差または1つ以上の次元配列を指定する必要があります。そのため、メジャー次元以外のすべての次元に対して1つの許容差を指定するか、または次元配列でメジャー次元以外の各次元に関連付けられている許容差を使用するかを選択できます。許容差は、メジャー次元ではなく、データのジオメトリ部分にのみ適用されます。測地データの許容差の単位はmです。非測地データの場合、許容差の単位はデータに関連付けられた測定単位です。(許容差の詳細は、1.5.5項を参照。)
データと目的に合った許容差を使用しているかどうかを確認してください。LRSファンクションの結果が正しくない場合、許容差を小さくする必要がある場合があります。
クリップ操作(7.5.3項を参照)およびオフセット操作(7.5.7項を参照)では、戻されたセグメントに入力ジオメトリ・セグメントの(本来、戻されたセグメントの開始点または終了点になる点から)許容差内の形状点が生成された場合、その形状点は、戻されたセグメントの開始点または終了点として使用されます。これは、結果のジオメトリに重複する頂点が含まれないようにするためです。頂点が重複すると、ジオメトリが無効になります。たとえば、図7-19では、ジオメトリ・セグメント(非測地データ)に関連付けられる許容差が0.5であると想定されています。
図7-19で、メジャー値0(開始点)と61.5の間のセグメントを戻すクリップ操作を要求し、メジャー値61.5と61.257に関連付けられた点の間の距離が許容差0.5未満である場合、戻されるセグメントの終了点は(35, 10, 61.257)になります。
この項では、LRSファンクションを使用する例を示します。この例では、この章で説明する概要および第25章で説明するファンクションを使用します。
図7-20の道路を使用して説明します。
図7-20で、高速道路(Route 1)は点2,2で始まり、点5,14で終了し、図示されているパスに従います。また、6つの入口と出口の点(Exit 1からExit 6)があります。単純化するために、グラフの単位は1メジャー単位を表し、開始点から終了点までのメジャーは27です(Exit 5からExit 6のセグメントは、辺が3:4:5の直角三角形の斜辺)。
表7-1に、実際の高速道路のフィーチャ、およびそのフィーチャに対応するLRSの機能またはそのフィーチャを表現するためのLRSの機能を示します。
表7-1 高速道路のフィーチャとLRSの機能
高速道路のフィーチャ | LRSの機能 |
---|---|
名前が付いたルート、道路、通り |
LRSセグメントまたは線形フィーチャ(セグメントの論理セット) |
マイルまたはkmの標識 |
メジャー |
事故の連絡および位置の追跡 |
SDO_LRS.LOCATE_PTファンクション |
建設区域(道路の一部) |
SDO_LRS.CLIP_GEOM_SEGMENTファンクション |
道路の拡張(開始地点または終了地点の追加)または連結(1つに重なる2つの道路の設計および変名) |
|
道路の改修または分割(名前が付いた1つの道路を名前が付いた2つの道路に分割) |
|
道路の外にある地点(建物など)に最も近い道路上にある地点の検索 |
SDO_LRS.PROJECT_PTファンクション |
道路沿いのガード・レールまたはフェンス |
SDO_LRS.OFFSET_GEOM_SEGMENTファンクション |
例7-2では、次の処理を行います。
図7-20に示すセグメントを格納する表を作成する
図7-20に示す高速道路の定義を表に挿入する
必要なメタデータをUSER_SDO_GEOM_METADATAビューに挿入する
PL/SQLおよびSQL文を使用して、セグメントの定義およびセグメントに対する処理を行う
例7-2 高速道路の例
-- Create a table for routes (highways). CREATE TABLE lrs_routes ( route_id NUMBER PRIMARY KEY, route_name VARCHAR2(32), route_geometry SDO_GEOMETRY); -- Populate table with just one route for this example. INSERT INTO lrs_routes VALUES( 1, 'Route1', SDO_GEOMETRY( 3302, -- line string, 3 dimensions: X,Y,M NULL, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), -- one line string, straight segments SDO_ORDINATE_ARRAY( 2,2,0, -- Start point - Exit1; 0 is measure from start. 2,4,2, -- Exit2; 2 is measure from start. 8,4,8, -- Exit3; 8 is measure from start. 12,4,12, -- Exit4; 12 is measure from start. 12,10,NULL, -- Not an exit; measure automatically calculated and filled. 8,10,22, -- Exit5; 22 is measure from start. 5,14,27) -- End point (Exit6); 27 is measure from start. ) ); -- Update the Spatial metadata. INSERT INTO user_sdo_geom_metadata (TABLE_NAME, COLUMN_NAME, DIMINFO, SRID) VALUES ( 'lrs_routes', 'route_geometry', SDO_DIM_ARRAY( -- 20X20 grid SDO_DIM_ELEMENT('X', 0, 20, 0.005), SDO_DIM_ELEMENT('Y', 0, 20, 0.005), SDO_DIM_ELEMENT('M', 0, 20, 0.005) -- Measure dimension ), NULL -- SRID ); -- Create the spatial index. CREATE INDEX lrs_routes_idx ON lrs_routes(route_geometry) INDEXTYPE IS MDSYS.SPATIAL_INDEX; -- Test the LRS procedures. DECLARE geom_segment SDO_GEOMETRY; line_string SDO_GEOMETRY; dim_array SDO_DIM_ARRAY; result_geom_1 SDO_GEOMETRY; result_geom_2 SDO_GEOMETRY; result_geom_3 SDO_GEOMETRY; BEGIN SELECT a.route_geometry into geom_segment FROM lrs_routes a WHERE a.route_name = 'Route1'; SELECT m.diminfo into dim_array from user_sdo_geom_metadata m WHERE m.table_name = 'LRS_ROUTES' AND m.column_name = 'ROUTE_GEOMETRY'; -- Define the LRS segment for Route1. This will populate any null measures. -- No need to specify start and end measures, because they are already defined -- in the geometry. SDO_LRS.DEFINE_GEOM_SEGMENT (geom_segment, dim_array); SELECT a.route_geometry INTO line_string FROM lrs_routes a WHERE a.route_name = 'Route1'; -- Split Route1 into two segments. SDO_LRS.SPLIT_GEOM_SEGMENT(line_string,dim_array,5,result_geom_1,result_geom_2); -- Concatenate the segments that were just split. result_geom_3 := SDO_LRS.CONCATENATE_GEOM_SEGMENTS(result_geom_1, dim_array, result_geom_2, dim_array); -- Update and insert geometries into table, to display later. UPDATE lrs_routes a SET a.route_geometry = geom_segment WHERE a.route_id = 1; INSERT INTO lrs_routes VALUES( 11, 'result_geom_1', result_geom_1 ); INSERT INTO lrs_routes VALUES( 12, 'result_geom_2', result_geom_2 ); INSERT INTO lrs_routes VALUES( 13, 'result_geom_3', result_geom_3 ); END; / -- First, display the data in the LRS table. SELECT route_id, route_name, route_geometry FROM lrs_routes; -- Are result_geom_1 and result_geom2 connected? SELECT SDO_LRS.CONNECTED_GEOM_SEGMENTS(a.route_geometry, b.route_geometry, 0.005) FROM lrs_routes a, lrs_routes b WHERE a.route_id = 11 AND b.route_id = 12; -- Is the Route1 segment valid? SELECT SDO_LRS.VALID_GEOM_SEGMENT(route_geometry) FROM lrs_routes WHERE route_id = 1; -- Is 50 a valid measure on Route1? (Should return FALSE; highest Route1 measure is 27.) SELECT SDO_LRS.VALID_MEASURE(route_geometry, 50) FROM lrs_routes WHERE route_id = 1; -- Is the Route1 segment defined? SELECT SDO_LRS.IS_GEOM_SEGMENT_DEFINED(route_geometry) FROM lrs_routes WHERE route_id = 1; -- How long is Route1? SELECT SDO_LRS.GEOM_SEGMENT_LENGTH(route_geometry) FROM lrs_routes WHERE route_id = 1; -- What is the start measure of Route1? SELECT SDO_LRS.GEOM_SEGMENT_START_MEASURE(route_geometry) FROM lrs_routes WHERE route_id = 1; -- What is the end measure of Route1? SELECT SDO_LRS.GEOM_SEGMENT_END_MEASURE(route_geometry) FROM lrs_routes WHERE route_id = 1; -- What is the start point of Route1? SELECT SDO_LRS.GEOM_SEGMENT_START_PT(route_geometry) FROM lrs_routes WHERE route_id = 1; -- What is the end point of Route1? SELECT SDO_LRS.GEOM_SEGMENT_END_PT(route_geometry) FROM lrs_routes WHERE route_id = 1; -- Translate (shift measure values) (+10). -- First, display the original segment; then, translate. SELECT a.route_geometry FROM lrs_routes a WHERE a.route_id = 1; SELECT SDO_LRS.TRANSLATE_MEASURE(a.route_geometry, m.diminfo, 10) FROM lrs_routes a, user_sdo_geom_metadata m WHERE m.table_name = 'LRS_ROUTES' AND m.column_name = 'ROUTE_GEOMETRY' AND a.route_id = 1; -- Redefine geometric segment to "convert" miles to kilometers DECLARE geom_segment SDO_GEOMETRY; dim_array SDO_DIM_ARRAY; BEGIN SELECT a.route_geometry into geom_segment FROM lrs_routes a WHERE a.route_name = 'Route1'; SELECT m.diminfo into dim_array from user_sdo_geom_metadata m WHERE m.table_name = 'LRS_ROUTES' AND m.column_name = 'ROUTE_GEOMETRY'; -- "Convert" mile measures to kilometers (27 * 1.609 = 43.443). SDO_LRS.REDEFINE_GEOM_SEGMENT (geom_segment, dim_array, 0, -- Zero starting measure: LRS segment starts at start of route. 43.443); -- End of LRS segment. 27 miles = 43.443 kilometers. -- Update and insert geometries into table, to display later. UPDATE lrs_routes a SET a.route_geometry = geom_segment WHERE a.route_id = 1; END;/ -- Display the redefined segment, with all measures "converted." SELECT a.route_geometry FROM lrs_routes a WHERE a.route_id = 1; -- Clip a piece of Route1. SELECT SDO_LRS.CLIP_GEOM_SEGMENT(route_geometry, 5, 10) FROM lrs_routes WHERE route_id = 1; -- Point (9,3,NULL) is off the road; should return (9,4,9). SELECT SDO_LRS.PROJECT_PT(route_geometry, SDO_GEOMETRY(3301, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1, 1), SDO_ORDINATE_ARRAY(9, 3, NULL)) ) FROM lrs_routes WHERE route_id = 1; -- Return the measure of the projected point. SELECT SDO_LRS.GET_MEASURE( SDO_LRS.PROJECT_PT(a.route_geometry, m.diminfo, SDO_GEOMETRY(3301, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1, 1), SDO_ORDINATE_ARRAY(9, 3, NULL)) ), m.diminfo ) FROM lrs_routes a, user_sdo_geom_metadata m WHERE m.table_name = 'LRS_ROUTES' AND m.column_name = 'ROUTE_GEOMETRY' AND a.route_id = 1; -- Is point (9,3,NULL) a valid LRS point? (Should return TRUE.) SELECT SDO_LRS.VALID_LRS_PT( SDO_GEOMETRY(3301, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1, 1), SDO_ORDINATE_ARRAY(9, 3, NULL)), m.diminfo) FROM lrs_routes a, user_sdo_geom_metadata m WHERE m.table_name = 'LRS_ROUTES' AND m.column_name = 'ROUTE_GEOMETRY' AND a.route_id = 1; -- Locate the point on Route1 at measure 9, offset 0. SELECT SDO_LRS.LOCATE_PT(route_geometry, 9, 0) FROM lrs_routes WHERE route_id = 1;
例7-3 SELECT文の出力例
SQL> -- First, display the data in the LRS table. SQL> SELECT route_id, route_name, route_geometry FROM lrs_routes; ROUTE_ID ROUTE_NAME ---------- -------------------------------- ROUTE_GEOMETRY(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDIN -------------------------------------------------------------------------------- 1 Route1 SDO_GEOMETRY(3302, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 2, 1), SDO_ORDINATE_ARRAY( 2, 2, 0, 2, 4, 2, 8, 4, 8, 12, 4, 12, 12, 10, 18, 8, 10, 22, 5, 14, 27)) 11 result_geom_1 SDO_GEOMETRY(3302, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 2, 1), SDO_ORDINATE_ARRAY( 2, 2, 0, 2, 4, 2, 5, 4, 5)) 12 result_geom_2 ROUTE_ID ROUTE_NAME ---------- -------------------------------- ROUTE_GEOMETRY(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDIN -------------------------------------------------------------------------------- SDO_GEOMETRY(3302, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 2, 1), SDO_ORDINATE_ARRAY( 5, 4, 5, 8, 4, 8, 12, 4, 12, 12, 10, 18, 8, 10, 22, 5, 14, 27)) 13 result_geom_3 SDO_GEOMETRY(3302, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 2, 1), SDO_ORDINATE_ARRAY( 2, 2, 0, 2, 4, 2, 5, 4, 5, 8, 4, 8, 12, 4, 12, 12, 10, 18, 8, 10, 22, 5, 14, 27) ) SQL> -- Are result_geom_1 and result_geom2 connected? SQL> SELECT SDO_LRS.CONNECTED_GEOM_SEGMENTS(a.route_geometry, 2 b.route_geometry, 0.005) 3 FROM lrs_routes a, lrs_routes b 4 WHERE a.route_id = 11 AND b.route_id = 12; SDO_LRS.CONNECTED_GEOM_SEGMENTS(A.ROUTE_GEOMETRY,B.ROUTE_GEOMETRY,0.005) -------------------------------------------------------------------------------- TRUE SQL> -- Is the Route1 segment valid? SQL> SELECT SDO_LRS.VALID_GEOM_SEGMENT(route_geometry) 2 FROM lrs_routes WHERE route_id = 1; SDO_LRS.VALID_GEOM_SEGMENT(ROUTE_GEOMETRY) -------------------------------------------------------------------------------- TRUE SQL> -- Is 50 a valid measure on Route1? (Should return FALSE; highest Route1 measure is 27.) SQL> SELECT SDO_LRS.VALID_MEASURE(route_geometry, 50) 2 FROM lrs_routes WHERE route_id = 1; SDO_LRS.VALID_MEASURE(ROUTE_GEOMETRY,50) -------------------------------------------------------------------------------- FALSE SQL> -- Is the Route1 segment defined? SQL> SELECT SDO_LRS.IS_GEOM_SEGMENT_DEFINED(route_geometry) 2 FROM lrs_routes WHERE route_id = 1; SDO_LRS.IS_GEOM_SEGMENT_DEFINED(ROUTE_GEOMETRY) -------------------------------------------------------------------------------- TRUE SQL> -- How long is Route1? SQL> SELECT SDO_LRS.GEOM_SEGMENT_LENGTH(route_geometry) 2 FROM lrs_routes WHERE route_id = 1; SDO_LRS.GEOM_SEGMENT_LENGTH(ROUTE_GEOMETRY) ------------------------------------------- 27 SQL> -- What is the start measure of Route1? SQL> SELECT SDO_LRS.GEOM_SEGMENT_START_MEASURE(route_geometry) 2 FROM lrs_routes WHERE route_id = 1; SDO_LRS.GEOM_SEGMENT_START_MEASURE(ROUTE_GEOMETRY) -------------------------------------------------- 0 SQL> -- What is the end measure of Route1? SQL> SELECT SDO_LRS.GEOM_SEGMENT_END_MEASURE(route_geometry) 2 FROM lrs_routes WHERE route_id = 1; SDO_LRS.GEOM_SEGMENT_END_MEASURE(ROUTE_GEOMETRY) ------------------------------------------------ 27 SQL> -- What is the start point of Route1? SQL> SELECT SDO_LRS.GEOM_SEGMENT_START_PT(route_geometry) 2 FROM lrs_routes WHERE route_id = 1; SDO_LRS.GEOM_SEGMENT_START_PT(ROUTE_GEOMETRY)(SDO_GTYPE, SDO_SRID, SDO_POINT(X, -------------------------------------------------------------------------------- SDO_GEOMETRY(3301, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1, 1), SDO_ORDINATE_ARRAY( 2, 2, 0)) SQL> -- What is the end point of Route1? SQL> SELECT SDO_LRS.GEOM_SEGMENT_END_PT(route_geometry) 2 FROM lrs_routes WHERE route_id = 1; SDO_LRS.GEOM_SEGMENT_END_PT(ROUTE_GEOMETRY)(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, -------------------------------------------------------------------------------- SDO_GEOMETRY(3301, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1, 1), SDO_ORDINATE_ARRAY( 5, 14, 27)) SQL> -- Translate (shift measure values) (+10). SQL> -- First, display the original segment; then, translate. SQL> SELECT a.route_geometry FROM lrs_routes a WHERE a.route_id = 1; ROUTE_GEOMETRY(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDIN -------------------------------------------------------------------------------- SDO_GEOMETRY(3302, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 2, 1), SDO_ORDINATE_ARRAY( 2, 2, 0, 2, 4, 2, 8, 4, 8, 12, 4, 12, 12, 10, 18, 8, 10, 22, 5, 14, 27)) SQL> SELECT SDO_LRS.TRANSLATE_MEASURE(a.route_geometry, m.diminfo, 10) 2 FROM lrs_routes a, user_sdo_geom_metadata m 3 WHERE m.table_name = 'LRS_ROUTES' AND m.column_name = 'ROUTE_GEOMETRY' 4 AND a.route_id = 1; SDO_LRS.TRANSLATE_MEASURE(A.ROUTE_GEOMETRY,M.DIMINFO,10)(SDO_GTYPE, SDO_SRID, SD -------------------------------------------------------------------------------- SDO_GEOMETRY(3302, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 2, 1), SDO_ORDINATE_ARRAY( 2, 2, 10, 2, 4, 12, 8, 4, 18, 12, 4, 22, 12, 10, 28, 8, 10, 32, 5, 14, 37)) SQL> -- Redefine geometric segment to "convert" miles to kilometers SQL> DECLARE 2 geom_segment SDO_GEOMETRY; 3 dim_array SDO_DIM_ARRAY; 4 5 BEGIN 6 7 SELECT a.route_geometry into geom_segment FROM lrs_routes a 8 WHERE a.route_name = 'Route1'; 9 SELECT m.diminfo into dim_array from 10 user_sdo_geom_metadata m 11 WHERE m.table_name = 'LRS_ROUTES' AND m.column_name = 'ROUTE_GEOMETRY'; 12 13 -- "Convert" mile measures to kilometers (27 * 1.609 = 43.443). 14 SDO_LRS.REDEFINE_GEOM_SEGMENT (geom_segment, 15 dim_array, 16 0, -- Zero starting measure: LRS segment starts at start of route. 17 43.443); -- End of LRS segment. 27 miles = 43.443 kilometers. 18 19 -- Update and insert geometries into table, to display later. 20 UPDATE lrs_routes a SET a.route_geometry = geom_segment 21 WHERE a.route_id = 1; 22 23 END; 24 / PL/SQL procedure successfully completed. SQL> -- Display the redefined segment, with all measures "converted." SQL> SELECT a.route_geometry FROM lrs_routes a WHERE a.route_id = 1; ROUTE_GEOMETRY(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDIN -------------------------------------------------------------------------------- SDO_GEOMETRY(3302, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 2, 1), SDO_ORDINATE_ARRAY( 2, 2, 0, 2, 4, 3.218, 8, 4, 12.872, 12, 4, 19.308, 12, 10, 28.962, 8, 10, 35.398 , 5, 14, 43.443)) SQL> -- Clip a piece of Route1. SQL> SELECT SDO_LRS.CLIP_GEOM_SEGMENT(route_geometry, 5, 10) 2 FROM lrs_routes WHERE route_id = 1; SDO_LRS.CLIP_GEOM_SEGMENT(ROUTE_GEOMETRY,5,10)(SDO_GTYPE, SDO_SRID, SDO_POINT(X, -------------------------------------------------------------------------------- SDO_GEOMETRY(3302, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 2, 1), SDO_ORDINATE_ARRAY( 5, 4, 5, 8, 4, 8, 10, 4, 10)) SQL> -- Point (9,3,NULL) is off the road; should return (9,4,9). SQL> SELECT SDO_LRS.PROJECT_PT(route_geometry, 2 SDO_GEOMETRY(3301, NULL, NULL, 3 SDO_ELEM_INFO_ARRAY(1, 1, 1), 4 SDO_ORDINATE_ARRAY(9, 3, NULL)) ) 5 FROM lrs_routes WHERE route_id = 1; SDO_LRS.PROJECT_PT(ROUTE_GEOMETRY,SDO_GEOMETRY(3301,NULL,NULL,SDO_EL -------------------------------------------------------------------------------- SDO_GEOMETRY(3301, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1, 1), SDO_ORDINATE_ARRAY( 9, 4, 9)) SQL> -- Return the measure of the projected point. SQL> SELECT SDO_LRS.GET_MEASURE( 2 SDO_LRS.PROJECT_PT(a.route_geometry, m.diminfo, 3 SDO_GEOMETRY(3301, NULL, NULL, 4 SDO_ELEM_INFO_ARRAY(1, 1, 1), 5 SDO_ORDINATE_ARRAY(9, 3, NULL)) ), 6 m.diminfo ) 7 FROM lrs_routes a, user_sdo_geom_metadata m 8 WHERE m.table_name = 'LRS_ROUTES' AND m.column_name = 'ROUTE_GEOMETRY' 9 AND a.route_id = 1; SDO_LRS.GET_MEASURE(SDO_LRS.PROJECT_PT(A.ROUTE_GEOMETRY,M.DIMINFO,SDO_GEOM -------------------------------------------------------------------------------- 9 SQL> -- Is point (9,3,NULL) a valid LRS point? (Should return TRUE.) SQL> SELECT SDO_LRS.VALID_LRS_PT( 2 SDO_GEOMETRY(3301, NULL, NULL, 3 SDO_ELEM_INFO_ARRAY(1, 1, 1), 4 SDO_ORDINATE_ARRAY(9, 3, NULL)), 5 m.diminfo) 6 FROM lrs_routes a, user_sdo_geom_metadata m 7 WHERE m.table_name = 'LRS_ROUTES' AND m.column_name = 'ROUTE_GEOMETRY' 8 AND a.route_id = 1; SDO_LRS.VALID_LRS_PT(SDO_GEOMETRY(3301,NULL,NULL,SDO_ELEM_INFO_ARRAY ------------------------------------------------------------------------------ TRUE SQL> -- Locate the point on Route1 at measure 9, offset 0. SQL> SELECT SDO_LRS.LOCATE_PT(route_geometry, 9, 0) 2 FROM lrs_routes WHERE route_id = 1; SDO_LRS.LOCATE_PT(ROUTE_GEOMETRY,9,0)(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), S -------------------------------------------------------------------------------- SDO_GEOMETRY(3301, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1, 1), SDO_ORDINATE_ARRAY( 9, 4, 9))