int main(int /*argc*/, char** /*argv*/) { try { ofstream out("WKTOut"); ifstream in("WKTIn"); string instr; string outstr; WKTReader *r = new WKTReader(new GeometryFactory(new PrecisionModel(),10)); WKTWriter *w = new WKTWriter(); Geometry *g; cout << "Start Testing:" << endl; while(!in.eof()) { getline(in,instr); if (instr!="") { g=r->read(instr); outstr=w->write(g); out << "----------" << endl; out << instr << endl; out << outstr << endl; out << "----------" << endl << endl; } } out.flush(); out.close(); cout << "End of Testing" << endl; } catch (const GEOSException& ge) { cout << ge.what() << endl; } return 0; }
//helper function for funning triangulation void runVoronoi(const char *sitesWkt, const char *expectedWkt , const double tolerance) { WKTReader reader; WKTWriter writer; geos::triangulate::VoronoiDiagramBuilder builder; std::auto_ptr<Geometry> sites ( reader.read(sitesWkt) ); std::auto_ptr<Geometry> expected ( reader.read(expectedWkt) ); std::auto_ptr<GeometryCollection> results; GeometryFactory geomFact; builder.setSites(*sites); //set Tolerance: builder.setTolerance(tolerance); results = builder.getDiagram(geomFact); results->normalize(); expected->normalize(); ensure_equals(results->getCoordinateDimension(), expected->getCoordinateDimension()); bool eq = results->equalsExact(expected.get(), 1e-7); if ( ! eq ) { writer.setTrim(true); cout << endl; cout << " Expected: " << writer.write(expected.get()) << endl; cout << " Obtained: " << writer.write(results.get()) << endl; } ensure(eq); }
std::string mlsToMlp(const std::string &input1){ std::string result; WKTReader wktr; WKTWriter wktw; Geometry *mls = wktr.read(input1); // First we have to properly node the linestrings. Union makes this easy. Polygon *envelope = dynamic_cast<Polygon*>(mls->getEnvelope()); Geometry *nodedLineStrings = envelope->getExteriorRing()->Union(mls); // The polygonizer creates polygons out of the linework geos::operation::polygonize::Polygonizer polygonizer; polygonizer.add(nodedLineStrings); std::vector<Polygon*> *polygons = polygonizer.getPolygons(); // Annoyingly, we have to transform one vector type to another std::vector<Geometry*> geometries; for(int inx = 0; inx < polygons->size(); inx++){ geometries.push_back((*polygons)[inx]); } Geometry *mlp = GeometryFactory::getDefaultInstance()->createMultiPolygon(geometries); result = wktw.write(mlp); return result; }
std::vector<std::string> polygonize(const std::string &input1, const std::string &input2) { std::vector<std::string> result; WKTReader wktr; WKTWriter wktw; Geometry *line1 = wktr.read(input1); Geometry *line2 = wktr.read(input2); // Unioning the linestrings inserts nodes for polygonization Geometry *nodedLineStrings = line1->Union(line2); // Add additional lineStrings to each end to close them off LineString *ls1 = dynamic_cast<LineString*>(line1); LineString *ls2 = dynamic_cast<LineString*>(line2); Point *sp1 = ls1->getStartPoint(); Point *sp2 = ls2->getStartPoint(); Point *ep1 = ls1->getEndPoint(); Point *ep2 = ls2->getEndPoint(); Geometry *smallests = smallestSegment(sp1, ep1, sp2, ep2); nodedLineStrings = nodedLineStrings->Union(smallests); // Use GEOS to polygonize the strings geos::operation::polygonize::Polygonizer polygonizer; polygonizer.add(nodedLineStrings); std::vector<Polygon*> *polygons = polygonizer.getPolygons(); for(int inx = 0; inx < polygons->size(); inx++){ result.push_back(wktw.write((*polygons)[inx])); } return result; }
// This function will print given geometries in WKT // format to stdout. As a side-effect, will test WKB // output and input, using the WKBtest function. void wkt_print_geoms(vector<Geometry *> *geoms) { WKBtest(geoms); // test WKB parser // WKT-print given geometries WKTWriter *wkt = new WKTWriter(); for (unsigned int i=0; i<geoms->size(); i++) { const Geometry *g = (*geoms)[i]; string tmp=wkt->write(g); cout<<"["<<i<<"] (WKT) "<<tmp<<endl; } delete wkt; }
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; } }
// // This function tests writing and reading WKB // TODO: // - compare input and output geometries for equality // - remove debugging lines (on stream state) // void WKBtest(vector<Geometry*>*geoms) { stringstream s(ios_base::binary|ios_base::in|ios_base::out); WKBReader wkbReader(*global_factory); WKBWriter wkbWriter; Geometry *gout; #if DEBUG_STREAM_STATE cout<<"WKBtest: machine byte order: "<<BYTE_ORDER<<endl; #endif unsigned int ngeoms=geoms->size(); for (unsigned int i=0; i<ngeoms; ++i) { Geometry *gin = (*geoms)[i]; #if DEBUG_STREAM_STATE cout<<"State of stream before WRITE: "; cout<<"p:"<<s.tellp()<<" g:"<<s.tellg()<< " good:"<<s.good()<< " eof:"<<s.eof()<< " bad:"<<s.bad()<< " fail:"<<s.fail()<<endl; #endif #if DEBUG_STREAM_STATE cout<<"State of stream after SEEKP: "; cout<<"p:"<<s.tellp()<<" g:"<<s.tellg()<< " good:"<<s.good()<< " eof:"<<s.eof()<< " bad:"<<s.bad()<< " fail:"<<s.fail()<<endl; #endif wkbWriter.write(*gin, s); #if DEBUG_STREAM_STATE cout<<"wkbWriter wrote and reached "; cout<<"p:"<<s.tellp()<<" g:"<<s.tellg()<<endl; cout<<"State of stream before DUMP: "; cout<<"p:"<<s.tellp()<<" g:"<<s.tellg()<< " good:"<<s.good()<< " eof:"<<s.eof()<< " bad:"<<s.bad()<< " fail:"<<s.fail()<<endl; #endif #if DEBUG_STREAM_STATE cout<<"State of stream after DUMP: "; cout<<"p:"<<s.tellp()<<" g:"<<s.tellg()<< " good:"<<s.good()<< " eof:"<<s.eof()<< " bad:"<<s.bad()<< " fail:"<<s.fail()<<endl; #endif s.seekg(0, ios::beg); // rewind reader pointer #if DEBUG_STREAM_STATE cout<<"State of stream before READ: "; cout<<"p:"<<s.tellp()<<" g:"<<s.tellg()<< " good:"<<s.good()<< " eof:"<<s.eof()<< " bad:"<<s.bad()<< " fail:"<<s.fail()<<endl; #endif gout = wkbReader.read(s); #if DEBUG_STREAM_STATE cout<<"State of stream after READ: "; cout<<"p:"<<s.tellp()<<" g:"<<s.tellg()<< " good:"<<s.good()<< " eof:"<<s.eof()<< " bad:"<<s.bad()<< " fail:"<<s.fail()<<endl; #endif gin->normalize(); gout->normalize(); int failed = gin->compareTo(gout); if ( failed ) cout<<"{"<<i<<"} (WKB) "; else cout<<"["<<i<<"] (WKB) "; WKBReader::printHEX(s, cout); cout<<endl; if ( failed ) { WKTWriter wkt; cout<<" IN: "<<wkt.write(gin)<<endl; cout<<" OUT: "<<wkt.write(gout)<<endl; } s.seekp(0, ios::beg); // rewind writer pointer delete gout; } }
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; }
Handle<Value> WKTWriter::New(const Arguments& args) { HandleScope scope; WKTWriter* writer = new WKTWriter(); writer->Wrap(args.This()); return args.This(); }