49#ifndef GEOS_GEOM_BINARYOP_H
50#define GEOS_GEOM_BINARYOP_H
52#include <geos/algorithm/BoundaryNodeRule.h>
53#include <geos/geom/Geometry.h>
54#include <geos/geom/GeometryCollection.h>
55#include <geos/geom/Polygon.h>
56#include <geos/geom/Lineal.h>
57#include <geos/geom/PrecisionModel.h>
58#include <geos/geom/GeometryFactory.h>
59#include <geos/precision/CommonBitsRemover.h>
60#include <geos/precision/SimpleGeometryPrecisionReducer.h>
61#include <geos/precision/GeometryPrecisionReducer.h>
63#include <geos/operation/overlay/snap/GeometrySnapper.h>
65#include <geos/simplify/TopologyPreservingSimplifier.h>
66#include <geos/operation/IsSimpleOp.h>
67#include <geos/operation/valid/IsValidOp.h>
68#include <geos/operation/valid/TopologyValidationError.h>
69#include <geos/util/TopologyException.h>
76#ifdef GEOS_DEBUG_BINARYOP
86#ifndef USE_ORIGINAL_INPUT
87# define USE_ORIGINAL_INPUT 1
95#ifndef USE_PRECISION_REDUCTION_POLICY
96# define USE_PRECISION_REDUCTION_POLICY 1
104#ifndef USE_TP_SIMPLIFY_POLICY
113#ifndef USE_COMMONBITS_POLICY
114# define USE_COMMONBITS_POLICY 1
128#define GEOS_CHECK_COMMONBITS_VALIDITY 1
133#ifndef USE_SNAPPING_POLICY
134# define USE_SNAPPING_POLICY 1
141check_valid(
const Geometry& g,
const std::string& label,
bool doThrow=
false,
bool validOnly=
false)
143 if (
dynamic_cast<const Lineal*
>(&g) ) {
146 if ( ! sop.isSimple() )
149 throw geos::util::TopologyException(
150 label +
" is not simple");
156 operation::valid::IsValidOp ivo(&g);
157 if ( ! ivo.isValid() )
159 using operation::valid::TopologyValidationError;
160 TopologyValidationError* err = ivo.getValidationError();
161#ifdef GEOS_DEBUG_BINARYOP
162 std::cerr << label <<
" is INVALID: "
164 <<
" (" << std::setprecision(20)
165 << err->getCoordinate() <<
")"
169 throw geos::util::TopologyException(
170 label +
" is invalid: " + err->toString(),
171 err->getCoordinate());
185inline std::auto_ptr<Geometry>
186fix_self_intersections(std::auto_ptr<Geometry> g,
const std::string& label)
188 ::geos::ignore_unused_variable_warning(label);
189#ifdef GEOS_DEBUG_BINARYOP
190 std::cerr << label <<
" fix_self_intersection (UnaryUnion)" << std::endl;
196 using operation::valid::IsValidOp;
198 IsValidOp ivo(g.get());
201 if ( ivo.isValid() )
return g;
205 using operation::valid::TopologyValidationError;
206 TopologyValidationError* err = ivo.getValidationError();
207 switch ( err->getErrorType() ) {
208 case TopologyValidationError::eRingSelfIntersection:
209 case TopologyValidationError::eTooFewPoints:
210#ifdef GEOS_DEBUG_BINARYOP
211 std::cerr << label <<
" ATTEMPT_TO_FIX: " << err->getErrorType() <<
": " << *g << std::endl;
214#ifdef GEOS_DEBUG_BINARYOP
215 std::cerr << label <<
" ATTEMPT_TO_FIX succeeded.. " << std::endl;
218 case TopologyValidationError::eSelfIntersection:
221#ifdef GEOS_DEBUG_BINARYOP
222 std::cerr << label <<
" invalidity is: " << err->getErrorType() << std::endl;
234template <
class BinOp>
235std::auto_ptr<Geometry>
238 typedef std::auto_ptr<Geometry> GeomPtr;
240#define CBR_BEFORE_SNAPPING 1
247 double snapTolerance = GeometrySnapper::computeOverlaySnapTolerance(*g0, *g1);
248#if GEOS_DEBUG_BINARYOP
249 std::cerr<< std::setprecision(20) <<
"Computed snap tolerance: "<<snapTolerance<<std::endl;
253#if CBR_BEFORE_SNAPPING
257#if GEOS_DEBUG_BINARYOP
265#if GEOS_DEBUG_BINARYOP
266 check_valid(*rG0,
"CBR: removed-bits geom 0");
267 check_valid(*rG1,
"CBR: removed-bits geom 1");
278 GeometrySnapper snapper0( operand0 );
279 GeomPtr snapG0( snapper0.snapTo(operand1, snapTolerance) );
283 GeometrySnapper snapper1( operand1 );
284 GeomPtr snapG1( snapper1.snapTo(*snapG0, snapTolerance) );
288 GeomPtr result( _Op(snapG0.get(), snapG1.get()) );
290#if GEOS_DEBUG_BINARYOP
291 check_valid(*result,
"SNAP: result (before common-bits addition");
294#if CBR_BEFORE_SNAPPING
299 check_valid(*result,
"CBR: result (after common-bits addition)",
true);
306template <
class BinOp>
307std::auto_ptr<Geometry>
308BinaryOp(
const Geometry* g0,
const Geometry *g1, BinOp _Op)
310 typedef std::auto_ptr<Geometry> GeomPtr;
315#ifdef USE_ORIGINAL_INPUT
319#if GEOS_DEBUG_BINARYOP
320 std::cerr <<
"Trying with original input." << std::endl;
322 ret.reset(_Op(g0, g1));
328#if GEOS_DEBUG_BINARYOP
329 std::cerr <<
"Original exception: " << ex.what() << std::endl;
333 check_valid(*g0,
"Input geom 0",
true,
true);
334 check_valid(*g1,
"Input geom 1",
true,
true);
336#if GEOS_DEBUG_BINARYOP
338 check_valid(*g0,
"Input geom 0");
339 check_valid(*g1,
"Input geom 1");
344#ifdef USE_COMMONBITS_POLICY
356 precision::CommonBitsRemover cbr;
358#if GEOS_DEBUG_BINARYOP
359 std::cerr <<
"Trying with Common Bits Remover (CBR)" << std::endl;
365 rG0.reset( cbr.removeCommonBits(g0->clone()) );
366 rG1.reset( cbr.removeCommonBits(g1->clone()) );
368#if GEOS_DEBUG_BINARYOP
369 check_valid(*rG0,
"CBR: geom 0 (after common-bits removal)");
370 check_valid(*rG1,
"CBR: geom 1 (after common-bits removal)");
373 ret.reset( _Op(rG0.get(), rG1.get()) );
375#if GEOS_DEBUG_BINARYOP
376 check_valid(*ret,
"CBR: result (before common-bits addition)");
379 cbr.addCommonBits( ret.get() );
381 check_valid(*ret,
"CBR: result (after common-bits addition)",
true);
383#if GEOS_CHECK_COMMONBITS_VALIDITY
386 using operation::valid::IsValidOp;
387 using operation::valid::TopologyValidationError;
388 IsValidOp ivo(ret.get());
389 if ( ! ivo.isValid() )
391 TopologyValidationError* e = ivo.getValidationError();
392 throw geos::util::TopologyException(
393 "Result of overlay became invalid "
394 "after re-addin common bits of operand "
395 "coordinates: " + e->toString(),
402 catch (
const geos::util::TopologyException& ex)
404 ::geos::ignore_unused_variable_warning(ex);
405#if GEOS_DEBUG_BINARYOP
406 std::cerr <<
"CBR: " << ex.what() << std::endl;
418#if USE_SNAPPING_POLICY
420#if GEOS_DEBUG_BINARYOP
421 std::cerr <<
"Trying with snapping " << std::endl;
425 ret =
SnapOp(g0, g1, _Op);
426#if GEOS_DEBUG_BINARYOP
427 std::cerr <<
"SnapOp succeeded" << std::endl;
432 catch (
const geos::util::TopologyException& ex)
434 ::geos::ignore_unused_variable_warning(ex);
435#if GEOS_DEBUG_BINARYOP
436 std::cerr <<
"SNAP: " << ex.what() << std::endl;
443#if USE_PRECISION_REDUCTION_POLICY
449 long unsigned int g0scale =
450 static_cast<long unsigned int>(g0->getFactory()->getPrecisionModel()->getScale());
451 long unsigned int g1scale =
452 static_cast<long unsigned int>(g1->getFactory()->getPrecisionModel()->getScale());
454#if GEOS_DEBUG_BINARYOP
455 std::cerr <<
"Original input scales are: "
462 double maxScale = 1e16;
465 if ( g0scale && g0scale < maxScale ) maxScale = g0scale;
466 if ( g1scale && g1scale < maxScale ) maxScale = g1scale;
469 for (
double scale=maxScale; scale >= 1; scale /= 10)
473#if GEOS_DEBUG_BINARYOP
474 std::cerr <<
"Trying with scale " << scale << std::endl;
477 precision::GeometryPrecisionReducer reducer( *gf );
478 GeomPtr rG0( reducer.reduce(*g0) );
479 GeomPtr rG1( reducer.reduce(*g1) );
483 ret.reset( _Op(rG0.get(), rG1.get()) );
485 if ( g0->getFactory()->getPrecisionModel()->compareTo( g1->getFactory()->getPrecisionModel() ) < 0 ) {
486 ret.reset( g0->getFactory()->createGeometry(ret.get()) );
489 ret.reset( g1->getFactory()->createGeometry(ret.get()) );
493 catch (
const geos::util::TopologyException& ex)
495 if ( scale == 1 )
throw ex;
496#if GEOS_DEBUG_BINARYOP
497 std::cerr <<
"Reduced with scale (" << scale <<
"): "
498 << ex.what() << std::endl;
505 catch (
const geos::util::TopologyException& ex)
507#if GEOS_DEBUG_BINARYOP
508 std::cerr <<
"Reduced: " << ex.what() << std::endl;
510 ::geos::ignore_unused_variable_warning(ex);
521#if USE_TP_SIMPLIFY_POLICY
527 double maxTolerance = 0.04;
528 double minTolerance = 0.01;
529 double tolStep = 0.01;
531 for (
double tol = minTolerance; tol <= maxTolerance; tol += tolStep)
533#if GEOS_DEBUG_BINARYOP
534 std::cerr <<
"Trying simplifying with tolerance " << tol << std::endl;
537 GeomPtr rG0( simplify::TopologyPreservingSimplifier::simplify(g0, tol) );
538 GeomPtr rG1( simplify::TopologyPreservingSimplifier::simplify(g1, tol) );
542 ret.reset( _Op(rG0.get(), rG1.get()) );
545 catch (
const geos::util::TopologyException& ex)
547 if ( tol >= maxTolerance )
throw ex;
548#if GEOS_DEBUG_BINARYOP
549 std::cerr <<
"Simplified with tolerance (" << tol <<
"): "
550 << ex.what() << std::endl;
559 catch (
const geos::util::TopologyException& ex)
561#if GEOS_DEBUG_BINARYOP
562 std::cerr <<
"Simplified: " << ex.what() << std::endl;
static const BoundaryNodeRule & getBoundaryEndPoint()
The Endpoint Boundary Node Rule.
Represents a collection of heterogeneous Geometry objects.
Definition GeometryCollection.h:56
static GeometryFactory::unique_ptr create()
Constructs a GeometryFactory that generates Geometries having a floating PrecisionModel and a spatial...
Basic implementation of Geometry, constructed and destructed by GeometryFactory.
Definition Geometry.h:167
virtual Geometry * clone() const =0
Make a deep-copy of this Geometry.
Specifies the precision model of the Coordinate in a Geometry.
Definition PrecisionModel.h:87
Snaps the vertices and segments of a Geometry to another Geometry's vertices.
Definition GeometrySnapper.h:58
Allow computing and removing common mantissa bits from one or more Geometries.
Definition CommonBitsRemover.h:40
geom::Coordinate & getCommonCoordinate()
geom::Geometry * addCommonBits(geom::Geometry *geom)
Adds the common coordinate bits back into a Geometry. The coordinates of the Geometry are changed.
geom::Geometry * removeCommonBits(geom::Geometry *geom)
Removes the common coordinate bits from a Geometry. The coordinates of the Geometry are changed.
void add(const geom::Geometry *geom)
Indicates an invalid or inconsistent topological situation encountered during processing.
Definition TopologyException.h:35
Contains the Geometry interface hierarchy and supporting classes.
Definition IndexedNestedRingTester.h:26
std::auto_ptr< Geometry > SnapOp(const Geometry *g0, const Geometry *g1, BinOp _Op)
Apply a binary operation to the given geometries after snapping them to each other after common-bits ...
Definition BinaryOp.h:236
Basic namespace for all GEOS functionalities.
Definition IndexedNestedRingTester.h:25