与 ST_DWithin 的奇怪差异 - 地理与几何
Strange difference with ST_DWithin - Geography vs Geometry
(编辑:抱歉。忘了提及。Postgresql 13,PostGIS:3.1 USE_GEOS=1 USE_PROJ=1 USE_STATS=1。抱歉)。
在我看来,以下 2 个查询在这两种情况下都应该 return "true"。
该点显然位于多边形(正方形)内。显示两者肯定表明如此。
我开始想知道我在这里缺少什么基本的东西。
老实说,多年来我一直在围绕这个问题徘徊,因为我一直无法找到“最终”的东西来理解正在发生的事情。在这种情况下,该点有点靠近多边形的边缘,但有时我会遇到完全位于多边形内的点的相同问题。
这两个查询之间的唯一区别是一个使用几何,另一个使用地理。如您所见,我们使用 0.0 作为距离值。这就像一个相交。
OH,顺便说一句,使用相交会产生相同的结果。我对此很困惑。
select
ST_Dwithin(
St_GeometryFromText(
'POLYGON((-95.979486 41.676556,-81.432269 41.676556,-81.432269 30.196043,-95.979486 30.196043,-95.979486 41.676556))', 4326),
ST_GeometryFromText('POINT (-87.70551 30.24481)', 4326),
0
)
select
ST_Dwithin(
St_GeographyFromText(
'POLYGON((-95.979486 41.676556,-81.432269 41.676556,-81.432269 30.196043,-95.979486 30.196043,-95.979486 41.676556))'),
St_GeographyFromText('POINT (-87.70551 30.24481)'),
0
)
编辑。
抱歉,不确定正确的礼仪。在获得好评后,我添加了更多上下文,以防有人觉得有趣。
我正在处理包含国家/地区多边形的“世界”数据集。由于其中一些很大,我选择 st_subdivide 它们。
![st_subdivide 美国] https://imgur.com/IQRz8vg
并且在缩放时我们可以清楚地看到下面答案中解释的内容:
![缩放 st_subdivide 美国] https://imgur.com/fgmpBx0
太棒了,完美的解释,非常感谢。
我知道我不应该用地理,嗯,“不应该”。然而,我还需要在距离和扩展方面做很多工作,而 geom(4326) 对于我找到的单位来说非常烦人。
首先,你需要了解几何学和地理学的区别。
- Geometry,它假定您的所有数据都位于笛卡尔平面上。
- 地理,它假定您的数据由地球表面的点组成。
问题如下。当您投影几何体时,PostGIS 假设几何体的边缘不是平面的(因为地球表面不是平面的)并将它们转换为球面(此过程称为曲面细分)。因此,当您尝试与它们相交时,该点不在多边形内部。
如果地理区域足够小,球面边缘和平面边缘之间的差异可以忽略,但在您的情况下,多边形是一个巨大的多边形。
您将几何图形投影到 EPSG 4326 上,以便将其投影到地球表面,但是尽管该点在平面坐标系中位于正方形内部,但它不在球形坐标系中。
总而言之,您需要了解哪种类型、几何形状或地理位置适用于您的用例。
您可以通过强制边缘为平面来解决此问题(在 PostGIS 的某些实现中作为 BigQuery):
St_GeogFromText(
'POLYGON((-95.979486 41.676556,-81.432269 41.676556,-81.432269 30.196043,-95.979486 30.196043,-95.979486 41.676556))',
planar => True)
除了@sergiomahi 的回答(应该被接受)之外,我还想添加一些示例来使他的观点更清楚。问题不在于类型 geography
本身,而是特征投影到哪个表面。
给定你的多边形和点,如果我们 ST_Distance
使用 geometry
距离为零,因为它将使用笛卡尔平面,但使用 geography
它 returns 16524.35577956
米,因为球形边缘和多边形的大小,正如@sergiomahi 所指出的。因此,它们不再重叠。
WITH j (pol,poi) AS (
VALUES
('SRID=4326;POLYGON((-95.979486 41.676556,-81.432269 41.676556,-81.432269 30.196043,-95.979486 30.196043,-95.979486 41.676556))',
'SRID=4326;POINT (-87.70551 30.24481)')
)
SELECT
ST_Distance(poi::geometry,pol::geometry) AS geom_dist,
ST_Distance(poi::geography,pol::geography) AS geog_dist
FROM j;
geom_dist | geog_dist
-----------+----------------
0 | 16524.35577956
但是,如果您坚持 geometry
并告诉 PostGIS 应该使用球体计算距离,您会得到与 geography
:
类似的结果
WITH j (pol,poi) AS (
VALUES
('SRID=4326;POLYGON((-95.979486 41.676556,-81.432269 41.676556,-81.432269 30.196043,-95.979486 30.196043,-95.979486 41.676556))',
'SRID=4326;POINT(-87.70551 30.24481)'))
SELECT
ST_Distance(poi::geography,pol::geography) AS geog_dist,
ST_DistanceSphere(poi::geometry,pol::geometry) AS geom_dist_sphere
FROM j;
geog_dist | geom_dist_sphere
----------------+------------------
16524.35577956 | 16574.61755546
(1 Zeile)
(编辑:抱歉。忘了提及。Postgresql 13,PostGIS:3.1 USE_GEOS=1 USE_PROJ=1 USE_STATS=1。抱歉)。
在我看来,以下 2 个查询在这两种情况下都应该 return "true"。 该点显然位于多边形(正方形)内。显示两者肯定表明如此。 我开始想知道我在这里缺少什么基本的东西。
老实说,多年来我一直在围绕这个问题徘徊,因为我一直无法找到“最终”的东西来理解正在发生的事情。在这种情况下,该点有点靠近多边形的边缘,但有时我会遇到完全位于多边形内的点的相同问题。
这两个查询之间的唯一区别是一个使用几何,另一个使用地理。如您所见,我们使用 0.0 作为距离值。这就像一个相交。
OH,顺便说一句,使用相交会产生相同的结果。我对此很困惑。
select
ST_Dwithin(
St_GeometryFromText(
'POLYGON((-95.979486 41.676556,-81.432269 41.676556,-81.432269 30.196043,-95.979486 30.196043,-95.979486 41.676556))', 4326),
ST_GeometryFromText('POINT (-87.70551 30.24481)', 4326),
0
)
select
ST_Dwithin(
St_GeographyFromText(
'POLYGON((-95.979486 41.676556,-81.432269 41.676556,-81.432269 30.196043,-95.979486 30.196043,-95.979486 41.676556))'),
St_GeographyFromText('POINT (-87.70551 30.24481)'),
0
)
编辑。 抱歉,不确定正确的礼仪。在获得好评后,我添加了更多上下文,以防有人觉得有趣。
我正在处理包含国家/地区多边形的“世界”数据集。由于其中一些很大,我选择 st_subdivide 它们。
![st_subdivide 美国] https://imgur.com/IQRz8vg
并且在缩放时我们可以清楚地看到下面答案中解释的内容:
![缩放 st_subdivide 美国] https://imgur.com/fgmpBx0
太棒了,完美的解释,非常感谢。
我知道我不应该用地理,嗯,“不应该”。然而,我还需要在距离和扩展方面做很多工作,而 geom(4326) 对于我找到的单位来说非常烦人。
首先,你需要了解几何学和地理学的区别。
- Geometry,它假定您的所有数据都位于笛卡尔平面上。
- 地理,它假定您的数据由地球表面的点组成。
问题如下。当您投影几何体时,PostGIS 假设几何体的边缘不是平面的(因为地球表面不是平面的)并将它们转换为球面(此过程称为曲面细分)。因此,当您尝试与它们相交时,该点不在多边形内部。
如果地理区域足够小,球面边缘和平面边缘之间的差异可以忽略,但在您的情况下,多边形是一个巨大的多边形。
您将几何图形投影到 EPSG 4326 上,以便将其投影到地球表面,但是尽管该点在平面坐标系中位于正方形内部,但它不在球形坐标系中。
总而言之,您需要了解哪种类型、几何形状或地理位置适用于您的用例。
您可以通过强制边缘为平面来解决此问题(在 PostGIS 的某些实现中作为 BigQuery):
St_GeogFromText(
'POLYGON((-95.979486 41.676556,-81.432269 41.676556,-81.432269 30.196043,-95.979486 30.196043,-95.979486 41.676556))',
planar => True)
除了@sergiomahi 的回答(应该被接受)之外,我还想添加一些示例来使他的观点更清楚。问题不在于类型 geography
本身,而是特征投影到哪个表面。
给定你的多边形和点,如果我们 ST_Distance
使用 geometry
距离为零,因为它将使用笛卡尔平面,但使用 geography
它 returns 16524.35577956
米,因为球形边缘和多边形的大小,正如@sergiomahi 所指出的。因此,它们不再重叠。
WITH j (pol,poi) AS (
VALUES
('SRID=4326;POLYGON((-95.979486 41.676556,-81.432269 41.676556,-81.432269 30.196043,-95.979486 30.196043,-95.979486 41.676556))',
'SRID=4326;POINT (-87.70551 30.24481)')
)
SELECT
ST_Distance(poi::geometry,pol::geometry) AS geom_dist,
ST_Distance(poi::geography,pol::geography) AS geog_dist
FROM j;
geom_dist | geog_dist
-----------+----------------
0 | 16524.35577956
但是,如果您坚持 geometry
并告诉 PostGIS 应该使用球体计算距离,您会得到与 geography
:
WITH j (pol,poi) AS (
VALUES
('SRID=4326;POLYGON((-95.979486 41.676556,-81.432269 41.676556,-81.432269 30.196043,-95.979486 30.196043,-95.979486 41.676556))',
'SRID=4326;POINT(-87.70551 30.24481)'))
SELECT
ST_Distance(poi::geography,pol::geography) AS geog_dist,
ST_DistanceSphere(poi::geometry,pol::geometry) AS geom_dist_sphere
FROM j;
geog_dist | geom_dist_sphere
----------------+------------------
16524.35577956 | 16574.61755546
(1 Zeile)