/********************************************************************** * $Id$ * * GEOS - Geometry Engine Open Source * http://geos.refractions.net * * Copyright (C) 2001-2002 Vivid Solutions Inc. * Copyright (C) 2005 Refractions Research Inc. * * This is free software; you can redistribute and/or modify it under * the terms of the GNU Lesser General Public Licence as published * by the Free Software Foundation. * See the COPYING file for more information. * ********************************************************************* * * This file should document by example usage of the GEOS library. * It could actually be a live discuss-by-example board for * architectural design choices. * * --strk; * * DEBUGGING TIPS: * use -D__USE_MALLOC at compile time for gcc 2.91, 2.95, 3.0 and 3.1 * and GLIBCXX_FORCE_NEW or GLIBCPP_FORCE_NEW at run time with gcc 3.2.2+ * to force libstdc++ avoid caching memory. This should remove some * obscure reports from memory checkers like valgrind. * **********************************************************************/ #include #include #include #include #include using namespace geos; // Prototypes void wkt_print_geoms(vector *geoms); // This object will be used to construct our geometries. // It might be bypassed by directly call geometry constructors, // but that would be boring because you'd need to specify // a PrecisionModel and a SRID everytime: those infos are // cached inside a GeometryFactory object. GeometryFactory *global_factory; //#define DEBUG_STREAM_STATE 1 // // This function tests writing and reading WKB // TODO: // - compare input and output geometries for equality // - remove debugging lines (on stream state) // void WKBtest(vector*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: "<size(); for (unsigned int i=0; inormalize(); gout->normalize(); int failed = gin->compareTo(gout); if ( failed ) cout<<"{"< *geoms) { WKBtest(geoms); // test WKB parser // WKT-print given geometries WKTWriter *wkt = new WKTWriter(); for (unsigned int i=0; isize(); i++) { const Geometry *g = (*geoms)[i]; string tmp=wkt->write(g); cout<<"["<createPoint(c); return p; } // This function will create a LinearString // geometry with the shape of the letter U // having top-left corner at given coordinates // and 'side' height and width LineString * create_ushaped_linestring(double xoffset, double yoffset, double side) { // We will use a coordinate list to build the linestring CoordinateSequence *cl = new DefaultCoordinateSequence(); cl->add(Coordinate(xoffset, yoffset)); cl->add(Coordinate(xoffset, yoffset+side)); cl->add(Coordinate(xoffset+side, yoffset+side)); cl->add(Coordinate(xoffset+side, yoffset)); // Now that we have a CoordinateSequence we can create // the linestring. // The newly created LineString will take ownership // of the CoordinateSequence. LineString *ls = global_factory->createLineString(cl); // This is what you do if you want the new LineString // to make a copy of your CoordinateSequence: // LineString *ls = global_factory->createLineString(*cl); return ls; // our LineString } // This function will create a LinearRing // geometry rapresenting a square with the given origin // and side LinearRing * create_square_linearring(double xoffset, double yoffset, double side) { // We will use a coordinate list to build the linearring CoordinateSequence *cl = new DefaultCoordinateSequence(); cl->add(Coordinate(xoffset, yoffset)); cl->add(Coordinate(xoffset, yoffset+side)); cl->add(Coordinate(xoffset+side, yoffset+side)); cl->add(Coordinate(xoffset+side, yoffset)); cl->add(Coordinate(xoffset, yoffset)); // Now that we have a CoordinateSequence we can create // the linearring. // The newly created LinearRing will take ownership // of the CoordinateSequence. LinearRing *lr = global_factory->createLinearRing(cl); // This is what you do if you want the new LinearRing // to make a copy of your CoordinateSequence: // LinearRing *lr = global_factory->createLinearRing(*cl); return lr; // our LinearRing } // This function will create a Polygon // geometry rapresenting a square with the given origin // and side and with a central hole 1/3 sided. Polygon * create_square_polygon(double xoffset, double yoffset, double side) { // We need a LinearRing for the polygon shell LinearRing *outer = create_square_linearring(xoffset,yoffset,side); // And another for the hole LinearRing *inner = create_square_linearring(xoffset+(side/3), yoffset+(side/3),(side/3)); // If we need to specify any hole, we do it using // a vector of Geometry pointers (I don't know why // not LinearRings) vector *holes = new vector; // We add the newly created geometry to the vector // of holes. holes->push_back(inner); // And finally we call the polygon constructor. // Both the outer LinearRing and the vector of holes // will be referenced by the resulting Polygon object, // thus we CANNOT delete them, neither the holes, nor // the vector containing their pointers, nor the outer // LinearRing. Everything will be deleted at Polygon // deletion time (this is inconsistent with LinearRing // behaviour... what should we do?). Polygon *poly = global_factory->createPolygon(outer, holes); return poly; } // // This function will create a GeometryCollection // containing copies of all Geometries in given vector. // GeometryCollection * create_simple_collection(vector *geoms) { return global_factory->createGeometryCollection(*geoms); // if you wanted to transfer ownership of vector end // its elements you should have call: // return global_factory->createGeometryCollection(geoms); } // // This function uses GeometricShapeFactory to render // a circle having given center and radius // Polygon * create_circle(double centerX, double centerY, double radius) { GeometricShapeFactory shapefactory(global_factory); shapefactory.setCentre(Coordinate(centerX, centerY)); shapefactory.setSize(radius); // same as: // shapefactory.setHeight(radius); // shapefactory.setWidth(radius); return shapefactory.createCircle(); }; // // This function uses GeometricShapeFactory to render // an ellipse having given center and axis size // Polygon * create_ellipse(double centerX, double centerY, double width, double height) { GeometricShapeFactory shapefactory(global_factory); shapefactory.setCentre(Coordinate(centerX, centerY)); shapefactory.setHeight(height); shapefactory.setWidth(width); return shapefactory.createCircle(); }; // // This function uses GeometricShapeFactory to render // a rectangle having lower-left corner at given coordinates // and given sizes. // Polygon * create_rectangle(double llX, double llY, double width, double height) { GeometricShapeFactory shapefactory(global_factory); shapefactory.setBase(Coordinate(llX, llY)); shapefactory.setHeight(height); shapefactory.setWidth(width); shapefactory.setNumPoints(4); // we don't need more then 4 points for a rectangle... // can use setSize for a square return shapefactory.createRectangle(); }; // // This function uses GeometricShapeFactory to render // an arc having lower-left corner at given coordinates, // given sizes and given angles. // LineString * create_arc(double llX, double llY, double width, double height, double startang, double endang) { GeometricShapeFactory shapefactory(global_factory); shapefactory.setBase(Coordinate(llX, llY)); shapefactory.setHeight(height); shapefactory.setWidth(width); // shapefactory.setNumPoints(100); // the default (100 pts) // can use setSize for a square return shapefactory.createArc(startang, endang); }; // Start reading here void do_all() { vector *geoms = new vector; vector *newgeoms; // Define a precision model using 0,0 as the reference origin // and 2.0 as coordinates scale. PrecisionModel *pm = new PrecisionModel(2.0, 0, 0); // Initialize global factory with defined PrecisionModel // and a SRID of -1 (undefined). global_factory = new GeometryFactory(pm, -1); // We do not need PrecisionMode object anymore, it has // been copied to global_factory private storage delete pm; //////////////////////////////////////////////////////////////////////// // GEOMETRY CREATION //////////////////////////////////////////////////////////////////////// // Read function bodies to see the magic behind them geoms->push_back(create_point(150, 350)); geoms->push_back(create_ushaped_linestring(60,60,100)); geoms->push_back(create_square_linearring(0,0,100)); geoms->push_back(create_square_polygon(0,200,300)); geoms->push_back(create_square_polygon(0,250,300)); geoms->push_back(create_simple_collection(geoms)); // These ones use a GeometricShapeFactory geoms->push_back(create_circle(0, 0, 10)); geoms->push_back(create_ellipse(0, 0, 8, 12)); geoms->push_back(create_rectangle(-5, -5, 10, 10)); // a square geoms->push_back(create_rectangle(-5, -5, 10, 20)); // a rectangle // The upper-right quarter of a vertical ellipse geoms->push_back(create_arc(0, 0, 10, 20, 0, M_PI/2)); // Print all geoms. cout<<"--------HERE ARE THE BASE GEOMS ----------"<; for (unsigned int i=0; isize(); i++) { Geometry *g = (*geoms)[i]; newgeoms->push_back( g->getCentroid() ); } // Print all convex hulls cout<size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; ///////////////////////////////////////////// // BUFFER ///////////////////////////////////////////// newgeoms = new vector; for (unsigned int i=0; isize(); i++) { Geometry *g = (*geoms)[i]; try { Geometry *g2 = g->buffer(10); newgeoms->push_back(g2); } catch (GEOSException *exc) { cerr <<"GEOS Exception: geometry "<buffer(10): "<toString()<<"\n"; delete exc; } } cout<size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; ///////////////////////////////////////////// // CONVEX HULL ///////////////////////////////////////////// // Make convex hulls of geometries newgeoms = new vector; for (unsigned int i=0; isize(); i++) { Geometry *g = (*geoms)[i]; newgeoms->push_back( g->convexHull() ); } // Print all convex hulls cout<size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; //////////////////////////////////////////////////////////////////////// // RELATIONAL OPERATORS //////////////////////////////////////////////////////////////////////// cout<<"-------------------------------------------------------------------------------"<size(); i++) { cout<<"\t["<size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<size(); j++) { Geometry *g2 = (*geoms)[j]; try { if ( g1->disjoint(g2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (IllegalArgumentException *exc) { cout<<" X\t"; delete exc; } catch (GEOSException *exc) { cerr<toString()<size(); i++) { cout<<"\t["<size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<size(); j++) { Geometry *g2 = (*geoms)[j]; try { if ( g1->touches(g2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (IllegalArgumentException *exc) { cout<<" X\t"; delete exc; } catch (GEOSException *exc) { cerr<toString()<size(); i++) { cout<<"\t["<size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<size(); j++) { Geometry *g2 = (*geoms)[j]; try { if ( g1->intersects(g2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (IllegalArgumentException *exc) { cout<<" X\t"; delete exc; } catch (GEOSException *exc) { cerr<toString()<size(); i++) { cout<<"\t["<size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<size(); j++) { Geometry *g2 = (*geoms)[j]; try { if ( g1->crosses(g2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (IllegalArgumentException *exc) { cout<<" X\t"; delete exc; } catch (GEOSException *exc) { cerr<toString()<size(); i++) { cout<<"\t["<size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<size(); j++) { Geometry *g2 = (*geoms)[j]; try { if ( g1->within(g2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (IllegalArgumentException *exc) { cout<<" X\t"; delete exc; } catch (GEOSException *exc) { cerr<toString()<size(); i++) { cout<<"\t["<size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<size(); j++) { Geometry *g2 = (*geoms)[j]; try { if ( g1->contains(g2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (IllegalArgumentException *exc) { cout<<" X\t"; delete exc; } catch (GEOSException *exc) { cerr<toString()<size(); i++) { cout<<"\t["<size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<size(); j++) { Geometry *g2 = (*geoms)[j]; try { if ( g1->overlaps(g2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (IllegalArgumentException *exc) { cout<<" X\t"; delete exc; } catch (GEOSException *exc) { cerr<toString()<size(); i++) { cout<<"\t["<size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<size(); j++) { Geometry *g2 = (*geoms)[j]; IntersectionMatrix *im=NULL; try { // second argument is intersectionPattern if ( g1->relate(g2, "212101212") ) cout<<" 1\t"; else cout<<" 0\t"; // get the intersectionMatrix itself im=g1->relate(g2); delete im; // delete afterwards } // Geometry Collection is not a valid argument catch (IllegalArgumentException *exc) { cout<<" X\t"; delete exc; } catch (GEOSException *exc) { cerr<toString()<size(); i++) { cout<<"\t["<size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<size(); j++) { Geometry *g2 = (*geoms)[j]; try { if ( g1->equals(g2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (IllegalArgumentException *exc) { cout<<" X\t"; delete exc; } catch (GEOSException *exc) { cerr<toString()<size(); i++) { cout<<"\t["<size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<size(); j++) { Geometry *g2 = (*geoms)[j]; try { // second argument is a tolerance if ( g1->equalsExact(g2, 0.5) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (IllegalArgumentException *exc) { cout<<" X\t"; delete exc; } catch (GEOSException *exc) { cerr<toString()<size(); i++) { cout<<"\t["<size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<size(); j++) { Geometry *g2 = (*geoms)[j]; try { // second argument is the distance if ( g1->isWithinDistance(g2,2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (IllegalArgumentException *exc) { cout<<" X\t"; delete exc; } catch (GEOSException *exc) { cerr<toString()<; for (unsigned int i=0; isize()-1; i++) { Geometry *g1 = (*geoms)[i]; for (unsigned int j=i+1; jsize(); j++) { Geometry *g2 = (*geoms)[j]; try { Geometry *g3 = g1->Union(g2); newgeoms->push_back(g3); } // It's illegal to union a collection ... catch (IllegalArgumentException *ill) { //cerr <toString()<<"\n"; delete ill; } catch (GEOSException *exc) { cerr <<"GEOS Exception: "<toString()<<"\n"; delete exc; } } } // Print all unions cout<size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; ///////////////////////////////////////////// // INTERSECTION ///////////////////////////////////////////// // Compute intersection of adhiacent geometries newgeoms = new vector; for (unsigned int i=0; isize()-1; i++) { Geometry *g1 = (*geoms)[i]; for (unsigned int j=i+1; jsize(); j++) { Geometry *g2 = (*geoms)[j]; try { Geometry *g3 = g1->intersection(g2); newgeoms->push_back(g3); } // Collection are illegal as intersection argument catch (IllegalArgumentException *ill) { //cerr <toString()<<"\n"; delete ill; } catch (GEOSException *exc) { cerr <<"GEOS Exception: "<toString()<<"\n"; delete exc; } } } cout<size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; ///////////////////////////////////////////// // DIFFERENCE ///////////////////////////////////////////// // Compute difference of adhiacent geometries newgeoms = new vector; for (unsigned int i=0; isize()-1; i++) { Geometry *g1 = (*geoms)[i]; for (unsigned int j=i+1; jsize(); j++) { Geometry *g2 = (*geoms)[j]; try { Geometry *g3 = g1->difference(g2); newgeoms->push_back(g3); } // Collection are illegal as difference argument catch (IllegalArgumentException *ill) { //cerr <toString()<<"\n"; delete ill; } catch (GEOSException *exc) { cerr <<"GEOS Exception: "<toString()<<"\n"; delete exc; } } } cout<size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; ///////////////////////////////////////////// // SYMMETRIC DIFFERENCE ///////////////////////////////////////////// // Compute symmetric difference of adhiacent geometries newgeoms = new vector; for (unsigned int i=0; isize()-1; i++) { Geometry *g1 = (*geoms)[i]; for (unsigned int j=i+1; jsize(); j++) { Geometry *g2 = (*geoms)[j]; try { Geometry *g3 = g1->symDifference(g2); newgeoms->push_back(g3); } // Collection are illegal as symdifference argument catch (IllegalArgumentException *ill) { //cerr <toString()<<"\n"; delete ill; } catch (GEOSException *exc) { cerr <<"GEOS Exception: "<toString()<<"\n"; delete exc; } } } cout<size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; ///////////////////////////////////////////// // LINEMERGE ///////////////////////////////////////////// LineMerger lm; lm.add(geoms); vector *mls = lm.getMergedLineStrings(); newgeoms = new vector; for (unsigned int i=0; isize(); i++) newgeoms->push_back((*mls)[i]); delete mls; cout<size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; ///////////////////////////////////////////// // POLYGONIZE ///////////////////////////////////////////// Polygonizer plgnzr; plgnzr.add(geoms); vector *polys = plgnzr.getPolygons(); newgeoms = new vector; for (unsigned int i=0; isize(); i++) newgeoms->push_back((*polys)[i]); delete polys; cout<size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; ///////////////////////////////////////////// // CLEANUP ///////////////////////////////////////////// // Delete base geometries for (unsigned int i=0; isize(); i++) { delete (*geoms)[i]; } delete geoms; delete global_factory; } int main() { cout<<"GEOS "<toString()<<"\n"; delete exc; exit(1); } catch (exception &e) { cerr <<"Standard exception thrown: "<