如何在Postgresql上查找与我的包裹相邻的包裹

zf9nrax1  于 2022-12-12  发布在  PostgreSQL
关注(0)|答案(2)|浏览(128)

我的问题是:我有1000个包裹,其中1个是我的,我要做的是找到哪些是我的邻居,这意味着谁的包裹与我的包裹接触。一个完美的例子是在我发给你的图片上显示的。红色矩形是我的包裹,黑色矩形是我的邻居。我要做的是找到他们是谁。我创建了2个表,第一个表(parcels)包含不包含我的所有宗地,第二个表(Myparticle)仅包含我的宗地。作为空间数据,我拥有所有宗地的几何(列geom)和宗地数量。My parcel is red color and neighbourhood parcels are black
我正在尝试解决一个问题,我已经尝试了几天来解决它,但没有结果!所以最终的结果是,我想知道哪些包裹与我的包裹接触。我已经创建了2个表,这是我的代码,这是不工作
从kultura5_maxsip1 k、kultura5_maxsip s中选择st_touches(k.几何体,s.几何体)

tjvv9vkg

tjvv9vkg1#

ST_Touches()可能不会返回太多结果,因为通常几何图形会自然地移动,除非您将它们ST_Snap()在一起,或者应用统一的ST_SnapToGrid()。此外,对“touch”的直观理解在这里是误导性的,因为如果一个形状的结束位置正好是另一个形状的开始位置,ST_Touches()将返回True。如果一个完全在另一个里面,它们也不被认为接触。
阅读DE-9 IM的相关内容或浏览PostGIS文档以了解哪些函数查找哪些类型的空间关系是很好的选择。您可以轻松地测试所有这些函数,使用ST_GeomFromText()构建非常简单的形状,然后使用ST_AsText()QGIS检查它们。Demo

create table my_parcel(
  id serial primary key, 
  geom geometry(POLYGON,--type of shape
                21781   --SRID, Switzerland in this case, coordinates in METERS
               )
  );
--always build an index on the geometry column to speed things up
create index on my_parcel using gist(geom);

insert into my_parcel(geom) values 
(ST_GeomFromText('POLYGON((0 0,1 0,1 1,0 1,0 0))')); --a 1x1 square, north-east of origin

您可以在EPSG.io上阅读有关SRIDs的内容。请务必记住,它们不仅定义了目标区域限制,还定义了测量单位。如果您使用全局4326,然后测量ST_Distance(),它的单位是度,而不是米。如果你使用21781,你不能用一些缓冲区来编码瑞士以外的坐标。也有以英里/英尺为单位的系统。

create table all_parcels(like my_parcel including all);

insert into all_parcels(geom) 
select st_translate(geom,move.x,move.y) --generates a copy moved by an offset
from my_parcel, 
  (values --these offsets define chess king movements, 1 in all directions
  (0,1),  --move up             /north 
  (1,1),  --move right and up   /north-east
  (1,0),  --move right          /east
  (-1,0), --move left           /west
  (-1,-1),--move left down      /south-west
  (0,-1), --move down           /south
  (1,-1)  --move right and down /south-east
  ) as move(x,y);

这些包裹将在ST_Touches()意义上接触,因为它们重复使用相同的、完全圆形的坐标。

select id,st_astext(geom) from all_parcels;
-- id |              st_astext
------+--------------------------------------
--  2 | POLYGON((0 1,1 1,1 2,0 2,0 1))
--  3 | POLYGON((1 1,2 1,2 2,1 2,1 1))
--  4 | POLYGON((1 0,2 0,2 1,1 1,1 0))
--  5 | POLYGON((-1 0,0 0,0 1,-1 1,-1 0))
--  6 | POLYGON((-1 -1,0 -1,0 0,-1 0,-1 -1))
--  7 | POLYGON((0 -1,1 -1,1 0,0 0,0 -1))
--  8 | POLYGON((1 -1,2 -1,2 0,1 0,1 -1))
select b.id
from my_parcel a,
  all_parcels b
where st_touches(a.geom,b.geom);
-- id
------
--  2
--  3
--  4
--  5
--  6
--  7
--  8

现实生活中的数据通常来自于次优条件下容易出错的测量。只要它们移动了一点,就不再“接触”:

create table all_parcels_slightly_shifted(like all_parcels including all);

insert into all_parcels_slightly_shifted 
select 
  id, 
  st_translate(geom, random()/100, random()/100) --random milimeter offset
from all_parcels;
-- id |                                                                                             st_astext                                            
------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--  2 | POLYGON((0.005739247141314 1.002288654993983,1.005739247141314 1.002288654993983,1.005739247141314 2.002288654993983,0.005739247141314 2.002288654993983,0.005739247141314 1.002288654993983))
--  3 | POLYGON((1.005088105236068 1.000882987726616,2.005088105236068 1.000882987726616,2.005088105236068 2.000882987726616,1.005088105236068 2.000882987726616,1.005088105236068 1.000882987726616))
--  4 | POLYGON((1.001129227264427 0.007497058517941,2.001129227264427 0.007497058517941,2.001129227264427 1.007497058517941,1.001129227264427 1.007497058517941,1.001129227264427 0.007497058517941))
--  5 | POLYGON((-0.991909588170889 0.006005249136691,0.008090411829111 0.006005249136691,0.008090411829111 1.006005249136691,-0.991909588170889 1.006005249136691,-0.991909588170889 0.006005249136691))
--  6 | POLYGON((-0.993659995690557 -0.99898573996986,0.006340004309443 -0.99898573996986,0.006340004309443 0.00101426003014,-0.993659995690557 0.00101426003014,-0.993659995690557 -0.99898573996986))
--  7 | POLYGON((0.009123227228849 -0.992001817630975,1.009123227228849 -0.992001817630975,1.009123227228849 0.007998182369025,0.009123227228849 0.007998182369025,0.009123227228849 -0.992001817630975))
--  8 | POLYGON((1.005054414974922 -0.996745585497164,2.005054414974923 -0.996745585497164,2.005054414974923 0.003254414502835,1.005054414974922 0.003254414502835,1.005054414974922 -0.996745585497164))
select b.id 
from my_parcel a, 
  all_parcels_slightly_shifted b 
where st_touches(a.geom,b.geom);
--<nothing>

但是,如果你问现在哪些是相交的(有 * 任何 * 空间关系)或在一定距离内(你会认为足够近,同意他们在口语意义上接触):

select b.id, st_astext(b.geom)
from my_parcel a,
  all_parcels_slightly_shifted b
where st_intersects(a.geom,b.geom);
-- id |                                                                                             st_astext
------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--  5 | POLYGON((-0.991909588170889 0.006005249136691,0.008090411829111 0.006005249136691,0.008090411829111 1.006005249136691,-0.991909588170889 1.006005249136691,-0.991909588170889 0.006005249136691))
--  6 | POLYGON((-0.993659995690557 -0.99898573996986,0.006340004309443 -0.99898573996986,0.006340004309443 0.00101426003014,-0.993659995690557 0.00101426003014,-0.993659995690557 -0.99898573996986))
--  7 | POLYGON((0.009123227228849 -0.992001817630975,1.009123227228849 -0.992001817630975,1.009123227228849 0.007998182369025,0.009123227228849 0.007998182369025,0.009123227228849 -0.992001817630975))
select b.id, st_astext(b.geom)
from my_parcel a,
  all_parcels_slightly_shifted b
where st_dwithin(a.geom,b.geom,0.01);
-- id |                                                                                             st_astext
------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--  2 | POLYGON((0.005739247141314 1.002288654993983,1.005739247141314 1.002288654993983,1.005739247141314 2.002288654993983,0.005739247141314 2.002288654993983,0.005739247141314 1.002288654993983))
--  3 | POLYGON((1.005088105236068 1.000882987726616,2.005088105236068 1.000882987726616,2.005088105236068 2.000882987726616,1.005088105236068 2.000882987726616,1.005088105236068 1.000882987726616))
--  4 | POLYGON((1.001129227264427 0.007497058517941,2.001129227264427 0.007497058517941,2.001129227264427 1.007497058517941,1.001129227264427 1.007497058517941,1.001129227264427 0.007497058517941))
--  5 | POLYGON((-0.991909588170889 0.006005249136691,0.008090411829111 0.006005249136691,0.008090411829111 1.006005249136691,-0.991909588170889 1.006005249136691,-0.991909588170889 0.006005249136691))
--  6 | POLYGON((-0.993659995690557 -0.99898573996986,0.006340004309443 -0.99898573996986,0.006340004309443 0.00101426003014,-0.993659995690557 0.00101426003014,-0.993659995690557 -0.99898573996986))
--  7 | POLYGON((0.009123227228849 -0.992001817630975,1.009123227228849 -0.992001817630975,1.009123227228849 0.007998182369025,0.009123227228849 0.007998182369025,0.009123227228849 -0.992001817630975))
--  8 | POLYGON((1.005054414974922 -0.996745585497164,2.005054414974923 -0.996745585497164,2.005054414974923 0.003254414502835,1.005054414974922 0.003254414502835,1.005054414974922 -0.996745585497164))

你可以阅读Hausdorff distance,它更好地告诉你 * 整个 * 形状之间的距离有多近,而不仅仅是它们之间的最短捷径有多长。ST_DWithin()True,它基于形状之间的最小距离(最短捷径)是否低于限制。

brccelvz

brccelvz2#

您可以尝试在此用例中使用DBScanimplemented in PostGIS)来确定相邻集群。

SELECT *, 
       ST_ClusterDBSCAN(geom, 0, 1) OVER() AS cluster_id 
FROM <your_table>;

cluster_id代表数据列所属的丛集。如果epsilon值为0,函数只会依交集丛集。如果您的多边形不相交,您可以使用较小的值缓冲它们。

相关问题