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/io/WKTReader.h>
#include <geos/io/WKTWriter.h>
#include <geos/util/GEOSException.h>
#include <geos/opLinemerge.h>
using namespace geos::geom;
using namespace geos::io;
using namespace geos::util;
using namespace geos::operation::linemerge;
#else
/* geos-2.2.3 */
@ -50,187 +52,39 @@ using namespace geos;
#include "build_geometry.h"
typedef std::auto_ptr<Geometry> geom_ptr;
using namespace std;
struct Segment
{
Segment(double x0_,double y0_,double x1_,double y1_)
:x0(x0_),y0(y0_),x1(x1_),y1(y1_) {}
char *get_wkt(osmNode *nodes, int count, int polygon, double *area) {
GeometryFactory gf;
double x0;
double y0;
double x1;
double y1;
};
auto_ptr<CoordinateSequence> coords(
gf.getCoordinateSequenceFactory()->create(0, 2));
for (int i = 0; i < count; i++) {
Coordinate c;
c.x = nodes[i].lon;
c.y = nodes[i].lat;
coords->add(c, i);
}
struct Interior
{
Interior(double x_, double y_)
: x(x_), y(y_) {}
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;
}
}
}
auto_ptr<Geometry> geom;
if (polygon) {
if (coords->getSize() < 4 ||
!coords->getAt(coords->getSize() - 1).equals2D(coords->getAt(0))) {
return 0;
}
catch (...)
{
std::cerr << std::endl << "excepton caught processing way id=" << osm_id << std::endl;
wkt_size = 0;
auto_ptr<LinearRing> shell(gf.createLinearRing(coords.release()));
geom = auto_ptr<Geometry>(gf.createPolygon(shell.release(),
new vector<Geometry *>));
*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" {
#endif
int is_simple(const char* wkt);
void add_segment(double x0,double y0,double x1, double y1);
char* get_wkt(size_t index);
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();
#include "osmtypes.h"
char *get_wkt(struct osmNode *, int count, int polygon, double *area);
#ifdef __cplusplus
}

View File

@ -24,7 +24,7 @@
static char conninfo[256];
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 {
@ -50,17 +50,6 @@ static struct table_desc tables [] = {
analyze: "ANALYZE nodes;\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,
name: "node_tag",
@ -88,15 +77,15 @@ static struct table_desc tables [] = {
stop: "COMMIT;\n"
},
{
//table: t_way_seg,
name: "way_seg",
//table: t_way_nd,
name: "way_nd",
start: "BEGIN;\n",
create: "CREATE TABLE way_seg (\"id\" int4 NOT NULL, \"seg_id\" int4);\n"
"CREATE INDEX way_seg_idx ON way_seg (\"id\");\n",
prepare: "PREPARE insert_way_seg (int4, int4) AS INSERT INTO way_seg VALUES ($1,$2);\n"
"PREPARE get_way_seg (int4) AS SELECT \"seg_id\" FROM way_seg WHERE \"id\" = $1;\n",
copy: "COPY way_seg FROM STDIN;\n",
analyze: "ANALYZE way_seg;\n",
create: "CREATE TABLE way_nd (\"id\" int4 NOT NULL, \"nd_id\" int4);\n"
"CREATE INDEX way_nd_idx ON way_nd (\"id\");\n",
prepare: "PREPARE insert_way_nd (int4, int4) AS INSERT INTO way_nd VALUES ($1,$2);\n"
"PREPARE get_way_nd (int4) AS SELECT \"nd_id\" FROM way_nd WHERE \"id\" = $1;\n",
copy: "COPY way_nd FROM STDIN;\n",
analyze: "ANALYZE way_nd;\n",
stop: "COMMIT;\n"
}
};
@ -268,59 +257,13 @@ static int pgsql_nodes_get(struct osmNode *out, int id)
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];
int r;
sprintf(sql, "%d\t%d\t%d\n", id, from, to);
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);
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);
@ -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
struct keyval *p;
while((p = popItem(segs)) != NULL) {
int seg_id = strtol(p->value, NULL, 10);
psql_add_way_seg(way_id, seg_id);
while((p = popItem(nds)) != NULL) {
int nd_id = strtol(p->value, NULL, 10);
psql_add_way_nd(way_id, nd_id);
freeItem(p);
}
@ -346,9 +289,9 @@ static int pgsql_ways_set(int way_id, struct keyval *segs, struct keyval *tags)
}
#else
// 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(segs);
resetList(nds);
#endif
return 0;
}
@ -412,49 +355,6 @@ static void pgsql_iterate_nodes(int (*callback)(int id, struct keyval *tags, dou
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)
{
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];
PGresult *res_ways, *res_nodes;
int i, j, count = 0;
struct keyval tags;
struct osmSegLL *segll;
PGconn *sql_conn_segs = sql_conns[t_way_seg];
struct osmNode *nodes;
PGconn *sql_conn_nds = sql_conns[t_way_nd];
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
*/
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) {
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);
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");
for (i = 0; i < PQntuples(res_ways); i++) {
int id = strtol(PQgetvalue(res_ways, i, 0), NULL, 10);
int segCount;
int ndCount;
if (count++ %1000 == 0)
fprintf(stderr, "\rprocessing way (%dk)", count/1000);
getTags(id, &tags);
sprintf(sql,"SELECT nf.lat,nf.lon,nt.lat,nt.lon "
"FROM way_seg AS w,nodes AS nf, nodes AS nt, segments AS s "
"WHERE w.seg_id=s.id AND nf.id=s.from AND nt.id=s.to AND w.id=%d", id);
sprintf(sql,"SELECT n.lat, n.lon FROM way_nd AS w, nodes AS n "
"WHERE w.nd_id = n.id 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) {
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);
exit_nicely();
}
segCount = PQntuples(res_nodes);
segll = malloc(segCount * sizeof(struct osmSegLL));
ndCount = PQntuples(res_nodes);
nodes = malloc(ndCount * sizeof(struct osmNode));
if (segll) {
for (j=0; j<segCount; j++) {
segll[j].lat0 = strtod(PQgetvalue(res_nodes, j, 0), NULL);
segll[j].lon0 = 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);
if (nodes) {
for (j=0; j<ndCount; j++) {
nodes[j].lat = strtod(PQgetvalue(res_nodes, j, 0), NULL);
nodes[j].lon = strtod(PQgetvalue(res_nodes, j, 1), NULL);
}
callback(id, &tags, segll, segCount);
free(segll);
callback(id, &tags, nodes, ndCount);
free(nodes);
}
PQclear(res_nodes);
resetList(&tags);
@ -725,8 +622,6 @@ struct middle_t mid_pgsql = {
cleanup: pgsql_cleanup,
analyze: pgsql_analyze,
end: pgsql_end,
segments_set: pgsql_segments_set,
segments_get: pgsql_segments_get,
nodes_set: pgsql_nodes_set,
nodes_get: pgsql_nodes_get,
ways_set: pgsql_ways_set,

View File

@ -38,14 +38,9 @@ struct ramNode {
#endif
};
struct ramSegment {
int from;
int to;
};
struct ramWay {
struct keyval *tags;
int *segids;
int *ndids;
};
/* Object storage now uses 2 levels of storage arrays.
@ -67,17 +62,16 @@ struct ramWay {
#define NUM_BLOCKS (1 << (32 - BLOCK_SHIFT))
static struct ramNode *nodes[NUM_BLOCKS];
static struct ramSegment *segments[NUM_BLOCKS];
static struct ramWay *ways[NUM_BLOCKS];
static int node_blocks, segment_blocks;
static int node_blocks;
#ifdef USE_CLEAN
static int way_blocks;
#endif
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)
{
@ -151,53 +145,16 @@ static int ram_nodes_get(struct osmNode *out, int id)
return 0;
}
static int ram_segments_set(int id, int from, int to, 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)
static int ram_ways_set(int id, struct keyval *nds, struct keyval *tags)
{
struct keyval *p;
int *segids;
int segCount, i;
int *ndids;
int ndCount, i;
#ifdef USE_CLEAN
int block = id2block(id);
int offset = id2offset(id);
#else
struct osmSegLL *segll;
struct osmNode *nodes;
#endif
#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);
}
if (ways[block][offset].segids) {
free(ways[block][offset].segids);
ways[block][offset].segids = NULL;
ndCount = countList(nds);
if (!ndCount)
return 1;
if (ways[block][offset].ndids) {
free(ways[block][offset].ndids);
ways[block][offset].ndids = NULL;
}
#endif
segCount = countList(segs);
if (!segCount)
ndCount = countList(nds);
if (!ndCount)
return 1;
segids = malloc(sizeof(int) * (segCount+1));
if (!segids) {
ndids = malloc(sizeof(int) * (ndCount+1));
if (!ndids) {
fprintf(stderr, "%s malloc failed\n", __FUNCTION__);
exit_nicely();
}
#ifdef USE_CLEAN
ways[block][offset].segids = segids;
ways[block][offset].ndids = ndids;
#endif
i = 0;
while ((p = popItem(segs)) != NULL) {
int seg_id = strtol(p->value, NULL, 10);
while ((p = popItem(nds)) != NULL) {
int nd_id = strtol(p->value, NULL, 10);
freeItem(p);
if (seg_id) /* id = 0 is used as list terminator */
segids[i++] = seg_id;
if (nd_id) /* id = 0 is used as list terminator */
ndids[i++] = nd_id;
}
segids[i] = 0;
ndids[i] = 0;
#ifdef USE_CLEAN
if (!ways[block][offset].tags) {
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)
pushItem(ways[block][offset].tags, p);
#else
segll = getSegLL(segids, &segCount);
free(segids);
nodes = getNodes(ndids, &ndCount);
free(ndids);
if (segll) {
out_pgsql.way(id, tags, segll, segCount);
free(segll);
if (nodes) {
out_pgsql.way(id, tags, nodes, ndCount);
free(nodes);
}
#endif
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 i, count = 0;
struct osmSegLL *segll;
struct osmNode *nodes;
while(segids[count])
while(ndids[count])
count++;
segll = malloc(count * sizeof(struct osmSegLL));
nodes = malloc(count * sizeof(struct osmNode));
if (!segll) {
*segCount = 0;
if (!nodes) {
*ndCount = 0;
return NULL;
}
count = 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;
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++;
}
*segCount = count;
return segll;
*ndCount = count;
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;
struct osmSegLL *segll;
int block, offset, ndCount = 0;
struct osmNode *nodes;
fprintf(stderr, "\n");
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;
for (offset=0; offset < PER_BLOCK; offset++) {
if (ways[block][offset].segids) {
if (ways[block][offset].ndids) {
way_out_count++;
if (way_out_count % 1000 == 0)
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);
callback(id, ways[block][offset].tags, segll, segCount);
free(segll);
callback(id, ways[block][offset].tags, nodes, ndCount);
free(nodes);
}
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);
ways[block][offset].tags = NULL;
}
if (ways[block][offset].segids) {
free(ways[block][offset].segids);
ways[block][offset].segids = NULL;
if (ways[block][offset].ndids) {
free(ways[block][offset].ndids);
ways[block][offset].ndids = NULL;
}
}
}
@ -378,18 +325,14 @@ static void ram_stop(void)
free(nodes[i]);
nodes[i] = NULL;
}
if (segments[i]) {
free(segments[i]);
segments[i] = NULL;
}
if (ways[i]) {
for (j=0; j<PER_BLOCK; j++) {
if (ways[i][j].tags) {
resetList(ways[i][j].tags);
free(ways[i][j].tags);
}
if (ways[i][j].segids)
free(ways[i][j].segids);
if (ways[i][j].ndids)
free(ways[i][j].ndids);
}
free(ways[i]);
ways[i] = NULL;
@ -403,8 +346,6 @@ struct middle_t mid_ram = {
end: ram_end,
cleanup: ram_stop,
analyze: ram_analyze,
segments_set: ram_segments_set,
segments_get: ram_segments_get,
nodes_set: ram_nodes_set,
nodes_get: ram_nodes_get,
ways_set: ram_ways_set,

View File

@ -1,7 +1,7 @@
/* Common middle layer interface */
/* 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
@ -15,14 +15,12 @@ struct middle_t {
void (*cleanup)(void);
void (*analyze)(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_get)(struct osmNode *out, int id);
int (*ways_set)(int id, struct keyval *segs, struct keyval *tags);
int *(*ways_get)(int id);
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

View File

@ -46,20 +46,18 @@
#include "input.h"
static int count_node, max_node;
static int count_segment, max_segment;
static int count_way, max_way;
static int count_way_seg;
static int count_rel, max_rel;
struct middle_t *mid;
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
start tag and can therefore be cached.
*/
static double node_lon, node_lat;
static int seg_to, seg_from;
static struct keyval tags, segs;
static struct keyval tags, nds, members;
static int osm_id;
int verbose;
@ -67,14 +65,15 @@ int latlong;
static void printStatus(void)
{
fprintf(stderr, "\rProcessing: Node(%dk) Segment(%dk) Way(%dk)",
count_node/1000, count_segment/1000, count_way/1000);
fprintf(stderr, "\rProcessing: Node(%dk) Way(%dk) Relation(%dk)",
count_node/1000, count_way/1000, count_rel/1000);
}
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;
if (xmlStrEqual(name, BAD_CAST "node")) {
@ -97,25 +96,6 @@ void StartElement(xmlTextReaderPtr reader, const xmlChar *name)
xmlFree(xid);
xmlFree(xlon);
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")) {
xk = xmlTextReaderGetAttribute(reader, BAD_CAST "k");
assert(xk);
@ -147,14 +127,61 @@ void StartElement(xmlTextReaderPtr reader, const xmlChar *name)
printStatus();
xmlFree(xid);
} else if (xmlStrEqual(name, BAD_CAST "seg")) {
xid = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
} else if (xmlStrEqual(name, BAD_CAST "nd")) {
xid = xmlTextReaderGetAttribute(reader, BAD_CAST "ref");
assert(xid);
if (addItem(&segs, "id", (char *)xid, 1))
count_way_seg++;
addItem(&nds, "id", (char *)xid, 0);
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")) {
/* ignore */
} else if (xmlStrEqual(name, BAD_CAST "bound")) {
@ -171,17 +198,20 @@ void EndElement(const xmlChar *name)
reproject(&node_lat, &node_lon);
mid->nodes_set(osm_id, node_lat, node_lon, &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")) {
mid->ways_set(osm_id, &segs, &tags);
mid->ways_set(osm_id, &nds, &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")) {
/* ignore */
} else if (xmlStrEqual(name, BAD_CAST "seg")) {
} else if (xmlStrEqual(name, BAD_CAST "nd")) {
/* ignore */
} else if (xmlStrEqual(name, BAD_CAST "member")) {
/* ignore */
} else if (xmlStrEqual(name, BAD_CAST "osm")) {
printStatus();
} else if (xmlStrEqual(name, BAD_CAST "bound")) {
@ -338,7 +368,12 @@ int main(int argc, char *argv[])
text_init();
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
@ -366,12 +401,11 @@ int main(int argc, char *argv[])
xmlCleanupParser();
xmlMemoryDump();
if (count_node || count_segment || count_way) {
if (count_node || count_way || count_rel) {
fprintf(stderr, "\n");
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: 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");
//out->process(mid);

View File

@ -9,18 +9,6 @@ struct osmNode {
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 */
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)
{
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);
}
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';
const char *amenity = getItem(tags, "amenity");
@ -380,8 +363,6 @@ void add_parking_node(int id, struct keyval *tags, size_t index)
if (name)
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);
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
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;
unsigned int i;
size_t wkt_size;
int polygon = 0, export = 0;
int roads = 0;
char *wkt;
double area;
for (i=0; i < numTags; i++) {
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);
wkt_size = WKT(segll, count, polygon, id);
for (i=0;i<wkt_size;i++)
{
char *wkt = get_wkt(i);
if (strlen(wkt)) {
/* FIXME: there should be a better way to detect polygons */
if (!strncmp(wkt, "POLYGON", strlen("POLYGON"))) {
double area = get_area(i);
if (area > 0.0) {
char tmp[32];
snprintf(tmp, sizeof(tmp), "%f", area);
addItem(tags, "way_area", tmp, 0);
}
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]);
}
wkt = get_wkt(nodes, count, polygon, &area);
if (wkt && strlen(wkt)) {
/* FIXME: there should be a better way to detect polygons */
if (!strncmp(wkt, "POLYGON", strlen("POLYGON"))) {
if (area > 0.0) {
char tmp[32];
snprintf(tmp, sizeof(tmp), "%f", area);
addItem(tags, "way_area", tmp, 0);
}
write_wkts(id, tags, wkt, sql_conns[t_poly]);
add_parking_node(id, tags);
} 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;
}

View File

@ -19,7 +19,7 @@ struct output_t {
void (*cleanup)(void);
void (*process)(struct middle_t *mid);
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