Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * geo_decls.h - Declarations for various 2D constructs. 4 : * 5 : * 6 : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group 7 : * Portions Copyright (c) 1994, Regents of the University of California 8 : * 9 : * src/include/utils/geo_decls.h 10 : * 11 : * XXX These routines were not written by a numerical analyst. 12 : * 13 : * XXX I have made some attempt to flesh out the operators 14 : * and data types. There are still some more to do. - tgl 97/04/19 15 : * 16 : *------------------------------------------------------------------------- 17 : */ 18 : #ifndef GEO_DECLS_H 19 : #define GEO_DECLS_H 20 : 21 : #include <math.h> 22 : 23 : #include "fmgr.h" 24 : 25 : /*-------------------------------------------------------------------- 26 : * Useful floating point utilities and constants. 27 : *-------------------------------------------------------------------- 28 : * 29 : * "Fuzzy" floating-point comparisons: values within EPSILON of each other 30 : * are considered equal. Beware of normal reasoning about the behavior of 31 : * these comparisons, since for example FPeq does not behave transitively. 32 : * 33 : * Note that these functions are not NaN-aware and will give FALSE for 34 : * any case involving NaN inputs. 35 : * 36 : * Also note that these will give sane answers for infinite inputs, 37 : * where it's important to avoid computing Inf minus Inf; we do so 38 : * by eliminating equality cases before subtracting. 39 : */ 40 : 41 : #define EPSILON 1.0E-06 42 : 43 : #ifdef EPSILON 44 : #define FPzero(A) (fabs(A) <= EPSILON) 45 : 46 : static inline bool 47 18273306 : FPeq(double A, double B) 48 : { 49 18273306 : return A == B || fabs(A - B) <= EPSILON; 50 : } 51 : 52 : static inline bool 53 384 : FPne(double A, double B) 54 : { 55 384 : return A != B && fabs(A - B) > EPSILON; 56 : } 57 : 58 : static inline bool 59 2862878 : FPlt(double A, double B) 60 : { 61 2862878 : return A + EPSILON < B; 62 : } 63 : 64 : static inline bool 65 3182184 : FPle(double A, double B) 66 : { 67 3182184 : return A <= B + EPSILON; 68 : } 69 : 70 : static inline bool 71 31562126 : FPgt(double A, double B) 72 : { 73 31562126 : return A > B + EPSILON; 74 : } 75 : 76 : static inline bool 77 1116512 : FPge(double A, double B) 78 : { 79 1116512 : return A + EPSILON >= B; 80 : } 81 : #else 82 : #define FPzero(A) ((A) == 0) 83 : #define FPeq(A,B) ((A) == (B)) 84 : #define FPne(A,B) ((A) != (B)) 85 : #define FPlt(A,B) ((A) < (B)) 86 : #define FPle(A,B) ((A) <= (B)) 87 : #define FPgt(A,B) ((A) > (B)) 88 : #define FPge(A,B) ((A) >= (B)) 89 : #endif 90 : 91 : 92 : /*--------------------------------------------------------------------- 93 : * Point - (x,y) 94 : *-------------------------------------------------------------------*/ 95 : typedef struct 96 : { 97 : float8 x, 98 : y; 99 : } Point; 100 : 101 : 102 : /*--------------------------------------------------------------------- 103 : * LSEG - A straight line, specified by endpoints. 104 : *-------------------------------------------------------------------*/ 105 : typedef struct 106 : { 107 : Point p[2]; 108 : } LSEG; 109 : 110 : 111 : /*--------------------------------------------------------------------- 112 : * PATH - Specified by vertex points. 113 : *-------------------------------------------------------------------*/ 114 : typedef struct 115 : { 116 : int32 vl_len_; /* varlena header (do not touch directly!) */ 117 : int32 npts; 118 : int32 closed; /* is this a closed polygon? */ 119 : int32 dummy; /* padding to make it double align */ 120 : Point p[FLEXIBLE_ARRAY_MEMBER]; 121 : } PATH; 122 : 123 : 124 : /*--------------------------------------------------------------------- 125 : * LINE - Specified by its general equation (Ax+By+C=0). 126 : *-------------------------------------------------------------------*/ 127 : typedef struct 128 : { 129 : float8 A, 130 : B, 131 : C; 132 : } LINE; 133 : 134 : 135 : /*--------------------------------------------------------------------- 136 : * BOX - Specified by two corner points, which are 137 : * sorted to save calculation time later. 138 : *-------------------------------------------------------------------*/ 139 : typedef struct 140 : { 141 : Point high, 142 : low; /* corner POINTs */ 143 : } BOX; 144 : 145 : /*--------------------------------------------------------------------- 146 : * POLYGON - Specified by an array of doubles defining the points, 147 : * keeping the number of points and the bounding box for 148 : * speed purposes. 149 : *-------------------------------------------------------------------*/ 150 : typedef struct 151 : { 152 : int32 vl_len_; /* varlena header (do not touch directly!) */ 153 : int32 npts; 154 : BOX boundbox; 155 : Point p[FLEXIBLE_ARRAY_MEMBER]; 156 : } POLYGON; 157 : 158 : /*--------------------------------------------------------------------- 159 : * CIRCLE - Specified by a center point and radius. 160 : *-------------------------------------------------------------------*/ 161 : typedef struct 162 : { 163 : Point center; 164 : float8 radius; 165 : } CIRCLE; 166 : 167 : /* 168 : * fmgr interface functions 169 : * 170 : * Path and Polygon are toastable varlena types, the others are just 171 : * fixed-size pass-by-reference types. 172 : */ 173 : 174 : static inline Point * 175 100280236 : DatumGetPointP(Datum X) 176 : { 177 100280236 : return (Point *) DatumGetPointer(X); 178 : } 179 : static inline Datum 180 80658662 : PointPGetDatum(const Point *X) 181 : { 182 80658662 : return PointerGetDatum(X); 183 : } 184 : #define PG_GETARG_POINT_P(n) DatumGetPointP(PG_GETARG_DATUM(n)) 185 : #define PG_RETURN_POINT_P(x) return PointPGetDatum(x) 186 : 187 : static inline LSEG * 188 83002 : DatumGetLsegP(Datum X) 189 : { 190 83002 : return (LSEG *) DatumGetPointer(X); 191 : } 192 : static inline Datum 193 61570 : LsegPGetDatum(const LSEG *X) 194 : { 195 61570 : return PointerGetDatum(X); 196 : } 197 : #define PG_GETARG_LSEG_P(n) DatumGetLsegP(PG_GETARG_DATUM(n)) 198 : #define PG_RETURN_LSEG_P(x) return LsegPGetDatum(x) 199 : 200 : static inline PATH * 201 2847034 : DatumGetPathP(Datum X) 202 : { 203 2847034 : return (PATH *) PG_DETOAST_DATUM(X); 204 : } 205 : static inline PATH * 206 1866 : DatumGetPathPCopy(Datum X) 207 : { 208 1866 : return (PATH *) PG_DETOAST_DATUM_COPY(X); 209 : } 210 : static inline Datum 211 32866 : PathPGetDatum(const PATH *X) 212 : { 213 32866 : return PointerGetDatum(X); 214 : } 215 : #define PG_GETARG_PATH_P(n) DatumGetPathP(PG_GETARG_DATUM(n)) 216 : #define PG_GETARG_PATH_P_COPY(n) DatumGetPathPCopy(PG_GETARG_DATUM(n)) 217 : #define PG_RETURN_PATH_P(x) return PathPGetDatum(x) 218 : 219 : static inline LINE * 220 19408 : DatumGetLineP(Datum X) 221 : { 222 19408 : return (LINE *) DatumGetPointer(X); 223 : } 224 : static inline Datum 225 618 : LinePGetDatum(const LINE *X) 226 : { 227 618 : return PointerGetDatum(X); 228 : } 229 : #define PG_GETARG_LINE_P(n) DatumGetLineP(PG_GETARG_DATUM(n)) 230 : #define PG_RETURN_LINE_P(x) return LinePGetDatum(x) 231 : 232 : static inline BOX * 233 97193474 : DatumGetBoxP(Datum X) 234 : { 235 97193474 : return (BOX *) DatumGetPointer(X); 236 : } 237 : static inline Datum 238 2594454 : BoxPGetDatum(const BOX *X) 239 : { 240 2594454 : return PointerGetDatum(X); 241 : } 242 : #define PG_GETARG_BOX_P(n) DatumGetBoxP(PG_GETARG_DATUM(n)) 243 : #define PG_RETURN_BOX_P(x) return BoxPGetDatum(x) 244 : 245 : static inline POLYGON * 246 875666 : DatumGetPolygonP(Datum X) 247 : { 248 875666 : return (POLYGON *) PG_DETOAST_DATUM(X); 249 : } 250 : static inline POLYGON * 251 : DatumGetPolygonPCopy(Datum X) 252 : { 253 : return (POLYGON *) PG_DETOAST_DATUM_COPY(X); 254 : } 255 : static inline Datum 256 79224 : PolygonPGetDatum(const POLYGON *X) 257 : { 258 79224 : return PointerGetDatum(X); 259 : } 260 : #define PG_GETARG_POLYGON_P(n) DatumGetPolygonP(PG_GETARG_DATUM(n)) 261 : #define PG_GETARG_POLYGON_P_COPY(n) DatumGetPolygonPCopy(PG_GETARG_DATUM(n)) 262 : #define PG_RETURN_POLYGON_P(x) return PolygonPGetDatum(x) 263 : 264 : static inline CIRCLE * 265 343130 : DatumGetCircleP(Datum X) 266 : { 267 343130 : return (CIRCLE *) DatumGetPointer(X); 268 : } 269 : static inline Datum 270 200786 : CirclePGetDatum(const CIRCLE *X) 271 : { 272 200786 : return PointerGetDatum(X); 273 : } 274 : #define PG_GETARG_CIRCLE_P(n) DatumGetCircleP(PG_GETARG_DATUM(n)) 275 : #define PG_RETURN_CIRCLE_P(x) return CirclePGetDatum(x) 276 : 277 : #endif /* GEO_DECLS_H */