Skip to content

Commit dcb44e8

Browse files
Rub21geohacker
authored andcommitted
Fix api db function - postgres version 11
1 parent e245229 commit dcb44e8

File tree

12 files changed

+328
-20
lines changed

12 files changed

+328
-20
lines changed

images/db/Dockerfile

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
11
FROM postgres:11
2+
RUN apt-get update \
3+
&& apt-get install -y \
4+
postgresql-server-dev-11 \
5+
make \
6+
build-essential \
7+
postgresql-11-postgis-2.5 \
8+
&& apt-get clean && rm -rf /var/lib/apt/lists/*
29

3-
# Add db init script to install OSM-specific Postgres functions/extensions.
4-
ADD openstreetmap-postgres-init.sh /docker-entrypoint-initdb.d/
10+
ADD functions/functions.sql /usr/local/share/osm-db-functions.sql
11+
ADD docker_postgres.sh /docker-entrypoint-initdb.d/
12+
RUN mkdir -p db
13+
RUN mkdir -p lib
14+
ADD functions/ db/functions/
15+
ADD lib/quad_tile/ lib/quad_tile/
516

6-
# Custom database functions are in a SQL file.
7-
ADD functions/functions.sql /usr/local/share/osm-db-functions.sql
17+
RUN make -C db/functions/
18+
RUN chown -R postgres lib/
19+
RUN chown -R postgres db/

images/db/docker_postgres.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# From: https://github.com/openstreetmap/openstreetmap-website/blob/af273f5d6ae160de0001ce1ac0c087d92a2463c6/docker/postgres/openstreetmap-postgres-init.sh
5+
# Create 'openstreetmap' user
6+
# Password and superuser privilege are needed to successfully run test suite
7+
psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" <<-EOSQL
8+
CREATE USER openstreetmap SUPERUSER PASSWORD 'openstreetmap';
9+
GRANT ALL PRIVILEGES ON DATABASE openstreetmap TO openstreetmap;
10+
EOSQL
11+
12+
psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -c "CREATE ROLE hosm WITH SUPERUSER" openstreetmap
13+
psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -c "CREATE EXTENSION btree_gist" openstreetmap
14+
psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -c "CREATE EXTENSION postgis" openstreetmap
15+
make -C /db/functions libpgosm.so
16+
psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -c "CREATE FUNCTION maptile_for_point(int8, int8, int4) RETURNS int4 AS '/db/functions/libpgosm', 'maptile_for_point' LANGUAGE C STRICT" openstreetmap
17+
# psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -c "CREATE FUNCTION tile_for_point(int4, int4) RETURNS int8 AS '/db/functions/libpgosm', 'tile_for_point' LANGUAGE C STRICT" openstreetmap
18+
psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -c "CREATE FUNCTION xid_to_int4(xid) RETURNS int4 AS '/db/functions/libpgosm', 'xid_to_int4' LANGUAGE C STRICT" openstreetmap
19+
20+
21+
# Define custom functions
22+
psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -f "/usr/local/share/osm-db-functions.sql" openstreetmap

images/db/functions/Makefile

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
PG_CONFIG ?= pg_config
2+
DESTDIR ?= .
3+
4+
QTDIR=../../lib/quad_tile
5+
6+
OS=$(shell uname -s)
7+
ifeq (${OS},Darwin)
8+
LDFLAGS=-bundle
9+
else
10+
LDFLAGS=-shared
11+
endif
12+
13+
all: ${DESTDIR}/libpgosm.so
14+
15+
clean:
16+
$(RM) ${DESTDIR}/*.so ${DESTDIR}/*.o
17+
18+
${DESTDIR}/libpgosm.so: ${DESTDIR}/quadtile.o ${DESTDIR}/maptile.o ${DESTDIR}/xid_to_int4.o
19+
cc ${LDFLAGS} -o $@ $^
20+
21+
${DESTDIR}/%.o: %.c
22+
cc -I `${PG_CONFIG} --includedir` -I `${PG_CONFIG} --includedir-server` -I${QTDIR} -fPIC -O3 -DUSE_PGSQL -c -o $@ $<
23+
24+
${DESTDIR}/quadtile.o: ${QTDIR}/quad_tile.h

images/db/functions/maptile.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include <math.h>
2+
#include <postgres.h>
3+
#include <fmgr.h>
4+
5+
Datum
6+
maptile_for_point(PG_FUNCTION_ARGS)
7+
{
8+
double lat = PG_GETARG_INT64(0) / 10000000.0;
9+
double lon = PG_GETARG_INT64(1) / 10000000.0;
10+
int zoom = PG_GETARG_INT32(2);
11+
double scale = pow(2, zoom);
12+
double r_per_d = M_PI / 180;
13+
unsigned int x;
14+
unsigned int y;
15+
16+
x = floor((lon + 180.0) * scale / 360.0);
17+
y = floor((1 - log(tan(lat * r_per_d) + 1.0 / cos(lat * r_per_d)) / M_PI) * scale / 2.0);
18+
19+
PG_RETURN_INT32((x << zoom) | y);
20+
}
21+
22+
PG_FUNCTION_INFO_V1(maptile_for_point);
23+
24+
/*
25+
* To bind this into PGSQL, try something like:
26+
*
27+
* CREATE FUNCTION maptile_for_point(int8, int8, int4) RETURNS int4
28+
* AS '/path/to/rails-port/db/functions/libpgosm', 'maptile_for_point'
29+
* LANGUAGE C STRICT;
30+
*
31+
* (without all the *s)
32+
*/
33+
34+
#ifdef PG_MODULE_MAGIC
35+
PG_MODULE_MAGIC;
36+
#endif

images/db/functions/quadtile.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <math.h>
2+
#include <quad_tile.h>
3+
#include <postgres.h>
4+
#include <fmgr.h>
5+
6+
Datum
7+
tile_for_point(PG_FUNCTION_ARGS)
8+
{
9+
double lat = PG_GETARG_INT32(0) / 10000000.0;
10+
double lon = PG_GETARG_INT32(1) / 10000000.0;
11+
12+
PG_RETURN_INT64(xy2tile(lon2x(lon), lat2y(lat)));
13+
}
14+
15+
PG_FUNCTION_INFO_V1(tile_for_point);
16+
17+
/*
18+
* To bind this into PGSQL, try something like:
19+
*
20+
* CREATE FUNCTION tile_for_point(int4, int4) RETURNS int8
21+
* AS '/path/to/rails-port/db/functions/libpgosm', 'tile_for_point'
22+
* LANGUAGE C STRICT;
23+
*
24+
* (without all the *s)
25+
*/

images/db/functions/xid_to_int4.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
#include <postgres.h>
3+
#include <fmgr.h>
4+
5+
Datum
6+
xid_to_int4(PG_FUNCTION_ARGS)
7+
{
8+
TransactionId xid = PG_GETARG_INT32(0);
9+
10+
PG_RETURN_INT32(xid);
11+
}
12+
13+
PG_FUNCTION_INFO_V1(xid_to_int4);
14+
15+
/*
16+
* To bind this into PGSQL, try something like:
17+
*
18+
* CREATE FUNCTION xid_to_int4(xid) RETURNS int4
19+
* AS '/path/to/rails-port/db/functions/libpgosm', 'xid_to_int4'
20+
* LANGUAGE C IMMUTABLE STRICT;
21+
*
22+
* (without all the *s)
23+
*/

images/db/lib/quad_tile/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Makefile
2+
quad_tile.o
3+
quad_tile_so.so

images/db/lib/quad_tile/extconf.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
require "mkmf"
2+
3+
with_cflags("-std=c99 #{$CFLAGS}") do
4+
create_makefile("quad_tile_so")
5+
end

images/db/lib/quad_tile/quad_tile.c

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#include "ruby.h"
2+
#include "quad_tile.h"
3+
4+
typedef struct {
5+
unsigned int *tilev;
6+
unsigned int tilec;
7+
} tilelist_t;
8+
9+
static tilelist_t tilelist_for_area(unsigned int minx, unsigned int miny, unsigned int maxx, unsigned int maxy)
10+
{
11+
unsigned int x;
12+
unsigned int y;
13+
tilelist_t tl;
14+
unsigned int maxtilec;
15+
16+
maxtilec = 256;
17+
18+
tl.tilev = malloc(maxtilec * sizeof(unsigned int));
19+
tl.tilec = 0;
20+
21+
for (x = minx; x <= maxx; x++)
22+
{
23+
for (y = miny; y <= maxy; y++)
24+
{
25+
if (tl.tilec == maxtilec)
26+
{
27+
maxtilec = maxtilec * 2;
28+
29+
tl.tilev = realloc(tl.tilev, maxtilec * sizeof(unsigned int));
30+
}
31+
32+
tl.tilev[tl.tilec++] = xy2tile(x, y);
33+
}
34+
}
35+
36+
return tl;
37+
}
38+
39+
static int tile_compare(const void *ap, const void *bp)
40+
{
41+
unsigned int a = *(unsigned int *)ap;
42+
unsigned int b = *(unsigned int *)bp;
43+
44+
if (a < b)
45+
{
46+
return -1;
47+
}
48+
else if (a > b)
49+
{
50+
return 1;
51+
}
52+
else
53+
{
54+
return 0;
55+
}
56+
}
57+
58+
static VALUE tile_for_point(VALUE self, VALUE lat, VALUE lon)
59+
{
60+
unsigned int x = lon2x(NUM2DBL(lon));
61+
unsigned int y = lat2y(NUM2DBL(lat));
62+
63+
return UINT2NUM(xy2tile(x, y));
64+
}
65+
66+
static VALUE tiles_for_area(VALUE self, VALUE bbox)
67+
{
68+
unsigned int minx = lon2x(NUM2DBL(rb_iv_get(bbox, "@min_lon")));
69+
unsigned int maxx = lon2x(NUM2DBL(rb_iv_get(bbox, "@max_lon")));
70+
unsigned int miny = lat2y(NUM2DBL(rb_iv_get(bbox, "@min_lat")));
71+
unsigned int maxy = lat2y(NUM2DBL(rb_iv_get(bbox, "@max_lat")));
72+
tilelist_t tl = tilelist_for_area(minx, miny, maxx, maxy);
73+
VALUE tiles = rb_ary_new();
74+
unsigned int t;
75+
76+
for (t = 0; t < tl.tilec; t++)
77+
{
78+
rb_ary_push(tiles, UINT2NUM(tl.tilev[tl.tilec]));
79+
}
80+
81+
free(tl.tilev);
82+
83+
return tiles;
84+
}
85+
86+
static VALUE tile_for_xy(VALUE self, VALUE x, VALUE y)
87+
{
88+
return UINT2NUM(xy2tile(NUM2UINT(x), NUM2UINT(y)));
89+
}
90+
91+
static VALUE iterate_tiles_for_area(VALUE self, VALUE bbox)
92+
{
93+
unsigned int minx = lon2x(NUM2DBL(rb_iv_get(bbox, "@min_lon")));
94+
unsigned int maxx = lon2x(NUM2DBL(rb_iv_get(bbox, "@max_lon")));
95+
unsigned int miny = lat2y(NUM2DBL(rb_iv_get(bbox, "@min_lat")));
96+
unsigned int maxy = lat2y(NUM2DBL(rb_iv_get(bbox, "@max_lat")));
97+
tilelist_t tl = tilelist_for_area(minx, miny, maxx, maxy);
98+
99+
if (tl.tilec > 0)
100+
{
101+
unsigned int first;
102+
unsigned int last;
103+
unsigned int t;
104+
VALUE a = rb_ary_new();
105+
106+
qsort(tl.tilev, tl.tilec, sizeof(unsigned int), tile_compare);
107+
108+
first = last = tl.tilev[0];
109+
110+
for (t = 1; t < tl.tilec; t++)
111+
{
112+
unsigned int tile = tl.tilev[t];
113+
114+
if (tile == last + 1)
115+
{
116+
last = tile;
117+
}
118+
else
119+
{
120+
rb_ary_store(a, 0, UINT2NUM(first));
121+
rb_ary_store(a, 1, UINT2NUM(last));
122+
rb_yield(a);
123+
124+
first = last = tile;
125+
}
126+
}
127+
128+
rb_ary_store(a, 0, UINT2NUM(first));
129+
rb_ary_store(a, 1, UINT2NUM(last));
130+
rb_yield(a);
131+
}
132+
133+
free(tl.tilev);
134+
135+
return Qnil;
136+
}
137+
138+
void Init_quad_tile_so(void)
139+
{
140+
VALUE m = rb_define_module("QuadTile");
141+
142+
rb_define_module_function(m, "tile_for_point", tile_for_point, 2);
143+
rb_define_module_function(m, "tiles_for_area", tiles_for_area, 1);
144+
rb_define_module_function(m, "tile_for_xy", tile_for_xy, 2);
145+
rb_define_module_function(m, "iterate_tiles_for_area", iterate_tiles_for_area, 1);
146+
147+
return;
148+
}

images/db/lib/quad_tile/quad_tile.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <math.h>
2+
3+
inline unsigned int xy2tile(unsigned int x, unsigned int y)
4+
{
5+
unsigned int tile = 0;
6+
int i;
7+
8+
for (i = 15; i >= 0; i--)
9+
{
10+
tile = (tile << 1) | ((x >> i) & 1);
11+
tile = (tile << 1) | ((y >> i) & 1);
12+
}
13+
14+
return tile;
15+
}
16+
17+
inline unsigned int lon2x(double lon)
18+
{
19+
return round((lon + 180.0) * 65535.0 / 360.0);
20+
}
21+
22+
inline unsigned int lat2y(double lat)
23+
{
24+
return round((lat + 90.0) * 65535.0 / 180.0);
25+
}

0 commit comments

Comments
 (0)