当点在多边形外部时,ST_Within错误地返回true

时间:2018-10-19 20:42:08

标签: google-bigquery gis postgis

此查询确定点是否在多边形内...

SELECT ST_Within
(
    ST_GeogPoint(69.6, 21.1),
    ST_GeogFromText('POLYGON((67.8 23.4, 69 17, 72.8 16.9, 67.8 23.4))')
)

...在BigQuery中返回TRUE。这是不正确的结果。

相同的查询...

SELECT ST_Within
(
    ST_MakePoint(69.6, 21.1),
    'POLYGON((67.8 23.4, 69 17, 72.8 16.9, 67.8 23.4))'
)

...在PostGIS中返回FALSE。这是正确的结果。

3 个答案:

答案 0 :(得分:7)

此查询为您提供您正在寻找的false答复:

SELECT ST_WITHIN(
  ST_GeogPoint(69.6, 21.1)
  , ST_GeogFromGeoJSON(
    '{"type": "Polygon", "coordinates": [[[67.8, 23.4], [69, 17], [72.8, 16.9], [67.8, 23.4]]]}'
))

有什么区别?

让我们检查一下文档:

  

BigQuery GEOGRAPHY具有球形测地线边缘,而GeoJSON Geometry对象显式具有平面边缘。为了在这两种类型的边缘之间进行转换,BigQuery会在必要时向该行添加其他点,以使所得的边缘序列保持在原始边缘的10米以内。

实际上,在两个系统之间进行转换时,确实发生了非常有趣的细分:

 SELECT ST_GeogFromGeoJSON(
   '{"type": "Polygon", "coordinates": [[[67.8, 23.4], [69, 17], [72.8, 16.9], [67.8, 23.4]]]}'
 )

 POLYGON((67.8 23.4, 67.875 23, 67.95 22.6, 68.025 22.2, 68.1 21.8, 68.175 21.4, 68.25 21, 68.325 20.6, 68.4 20.2, 68.475 19.8, 68.55 19.4, 68.625 19, 68.7 18.6, 68.775 18.2, 68.85 17.8, 68.925 17.4, 69 17, 69.2375 16.99375, 69.475 16.9875, 69.7125 16.98125, 69.95 16.975, 70.1875 16.96875, 70.425 16.9625, 70.6625 16.95625, 70.9 16.95, 71.1375 16.94375, 71.375 16.9375, 71.6125 16.93125, 71.85 16.925, 72.0875 16.91875, 72.325 16.9125, 72.5625 16.90625, 72.8 16.9, 72.64375 17.103125, 72.4875 17.30625, 72.33125 17.509375, 72.175 17.7125, 72.01875 17.915625, 71.8625 18.11875, 71.70625 18.321875, 71.55 18.525, 71.39375 18.728125, 71.2375 18.93125, 71.08125 19.134375, 70.925 19.3375, 70.76875 19.540625, 70.6125 19.74375, 70.45625 19.946875, 70.3 20.15, 70.14375 20.353125, 69.9875 20.55625, 69.83125 20.759375, 69.675 20.9625, 69.51875 21.165625, 69.3625 21.36875, 69.20625 21.571875, 69.05 21.775, 68.89375 21.978125, 68.7375 22.18125, 68.58125 22.384375, 68.425 22.5875, 68.26875 22.790625, 68.1125 22.99375, 67.95625 23.196875, 67.8 23.4))   

顺便说一句,来自Earth Engine文档:

  

在Earth Engine中创建的几何图形是测地线(即,边缘是球体表面上的最短路径)或平面(即,边缘是2D笛卡尔平面中的最短路径)。没有一个平面坐标系适合全局要素集合,因此默认情况下,Earth Engine的几何构造函数会构建测地几何。

enter image description here


现在让我们检查一下PostGIS-它可以与Geometries和Geographies一起使用。

SELECT ST_CoveredBy (
    ST_MakePoint(69.6, 21.1),
    'POLYGON((67.8 23.4, 69 17, 72.8 16.9, 67.8 23.4))'
)    
false

SELECT ST_CoveredBy(
    ST_MakePoint(69.6, 21.1)::geography,
    'POLYGON((67.8 23.4, 69 17, 72.8 16.9, 67.8 23.4))'
)
true

(在此多边形的大陆范围内:您确实想在地理上使用地理-尽管PostGIS的性能会变慢)


返回BigQuery:巴黎到洛杉矶的距离是多少?

SELECT ROUND(ST_Length(line)/1000,2) km
FROM (
  SELECT [
    ST_GeogFromGeoJSON('{"type": "LineString", "coordinates": [[-118.4079, 33.9434], [2.5559, 49.0083]]}')
    , ST_GEOGFROMTEXT('LINESTRING(-118.4079 33.9434, 2.5559 49.0083)')
  ] lines
), UNNEST(lines) line


km
10187.92     
9103.09

enter image description here

我刚刚使用测地线为您节省了1084公里的路程。

答案 1 :(得分:1)

Google BigQuery不在地图上使用平面线,而是BigQuery Geography将其定义为测地线(更多详细信息,请参见“ Coordinate systems and edges”部分)

因此,如果您绘制多边形并指向BigQuery GIS Data Visualization Tool-您将看到该点位于多边形内部

答案 2 :(得分:1)

在Google Earth上绘制图形时,它位于多边形之外。这是同时包含多边形和该点的屏幕截图和kml文件。这是否意味着Google Earth和BigQuery GIS数据可视化工具使用不同的坐标系?

point outside polygon on Google Earth

<?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">
<Folder>
    <name>Temporary Places</name>
    <open>1</open>
    <Document>
        <name>Big Query ST_Within test.kml</name>
        <Style id="prelim">
            <LineStyle>
                <color>ff0000ff</color>
            </LineStyle>
            <PolyStyle>
                <color>4c0000ff</color>
            </PolyStyle>
        </Style>
        <Placemark>
            <name>Big Query ST_Within polygon</name>
            <styleUrl>#prelim</styleUrl>
            <Polygon>
                <tessellate>1</tessellate>
                <outerBoundaryIs>
                    <LinearRing>
                        <coordinates>
                            67.8,23.4,0 69,17,0 72.8,16.9,0 67.8,23.4,0 
                        </coordinates>
                    </LinearRing>
                </outerBoundaryIs>
            </Polygon>
        </Placemark>
    </Document>
    <Placemark>
        <name>Big Query ST_Within point</name>
        <Point>
            <coordinates>69.6,21.1,0</coordinates>
        </Point>
    </Placemark>
</Folder>
</kml>