]> granicus.if.org Git - postgresql/commitdiff
Remove copied comments from geo_ops.c source file and replace with new
authorBruce Momjian <bruce@momjian.us>
Mon, 5 Mar 2007 23:29:14 +0000 (23:29 +0000)
committerBruce Momjian <bruce@momjian.us>
Mon, 5 Mar 2007 23:29:14 +0000 (23:29 +0000)
comments, and cleanup functions.  Remove copyright that is no longer
relevant.

src/backend/utils/adt/geo_ops.c

index 3360c07afc162bb9af6fbe80c138ec808a15c1e3..33a781bb30e2c2d1f3d8b5019968dab9551e8c7d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/geo_ops.c,v 1.95 2007/02/27 23:48:08 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/geo_ops.c,v 1.96 2007/03/05 23:29:14 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -5063,128 +5063,126 @@ poly_circle(PG_FUNCTION_ARGS)
  ***********************************************************************/
 
 /*
- *     Test to see if the point is inside the polygon.
- *     Code adapted from integer-based routines in WN: A Server for the HTTP
+ *     Test to see if the point is inside the polygon, returns 1/0, or 2 if
+ *     the point is on the polygon.
+ *     Code adapted but not copied from integer-based routines in WN: A
+ *     Server for the HTTP
  *     version 1.15.1, file wn/image.c
- *     GPL Copyright (C) 1995 by John Franks
  *     http://hopf.math.northwestern.edu/index.html
  *     Description of algorithm:  http://www.linuxjournal.com/article/2197
+ *                                                        http://www.linuxjournal.com/article/2029
  */
 
-#define HIT_IT INT_MAX
+#define POINT_ON_POLYGON INT_MAX
 
 static int
 point_inside(Point *p, int npts, Point *plist)
 {
        double          x0,
                                y0;
-       double          px,
-                               py;
-       int                     i;
+       double          prev_x,
+                               prev_y;
+       int                     i = 0;
        double          x,
                                y;
-       int                     cross,
-                               crossnum;
-
-/*
- * We calculate crossnum, which is twice the crossing number of a
- * ray from the origin parallel to the positive X axis.
- * A coordinate change is made to move the test point to the origin.
- * Then the function lseg_crossing() is called to calculate the crossnum of
- * one segment of the translated polygon with the ray which is the
- * positive X-axis.
- */
+       int                     cross, total_cross = 0;
 
-       crossnum = 0;
-       i = 0;
        if (npts <= 0)
                return 0;
 
+       /* compute first polygon point relative to single point */
        x0 = plist[0].x - p->x;
        y0 = plist[0].y - p->y;
 
-       px = x0;
-       py = y0;
+       prev_x = x0;
+       prev_y = y0;
+       /* loop over polygon points and aggregate total_cross */
        for (i = 1; i < npts; i++)
        {
+               /* compute next polygon point relative to single point */
                x = plist[i].x - p->x;
                y = plist[i].y - p->y;
 
-               if ((cross = lseg_crossing(x, y, px, py)) == HIT_IT)
+               /* compute previous to current point crossing */
+               if ((cross = lseg_crossing(x, y, prev_x, prev_y)) == POINT_ON_POLYGON)
                        return 2;
-               crossnum += cross;
-
-               px = x;
-               py = y;
+               total_cross += cross;
+               
+               prev_x = x;
+               prev_y = y;
        }
-       if ((cross = lseg_crossing(x0, y0, px, py)) == HIT_IT)
+
+       /* now do the first point */
+       if ((cross = lseg_crossing(x0, y0, prev_x, prev_y)) == POINT_ON_POLYGON)
                return 2;
-       crossnum += cross;
-       if (crossnum != 0)
+       total_cross += cross;
+
+       if (total_cross != 0)
                return 1;
        return 0;
 }
 
 
 /* lseg_crossing()
- * The function lseg_crossing() returns +2, or -2 if the segment from (x,y)
- * to previous (x,y) crosses the positive X-axis positively or negatively.
- * It returns +1 or -1 if one endpoint is on this ray, or 0 if both are.
- * It returns 0 if the ray and the segment don't intersect.
- * It returns HIT_IT if the segment contains (0,0)
+ * Returns +/-2 if line segment crosses the positive X-axis in a +/- direction.
+ * Returns +/-1 if one point is on the positive X-axis.
+ * Returns 0 if both points are on the positive X-axis, or there is no crossing.
+ * Returns POINT_ON_POLYGON if the segment contains (0,0).
+ * Wow, that is one confusing API, but it is used above, and when summed,
+ * can tell is if a point is in a polygon.
  */
 
 static int
-lseg_crossing(double x, double y, double px, double py)
+lseg_crossing(double x, double y, double prev_x, double prev_y)
 {
        double          z;
-       int                     sgn;
-
-       /* If (px,py) = (0,0) and not first call we have already sent HIT_IT */
+       int                     y_sign;
 
        if (FPzero(y))
-       {
-               if (FPzero(x))
-               {
-                       return HIT_IT;
-
-               }
+       {       /* y == 0, on X axis */
+               if (FPzero(x))  /* (x,y) is (0,0)? */
+                       return POINT_ON_POLYGON;
                else if (FPgt(x, 0))
-               {
-                       if (FPzero(py))
-                               return FPgt(px, 0) ? 0 : HIT_IT;
-                       return FPlt(py, 0) ? 1 : -1;
-
+               {       /* x > 0 */
+                       if (FPzero(prev_y))     /* y and prev_y are zero */
+                               /* prev_x > 0? */
+                               return FPgt(prev_x, 0) ? 0 : POINT_ON_POLYGON;
+                       return FPlt(prev_y, 0) ? 1 : -1;
                }
                else
-               {                                               /* x < 0 */
-                       if (FPzero(py))
-                               return FPlt(px, 0) ? 0 : HIT_IT;
+               {       /* x < 0, x not on positive X axis */
+                       if (FPzero(prev_y))
+                               /* prev_x < 0? */
+                               return FPlt(prev_x, 0) ? 0 : POINT_ON_POLYGON;
                        return 0;
                }
        }
-
-       /* Now we know y != 0;  set sgn to sign of y */
-       sgn = (FPgt(y, 0) ? 1 : -1);
-       if (FPzero(py))
-               return FPlt(px, 0) ? 0 : sgn;
-
-       if (FPgt((sgn * py), 0))
-       {                                                       /* y and py have same sign */
-               return 0;
-
-       }
        else
-       {                                                       /* y and py have opposite signs */
-               if (FPge(x, 0) && FPgt(px, 0))
-                       return 2 * sgn;
-               if (FPlt(x, 0) && FPle(px, 0))
-                       return 0;
-
-               z = (x - px) * y - (y - py) * x;
-               if (FPzero(z))
-                       return HIT_IT;
-               return FPgt((sgn * z), 0) ? 0 : 2 * sgn;
+       {       /* y != 0 */
+               /* compute y crossing direction from previous point */
+               y_sign = FPgt(y, 0) ? 1 : -1;
+
+               if (FPzero(prev_y))
+                       /* previous point was on X axis, so new point is either off or on */
+                       return FPlt(prev_x, 0) ? 0 : y_sign;
+               else if (FPgt(y_sign * prev_y, 0))
+                       /* both above or below X axis */
+                       return 0;       /* same sign */
+               else
+               {       /* y and prev_y cross X-axis */
+                       if (FPge(x, 0) && FPgt(prev_x, 0))
+                               /* both non-negative so cross positive X-axis */
+                               return 2 * y_sign;
+                       if (FPlt(x, 0) && FPle(prev_x, 0))
+                               /* both non-positive so do not cross positive X-axis */
+                               return 0;
+
+                       /* x and y cross axises, see URL above point_inside() */
+                       z = (x - prev_x) * y - (y - prev_y) * x;
+                       if (FPzero(z))
+                               return POINT_ON_POLYGON;
+                       return FPgt((y_sign * z), 0) ? 0 : 2 * y_sign;
+               }
        }
 }