Make changes for 0.5.

This commit is contained in:
Gabriel Ebner
2007-10-07 11:24:01 +00:00
parent 49baa4104a
commit ee4f3db1d1
9 changed files with 221 additions and 541 deletions

View File

@ -36,9 +36,11 @@
#include <geos/geom/Point.h> #include <geos/geom/Point.h>
#include <geos/io/WKTReader.h> #include <geos/io/WKTReader.h>
#include <geos/io/WKTWriter.h> #include <geos/io/WKTWriter.h>
#include <geos/util/GEOSException.h>
#include <geos/opLinemerge.h> #include <geos/opLinemerge.h>
using namespace geos::geom; using namespace geos::geom;
using namespace geos::io; using namespace geos::io;
using namespace geos::util;
using namespace geos::operation::linemerge; using namespace geos::operation::linemerge;
#else #else
/* geos-2.2.3 */ /* geos-2.2.3 */
@ -50,187 +52,39 @@ using namespace geos;
#include "build_geometry.h" #include "build_geometry.h"
typedef std::auto_ptr<Geometry> geom_ptr; using namespace std;
struct Segment char *get_wkt(osmNode *nodes, int count, int polygon, double *area) {
{ GeometryFactory gf;
Segment(double x0_,double y0_,double x1_,double y1_)
:x0(x0_),y0(y0_),x1(x1_),y1(y1_) {}
double x0; auto_ptr<CoordinateSequence> coords(
double y0; gf.getCoordinateSequenceFactory()->create(0, 2));
double x1; for (int i = 0; i < count; i++) {
double y1; Coordinate c;
}; c.x = nodes[i].lon;
c.y = nodes[i].lat;
coords->add(c, i);
}
struct Interior auto_ptr<Geometry> geom;
{ if (polygon) {
Interior(double x_, double y_) if (coords->getSize() < 4 ||
: x(x_), y(y_) {} !coords->getAt(coords->getSize() - 1).equals2D(coords->getAt(0))) {
return 0;
Interior(Geometry *geom) {
try {
std::auto_ptr<Point> pt(geom->getInteriorPoint());
x = pt->getX();
y = pt->getY();
} catch (...) {
// This happens on some unusual polygons, we'll ignore them for now
//std::cerr << std::endl << "Exception finding interior point" << std::endl;
x=y=0.0;
}
}
double x, y;
};
static std::vector<Segment> segs;
static std::vector<std::string> wkts;
static std::vector<Interior> interiors;
static std::vector<double> areas;
int is_simple(const char* wkt)
{
GeometryFactory factory;
WKTReader reader(&factory);
geom_ptr geom(reader.read(wkt));
if (geom->isSimple()) return 1;
return 0;
}
void add_segment(double x0,double y0,double x1,double y1)
{
segs.push_back(Segment(x0,y0,x1,y1));
}
char * get_wkt(size_t index)
{
// return wkts[index].c_str();
char *result;
result = (char*) std::malloc( wkts[index].length() + 1);
std::strcpy(result, wkts[index].c_str() );
return result;
}
void get_interior(size_t index, double *y, double *x)
{
*x = interiors[index].x;
*y = interiors[index].y;
}
double get_area(size_t index)
{
return areas[index];
}
void clear_wkts()
{
wkts.clear();
interiors.clear();
areas.clear();
}
size_t build_geometry(int polygon, int osm_id)
{
size_t wkt_size = 0;
GeometryFactory factory;
geom_ptr segment(0);
std::auto_ptr<std::vector<Geometry*> > lines(new std::vector<Geometry*>);
std::vector<Segment>::const_iterator pos=segs.begin();
std::vector<Segment>::const_iterator end=segs.end();
bool first=true;
try {
while (pos != end)
{
if (pos->x0 != pos->x1 || pos->y0 != pos->y1)
{
std::auto_ptr<CoordinateSequence> coords(factory.getCoordinateSequenceFactory()->create(0,2));
coords->add(Coordinate(pos->x0,pos->y0));
coords->add(Coordinate(pos->x1,pos->y1));
geom_ptr linestring(factory.createLineString(coords.release()));
if (first)
{
segment = linestring;
first=false;
}
else
{
lines->push_back(linestring.release());
}
}
++pos;
}
segs.clear();
if (segment.get())
{
geom_ptr mline (factory.createMultiLineString(lines.release()));
geom_ptr noded (segment->Union(mline.get()));
LineMerger merger;
merger.add(noded.get());
std::auto_ptr<std::vector<LineString *> > merged(merger.getMergedLineStrings());
WKTWriter writer;
if (polygon)
{
std::auto_ptr<LinearRing> exterior;
std::auto_ptr<std::vector<Geometry*> > interior(new std::vector<Geometry*>);
double ext_area = 0.0;
for (unsigned i=0 ;i < merged->size(); ++i)
{
std::auto_ptr<LineString> pline ((*merged ) [i]);
if (pline->getNumPoints() > 3 && pline->isClosed())
{
std::auto_ptr<LinearRing> ring(factory.createLinearRing(pline->getCoordinates()));
std::auto_ptr<Polygon> poly(factory.createPolygon(factory.createLinearRing(pline->getCoordinates()),0));
double poly_area = poly->getArea();
if (poly_area > ext_area) {
if (ext_area > 0.0)
interior->push_back(exterior.release());
ext_area = poly_area;
exterior = ring;
//std::cerr << "Found bigger ring, area(" << ext_area << ") " << writer.write(poly.get()) << std::endl;
} else {
interior->push_back(ring.release());
//std::cerr << "Found inner ring, area(" << poly->getArea() << ") " << writer.write(poly.get()) << std::endl;
}
} else {
//std::cerr << "polygon(" << osm_id << ") is no good: points(" << pline->getNumPoints() << "), closed(" << pline->isClosed() << "). " << writer.write(pline.get()) << std::endl;
std::string text = writer.write(pline.get());
wkts.push_back(text);
interiors.push_back(Interior(0,0));
areas.push_back(0.0);
wkt_size++;
}
}
if (ext_area > 0.0) {
std::auto_ptr<Polygon> poly(factory.createPolygon(exterior.release(), interior.release()));
std::string text = writer.write(poly.get());
//std::cerr << "Result: area(" << poly->getArea() << ") " << writer.write(poly.get()) << std::endl;
wkts.push_back(text);
interiors.push_back(Interior(poly.get()));
areas.push_back(ext_area);
wkt_size++;
}
} else {
for (unsigned i=0 ;i < merged->size(); ++i)
{
std::auto_ptr<LineString> pline ((*merged ) [i]);
std::string text = writer.write(pline.get());
wkts.push_back(text);
interiors.push_back(Interior(0,0));
areas.push_back(0.0);
++wkt_size;
}
}
}
} }
catch (...) auto_ptr<LinearRing> shell(gf.createLinearRing(coords.release()));
{ geom = auto_ptr<Geometry>(gf.createPolygon(shell.release(),
std::cerr << std::endl << "excepton caught processing way id=" << osm_id << std::endl; new vector<Geometry *>));
wkt_size = 0; *area = geom->getArea();
} else {
if (coords->getSize() < 2) {
return 0;
} }
return wkt_size; geom = auto_ptr<Geometry>(gf.createLineString(coords.release()));
} *area = 0;
}
WKTWriter wktw;
string wkt = wktw.write(geom.get());
return strdup(wkt.c_str());
}

View File

@ -27,13 +27,9 @@
extern "C" { extern "C" {
#endif #endif
int is_simple(const char* wkt); #include "osmtypes.h"
void add_segment(double x0,double y0,double x1, double y1);
char* get_wkt(size_t index); char *get_wkt(struct osmNode *, int count, int polygon, double *area);
void get_interior(size_t index, double *y, double *x);
double get_area(size_t index);
size_t build_geometry(int polygon, int osm_id);
void clear_wkts();
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -24,7 +24,7 @@
static char conninfo[256]; static char conninfo[256];
enum table_id { enum table_id {
t_node, t_segment, t_node_tag, t_way_tag, t_way_seg t_node, t_node_tag, t_way_tag, t_way_nd
} ; } ;
struct table_desc { struct table_desc {
@ -50,17 +50,6 @@ static struct table_desc tables [] = {
analyze: "ANALYZE nodes;\n", analyze: "ANALYZE nodes;\n",
stop: "COMMIT;\n" stop: "COMMIT;\n"
}, },
{
//table: t_segment,
name: "segments",
start: "BEGIN;\n",
create: "CREATE TABLE segments (\"id\" int4 PRIMARY KEY,\"from\" int4,\"to\" int4);\n",
prepare: "PREPARE insert_segment (int4, int4, int4) AS INSERT INTO segments VALUES ($1,$2,$3);\n"
"PREPARE get_segment (int4) AS SELECT \"from\",\"to\" FROM segments WHERE \"id\" = $1 LIMIT 1;\n",
copy: "COPY segments FROM STDIN;\n",
analyze: "ANALYZE segments;\n",
stop: "COMMIT;\n"
},
{ {
//table: t_node_tag, //table: t_node_tag,
name: "node_tag", name: "node_tag",
@ -88,15 +77,15 @@ static struct table_desc tables [] = {
stop: "COMMIT;\n" stop: "COMMIT;\n"
}, },
{ {
//table: t_way_seg, //table: t_way_nd,
name: "way_seg", name: "way_nd",
start: "BEGIN;\n", start: "BEGIN;\n",
create: "CREATE TABLE way_seg (\"id\" int4 NOT NULL, \"seg_id\" int4);\n" create: "CREATE TABLE way_nd (\"id\" int4 NOT NULL, \"nd_id\" int4);\n"
"CREATE INDEX way_seg_idx ON way_seg (\"id\");\n", "CREATE INDEX way_nd_idx ON way_nd (\"id\");\n",
prepare: "PREPARE insert_way_seg (int4, int4) AS INSERT INTO way_seg VALUES ($1,$2);\n" prepare: "PREPARE insert_way_nd (int4, int4) AS INSERT INTO way_nd VALUES ($1,$2);\n"
"PREPARE get_way_seg (int4) AS SELECT \"seg_id\" FROM way_seg WHERE \"id\" = $1;\n", "PREPARE get_way_nd (int4) AS SELECT \"nd_id\" FROM way_nd WHERE \"id\" = $1;\n",
copy: "COPY way_seg FROM STDIN;\n", copy: "COPY way_nd FROM STDIN;\n",
analyze: "ANALYZE way_seg;\n", analyze: "ANALYZE way_nd;\n",
stop: "COMMIT;\n" stop: "COMMIT;\n"
} }
}; };
@ -268,59 +257,13 @@ static int pgsql_nodes_get(struct osmNode *out, int id)
return 0; return 0;
} }
static int pgsql_segments_set(int id, int from, int to, struct keyval *tags) static void psql_add_way_nd(int way_id, int nd_id)
{ {
PGconn *sql_conn = sql_conns[t_segment]; PGconn *sql_conn = sql_conns[t_way_nd];
char sql[128]; char sql[128];
int r; int r;
sprintf(sql, "%d\t%d\t%d\n", id, from, to); sprintf(sql, "%d\t%d\n", way_id, nd_id);
r = PQputCopyData(sql_conn, sql, strlen(sql));
if (r != 1) {
fprintf(stderr, "%s - bad result %d, line %s\n", __FUNCTION__, r, sql);
exit_nicely();
}
resetList(tags);
return 0;
}
static int pgsql_segments_get(struct osmSegment *out, int id)
{
PGresult *res;
char tmp[16];
char const *paramValues[1];
PGconn *sql_conn = sql_conns[t_segment];
snprintf(tmp, sizeof(tmp), "%d", id);
paramValues[0] = tmp;
res = PQexecPrepared(sql_conn, "get_segment", 1, paramValues, NULL, NULL, 0);
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
fprintf(stderr, "get_segment failed: %s(%d)\n", PQerrorMessage(sql_conn), PQresultStatus(res));
PQclear(res);
exit_nicely();
}
if (PQntuples(res) != 1) {
PQclear(res);
return 1;
}
out->from = strtol(PQgetvalue(res, 0, 0), NULL, 10);
out->to = strtol(PQgetvalue(res, 0, 1), NULL, 10);
PQclear(res);
return 0;
}
static void psql_add_way_seg(int way_id, int seg_id)
{
PGconn *sql_conn = sql_conns[t_way_seg];
char sql[128];
int r;
sprintf(sql, "%d\t%d\n", way_id, seg_id);
r = PQputCopyData(sql_conn, sql, strlen(sql)); r = PQputCopyData(sql_conn, sql, strlen(sql));
if (r != 1) { if (r != 1) {
fprintf(stderr, "%s - bad result %d, line %s\n", __FUNCTION__, r, sql); fprintf(stderr, "%s - bad result %d, line %s\n", __FUNCTION__, r, sql);
@ -329,14 +272,14 @@ static void psql_add_way_seg(int way_id, int seg_id)
} }
static int pgsql_ways_set(int way_id, struct keyval *segs, struct keyval *tags) static int pgsql_ways_set(int way_id, struct keyval *nds, struct keyval *tags)
{ {
#if 1 #if 1
struct keyval *p; struct keyval *p;
while((p = popItem(segs)) != NULL) { while((p = popItem(nds)) != NULL) {
int seg_id = strtol(p->value, NULL, 10); int nd_id = strtol(p->value, NULL, 10);
psql_add_way_seg(way_id, seg_id); psql_add_way_nd(way_id, nd_id);
freeItem(p); freeItem(p);
} }
@ -346,9 +289,9 @@ static int pgsql_ways_set(int way_id, struct keyval *segs, struct keyval *tags)
} }
#else #else
// FIXME: Performance hack - output ways directly. Doesn't work in COPY model // FIXME: Performance hack - output ways directly. Doesn't work in COPY model
out_pgsql.way(&mid_pgsql, way_id, tags, segs); out_pgsql.way(&mid_pgsql, way_id, tags, nds);
resetList(tags); resetList(tags);
resetList(segs); resetList(nds);
#endif #endif
return 0; return 0;
} }
@ -412,49 +355,6 @@ static void pgsql_iterate_nodes(int (*callback)(int id, struct keyval *tags, dou
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
#if 0
static struct osmSegLL *getSegLL(struct keyval *segs, int *segCount)
{
struct keyval *p;
struct osmSegment segment;
struct osmNode node;
int id;
int count = 0;
struct osmSegLL *segll = malloc(countList(segs) * sizeof(struct osmSegLL));
if (!segll) {
resetList(segs);
*segCount = 0;
return NULL;
}
while ((p = popItem(segs)) != NULL)
{
id = strtol(p->value, NULL, 10);
freeItem(p);
if (pgsql_segments_get(&segment, id))
continue;
if (pgsql_nodes_get(&node, segment.from))
continue;
segll[count].lon0 = node.lon;
segll[count].lat0 = node.lat;
if (pgsql_nodes_get(&node, segment.to))
continue;
segll[count].lon1 = node.lon;
segll[count].lat1 = node.lat;
count++;
}
*segCount = count;
return segll;
}
#endif
void getTags(int id, struct keyval *tags) void getTags(int id, struct keyval *tags)
{ {
PGconn *sql_conn_tags = sql_conns[t_way_tag]; PGconn *sql_conn_tags = sql_conns[t_way_tag];
@ -482,14 +382,14 @@ void getTags(int id, struct keyval *tags)
} }
static void pgsql_iterate_ways(int (*callback)(int id, struct keyval *tags, struct osmSegLL *segll, int count)) static void pgsql_iterate_ways(int (*callback)(int id, struct keyval *tags, struct osmNode *nodes, int count))
{ {
char sql[2048]; char sql[2048];
PGresult *res_ways, *res_nodes; PGresult *res_ways, *res_nodes;
int i, j, count = 0; int i, j, count = 0;
struct keyval tags; struct keyval tags;
struct osmSegLL *segll; struct osmNode *nodes;
PGconn *sql_conn_segs = sql_conns[t_way_seg]; PGconn *sql_conn_nds = sql_conns[t_way_nd];
initList(&tags); initList(&tags);
@ -504,9 +404,9 @@ gis=> select w.id,s.id,nf.lat,nf.lon,nt.lat,nt.lon from way_seg as w,nodes as nf
3186577 | 10872310 | 51.721258 | -0.359137 | 51.720979 | -0.360532 3186577 | 10872310 | 51.721258 | -0.359137 | 51.720979 | -0.360532
*/ */
res_ways = PQexec(sql_conn_segs, "SELECT id from way_seg GROUP BY id"); res_ways = PQexec(sql_conn_nds, "SELECT id from way_nd GROUP BY id");
if (PQresultStatus(res_ways) != PGRES_TUPLES_OK) { if (PQresultStatus(res_ways) != PGRES_TUPLES_OK) {
fprintf(stderr, "%s(%d) failed: %s\n", __FUNCTION__, __LINE__, PQerrorMessage(sql_conn_segs)); fprintf(stderr, "%s(%d) failed: %s\n", __FUNCTION__, __LINE__, PQerrorMessage(sql_conn_nds));
PQclear(res_ways); PQclear(res_ways);
exit_nicely(); exit_nicely();
} }
@ -514,36 +414,33 @@ gis=> select w.id,s.id,nf.lat,nf.lon,nt.lat,nt.lon from way_seg as w,nodes as nf
//fprintf(stderr, "\nIterating ways\n"); //fprintf(stderr, "\nIterating ways\n");
for (i = 0; i < PQntuples(res_ways); i++) { for (i = 0; i < PQntuples(res_ways); i++) {
int id = strtol(PQgetvalue(res_ways, i, 0), NULL, 10); int id = strtol(PQgetvalue(res_ways, i, 0), NULL, 10);
int segCount; int ndCount;
if (count++ %1000 == 0) if (count++ %1000 == 0)
fprintf(stderr, "\rprocessing way (%dk)", count/1000); fprintf(stderr, "\rprocessing way (%dk)", count/1000);
getTags(id, &tags); getTags(id, &tags);
sprintf(sql,"SELECT nf.lat,nf.lon,nt.lat,nt.lon " sprintf(sql,"SELECT n.lat, n.lon FROM way_nd AS w, nodes AS n "
"FROM way_seg AS w,nodes AS nf, nodes AS nt, segments AS s " "WHERE w.nd_id = n.id AND w.id=%d", id);
"WHERE w.seg_id=s.id AND nf.id=s.from AND nt.id=s.to AND w.id=%d", id);
res_nodes = PQexec(sql_conn_segs, sql); res_nodes = PQexec(sql_conn_nds, sql);
if (PQresultStatus(res_nodes) != PGRES_TUPLES_OK) { if (PQresultStatus(res_nodes) != PGRES_TUPLES_OK) {
fprintf(stderr, "%s(%d) failed: %s\n", __FUNCTION__, __LINE__, PQerrorMessage(sql_conn_segs)); fprintf(stderr, "%s(%d) failed: %s\n", __FUNCTION__, __LINE__, PQerrorMessage(sql_conn_nds));
PQclear(res_nodes); PQclear(res_nodes);
exit_nicely(); exit_nicely();
} }
segCount = PQntuples(res_nodes); ndCount = PQntuples(res_nodes);
segll = malloc(segCount * sizeof(struct osmSegLL)); nodes = malloc(ndCount * sizeof(struct osmNode));
if (segll) { if (nodes) {
for (j=0; j<segCount; j++) { for (j=0; j<ndCount; j++) {
segll[j].lat0 = strtod(PQgetvalue(res_nodes, j, 0), NULL); nodes[j].lat = strtod(PQgetvalue(res_nodes, j, 0), NULL);
segll[j].lon0 = strtod(PQgetvalue(res_nodes, j, 1), NULL); nodes[j].lon = strtod(PQgetvalue(res_nodes, j, 1), NULL);
segll[j].lat1 = strtod(PQgetvalue(res_nodes, j, 2), NULL);
segll[j].lon1 = strtod(PQgetvalue(res_nodes, j, 3), NULL);
} }
callback(id, &tags, segll, segCount); callback(id, &tags, nodes, ndCount);
free(segll); free(nodes);
} }
PQclear(res_nodes); PQclear(res_nodes);
resetList(&tags); resetList(&tags);
@ -725,8 +622,6 @@ struct middle_t mid_pgsql = {
cleanup: pgsql_cleanup, cleanup: pgsql_cleanup,
analyze: pgsql_analyze, analyze: pgsql_analyze,
end: pgsql_end, end: pgsql_end,
segments_set: pgsql_segments_set,
segments_get: pgsql_segments_get,
nodes_set: pgsql_nodes_set, nodes_set: pgsql_nodes_set,
nodes_get: pgsql_nodes_get, nodes_get: pgsql_nodes_get,
ways_set: pgsql_ways_set, ways_set: pgsql_ways_set,

View File

@ -38,14 +38,9 @@ struct ramNode {
#endif #endif
}; };
struct ramSegment {
int from;
int to;
};
struct ramWay { struct ramWay {
struct keyval *tags; struct keyval *tags;
int *segids; int *ndids;
}; };
/* Object storage now uses 2 levels of storage arrays. /* Object storage now uses 2 levels of storage arrays.
@ -67,17 +62,16 @@ struct ramWay {
#define NUM_BLOCKS (1 << (32 - BLOCK_SHIFT)) #define NUM_BLOCKS (1 << (32 - BLOCK_SHIFT))
static struct ramNode *nodes[NUM_BLOCKS]; static struct ramNode *nodes[NUM_BLOCKS];
static struct ramSegment *segments[NUM_BLOCKS];
static struct ramWay *ways[NUM_BLOCKS]; static struct ramWay *ways[NUM_BLOCKS];
static int node_blocks, segment_blocks; static int node_blocks;
#ifdef USE_CLEAN #ifdef USE_CLEAN
static int way_blocks; static int way_blocks;
#endif #endif
static int way_out_count; static int way_out_count;
static struct osmSegLL *getSegLL(int *segids, int *segCount); static struct osmNode *getNodes(int *ndids, int *ndCount);
static inline int id2block(int id) static inline int id2block(int id)
{ {
@ -151,53 +145,16 @@ static int ram_nodes_get(struct osmNode *out, int id)
return 0; return 0;
} }
static int ram_segments_set(int id, int from, int to, struct keyval *tags) static int ram_ways_set(int id, struct keyval *nds, struct keyval *tags)
{
int block = id2block(id);
int offset = id2offset(id);
if (!segments[block]) {
segments[block] = calloc(PER_BLOCK, sizeof(struct ramSegment));
if (!segments[block]) {
fprintf(stderr, "Error allocating segments\n");
exit_nicely();
}
segment_blocks++;
//fprintf(stderr, "\tsegments(%zuMb)\n", segment_blocks * sizeof(struct ramSegment) * PER_BLOCK / 1000000);
}
segments[block][offset].from = from;
segments[block][offset].to = to;
resetList(tags);
return 0;
}
static int ram_segments_get(struct osmSegment *out, int id)
{
int block = id2block(id);
int offset = id2offset(id);
if (!segments[block])
return 1;
if (!segments[block][offset].from && !segments[block][offset].to)
return 1;
out->from = segments[block][offset].from;
out->to = segments[block][offset].to;
return 0;
}
static int ram_ways_set(int id, struct keyval *segs, struct keyval *tags)
{ {
struct keyval *p; struct keyval *p;
int *segids; int *ndids;
int segCount, i; int ndCount, i;
#ifdef USE_CLEAN #ifdef USE_CLEAN
int block = id2block(id); int block = id2block(id);
int offset = id2offset(id); int offset = id2offset(id);
#else #else
struct osmSegLL *segll; struct osmNode *nodes;
#endif #endif
#ifdef USE_CLEAN #ifdef USE_CLEAN
@ -211,33 +168,37 @@ static int ram_ways_set(int id, struct keyval *segs, struct keyval *tags)
//fprintf(stderr, "\tways(%zuMb)\n", way_blocks * sizeof(struct ramWay) * PER_BLOCK / 1000000); //fprintf(stderr, "\tways(%zuMb)\n", way_blocks * sizeof(struct ramWay) * PER_BLOCK / 1000000);
} }
if (ways[block][offset].segids) { ndCount = countList(nds);
free(ways[block][offset].segids); if (!ndCount)
ways[block][offset].segids = NULL; return 1;
if (ways[block][offset].ndids) {
free(ways[block][offset].ndids);
ways[block][offset].ndids = NULL;
} }
#endif #endif
segCount = countList(segs); ndCount = countList(nds);
if (!segCount) if (!ndCount)
return 1; return 1;
segids = malloc(sizeof(int) * (segCount+1)); ndids = malloc(sizeof(int) * (ndCount+1));
if (!segids) { if (!ndids) {
fprintf(stderr, "%s malloc failed\n", __FUNCTION__); fprintf(stderr, "%s malloc failed\n", __FUNCTION__);
exit_nicely(); exit_nicely();
} }
#ifdef USE_CLEAN #ifdef USE_CLEAN
ways[block][offset].segids = segids; ways[block][offset].ndids = ndids;
#endif #endif
i = 0; i = 0;
while ((p = popItem(segs)) != NULL) { while ((p = popItem(nds)) != NULL) {
int seg_id = strtol(p->value, NULL, 10); int nd_id = strtol(p->value, NULL, 10);
freeItem(p); freeItem(p);
if (seg_id) /* id = 0 is used as list terminator */ if (nd_id) /* id = 0 is used as list terminator */
segids[i++] = seg_id; ndids[i++] = nd_id;
} }
segids[i] = 0; ndids[i] = 0;
#ifdef USE_CLEAN #ifdef USE_CLEAN
if (!ways[block][offset].tags) { if (!ways[block][offset].tags) {
p = malloc(sizeof(struct keyval)); p = malloc(sizeof(struct keyval));
@ -254,65 +215,51 @@ static int ram_ways_set(int id, struct keyval *segs, struct keyval *tags)
while ((p = popItem(tags)) != NULL) while ((p = popItem(tags)) != NULL)
pushItem(ways[block][offset].tags, p); pushItem(ways[block][offset].tags, p);
#else #else
segll = getSegLL(segids, &segCount); nodes = getNodes(ndids, &ndCount);
free(segids); free(ndids);
if (segll) { if (nodes) {
out_pgsql.way(id, tags, segll, segCount); out_pgsql.way(id, tags, nodes, ndCount);
free(segll); free(nodes);
} }
#endif #endif
return 0; return 0;
} }
static struct osmSegLL *getSegLL(int *segids, int *segCount) static struct osmNode *getNodes(int *ndids, int *ndCount)
{ {
struct osmSegment segment;
struct osmNode node;
int id; int id;
int i, count = 0; int i, count = 0;
struct osmSegLL *segll; struct osmNode *nodes;
while(segids[count]) while(ndids[count])
count++; count++;
segll = malloc(count * sizeof(struct osmSegLL)); nodes = malloc(count * sizeof(struct osmNode));
if (!segll) { if (!nodes) {
*segCount = 0; *ndCount = 0;
return NULL; return NULL;
} }
count = 0; count = 0;
i = 0; i = 0;
while ((id = segids[i++]) != 0) while ((id = ndids[i++]) != 0)
{ {
if (ram_segments_get(&segment, id)) if (ram_nodes_get(&nodes[count], id))
continue; continue;
if (ram_nodes_get(&node, segment.from))
continue;
segll[count].lon0 = node.lon;
segll[count].lat0 = node.lat;
if (ram_nodes_get(&node, segment.to))
continue;
segll[count].lon1 = node.lon;
segll[count].lat1 = node.lat;
count++; count++;
} }
*segCount = count; *ndCount = count;
return segll; return nodes;
} }
static void ram_iterate_ways(int (*callback)(int id, struct keyval *tags, struct osmSegLL *segll, int count)) static void ram_iterate_ways(int (*callback)(int id, struct keyval *tags, struct osmNode *nodes, int count))
{ {
int block, offset, segCount = 0; int block, offset, ndCount = 0;
struct osmSegLL *segll; struct osmNode *nodes;
fprintf(stderr, "\n"); fprintf(stderr, "\n");
for(block=NUM_BLOCKS-1; block>=0; block--) { for(block=NUM_BLOCKS-1; block>=0; block--) {
@ -320,17 +267,17 @@ static void ram_iterate_ways(int (*callback)(int id, struct keyval *tags, struct
continue; continue;
for (offset=0; offset < PER_BLOCK; offset++) { for (offset=0; offset < PER_BLOCK; offset++) {
if (ways[block][offset].segids) { if (ways[block][offset].ndids) {
way_out_count++; way_out_count++;
if (way_out_count % 1000 == 0) if (way_out_count % 1000 == 0)
fprintf(stderr, "\rWriting way(%uk)", way_out_count/1000); fprintf(stderr, "\rWriting way(%uk)", way_out_count/1000);
segll = getSegLL(ways[block][offset].segids, &segCount); nodes = getNodes(ways[block][offset].ndids, &ndCount);
if (segll) { if (nodes) {
int id = block2id(block, offset); int id = block2id(block, offset);
callback(id, ways[block][offset].tags, segll, segCount); callback(id, ways[block][offset].tags, nodes, ndCount);
free(segll); free(nodes);
} }
if (ways[block][offset].tags) { if (ways[block][offset].tags) {
@ -338,9 +285,9 @@ static void ram_iterate_ways(int (*callback)(int id, struct keyval *tags, struct
free(ways[block][offset].tags); free(ways[block][offset].tags);
ways[block][offset].tags = NULL; ways[block][offset].tags = NULL;
} }
if (ways[block][offset].segids) { if (ways[block][offset].ndids) {
free(ways[block][offset].segids); free(ways[block][offset].ndids);
ways[block][offset].segids = NULL; ways[block][offset].ndids = NULL;
} }
} }
} }
@ -378,18 +325,14 @@ static void ram_stop(void)
free(nodes[i]); free(nodes[i]);
nodes[i] = NULL; nodes[i] = NULL;
} }
if (segments[i]) {
free(segments[i]);
segments[i] = NULL;
}
if (ways[i]) { if (ways[i]) {
for (j=0; j<PER_BLOCK; j++) { for (j=0; j<PER_BLOCK; j++) {
if (ways[i][j].tags) { if (ways[i][j].tags) {
resetList(ways[i][j].tags); resetList(ways[i][j].tags);
free(ways[i][j].tags); free(ways[i][j].tags);
} }
if (ways[i][j].segids) if (ways[i][j].ndids)
free(ways[i][j].segids); free(ways[i][j].ndids);
} }
free(ways[i]); free(ways[i]);
ways[i] = NULL; ways[i] = NULL;
@ -403,8 +346,6 @@ struct middle_t mid_ram = {
end: ram_end, end: ram_end,
cleanup: ram_stop, cleanup: ram_stop,
analyze: ram_analyze, analyze: ram_analyze,
segments_set: ram_segments_set,
segments_get: ram_segments_get,
nodes_set: ram_nodes_set, nodes_set: ram_nodes_set,
nodes_get: ram_nodes_get, nodes_get: ram_nodes_get,
ways_set: ram_ways_set, ways_set: ram_ways_set,

View File

@ -1,7 +1,7 @@
/* Common middle layer interface */ /* Common middle layer interface */
/* Each middle layer data store must provide methods for /* Each middle layer data store must provide methods for
* storing and retrieving node, segment and way data. * storing and retrieving node and way data.
*/ */
#ifndef MIDDLE_H #ifndef MIDDLE_H
@ -15,14 +15,12 @@ struct middle_t {
void (*cleanup)(void); void (*cleanup)(void);
void (*analyze)(void); void (*analyze)(void);
void (*end)(void); void (*end)(void);
int (*segments_set)(int id, int from, int to, struct keyval *tags);
int (*segments_get)(struct osmSegment *out, int id);
int (*nodes_set)(int id, double lat, double lon, struct keyval *tags); int (*nodes_set)(int id, double lat, double lon, struct keyval *tags);
int (*nodes_get)(struct osmNode *out, int id); int (*nodes_get)(struct osmNode *out, int id);
int (*ways_set)(int id, struct keyval *segs, struct keyval *tags); int (*ways_set)(int id, struct keyval *segs, struct keyval *tags);
int *(*ways_get)(int id); int *(*ways_get)(int id);
void (*iterate_nodes)(int (*callback)(int id, struct keyval *tags, double node_lat, double node_lon)); void (*iterate_nodes)(int (*callback)(int id, struct keyval *tags, double node_lat, double node_lon));
void (*iterate_ways)(int (*callback)(int id, struct keyval *tags, struct osmSegLL *segll, int count)); void (*iterate_ways)(int (*callback)(int id, struct keyval *tags, struct osmNode *nodes, int count));
}; };
#endif #endif

View File

@ -46,20 +46,18 @@
#include "input.h" #include "input.h"
static int count_node, max_node; static int count_node, max_node;
static int count_segment, max_segment;
static int count_way, max_way; static int count_way, max_way;
static int count_way_seg; static int count_rel, max_rel;
struct middle_t *mid; struct middle_t *mid;
struct output_t *out; struct output_t *out;
/* Since {node,segment,way} elements are not nested we can guarantee the /* Since {node,way} elements are not nested we can guarantee the
values in an end tag must match those of the corresponding values in an end tag must match those of the corresponding
start tag and can therefore be cached. start tag and can therefore be cached.
*/ */
static double node_lon, node_lat; static double node_lon, node_lat;
static int seg_to, seg_from; static struct keyval tags, nds, members;
static struct keyval tags, segs;
static int osm_id; static int osm_id;
int verbose; int verbose;
@ -67,14 +65,15 @@ int latlong;
static void printStatus(void) static void printStatus(void)
{ {
fprintf(stderr, "\rProcessing: Node(%dk) Segment(%dk) Way(%dk)", fprintf(stderr, "\rProcessing: Node(%dk) Way(%dk) Relation(%dk)",
count_node/1000, count_segment/1000, count_way/1000); count_node/1000, count_way/1000, count_rel/1000);
} }
void StartElement(xmlTextReaderPtr reader, const xmlChar *name) void StartElement(xmlTextReaderPtr reader, const xmlChar *name)
{ {
xmlChar *xid, *xlat, *xlon, *xfrom, *xto, *xk, *xv; xmlChar *xid, *xlat, *xlon, *xk, *xv, *xrole, *xtype;
char membtmp[32];
char *k; char *k;
if (xmlStrEqual(name, BAD_CAST "node")) { if (xmlStrEqual(name, BAD_CAST "node")) {
@ -97,25 +96,6 @@ void StartElement(xmlTextReaderPtr reader, const xmlChar *name)
xmlFree(xid); xmlFree(xid);
xmlFree(xlon); xmlFree(xlon);
xmlFree(xlat); xmlFree(xlat);
} else if (xmlStrEqual(name, BAD_CAST "segment")) {
xid = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
xfrom = xmlTextReaderGetAttribute(reader, BAD_CAST "from");
xto = xmlTextReaderGetAttribute(reader, BAD_CAST "to");
assert(xid); assert(xfrom); assert(xto);
osm_id = strtol((char *)xid, NULL, 10);
seg_from = strtol((char *)xfrom, NULL, 10);
seg_to = strtol((char *)xto, NULL, 10);
if (osm_id > max_segment)
max_segment = osm_id;
count_segment++;
if (count_segment%10000 == 0)
printStatus();
xmlFree(xid);
xmlFree(xfrom);
xmlFree(xto);
} else if (xmlStrEqual(name, BAD_CAST "tag")) { } else if (xmlStrEqual(name, BAD_CAST "tag")) {
xk = xmlTextReaderGetAttribute(reader, BAD_CAST "k"); xk = xmlTextReaderGetAttribute(reader, BAD_CAST "k");
assert(xk); assert(xk);
@ -147,14 +127,61 @@ void StartElement(xmlTextReaderPtr reader, const xmlChar *name)
printStatus(); printStatus();
xmlFree(xid); xmlFree(xid);
} else if (xmlStrEqual(name, BAD_CAST "seg")) { } else if (xmlStrEqual(name, BAD_CAST "nd")) {
xid = xmlTextReaderGetAttribute(reader, BAD_CAST "id"); xid = xmlTextReaderGetAttribute(reader, BAD_CAST "ref");
assert(xid); assert(xid);
if (addItem(&segs, "id", (char *)xid, 1)) addItem(&nds, "id", (char *)xid, 0);
count_way_seg++;
xmlFree(xid); xmlFree(xid);
} else if (xmlStrEqual(name, BAD_CAST "relation")) {
xid = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
assert(xid);
osm_id = strtol((char *)xid, NULL, 10);
if (osm_id > max_rel)
max_rel = osm_id;
count_rel++;
if (count_rel%1000 == 0)
printStatus();
xmlFree(xid);
} else if (xmlStrEqual(name, BAD_CAST "member")) {
xrole = xmlTextReaderGetAttribute(reader, BAD_CAST "role");
assert(xrole);
xtype = xmlTextReaderGetAttribute(reader, BAD_CAST "type");
assert(xtype);
xid = xmlTextReaderGetAttribute(reader, BAD_CAST "ref");
assert(xid);
/* The value we insert into the members keyval will be of the form [nwr]$id,
* that way we don't have another data structure and we can switch on the
* first char to figure out the type of the member. */
if (xmlStrEqual(xtype, BAD_CAST "node")) {
membtmp[0] = 'n';
} else if (xmlStrEqual(xtype, BAD_CAST "way")) {
membtmp[0] = 'w';
} else if (xmlStrEqual(xtype, BAD_CAST "relation")) {
membtmp[0] = 'r';
} else {
fprintf(stderr, "%s: Unknown member type: %s\n",
__FUNCTION__, xtype);
membtmp[0] = 0;
}
if (membtmp[0]) {
strncpy(membtmp + 1, (char *) xid, sizeof(membtmp) - 1);
assert(membtmp[sizeof(membtmp) - 1] == 0);
addItem(&members, (char *) xrole, membtmp, 0);
}
xmlFree(xid);
xmlFree(xrole);
xmlFree(xtype);
} else if (xmlStrEqual(name, BAD_CAST "osm")) { } else if (xmlStrEqual(name, BAD_CAST "osm")) {
/* ignore */ /* ignore */
} else if (xmlStrEqual(name, BAD_CAST "bound")) { } else if (xmlStrEqual(name, BAD_CAST "bound")) {
@ -171,17 +198,20 @@ void EndElement(const xmlChar *name)
reproject(&node_lat, &node_lon); reproject(&node_lat, &node_lon);
mid->nodes_set(osm_id, node_lat, node_lon, &tags); mid->nodes_set(osm_id, node_lat, node_lon, &tags);
resetList(&tags); resetList(&tags);
} else if (xmlStrEqual(name, BAD_CAST "segment")) {
mid->segments_set(osm_id, seg_from, seg_to, &tags);
resetList(&tags);
} else if (xmlStrEqual(name, BAD_CAST "way")) { } else if (xmlStrEqual(name, BAD_CAST "way")) {
mid->ways_set(osm_id, &segs, &tags); mid->ways_set(osm_id, &nds, &tags);
resetList(&tags); resetList(&tags);
resetList(&segs); resetList(&nds);
} else if (xmlStrEqual(name, BAD_CAST "relation")) {
/* mid->relations_set(osm_id, &members, &tags); */
resetList(&tags);
resetList(&members);
} else if (xmlStrEqual(name, BAD_CAST "tag")) { } else if (xmlStrEqual(name, BAD_CAST "tag")) {
/* ignore */ /* ignore */
} else if (xmlStrEqual(name, BAD_CAST "seg")) { } else if (xmlStrEqual(name, BAD_CAST "nd")) {
/* ignore */ /* ignore */
} else if (xmlStrEqual(name, BAD_CAST "member")) {
/* ignore */
} else if (xmlStrEqual(name, BAD_CAST "osm")) { } else if (xmlStrEqual(name, BAD_CAST "osm")) {
printStatus(); printStatus();
} else if (xmlStrEqual(name, BAD_CAST "bound")) { } else if (xmlStrEqual(name, BAD_CAST "bound")) {
@ -338,7 +368,12 @@ int main(int argc, char *argv[])
text_init(); text_init();
initList(&tags); initList(&tags);
initList(&segs); initList(&nds);
initList(&members);
count_node = max_node = 0;
count_way = max_way = 0;
count_rel = max_rel = 0;
LIBXML_TEST_VERSION LIBXML_TEST_VERSION
@ -366,12 +401,11 @@ int main(int argc, char *argv[])
xmlCleanupParser(); xmlCleanupParser();
xmlMemoryDump(); xmlMemoryDump();
if (count_node || count_segment || count_way) { if (count_node || count_way || count_rel) {
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "Node stats: total(%d), max(%d)\n", count_node, max_node); fprintf(stderr, "Node stats: total(%d), max(%d)\n", count_node, max_node);
fprintf(stderr, "Segment stats: total(%d), max(%d)\n", count_segment, max_segment);
fprintf(stderr, "Way stats: total(%d), max(%d)\n", count_way, max_way); fprintf(stderr, "Way stats: total(%d), max(%d)\n", count_way, max_way);
//fprintf(stderr, "Way stats: duplicate segments in ways %d\n", count_way_seg); fprintf(stderr, "Relation stats: total(%d), max(%d)\n", count_rel, max_rel);
} }
//fprintf(stderr, "\n\nEnding data import\n"); //fprintf(stderr, "\n\nEnding data import\n");
//out->process(mid); //out->process(mid);

View File

@ -9,18 +9,6 @@ struct osmNode {
double lat; double lat;
}; };
struct osmSegment {
int from;
int to;
};
struct osmSegLL {
double lon0;
double lat0;
double lon1;
double lat1;
};
/* exit_nicely - called to cleanup after fatal error */ /* exit_nicely - called to cleanup after fatal error */
void exit_nicely(void); void exit_nicely(void);

View File

@ -322,23 +322,6 @@ static int pgsql_out_node(int id, struct keyval *tags, double node_lat, double n
static size_t WKT(struct osmSegLL *segll, int count, int polygon, int osm_id)
{
double x0, y0, x1, y1;
int i;
for(i=0; i<count; i++) {
x0 = segll[i].lon0;
y0 = segll[i].lat0;
x1 = segll[i].lon1;
y1 = segll[i].lat1;
add_segment(x0,y0,x1,y1);
}
return build_geometry(polygon, osm_id);
}
static void write_wkts(int id, struct keyval *tags, const char *wkt, PGconn *sql_conn) static void write_wkts(int id, struct keyval *tags, const char *wkt, PGconn *sql_conn)
{ {
unsigned int j; unsigned int j;
@ -364,7 +347,7 @@ static void write_wkts(int id, struct keyval *tags, const char *wkt, PGconn *sql
sql_out(sql_conn, "\n", 1); sql_out(sql_conn, "\n", 1);
} }
void add_parking_node(int id, struct keyval *tags, size_t index) void add_parking_node(int id, struct keyval *tags)
{ {
// insert into planet_osm_point(osm_id,name,amenity,way) select osm_id,name,amenity,centroid(way) from planet_osm_polygon where amenity='parking'; // insert into planet_osm_point(osm_id,name,amenity,way) select osm_id,name,amenity,centroid(way) from planet_osm_polygon where amenity='parking';
const char *amenity = getItem(tags, "amenity"); const char *amenity = getItem(tags, "amenity");
@ -380,8 +363,6 @@ void add_parking_node(int id, struct keyval *tags, size_t index)
if (name) if (name)
addItem(&nodeTags, "name", name, 0); addItem(&nodeTags, "name", name, 0);
get_interior(index, &node_lat, &node_lon);
//fprintf(stderr, "Parking node: %s\t%f,%f\n", name ? name : "no_name", node_lat, node_lon); //fprintf(stderr, "Parking node: %s\t%f,%f\n", name ? name : "no_name", node_lat, node_lon);
pgsql_out_node(id, &nodeTags, node_lat, node_lon); pgsql_out_node(id, &nodeTags, node_lat, node_lon);
@ -397,13 +378,14 @@ E4C1421D5BF24D06053E7DF4940
212696 Oswald Road \N \N \N \N \N \N minor \N \N \N \N \N \N \N 0102000020E610000004000000467D923B6C22D5BFA359D93EE4DF4940B3976DA7AD11D5BF84BBB376DBDF4940997FF44D9A06D5BF4223D8B8FEDF49404D158C4AEA04D 212696 Oswald Road \N \N \N \N \N \N minor \N \N \N \N \N \N \N 0102000020E610000004000000467D923B6C22D5BFA359D93EE4DF4940B3976DA7AD11D5BF84BBB376DBDF4940997FF44D9A06D5BF4223D8B8FEDF49404D158C4AEA04D
5BF5BB39597FCDF4940 5BF5BB39597FCDF4940
*/ */
static int pgsql_out_way(int id, struct keyval *tags, struct osmSegLL *segll, int count) static int pgsql_out_way(int id, struct keyval *tags, struct osmNode *nodes, int count)
{ {
const char *v; const char *v;
unsigned int i; unsigned int i;
size_t wkt_size;
int polygon = 0, export = 0; int polygon = 0, export = 0;
int roads = 0; int roads = 0;
char *wkt;
double area;
for (i=0; i < numTags; i++) { for (i=0; i < numTags; i++) {
if ((v = getItem(tags, exportTags[i].name))) { if ((v = getItem(tags, exportTags[i].name))) {
@ -424,33 +406,25 @@ static int pgsql_out_way(int id, struct keyval *tags, struct osmSegLL *segll, in
fix_motorway_shields(tags); fix_motorway_shields(tags);
wkt_size = WKT(segll, count, polygon, id); wkt = get_wkt(nodes, count, polygon, &area);
if (wkt && strlen(wkt)) {
for (i=0;i<wkt_size;i++) /* FIXME: there should be a better way to detect polygons */
{ if (!strncmp(wkt, "POLYGON", strlen("POLYGON"))) {
char *wkt = get_wkt(i); if (area > 0.0) {
char tmp[32];
if (strlen(wkt)) { snprintf(tmp, sizeof(tmp), "%f", area);
/* FIXME: there should be a better way to detect polygons */ addItem(tags, "way_area", tmp, 0);
if (!strncmp(wkt, "POLYGON", strlen("POLYGON"))) { }
double area = get_area(i); write_wkts(id, tags, wkt, sql_conns[t_poly]);
if (area > 0.0) { add_parking_node(id, tags);
char tmp[32]; } else {
snprintf(tmp, sizeof(tmp), "%f", area); write_wkts(id, tags, wkt, sql_conns[t_line]);
addItem(tags, "way_area", tmp, 0); if (roads)
} write_wkts(id, tags, wkt, sql_conns[t_roads]);
write_wkts(id, tags, wkt, sql_conns[t_poly]);
add_parking_node(id, tags, i);
} else {
write_wkts(id, tags, wkt, sql_conns[t_line]);
if (roads)
write_wkts(id, tags, wkt, sql_conns[t_roads]);
}
} }
free(wkt);
} }
free(wkt);
clear_wkts();
return 0; return 0;
} }

View File

@ -19,7 +19,7 @@ struct output_t {
void (*cleanup)(void); void (*cleanup)(void);
void (*process)(struct middle_t *mid); void (*process)(struct middle_t *mid);
int (*node)(int id, struct keyval *tags, double node_lat, double node_lon); int (*node)(int id, struct keyval *tags, double node_lat, double node_lon);
int (*way)(int id, struct keyval *tags, struct osmSegLL *segll, int count); int (*way)(int id, struct keyval *tags, struct osmNode *nodes, int count);
}; };
#endif #endif