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_snap_collapses(std::auto_ptr<Geometry> g,
const std::string& label)
166 if ( ! check_valid(*g, label) ) {
167 #if GEOS_DEBUG_BINARYOP
168 std::cerr << label <<
": self-unioning" << std::endl;
171 #if GEOS_DEBUG_BINARYOP
172 std::stringstream ss;
173 ss << label <<
" self-unioned";
174 check_valid(*g, ss.str());
191 template <
class BinOp>
192 std::auto_ptr<Geometry>
195 typedef std::auto_ptr<Geometry> GeomPtr;
197 #define CBR_BEFORE_SNAPPING 1
204 double snapTolerance = GeometrySnapper::computeOverlaySnapTolerance(*g0, *g1);
205 #if GEOS_DEBUG_BINARYOP
206 std::cerr<< std::setprecision(20) <<
"Computed snap tolerance: "<<snapTolerance<<std::endl;
210 #if CBR_BEFORE_SNAPPING
214 #if GEOS_DEBUG_BINARYOP
222 #if GEOS_DEBUG_BINARYOP
223 check_valid(*rG0,
"CBR: removed-bits geom 0");
224 check_valid(*rG1,
"CBR: removed-bits geom 1");
229 #else // don't CBR before snapping
235 GeometrySnapper snapper0( operand0 );
236 GeomPtr snapG0( snapper0.snapTo(operand1, snapTolerance) );
237 snapG0 = fix_snap_collapses(snapG0,
"SNAP: snapped geom 0");
240 GeometrySnapper snapper1( operand1 );
241 GeomPtr snapG1( snapper1.snapTo(*snapG0, snapTolerance) );
242 snapG1 = fix_snap_collapses(snapG1,
"SNAP: snapped geom 1");
246 GeomPtr result( _Op(snapG0.get(), snapG1.get()) );
248 #if GEOS_DEBUG_BINARYOP
249 check_valid(*result,
"SNAP: result (before common-bits addition");
252 #if CBR_BEFORE_SNAPPING
257 #if GEOS_DEBUG_BINARYOP
258 check_valid(*result,
"SNAP: result (after common-bits addition");
264 template <
class BinOp>
265 std::auto_ptr<Geometry>
266 BinaryOp(
const Geometry* g0,
const Geometry *g1, BinOp _Op)
268 typedef std::auto_ptr<Geometry> GeomPtr;
273 #ifdef USE_ORIGINAL_INPUT
277 #if GEOS_DEBUG_BINARYOP
278 std::cerr <<
"Trying with original input." << std::endl;
280 ret.reset(_Op(g0, g1));
286 #if GEOS_DEBUG_BINARYOP
287 std::cerr <<
"Original exception: " << ex.what() << std::endl;
290 #endif // USE_ORIGINAL_INPUT
293 #ifdef USE_COMMONBITS_POLICY
305 precision::CommonBitsRemover cbr;
307 #if GEOS_DEBUG_BINARYOP
308 std::cerr <<
"Trying with Common Bits Remover (CBR)" << std::endl;
314 rG0.reset( cbr.removeCommonBits(g0->clone()) );
315 rG1.reset( cbr.removeCommonBits(g1->clone()) );
317 #if GEOS_DEBUG_BINARYOP
318 check_valid(*rG0,
"CBR: geom 0 (after common-bits removal)");
319 check_valid(*rG1,
"CBR: geom 1 (after common-bits removal)");
322 ret.reset( _Op(rG0.get(), rG1.get()) );
324 #if GEOS_DEBUG_BINARYOP
325 check_valid(*ret,
"CBR: result (before common-bits addition)");
328 cbr.addCommonBits( ret.get() );
330 #if GEOS_DEBUG_BINARYOP
331 check_valid(*ret,
"CBR: result (before common-bits addition)");
334 #if GEOS_CHECK_COMMONBITS_VALIDITY
337 using operation::valid::IsValidOp;
338 using operation::valid::TopologyValidationError;
339 IsValidOp ivo(ret.get());
340 if ( ! ivo.isValid() )
342 TopologyValidationError* e = ivo.getValidationError();
344 "Result of overlay became invalid "
345 "after re-addin common bits of operand "
346 "coordinates: " + e->toString(),
349 #endif // GEOS_CHECK_COMMONBITS_VALIDITY
355 ::geos::ignore_unused_variable_warning(ex);
356 #if GEOS_DEBUG_BINARYOP
357 std::cerr <<
"CBR: " << ex.what() << std::endl;
369 #if USE_SNAPPING_POLICY
371 #if GEOS_DEBUG_BINARYOP
372 std::cerr <<
"Trying with snapping " << std::endl;
376 ret =
SnapOp(g0, g1, _Op);
377 #if GEOS_DEBUG_BINARYOP
378 std::cerr <<
"SnapOp succeeded" << std::endl;
385 ::geos::ignore_unused_variable_warning(ex);
386 #if GEOS_DEBUG_BINARYOP
387 std::cerr <<
"SNAP: " << ex.what() << std::endl;
391 #endif // USE_SNAPPING_POLICY }
396 #if USE_PRECISION_REDUCTION_POLICY
404 for (
int precision=maxPrecision; precision; --precision)
406 std::auto_ptr<PrecisionModel> pm(
new PrecisionModel(precision));
407 #if GEOS_DEBUG_BINARYOP
408 std::cerr <<
"Trying with precision " << precision << std::endl;
411 precision::SimpleGeometryPrecisionReducer reducer( pm.get() );
412 GeomPtr rG0( reducer.reduce(g0) );
413 GeomPtr rG1( reducer.reduce(g1) );
417 ret.reset( _Op(rG0.get(), rG1.get()) );
422 if ( precision == 1 )
throw ex;
423 #if GEOS_DEBUG_BINARYOP
424 std::cerr <<
"Reduced with precision (" << precision <<
"): "
425 << ex.what() << std::endl;
434 #if GEOS_DEBUG_BINARYOP
435 std::cerr <<
"Reduced: " << ex.what() << std::endl;
443 #if USE_TP_SIMPLIFY_POLICY
449 double maxTolerance = 0.04;
450 double minTolerance = 0.01;
451 double tolStep = 0.01;
453 for (
double tol = minTolerance; tol <= maxTolerance; tol += tolStep)
455 #if GEOS_DEBUG_BINARYOP
456 std::cerr <<
"Trying simplifying with tolerance " << tol << std::endl;
459 GeomPtr rG0( simplify::TopologyPreservingSimplifier::simplify(g0, tol) );
460 GeomPtr rG1( simplify::TopologyPreservingSimplifier::simplify(g1, tol) );
464 ret.reset( _Op(rG0.get(), rG1.get()) );
469 if ( tol >= maxTolerance )
throw ex;
470 #if GEOS_DEBUG_BINARYOP
471 std::cerr <<
"Simplified with tolerance (" << tol <<
"): "
472 << ex.what() << std::endl;
483 #if GEOS_DEBUG_BINARYOP
484 std::cerr <<
"Simplified: " << ex.what() << std::endl;
498 #endif // GEOS_GEOM_BINARYOP_H