Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * geo_decls.h - Declarations for various 2D constructs. 4 : * 5 : * 6 : * Portions Copyright (c) 1996-2024, 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 18331908 : FPeq(double A, double B) 48 : { 49 18331908 : 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 2952388 : FPlt(double A, double B) 60 : { 61 2952388 : 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 36200950 : FPgt(double A, double B) 72 : { 73 36200950 : 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 : #define HYPOT(A, B) pg_hypot(A, B) 92 : 93 : /*--------------------------------------------------------------------- 94 : * Point - (x,y) 95 : *-------------------------------------------------------------------*/ 96 : typedef struct 97 : { 98 : float8 x, 99 : y; 100 : } Point; 101 : 102 : 103 : /*--------------------------------------------------------------------- 104 : * LSEG - A straight line, specified by endpoints. 105 : *-------------------------------------------------------------------*/ 106 : typedef struct 107 : { 108 : Point p[2]; 109 : } LSEG; 110 : 111 : 112 : /*--------------------------------------------------------------------- 113 : * PATH - Specified by vertex points. 114 : *-------------------------------------------------------------------*/ 115 : typedef struct 116 : { 117 : int32 vl_len_; /* varlena header (do not touch directly!) */ 118 : int32 npts; 119 : int32 closed; /* is this a closed polygon? */ 120 : int32 dummy; /* padding to make it double align */ 121 : Point p[FLEXIBLE_ARRAY_MEMBER]; 122 : } PATH; 123 : 124 : 125 : /*--------------------------------------------------------------------- 126 : * LINE - Specified by its general equation (Ax+By+C=0). 127 : *-------------------------------------------------------------------*/ 128 : typedef struct 129 : { 130 : float8 A, 131 : B, 132 : C; 133 : } LINE; 134 : 135 : 136 : /*--------------------------------------------------------------------- 137 : * BOX - Specified by two corner points, which are 138 : * sorted to save calculation time later. 139 : *-------------------------------------------------------------------*/ 140 : typedef struct 141 : { 142 : Point high, 143 : low; /* corner POINTs */ 144 : } BOX; 145 : 146 : /*--------------------------------------------------------------------- 147 : * POLYGON - Specified by an array of doubles defining the points, 148 : * keeping the number of points and the bounding box for 149 : * speed purposes. 150 : *-------------------------------------------------------------------*/ 151 : typedef struct 152 : { 153 : int32 vl_len_; /* varlena header (do not touch directly!) */ 154 : int32 npts; 155 : BOX boundbox; 156 : Point p[FLEXIBLE_ARRAY_MEMBER]; 157 : } POLYGON; 158 : 159 : /*--------------------------------------------------------------------- 160 : * CIRCLE - Specified by a center point and radius. 161 : *-------------------------------------------------------------------*/ 162 : typedef struct 163 : { 164 : Point center; 165 : float8 radius; 166 : } CIRCLE; 167 : 168 : /* 169 : * fmgr interface functions 170 : * 171 : * Path and Polygon are toastable varlena types, the others are just 172 : * fixed-size pass-by-reference types. 173 : */ 174 : 175 : static inline Point * 176 114510382 : DatumGetPointP(Datum X) 177 : { 178 114510382 : return (Point *) DatumGetPointer(X); 179 : } 180 : static inline Datum 181 92547206 : PointPGetDatum(const Point *X) 182 : { 183 92547206 : return PointerGetDatum(X); 184 : } 185 : #define PG_GETARG_POINT_P(n) DatumGetPointP(PG_GETARG_DATUM(n)) 186 : #define PG_RETURN_POINT_P(x) return PointPGetDatum(x) 187 : 188 : static inline LSEG * 189 83002 : DatumGetLsegP(Datum X) 190 : { 191 83002 : return (LSEG *) DatumGetPointer(X); 192 : } 193 : static inline Datum 194 61570 : LsegPGetDatum(const LSEG *X) 195 : { 196 61570 : return PointerGetDatum(X); 197 : } 198 : #define PG_GETARG_LSEG_P(n) DatumGetLsegP(PG_GETARG_DATUM(n)) 199 : #define PG_RETURN_LSEG_P(x) return LsegPGetDatum(x) 200 : 201 : static inline PATH * 202 2847034 : DatumGetPathP(Datum X) 203 : { 204 2847034 : return (PATH *) PG_DETOAST_DATUM(X); 205 : } 206 : static inline PATH * 207 1866 : DatumGetPathPCopy(Datum X) 208 : { 209 1866 : return (PATH *) PG_DETOAST_DATUM_COPY(X); 210 : } 211 : static inline Datum 212 32866 : PathPGetDatum(const PATH *X) 213 : { 214 32866 : return PointerGetDatum(X); 215 : } 216 : #define PG_GETARG_PATH_P(n) DatumGetPathP(PG_GETARG_DATUM(n)) 217 : #define PG_GETARG_PATH_P_COPY(n) DatumGetPathPCopy(PG_GETARG_DATUM(n)) 218 : #define PG_RETURN_PATH_P(x) return PathPGetDatum(x) 219 : 220 : static inline LINE * 221 19408 : DatumGetLineP(Datum X) 222 : { 223 19408 : return (LINE *) DatumGetPointer(X); 224 : } 225 : static inline Datum 226 618 : LinePGetDatum(const LINE *X) 227 : { 228 618 : return PointerGetDatum(X); 229 : } 230 : #define PG_GETARG_LINE_P(n) DatumGetLineP(PG_GETARG_DATUM(n)) 231 : #define PG_RETURN_LINE_P(x) return LinePGetDatum(x) 232 : 233 : static inline BOX * 234 97170994 : DatumGetBoxP(Datum X) 235 : { 236 97170994 : return (BOX *) DatumGetPointer(X); 237 : } 238 : static inline Datum 239 2595070 : BoxPGetDatum(const BOX *X) 240 : { 241 2595070 : return PointerGetDatum(X); 242 : } 243 : #define PG_GETARG_BOX_P(n) DatumGetBoxP(PG_GETARG_DATUM(n)) 244 : #define PG_RETURN_BOX_P(x) return BoxPGetDatum(x) 245 : 246 : static inline POLYGON * 247 875664 : DatumGetPolygonP(Datum X) 248 : { 249 875664 : return (POLYGON *) PG_DETOAST_DATUM(X); 250 : } 251 : static inline POLYGON * 252 : DatumGetPolygonPCopy(Datum X) 253 : { 254 : return (POLYGON *) PG_DETOAST_DATUM_COPY(X); 255 : } 256 : static inline Datum 257 79224 : PolygonPGetDatum(const POLYGON *X) 258 : { 259 79224 : return PointerGetDatum(X); 260 : } 261 : #define PG_GETARG_POLYGON_P(n) DatumGetPolygonP(PG_GETARG_DATUM(n)) 262 : #define PG_GETARG_POLYGON_P_COPY(n) DatumGetPolygonPCopy(PG_GETARG_DATUM(n)) 263 : #define PG_RETURN_POLYGON_P(x) return PolygonPGetDatum(x) 264 : 265 : static inline CIRCLE * 266 343130 : DatumGetCircleP(Datum X) 267 : { 268 343130 : return (CIRCLE *) DatumGetPointer(X); 269 : } 270 : static inline Datum 271 200786 : CirclePGetDatum(const CIRCLE *X) 272 : { 273 200786 : return PointerGetDatum(X); 274 : } 275 : #define PG_GETARG_CIRCLE_P(n) DatumGetCircleP(PG_GETARG_DATUM(n)) 276 : #define PG_RETURN_CIRCLE_P(x) return CirclePGetDatum(x) 277 : 278 : 279 : /* 280 : * in geo_ops.c 281 : */ 282 : 283 : extern float8 pg_hypot(float8 x, float8 y); 284 : 285 : #endif /* GEO_DECLS_H */