/* private */ auto_ptr<GeometryFactory> GeometryPrecisionReducer::createFactory( const GeometryFactory& oldGF, const PrecisionModel& newPM ) { auto_ptr<GeometryFactory> newFactory( new GeometryFactory(&newPM, oldGF.getSRID(), const_cast<CoordinateSequenceFactory*>(oldGF.getCoordinateSequenceFactory())) ); return newFactory; }
char *get_wkt_simple(osmNode *nodes, int count, int polygon) { GeometryFactory gf; std::auto_ptr<CoordinateSequence> coords(gf.getCoordinateSequenceFactory()->create((size_t)0, (size_t)2)); try { for (int i = 0; i < count ; i++) { Coordinate c; c.x = nodes[i].lon; c.y = nodes[i].lat; coords->add(c, 0); } geom_ptr geom; if (polygon && (coords->getSize() >= 4) && (coords->getAt(coords->getSize() - 1).equals2D(coords->getAt(0)))) { std::auto_ptr<LinearRing> shell(gf.createLinearRing(coords.release())); geom = geom_ptr(gf.createPolygon(shell.release(), new std::vector<Geometry *>)); if (!geom->isValid()) { if (excludepoly) { return NULL; } else { geom = geom_ptr(geom->buffer(0)); } } geom->normalize(); // Fix direction of ring } else { if (coords->getSize() < 2) return NULL; geom = geom_ptr(gf.createLineString(coords.release())); } WKTWriter wktw; std::string wkt = wktw.write(geom.get()); return strdup(wkt.c_str()); } catch (std::bad_alloc) { std::cerr << std::endl << "Exception caught processing way. You are likelly running out of memory." << std::endl; std::cerr << "Try in slim mode, using -s parameter." << std::endl; return NULL; } catch (...) { std::cerr << std::endl << "Exception caught processing way" << std::endl; return NULL; } }
size_t build_geometry(osmid_t osm_id, struct osmNode **xnodes, int *xcount, int make_polygon, int enable_multi, double split_at) { size_t wkt_size = 0; std::auto_ptr<std::vector<Geometry*> > lines(new std::vector<Geometry*>); GeometryFactory gf; geom_ptr geom; #ifdef HAS_PREPARED_GEOMETRIES geos::geom::prep::PreparedGeometryFactory pgf; #endif try { for (int c=0; xnodes[c]; c++) { std::auto_ptr<CoordinateSequence> coords(gf.getCoordinateSequenceFactory()->create((size_t)0, (size_t)2)); for (int i = 0; i < xcount[c]; i++) { struct osmNode *nodes = xnodes[c]; Coordinate c; c.x = nodes[i].lon; c.y = nodes[i].lat; coords->add(c, 0); } if (coords->getSize() > 1) { geom = geom_ptr(gf.createLineString(coords.release())); lines->push_back(geom.release()); } } //geom_ptr segment(0); geom_ptr mline (gf.createMultiLineString(lines.release())); //geom_ptr noded (segment->Union(mline.get())); LineMerger merger; //merger.add(noded.get()); merger.add(mline.get()); std::auto_ptr<std::vector<LineString *> > merged(merger.getMergedLineStrings()); WKTWriter writer; // Procces ways into lines or simple polygon list polygondata* polys = new polygondata[merged->size()]; unsigned totalpolys = 0; for (unsigned i=0 ;i < merged->size(); ++i) { std::auto_ptr<LineString> pline ((*merged ) [i]); if (make_polygon && pline->getNumPoints() > 3 && pline->isClosed()) { polys[totalpolys].polygon = gf.createPolygon(gf.createLinearRing(pline->getCoordinates()),0); polys[totalpolys].ring = gf.createLinearRing(pline->getCoordinates()); polys[totalpolys].area = polys[totalpolys].polygon->getArea(); polys[totalpolys].iscontained = 0; polys[totalpolys].containedbyid = 0; if (polys[totalpolys].area > 0.0) totalpolys++; else { delete(polys[totalpolys].polygon); delete(polys[totalpolys].ring); } } else { //std::cerr << "polygon(" << osm_id << ") is no good: points(" << pline->getNumPoints() << "), closed(" << pline->isClosed() << "). " << writer.write(pline.get()) << std::endl; double distance = 0; std::auto_ptr<CoordinateSequence> segment; segment = std::auto_ptr<CoordinateSequence>(gf.getCoordinateSequenceFactory()->create((size_t)0, (size_t)2)); segment->add(pline->getCoordinateN(0)); for(unsigned i=1; i<pline->getNumPoints(); i++) { segment->add(pline->getCoordinateN(i)); distance += pline->getCoordinateN(i).distance(pline->getCoordinateN(i-1)); if ((distance >= split_at) || (i == pline->getNumPoints()-1)) { geom = geom_ptr(gf.createLineString(segment.release())); std::string wkt = writer.write(geom.get()); wkts.push_back(wkt); areas.push_back(0); wkt_size++; distance=0; segment = std::auto_ptr<CoordinateSequence>(gf.getCoordinateSequenceFactory()->create((size_t)0, (size_t)2)); segment->add(pline->getCoordinateN(i)); } } //std::string text = writer.write(pline.get()); //wkts.push_back(text); //areas.push_back(0.0); //wkt_size++; } } if (totalpolys) { qsort(polys, totalpolys, sizeof(polygondata), polygondata_comparearea); unsigned toplevelpolygons = 0; int istoplevelafterall; for (unsigned i=0 ;i < totalpolys; ++i) { if (polys[i].iscontained != 0) continue; toplevelpolygons++; #ifdef HAS_PREPARED_GEOMETRIES const geos::geom::prep::PreparedGeometry* preparedtoplevelpolygon = pgf.create(polys[i].polygon); #endif for (unsigned j=i+1; j < totalpolys; ++j) { #ifdef HAS_PREPARED_GEOMETRIES // Does preparedtoplevelpolygon contain the smaller polygon[j]? if (polys[j].containedbyid == 0 && preparedtoplevelpolygon->contains(polys[j].polygon)) #else // Does polygon[i] contain the smaller polygon[j]? if (polys[j].containedbyid == 0 && polys[i].polygon->contains(polys[j].polygon)) #endif { // are we in a [i] contains [k] contains [j] situation // which would actually make j top level istoplevelafterall = 0; for (unsigned k=i+1; k < j; ++k) { if (polys[k].iscontained && polys[k].containedbyid == i && polys[k].polygon->contains(polys[j].polygon)) { istoplevelafterall = 1; break; } #if 0 else if (polys[k].polygon->intersects(polys[j].polygon) || polys[k].polygon->touches(polys[j].polygon)) { // FIXME: This code does not work as intended // It should be setting the polys[k].ring in order to update this object // but the value of polys[k].polygon calculated is normally NULL // Add polygon this polygon (j) to k since they intersect // Mark ourselfs to be dropped (2), delete the original k Geometry* polyunion = polys[k].polygon->Union(polys[j].polygon); delete(polys[k].polygon); polys[k].polygon = dynamic_cast<Polygon*>(polyunion); polys[j].iscontained = 2; // Drop istoplevelafterall = 2; break; } #endif } if (istoplevelafterall == 0) { polys[j].iscontained = 1; polys[j].containedbyid = i; } } } #ifdef HAS_PREPARED_GEOMETRIES pgf.destroy(preparedtoplevelpolygon); #endif } // polys now is a list of ploygons tagged with which ones are inside each other // List of polygons for multipolygon std::auto_ptr<std::vector<Geometry*> > polygons(new std::vector<Geometry*>); // For each top level polygon create a new polygon including any holes for (unsigned i=0 ;i < totalpolys; ++i) { if (polys[i].iscontained != 0) continue; // List of holes for this top level polygon std::auto_ptr<std::vector<Geometry*> > interior(new std::vector<Geometry*>); for (unsigned j=i+1; j < totalpolys; ++j) { if (polys[j].iscontained == 1 && polys[j].containedbyid == i) { interior->push_back(polys[j].ring); } } Polygon* poly(gf.createPolygon(polys[i].ring, interior.release())); poly->normalize(); polygons->push_back(poly); } // Make a multipolygon if required if ((toplevelpolygons > 1) && enable_multi) { std::auto_ptr<MultiPolygon> multipoly(gf.createMultiPolygon(polygons.release())); //if (multipoly->isValid()) //{ std::string text = writer.write(multipoly.get()); wkts.push_back(text); areas.push_back(multipoly->getArea()); wkt_size++; //} } else { for(unsigned i=0; i<toplevelpolygons; i++) { Polygon* poly = dynamic_cast<Polygon*>(polygons->at(i));; //if (poly->isValid()) //{ std::string text = writer.write(poly); wkts.push_back(text); areas.push_back(poly->getArea()); wkt_size++; //} delete(poly); } } } for (unsigned i=0; i < totalpolys; ++i) { delete(polys[i].polygon); } delete[](polys); } catch (std::exception& e) { std::cerr << std::endl << "Standard exception processing way_id "<< osm_id << ": " << e.what() << std::endl; wkt_size = 0; } catch (...) { std::cerr << std::endl << "Exception caught processing way id=" << osm_id << std::endl; wkt_size = 0; } return wkt_size; }
size_t get_wkt_split(osmNode *nodes, int count, int polygon, double split_at) { GeometryFactory gf; std::auto_ptr<CoordinateSequence> coords(gf.getCoordinateSequenceFactory()->create((size_t)0, (size_t)2)); double area; WKTWriter wktw; size_t wkt_size = 0; try { for (int i = 0; i < count ; i++) { Coordinate c; c.x = nodes[i].lon; c.y = nodes[i].lat; coords->add(c, 0); } geom_ptr geom; if (polygon && (coords->getSize() >= 4) && (coords->getAt(coords->getSize() - 1).equals2D(coords->getAt(0)))) { std::auto_ptr<LinearRing> shell(gf.createLinearRing(coords.release())); geom = geom_ptr(gf.createPolygon(shell.release(), new std::vector<Geometry *>)); geom->normalize(); // Fix direction of ring area = geom->getArea(); std::string wkt = wktw.write(geom.get()); wkts.push_back(wkt); areas.push_back(area); wkt_size++; } else { if (coords->getSize() < 2) return 0; double distance = 0; std::auto_ptr<CoordinateSequence> segment; segment = std::auto_ptr<CoordinateSequence>(gf.getCoordinateSequenceFactory()->create((size_t)0, (size_t)2)); segment->add(coords->getAt(0)); for(unsigned i=1; i<coords->getSize(); i++) { segment->add(coords->getAt(i)); distance += coords->getAt(i).distance(coords->getAt(i-1)); if ((distance >= split_at) || (i == coords->getSize()-1)) { geom = geom_ptr(gf.createLineString(segment.release())); std::string wkt = wktw.write(geom.get()); wkts.push_back(wkt); areas.push_back(0); wkt_size++; distance=0; segment = std::auto_ptr<CoordinateSequence>(gf.getCoordinateSequenceFactory()->create((size_t)0, (size_t)2)); segment->add(coords->getAt(i)); } } } } catch (std::bad_alloc) { std::cerr << std::endl << "Exception caught processing way. You are likelly running out of memory." << std::endl; std::cerr << "Try in slim mode, using -s parameter." << std::endl; wkt_size = 0; } catch (...) { std::cerr << std::endl << "Exception caught processing way" << std::endl; wkt_size = 0; } return wkt_size; }