Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4520ba6

Browse files
committed
Add point <-> polygon distance operator.
Alexander Korotkov, reviewed by Emre Hasegeli.
1 parentee3bec5 commit4520ba6

File tree

6 files changed

+82
-16
lines changed

6 files changed

+82
-16
lines changed

‎src/backend/utils/adt/geo_ops.c

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ static double dist_ps_internal(Point *pt, LSEG *lseg);
7373
staticPoint*line_interpt_internal(LINE*l1,LINE*l2);
7474
staticboollseg_inside_poly(Point*a,Point*b,POLYGON*poly,intstart);
7575
staticPoint*lseg_interpt_internal(LSEG*l1,LSEG*l2);
76+
staticdoubledist_ppoly_internal(Point*pt,POLYGON*poly);
7677

7778

7879
/*
@@ -2415,6 +2416,9 @@ lseg_interpt(PG_FUNCTION_ARGS)
24152416
*Minimum distance from one object to another.
24162417
*-------------------------------------------------------------------*/
24172418

2419+
/*
2420+
* Distance from a point to a line
2421+
*/
24182422
Datum
24192423
dist_pl(PG_FUNCTION_ARGS)
24202424
{
@@ -2431,6 +2435,9 @@ dist_pl_internal(Point *pt, LINE *line)
24312435
HYPOT(line->A,line->B));
24322436
}
24332437

2438+
/*
2439+
* Distance from a point to a lseg
2440+
*/
24342441
Datum
24352442
dist_ps(PG_FUNCTION_ARGS)
24362443
{
@@ -2494,7 +2501,7 @@ dist_ps_internal(Point *pt, LSEG *lseg)
24942501
}
24952502

24962503
/*
2497-
** Distance from a point to a path
2504+
* Distance from a point to a path
24982505
*/
24992506
Datum
25002507
dist_ppath(PG_FUNCTION_ARGS)
@@ -2550,6 +2557,9 @@ dist_ppath(PG_FUNCTION_ARGS)
25502557
PG_RETURN_FLOAT8(result);
25512558
}
25522559

2560+
/*
2561+
* Distance from a point to a box
2562+
*/
25532563
Datum
25542564
dist_pb(PG_FUNCTION_ARGS)
25552565
{
@@ -2566,7 +2576,9 @@ dist_pb(PG_FUNCTION_ARGS)
25662576
PG_RETURN_FLOAT8(result);
25672577
}
25682578

2569-
2579+
/*
2580+
* Distance from a lseg to a line
2581+
*/
25702582
Datum
25712583
dist_sl(PG_FUNCTION_ARGS)
25722584
{
@@ -2589,7 +2601,9 @@ dist_sl(PG_FUNCTION_ARGS)
25892601
PG_RETURN_FLOAT8(result);
25902602
}
25912603

2592-
2604+
/*
2605+
* Distance from a lseg to a box
2606+
*/
25932607
Datum
25942608
dist_sb(PG_FUNCTION_ARGS)
25952609
{
@@ -2608,7 +2622,9 @@ dist_sb(PG_FUNCTION_ARGS)
26082622
PG_RETURN_DATUM(result);
26092623
}
26102624

2611-
2625+
/*
2626+
* Distance from a line to a box
2627+
*/
26122628
Datum
26132629
dist_lb(PG_FUNCTION_ARGS)
26142630
{
@@ -2625,21 +2641,53 @@ dist_lb(PG_FUNCTION_ARGS)
26252641
PG_RETURN_NULL();
26262642
}
26272643

2628-
2644+
/*
2645+
* Distance from a circle to a polygon
2646+
*/
26292647
Datum
26302648
dist_cpoly(PG_FUNCTION_ARGS)
26312649
{
26322650
CIRCLE*circle=PG_GETARG_CIRCLE_P(0);
26332651
POLYGON*poly=PG_GETARG_POLYGON_P(1);
26342652
float8result;
2653+
2654+
/* calculate distance to center, and subtract radius */
2655+
result=dist_ppoly_internal(&circle->center,poly);
2656+
2657+
result-=circle->radius;
2658+
if (result<0)
2659+
result=0;
2660+
2661+
PG_RETURN_FLOAT8(result);
2662+
}
2663+
2664+
/*
2665+
* Distance from a point to a polygon
2666+
*/
2667+
Datum
2668+
dist_ppoly(PG_FUNCTION_ARGS)
2669+
{
2670+
Point*point=PG_GETARG_POINT_P(0);
2671+
POLYGON*poly=PG_GETARG_POLYGON_P(1);
2672+
float8result;
2673+
2674+
result=dist_ppoly_internal(point,poly);
2675+
2676+
PG_RETURN_FLOAT8(result);
2677+
}
2678+
2679+
staticdouble
2680+
dist_ppoly_internal(Point*pt,POLYGON*poly)
2681+
{
2682+
float8result;
26352683
float8d;
26362684
inti;
26372685
LSEGseg;
26382686

2639-
if (point_inside(&(circle->center),poly->npts,poly->p)!=0)
2687+
if (point_inside(pt,poly->npts,poly->p)!=0)
26402688
{
26412689
#ifdefGEODEBUG
2642-
printf("dist_cpoly- center inside of polygon\n");
2690+
printf("dist_ppoly_internal- point inside of polygon\n");
26432691
#endif
26442692
PG_RETURN_FLOAT8(0.0);
26452693
}
@@ -2649,9 +2697,9 @@ dist_cpoly(PG_FUNCTION_ARGS)
26492697
seg.p[0].y=poly->p[0].y;
26502698
seg.p[1].x=poly->p[poly->npts-1].x;
26512699
seg.p[1].y=poly->p[poly->npts-1].y;
2652-
result=dist_ps_internal(&circle->center,&seg);
2700+
result=dist_ps_internal(pt,&seg);
26532701
#ifdefGEODEBUG
2654-
printf("dist_cpoly- segment 0/n distance is %f\n",result);
2702+
printf("dist_ppoly_internal- segment 0/n distance is %f\n",result);
26552703
#endif
26562704

26572705
/* check distances for other segments */
@@ -2661,19 +2709,15 @@ dist_cpoly(PG_FUNCTION_ARGS)
26612709
seg.p[0].y=poly->p[i].y;
26622710
seg.p[1].x=poly->p[i+1].x;
26632711
seg.p[1].y=poly->p[i+1].y;
2664-
d=dist_ps_internal(&circle->center,&seg);
2712+
d=dist_ps_internal(pt,&seg);
26652713
#ifdefGEODEBUG
2666-
printf("dist_cpoly- segment %d distance is %f\n", (i+1),d);
2714+
printf("dist_ppoly_internal- segment %d distance is %f\n", (i+1),d);
26672715
#endif
26682716
if (d<result)
26692717
result=d;
26702718
}
26712719

2672-
result-=circle->radius;
2673-
if (result<0)
2674-
result=0;
2675-
2676-
PG_RETURN_FLOAT8(result);
2720+
returnresult;
26772721
}
26782722

26792723

‎src/include/catalog/pg_operator.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,8 @@ DATA(insert OID = 1521 ( "#" PGNSP PGUID l f f 0604 23 0 0 poly_npo
10161016
DESCR("number of points");
10171017
DATA(insertOID=1522 ("<->"PGNSPPGUIDbff60071870100dist_pc-- ));
10181018
DESCR("distance between");
1019+
DATA(insertOID=3276 ("<->"PGNSPPGUIDbff60060470100dist_ppoly-- ));
1020+
DESCR("distance between");
10191021
DATA(insertOID=1523 ("<->"PGNSPPGUIDbff71860470100dist_cpoly-- ));
10201022
DESCR("distance between");
10211023

‎src/include/catalog/pg_proc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,7 @@ DATA(insert OID = 726 ( dist_lb PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 70
844844
DATA(insert OID = 727 ( dist_sl PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "601 628" _null_ _null_ _null_ _null_dist_sl _null_ _null_ _null_ ));
845845
DATA(insert OID = 728 ( dist_cpoly PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "718 604" _null_ _null_ _null_ _null_dist_cpoly _null_ _null_ _null_ ));
846846
DATA(insert OID = 729 ( poly_distance PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "604 604" _null_ _null_ _null_ _null_poly_distance _null_ _null_ _null_ ));
847+
DATA(insert OID = 3275 ( dist_ppoly PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "600 604" _null_ _null_ _null_ _null_dist_ppoly _null_ _null_ _null_ ));
847848

848849
DATA(insert OID = 740 ( text_lt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "25 25" _null_ _null_ _null_ _null_ text_lt _null_ _null_ _null_ ));
849850
DATA(insert OID = 741 ( text_le PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "25 25" _null_ _null_ _null_ _null_ text_le _null_ _null_ _null_ ));

‎src/include/utils/geo_decls.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ extern Datum circle_radius(PG_FUNCTION_ARGS);
395395
externDatumcircle_distance(PG_FUNCTION_ARGS);
396396
externDatumdist_pc(PG_FUNCTION_ARGS);
397397
externDatumdist_cpoly(PG_FUNCTION_ARGS);
398+
externDatumdist_ppoly(PG_FUNCTION_ARGS);
398399
externDatumcircle_center(PG_FUNCTION_ARGS);
399400
externDatumcr_circle(PG_FUNCTION_ARGS);
400401
externDatumbox_circle(PG_FUNCTION_ARGS);

‎src/test/regress/expected/polygon.out

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,3 +279,14 @@ SELECT '((200,800),(800,800),(800,200),(200,200))' && '(1000,1000,0,0)'::polygo
279279
t
280280
(1 row)
281281

282+
-- distance from a point
283+
SELECT'(0,0)'::point <-> '((0,0),(1,2),(2,1))'::polygon as on_corner,
284+
'(1,1)'::point <-> '((0,0),(2,2),(1,3))'::polygon as on_segment,
285+
'(2,2)'::point <-> '((0,0),(1,4),(3,1))'::polygon as inside,
286+
'(3,3)'::point <-> '((0,2),(2,0),(2,2))'::polygon as near_corner,
287+
'(4,4)'::point <-> '((0,0),(0,3),(4,0))'::polygon as near_segment;
288+
on_corner | on_segment | inside | near_corner | near_segment
289+
-----------+------------+--------+-----------------+--------------
290+
0 | 0 | 0 | 1.4142135623731 | 3.2
291+
(1 row)
292+

‎src/test/regress/sql/polygon.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,10 @@ SELECT '((0,4),(6,4),(1,2),(6,0),(0,0))'::polygon && '((2,1),(2,3),(3,3),(3,1))'
172172
-- +-------+
173173
SELECT'((1,4),(1,1),(4,1),(4,2),(2,2),(2,4),(1,4))'::polygon &&'((3,3),(4,3),(4,4),(3,4),(3,3))'::polygonAS"false";
174174
SELECT'((200,800),(800,800),(800,200),(200,200))' &&'(1000,1000,0,0)'::polygonAS"true";
175+
176+
-- distance from a point
177+
SELECT'(0,0)'::point<->'((0,0),(1,2),(2,1))'::polygonas on_corner,
178+
'(1,1)'::point<->'((0,0),(2,2),(1,3))'::polygonas on_segment,
179+
'(2,2)'::point<->'((0,0),(1,4),(3,1))'::polygonas inside,
180+
'(3,3)'::point<->'((0,2),(2,0),(2,2))'::polygonas near_corner,
181+
'(4,4)'::point<->'((0,0),(0,3),(4,0))'::polygonas near_segment;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp