web-dev-qa-db-ja.com

計画されたルートに関連する地理座標を保存する最良の方法は何ですか?

これが私のシナリオです:

アプリケーション「A」は、計画されたルートに対応する緯度と経度のポイントを生成します。ルート距離によっては、数千のポイントが存在する場合があります。 GeographyとGeometryのデータ型を知っていますが、SQL 2008で作成されたと思っていても、まだ誰も使用していないので、それを使用するのに適したシナリオはわかりません。アプリ「A」が生成するポイントに加えて、実際のルートに対応するアプリ「B」のポイントを保存する必要があります。すべて保存されたら、計画したルートからの逸脱を見つける必要があります。

3

これはNP完全問題かもしれません http://en.wikipedia.org/wiki/NP-complete 巡回セールスマン問題と比較してください http://en.wikipedia .org/wiki/Travelling_salesman_problem 私の大学のテキストが保管されているため、NP-Completeであるかどうかはわかりません。複雑さのクラスからしばらく経っています。

@kenwilsondbaによって提案されたテーブルアプローチから始めて、SQL Serverの空間データ型を使用して単純化された「ドリフト計算」を実行することはできないことは言うまでもありません。

より完全な(NP-Completeでない場合は)アプローチでは、実際のルートが他のものの間で軌道に戻った場所を探します。

ただし、必要なのがドリフトの単純な計算である場合、SQL Serverの空間データ型を使用して次のことを行うことができます。実際のルートが通過した場合、余分な宛先を捨てるだけで済みます。実際のルートが通過した場合、最後の実際のエンドポイントを繰り返します。 、ルートが軌道に戻ったセグメントはすべて無視し、ストップIDは実際には連続していると想定します。

この計算方法では、最初に迷っただけで残りのルートに迷わない実際のルートにもペナルティが課され、最後のポイントまでトラックに留まっている人には報いることに注意してください。

もう1つの注意点は、以下のテーブルデザインのフィールドが冗長であることです。

距離の計算は、デフォルトではメートル単位です。

CREATE TABLE a_planned_point (
    route_id            INT, 
    stop_id             INT,
    lat                 DECIMAL(10,7), 
    long                DECIMAL(10,7), 
    pointspatialdata    GEOGRAPHY,    
    city                VARCHAR(20),
    state               CHAR(2) )

CREATE TABLE b_actual_point (
    route_id            INT, 
    stop_id             INT,
    lat                 DECIMAL(10,7), 
    long                DECIMAL(10,7), 
    pointspatialdata    GEOGRAPHY,    
    city                VARCHAR(20),
    state               CHAR(2) )

CREATE TABLE c_planned_segment (
    route_id            INT, 
    start_id            INT,
    stop_id             INT,
    lat_planned_stop    DECIMAL(10,7), 
    long_planned_stop   DECIMAL(10,7), 
    city_planned        VARCHAR(20),
    state_planned       CHAR(2), 
    segmentspatialdata  GEOGRAPHY)

CREATE TABLE d_actual_segment (
    route_id            INT, 
    start_id            INT,
    stop_id             INT,
    lat_actual_stop     DECIMAL(10,7), 
    long_actual_stop    DECIMAL(10,7), 
    city_actual         VARCHAR(20),
    state_actual        CHAR(2), 
    segmentspatialdata  GEOGRAPHY)

CREATE TABLE e_drift_segment (
    route_id            INT, 
    planned_stop_id     INT,
    actual_stop_id      INT,
    lat_planned_stop    DECIMAL(10,7), 
    long_planned_stop   DECIMAL(10,7), 
    city_planned        VARCHAR(20),
    state_planned       CHAR(2), 
    lat_actual_stop     DECIMAL(10,7), 
    long_actual_stop    DECIMAL(10,7), 
    city_actual         VARCHAR(20),
    state_actual        CHAR(2), 
    distance_drift      FLOAT,
    segmentspatialdata  GEOGRAPHY)

INSERT INTO a_planned_point (route_id, stop_id, lat, long, pointspatialdata, city, state) VALUES
    (1, 0, 33.93, -118.40, CAST('POINT(-118.40 33.93)' AS GEOGRAPHY), 'Los Angeles', 'CA'), 
    (1, 1, 33.43, -112.02, CAST('POINT(-112.02 33.43)' AS GEOGRAPHY), 'Phoenix', 'AZ'),
    (1, 2, 39.75, -104.87, CAST('POINT(-104.87 39.75)' AS GEOGRAPHY), 'Denver', 'CO'), 
    (1, 3, 25.82, -80.28,  CAST('POINT(-80.28 25.82)' AS GEOGRAPHY),  'Miami Intl', 'FL'), 
    (1, 4, 40.77, -73.98,  CAST('POINT(-73.98 40.77)' AS GEOGRAPHY),  'New York', 'NY'), 
    (1, 5, 42.37, -71.03,  CAST('POINT(-71.03 42.37)' AS GEOGRAPHY),  'Boston', 'MA')

INSERT INTO b_actual_point (route_id, stop_id, lat, long, pointspatialdata, city, state) VALUES
    (1, 0, 33.93, -118.40, CAST('POINT(-118.40 33.93)' AS GEOGRAPHY), 'Los Angeles', 'CA'), 
    (1, 1, 39.75, -104.87, CAST('POINT(-104.87 39.75)' AS GEOGRAPHY), 'Denver', 'CO'), 
    (1, 2, 33.43, -112.02, CAST('POINT(-112.02 33.43)' AS GEOGRAPHY), 'Phoenix', 'AZ'),
    (1, 3, 25.82, -80.28,  CAST('POINT(-80.28 25.82)' AS GEOGRAPHY),  'Miami Intl', 'FL'), 
    (1, 4, 40.77, -73.98,  CAST('POINT(-73.98 40.77)' AS GEOGRAPHY),  'New York', 'NY')



INSERT INTO c_planned_segment (
    route_id,
    start_id, 
    stop_id,
    lat_planned_stop,
    long_planned_stop,
    city_planned,  
    state_planned,
    segmentspatialdata
    )
    SELECT 
        x.route_id, 
        x.stop_id, 
        y.stop_id, 
        y.lat, 
        y.long, 
        y.city, 
        y.state, 
        CAST('LINESTRING(' + CAST(x.long AS VARCHAR) +' '+ CAST(x.lat AS VARCHAR) +', '+ 
            CAST(y.long AS VARCHAR) +' '+ CAST(y.lat AS VARCHAR) + ')' AS GEOGRAPHY) AS segmentspatialdata
    FROM 
        a_planned_point x
    LEFT OUTER JOIN 
        a_planned_point y
    ON     
        y.stop_id = x.stop_id + 1 
    WHERE 
        y.stop_id IS NOT NULL   
        and 
        x.route_id = 1
    ORDER BY x.stop_id

INSERT INTO d_actual_segment (
    route_id, 
    start_id, 
    stop_id, 
    lat_actual_stop,
    long_actual_stop,  
    city_actual, 
    state_actual,
    segmentspatialdata 
    )
    SELECT 
        x.route_id, 
        x.stop_id, 
        y.stop_id, 
        y.lat, 
        y.long, 
        y.city, 
        y.state, 
        CAST('LINESTRING(' + CAST(x.long AS VARCHAR) +' '+ CAST(x.lat AS VARCHAR) +', '+ 
            CAST(y.long AS VARCHAR) +' '+ CAST(y.lat AS VARCHAR) + ')' AS GEOGRAPHY) AS segmentspatialdata
    FROM 
        b_actual_point x
    LEFT OUTER JOIN 
        b_actual_point y
    ON     
        y.stop_id = x.stop_id + 1 
    WHERE 
        y.stop_id IS NOT NULL   
        and 
        x.route_id = 1
    ORDER BY x.stop_id



INSERT INTO e_drift_segment (
    route_id, 
    planned_stop_id, 
    actual_stop_id, 
    lat_planned_stop, 
    long_planned_stop, 
    city_planned, 
    state_planned,
    lat_actual_stop,
    long_actual_stop,
    city_actual,
    state_actual,
    distance_drift,
    segmentspatialdata 
    )
    SELECT 
        x.route_id, 
        x.stop_id, 
        y.stop_id, 
        x.lat,
        x.long, 
        x.city, 
        x.state,
        y.lat, 
        y.long, 
        y.city, 
        y.state,
        x.pointspatialdata.STDistance(y.pointspatialdata), 
        CAST('LINESTRING(' + CAST(x.long AS VARCHAR) +' '+ CAST(x.lat AS VARCHAR) +', '+ 
            CAST(y.long + 0.0000001 AS VARCHAR) +' '+ CAST(y.lat AS VARCHAR) + ')' AS GEOGRAPHY) AS segmentspatialdata
    FROM 
        a_planned_point x
    LEFT OUTER JOIN 
        b_actual_point y
    ON     
        y.stop_id = x.stop_id 
    WHERE 
        x.stop_id IS NOT NULL   
        and 
        y.stop_id IS NOT NULL   
        and
        x.route_id = 1
    ORDER BY x.stop_id

ドリフトの総量をメートル単位で確認するには:

select sum(distance_drift) from e_drift_segment where route_id = 1

SQL Serverの[空間結果]タブで、計画されたルートセグメントと実際のルートセグメント、ドリフトルートセグメントの両方を一度に表示するには:

select segmentspatialdata from c_planned_segment where route_id = 1
union all
select segmentspatialdata from d_actual_segment where route_id = 1
union all
select segmentspatialdata from e_drift_segment where route_id = 1
3
kkarns

2つのテーブルの使用をお勧めします。計画ルートの表Aと実際のルートの表B。両方のテーブルにデータを入力したら、なんらかの識別子で2つのテーブルを結合し、STDistanceメソッドを使用して偏差を決定できます。このような状況で役立つと思う方法は他にもたくさんあります。

参照 http://technet.Microsoft.com/en-us/library/cc280766.aspx

1
KenWilson