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