88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.58 2001/03/22 03:59:50 momjian Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.59 2001/10/13 17:40:24 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -948,7 +948,7 @@ line_construct_pts(LINE *line, Point *pt1, Point *pt2)
948948}
949949else if (FPeq (pt1 -> y ,pt2 -> y ))
950950{/* horizontal */
951- /* use "x = C" */
951+ /* use "y = C" */
952952line -> A = 0 ;
953953line -> B = -1 ;
954954line -> C = pt1 -> y ;
@@ -1376,6 +1376,9 @@ path_inter(PG_FUNCTION_ARGS)
13761376LSEG seg1 ,
13771377seg2 ;
13781378
1379+ if (p1 -> npts <=0 || p2 -> npts <=0 )
1380+ PG_RETURN_BOOL (false);
1381+
13791382b1 .high .x = b1 .low .x = p1 -> p [0 ].x ;
13801383b1 .high .y = b1 .low .y = p1 -> p [0 ].y ;
13811384for (i = 1 ;i < p1 -> npts ;i ++ )
@@ -1398,12 +1401,34 @@ path_inter(PG_FUNCTION_ARGS)
13981401PG_RETURN_BOOL (false);
13991402
14001403/* pairwise check lseg intersections */
1401- for (i = 0 ;i < p1 -> npts - 1 ;i ++ )
1404+ for (i = 0 ;i < p1 -> npts ;i ++ )
14021405{
1403- for (j = 0 ;j < p2 -> npts - 1 ;j ++ )
1406+ int iprev ;
1407+
1408+ if (i > 0 )
1409+ iprev = i - 1 ;
1410+ else
14041411{
1405- statlseg_construct (& seg1 ,& p1 -> p [i ],& p1 -> p [i + 1 ]);
1406- statlseg_construct (& seg2 ,& p2 -> p [j ],& p2 -> p [j + 1 ]);
1412+ if (!p1 -> closed )
1413+ continue ;
1414+ iprev = p1 -> npts - 1 ;/* include the closure segment */
1415+ }
1416+
1417+ for (j = 0 ;j < p2 -> npts ;j ++ )
1418+ {
1419+ int jprev ;
1420+
1421+ if (j > 0 )
1422+ jprev = j - 1 ;
1423+ else
1424+ {
1425+ if (!p2 -> closed )
1426+ continue ;
1427+ jprev = p2 -> npts - 1 ;/* include the closure segment */
1428+ }
1429+
1430+ statlseg_construct (& seg1 ,& p1 -> p [iprev ],& p1 -> p [i ]);
1431+ statlseg_construct (& seg2 ,& p2 -> p [jprev ],& p2 -> p [j ]);
14071432if (lseg_intersect_internal (& seg1 ,& seg2 ))
14081433PG_RETURN_BOOL (true);
14091434}
@@ -1422,20 +1447,42 @@ path_distance(PG_FUNCTION_ARGS)
14221447{
14231448PATH * p1 = PG_GETARG_PATH_P (0 );
14241449PATH * p2 = PG_GETARG_PATH_P (1 );
1425- bool have_min = false;
14261450float8 min = 0.0 ;/* initialize to keep compiler quiet */
1451+ bool have_min = false;
14271452float8 tmp ;
14281453int i ,
14291454j ;
14301455LSEG seg1 ,
14311456seg2 ;
14321457
1433- for (i = 0 ;i < p1 -> npts - 1 ;i ++ )
1458+ for (i = 0 ;i < p1 -> npts ;i ++ )
14341459{
1435- for (j = 0 ;j < p2 -> npts - 1 ;j ++ )
1460+ int iprev ;
1461+
1462+ if (i > 0 )
1463+ iprev = i - 1 ;
1464+ else
14361465{
1437- statlseg_construct (& seg1 ,& p1 -> p [i ],& p1 -> p [i + 1 ]);
1438- statlseg_construct (& seg2 ,& p2 -> p [j ],& p2 -> p [j + 1 ]);
1466+ if (!p1 -> closed )
1467+ continue ;
1468+ iprev = p1 -> npts - 1 ;/* include the closure segment */
1469+ }
1470+
1471+ for (j = 0 ;j < p2 -> npts ;j ++ )
1472+ {
1473+ int jprev ;
1474+
1475+ if (j > 0 )
1476+ jprev = j - 1 ;
1477+ else
1478+ {
1479+ if (!p2 -> closed )
1480+ continue ;
1481+ jprev = p2 -> npts - 1 ;/* include the closure segment */
1482+ }
1483+
1484+ statlseg_construct (& seg1 ,& p1 -> p [iprev ],& p1 -> p [i ]);
1485+ statlseg_construct (& seg2 ,& p2 -> p [jprev ],& p2 -> p [j ]);
14391486
14401487tmp = DatumGetFloat8 (DirectFunctionCall2 (lseg_distance ,
14411488LsegPGetDatum (& seg1 ),
@@ -1463,12 +1510,24 @@ Datum
14631510path_length (PG_FUNCTION_ARGS )
14641511{
14651512PATH * path = PG_GETARG_PATH_P (0 );
1466- float8 result ;
1513+ float8 result = 0.0 ;
14671514int i ;
14681515
1469- result = 0.0 ;
1470- for (i = 0 ;i < (path -> npts - 1 );i ++ )
1471- result += point_dt (& path -> p [i ],& path -> p [i + 1 ]);
1516+ for (i = 0 ;i < path -> npts ;i ++ )
1517+ {
1518+ int iprev ;
1519+
1520+ if (i > 0 )
1521+ iprev = i - 1 ;
1522+ else
1523+ {
1524+ if (!path -> closed )
1525+ continue ;
1526+ iprev = path -> npts - 1 ;/* include the closure segment */
1527+ }
1528+
1529+ result += point_dt (& path -> p [iprev ],& path -> p [i ]);
1530+ }
14721531
14731532PG_RETURN_FLOAT8 (result );
14741533}
@@ -2133,17 +2192,18 @@ dist_ppath(PG_FUNCTION_ARGS)
21332192Point * pt = PG_GETARG_POINT_P (0 );
21342193PATH * path = PG_GETARG_PATH_P (1 );
21352194float8 result = 0.0 ;/* keep compiler quiet */
2195+ bool have_min = false;
21362196float8 tmp ;
21372197int i ;
21382198LSEG lseg ;
21392199
21402200switch (path -> npts )
21412201{
2142- /* no points in path? then result is undefined... */
21432202case 0 :
2203+ /* no points in path? then result is undefined... */
21442204PG_RETURN_NULL ();
2145- /* one point in path? then get distance between two points... */
21462205case 1 :
2206+ /* one point in path? then get distance between two points... */
21472207result = point_dt (pt ,& path -> p [0 ]);
21482208break ;
21492209default :
@@ -2154,12 +2214,26 @@ dist_ppath(PG_FUNCTION_ARGS)
21542214 * the distance from a point to a path is the smallest
21552215 * distance from the point to any of its constituent segments.
21562216 */
2157- for (i = 0 ;i < path -> npts - 1 ;i ++ )
2217+ for (i = 0 ;i < path -> npts ;i ++ )
21582218{
2159- statlseg_construct (& lseg ,& path -> p [i ],& path -> p [i + 1 ]);
2219+ int iprev ;
2220+
2221+ if (i > 0 )
2222+ iprev = i - 1 ;
2223+ else
2224+ {
2225+ if (!path -> closed )
2226+ continue ;
2227+ iprev = path -> npts - 1 ;/* include the closure segment */
2228+ }
2229+
2230+ statlseg_construct (& lseg ,& path -> p [iprev ],& path -> p [i ]);
21602231tmp = dist_ps_internal (pt ,& lseg );
2161- if (i == 0 || tmp < result )
2232+ if (!have_min || tmp < result )
2233+ {
21622234result = tmp ;
2235+ have_min = true;
2236+ }
21632237}
21642238break ;
21652239}
@@ -2824,8 +2898,6 @@ on_pb(PG_FUNCTION_ARGS)
28242898 *but not cross.
28252899 *(we can do p-in-p in lg(n), but it takes preprocessing)
28262900 */
2827- #define NEXT (A ) (((A)+1) % path->npts)/* cyclic "i+1" */
2828-
28292901Datum
28302902on_ppath (PG_FUNCTION_ARGS )
28312903{