2017-10-09 11 views
0

OpenStreetMapsに表示されている建物の面積を自動的に計算しようとしています。
これを行うために、私は橋渡しAPIを介して建物ポリゴンの座標を取得します。なぜ私はPostGis ST_Areaと比べてわずかに異なる領域を取得するのですか?

私はJavaScriptでエリアmyselfsを計算する前に、今、私に

{ 
    "version": 0.6, 
    "generator": "Overpass API", 
    "osm3s": { 
    "timestamp_osm_base": "2017-10-09T09:54:02Z", 
    "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." 
    }, 
    "elements": [ 

{ 
    "type": "way", 
    "id": 29858799, 
    "bounds": { 
    "minlat": 47.3604067, 
    "minlon": 8.5342631, 
    "maxlat": 47.3612503, 
    "maxlon": 8.5352457 
    }, 
    "geometry": [ 
    { "lat": 47.3612503, "lon": 8.5351944 }, 
    { "lat": 47.3612252, "lon": 8.5342631 }, 
    { "lat": 47.3610145, "lon": 8.5342755 }, 
    { "lat": 47.3610212, "lon": 8.5345227 }, 
    { "lat": 47.3606405, "lon": 8.5345451 }, 
    { "lat": 47.3606350, "lon": 8.5343411 }, 
    { "lat": 47.3604067, "lon": 8.5343545 }, 
    { "lat": 47.3604120, "lon": 8.5345623 }, 
    { "lat": 47.3604308, "lon": 8.5352457 }, 
    { "lat": 47.3606508, "lon": 8.5352328 }, 
    { "lat": 47.3606413, "lon": 8.5348784 }, 
    { "lat": 47.3610383, "lon": 8.5348551 }, 
    { "lat": 47.3610477, "lon": 8.5352063 }, 
    { "lat": 47.3612503, "lon": 8.5351944 } 
    ] 
} 

    ] 
} 

を出力 https://overpass-turbo.eu/

[out:json]; 
way(29858799); 
out ids geom; 

、私は、PostGISのに入れて、PostGISのが私与えるものの領域を参照してください。

SELECT  
    ST_Area 
     (
     ST_GeomFromText(' 
POLYGON 
(
     (
      47.3612503 8.5351944 
      ,47.3612252 8.5342631,47.3610145 8.5342755,47.3610212 8.5345227,47.3606405 8.5345451 
      ,47.3606350 8.5343411,47.3604067 8.5343545,47.3604120 8.5345623,47.3604308 8.5352457 
      ,47.3606508 8.5352328,47.3606413 8.5348784,47.3610383 8.5348551,47.3610477 8.5352063 
      ,47.3612503 8.5351944 
     ) 
)' 
      ,4326 -- WGS84 
      ) 
      ,false -- 
    ) 
    -- false: 6379.25032051953 
    -- true: 6350.65051177517 

楕円体では6379.25032051953 m2、回転楕円体では6350.65051177517です。

は今ではJavaScript
で面積を計算してみてくださいだから私は、これらの座標を取るとJS配列にそれらを置く:

var poly = [ 
     [47.3612503, 8.5351944], 
     [47.3612252, 8.5342631], 
     [47.3610145, 8.5342755], 
     [47.3610212, 8.5345227], 
     [47.3606405, 8.5345451], 
     [47.3606350, 8.5343411], 
     [47.3604067, 8.5343545], 
     [47.3604120, 8.5345623], 
     [47.3604308, 8.5352457], 
     [47.3606508, 8.5352328], 
     [47.3606413, 8.5348784], 
     [47.3610383, 8.5348551], 
     [47.3610477, 8.5352063], 
     [47.3612503, 8.5351944] 
    ]; 

および参照としてthis gis postを使用して、JavaScriptで面積を計算してみてください。

Math.radians = function(degrees) 
{ 
    return degrees * Math.PI/180.0; 
}; 


// https://gis.stackexchange.com/a/816/3997 
function polygonArea() 
{ 
    var poly = [ 
     [47.3612503, 8.5351944], 
     [47.3612252, 8.5342631], 
     [47.3610145, 8.5342755], 
     [47.3610212, 8.5345227], 
     [47.3606405, 8.5345451], 
     [47.3606350, 8.5343411], 
     [47.3604067, 8.5343545], 
     [47.3604120, 8.5345623], 
     [47.3604308, 8.5352457], 
     [47.3606508, 8.5352328], 
     [47.3606413, 8.5348784], 
     [47.3610383, 8.5348551], 
     [47.3610477, 8.5352063], 
     [47.3612503, 8.5351944] 
    ]; 


    var area = 0.0; 
    var len = poly.length; 

    if (len > 2) 
    { 

     var p1, p2; 

     for (var i = 0; i < len - 1; i++) 
     { 

      p1 = poly[i]; 
      p2 = poly[i + 1]; 

      area += Math.radians(p2[0] - p1[0]) * 
       (
        2 
        + Math.sin(Math.radians(p1[1])) 
        + Math.sin(Math.radians(p2[1])) 
       ); 
     } 

     // https://en.wikipedia.org/wiki/Earth_radius#Equatorial_radius 
     // https://en.wikipedia.org/wiki/Earth_ellipsoid 
     // The radius you are using, 6378137.0 m corresponds to the equatorial radius of the Earth. 
     var equatorial_radius = 6378137; // m 
     var polar_radius = 6356752.3142; // m 
     var mean_radius = 6371008.8; // m 
     var authalic_radius = 6371007.2; // m (radius of perfect sphere with same surface as reference ellipsoid) 
     var volumetric_radius = 6371000.8 // m (radius of a sphere of volume equal to the ellipsoid) 
     // geodetic latitude φ 
     var siteLatitude = Math.radians(poly[0][0]); 


     // https://en.wikipedia.org/wiki/Semi-major_and_semi-minor_axes 
     // https://en.wikipedia.org/wiki/World_Geodetic_System 
     var a = 6378137; // m 
     var b = 6356752.3142; // m 
     // where a and b are, respectively, the equatorial radius and the polar radius. 

     var R1 = Math.pow(a * a * Math.cos(siteLatitude), 2) + Math.pow(b * b * Math.sin(siteLatitude), 2) 
     var R2 = Math.pow(a * Math.cos(siteLatitude), 2) + Math.pow(b * Math.sin(siteLatitude), 2); 

     // https://en.wikipedia.org/wiki/Earth_radius#Radius_at_a_given_geodetic_latitude 
     // Geocentric radius 
     var R = Math.sqrt(R1/R2); 
     // var merid_radius = ((a * a) * (b * b))/Math.pow(Math.pow(a * Math.cos(siteLatitude), 2) + Math.pow(b * Math.sin(siteLatitude), 2), 3/2) 



     // console.log(R); 
     // var hrad = polar_radius + (90 - Math.abs(siteLatitude))/90 * (equatorial_radius - polar_radius); 
     var radius = mean_radius; 

     area = area * radius * radius/2.0; 
    } // End if len > 0 

    // equatorial_radius: 6391.565558418869 m2 
    // mean_radius:  6377.287126172337m2 
    // authalic_radius: 6377.283923019292 m2 
    // volumetric_radius: 6377.271110415153 m2 
    // merid_radius:  6375.314923754325 m2 
    // polar_radius:  6348.777989748668 m2 
    // R:     6368.48180842528 m2 
    // hrad:    6391.171919886588 m2 

    // http://postgis.net/docs/doxygen/2.2/dc/d52/geography__measurement_8c_a1a7c48d59bcf4ed56522ab26c142f61d.html 
    // ST_Area(false)  6379.25032051953 
    // ST_Area(true)  6350.65051177517 

    // return area; 
    return area.toFixed(2); 
} 

しかし、どの半径を選んでも、私はPostGis出力から少なくとも2平方メートル離れています。

さらに重要なことに、緯度Xの正確な半径を使用して領域を計算すると、私はPostGISの球面結果に近づきますが、回転楕円面の半径を選択すると、PostGisの結果より高い結果を得る。

私は実際になぜこのような異なる結果が得られるのか不思議です。グーグルを使って

私はPostGISのST_Areaははgeography_areaを呼び出し、そして今私はもっと間違っている2つの結果セットのどの思ったんだけど...

は、この計算に何か問題があることが、ここで http://postgis.net/docs/doxygen/2.2/dc/d52/geography__measurement_8c_a1a7c48d59bcf4ed56522ab26c142f61d.html ましたか? それとも、その責任はPostGISに行きますか?私は、SQL-Serverの面積を計算する際

皮肉なことに、私は(実際に6350.65051472187)PostGISの球状の領域を...取得

DECLARE @v_polygon_string varchar(1000); 
DECLARE @g Geography; 
SET @v_polygon_string = 'POLYGON((
47.3612503 8.5351944, 
47.3610477 8.5352063, 
47.3610383 8.5348551, 
47.3606413 8.5348784, 
47.3606508 8.5352328, 
47.3604308 8.5352457, 
47.3604120 8.5345623, 
47.3604067 8.5343545, 
47.3606350 8.5343411, 
47.3606405 8.5345451, 
47.3610212 8.5345227, 
47.3610145 8.5342755, 
47.3612252 8.5342631, 
47.3612503 8.5351944 
)) '; 
SET @g = Geography::STGeomFromText(@v_polygon_string,4326); 
SELECT @g.STArea() 

(ただし、ポリゴンは左手の法則を使用して定義されている場合のみ

参照)そうでない場合、私はSystem.ArgumentException: 24200: The specified input does not represent a valid geography instance.を取得し、[配列がここに逆転されている理由である]:
ST_Area
Source Code

答えて

0

ああ、答えは自分で見つけました。
これは、GoogleマップでWeb-Mercator投影が使用されているためです。

座標はWGS84であり、そこから面積を計算するには、座標を領域保存マッププロジェクションに変換する必要があります。

そうしないと、実際の領域が(地球上のどこに応じて)保存される必要はなくなり、計算領域が実際の領域から広がります。

本当の根本的な質問は次のとおりです。What does ST_Area actually do
そして、この質問に対する答えは、地理空間ライブラリを調べることでわかりました。

は実際6377.28の結果は、円筒等しい面積球(6377.2695087222382)またはEckertIV-球(6377.26664171461)と0.02メートルの精度で適合する。

6350の結果は、(非球形の)円筒形の等面積世界、またはAlbers-Projectionに適合しますが、

Details on the stackexchange-GIS-site

アルバースプロジェクション: ​​

円筒等積プロジェクション: Cylindrical Cylindrical 2

関連する問題