1157 строки
35 KiB
C++
1157 строки
35 KiB
C++
/**********************************************************************
|
|
*
|
|
* GEOS - Geometry Engine Open Source
|
|
* http://geos.osgeo.org
|
|
*
|
|
* 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 <geos/geom/PrecisionModel.h>
|
|
#include <geos/geom/GeometryFactory.h>
|
|
#include <geos/geom/Geometry.h>
|
|
#include <geos/geom/Point.h>
|
|
#include <geos/geom/LinearRing.h>
|
|
#include <geos/geom/LineString.h>
|
|
#include <geos/geom/Polygon.h>
|
|
#include <geos/geom/GeometryCollection.h>
|
|
#include <geos/geom/Coordinate.h>
|
|
#include <geos/geom/CoordinateSequence.h>
|
|
#include <geos/geom/CoordinateArraySequence.h>
|
|
#include <geos/geom/IntersectionMatrix.h>
|
|
#include <geos/io/WKBReader.h>
|
|
#include <geos/io/WKBWriter.h>
|
|
#include <geos/io/WKTWriter.h>
|
|
#include <geos/util/GeometricShapeFactory.h>
|
|
#include <geos/geom/util/SineStarFactory.h>
|
|
#include <geos/util/GEOSException.h>
|
|
#include <geos/util/IllegalArgumentException.h>
|
|
#include <geos/opLinemerge.h>
|
|
#include <geos/opPolygonize.h>
|
|
#include <geos/constants.h>
|
|
#include <vector>
|
|
#include <sstream>
|
|
#include <iomanip>
|
|
#include <cstdlib> // exit()
|
|
|
|
// Set to 0 to skip section
|
|
#define GEOMETRIC_SHAPES 1
|
|
#define RELATIONAL_OPERATORS 1
|
|
#define COMBINATIONS 1
|
|
#define UNARY_OPERATIONS 1
|
|
#define LINEMERGE 1
|
|
#define POLYGONIZE 1
|
|
|
|
|
|
using namespace std;
|
|
using namespace geos;
|
|
using namespace geos::geom;
|
|
using namespace geos::operation::polygonize;
|
|
using namespace geos::operation::linemerge;
|
|
using geos::util::GEOSException;
|
|
using geos::util::IllegalArgumentException;
|
|
|
|
|
|
// Prototypes
|
|
void wkt_print_geoms(vector<const Geometry*>* 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::Ptr 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<const Geometry*>* geoms)
|
|
{
|
|
stringstream s(ios_base::binary | ios_base::in | ios_base::out);
|
|
io::WKBReader wkbReader(*global_factory);
|
|
io::WKBWriter wkbWriter;
|
|
Geometry* gout;
|
|
|
|
#if DEBUG_STREAM_STATE
|
|
cout << "WKBtest: machine byte order: " << BYTE_ORDER << endl;
|
|
#endif
|
|
|
|
|
|
size_t ngeoms = geoms->size();
|
|
for(unsigned int i = 0; i < ngeoms; ++i) {
|
|
const 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).release();
|
|
|
|
#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
|
|
|
|
const_cast<Geometry*>(gin)->normalize();
|
|
gout->normalize();
|
|
int failed = gin->compareTo(gout);
|
|
if(failed) {
|
|
cout << "{" << i << "} (WKB) ";
|
|
}
|
|
else {
|
|
cout << "[" << i << "] (WKB) ";
|
|
}
|
|
|
|
io::WKBReader::printHEX(s, cout);
|
|
cout << endl;
|
|
|
|
if(failed) {
|
|
io::WKTWriter wkt;
|
|
cout << " IN: " << wkt.write(gin) << endl;
|
|
cout << " OUT: " << wkt.write(gout) << endl;
|
|
}
|
|
|
|
s.seekp(0, ios::beg); // rewind writer pointer
|
|
|
|
delete gout;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// 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<const Geometry*>* geoms)
|
|
{
|
|
WKBtest(geoms); // test WKB parser
|
|
|
|
// WKT-print given geometries
|
|
io::WKTWriter* wkt = new io::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;
|
|
}
|
|
|
|
// This is the simpler geometry you can get: a point.
|
|
Point*
|
|
create_point(double x, double y)
|
|
{
|
|
Coordinate c(x, y);
|
|
Point* p = global_factory->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
|
|
CoordinateArraySequence* cl = new CoordinateArraySequence();
|
|
|
|
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
|
|
CoordinateArraySequence* cl = new CoordinateArraySequence();
|
|
|
|
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 LinearRing pointers
|
|
vector<LinearRing*>* holes = new vector<LinearRing*>;
|
|
|
|
// 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<const Geometry*>* 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)
|
|
{
|
|
geos::util::GeometricShapeFactory shapefactory(global_factory.get());
|
|
shapefactory.setCentre(Coordinate(centerX, centerY));
|
|
shapefactory.setSize(radius);
|
|
// same as:
|
|
// shapefactory.setHeight(radius);
|
|
// shapefactory.setWidth(radius);
|
|
return shapefactory.createCircle().release();
|
|
}
|
|
|
|
//
|
|
// 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)
|
|
{
|
|
geos::util::GeometricShapeFactory shapefactory(global_factory.get());
|
|
shapefactory.setCentre(Coordinate(centerX, centerY));
|
|
shapefactory.setHeight(height);
|
|
shapefactory.setWidth(width);
|
|
return shapefactory.createCircle().release();
|
|
}
|
|
|
|
//
|
|
// 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)
|
|
{
|
|
geos::util::GeometricShapeFactory shapefactory(global_factory.get());
|
|
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().release();
|
|
}
|
|
|
|
//
|
|
// 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)
|
|
{
|
|
geos::util::GeometricShapeFactory shapefactory(global_factory.get());
|
|
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).release();
|
|
}
|
|
|
|
unique_ptr<Polygon>
|
|
create_sinestar(double cx, double cy, double size, int nArms, double armLenRat)
|
|
{
|
|
geos::geom::util::SineStarFactory fact(global_factory.get());
|
|
fact.setCentre(Coordinate(cx, cy));
|
|
fact.setSize(size);
|
|
fact.setNumPoints(nArms * 5);
|
|
fact.setArmLengthRatio(armLenRat);
|
|
fact.setNumArms(nArms);
|
|
return fact.createSineStar();
|
|
}
|
|
|
|
// Start reading here
|
|
void
|
|
do_all()
|
|
{
|
|
vector<const Geometry*>* geoms = new vector<const Geometry*>;
|
|
vector<const Geometry*>* 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 = GeometryFactory::create(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_square_linearring(0, 0, 100));
|
|
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));
|
|
|
|
#if GEOMETRIC_SHAPES
|
|
// 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));
|
|
geoms->push_back(create_sinestar(10, 10, 100, 5, 2).release()); // a sine star
|
|
#endif
|
|
|
|
// Print all geoms.
|
|
cout << "--------HERE ARE THE BASE GEOMS ----------" << endl;
|
|
wkt_print_geoms(geoms);
|
|
|
|
|
|
#if UNARY_OPERATIONS
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// UNARY OPERATIONS
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////
|
|
// CENTROID
|
|
/////////////////////////////////////////////
|
|
|
|
// Find centroid of each base geometry
|
|
newgeoms = new vector<const Geometry*>;
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
const Geometry* g = (*geoms)[i];
|
|
newgeoms->push_back(g->getCentroid().release());
|
|
}
|
|
|
|
// Print all convex hulls
|
|
cout << endl << "------- AND HERE ARE THEIR CENTROIDS -----" << endl;
|
|
wkt_print_geoms(newgeoms);
|
|
|
|
// Delete the centroids
|
|
for(unsigned int i = 0; i < newgeoms->size(); i++) {
|
|
delete(*newgeoms)[i];
|
|
}
|
|
delete newgeoms;
|
|
|
|
/////////////////////////////////////////////
|
|
// BUFFER
|
|
/////////////////////////////////////////////
|
|
|
|
newgeoms = new vector<const Geometry*>;
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
const Geometry* g = (*geoms)[i];
|
|
try {
|
|
Geometry* g2 = g->buffer(10).release();
|
|
newgeoms->push_back(g2);
|
|
}
|
|
catch(const GEOSException& exc) {
|
|
cerr << "GEOS Exception: geometry " << i << "->buffer(10): " << exc.what() << "\n";
|
|
}
|
|
}
|
|
|
|
cout << endl << "--------HERE COMES THE BUFFERED GEOMS ----------" << endl;
|
|
wkt_print_geoms(newgeoms);
|
|
|
|
for(unsigned int i = 0; i < newgeoms->size(); i++) {
|
|
delete(*newgeoms)[i];
|
|
}
|
|
delete newgeoms;
|
|
|
|
/////////////////////////////////////////////
|
|
// CONVEX HULL
|
|
/////////////////////////////////////////////
|
|
|
|
// Make convex hulls of geometries
|
|
newgeoms = new vector<const Geometry*>;
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
const Geometry* g = (*geoms)[i];
|
|
newgeoms->push_back(g->convexHull().release());
|
|
}
|
|
|
|
// Print all convex hulls
|
|
cout << endl << "--------HERE COMES THE HULLS----------" << endl;
|
|
wkt_print_geoms(newgeoms);
|
|
|
|
// Delete the hulls
|
|
for(unsigned int i = 0; i < newgeoms->size(); i++) {
|
|
delete(*newgeoms)[i];
|
|
}
|
|
delete newgeoms;
|
|
|
|
#endif // UNARY_OPERATIONS
|
|
|
|
#if RELATIONAL_OPERATORS
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// RELATIONAL OPERATORS
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
cout << "-------------------------------------------------------------------------------" << endl;
|
|
cout << "RELATIONAL OPERATORS" << endl;
|
|
cout << "-------------------------------------------------------------------------------" << endl;
|
|
|
|
/////////////////////////////////////////////
|
|
// DISJOINT
|
|
/////////////////////////////////////////////
|
|
|
|
cout << endl;
|
|
cout << " DISJOINT ";
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
cout << "\t[" << i << "]";
|
|
}
|
|
cout << endl;
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
const Geometry* g1 = (*geoms)[i];
|
|
cout << " [" << i << "]\t";
|
|
for(unsigned int j = 0; j < geoms->size(); j++) {
|
|
const Geometry* g2 = (*geoms)[j];
|
|
try {
|
|
if(g1->disjoint(g2)) {
|
|
cout << " 1\t";
|
|
}
|
|
else {
|
|
cout << " 0\t";
|
|
}
|
|
}
|
|
// Geometry Collection is not a valid argument
|
|
catch(const IllegalArgumentException&) {
|
|
cout << " X\t";
|
|
}
|
|
catch(const std::exception& exc) {
|
|
cerr << exc.what() << endl;
|
|
}
|
|
}
|
|
cout << endl;
|
|
}
|
|
|
|
/////////////////////////////////////////////
|
|
// TOUCHES
|
|
/////////////////////////////////////////////
|
|
|
|
cout << endl;
|
|
cout << " TOUCHES ";
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
cout << "\t[" << i << "]";
|
|
}
|
|
cout << endl;
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
const Geometry* g1 = (*geoms)[i];
|
|
cout << " [" << i << "]\t";
|
|
for(unsigned int j = 0; j < geoms->size(); j++) {
|
|
const Geometry* g2 = (*geoms)[j];
|
|
try {
|
|
if(g1->touches(g2)) {
|
|
cout << " 1\t";
|
|
}
|
|
else {
|
|
cout << " 0\t";
|
|
}
|
|
}
|
|
// Geometry Collection is not a valid argument
|
|
catch(const IllegalArgumentException&) {
|
|
cout << " X\t";
|
|
}
|
|
catch(const std::exception& exc) {
|
|
cerr << exc.what() << endl;
|
|
}
|
|
}
|
|
cout << endl;
|
|
}
|
|
|
|
/////////////////////////////////////////////
|
|
// INTERSECTS
|
|
/////////////////////////////////////////////
|
|
|
|
cout << endl;
|
|
cout << " INTERSECTS ";
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
cout << "\t[" << i << "]";
|
|
}
|
|
cout << endl;
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
const Geometry* g1 = (*geoms)[i];
|
|
cout << " [" << i << "]\t";
|
|
for(unsigned int j = 0; j < geoms->size(); j++) {
|
|
const Geometry* g2 = (*geoms)[j];
|
|
try {
|
|
if(g1->intersects(g2)) {
|
|
cout << " 1\t";
|
|
}
|
|
else {
|
|
cout << " 0\t";
|
|
}
|
|
}
|
|
// Geometry Collection is not a valid argument
|
|
catch(const IllegalArgumentException&) {
|
|
cout << " X\t";
|
|
}
|
|
catch(const std::exception& exc) {
|
|
cerr << exc.what() << endl;
|
|
}
|
|
}
|
|
cout << endl;
|
|
}
|
|
|
|
/////////////////////////////////////////////
|
|
// CROSSES
|
|
/////////////////////////////////////////////
|
|
|
|
cout << endl;
|
|
cout << " CROSSES ";
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
cout << "\t[" << i << "]";
|
|
}
|
|
cout << endl;
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
const Geometry* g1 = (*geoms)[i];
|
|
cout << " [" << i << "]\t";
|
|
for(unsigned int j = 0; j < geoms->size(); j++) {
|
|
const Geometry* g2 = (*geoms)[j];
|
|
try {
|
|
if(g1->crosses(g2)) {
|
|
cout << " 1\t";
|
|
}
|
|
else {
|
|
cout << " 0\t";
|
|
}
|
|
}
|
|
// Geometry Collection is not a valid argument
|
|
catch(const IllegalArgumentException&) {
|
|
cout << " X\t";
|
|
}
|
|
catch(const std::exception& exc) {
|
|
cerr << exc.what() << endl;
|
|
}
|
|
}
|
|
cout << endl;
|
|
}
|
|
|
|
/////////////////////////////////////////////
|
|
// WITHIN
|
|
/////////////////////////////////////////////
|
|
|
|
cout << endl;
|
|
cout << " WITHIN ";
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
cout << "\t[" << i << "]";
|
|
}
|
|
cout << endl;
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
const Geometry* g1 = (*geoms)[i];
|
|
cout << " [" << i << "]\t";
|
|
for(unsigned int j = 0; j < geoms->size(); j++) {
|
|
const Geometry* g2 = (*geoms)[j];
|
|
try {
|
|
if(g1->within(g2)) {
|
|
cout << " 1\t";
|
|
}
|
|
else {
|
|
cout << " 0\t";
|
|
}
|
|
}
|
|
// Geometry Collection is not a valid argument
|
|
catch(const IllegalArgumentException&) {
|
|
cout << " X\t";
|
|
}
|
|
catch(const std::exception& exc) {
|
|
cerr << exc.what() << endl;
|
|
}
|
|
}
|
|
cout << endl;
|
|
}
|
|
|
|
/////////////////////////////////////////////
|
|
// CONTAINS
|
|
/////////////////////////////////////////////
|
|
|
|
cout << endl;
|
|
cout << " CONTAINS ";
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
cout << "\t[" << i << "]";
|
|
}
|
|
cout << endl;
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
const Geometry* g1 = (*geoms)[i];
|
|
cout << " [" << i << "]\t";
|
|
for(unsigned int j = 0; j < geoms->size(); j++) {
|
|
const Geometry* g2 = (*geoms)[j];
|
|
try {
|
|
if(g1->contains(g2)) {
|
|
cout << " 1\t";
|
|
}
|
|
else {
|
|
cout << " 0\t";
|
|
}
|
|
}
|
|
// Geometry Collection is not a valid argument
|
|
catch(const IllegalArgumentException&) {
|
|
cout << " X\t";
|
|
}
|
|
catch(const std::exception& exc) {
|
|
cerr << exc.what() << endl;
|
|
}
|
|
}
|
|
cout << endl;
|
|
}
|
|
|
|
/////////////////////////////////////////////
|
|
// OVERLAPS
|
|
/////////////////////////////////////////////
|
|
|
|
cout << endl;
|
|
cout << " OVERLAPS ";
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
cout << "\t[" << i << "]";
|
|
}
|
|
cout << endl;
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
const Geometry* g1 = (*geoms)[i];
|
|
cout << " [" << i << "]\t";
|
|
for(unsigned int j = 0; j < geoms->size(); j++) {
|
|
const Geometry* g2 = (*geoms)[j];
|
|
try {
|
|
if(g1->overlaps(g2)) {
|
|
cout << " 1\t";
|
|
}
|
|
else {
|
|
cout << " 0\t";
|
|
}
|
|
}
|
|
// Geometry Collection is not a valid argument
|
|
catch(const IllegalArgumentException&) {
|
|
cout << " X\t";
|
|
}
|
|
catch(const std::exception& exc) {
|
|
cerr << exc.what() << endl;
|
|
}
|
|
}
|
|
cout << endl;
|
|
}
|
|
|
|
/////////////////////////////////////////////
|
|
// RELATE
|
|
/////////////////////////////////////////////
|
|
|
|
cout << endl;
|
|
cout << " RELATE ";
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
cout << "\t[" << i << "]";
|
|
}
|
|
cout << endl;
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
const Geometry* g1 = (*geoms)[i];
|
|
cout << " [" << i << "]\t";
|
|
for(unsigned int j = 0; j < geoms->size(); j++) {
|
|
const Geometry* g2 = (*geoms)[j];
|
|
try {
|
|
// second argument is intersectionPattern
|
|
string pattern = "212101212";
|
|
if(g1->relate(g2, pattern)) {
|
|
cout << " 1\t";
|
|
}
|
|
else {
|
|
cout << " 0\t";
|
|
}
|
|
|
|
// get the intersectionMatrix itself
|
|
auto im = g1->relate(g2);
|
|
}
|
|
// Geometry Collection is not a valid argument
|
|
catch(const IllegalArgumentException&) {
|
|
cout << " X\t";
|
|
}
|
|
catch(const std::exception& exc) {
|
|
cerr << exc.what() << endl;
|
|
}
|
|
}
|
|
cout << endl;
|
|
}
|
|
|
|
/////////////////////////////////////////////
|
|
// EQUALS
|
|
/////////////////////////////////////////////
|
|
|
|
cout << endl;
|
|
cout << " EQUALS ";
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
cout << "\t[" << i << "]";
|
|
}
|
|
cout << endl;
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
const Geometry* g1 = (*geoms)[i];
|
|
cout << " [" << i << "]\t";
|
|
for(unsigned int j = 0; j < geoms->size(); j++) {
|
|
const Geometry* g2 = (*geoms)[j];
|
|
try {
|
|
if(g1->equals(g2)) {
|
|
cout << " 1\t";
|
|
}
|
|
else {
|
|
cout << " 0\t";
|
|
}
|
|
}
|
|
// Geometry Collection is not a valid argument
|
|
catch(const IllegalArgumentException&) {
|
|
cout << " X\t";
|
|
}
|
|
catch(const std::exception& exc) {
|
|
cerr << exc.what() << endl;
|
|
}
|
|
}
|
|
cout << endl;
|
|
}
|
|
|
|
/////////////////////////////////////////////
|
|
// EQUALS_EXACT
|
|
/////////////////////////////////////////////
|
|
|
|
cout << endl;
|
|
cout << "EQUALS_EXACT ";
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
cout << "\t[" << i << "]";
|
|
}
|
|
cout << endl;
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
const Geometry* g1 = (*geoms)[i];
|
|
cout << " [" << i << "]\t";
|
|
for(unsigned int j = 0; j < geoms->size(); j++) {
|
|
const 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(const IllegalArgumentException&) {
|
|
cout << " X\t";
|
|
}
|
|
catch(const std::exception& exc) {
|
|
cerr << exc.what() << endl;
|
|
}
|
|
}
|
|
cout << endl;
|
|
}
|
|
|
|
/////////////////////////////////////////////
|
|
// IS_WITHIN_DISTANCE
|
|
/////////////////////////////////////////////
|
|
|
|
cout << endl;
|
|
cout << "IS_WITHIN_DIST";
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
cout << "\t[" << i << "]";
|
|
}
|
|
cout << endl;
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
const Geometry* g1 = (*geoms)[i];
|
|
cout << " [" << i << "]\t";
|
|
for(unsigned int j = 0; j < geoms->size(); j++) {
|
|
const 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(const IllegalArgumentException&) {
|
|
cout << " X\t";
|
|
}
|
|
catch(const std::exception& exc) {
|
|
cerr << exc.what() << endl;
|
|
}
|
|
}
|
|
cout << endl;
|
|
}
|
|
|
|
#endif // RELATIONAL_OPERATORS
|
|
|
|
#if COMBINATIONS
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// COMBINATIONS
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
cout << endl;
|
|
cout << "-------------------------------------------------------------------------------" << endl;
|
|
cout << "COMBINATIONS" << endl;
|
|
cout << "-------------------------------------------------------------------------------" << endl;
|
|
|
|
/////////////////////////////////////////////
|
|
// UNION
|
|
/////////////////////////////////////////////
|
|
|
|
// Make unions of all geoms
|
|
newgeoms = new vector<const Geometry*>;
|
|
for(unsigned int i = 0; i < geoms->size() - 1; i++) {
|
|
const Geometry* g1 = (*geoms)[i];
|
|
for(unsigned int j = i + 1; j < geoms->size(); j++) {
|
|
const Geometry* g2 = (*geoms)[j];
|
|
try {
|
|
Geometry* g3 = g1->Union(g2).release();
|
|
newgeoms->push_back(g3);
|
|
}
|
|
// It's illegal to union a collection ...
|
|
catch(const IllegalArgumentException&) {
|
|
//cerr <<ill.toString()<<"\n";
|
|
}
|
|
catch(const std::exception& exc) {
|
|
cerr << exc.what() << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Print all unions
|
|
cout << endl << "----- AND HERE ARE SOME UNION COMBINATIONS ------" << endl;
|
|
wkt_print_geoms(newgeoms);
|
|
|
|
// Delete the resulting geoms
|
|
for(unsigned int i = 0; i < newgeoms->size(); i++) {
|
|
delete(*newgeoms)[i];
|
|
}
|
|
delete newgeoms;
|
|
|
|
|
|
/////////////////////////////////////////////
|
|
// INTERSECTION
|
|
/////////////////////////////////////////////
|
|
|
|
// Compute intersection of adjacent geometries
|
|
newgeoms = new vector<const Geometry*>;
|
|
for(unsigned int i = 0; i < geoms->size() - 1; i++) {
|
|
const Geometry* g1 = (*geoms)[i];
|
|
for(unsigned int j = i + 1; j < geoms->size(); j++) {
|
|
const Geometry* g2 = (*geoms)[j];
|
|
try {
|
|
Geometry* g3 = g1->intersection(g2).release();
|
|
newgeoms->push_back(g3);
|
|
}
|
|
// Collection are illegal as intersection argument
|
|
catch(const IllegalArgumentException&) {
|
|
//cerr <<ill.toString()<<"\n";
|
|
}
|
|
catch(const std::exception& exc) {
|
|
cerr << exc.what() << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
cout << endl << "----- HERE ARE SOME INTERSECTIONS COMBINATIONS ------" << endl;
|
|
wkt_print_geoms(newgeoms);
|
|
|
|
// Delete the resulting geoms
|
|
for(unsigned int i = 0; i < newgeoms->size(); i++) {
|
|
delete(*newgeoms)[i];
|
|
}
|
|
delete newgeoms;
|
|
|
|
/////////////////////////////////////////////
|
|
// DIFFERENCE
|
|
/////////////////////////////////////////////
|
|
|
|
// Compute difference of adhiacent geometries
|
|
newgeoms = new vector<const Geometry*>;
|
|
for(unsigned int i = 0; i < geoms->size() - 1; i++) {
|
|
const Geometry* g1 = (*geoms)[i];
|
|
for(unsigned int j = i + 1; j < geoms->size(); j++) {
|
|
const Geometry* g2 = (*geoms)[j];
|
|
try {
|
|
Geometry* g3 = g1->difference(g2).release();
|
|
newgeoms->push_back(g3);
|
|
}
|
|
// Collection are illegal as difference argument
|
|
catch(const IllegalArgumentException&) {
|
|
//cerr <<ill.toString()<<"\n";
|
|
}
|
|
catch(const std::exception& exc) {
|
|
cerr << exc.what() << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
cout << endl << "----- HERE ARE SOME DIFFERENCE COMBINATIONS ------" << endl;
|
|
wkt_print_geoms(newgeoms);
|
|
|
|
// Delete the resulting geoms
|
|
for(unsigned int i = 0; i < newgeoms->size(); i++) {
|
|
delete(*newgeoms)[i];
|
|
}
|
|
delete newgeoms;
|
|
|
|
/////////////////////////////////////////////
|
|
// SYMMETRIC DIFFERENCE
|
|
/////////////////////////////////////////////
|
|
|
|
// Compute symmetric difference of adhiacent geometries
|
|
newgeoms = new vector<const Geometry*>;
|
|
for(unsigned int i = 0; i < geoms->size() - 1; i++) {
|
|
const Geometry* g1 = (*geoms)[i];
|
|
for(unsigned int j = i + 1; j < geoms->size(); j++) {
|
|
const Geometry* g2 = (*geoms)[j];
|
|
try {
|
|
Geometry* g3 = g1->symDifference(g2).release();
|
|
newgeoms->push_back(g3);
|
|
}
|
|
// Collection are illegal as symdifference argument
|
|
catch(const IllegalArgumentException&) {
|
|
//cerr <<ill.toString()<<"\n";
|
|
}
|
|
catch(const std::exception& exc) {
|
|
cerr << exc.what() << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
cout << endl << "----- HERE ARE SYMMETRIC DIFFERENCES ------" << endl;
|
|
wkt_print_geoms(newgeoms);
|
|
|
|
// Delete the resulting geoms
|
|
for(unsigned int i = 0; i < newgeoms->size(); i++) {
|
|
delete(*newgeoms)[i];
|
|
}
|
|
delete newgeoms;
|
|
|
|
#endif // COMBINATIONS
|
|
|
|
#if LINEMERGE
|
|
|
|
/////////////////////////////////////////////
|
|
// LINEMERGE
|
|
/////////////////////////////////////////////
|
|
LineMerger lm;
|
|
lm.add(geoms);
|
|
vector<LineString*>* mls = lm.getMergedLineStrings();
|
|
newgeoms = new vector<const Geometry*>;
|
|
for(unsigned int i = 0; i < mls->size(); i++) {
|
|
newgeoms->push_back((*mls)[i]);
|
|
}
|
|
delete mls;
|
|
|
|
cout << endl << "----- HERE IS THE LINEMERGE OUTPUT ------" << endl;
|
|
wkt_print_geoms(newgeoms);
|
|
|
|
// Delete the resulting geoms
|
|
for(unsigned int i = 0; i < newgeoms->size(); i++) {
|
|
delete(*newgeoms)[i];
|
|
}
|
|
delete newgeoms;
|
|
|
|
#endif // LINEMERGE
|
|
|
|
#if POLYGONIZE
|
|
|
|
/////////////////////////////////////////////
|
|
// POLYGONIZE
|
|
/////////////////////////////////////////////
|
|
Polygonizer plgnzr;
|
|
plgnzr.add(geoms);
|
|
auto polys = plgnzr.getPolygons();
|
|
newgeoms = new vector<const Geometry*>;
|
|
for(unsigned int i = 0; i < polys->size(); i++) {
|
|
newgeoms->push_back((*polys)[i].release());
|
|
}
|
|
|
|
cout << endl << "----- HERE IS POLYGONIZE OUTPUT ------" << endl;
|
|
wkt_print_geoms(newgeoms);
|
|
|
|
// Delete the resulting geoms
|
|
for(unsigned int i = 0; i < newgeoms->size(); i++) {
|
|
delete(*newgeoms)[i];
|
|
}
|
|
delete newgeoms;
|
|
|
|
#endif // POLYGONIZE
|
|
|
|
/////////////////////////////////////////////
|
|
// CLEANUP
|
|
/////////////////////////////////////////////
|
|
|
|
// Delete base geometries
|
|
for(unsigned int i = 0; i < geoms->size(); i++) {
|
|
delete(*geoms)[i];
|
|
}
|
|
delete geoms;
|
|
}
|
|
|
|
int
|
|
main()
|
|
{
|
|
cout << "GEOS " << geosversion() << " ported from JTS " << jtsport() << endl;
|
|
try {
|
|
do_all();
|
|
}
|
|
// All exception thrown by GEOS are subclasses of this
|
|
// one, so this is a catch-all
|
|
catch(const GEOSException& exc) {
|
|
cerr << "GEOS Exception: " << exc.what() << "\n";
|
|
exit(1);
|
|
}
|
|
catch(const exception& e) {
|
|
cerr << "Standard exception thrown: " << e.what() << endl;
|
|
exit(1);
|
|
}
|
|
// and this is a catch-all non standard ;)
|
|
catch(...) {
|
|
cerr << "unknown exception trown!\n";
|
|
exit(1);
|
|
}
|
|
|
|
// Unload is no more necessary
|
|
//io::Unload::Release();
|
|
|
|
exit(0);
|
|
}
|