2016-11-09 3 views
2

PostgreSQLのテーブルに格納されているポリゴンに対して、特定のポイントの最短距離を計算するアプリケーションを開発しています。PostgreSQLデータベースのST_Distance関数で距離が正しく計算されていませんか?

我々はPostgreSQLデータベースからのST_Distance関数を使用しています。

我々はGoogle Earthで算出した距離を比較すると、それらの間の広大な違いがあります。

もちろん、グーグルやPostgreSQLのどちらが間違っている可能性(あるいは、彼らは何ですか?)ので、我々は明らかにここで何かが欠けています。

何が問題になりますか?

私たちはグーグルアースのスクリーンショットと一緒にPostgreSQLのでテストしたサンプルクエリの下に与えられています。

SELECT ST_Distance(Place1, Place2) As Place1ToPlace2 
    , ST_Distance(Place1, Spot1) As Place1ToSpot1 
    , ST_Distance(Place1, Spot2) As Place1ToSpot2 
    , ST_Distance(Place2, Spot1) As Place2ToSpot1 
    , ST_Distance(Place2, Spot2) As Place2ToSpot2 
FROM (SELECT 
    ST_PolygonFromText('SRID=4326;POLYGON((-74.0050636293915 40.75265123968514,-74.00500355126653 40.75268991743845,-74.00498169169283 40.75267084386348,-74.00503571044075 40.75263867886528,-74.0050636293915 40.75265123968514))') as Spot1 
    ,ST_PolygonFromText('SRID=4326;POLYGON((-74.00503571044075 40.75263867886528,-74.00498225451273 40.75267084385684,-74.00495878551709 40.75265859837483,-74.00501023946696 40.75262521978885,-74.00503571044075 40.75263867886528))') as Spot2 
    ,ST_GeogFromText('SRID=4326;POINT(-74.00489 40.752894)') As Place1 
    ,ST_GeogFromText('SRID=4326;POINT(-74.004774 40.752846)') As Place2 
    ) As foo ; 

それは次の値になり:

place1toplace2 |place1tospot1 |place1tospot2 |place2tospot1 |place2tospot2 | 
---------------|--------------|--------------|--------------|--------------| 
11.152362504 |24.608417285 |25.977083731 |26.004190091 |26.011579435 | 

後は、Google Earthのからのスクリーンショットです:

  1. Place1ToPlace2
  2. Place1ToSpot2
  3. Place2ToSpot1
  4. Place2ToSpot2

事前に感謝します!続き

は、Google EarthのからエクスポートのKMLです:

<?xml version="1.0" encoding="UTF-8"?> 
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom"> 
<Document> 
    <name>Spot 1.kml</name> 
    <Style id="inline"> 
     <LineStyle> 
      <color>ff0000ff</color> 
      <width>2</width> 
     </LineStyle> 
     <PolyStyle> 
      <fill>0</fill> 
     </PolyStyle> 
    </Style> 
    <Style id="inline0"> 
     <LineStyle> 
      <color>ff0000ff</color> 
      <width>2</width> 
     </LineStyle> 
     <PolyStyle> 
      <fill>0</fill> 
     </PolyStyle> 
    </Style> 
    <StyleMap id="inline1"> 
     <Pair> 
      <key>normal</key> 
      <styleUrl>#inline</styleUrl> 
     </Pair> 
     <Pair> 
      <key>highlight</key> 
      <styleUrl>#inline0</styleUrl> 
     </Pair> 
    </StyleMap> 
    <Placemark> 
     <name>Spot 1</name> 
     <styleUrl>#inline1</styleUrl> 
     <Polygon> 
      <tessellate>1</tessellate> 
      <outerBoundaryIs> 
       <LinearRing> 
        <coordinates> 
         -74.0050636293915,40.75265123968514,0 -74.00500355126653,40.75268991743845,0 -74.00498169169283,40.75267084386348,0 -74.00503571044075,40.75263867886528,0 -74.0050636293915,40.75265123968514,0 
        </coordinates> 
       </LinearRing> 
      </outerBoundaryIs> 
     </Polygon> 
    </Placemark> 
</Document> 
</kml> 


<?xml version="1.0" encoding="UTF-8"?> 
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom"> 
<Document> 
    <name>Spot 2.kml</name> 
    <Style id="inline"> 
     <LineStyle> 
      <color>ff0000ff</color> 
      <width>2</width> 
     </LineStyle> 
     <PolyStyle> 
      <fill>0</fill> 
     </PolyStyle> 
    </Style> 
    <StyleMap id="inline0"> 
     <Pair> 
      <key>normal</key> 
      <styleUrl>#inline1</styleUrl> 
     </Pair> 
     <Pair> 
      <key>highlight</key> 
      <styleUrl>#inline</styleUrl> 
     </Pair> 
    </StyleMap> 
    <Style id="inline1"> 
     <LineStyle> 
      <color>ff0000ff</color> 
      <width>2</width> 
     </LineStyle> 
     <PolyStyle> 
      <fill>0</fill> 
     </PolyStyle> 
    </Style> 
    <Placemark> 
     <name>Spot 2</name> 
     <styleUrl>#inline0</styleUrl> 
     <Polygon> 
      <tessellate>1</tessellate> 
      <outerBoundaryIs> 
       <LinearRing> 
        <coordinates> 
         -74.00503571044075,40.75263867886528,0 -74.00498225451273,40.75267084385684,0 -74.00495878551709,40.75265859837483,0 -74.00501023946696,40.75262521978885,0 -74.00503571044075,40.75263867886528,0 
        </coordinates> 
       </LinearRing> 
      </outerBoundaryIs> 
     </Polygon> 
    </Placemark> 
</Document> 
</kml> 

EDIT 2!

もう1つ試しました。私はSpot1から視覚的にPlace1に最も近い場所を見つけ、Place3としてマークしました。

我々はマップ上でそれを見るとPlace3がPlace2よりPlace1に近いあるように、それは見えますが、クエリをチェックする際に、Place3までの距離がより高い値を示します。

私は次のクエリで確認している:

SELECT ST_Distance(Place1, Place2) As Place1ToPlace2 
,ST_Distance(Place1, Place3) As Place1ToPlace3 
FROM (SELECT 
    ST_GeogFromText('SRID=4326;POINT(-74.00489 40.752894)') As Place1 
    ,ST_GeogFromText('SRID=4326;POINT(-74.004774 40.752846)') As Place2 
    ,ST_GeogFromText('SRID=4326;POINT(-74.00500355126653 40.75268991743845)') As Place3 
    ) As foo; 

そして、それは次のような結果が得られます。

place1toplace2 |place1toplace3 | 
---------------|---------------| 
11.152362504 |24.608417285 | 

ながら地図上: Place1ToPlace3

後はPlace1、Place2用KMLですand Place3(KMLからスタイル関連のタグを削除しました)

私が見る
<?xml version="1.0" encoding="UTF-8"?> 
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom"> 
<Document> 
    <name>Distance Comparison.kml</name> 
    <Folder> 
     <name>Distance Comparison</name> 
     <open>1</open> 
     <Style> 
      <ListStyle> 
       <listItemType>check</listItemType> 
       <bgColor>00ffffff</bgColor> 
       <maxSnippetLines>2</maxSnippetLines> 
      </ListStyle> 
     </Style> 
     <Placemark> 
      <name>Place 1 - 40°45&apos;9.78&quot;N 74° 0&apos;18.07&quot;W (40.752894, -74.00489)</name> 
      <open>1</open> 
      <LookAt> 
       <longitude>-74.00500758183839</longitude> 
       <latitude>40.75269419172616</latitude> 
       <altitude>0</altitude> 
       <heading>-0.0008536233435993688</heading> 
       <tilt>29.8433509629012</tilt> 
       <range>47.16429940085073</range> 
       <gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode> 
      </LookAt> 
      <styleUrl>#msn_1</styleUrl> 
      <Point> 
       <gx:drawOrder>1</gx:drawOrder> 
       <coordinates>-74.00501944444444,40.75271666666666,0</coordinates> 
      </Point> 
     </Placemark> 
     <Placemark> 
      <name>Place 2 - 40°45&apos;9.54&quot;N 74° 0&apos;17.70&quot;W (40.752846, -74.004774)</name> 
      <open>1</open> 
      <LookAt> 
       <longitude>-74.00500758183839</longitude> 
       <latitude>40.75269419172616</latitude> 
       <altitude>0</altitude> 
       <heading>-0.0008536233435993688</heading> 
       <tilt>29.8433509629012</tilt> 
       <range>47.16429940085073</range> 
       <gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode> 
      </LookAt> 
      <styleUrl>#msn_2</styleUrl> 
      <Point> 
       <gx:drawOrder>1</gx:drawOrder> 
       <coordinates>-74.00491666666667,40.75265,0</coordinates> 
      </Point> 
     </Placemark> 
     <Placemark> 
      <name>Place 3 - 40°45&apos;9.68&quot;N 74° 0&apos;18.01&quot;W (40.75268991743845 -74.00500355126653)</name> 
      <open>1</open> 
      <styleUrl>#msn_3</styleUrl> 
      <Point> 
       <coordinates>-74.00500277777778,40.75268888888889,0</coordinates> 
      </Point> 
     </Placemark> 
    </Folder> 
</Document> 
</kml> 
+0

http://gis.stackexchange.com/この質問の良い場所はありますか? そこに移動するには? –

+1

私はPostgisで構築したポリゴンは、Google Earthで使ったポリゴンと同じではないと思います。 Google Earthから座標を抽出したか、またはGoogle Earthからポリゴンをkmlとしてエクスポートし、データを回答に追加してください。 –

+0

元々Google EarthからKMLをエクスポートしてクエリに使用しました。また、参考のためにオリジナルの質問にKMLを追加しました –

答えて

0

PostGISのあなたの機能は、Googleのどこにあるのかわかりません。私はそれを視覚化しています。

Points and polygons

今、2つの問題があります。まず、geometry and geographyの違い。第二に、距離の計算。

st_distanceオン地理はメートルで値を返します。だからこそ、あなたの最初のクエリの出力は基本的には、フィーチャーの位置を考慮すると(あなたのポイントは地理的な場所だったので、Postgresはポリゴンを地理学にキャストします)ただし、st_distance on ジオメトリは、下の投影の単位(この場合は度)の値を返します。 2番目のクエリの出力が説明されています。

オンdistance calculation。ここでは簡潔にしようとしていますが、計算に影響を及ぼす最大の問題は基礎となる予測です。わたしの理解から、地理タイプはより広い領域で優れています。分析している領域に適した投影図でジオメトリを使用すると、より正確な結果が得られます。 "suitable projection"は、あなたが見ている世界のどの部分があなたの目的であるかによって異なります。

また、Googleの数字が正しいと仮定しないでください。私はクイック検索を行いましたが、距離の計算方法については何も見つかりませんでした。彼らが別の方法を使用する場合は、別の答えを得るでしょう...

EDIT ここでは、スクリーンショットに表示される座標を使ったクエリです。座標値の違いに注意してください!また、スクリーンショットに表示される分 - 秒 - 秒は角括弧内の小数点以下の値と一致しません。返さ

SELECT ST_Distance(Place1, Place2) As Place1ToPlace2 
    , ST_Distance(Place1, Spot1) As Place1ToSpot1 
    , ST_Distance(Place1, Spot2) As Place1ToSpot2 
    , ST_Distance(Place2, Spot1) As Place2ToSpot1 
    , ST_Distance(Place2, Spot2) As Place2ToSpot2 
FROM (SELECT 
    ST_PolygonFromText('SRID=4326;POLYGON((-74.0050636293915 40.75265123968514,-74.00500355126653 40.75268991743845,-74.00498169169283 40.75267084386348,-74.00503571044075 40.75263867886528,-74.0050636293915 40.75265123968514))') as Spot1 
    ,ST_PolygonFromText('SRID=4326;POLYGON((-74.00503571044075 40.75263867886528,-74.00498225451273 40.75267084385684,-74.00495878551709 40.75265859837483,-74.00501023946696 40.75262521978885,-74.00503571044075 40.75263867886528))') as Spot2 
    ,ST_GeogFromText('SRID=4326;POINT(-74.005019 40.752717)') As Place1 
    ,ST_GeogFromText('SRID=4326;POINT(-74.004917 40.752650)') As Place2 
    ) As foo ; 

値は11.38223433、3.27827391、5.99175215、5.93327383、3.65564537です。それらはGoogleの検索結果の1cm以内です。

+0

私は同じ結果を得ました:座標は正しいようですが、Google Earthのスクリーンショットは別のものを表示します... –

+0

ポイントとポリゴンの間の計算ではなく、2点間の距離を計算しようとしました。結果は私には難解です。私は元の質問に編集として私のクエリを追加しました。 –

+0

Place1とPlace2は、あなたがそうだとは思わない場所です。3つ目の場所は、一番左のポリゴンの左上隅です(私の写真の中にあります)。あなたのスクリーンショットの小数点座標を見て、あなたのクエリの値と比較してください - それらは異なっています! – mlinth

0

I潜在的に大きな問題は、あなたがST_Distanceにお電話でのジオメトリや地域を混合していることです。​​を一見すると、ST_Distance関数はジオメトリまたはジオメトリのいずれかをとりますが、どちらも使用できません。

次のクエリを試してください。ここでは、あなたの呼び出しをST_GeogFromTextに置き換えました。地形を返します。ST_GeometryFromTextはジオメトリを返します。

SELECT ST_Distance(Place1, Place2) AS Place1ToPlace2, 
     ST_Distance(Place1, Spot1) AS Place1ToSpot1 
     ST_Distance(Place1, Spot2) AS Place1ToSpot2 
     ST_Distance(Place2, Spot1) AS Place2ToSpot1 
     ST_Distance(Place2, Spot2) AS Place2ToSpot2 
FROM 
(
    SELECT ST_PolygonFromText('SRID=4326;POLYGON((-74.0050636293915 40.75265123968514,-74.00500355126653 40.75268991743845,-74.00498169169283 40.75267084386348,-74.00503571044075 40.75263867886528,-74.0050636293915 40.75265123968514))') AS Spot1, 
      ST_PolygonFromText('SRID=4326;POLYGON((-74.00503571044075 40.75263867886528,-74.00498225451273 40.75267084385684,-74.00495878551709 40.75265859837483,-74.00501023946696 40.75262521978885,-74.00503571044075 40.75263867886528))') AS Spot2, 
      ST_GeometryFromText('SRID=4326;POINT(-74.00489 40.752894)') AS Place1 
      ST_GeometryFromText('SRID=4326;POINT(-74.004774 40.752846)') AS Place2 
) AS foo; 
+0

返事をありがとう。 PostgreSQLのドキュメントに従って、クエリーは投影された単位の2つのジオメトリ間の2次元デカルト最小距離(空間参照に基づく)の結果を提供します。これは元の質問にEDITとして追加した結果になります。 –

+0

私の質問をお試しください、それがあなたのために働いた場合はお知らせください。 –

関連する問題