Skip to content

Commit 74514bd

Browse files
committed
geo_ops.c: Clarify comments and function arguments
These functions were not crystal clear about what their respective APIs are. Make an effort to improve that. Emre's patch was correct AFAICT, but I (Álvaro) felt the need to improve a few comments a bit more. Any resulting errors are my own. Per complaint from Coverity, Ning Yu, and Tom Lane. Author: Emre Hasegeli, Álvaro Herrera Reviewed-by: Tomas Vondra, Álvaro Herrera Discussion: https://postgr.es/m/26769.1533090136@sss.pgh.pa.us
1 parent 621a8ac commit 74514bd

File tree

1 file changed

+100
-72
lines changed

1 file changed

+100
-72
lines changed

src/backend/utils/adt/geo_ops.c

Lines changed: 100 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@
33
* geo_ops.c
44
* 2D geometric operations
55
*
6+
* This module implements the geometric functions and operators. The
7+
* geometric types are (from simple to more complicated):
8+
*
9+
* - point
10+
* - line
11+
* - line segment
12+
* - box
13+
* - circle
14+
* - polygon
15+
*
616
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
717
* Portions Copyright (c) 1994, Regents of the University of California
818
*
@@ -25,6 +35,34 @@
2535
#include "utils/fmgrprotos.h"
2636
#include "utils/geo_decls.h"
2737

38+
/*
39+
* * Type constructors have this form:
40+
* void type_construct(Type *result, ...);
41+
*
42+
* * Operators commonly have signatures such as
43+
* void type1_operator_type2(Type *result, Type1 *obj1, Type2 *obj2);
44+
*
45+
* Common operators are:
46+
* * Intersection point:
47+
* bool type1_interpt_type2(Point *result, Type1 *obj1, Type2 *obj2);
48+
* Return whether the two objects intersect. If *result is not NULL,
49+
* it is set to the intersection point.
50+
*
51+
* * Containment:
52+
* bool type1_contain_type2(Type1 *obj1, Type2 *obj2);
53+
* Return whether obj1 contains obj2.
54+
* bool type1_contain_type2(Type1 *contains_obj, Type1 *contained_obj);
55+
* Return whether obj1 contains obj2 (used when types are the same)
56+
*
57+
* * Distance of closest point in or on obj1 to obj2:
58+
* float8 type1_closept_type2(Point *result, Type1 *obj1, Type2 *obj2);
59+
* Returns the shortest distance between two objects. If *result is not
60+
* NULL, it is set to the closest point in or on obj1 to obj2.
61+
*
62+
* These functions may be used to implement multiple SQL-level operators. For
63+
* example, determining whether two lines are parallel is done by checking
64+
* whether they don't intersect.
65+
*/
2866

2967
/*
3068
* Internal routines
@@ -64,7 +102,7 @@ static int lseg_crossing(float8 x, float8 y, float8 px, float8 py);
64102
static bool lseg_contain_point(LSEG *lseg, Point *point);
65103
static float8 lseg_closept_point(Point *result, LSEG *lseg, Point *pt);
66104
static float8 lseg_closept_line(Point *result, LSEG *lseg, LINE *line);
67-
static float8 lseg_closept_lseg(Point *result, LSEG *l1, LSEG *l2);
105+
static float8 lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg);
68106

69107
/* Routines for boxes */
70108
static inline void box_construct(BOX *result, Point *pt1, Point *pt2);
@@ -74,7 +112,7 @@ static float8 box_ar(BOX *box);
74112
static float8 box_ht(BOX *box);
75113
static float8 box_wd(BOX *box);
76114
static bool box_contain_point(BOX *box, Point *point);
77-
static bool box_contain_box(BOX *box1, BOX *box2);
115+
static bool box_contain_box(BOX *contains_box, BOX *contained_box);
78116
static bool box_contain_lseg(BOX *box, LSEG *lseg);
79117
static bool box_interpt_lseg(Point *result, BOX *box, LSEG *lseg);
80118
static float8 box_closept_point(Point *result, BOX *box, Point *point);
@@ -87,7 +125,7 @@ static float8 circle_ar(CIRCLE *circle);
87125
static void make_bound_box(POLYGON *poly);
88126
static void poly_to_circle(CIRCLE *result, POLYGON *poly);
89127
static bool lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start);
90-
static bool poly_contain_poly(POLYGON *polya, POLYGON *polyb);
128+
static bool poly_contain_poly(POLYGON *contains_poly, POLYGON *contained_poly);
91129
static bool plist_same(int npts, Point *p1, Point *p2);
92130
static float8 dist_ppoly_internal(Point *pt, POLYGON *poly);
93131

@@ -648,15 +686,15 @@ box_contain(PG_FUNCTION_ARGS)
648686
}
649687

650688
/*
651-
* Check whether the box is in the box or on its border
689+
* Check whether the second box is in the first box or on its border
652690
*/
653691
static bool
654-
box_contain_box(BOX *box1, BOX *box2)
692+
box_contain_box(BOX *contains_box, BOX *contained_box)
655693
{
656-
return FPge(box1->high.x, box2->high.x) &&
657-
FPle(box1->low.x, box2->low.x) &&
658-
FPge(box1->high.y, box2->high.y) &&
659-
FPle(box1->low.y, box2->low.y);
694+
return FPge(contains_box->high.x, contained_box->high.x) &&
695+
FPle(contains_box->low.x, contained_box->low.x) &&
696+
FPge(contains_box->high.y, contained_box->high.y) &&
697+
FPle(contains_box->low.y, contained_box->low.y);
660698
}
661699

662700

@@ -1223,9 +1261,8 @@ line_interpt(PG_FUNCTION_ARGS)
12231261
/*
12241262
* Internal version of line_interpt
12251263
*
1226-
* This returns true if two lines intersect (they do, if they are not
1227-
* parallel), false if they do not. This also sets the intersection point
1228-
* to *result, if it is not NULL.
1264+
* Return whether two lines intersect. If *result is not NULL, it is set to
1265+
* the intersection point.
12291266
*
12301267
* NOTE: If the lines are identical then we will find they are parallel
12311268
* and report "no intersection". This is a little weird, but since
@@ -2244,10 +2281,9 @@ lseg_center(PG_FUNCTION_ARGS)
22442281

22452282

22462283
/*
2247-
* Find the intersection point of two segments (if any).
2284+
* Return whether the two segments intersect. If *result is not NULL,
2285+
* it is set to the intersection point.
22482286
*
2249-
* This returns true if two line segments intersect, false if they do not.
2250-
* This also sets the intersection point to *result, if it is not NULL.
22512287
* This function is almost perfectly symmetric, even though it doesn't look
22522288
* like it. See lseg_interpt_line() for the other half of it.
22532289
*/
@@ -2507,11 +2543,8 @@ dist_ppoly_internal(Point *pt, POLYGON *poly)
25072543
*-------------------------------------------------------------------*/
25082544

25092545
/*
2510-
* Check if the line segment intersects with the line
2511-
*
2512-
* This returns true if line segment intersects with line, false if they
2513-
* do not. This also sets the intersection point to *result, if it is not
2514-
* NULL.
2546+
* Return whether the line segment intersect with the line. If *result is not
2547+
* NULL, it is set to the intersection point.
25152548
*/
25162549
static bool
25172550
lseg_interpt_line(Point *result, LSEG *lseg, LINE *line)
@@ -2534,21 +2567,20 @@ lseg_interpt_line(Point *result, LSEG *lseg, LINE *line)
25342567
*/
25352568
if (!lseg_contain_point(lseg, &interpt))
25362569
return false;
2537-
2538-
if (result == NULL)
2539-
return true;
2540-
2541-
/*
2542-
* If there is an intersection, then check explicitly for matching
2543-
* endpoints since there may be rounding effects with annoying LSB
2544-
* residue.
2545-
*/
2546-
if (point_eq_point(&lseg->p[0], &interpt))
2547-
*result = lseg->p[0];
2548-
else if (point_eq_point(&lseg->p[1], &interpt))
2549-
*result = lseg->p[1];
2550-
else
2551-
*result = interpt;
2570+
if (result != NULL)
2571+
{
2572+
/*
2573+
* If there is an intersection, then check explicitly for matching
2574+
* endpoints since there may be rounding effects with annoying LSB
2575+
* residue.
2576+
*/
2577+
if (point_eq_point(&lseg->p[0], &interpt))
2578+
*result = lseg->p[0];
2579+
else if (point_eq_point(&lseg->p[1], &interpt))
2580+
*result = lseg->p[1];
2581+
else
2582+
*result = interpt;
2583+
}
25522584

25532585
return true;
25542586
}
@@ -2559,11 +2591,9 @@ lseg_interpt_line(Point *result, LSEG *lseg, LINE *line)
25592591
*-------------------------------------------------------------------*/
25602592

25612593
/*
2562-
* The intersection point of a perpendicular of the line
2563-
* through the point.
2564-
*
2565-
* This sets the closest point to the *result if it is not NULL and returns
2566-
* the distance to the closest point.
2594+
* If *result is not NULL, it is set to the intersection point of a
2595+
* perpendicular of the line through the point. Returns the distance
2596+
* of those two points.
25672597
*/
25682598
static float8
25692599
line_closept_point(Point *result, LINE *line, Point *point)
@@ -2610,8 +2640,8 @@ close_pl(PG_FUNCTION_ARGS)
26102640
/*
26112641
* Closest point on line segment to specified point.
26122642
*
2613-
* This sets the closest point to the *result if it is not NULL and returns
2614-
* the distance to the closest point.
2643+
* If *result is not NULL, set it to the closest point on the line segment
2644+
* to the point. Returns the distance of the two points.
26152645
*/
26162646
static float8
26172647
lseg_closept_point(Point *result, LSEG *lseg, Point *pt)
@@ -2650,27 +2680,24 @@ close_ps(PG_FUNCTION_ARGS)
26502680

26512681
/*
26522682
* Closest point on line segment to line segment
2653-
*
2654-
* This sets the closest point to the *result if it is not NULL and returns
2655-
* the distance to the closest point.
26562683
*/
26572684
static float8
2658-
lseg_closept_lseg(Point *result, LSEG *l1, LSEG *l2)
2685+
lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
26592686
{
26602687
Point point;
26612688
float8 dist,
26622689
d;
26632690

26642691
/* First, we handle the case when the line segments are intersecting. */
2665-
if (lseg_interpt_lseg(result, l1, l2))
2692+
if (lseg_interpt_lseg(result, on_lseg, to_lseg))
26662693
return 0.0;
26672694

26682695
/*
26692696
* Then, we find the closest points from the endpoints of the second
26702697
* line segment, and keep the closest one.
26712698
*/
2672-
dist = lseg_closept_point(result, l1, &l2->p[0]);
2673-
d = lseg_closept_point(&point, l1, &l2->p[1]);
2699+
dist = lseg_closept_point(result, on_lseg, &to_lseg->p[0]);
2700+
d = lseg_closept_point(&point, on_lseg, &to_lseg->p[1]);
26742701
if (float8_lt(d, dist))
26752702
{
26762703
dist = d;
@@ -2679,19 +2706,19 @@ lseg_closept_lseg(Point *result, LSEG *l1, LSEG *l2)
26792706
}
26802707

26812708
/* The closest point can still be one of the endpoints, so we test them. */
2682-
d = lseg_closept_point(NULL, l2, &l1->p[0]);
2709+
d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[0]);
26832710
if (float8_lt(d, dist))
26842711
{
26852712
dist = d;
26862713
if (result != NULL)
2687-
*result = l1->p[0];
2714+
*result = on_lseg->p[0];
26882715
}
2689-
d = lseg_closept_point(NULL, l2, &l1->p[1]);
2716+
d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[1]);
26902717
if (float8_lt(d, dist))
26912718
{
26922719
dist = d;
26932720
if (result != NULL)
2694-
*result = l1->p[1];
2721+
*result = on_lseg->p[1];
26952722
}
26962723

26972724
return dist;
@@ -2719,8 +2746,8 @@ close_lseg(PG_FUNCTION_ARGS)
27192746
/*
27202747
* Closest point on or in box to specified point.
27212748
*
2722-
* This sets the closest point to the *result if it is not NULL and returns
2723-
* the distance to the closest point.
2749+
* If *result is not NULL, set it to the closest point on the box to the
2750+
* given point, and return the distance of the two points.
27242751
*/
27252752
static float8
27262753
box_closept_point(Point *result, BOX *box, Point *pt)
@@ -2837,11 +2864,11 @@ close_sl(PG_FUNCTION_ARGS)
28372864
/*
28382865
* Closest point on line segment to line.
28392866
*
2840-
* This sets the closest point to the *result if it is not NULL and returns
2841-
* the distance to the closest point.
2867+
* Return the distance between the line and the closest point of the line
2868+
* segment to the line. If *result is not NULL, set it to that point.
28422869
*
28432870
* NOTE: When the lines are parallel, endpoints of one of the line segment
2844-
* are FPeq(), in presence of NaN or Infinitive coordinates, or perhaps =
2871+
* are FPeq(), in presence of NaN or Infinite coordinates, or perhaps =
28452872
* even because of simple roundoff issues, there may not be a single closest
28462873
* point. We are likely to set the result to the second endpoint in these
28472874
* cases.
@@ -2896,8 +2923,8 @@ close_ls(PG_FUNCTION_ARGS)
28962923
/*
28972924
* Closest point on or in box to line segment.
28982925
*
2899-
* This sets the closest point to the *result if it is not NULL and returns
2900-
* the distance to the closest point.
2926+
* Returns the distance between the closest point on or in the box to
2927+
* the line segment. If *result is not NULL, it is set to that point.
29012928
*/
29022929
static float8
29032930
box_closept_lseg(Point *result, BOX *box, LSEG *lseg)
@@ -3753,7 +3780,7 @@ touched_lseg_inside_poly(Point *a, Point *b, LSEG *s, POLYGON *poly, int start)
37533780
/*
37543781
* Returns true if segment (a,b) is in polygon, option
37553782
* start is used for optimization - function checks
3756-
* polygon's edges started from start
3783+
* polygon's edges starting from start
37573784
*/
37583785
static bool
37593786
lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start)
@@ -3821,29 +3848,30 @@ lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start)
38213848
return res;
38223849
}
38233850

3824-
/*-----------------------------------------------------------------
3825-
* Determine if polygon A contains polygon B.
3826-
*-----------------------------------------------------------------*/
3851+
/*
3852+
* Check whether the first polygon contains the second
3853+
*/
38273854
static bool
3828-
poly_contain_poly(POLYGON *polya, POLYGON *polyb)
3855+
poly_contain_poly(POLYGON *contains_poly, POLYGON *contained_poly)
38293856
{
38303857
int i;
38313858
LSEG s;
38323859

3833-
Assert(polya->npts > 0 && polyb->npts > 0);
3860+
Assert(contains_poly->npts > 0 && contained_poly->npts > 0);
38343861

38353862
/*
3836-
* Quick check to see if bounding box is contained.
3863+
* Quick check to see if contained's bounding box is contained in
3864+
* contains' bb.
38373865
*/
3838-
if (!box_contain_box(&polya->boundbox, &polyb->boundbox))
3866+
if (!box_contain_box(&contains_poly->boundbox, &contained_poly->boundbox))
38393867
return false;
38403868

3841-
s.p[0] = polyb->p[polyb->npts - 1];
3869+
s.p[0] = contained_poly->p[contained_poly->npts - 1];
38423870

3843-
for (i = 0; i < polyb->npts; i++)
3871+
for (i = 0; i < contained_poly->npts; i++)
38443872
{
3845-
s.p[1] = polyb->p[i];
3846-
if (!lseg_inside_poly(s.p, s.p + 1, polya, 0))
3873+
s.p[1] = contained_poly->p[i];
3874+
if (!lseg_inside_poly(s.p, s.p + 1, contains_poly, 0))
38473875
return false;
38483876
s.p[0] = s.p[1];
38493877
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy