1 /*-------------------------------------------------------------------------
2  *
3  * geo_decls.h - Declarations for various 2D constructs.
4  *
5  *
6  * Portions Copyright (c) 1996-2021, 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
FPeq(double A,double B)47 FPeq(double A, double B)
48 {
49 	return A == B || fabs(A - B) <= EPSILON;
50 }
51 
52 static inline bool
FPne(double A,double B)53 FPne(double A, double B)
54 {
55 	return A != B && fabs(A - B) > EPSILON;
56 }
57 
58 static inline bool
FPlt(double A,double B)59 FPlt(double A, double B)
60 {
61 	return A + EPSILON < B;
62 }
63 
64 static inline bool
FPle(double A,double B)65 FPle(double A, double B)
66 {
67 	return A <= B + EPSILON;
68 }
69 
70 static inline bool
FPgt(double A,double B)71 FPgt(double A, double B)
72 {
73 	return A > B + EPSILON;
74 }
75 
76 static inline bool
FPge(double A,double B)77 FPge(double A, double B)
78 {
79 	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 macros
170  *
171  * Path and Polygon are toastable varlena types, the others are just
172  * fixed-size pass-by-reference types.
173  */
174 
175 #define DatumGetPointP(X)	 ((Point *) DatumGetPointer(X))
176 #define PointPGetDatum(X)	 PointerGetDatum(X)
177 #define PG_GETARG_POINT_P(n) DatumGetPointP(PG_GETARG_DATUM(n))
178 #define PG_RETURN_POINT_P(x) return PointPGetDatum(x)
179 
180 #define DatumGetLsegP(X)	((LSEG *) DatumGetPointer(X))
181 #define LsegPGetDatum(X)	PointerGetDatum(X)
182 #define PG_GETARG_LSEG_P(n) DatumGetLsegP(PG_GETARG_DATUM(n))
183 #define PG_RETURN_LSEG_P(x) return LsegPGetDatum(x)
184 
185 #define DatumGetPathP(X)		 ((PATH *) PG_DETOAST_DATUM(X))
186 #define DatumGetPathPCopy(X)	 ((PATH *) PG_DETOAST_DATUM_COPY(X))
187 #define PathPGetDatum(X)		 PointerGetDatum(X)
188 #define PG_GETARG_PATH_P(n)		 DatumGetPathP(PG_GETARG_DATUM(n))
189 #define PG_GETARG_PATH_P_COPY(n) DatumGetPathPCopy(PG_GETARG_DATUM(n))
190 #define PG_RETURN_PATH_P(x)		 return PathPGetDatum(x)
191 
192 #define DatumGetLineP(X)	((LINE *) DatumGetPointer(X))
193 #define LinePGetDatum(X)	PointerGetDatum(X)
194 #define PG_GETARG_LINE_P(n) DatumGetLineP(PG_GETARG_DATUM(n))
195 #define PG_RETURN_LINE_P(x) return LinePGetDatum(x)
196 
197 #define DatumGetBoxP(X)    ((BOX *) DatumGetPointer(X))
198 #define BoxPGetDatum(X)    PointerGetDatum(X)
199 #define PG_GETARG_BOX_P(n) DatumGetBoxP(PG_GETARG_DATUM(n))
200 #define PG_RETURN_BOX_P(x) return BoxPGetDatum(x)
201 
202 #define DatumGetPolygonP(X)			((POLYGON *) PG_DETOAST_DATUM(X))
203 #define DatumGetPolygonPCopy(X)		((POLYGON *) PG_DETOAST_DATUM_COPY(X))
204 #define PolygonPGetDatum(X)			PointerGetDatum(X)
205 #define PG_GETARG_POLYGON_P(n)		DatumGetPolygonP(PG_GETARG_DATUM(n))
206 #define PG_GETARG_POLYGON_P_COPY(n) DatumGetPolygonPCopy(PG_GETARG_DATUM(n))
207 #define PG_RETURN_POLYGON_P(x)		return PolygonPGetDatum(x)
208 
209 #define DatumGetCircleP(X)	  ((CIRCLE *) DatumGetPointer(X))
210 #define CirclePGetDatum(X)	  PointerGetDatum(X)
211 #define PG_GETARG_CIRCLE_P(n) DatumGetCircleP(PG_GETARG_DATUM(n))
212 #define PG_RETURN_CIRCLE_P(x) return CirclePGetDatum(x)
213 
214 
215 /*
216  * in geo_ops.c
217  */
218 
219 extern float8 pg_hypot(float8 x, float8 y);
220 
221 #endif							/* GEO_DECLS_H */
222