PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
lwgeom_rectree.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 (C) 2018 Paul Ramsey
22 *
23 **********************************************************************/
24
25
26#include "postgres.h"
27#include "funcapi.h"
28#include "fmgr.h"
29#include "liblwgeom.h"
30#include "liblwgeom_internal.h" /* For FP comparators. */
31#include "lwgeom_pg.h"
32#include "lwtree.h"
33#include "lwgeom_cache.h"
34
35
36/* Prototypes */
37Datum ST_DistanceRectTree(PG_FUNCTION_ARGS);
38Datum ST_DistanceRectTreeCached(PG_FUNCTION_ARGS);
39
40
41/**********************************************************************
42* RectTree Caching support
43**********************************************************************/
44
45/*
46* Specific tree types include all the generic slots and
47* their own slots for their trees. We put the implementation
48* for the RectTreeGeomCache here because we can't shove
49* the PgSQL specific bits of the code (fcinfo) back into
50* liblwgeom/lwtree.c, where most of the rect_tree logic lives.
51*/
52typedef struct {
53 GeomCache gcache;
56
57
61static int
62RectTreeBuilder(const LWGEOM *lwgeom, GeomCache *cache)
63{
64 RectTreeGeomCache *rect_cache = (RectTreeGeomCache*)cache;
65 RECT_NODE *tree = rect_tree_from_lwgeom(lwgeom);
66
67 if ( rect_cache->index )
68 {
69 rect_tree_free(rect_cache->index);
70 rect_cache->index = 0;
71 }
72 if ( ! tree )
73 return LW_FAILURE;
74
75 rect_cache->index = tree;
76 return LW_SUCCESS;
77}
78
79static int
80RectTreeFreer(GeomCache *cache)
81{
82 RectTreeGeomCache *rect_cache = (RectTreeGeomCache*)cache;
83 if ( rect_cache->index )
84 {
85 rect_tree_free(rect_cache->index);
86 rect_cache->index = 0;
87 rect_cache->gcache.argnum = 0;
88 }
89 return LW_SUCCESS;
90}
91
92static GeomCache *
94{
95 RectTreeGeomCache *cache = palloc(sizeof(RectTreeGeomCache));
96 memset(cache, 0, sizeof(RectTreeGeomCache));
97 return (GeomCache*)cache;
98}
99
100static GeomCacheMethods RectTreeCacheMethods =
101{
102 RECT_CACHE_ENTRY,
106};
107
108static RectTreeGeomCache *
109GetRectTreeGeomCache(FunctionCallInfo fcinfo, SHARED_GSERIALIZED *g1, SHARED_GSERIALIZED *g2)
110{
111 return (RectTreeGeomCache*)GetGeomCache(fcinfo, &RectTreeCacheMethods, g1, g2);
112}
113
114
115/**********************************************************************
116* ST_DistanceRectTree
117**********************************************************************/
118
120Datum ST_DistanceRectTree(PG_FUNCTION_ARGS)
121{
122 GSERIALIZED *g1 = PG_GETARG_GSERIALIZED_P(0);
123 GSERIALIZED *g2 = PG_GETARG_GSERIALIZED_P(1);
124 LWGEOM *lwg1, *lwg2;
125 RECT_NODE *n1, *n2;
126
127 /* Return NULL on empty arguments. */
129 {
130 PG_FREE_IF_COPY(g1, 0);
131 PG_FREE_IF_COPY(g2, 1);
132 PG_RETURN_NULL();
133 }
134
135 lwg1 = lwgeom_from_gserialized(g1);
136 lwg2 = lwgeom_from_gserialized(g2);
137
138 /* Two points? Get outa here... */
139 if (lwg1->type == POINTTYPE && lwg2->type == POINTTYPE)
140 PG_RETURN_FLOAT8(lwgeom_mindistance2d(lwg1, lwg2));
141
142
143 n1 = rect_tree_from_lwgeom(lwg1);
144 n2 = rect_tree_from_lwgeom(lwg2);
145 PG_RETURN_FLOAT8(rect_tree_distance_tree(n1, n2, 0.0));
146}
147
149Datum ST_DistanceRectTreeCached(PG_FUNCTION_ARGS)
150{
151 RectTreeGeomCache *tree_cache = NULL;
152 SHARED_GSERIALIZED *shared_geom1 = ToastCacheGetGeometry(fcinfo, 0);
153 SHARED_GSERIALIZED *shared_geom2 = ToastCacheGetGeometry(fcinfo, 1);
154 const GSERIALIZED *g1 = shared_gserialized_get(shared_geom1);
155 const GSERIALIZED *g2 = shared_gserialized_get(shared_geom2);
156
157 /* Return NULL on empty arguments. */
159 {
160 PG_RETURN_NULL();
161 }
162
163 /* Two points? Get outa here... */
165 {
168 PG_RETURN_FLOAT8(lwgeom_mindistance2d(lwg1, lwg2));
169 }
170
171 /* Fetch/build our cache, if appropriate, etc... */
172 tree_cache = GetRectTreeGeomCache(fcinfo, shared_geom1, shared_geom2);
173
174 if (tree_cache && tree_cache->gcache.argnum)
175 {
176 RECT_NODE *n;
177 RECT_NODE *n_cached = tree_cache->index;
178 if (tree_cache->gcache.argnum == 1)
179 {
181 n = rect_tree_from_lwgeom(lwg2);
182 }
183 else if (tree_cache->gcache.argnum == 2)
184 {
186 n = rect_tree_from_lwgeom(lwg1);
187 }
188 else
189 {
190 elog(ERROR, "reached unreachable block in %s", __func__);
191 }
192 PG_RETURN_FLOAT8(rect_tree_distance_tree(n, n_cached, 0.0));
193 }
194 else
195 {
198 PG_RETURN_FLOAT8(lwgeom_mindistance2d(lwg1, lwg2));
199 }
200
201 PG_RETURN_NULL();
202}
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
#define LW_FAILURE
Definition liblwgeom.h:96
#define LW_SUCCESS
Definition liblwgeom.h:97
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:102
double lwgeom_mindistance2d(const LWGEOM *lw1, const LWGEOM *lw2)
Function initializing min distance calculation.
Definition measures.c:212
This library is the generic geometry handling section of PostGIS.
static int RectTreeBuilder(const LWGEOM *lwgeom, GeomCache *cache)
Builder, freeer and public accessor for cached RECT_NODE trees.
static GeomCacheMethods RectTreeCacheMethods
Datum ST_DistanceRectTree(PG_FUNCTION_ARGS)
static RectTreeGeomCache * GetRectTreeGeomCache(FunctionCallInfo fcinfo, SHARED_GSERIALIZED *g1, SHARED_GSERIALIZED *g2)
static GeomCache * RectTreeAllocator(void)
static int RectTreeFreer(GeomCache *cache)
PG_FUNCTION_INFO_V1(ST_DistanceRectTree)
Datum ST_DistanceRectTreeCached(PG_FUNCTION_ARGS)
RECT_NODE * rect_tree_from_lwgeom(const LWGEOM *lwgeom)
Create a tree index on top an LWGEOM.
Definition lwtree.c:861
void rect_tree_free(RECT_NODE *node)
Recurse from top of node tree and free all children.
Definition lwtree.c:69
double rect_tree_distance_tree(RECT_NODE *n1, RECT_NODE *n2, double threshold)
Return the distance between two RECT_NODE trees.
Definition lwtree.c:1354
uint8_t type
Definition liblwgeom.h:462