7
7
*
8
8
*
9
9
* IDENTIFICATION
10
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.31 1998/02/26 04:37:08 momjian Exp $
10
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.32 1998/05/09 22:39:55 thomas Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -42,11 +42,6 @@ static double box_wd(BOX *box);
42
42
static double circle_ar (CIRCLE * circle );
43
43
static CIRCLE * circle_copy (CIRCLE * circle );
44
44
static LINE * line_construct_pm (Point * pt , double m );
45
- static bool line_horizontal (LINE * line );
46
- static Point * line_interpt (LINE * l1 , LINE * l2 );
47
- static bool line_intersect (LINE * l1 , LINE * l2 );
48
- static bool line_parallel (LINE * l1 , LINE * l2 );
49
- static bool line_vertical (LINE * line );
50
45
static double lseg_dt (LSEG * l1 , LSEG * l2 );
51
46
static void make_bound_box (POLYGON * poly );
52
47
static PATH * path_copy (PATH * path );
@@ -63,7 +58,6 @@ static char *path_encode(bool closed, int npts, Point *pt);
63
58
static void statlseg_construct (LSEG * lseg , Point * pt1 , Point * pt2 );
64
59
static double box_ar (BOX * box );
65
60
static Point * interpt_sl (LSEG * lseg , LINE * line );
66
- static LINE * line_construct_pp (Point * pt1 , Point * pt2 );
67
61
68
62
69
63
/*
@@ -776,12 +770,105 @@ box_diagonal(BOX *box)
776
770
**
777
771
***********************************************************************/
778
772
773
+ LINE *
774
+ line_in (char * str )
775
+ {
776
+ LINE * line ;
777
+
778
+ #if LINEDEBUG
779
+ LSEG lseg ;
780
+ int isopen ;
781
+ char * s ;
782
+ #endif
783
+
784
+ if (!PointerIsValid (str ))
785
+ elog (ERROR , " Bad (null) line external representation" , NULL );
786
+
787
+ #if LINEDEBUG
788
+ if ((!path_decode (TRUE, 2 , str , & isopen , & s , & (lseg .p [0 ])))
789
+ || (* s != '\0' ))
790
+ elog (ERROR , "Bad line external representation '%s'" , str );
791
+
792
+ line = line_construct_pp (& (lseg .p [0 ]), & (lseg .p [1 ]));
793
+ #else
794
+ elog (ERROR , "line not yet implemented" );
795
+ line = NULL ;
796
+ #endif
797
+
798
+ return (line );
799
+ } /* line_in() */
800
+
801
+
802
+ char *
803
+ line_out (LINE * line )
804
+ {
805
+ char * result ;
806
+
807
+ if (!PointerIsValid (line ))
808
+ return (NULL );
809
+
810
+ #if LINEDEBUG
811
+ if (FPzero (line -> B ))
812
+ { /* vertical */
813
+ /* use "x = C" */
814
+ result -> A = -1 ;
815
+ result -> B = 0 ;
816
+ result -> C = pt1 -> x ;
817
+ #ifdef GEODEBUG
818
+ printf ("line_construct_pp- line is vertical\n" );
819
+ #endif
820
+ #if FALSE
821
+ result -> m = DBL_MAX ;
822
+ #endif
823
+
824
+ }
825
+ else if (FPzero (line -> A ))
826
+ { /* horizontal */
827
+ /* use "x = C" */
828
+ result -> A = 0 ;
829
+ result -> B = -1 ;
830
+ result -> C = pt1 -> y ;
831
+ #ifdef GEODEBUG
832
+ printf ("line_construct_pp- line is horizontal\n" );
833
+ #endif
834
+ #if FALSE
835
+ result -> m = 0.0 ;
836
+ #endif
837
+
838
+ }
839
+ else
840
+ {
841
+ }
842
+
843
+ if (line_horizontal (line ))
844
+ {
845
+ }
846
+ else if (line_vertical (line ))
847
+ {
848
+ }
849
+ else
850
+ {
851
+ }
852
+
853
+ return (path_encode (TRUE, 2 , (Point * ) & (ls -> p [0 ])));
854
+ #else
855
+ elog (ERROR , "line not yet implemented" );
856
+ result = NULL ;
857
+ #endif
858
+
859
+ return (result );
860
+ } /* line_out() */
861
+
862
+
779
863
/*----------------------------------------------------------
780
864
* Conversion routines from one line formula to internal.
781
865
* Internal form: Ax+By+C=0
782
866
*---------------------------------------------------------*/
783
867
784
- static LINE * /* point-slope */
868
+ /* line_construct_pm()
869
+ * point-slope
870
+ */
871
+ LINE *
785
872
line_construct_pm (Point * pt , double m )
786
873
{
787
874
LINE * result = palloc (sizeof (LINE ));
@@ -799,7 +886,10 @@ line_construct_pm(Point *pt, double m)
799
886
} /* line_construct_pm() */
800
887
801
888
802
- static LINE * /* two points */
889
+ /* line_construct_pp()
890
+ * two points
891
+ */
892
+ LINE *
803
893
line_construct_pp (Point * pt1 , Point * pt2 )
804
894
{
805
895
LINE * result = palloc (sizeof (LINE ));
@@ -857,13 +947,13 @@ line_construct_pp(Point *pt1, Point *pt2)
857
947
* Relative position routines.
858
948
*---------------------------------------------------------*/
859
949
860
- static bool
950
+ bool
861
951
line_intersect (LINE * l1 , LINE * l2 )
862
952
{
863
953
return (!line_parallel (l1 , l2 ));
864
954
}
865
955
866
- static bool
956
+ bool
867
957
line_parallel (LINE * l1 , LINE * l2 )
868
958
{
869
959
#if FALSE
@@ -877,7 +967,6 @@ line_parallel(LINE *l1, LINE *l2)
877
967
return (FPeq (l2 -> A , l1 -> A * (l2 -> B / l1 -> B )));
878
968
} /* line_parallel() */
879
969
880
- #ifdef NOT_USED
881
970
bool
882
971
line_perp (LINE * l1 , LINE * l2 )
883
972
{
@@ -899,9 +988,7 @@ line_perp(LINE *l1, LINE *l2)
899
988
return (FPeq (((l1 -> A * l2 -> B ) / (l1 -> B * l2 -> A )), -1.0 ));
900
989
} /* line_perp() */
901
990
902
- #endif
903
-
904
- static bool
991
+ bool
905
992
line_vertical (LINE * line )
906
993
{
907
994
#if FALSE
@@ -910,7 +997,7 @@ line_vertical(LINE *line)
910
997
return (FPzero (line -> B ));
911
998
} /* line_vertical() */
912
999
913
- static bool
1000
+ bool
914
1001
line_horizontal (LINE * line )
915
1002
{
916
1003
#if FALSE
@@ -919,7 +1006,6 @@ line_horizontal(LINE *line)
919
1006
return (FPzero (line -> A ));
920
1007
} /* line_horizontal() */
921
1008
922
- #ifdef NOT_USED
923
1009
bool
924
1010
line_eq (LINE * l1 , LINE * l2 )
925
1011
{
@@ -939,13 +1025,15 @@ line_eq(LINE *l1, LINE *l2)
939
1025
FPeq (l1 -> C , k * l2 -> C ));
940
1026
}
941
1027
942
- #endif
943
1028
944
1029
/*----------------------------------------------------------
945
1030
* Line arithmetic routines.
946
1031
*---------------------------------------------------------*/
947
1032
948
- double * /* distance between l1, l2 */
1033
+ /* line_distance()
1034
+ * Distance between two lines.
1035
+ */
1036
+ double *
949
1037
line_distance (LINE * l1 , LINE * l2 )
950
1038
{
951
1039
double * result = palloc (sizeof (double ));
@@ -970,7 +1058,7 @@ line_distance(LINE *l1, LINE *l2)
970
1058
/* line_interpt()
971
1059
* Point where two lines l1, l2 intersect (if any)
972
1060
*/
973
- static Point *
1061
+ Point *
974
1062
line_interpt (LINE * l1 , LINE * l2 )
975
1063
{
976
1064
Point * result ;
@@ -2266,6 +2354,7 @@ close_pl(Point *pt, LINE *line)
2266
2354
*
2267
2355
* Some tricky code here, relying on boolean expressions
2268
2356
* evaluating to only zero or one to use as an array index.
2357
+ * bug fixes by gthaker@atl.lmco.com; May 1, 98
2269
2358
*/
2270
2359
Point *
2271
2360
close_ps (Point * pt , LSEG * lseg )
@@ -2276,26 +2365,31 @@ close_ps(Point *pt, LSEG *lseg)
2276
2365
int xh ,
2277
2366
yh ;
2278
2367
2368
+
2369
+ /* fprintf(stderr,"close_sp:pt->x %f pt->y %f\nlseg(0).x %f lseg(0).y %f lseg(1).x %f lseg(1).y %f\n", */
2370
+ /* pt->x, pt->y, lseg->p[0].x, lseg->p[0].y, lseg->p[1].x, lseg->p[1].y); */
2371
+
2279
2372
result = NULL ;
2280
2373
xh = lseg -> p [0 ].x < lseg -> p [1 ].x ;
2281
2374
yh = lseg -> p [0 ].y < lseg -> p [1 ].y ;
2282
- if (pt -> x < lseg -> p [!xh ].x )
2283
- result = point_copy (& lseg -> p [!xh ]);
2284
- else if (pt -> x > lseg -> p [xh ].x )
2285
- result = point_copy (& lseg -> p [xh ]);
2286
- else if (pt -> y < lseg -> p [!yh ].y )
2287
- result = point_copy (& lseg -> p [!yh ]);
2288
- else if (pt -> y > lseg -> p [yh ].y )
2289
- result = point_copy (& lseg -> p [yh ]);
2290
- if (result != NULL )
2291
- return (result );
2375
+ /* !xh (or !yh) is the index of lower x( or y) end point of lseg */
2292
2376
2293
2377
/* vertical segment? */
2294
2378
if (lseg_vertical (lseg ))
2295
2379
{
2296
2380
#ifdef GEODEBUG
2297
2381
printf ("close_ps- segment is vertical\n" );
2298
2382
#endif
2383
+ /* first check if point is below or above the entire lseg. */
2384
+ if (pt -> y < lseg -> p [!yh ].y )
2385
+ result = point_copy (& lseg -> p [!yh ]); /* below the lseg */
2386
+ else if (pt -> y > lseg -> p [yh ].y )
2387
+ result = point_copy (& lseg -> p [yh ]); /* above the lseg */
2388
+ if (result != NULL )
2389
+ return (result );
2390
+
2391
+ /* point lines along (to left or right) of the vertical lseg. */
2392
+
2299
2393
result = palloc (sizeof (* result ));
2300
2394
result -> x = lseg -> p [0 ].x ;
2301
2395
result -> y = pt -> y ;
@@ -2306,15 +2400,47 @@ close_ps(Point *pt, LSEG *lseg)
2306
2400
#ifdef GEODEBUG
2307
2401
printf ("close_ps- segment is horizontal\n" );
2308
2402
#endif
2403
+ /* first check if point is left or right of the entire lseg. */
2404
+ if (pt -> x < lseg -> p [!xh ].x )
2405
+ result = point_copy (& lseg -> p [!xh ]); /* left of the lseg */
2406
+ else if (pt -> x > lseg -> p [xh ].x )
2407
+ result = point_copy (& lseg -> p [xh ]); /* right of the lseg */
2408
+ if (result != NULL )
2409
+ return (result );
2410
+
2411
+ /* point lines along (at top or below) the horiz. lseg. */
2309
2412
result = palloc (sizeof (* result ));
2310
2413
result -> x = pt -> x ;
2311
2414
result -> y = lseg -> p [0 ].y ;
2312
2415
return (result );
2313
2416
}
2314
2417
2418
+ /* vert. and horiz. cases are down, now check if the closest
2419
+ * point is one of the end points or someplace on the lseg. */
2420
+
2421
+ /* TODO: Ask if "tmp" should be freed to prevent memory leak */
2422
+
2315
2423
invm = -1.0 / point_sl (& (lseg -> p [0 ]), & (lseg -> p [1 ]));
2424
+ tmp = line_construct_pm (& lseg -> p [!yh ], invm ); /* lower edge of the "band" */
2425
+ if (pt -> y < (tmp -> A * pt -> x + tmp -> C )) { /* we are below the lower edge */
2426
+ result = point_copy (& lseg -> p [!yh ]); /* below the lseg, take lower end pt */
2427
+ /* fprintf(stderr,"below: tmp A %f B %f C %f m %f\n",tmp->A,tmp->B,tmp->C, tmp->m); */
2428
+
2429
+ return result ;
2430
+ }
2431
+ tmp = line_construct_pm (& lseg -> p [yh ], invm ); /* upper edge of the "band" */
2432
+ if (pt -> y > (tmp -> A * pt -> x + tmp -> C )) { /* we are below the lower edge */
2433
+ result = point_copy (& lseg -> p [yh ]); /* above the lseg, take higher end pt */
2434
+ /* fprintf(stderr,"above: tmp A %f B %f C %f m %f\n",tmp->A,tmp->B,tmp->C, tmp->m); */
2435
+ return result ;
2436
+ }
2437
+
2438
+ /* at this point the "normal" from point will hit lseg. The closet point
2439
+ * will be somewhere on the lseg */
2316
2440
tmp = line_construct_pm (pt , invm );
2441
+ /* fprintf(stderr,"tmp A %f B %f C %f m %f\n",tmp->A,tmp->B,tmp->C, tmp->m); */
2317
2442
result = interpt_sl (lseg , tmp );
2443
+ /* fprintf(stderr,"result.x %f result.y %f\n", result->x, result->y); */
2318
2444
return (result );
2319
2445
} /* close_ps() */
2320
2446
@@ -3309,16 +3435,6 @@ box_div(BOX *box, Point *p)
3309
3435
} /* box_div() */
3310
3436
3311
3437
3312
- /***********************************************************************
3313
- **
3314
- ** Routines for 2D lines.
3315
- ** Lines are not intended to be used as ADTs per se,
3316
- ** but their ops are useful tools for other ADT ops. Thus,
3317
- ** there are few relops.
3318
- **
3319
- ***********************************************************************/
3320
-
3321
-
3322
3438
/***********************************************************************
3323
3439
**
3324
3440
** Routines for 2D paths.
@@ -4330,7 +4446,7 @@ box_circle(BOX *box)
4330
4446
} /* box_circle() */
4331
4447
4332
4448
4333
- POLYGON *
4449
+ POLYGON *
4334
4450
circle_poly (int npts , CIRCLE * circle )
4335
4451
{
4336
4452
POLYGON * poly ;
0 commit comments