00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include <geos/geom/Geometry.h>
00050 #include <geos/geom/PrecisionModel.h>
00051 #include <geos/util/TopologyException.h>
00052 #include <geos/precision/CommonBitsRemover.h>
00053 #include <geos/precision/SimpleGeometryPrecisionReducer.h>
00054 #include <geos/precision/GeometrySnapper.h>
00055 #include <geos/simplify/TopologyPreservingSimplifier.h>
00056 #include <geos/operation/valid/IsValidOp.h>
00057
00058 #include <memory>
00059
00060
00061
00062
00063
00064
00065
00066 #ifndef USE_ORIGINAL_INPUT
00067 # define USE_ORIGINAL_INPUT 1
00068 #endif
00069
00070
00071
00072
00073
00074
00075 #ifndef USE_PRECISION_REDUCTION_POLICY
00076
00077 #endif
00078
00079
00080
00081
00082
00083
00084 #ifndef USE_TP_SIMPLIFY_POLICY
00085
00086 #endif
00087
00088
00089
00090
00091
00092
00093 #ifndef USE_COMMONBITS_POLICY
00094 # define USE_COMMONBITS_POLICY 1
00095 #endif
00096
00097
00098
00099
00100 #ifndef USE_SNAPPING_POLICY
00101 # define USE_SNAPPING_POLICY 1
00102 #endif
00103
00104 namespace geos {
00105 namespace geom {
00106
00107 bool
00108 check_valid(const Geometry& g, const std::string& label)
00109 {
00110 operation::valid::IsValidOp ivo(&g);
00111 if ( ! ivo.isValid() )
00112 {
00113 std::cerr << label << ": is invalid!"
00114 << ivo.getValidationError()->toString() << std::endl;
00115 return false;
00116 }
00117 return true;
00118 }
00119
00125 template <class BinOp>
00126 std::auto_ptr<Geometry>
00127 SnapOp(const Geometry* g0, const Geometry *g1, BinOp _Op)
00128 {
00129 typedef std::auto_ptr<Geometry> GeomPtr;
00130
00131 #define CBR_BEFORE_SNAPPING 1
00132
00133 using geos::precision::GeometrySnapper;
00134
00135
00136
00137 double snapTolerance = GeometrySnapper::computeOverlaySnapTolerance(*g0, *g1);
00138 #if GEOS_DEBUG_BINARYOP
00139 std::cerr<<"Computed snap tolerance: "<<snapTolerance<<std::endl;
00140 #endif
00141
00142 geos::precision::CommonBitsRemover cbr;
00143
00144 #if CBR_BEFORE_SNAPPING
00145
00146 GeomPtr rG0( cbr.removeCommonBits(g0->clone()) );
00147 GeomPtr rG1( cbr.removeCommonBits(g1->clone()) );
00148
00149 #if GEOS_DEBUG_BINARYOP
00150 check_valid(*rG0, "CBR: removed-bits geom 0");
00151 check_valid(*rG1, "CBR: removed-bits geom 1");
00152 #endif
00153
00154 const Geometry& operand0 = *rG0;
00155 const Geometry& operand1 = *rG1;
00156 #else // don't CBR before snapping
00157 const Geometry& operand0 = *g0
00158 const Geometry& operand1 = *g1
00159 #endif
00160
00161 GeometrySnapper snapper0( operand0 );
00162 GeomPtr snapG0( snapper0.snapTo(operand1, snapTolerance) );
00163
00164
00165 GeometrySnapper snapper1( operand1 );
00166 GeomPtr snapG1( snapper1.snapTo(*snapG0, snapTolerance) );
00167
00168 #if GEOS_DEBUG_BINARYOP
00169 check_valid(*snapG0, "SNAP: snapped geom 0");
00170 check_valid(*snapG1, "SNAP: snapped geom 1");
00171 #endif
00172
00173
00174 GeomPtr result( _Op(snapG0.get(), snapG1.get()) );
00175
00176 #if GEOS_DEBUG_BINARYOP
00177 check_valid(*result, "Op result (before common-bits addition");
00178 #endif
00179
00180 #if CBR_BEFORE_SNAPPING
00181
00182 cbr.addCommonBits( result.get() );
00183 #endif
00184
00185 #if GEOS_DEBUG_BINARYOP
00186 check_valid(*result, "Op result (after common-bits addition");
00187 #endif
00188
00189 return result;
00190 }
00191
00192 template <class BinOp>
00193 std::auto_ptr<Geometry>
00194 BinaryOp(const Geometry* g0, const Geometry *g1, BinOp _Op)
00195 {
00196 typedef std::auto_ptr<Geometry> GeomPtr;
00197
00198 GeomPtr ret;
00199 util::TopologyException origException;
00200
00201 #ifdef USE_ORIGINAL_INPUT
00202
00203 try
00204 {
00205 #if GEOS_DEBUG_BINARYOP
00206 std::cerr << "Trying with original input." << std::endl;
00207 #endif
00208 ret.reset(_Op(g0, g1));
00209 return ret;
00210 }
00211 catch (const util::TopologyException& ex)
00212 {
00213 origException=ex;
00214 #if GEOS_DEBUG_BINARYOP
00215 std::cerr << "Original exception: " << ex.what() << std::endl;
00216 #endif
00217 }
00218 #endif // USE_ORIGINAL_INPUT
00219
00220
00221 #ifdef USE_COMMONBITS_POLICY
00222
00223 try
00224 {
00225 GeomPtr rG0;
00226 GeomPtr rG1;
00227 precision::CommonBitsRemover cbr;
00228
00229 #if GEOS_DEBUG_BINARYOP
00230 std::cerr << "Trying with Common bits remover." << std::endl;
00231 #endif
00232
00233 cbr.add(g0);
00234 cbr.add(g1);
00235
00236 rG0.reset( cbr.removeCommonBits(g0->clone()) );
00237 rG1.reset( cbr.removeCommonBits(g1->clone()) );
00238
00239 #if GEOS_DEBUG_BINARYOP
00240 if ( ! rG0->isValid() )
00241 {
00242 std::cerr << " CBR: geom 0 is invalid!" << std::endl;
00243 }
00244
00245 if ( ! rG1->isValid() )
00246 {
00247 std::cerr << " CBR: geom 1 is invalid!" << std::endl;
00248 }
00249 #endif
00250
00251 ret.reset( _Op(rG0.get(), rG1.get()) );
00252
00253 cbr.addCommonBits( ret.get() );
00254
00255 return ret;
00256 }
00257 catch (const util::TopologyException& ex)
00258 {
00259 #if GEOS_DEBUG_BINARYOP
00260 std::cerr << "CBR: " << ex.what() << std::endl;
00261 #endif
00262 }
00263 #endif
00264
00265
00266
00267
00268
00269
00270
00271
00272 #if USE_SNAPPING_POLICY
00273
00274 #if GEOS_DEBUG_BINARYOP
00275 std::cerr << "Trying with snapping " << std::endl;
00276 #endif
00277
00278 try {
00279 ret = SnapOp(g0, g1, _Op);
00280 #if GEOS_DEBUG_BINARYOP
00281 std::cerr << "SnapOp succeeded" << std::endl;
00282 #endif
00283 return ret;
00284
00285 }
00286 catch (const util::TopologyException& ex)
00287 {
00288 #if GEOS_DEBUG_BINARYOP
00289 std::cerr << "SNAP: " << ex.what() << std::endl;
00290 #endif
00291 }
00292
00293 #endif // USE_SNAPPING_POLICY }
00294
00295
00296
00297
00298 #if USE_PRECISION_REDUCTION_POLICY
00299
00300
00301
00302 try
00303 {
00304 int maxPrecision=25;
00305
00306 for (int precision=maxPrecision; precision; --precision)
00307 {
00308 std::auto_ptr<PrecisionModel> pm(new PrecisionModel(precision));
00309 #if GEOS_DEBUG_BINARYOP
00310 std::cerr << "Trying with precision " << precision << std::endl;
00311 #endif
00312
00313 precision::SimpleGeometryPrecisionReducer reducer( pm.get() );
00314 GeomPtr rG0( reducer.reduce(g0) );
00315 GeomPtr rG1( reducer.reduce(g1) );
00316
00317 try
00318 {
00319 ret.reset( _Op(rG0.get(), rG1.get()) );
00320 return ret;
00321 }
00322 catch (const util::TopologyException& ex)
00323 {
00324 if ( precision == 1 ) throw ex;
00325 #if GEOS_DEBUG_BINARYOP
00326 std::cerr << "Reduced with precision (" << precision << "): "
00327 << ex.what() << std::endl;
00328 #endif
00329 }
00330
00331 }
00332
00333 }
00334 catch (const util::TopologyException& ex)
00335 {
00336 #if GEOS_DEBUG_BINARYOP
00337 std::cerr << "Reduced: " << ex.what() << std::endl;
00338 #endif
00339 }
00340
00341 #endif
00342
00343
00344
00345 #if USE_TP_SIMPLIFY_POLICY
00346
00347
00348 try
00349 {
00350
00351 double maxTolerance = 0.04;
00352 double minTolerance = 0.01;
00353 double tolStep = 0.01;
00354
00355 for (double tol = minTolerance; tol <= maxTolerance; tol += tolStep)
00356 {
00357 #if GEOS_DEBUG_BINARYOP
00358 std::cerr << "Trying simplifying with tolerance " << tol << std::endl;
00359 #endif
00360
00361 GeomPtr rG0( simplify::TopologyPreservingSimplifier::simplify(g0, tol) );
00362 GeomPtr rG1( simplify::TopologyPreservingSimplifier::simplify(g1, tol) );
00363
00364 try
00365 {
00366 ret.reset( _Op(rG0.get(), rG1.get()) );
00367 return ret;
00368 }
00369 catch (const util::TopologyException& ex)
00370 {
00371 if ( tol >= maxTolerance ) throw ex;
00372 #if GEOS_DEBUG_BINARYOP
00373 std::cerr << "Simplified with tolerance (" << tol << "): "
00374 << ex.what() << std::endl;
00375 #endif
00376 }
00377
00378 }
00379
00380 return ret;
00381
00382 }
00383 catch (const util::TopologyException& ex)
00384 {
00385 #if GEOS_DEBUG_BINARYOP
00386 std::cerr << "Simplified: " << ex.what() << std::endl;
00387 #endif
00388 }
00389
00390 #endif
00391
00392
00393 throw origException;
00394 }
00395
00396
00397 }
00398 }