49 #ifndef GEOS_GEOM_BINARYOP_H
50 #define GEOS_GEOM_BINARYOP_H
52 #include <geos/geom/Geometry.h>
53 #include <geos/geom/PrecisionModel.h>
54 #include <geos/precision/CommonBitsRemover.h>
55 #include <geos/precision/SimpleGeometryPrecisionReducer.h>
57 #include <geos/operation/overlay/snap/GeometrySnapper.h>
59 #include <geos/simplify/TopologyPreservingSimplifier.h>
60 #include <geos/operation/valid/IsValidOp.h>
61 #include <geos/operation/valid/TopologyValidationError.h>
62 #include <geos/util/TopologyException.h>
63 #include <geos/util.h>
69 #ifdef GEOS_DEBUG_BINARYOP
79 #ifndef USE_ORIGINAL_INPUT
80 # define USE_ORIGINAL_INPUT 1
88 #ifndef USE_PRECISION_REDUCTION_POLICY
97 #ifndef USE_TP_SIMPLIFY_POLICY
106 #ifndef USE_COMMONBITS_POLICY
107 # define USE_COMMONBITS_POLICY 1
121 #define GEOS_CHECK_COMMONBITS_VALIDITY 1
126 #ifndef USE_SNAPPING_POLICY
127 # define USE_SNAPPING_POLICY 1
134 check_valid(
const Geometry& g,
const std::string& label)
136 operation::valid::IsValidOp ivo(&g);
137 if ( ! ivo.isValid() )
139 #ifdef GEOS_DEBUG_BINARYOP
140 using operation::valid::TopologyValidationError;
141 TopologyValidationError* err = ivo.getValidationError();
142 std::cerr << label <<
" is INVALID: "
144 <<
" (" << std::setprecision(20)
145 << err->getCoordinate() <<
")"
156 inline std::auto_ptr<Geometry>
157 fix_self_intersections(std::auto_ptr<Geometry> g,
const std::string& label)
169 template <
class BinOp>
170 std::auto_ptr<Geometry>
173 typedef std::auto_ptr<Geometry> GeomPtr;
175 #define CBR_BEFORE_SNAPPING 1
182 double snapTolerance = GeometrySnapper::computeOverlaySnapTolerance(*g0, *g1);
183 #if GEOS_DEBUG_BINARYOP
184 std::cerr<< std::setprecision(20) <<
"Computed snap tolerance: "<<snapTolerance<<std::endl;
188 #if CBR_BEFORE_SNAPPING
192 #if GEOS_DEBUG_BINARYOP
200 #if GEOS_DEBUG_BINARYOP
201 check_valid(*rG0,
"CBR: removed-bits geom 0");
202 check_valid(*rG1,
"CBR: removed-bits geom 1");
207 #else // don't CBR before snapping
213 GeometrySnapper snapper0( operand0 );
214 GeomPtr snapG0( snapper0.snapTo(operand1, snapTolerance) );
215 snapG0 = fix_self_intersections(snapG0,
"SNAP: snapped geom 0");
218 GeometrySnapper snapper1( operand1 );
219 GeomPtr snapG1( snapper1.snapTo(*snapG0, snapTolerance) );
220 snapG1 = fix_self_intersections(snapG1,
"SNAP: snapped geom 1");
223 GeomPtr result( _Op(snapG0.get(), snapG1.get()) );
225 #if GEOS_DEBUG_BINARYOP
226 check_valid(*result,
"SNAP: result (before common-bits addition");
229 #if CBR_BEFORE_SNAPPING
232 result = fix_self_intersections(result,
"SNAP: result (after common-bits addition)");
235 #if GEOS_DEBUG_BINARYOP
236 check_valid(*result,
"SNAP: result (after common-bits addition");
242 template <
class BinOp>
243 std::auto_ptr<Geometry>
244 BinaryOp(
const Geometry* g0,
const Geometry *g1, BinOp _Op)
246 typedef std::auto_ptr<Geometry> GeomPtr;
251 #ifdef USE_ORIGINAL_INPUT
255 #if GEOS_DEBUG_BINARYOP
256 std::cerr <<
"Trying with original input." << std::endl;
258 ret.reset(_Op(g0, g1));
264 #if GEOS_DEBUG_BINARYOP
265 std::cerr <<
"Original exception: " << ex.what() << std::endl;
271 check_valid(*g0,
"Input geom 0");
272 check_valid(*g1,
"Input geom 1");
275 #endif // USE_ORIGINAL_INPUT
278 #ifdef USE_COMMONBITS_POLICY
290 precision::CommonBitsRemover cbr;
292 #if GEOS_DEBUG_BINARYOP
293 std::cerr <<
"Trying with Common Bits Remover (CBR)" << std::endl;
299 rG0.reset( cbr.removeCommonBits(g0->clone()) );
300 rG1.reset( cbr.removeCommonBits(g1->clone()) );
302 #if GEOS_DEBUG_BINARYOP
303 check_valid(*rG0,
"CBR: geom 0 (after common-bits removal)");
304 check_valid(*rG1,
"CBR: geom 1 (after common-bits removal)");
307 ret.reset( _Op(rG0.get(), rG1.get()) );
309 #if GEOS_DEBUG_BINARYOP
310 check_valid(*ret,
"CBR: result (before common-bits addition)");
313 cbr.addCommonBits( ret.get() );
315 #if GEOS_DEBUG_BINARYOP
316 check_valid(*ret,
"CBR: result (after common-bits addition)");
320 ret = fix_self_intersections(ret,
"CBR: result (after common-bits addition)");
322 #if GEOS_DEBUG_BINARYOP
323 check_valid(*ret,
"CBR: result (after common-bits addition and fix_self_intersections)");
326 #if GEOS_CHECK_COMMONBITS_VALIDITY
329 using operation::valid::IsValidOp;
330 using operation::valid::TopologyValidationError;
331 IsValidOp ivo(ret.get());
332 if ( ! ivo.isValid() )
334 TopologyValidationError* e = ivo.getValidationError();
336 "Result of overlay became invalid "
337 "after re-addin common bits of operand "
338 "coordinates: " + e->toString(),
341 #endif // GEOS_CHECK_COMMONBITS_VALIDITY
347 ::geos::ignore_unused_variable_warning(ex);
348 #if GEOS_DEBUG_BINARYOP
349 std::cerr <<
"CBR: " << ex.what() << std::endl;
361 #if USE_SNAPPING_POLICY
363 #if GEOS_DEBUG_BINARYOP
364 std::cerr <<
"Trying with snapping " << std::endl;
368 ret =
SnapOp(g0, g1, _Op);
369 #if GEOS_DEBUG_BINARYOP
370 std::cerr <<
"SnapOp succeeded" << std::endl;
377 ::geos::ignore_unused_variable_warning(ex);
378 #if GEOS_DEBUG_BINARYOP
379 std::cerr <<
"SNAP: " << ex.what() << std::endl;
383 #endif // USE_SNAPPING_POLICY }
388 #if USE_PRECISION_REDUCTION_POLICY
396 for (
int precision=maxPrecision; precision; --precision)
398 std::auto_ptr<PrecisionModel> pm(
new PrecisionModel(precision));
399 #if GEOS_DEBUG_BINARYOP
400 std::cerr <<
"Trying with precision " << precision << std::endl;
403 precision::SimpleGeometryPrecisionReducer reducer( pm.get() );
404 GeomPtr rG0( reducer.reduce(g0) );
405 GeomPtr rG1( reducer.reduce(g1) );
409 ret.reset( _Op(rG0.get(), rG1.get()) );
414 if ( precision == 1 )
throw ex;
415 #if GEOS_DEBUG_BINARYOP
416 std::cerr <<
"Reduced with precision (" << precision <<
"): "
417 << ex.what() << std::endl;
426 #if GEOS_DEBUG_BINARYOP
427 std::cerr <<
"Reduced: " << ex.what() << std::endl;
435 #if USE_TP_SIMPLIFY_POLICY
441 double maxTolerance = 0.04;
442 double minTolerance = 0.01;
443 double tolStep = 0.01;
445 for (
double tol = minTolerance; tol <= maxTolerance; tol += tolStep)
447 #if GEOS_DEBUG_BINARYOP
448 std::cerr <<
"Trying simplifying with tolerance " << tol << std::endl;
451 GeomPtr rG0( simplify::TopologyPreservingSimplifier::simplify(g0, tol) );
452 GeomPtr rG1( simplify::TopologyPreservingSimplifier::simplify(g1, tol) );
456 ret.reset( _Op(rG0.get(), rG1.get()) );
461 if ( tol >= maxTolerance )
throw ex;
462 #if GEOS_DEBUG_BINARYOP
463 std::cerr <<
"Simplified with tolerance (" << tol <<
"): "
464 << ex.what() << std::endl;
475 #if GEOS_DEBUG_BINARYOP
476 std::cerr <<
"Simplified: " << ex.what() << std::endl;
490 #endif // GEOS_GEOM_BINARYOP_H