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/PrecisionModel.h> 57 #include <geos/geom/GeometryFactory.h> 58 #include <geos/precision/CommonBitsRemover.h> 59 #include <geos/precision/SimpleGeometryPrecisionReducer.h> 60 #include <geos/precision/GeometryPrecisionReducer.h> 62 #include <geos/operation/overlay/snap/GeometrySnapper.h> 64 #include <geos/simplify/TopologyPreservingSimplifier.h> 65 #include <geos/operation/IsSimpleOp.h> 66 #include <geos/operation/valid/IsValidOp.h> 67 #include <geos/operation/valid/TopologyValidationError.h> 68 #include <geos/util/TopologyException.h> 69 #include <geos/util.h> 74 #define GEOS_DEBUG_BINARYOP_PRINT_INVALID 1 76 #ifdef GEOS_DEBUG_BINARYOP 86 #ifndef USE_ORIGINAL_INPUT 87 # define USE_ORIGINAL_INPUT 1 93 #define GEOS_CHECK_ORIGINAL_RESULT_VALIDITY 0 101 #ifndef USE_PRECISION_REDUCTION_POLICY 102 # define USE_PRECISION_REDUCTION_POLICY 1 114 #define GEOS_CHECK_PRECISION_REDUCTION_VALIDITY 0 121 #ifndef USE_TP_SIMPLIFY_POLICY 130 #ifndef USE_COMMONBITS_POLICY 131 # define USE_COMMONBITS_POLICY 1 145 #define GEOS_CHECK_COMMONBITS_VALIDITY 1 150 #ifndef USE_SNAPPING_POLICY 151 # define USE_SNAPPING_POLICY 1 155 #ifndef CBR_BEFORE_SNAPPING 156 # define CBR_BEFORE_SNAPPING 1 163 #define GEOS_CHECK_SNAPPINGOP_VALIDITY 0 170 check_valid(
const Geometry& g,
const std::string& label,
bool doThrow =
false,
bool validOnly =
false)
175 if(! sop.isSimple()) {
178 label +
" is not simple");
185 operation::valid::IsValidOp ivo(&g);
186 if(! ivo.isValid()) {
187 using operation::valid::TopologyValidationError;
188 TopologyValidationError* err = ivo.getValidationError();
189 #ifdef GEOS_DEBUG_BINARYOP 190 std::cerr << label <<
" is INVALID: " 192 <<
" (" << std::setprecision(20)
193 << err->getCoordinate() <<
")" 195 #ifdef GEOS_DEBUG_BINARYOP_PRINT_INVALID 196 <<
"<A>" << std::endl
199 <<
"</A>" << std::endl
205 label +
" is invalid: " + err->toString(),
206 err->getCoordinate());
220 inline std::unique_ptr<Geometry>
221 fix_self_intersections(std::unique_ptr<Geometry> g,
const std::string& label)
223 ::geos::ignore_unused_variable_warning(label);
224 #ifdef GEOS_DEBUG_BINARYOP 225 std::cerr << label <<
" fix_self_intersection (UnaryUnion)" << std::endl;
229 if(! dynamic_cast<const GeometryCollection*>(g.get())) {
233 using operation::valid::IsValidOp;
235 IsValidOp ivo(g.get());
244 using operation::valid::TopologyValidationError;
245 TopologyValidationError* err = ivo.getValidationError();
246 switch(err->getErrorType()) {
247 case TopologyValidationError::eRingSelfIntersection:
248 case TopologyValidationError::eTooFewPoints:
249 #ifdef GEOS_DEBUG_BINARYOP 250 std::cerr << label <<
" ATTEMPT_TO_FIX: " << err->getErrorType() <<
": " << *g << std::endl;
253 #ifdef GEOS_DEBUG_BINARYOP 254 std::cerr << label <<
" ATTEMPT_TO_FIX succeeded.. " << std::endl;
257 case TopologyValidationError::eSelfIntersection:
260 #ifdef GEOS_DEBUG_BINARYOP 261 std::cerr << label <<
" invalidity is: " << err->getErrorType() << std::endl;
273 template <
class BinOp>
274 std::unique_ptr<Geometry>
277 typedef std::unique_ptr<Geometry> GeomPtr;
284 double snapTolerance = GeometrySnapper::computeOverlaySnapTolerance(*g0, *g1);
285 #if GEOS_DEBUG_BINARYOP 286 std::cerr << std::setprecision(20) <<
"Computed snap tolerance: " << snapTolerance << std::endl;
290 #if CBR_BEFORE_SNAPPING 295 #if GEOS_DEBUG_BINARYOP 300 GeomPtr rG0 = g0->
clone();
302 GeomPtr rG1 = g1->
clone();
305 #if GEOS_DEBUG_BINARYOP 306 check_valid(*rG0,
"CBR: removed-bits geom 0");
307 check_valid(*rG1,
"CBR: removed-bits geom 1");
312 #else // don't CBR before snapping 318 GeometrySnapper snapper0(operand0);
319 GeomPtr snapG0(snapper0.snapTo(operand1, snapTolerance));
323 GeometrySnapper snapper1(operand1);
324 GeomPtr snapG1(snapper1.snapTo(*snapG0, snapTolerance));
328 GeomPtr result(_Op(snapG0.get(), snapG1.get()));
330 #if GEOS_DEBUG_BINARYOP 331 check_valid(*result,
"SNAP: result (before common-bits addition");
334 #if CBR_BEFORE_SNAPPING 339 check_valid(*result,
"CBR: result (after common-bits addition)",
true);
346 template <
class BinOp>
347 std::unique_ptr<Geometry>
348 BinaryOp(
const Geometry* g0,
const Geometry* g1, BinOp _Op)
350 typedef std::unique_ptr<Geometry> GeomPtr;
355 #ifdef USE_ORIGINAL_INPUT 358 #if GEOS_DEBUG_BINARYOP 359 std::cerr <<
"Trying with original input." << std::endl;
361 ret.reset(_Op(g0, g1));
363 #if GEOS_CHECK_ORIGINAL_RESULT_VALIDITY 364 check_valid(*ret,
"Overlay result between original inputs",
true,
true);
367 #if GEOS_DEBUG_BINARYOP 368 std::cerr <<
"Attempt with original input succeeded" << std::endl;
374 #if GEOS_DEBUG_BINARYOP 375 std::cerr <<
"Original exception: " << ex.what() << std::endl;
378 #endif // USE_ORIGINAL_INPUT 380 check_valid(*g0,
"Input geom 0",
true,
true);
381 check_valid(*g1,
"Input geom 1",
true,
true);
383 #if USE_COMMONBITS_POLICY 394 precision::CommonBitsRemover cbr;
396 #if GEOS_DEBUG_BINARYOP 397 std::cerr <<
"Trying with Common Bits Remover (CBR)" << std::endl;
404 cbr.removeCommonBits(rG0.get());
407 cbr.removeCommonBits(rG1.get());
409 #if GEOS_DEBUG_BINARYOP 410 check_valid(*rG0,
"CBR: geom 0 (after common-bits removal)");
411 check_valid(*rG1,
"CBR: geom 1 (after common-bits removal)");
414 ret.reset(_Op(rG0.get(), rG1.get()));
416 #if GEOS_DEBUG_BINARYOP 417 check_valid(*ret,
"CBR: result (before common-bits addition)");
420 cbr.addCommonBits(ret.get());
422 #if GEOS_CHECK_COMMONBITS_VALIDITY 423 check_valid(*ret,
"CBR: result (after common-bits addition)",
true);
426 #if GEOS_DEBUG_BINARYOP 427 std::cerr <<
"Attempt with CBR succeeded" << std::endl;
433 ::geos::ignore_unused_variable_warning(ex);
434 #if GEOS_DEBUG_BINARYOP 435 std::cerr <<
"CBR: " << ex.what() << std::endl;
447 #if USE_SNAPPING_POLICY 449 #if GEOS_DEBUG_BINARYOP 450 std::cerr <<
"Trying with snapping " << std::endl;
454 ret =
SnapOp(g0, g1, _Op);
455 #if GEOS_CHECK_SNAPPINGOP_VALIDITY 456 check_valid(*ret,
"SNAP: result",
true,
true);
458 #if GEOS_DEBUG_BINARYOP 459 std::cerr <<
"SnapOp succeeded" << std::endl;
465 ::geos::ignore_unused_variable_warning(ex);
466 #if GEOS_DEBUG_BINARYOP 467 std::cerr <<
"SNAP: " << ex.what() << std::endl;
471 #endif // USE_SNAPPING_POLICY } 474 #if USE_PRECISION_REDUCTION_POLICY 479 long unsigned int g0scale =
480 static_cast<long unsigned int>(g0->getFactory()->getPrecisionModel()->getScale());
481 long unsigned int g1scale =
482 static_cast<long unsigned int>(g1->getFactory()->getPrecisionModel()->getScale());
484 #if GEOS_DEBUG_BINARYOP 485 std::cerr <<
"Original input scales are: " 492 double maxScale = 1e16;
495 if(g0scale && static_cast<double>(g0scale) < maxScale) {
496 maxScale = static_cast<double>(g0scale);
498 if(g1scale && static_cast<double>(g1scale) < maxScale) {
499 maxScale = static_cast<double>(g1scale);
503 for(
double scale = maxScale; scale >= 1; scale /= 10) {
504 PrecisionModel pm(scale);
506 #if GEOS_DEBUG_BINARYOP 507 std::cerr <<
"Trying with scale " << scale << std::endl;
510 precision::GeometryPrecisionReducer reducer(*gf);
511 GeomPtr rG0(reducer.reduce(*g0));
512 GeomPtr rG1(reducer.reduce(*g1));
514 #if GEOS_DEBUG_BINARYOP 515 check_valid(*rG0,
"PR: geom 0 (after precision reduction)");
516 check_valid(*rG1,
"PR: geom 1 (after precision reduction)");
520 ret.reset(_Op(rG0.get(), rG1.get()));
522 if(g0->getFactory()->getPrecisionModel()->compareTo(g1->getFactory()->getPrecisionModel()) < 0) {
523 ret.reset(g0->getFactory()->createGeometry(ret.get()));
526 ret.reset(g1->getFactory()->createGeometry(ret.get()));
529 #if GEOS_CHECK_PRECISION_REDUCTION_VALIDITY 530 check_valid(*ret,
"PR: result (after restore of original precision)",
true);
533 #if GEOS_DEBUG_BINARYOP 534 std::cerr <<
"Attempt with scale " << scale <<
" succeeded" << std::endl;
539 #if GEOS_DEBUG_BINARYOP 540 std::cerr <<
"Reduced with scale (" << scale <<
"): " 541 << ex.what() << std::endl;
552 #if GEOS_DEBUG_BINARYOP 553 std::cerr <<
"Reduced: " << ex.what() << std::endl;
555 ::geos::ignore_unused_variable_warning(ex);
566 #if USE_TP_SIMPLIFY_POLICY 571 double maxTolerance = 0.04;
572 double minTolerance = 0.01;
573 double tolStep = 0.01;
575 for(
double tol = minTolerance; tol <= maxTolerance; tol += tolStep) {
576 #if GEOS_DEBUG_BINARYOP 577 std::cerr <<
"Trying simplifying with tolerance " << tol << std::endl;
580 GeomPtr rG0(simplify::TopologyPreservingSimplifier::simplify(g0, tol));
581 GeomPtr rG1(simplify::TopologyPreservingSimplifier::simplify(g1, tol));
584 ret.reset(_Op(rG0.get(), rG1.get()));
588 if(tol >= maxTolerance) {
591 #if GEOS_DEBUG_BINARYOP 592 std::cerr <<
"Simplified with tolerance (" << tol <<
"): " 593 << ex.what() << std::endl;
603 #if GEOS_DEBUG_BINARYOP 604 std::cerr <<
"Simplified: " << ex.what() << std::endl;
611 #if GEOS_DEBUG_BINARYOP 612 std::cerr <<
"No attempts worked to union " << std::endl;
613 std::cerr <<
"Input geometries:" << std::endl
614 <<
"<A>" << std::endl
615 << g0->toString() << std::endl
616 <<
"</A>" << std::endl
617 <<
"<B>" << std::endl
618 << g1->toString() << std::endl
619 <<
"</B>" << std::endl;
629 #endif // GEOS_GEOM_BINARYOP_H Allow computing and removing common mantissa bits from one or more Geometries.
Definition: CommonBitsRemover.h:40
void removeCommonBits(geom::Geometry *geom)
Removes the common coordinate bits from a Geometry. The coordinates of the Geometry are changed.
Basic implementation of Geometry, constructed and destructed by GeometryFactory.
Definition: Geometry.h:188
geom::Coordinate & getCommonCoordinate()
std::unique_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:275
Basic namespace for all GEOS functionalities.
Definition: IndexedNestedRingTester.h:25
Snaps the vertices and segments of a geom::Geometry to another Geometry's vertices.
Definition: GeometrySnapper.h:58
virtual std::unique_ptr< Geometry > clone() const =0
Make a deep-copy of this Geometry.
Indicates an invalid or inconsistent topological situation encountered during processing.
Definition: TopologyException.h:35
geom::Geometry * addCommonBits(geom::Geometry *geom)
Adds the common coordinate bits back into a Geometry. The coordinates of the Geometry are changed.
void add(const geom::Geometry *geom)
static const BoundaryNodeRule & getBoundaryEndPoint()
The Endpoint Boundary Node Rule.
static GeometryFactory::Ptr create()
Constructs a GeometryFactory that generates Geometries having a floating PrecisionModel and a spatial...