PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
lwgeom_box3d.c
Go to the documentation of this file.
1/**********************************************************************
2 *
3 * PostGIS - Spatial Types for PostgreSQL
4 * http://postgis.net
5 *
6 * PostGIS is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * PostGIS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18 *
19 **********************************************************************
20 *
21 * Copyright 2009 Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
22 * Copyright 2009-2017 Paul Ramsey <pramsey@cleverelephant.ca>
23 * Copyright 2018 Darafei Praliaskouski <me@komzpa.net>
24 *
25 **********************************************************************/
26
27#include "postgres.h"
28#include "fmgr.h"
29#include "utils/elog.h"
30#include "utils/geo_decls.h"
32
33#include "../postgis_config.h"
34#include "lwgeom_pg.h"
35#include "liblwgeom.h"
36#include "liblwgeom_internal.h"
37#include "lwgeom_box3d.h"
38
39#include <math.h>
40#include <float.h>
41#include <string.h>
42#include <stdio.h>
43
44
55Datum BOX3D_in(PG_FUNCTION_ARGS)
56{
57 char *str = PG_GETARG_CSTRING(0);
58 int nitems;
59 BOX3D *box = (BOX3D *)palloc(sizeof(BOX3D));
60 box->zmin = 0;
61 box->zmax = 0;
62
63 if (strstr(str, "BOX3D(") != str)
64 {
65 pfree(box);
66 elog(ERROR, "BOX3D parser - doesn't start with BOX3D(");
67 PG_RETURN_NULL();
68 }
69
70 nitems = sscanf(str,
71 "BOX3D(%le %le %le ,%le %le %le)",
72 &box->xmin,
73 &box->ymin,
74 &box->zmin,
75 &box->xmax,
76 &box->ymax,
77 &box->zmax);
78 if (nitems != 6)
79 {
80 nitems = sscanf(str, "BOX3D(%le %le ,%le %le)", &box->xmin, &box->ymin, &box->xmax, &box->ymax);
81 if (nitems != 4)
82 {
83 pfree(box);
84 elog(
85 ERROR,
86 "BOX3D parser - couldn't parse. It should look like: BOX3D(xmin ymin zmin,xmax ymax zmax) or BOX3D(xmin ymin,xmax ymax)");
87 PG_RETURN_NULL();
88 }
89 }
90
91 if (box->xmin > box->xmax)
92 {
93 float tmp = box->xmin;
94 box->xmin = box->xmax;
95 box->xmax = tmp;
96 }
97 if (box->ymin > box->ymax)
98 {
99 float tmp = box->ymin;
100 box->ymin = box->ymax;
101 box->ymax = tmp;
102 }
103 if (box->zmin > box->zmax)
104 {
105 float tmp = box->zmin;
106 box->zmin = box->zmax;
107 box->zmax = tmp;
108 }
109 box->srid = SRID_UNKNOWN;
110 PG_RETURN_POINTER(box);
111}
112
120Datum BOX3D_out(PG_FUNCTION_ARGS)
121{
122 BOX3D *bbox = (BOX3D *)PG_GETARG_POINTER(0);
123 static const int precision = 15;
124 static int size = OUT_MAX_BYTES_DOUBLE * 6 + 5 + 2 + 4 + 5 + 1; /* double * 6 + "BOX3D"+ "()" + commas + null */
125 int i = 0;
126 char *result;
127
128 if (bbox == NULL)
129 {
130 result = palloc(5);
131 strcat(result, "NULL");
132 PG_RETURN_CSTRING(result);
133 }
134
135 result = (char *)palloc(size);
136 result[i++] = 'B';
137 result[i++] = 'O';
138 result[i++] = 'X';
139 result[i++] = '3';
140 result[i++] = 'D';
141 result[i++] = '(';
142 i += lwprint_double(bbox->xmin, precision, &result[i]);
143 result[i++] = ' ';
144 i += lwprint_double(bbox->ymin, precision, &result[i]);
145 result[i++] = ' ';
146 i += lwprint_double(bbox->zmin, precision, &result[i]);
147 result[i++] = ',';
148 i += lwprint_double(bbox->xmax, precision, &result[i]);
149 result[i++] = ' ';
150 i += lwprint_double(bbox->ymax, precision, &result[i]);
151 result[i++] = ' ';
152 i += lwprint_double(bbox->zmax, precision, &result[i]);
153 result[i++] = ')';
154 result[i++] = '\0';
155
156 PG_RETURN_CSTRING(result);
157}
158
160Datum BOX3D_to_BOX2D(PG_FUNCTION_ARGS)
161{
162 BOX3D *in = (BOX3D *)PG_GETARG_POINTER(0);
163 GBOX *out = box3d_to_gbox(in);
164 PG_RETURN_POINTER(out);
165}
166
167static void
168box3d_to_box_p(BOX3D *box, BOX *out)
169{
170 if (!box)
171 return;
172
173 out->low.x = box->xmin;
174 out->low.y = box->ymin;
175
176 out->high.x = box->xmax;
177 out->high.y = box->ymax;
178}
179
181Datum BOX3D_to_BOX(PG_FUNCTION_ARGS)
182{
183 BOX3D *in = (BOX3D *)PG_GETARG_POINTER(0);
184 BOX *box = palloc(sizeof(BOX));
185
186 box3d_to_box_p(in, box);
187 PG_RETURN_POINTER(box);
188}
189
191Datum BOX3D_to_LWGEOM(PG_FUNCTION_ARGS)
192{
193 BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
194 POINTARRAY *pa;
196 POINT4D pt;
197
211
212 /* BOX3D is a point */
213 if ((box->xmin == box->xmax) && (box->ymin == box->ymax) && (box->zmin == box->zmax))
214 {
215 LWPOINT *lwpt = lwpoint_construct(SRID_UNKNOWN, NULL, pa);
216
217 pt.x = box->xmin;
218 pt.y = box->ymin;
219 pt.z = box->zmin;
221
222 result = geometry_serialize(lwpoint_as_lwgeom(lwpt));
223 lwpoint_free(lwpt);
224 }
225 /* BOX3D is a line */
226 else if (((box->xmin == box->xmax || box->ymin == box->ymax) && box->zmin == box->zmax) ||
227 ((box->xmin == box->xmax || box->zmin == box->zmax) && box->ymin == box->ymax) ||
228 ((box->ymin == box->ymax || box->zmin == box->zmax) && box->xmin == box->xmax))
229 {
230 LWLINE *lwline = lwline_construct(SRID_UNKNOWN, NULL, pa);
231
232 pt.x = box->xmin;
233 pt.y = box->ymin;
234 pt.z = box->zmin;
236 pt.x = box->xmax;
237 pt.y = box->ymax;
238 pt.z = box->zmax;
240
241 result = geometry_serialize(lwline_as_lwgeom(lwline));
242 lwline_free(lwline);
243 }
244 /* BOX3D is a polygon in the X plane */
245 else if (box->xmin == box->xmax)
246 {
247 POINT4D points[4];
248 LWPOLY *lwpoly;
249
250 /* Initialize the 4 vertices of the polygon */
251 points[0] = (POINT4D){box->xmin, box->ymin, box->zmin, 0.0};
252 points[1] = (POINT4D){box->xmin, box->ymax, box->zmin, 0.0};
253 points[2] = (POINT4D){box->xmin, box->ymax, box->zmax, 0.0};
254 points[3] = (POINT4D){box->xmin, box->ymin, box->zmax, 0.0};
255
256 lwpoly = lwpoly_construct_rectangle(LW_TRUE, LW_FALSE, &points[0], &points[1], &points[2], &points[3]);
257 result = geometry_serialize(lwpoly_as_lwgeom(lwpoly));
258 lwpoly_free(lwpoly);
259 }
260 /* BOX3D is a polygon in the Y plane */
261 else if (box->ymin == box->ymax)
262 {
263 POINT4D points[4];
264 LWPOLY *lwpoly;
265
266 /* Initialize the 4 vertices of the polygon */
267 points[0] = (POINT4D){box->xmin, box->ymin, box->zmin, 0.0};
268 points[1] = (POINT4D){box->xmax, box->ymin, box->zmin, 0.0};
269 points[2] = (POINT4D){box->xmax, box->ymin, box->zmax, 0.0};
270 points[3] = (POINT4D){box->xmin, box->ymin, box->zmax, 0.0};
271
272 lwpoly = lwpoly_construct_rectangle(LW_TRUE, LW_FALSE, &points[0], &points[1], &points[2], &points[3]);
273 result = geometry_serialize(lwpoly_as_lwgeom(lwpoly));
274 lwpoly_free(lwpoly);
275 }
276 /* BOX3D is a polygon in the Z plane */
277 else if (box->zmin == box->zmax)
278 {
279 POINT4D points[4];
280 LWPOLY *lwpoly;
281
282 /* Initialize the 4 vertices of the polygon */
283 points[0] = (POINT4D){box->xmin, box->ymin, box->zmin, 0.0};
284 points[1] = (POINT4D){box->xmin, box->ymax, box->zmin, 0.0};
285 points[2] = (POINT4D){box->xmax, box->ymax, box->zmin, 0.0};
286 points[3] = (POINT4D){box->xmax, box->ymin, box->zmin, 0.0};
287
288 lwpoly = lwpoly_construct_rectangle(LW_TRUE, LW_FALSE, &points[0], &points[1], &points[2], &points[3]);
289 result = geometry_serialize(lwpoly_as_lwgeom(lwpoly));
290 lwpoly_free(lwpoly);
291 }
292 /* BOX3D is a polyhedron */
293 else
294 {
295 POINT4D points[8];
296 static const int ngeoms = 6;
297 LWGEOM **geoms = (LWGEOM **)lwalloc(sizeof(LWGEOM *) * ngeoms);
298 LWGEOM *geom = NULL;
299
300 /* Initialize the 8 vertices of the box */
301 points[0] = (POINT4D){box->xmin, box->ymin, box->zmin, 0.0};
302 points[1] = (POINT4D){box->xmin, box->ymax, box->zmin, 0.0};
303 points[2] = (POINT4D){box->xmax, box->ymax, box->zmin, 0.0};
304 points[3] = (POINT4D){box->xmax, box->ymin, box->zmin, 0.0};
305 points[4] = (POINT4D){box->xmin, box->ymin, box->zmax, 0.0};
306 points[5] = (POINT4D){box->xmin, box->ymax, box->zmax, 0.0};
307 points[6] = (POINT4D){box->xmax, box->ymax, box->zmax, 0.0};
308 points[7] = (POINT4D){box->xmax, box->ymin, box->zmax, 0.0};
309
310 /* add bottom polygon */
311 geoms[0] = lwpoly_as_lwgeom(
312 lwpoly_construct_rectangle(LW_TRUE, LW_FALSE, &points[0], &points[1], &points[2], &points[3]));
313 /* add top polygon */
314 geoms[1] = lwpoly_as_lwgeom(
315 lwpoly_construct_rectangle(LW_TRUE, LW_FALSE, &points[4], &points[7], &points[6], &points[5]));
316 /* add left polygon */
317 geoms[2] = lwpoly_as_lwgeom(
318 lwpoly_construct_rectangle(LW_TRUE, LW_FALSE, &points[0], &points[4], &points[5], &points[1]));
319 /* add right polygon */
320 geoms[3] = lwpoly_as_lwgeom(
321 lwpoly_construct_rectangle(LW_TRUE, LW_FALSE, &points[3], &points[2], &points[6], &points[7]));
322 /* add front polygon */
323 geoms[4] = lwpoly_as_lwgeom(
324 lwpoly_construct_rectangle(LW_TRUE, LW_FALSE, &points[0], &points[3], &points[7], &points[4]));
325 /* add back polygon */
326 geoms[5] = lwpoly_as_lwgeom(
327 lwpoly_construct_rectangle(LW_TRUE, LW_FALSE, &points[1], &points[5], &points[6], &points[2]));
328
329 geom = (LWGEOM *)lwcollection_construct(POLYHEDRALSURFACETYPE, SRID_UNKNOWN, NULL, ngeoms, geoms);
330
331 FLAGS_SET_SOLID(geom->flags, 1);
332
333 result = geometry_serialize(geom);
335 }
336
338
339 PG_RETURN_POINTER(result);
340}
341
343void
344expand_box3d(BOX3D *box, double d)
345{
346 box->xmin -= d;
347 box->ymin -= d;
348 box->zmin -= d;
349
350 box->xmax += d;
351 box->ymax += d;
352 box->zmax += d;
353}
354
355static void
356expand_box3d_xyz(BOX3D *box, double dx, double dy, double dz)
357{
358 box->xmin -= dx;
359 box->xmax += dx;
360 box->ymin -= dy;
361 box->ymax += dy;
362 box->zmin -= dz;
363 box->zmax += dz;
364}
365
367Datum BOX3D_expand(PG_FUNCTION_ARGS)
368{
369 BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
370 BOX3D *result = (BOX3D *)palloc(sizeof(BOX3D));
371 memcpy(result, box, sizeof(BOX3D));
372
373 if (PG_NARGS() == 2)
374 {
375 /* Expand the box the same amount in all directions */
376 double d = PG_GETARG_FLOAT8(1);
378 }
379 else
380 {
381 double dx = PG_GETARG_FLOAT8(1);
382 double dy = PG_GETARG_FLOAT8(2);
383 double dz = PG_GETARG_FLOAT8(3);
384
385 expand_box3d_xyz(result, dx, dy, dz);
386 }
387
388 PG_RETURN_POINTER(result);
389}
390
398Datum LWGEOM_to_BOX3D(PG_FUNCTION_ARGS)
399{
400 GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
401 LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
402 GBOX gbox;
403 BOX3D *result;
404 int rv = lwgeom_calculate_gbox(lwgeom, &gbox);
405
406 if (rv == LW_FAILURE)
407 PG_RETURN_NULL();
408
409 result = box3d_from_gbox(&gbox);
410 result->srid = lwgeom->srid;
411
412 lwgeom_free(lwgeom);
413 PG_RETURN_POINTER(result);
414}
415
417Datum BOX3D_xmin(PG_FUNCTION_ARGS)
418{
419 BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
420 PG_RETURN_FLOAT8(Min(box->xmin, box->xmax));
421}
422
424Datum BOX3D_ymin(PG_FUNCTION_ARGS)
425{
426 BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
427 PG_RETURN_FLOAT8(Min(box->ymin, box->ymax));
428}
429
431Datum BOX3D_zmin(PG_FUNCTION_ARGS)
432{
433 BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
434 PG_RETURN_FLOAT8(Min(box->zmin, box->zmax));
435}
436
438Datum BOX3D_xmax(PG_FUNCTION_ARGS)
439{
440 BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
441 PG_RETURN_FLOAT8(Max(box->xmin, box->xmax));
442}
443
445Datum BOX3D_ymax(PG_FUNCTION_ARGS)
446{
447 BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
448 PG_RETURN_FLOAT8(Max(box->ymin, box->ymax));
449}
450
452Datum BOX3D_zmax(PG_FUNCTION_ARGS)
453{
454 BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
455 PG_RETURN_FLOAT8(Max(box->zmin, box->zmax));
456}
457
458
459Datum ST_MMin(PG_FUNCTION_ARGS);
461Datum ST_MMin(PG_FUNCTION_ARGS)
462{
463 GBOX gbox;
464 GSERIALIZED *gser = PG_GETARG_GSERIALIZED_P(0);
465
466 if (gserialized_get_gbox_p(gser, &gbox) != LW_TRUE)
467 PG_RETURN_NULL();
468
469 if (!FLAGS_GET_M(gbox.flags))
470 PG_RETURN_NULL();
471
472 PG_RETURN_FLOAT8(Min(gbox.mmin, gbox.mmax));
473}
474
475
476Datum ST_MMax(PG_FUNCTION_ARGS);
478Datum ST_MMax(PG_FUNCTION_ARGS)
479{
480 GBOX gbox;
481 GSERIALIZED *gser = PG_GETARG_GSERIALIZED_P(0);
482
483 if (gserialized_get_gbox_p(gser, &gbox) != LW_TRUE)
484 PG_RETURN_NULL();
485
486 if (!FLAGS_GET_M(gbox.flags))
487 PG_RETURN_NULL();
488
489 PG_RETURN_FLOAT8(Max(gbox.mmin, gbox.mmax));
490}
491
492
499Datum BOX3D_combine(PG_FUNCTION_ARGS)
500{
501 BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
502 GSERIALIZED *geom = PG_ARGISNULL(1) ? NULL : (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
503 LWGEOM *lwgeom = NULL;
504 BOX3D *result = NULL;
505 GBOX gbox;
506 int32_t srid;
507 int rv;
508
509 /* Can't do anything with null inputs */
510 if (!box && !geom)
511 {
512 PG_RETURN_NULL();
513 }
514 /* Null geometry but non-null box, return the box */
515 else if (!geom)
516 {
517 result = palloc(sizeof(BOX3D));
518 memcpy(result, box, sizeof(BOX3D));
519 PG_RETURN_POINTER(result);
520 }
521
522 /*
523 * Deserialize geometry and *calculate* the box
524 * We can't use the cached box because it's float, we *must* calculate
525 */
526 lwgeom = lwgeom_from_gserialized(geom);
527 srid = lwgeom->srid;
528 rv = lwgeom_calculate_gbox(lwgeom, &gbox);
529 lwgeom_free(lwgeom);
530
531 /* If we couldn't calculate the box, return what we know */
532 if (rv == LW_FAILURE)
533 {
534 PG_FREE_IF_COPY(geom, 1);
535 /* No geom box, no input box, so null return */
536 if (!box)
537 PG_RETURN_NULL();
538 result = palloc(sizeof(BOX3D));
539 memcpy(result, box, sizeof(BOX3D));
540 PG_RETURN_POINTER(result);
541 }
542
543 /* Null box and non-null geometry, just return the geometry box */
544 if (!box)
545 {
546 PG_FREE_IF_COPY(geom, 1);
547 result = box3d_from_gbox(&gbox);
548 result->srid = srid;
549 PG_RETURN_POINTER(result);
550 }
551
552 result = palloc(sizeof(BOX3D));
553 result->xmax = Max(box->xmax, gbox.xmax);
554 result->ymax = Max(box->ymax, gbox.ymax);
555 result->zmax = Max(box->zmax, gbox.zmax);
556 result->xmin = Min(box->xmin, gbox.xmin);
557 result->ymin = Min(box->ymin, gbox.ymin);
558 result->zmin = Min(box->zmin, gbox.zmin);
559 result->srid = srid;
560
561 PG_FREE_IF_COPY(geom, 1);
562 PG_RETURN_POINTER(result);
563}
564
566Datum BOX3D_combine_BOX3D(PG_FUNCTION_ARGS)
567{
568 BOX3D *box0 = (BOX3D *)(PG_ARGISNULL(0) ? NULL : PG_GETARG_POINTER(0));
569 BOX3D *box1 = (BOX3D *)(PG_ARGISNULL(1) ? NULL : PG_GETARG_POINTER(1));
570 BOX3D *result;
571
572 if (box0 && !box1)
573 PG_RETURN_POINTER(box0);
574
575 if (box1 && !box0)
576 PG_RETURN_POINTER(box1);
577
578 if (!box1 && !box0)
579 PG_RETURN_NULL();
580
581 result = palloc(sizeof(BOX3D));
582 result->xmax = Max(box0->xmax, box1->xmax);
583 result->ymax = Max(box0->ymax, box1->ymax);
584 result->zmax = Max(box0->zmax, box1->zmax);
585 result->xmin = Min(box0->xmin, box1->xmin);
586 result->ymin = Min(box0->ymin, box1->ymin);
587 result->zmin = Min(box0->zmin, box1->zmin);
588 result->srid = box0->srid;
589
590 PG_RETURN_POINTER(result);
591}
592
594Datum BOX3D_construct(PG_FUNCTION_ARGS)
595{
596 GSERIALIZED *min = PG_GETARG_GSERIALIZED_P(0);
597 GSERIALIZED *max = PG_GETARG_GSERIALIZED_P(1);
598 BOX3D *result = palloc(sizeof(BOX3D));
599 LWGEOM *minpoint, *maxpoint;
600 POINT3DZ minp, maxp;
601
602 minpoint = lwgeom_from_gserialized(min);
603 maxpoint = lwgeom_from_gserialized(max);
604
605 if (minpoint->type != POINTTYPE || maxpoint->type != POINTTYPE)
606 {
607 elog(ERROR, "BOX3D_construct: args must be points");
608 PG_RETURN_NULL();
609 }
610
611 if (lwgeom_is_empty(minpoint) || lwgeom_is_empty(maxpoint) ){
612 elog(ERROR, "BOX3D_construct: args can not be empty points");
613 PG_RETURN_NULL();
614 }
615
616 gserialized_error_if_srid_mismatch(min, max, __func__);
617
618 getPoint3dz_p(((LWPOINT *)minpoint)->point, 0, &minp);
619 getPoint3dz_p(((LWPOINT *)maxpoint)->point, 0, &maxp);
620
621 result->xmax = maxp.x;
622 result->ymax = maxp.y;
623 result->zmax = maxp.z;
624
625 result->xmin = minp.x;
626 result->ymin = minp.y;
627 result->zmin = minp.z;
628
629 result->srid = minpoint->srid;
630
631 PG_RETURN_POINTER(result);
632}
633
635/*****************************************************************************
636 * BOX3D functions
637 *****************************************************************************/
638
639/* contains? */
640bool
642{
643 return (box1->xmax >= box2->xmax && box1->xmin <= box2->xmin) &&
644 (box1->ymax >= box2->ymax && box1->ymin <= box2->ymin) &&
645 (box1->zmax >= box2->zmax && box1->zmin <= box2->zmin);
646}
647
649
650PGDLLEXPORT Datum BOX3D_contains(PG_FUNCTION_ARGS)
651{
652 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
653 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
654 bool result = BOX3D_contains_internal(box1, box2);
655 PG_RETURN_BOOL(result);
656}
657
658/* contained by? */
659bool
661{
662 return BOX3D_contains_internal(box2, box1);
663}
664
666
667PGDLLEXPORT Datum BOX3D_contained(PG_FUNCTION_ARGS)
668{
669 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
670 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
671 bool result = BOX3D_contained_internal(box1, box2);
672 PG_RETURN_BOOL(result);
673}
674
675/* overlaps? */
676bool
678{
679 return (box1->xmin <= box2->xmax && box2->xmin <= box1->xmax) &&
680 (box1->ymin <= box2->ymax && box2->ymin <= box1->ymax) &&
681 (box1->zmin <= box2->zmax && box2->zmin <= box1->zmax);
682}
683
685
686PGDLLEXPORT Datum BOX3D_overlaps(PG_FUNCTION_ARGS)
687{
688 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
689 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
690 bool result = BOX3D_overlaps_internal(box1, box2);
691 PG_RETURN_BOOL(result);
692}
693
694/* same? */
695bool
697{
698 return (FPeq(box1->xmax, box2->xmax) && FPeq(box1->xmin, box2->xmin)) &&
699 (FPeq(box1->ymax, box2->ymax) && FPeq(box1->ymin, box2->ymin)) &&
700 (FPeq(box1->zmax, box2->zmax) && FPeq(box1->zmin, box2->zmin));
701}
702
704
705PGDLLEXPORT Datum BOX3D_same(PG_FUNCTION_ARGS)
706{
707 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
708 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
709 bool result = BOX3D_same_internal(box1, box2);
710 PG_RETURN_BOOL(result);
711}
712
713/* strictly left of? */
714bool
716{
717 return box1->xmax < box2->xmin;
718}
719
721
722PGDLLEXPORT Datum BOX3D_left(PG_FUNCTION_ARGS)
723{
724 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
725 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
726 bool result = BOX3D_left_internal(box1, box2);
727 PG_RETURN_BOOL(result);
728}
729
730/* does not extend to right of? */
731bool
733{
734 return box1->xmax <= box2->xmax;
735}
736
738
739PGDLLEXPORT Datum BOX3D_overleft(PG_FUNCTION_ARGS)
740{
741 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
742 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
743 bool result = BOX3D_overleft_internal(box1, box2);
744 PG_RETURN_BOOL(result);
745}
746
747/* strictly right of? */
748bool
750{
751 return box1->xmin > box2->xmax;
752}
753
755
756PGDLLEXPORT Datum BOX3D_right(PG_FUNCTION_ARGS)
757{
758 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
759 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
760 bool result = BOX3D_right_internal(box1, box2);
761 PG_RETURN_BOOL(result);
762}
763
764/* does not extend to left of? */
765bool
767{
768 return box1->xmin >= box2->xmin;
769}
770
772
773PGDLLEXPORT Datum BOX3D_overright(PG_FUNCTION_ARGS)
774{
775 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
776 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
777 bool result = BOX3D_overright_internal(box1, box2);
778 PG_RETURN_BOOL(result);
779}
780
781/* strictly below of? */
782bool
784{
785 return box1->ymax < box2->ymin;
786}
787
789
790PGDLLEXPORT Datum BOX3D_below(PG_FUNCTION_ARGS)
791{
792 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
793 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
794 bool result = BOX3D_below_internal(box1, box2);
795 PG_RETURN_BOOL(result);
796}
797
798/* does not extend above of? */
799bool
801{
802 return box1->ymax <= box2->ymax;
803}
804
806
807PGDLLEXPORT Datum BOX3D_overbelow(PG_FUNCTION_ARGS)
808{
809 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
810 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
811 bool result = BOX3D_overbelow_internal(box1, box2);
812 PG_RETURN_BOOL(result);
813}
814
815/* strictly above of? */
816bool
818{
819 return box1->ymin > box2->ymax;
820}
821
823
824PGDLLEXPORT Datum BOX3D_above(PG_FUNCTION_ARGS)
825{
826 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
827 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
828 bool result = BOX3D_above_internal(box1, box2);
829 PG_RETURN_BOOL(result);
830}
831
832/* does not extend below of? */
833bool
835{
836 return box1->ymin >= box2->ymin;
837}
838
840
841PGDLLEXPORT Datum BOX3D_overabove(PG_FUNCTION_ARGS)
842{
843 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
844 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
845 bool result = BOX3D_overabove_internal(box1, box2);
846 PG_RETURN_BOOL(result);
847}
848
849/* strictly in before of? */
850bool
852{
853 return box1->zmax < box2->zmin;
854}
855
857
858PGDLLEXPORT Datum BOX3D_front(PG_FUNCTION_ARGS)
859{
860 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
861 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
862 bool result = BOX3D_front_internal(box1, box2);
863 PG_RETURN_BOOL(result);
864}
865
866/* does not extend to the after of? */
867bool
869{
870 return box1->zmax <= box2->zmax;
871}
872
874
875PGDLLEXPORT Datum BOX3D_overfront(PG_FUNCTION_ARGS)
876{
877 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
878 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
879 bool result = BOX3D_overfront_internal(box1, box2);
880 PG_RETURN_BOOL(result);
881}
882
883/* strictly after of? */
884bool
886{
887 return box1->zmin > box2->zmax;
888}
889
891
892PGDLLEXPORT Datum BOX3D_back(PG_FUNCTION_ARGS)
893{
894 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
895 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
896 bool result = BOX3D_back_internal(box1, box2);
897 PG_RETURN_BOOL(result);
898}
899
900/* does not extend to the before of? */
901bool
903{
904 return box1->zmin >= box2->zmin;
905}
906
908
909PGDLLEXPORT Datum BOX3D_overback(PG_FUNCTION_ARGS)
910{
911 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
912 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
913 bool result = BOX3D_overback_internal(box1, box2);
914 PG_RETURN_BOOL(result);
915}
916
917/* Minimum distance between 2 bounding boxes */
918double
920{
921 double sqrDist = 0;
922 double d;
923
924 if (BOX3D_overlaps_internal(box1, box2))
925 return 0.0;
926
927 /* X axis */
928 if (box1->xmax < box2->xmin)
929 {
930 d = box1->xmax - box2->xmin;
931 sqrDist += d * d;
932 }
933 else if (box1->xmin > box2->xmax)
934 {
935 d = box1->xmin - box2->xmax;
936 sqrDist += d * d;
937 }
938 /* Y axis */
939 if (box1->ymax < box2->ymin)
940 {
941 d = box1->ymax - box2->ymin;
942 sqrDist += d * d;
943 }
944 else if (box1->ymin > box2->ymax)
945 {
946 d = box1->ymin - box2->ymax;
947 sqrDist += d * d;
948 }
949 /* Z axis */
950 if (box1->zmax < box2->zmin)
951 {
952 d = box1->zmax - box2->zmin;
953 sqrDist += d * d;
954 }
955 else if (box1->zmin > box2->zmax)
956 {
957 d = box1->zmin - box2->zmax;
958 sqrDist += d * d;
959 }
960
961 return sqrt(sqrDist);
962}
963
965
966PGDLLEXPORT Datum BOX3D_distance(PG_FUNCTION_ARGS)
967{
968 BOX3D *box1 = PG_GETARG_BOX3D_P(0);
969 BOX3D *box2 = PG_GETARG_BOX3D_P(1);
970 PG_RETURN_FLOAT8(BOX3D_distance_internal(box1, box2));
971}
static uint8_t precision
Definition cu_in_twkb.c:25
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition cu_print.c:267
GBOX * box3d_to_gbox(const BOX3D *b3d)
Definition gbox.c:80
BOX3D * box3d_from_gbox(const GBOX *gbox)
Definition gbox.c:53
void gserialized_error_if_srid_mismatch(const GSERIALIZED *g1, const GSERIALIZED *g2, const char *funcname)
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Read the box from the GSERIALIZED or calculate it if necessary.
Definition gserialized.c:94
void gserialized_set_srid(GSERIALIZED *g, int32_t srid)
Write the SRID into the serialized form (it is packed into three bytes so this is a handy function).
LWCOLLECTION * lwcollection_construct(uint8_t type, int32_t srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition lwgeom.c:372
#define LW_FALSE
Definition liblwgeom.h:94
void lwpoint_free(LWPOINT *pt)
Definition lwpoint.c:213
#define LW_FAILURE
Definition liblwgeom.h:96
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1246
LWPOINT * lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
Definition lwpoint.c:129
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition ptarray.c:59
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:102
void * lwalloc(size_t size)
Definition lwutil.c:227
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwline.c:42
int getPoint3dz_p(const POINTARRAY *pa, uint32_t n, POINT3DZ *point)
Definition lwgeom_api.c:215
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:367
#define POLYHEDRALSURFACETYPE
Definition liblwgeom.h:114
#define FLAGS_GET_M(flags)
Definition liblwgeom.h:166
void lwcollection_free(LWCOLLECTION *col)
LWPOLY * lwpoly_construct_rectangle(char hasz, char hasm, POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D *p4)
Definition lwpoly.c:80
int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox)
Calculate bounding box of a geometry, automatically taking into account whether it is cartesian or ge...
Definition lwgeom.c:783
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE,...
Definition ptarray.c:147
void lwpoly_free(LWPOLY *poly)
Definition lwpoly.c:175
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:93
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:215
#define FLAGS_SET_SOLID(flags, value)
Definition liblwgeom.h:177
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition lwgeom.c:357
void lwline_free(LWLINE *line)
Definition lwline.c:67
This library is the generic geometry handling section of PostGIS.
#define OUT_MAX_BYTES_DOUBLE
int lwprint_double(double d, int maxdd, char *buf)
Definition lwprint.c:463
PGDLLEXPORT Datum BOX3D_below(PG_FUNCTION_ARGS)
bool BOX3D_above_internal(BOX3D *box1, BOX3D *box2)
PGDLLEXPORT Datum BOX3D_left(PG_FUNCTION_ARGS)
bool BOX3D_back_internal(BOX3D *box1, BOX3D *box2)
PGDLLEXPORT Datum BOX3D_overlaps(PG_FUNCTION_ARGS)
Datum BOX3D_to_BOX(PG_FUNCTION_ARGS)
static void box3d_to_box_p(BOX3D *box, BOX *out)
Datum BOX3D_to_LWGEOM(PG_FUNCTION_ARGS)
PGDLLEXPORT Datum BOX3D_contained(PG_FUNCTION_ARGS)
PGDLLEXPORT Datum BOX3D_overfront(PG_FUNCTION_ARGS)
Datum BOX3D_ymax(PG_FUNCTION_ARGS)
Datum BOX3D_zmax(PG_FUNCTION_ARGS)
PGDLLEXPORT Datum BOX3D_front(PG_FUNCTION_ARGS)
Datum BOX3D_xmax(PG_FUNCTION_ARGS)
Datum BOX3D_combine(PG_FUNCTION_ARGS)
Datum BOX3D_zmin(PG_FUNCTION_ARGS)
double BOX3D_distance_internal(BOX3D *box1, BOX3D *box2)
static void expand_box3d_xyz(BOX3D *box, double dx, double dy, double dz)
bool BOX3D_overlaps_internal(BOX3D *box1, BOX3D *box2)
PG_FUNCTION_INFO_V1(BOX3D_in)
BOX3D_in - takes a string rep of BOX3D and returns internal rep.
Datum ST_MMin(PG_FUNCTION_ARGS)
PGDLLEXPORT Datum BOX3D_overright(PG_FUNCTION_ARGS)
Datum BOX3D_construct(PG_FUNCTION_ARGS)
bool BOX3D_contains_internal(BOX3D *box1, BOX3D *box2)
Needed for SP-GiST support.
Datum BOX3D_to_BOX2D(PG_FUNCTION_ARGS)
bool BOX3D_overabove_internal(BOX3D *box1, BOX3D *box2)
PGDLLEXPORT Datum BOX3D_overleft(PG_FUNCTION_ARGS)
Datum BOX3D_out(PG_FUNCTION_ARGS)
bool BOX3D_right_internal(BOX3D *box1, BOX3D *box2)
Datum BOX3D_in(PG_FUNCTION_ARGS)
bool BOX3D_overback_internal(BOX3D *box1, BOX3D *box2)
bool BOX3D_overleft_internal(BOX3D *box1, BOX3D *box2)
PGDLLEXPORT Datum BOX3D_contains(PG_FUNCTION_ARGS)
Needed for SP-GiST support.
bool BOX3D_below_internal(BOX3D *box1, BOX3D *box2)
PGDLLEXPORT Datum BOX3D_back(PG_FUNCTION_ARGS)
PGDLLEXPORT Datum BOX3D_overback(PG_FUNCTION_ARGS)
Datum BOX3D_expand(PG_FUNCTION_ARGS)
void expand_box3d(BOX3D *box, double d)
Expand given box of 'd' units in all directions.
Datum ST_MMax(PG_FUNCTION_ARGS)
PGDLLEXPORT Datum BOX3D_above(PG_FUNCTION_ARGS)
bool BOX3D_left_internal(BOX3D *box1, BOX3D *box2)
bool BOX3D_overright_internal(BOX3D *box1, BOX3D *box2)
bool BOX3D_same_internal(BOX3D *box1, BOX3D *box2)
bool BOX3D_contained_internal(BOX3D *box1, BOX3D *box2)
Datum LWGEOM_to_BOX3D(PG_FUNCTION_ARGS)
Datum BOX3D_xmin(PG_FUNCTION_ARGS)
bool BOX3D_front_internal(BOX3D *box1, BOX3D *box2)
bool BOX3D_overfront_internal(BOX3D *box1, BOX3D *box2)
PGDLLEXPORT Datum BOX3D_right(PG_FUNCTION_ARGS)
PGDLLEXPORT Datum BOX3D_overabove(PG_FUNCTION_ARGS)
PGDLLEXPORT Datum BOX3D_overbelow(PG_FUNCTION_ARGS)
PGDLLEXPORT Datum BOX3D_same(PG_FUNCTION_ARGS)
bool BOX3D_overbelow_internal(BOX3D *box1, BOX3D *box2)
Datum BOX3D_combine_BOX3D(PG_FUNCTION_ARGS)
Datum BOX3D_ymin(PG_FUNCTION_ARGS)
PGDLLEXPORT Datum BOX3D_distance(PG_FUNCTION_ARGS)
#define str(s)
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition lwinline.h:199
double xmax
Definition liblwgeom.h:340
double zmin
Definition liblwgeom.h:339
double ymax
Definition liblwgeom.h:340
double ymin
Definition liblwgeom.h:339
double zmax
Definition liblwgeom.h:340
double xmin
Definition liblwgeom.h:339
int32_t srid
Definition liblwgeom.h:341
double ymax
Definition liblwgeom.h:357
double zmax
Definition liblwgeom.h:359
double xmax
Definition liblwgeom.h:355
double zmin
Definition liblwgeom.h:358
double mmax
Definition liblwgeom.h:361
double ymin
Definition liblwgeom.h:356
double xmin
Definition liblwgeom.h:354
double mmin
Definition liblwgeom.h:360
lwflags_t flags
Definition liblwgeom.h:353
uint8_t type
Definition liblwgeom.h:462
int32_t srid
Definition liblwgeom.h:460
lwflags_t flags
Definition liblwgeom.h:461
double z
Definition liblwgeom.h:396
double x
Definition liblwgeom.h:396
double y
Definition liblwgeom.h:396
double x
Definition liblwgeom.h:414
double z
Definition liblwgeom.h:414
double y
Definition liblwgeom.h:414