void XMLTester::parseTest(const TiXmlNode* node) { using namespace operation::overlay; typedef std::auto_ptr< geom::Geometry > GeomAutoPtr; int success=0; // no success by default std::string opName; std::string opArg1; std::string opArg2; std::string opArg3; std::string opArg4; std::string opRes; ++testCount; const TiXmlNode* opnode = node->FirstChild("op"); if ( ! opnode ) throw(runtime_error("case has no op")); //dump_to_stdout(opnode); const TiXmlElement* opel = opnode->ToElement(); const char* tmp = opel->Attribute("name"); if ( tmp ) opName = tmp; tmp = opel->Attribute("arg1"); if ( tmp ) opArg1 = tmp; tmp = opel->Attribute("arg2"); if ( tmp ) opArg2 = tmp; tmp = opel->Attribute("arg3"); if ( tmp ) opArg3 = tmp; tmp = opel->Attribute("arg4"); if ( tmp ) opArg4 = tmp; const TiXmlNode* resnode = opnode->FirstChild(); if ( ! resnode ) { std::stringstream tmp; tmp << "op of test " << testCount << " of case " << caseCount << " has no expected result child"; throw(runtime_error(tmp.str())); } opRes = resnode->Value(); // trim blanks opRes=trimBlanks(opRes); opName=trimBlanks(opName); tolower(opName); std::string opSig=""; if ( opArg1 != "" ) opSig=opArg1; if ( opArg2 != "" ) { if ( opSig != "" ) opSig += ", "; opSig += opArg2; } if ( opArg3 != "" ) { if ( opSig != "" ) opSig += ", "; opSig += opArg3; } if ( opArg4 != "" ) { if ( opSig != "" ) opSig += ", "; opSig += opArg4; } opSignature = opName + "(" + opSig + ")"; std::string actual_result="NONE"; // expected_result will be modified by specific tests // if needed (geometry normalization, for example) std::string expected_result=opRes; try { util::Profile profile("op"); if (opName=="relate") { std::auto_ptr<geom::IntersectionMatrix> im(gA->relate(gB)); assert(im.get()); if (im->matches(opArg3)) actual_result="true"; else actual_result="false"; if (actual_result==opRes) success=1; } else if (opName=="isvalid") { geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) { gT=gB; } if (gT->isValid()) actual_result="true"; else actual_result="false"; if (actual_result==opRes) success=1; } else if (opName=="intersection") { GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); #ifndef USE_BINARYOP GeomAutoPtr gRealRes(gA->intersection(gB)); #else GeomAutoPtr gRealRes = BinaryOp(gA, gB, overlayOp(OverlayOp::opINTERSECTION)); #endif gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); if ( testValidOutput ) success &= int(testValid(gRealRes.get(), "result")); } else if (opName=="union") { GeomAutoPtr gRes(parseGeometry(opRes, "expected")); GeomAutoPtr gRealRes; if ( gB ) { #ifndef USE_BINARYOP gRealRes.reset(gA->Union(gB)); #else gRealRes = BinaryOp(gA, gB, overlayOp(OverlayOp::opUNION)); #endif } else { gRealRes = gA->Union(); } if (gRes->equals(gRealRes.get())) success=1; actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); if ( testValidOutput ) success &= int(testValid(gRealRes.get(), "result")); } else if (opName=="difference") { GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); #ifndef USE_BINARYOP GeomAutoPtr gRealRes(gA->difference(gB)); #else GeomAutoPtr gRealRes = BinaryOp(gA, gB, overlayOp(OverlayOp::opDIFFERENCE)); #endif gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); if ( testValidOutput ) success &= int(testValid(gRealRes.get(), "result")); } else if (opName=="symdifference") { GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); #ifndef USE_BINARYOP GeomAutoPtr gRealRes(gA->symDifference(gB)); #else GeomAutoPtr gRealRes = BinaryOp(gA, gB, overlayOp(OverlayOp::opSYMDIFFERENCE)); #endif gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); if ( testValidOutput ) success &= int(testValid(gRealRes.get(), "result")); } else if (opName=="intersects") { geom::Geometry *g1 = opArg1 == "B" ? gB : gA; geom::Geometry *g2 = opArg2 == "B" ? gB : gA; if (g1->intersects(g2)) actual_result="true"; else actual_result="false"; if (actual_result==opRes) success=1; } else if (opName=="contains") { geom::Geometry *g1 = opArg1 == "B" ? gB : gA; geom::Geometry *g2 = opArg2 == "B" ? gB : gA; if (g1->contains(g2)) actual_result="true"; else actual_result="false"; if (actual_result==opRes) success=1; } else if (opName=="within") { geom::Geometry *g1 = opArg1 == "B" ? gB : gA; geom::Geometry *g2 = opArg2 == "B" ? gB : gA; if (g1->within(g2)) actual_result="true"; else actual_result="false"; if (actual_result==opRes) success=1; } else if (opName=="covers") { geom::Geometry *g1 = opArg1 == "B" ? gB : gA; geom::Geometry *g2 = opArg2 == "B" ? gB : gA; if (g1->covers(g2)) actual_result="true"; else actual_result="false"; if (actual_result==opRes) success=1; } else if (opName=="coveredby") { geom::Geometry *g1 = opArg1 == "B" ? gB : gA; geom::Geometry *g2 = opArg2 == "B" ? gB : gA; if (g1->coveredBy(g2)) actual_result="true"; else actual_result="false"; if (actual_result==opRes) success=1; } else if (opName=="getboundary") { geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); GeomAutoPtr gRealRes(gT->getBoundary()); gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); if ( testValidOutput ) success &= int(testValid(gRealRes.get(), "result")); } else if (opName=="getcentroid") { geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); GeomAutoPtr gRealRes(gT->getCentroid()); if ( gRealRes.get() ) gRealRes->normalize(); else gRealRes.reset(factory->createPoint()); gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); if ( testValidOutput ) success &= int(testValid(gRealRes.get(), "result")); } else if (opName=="issimple") { geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; if (gT->isSimple()) actual_result="true"; else actual_result="false"; if (actual_result==opRes) success=1; } else if (opName=="convexhull") { geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); GeomAutoPtr gRealRes(gT->convexHull()); gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); if ( testValidOutput ) success &= int(testValid(gRealRes.get(), "result")); } else if (opName=="buffer") { using namespace operation::buffer; geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); profile.start(); GeomAutoPtr gRealRes; double dist = std::atof(opArg2.c_str()); BufferParameters params; if ( opArg3 != "" ) { params.setQuadrantSegments(std::atoi(opArg3.c_str())); } BufferOp op(gT, params); gRealRes.reset(op.getResultGeometry(dist)); profile.stop(); gRealRes->normalize(); // Validate the buffer operation success = checkBufferSuccess(*gRes, *gRealRes, dist); actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); if ( testValidOutput ) success &= int(testValid(gRealRes.get(), "result")); } else if (opName=="buffersinglesided") { using namespace operation::buffer; geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); profile.start(); GeomAutoPtr gRealRes; double dist = std::atof(opArg2.c_str()); BufferParameters params ; params.setJoinStyle( BufferParameters::JOIN_ROUND ) ; if ( opArg3 != "" ) { params.setQuadrantSegments( std::atoi(opArg3.c_str())); } bool leftSide = true ; if ( opArg4 == "right" ) { leftSide = false ; } BufferBuilder bufBuilder( params ) ; gRealRes.reset( bufBuilder.bufferLineSingleSided( gT, dist, leftSide ) ) ; profile.stop(); gRealRes->normalize(); // Validate the single sided buffer operation success = checkSingleSidedBufferSuccess(*gRes, *gRealRes, dist); actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); if ( testValidOutput ) success &= int(testValid(gRealRes.get(), "result")); } else if (opName=="buffermitredjoin") { using namespace operation::buffer; geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); profile.start(); GeomAutoPtr gRealRes; double dist = std::atof(opArg2.c_str()); BufferParameters params; params.setJoinStyle(BufferParameters::JOIN_MITRE); if ( opArg3 != "" ) { params.setQuadrantSegments(std::atoi(opArg3.c_str())); } BufferOp op(gT, params); gRealRes.reset(op.getResultGeometry(dist)); profile.stop(); gRealRes->normalize(); // Validate the buffer operation success = checkBufferSuccess(*gRes, *gRealRes, dist); actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); if ( testValidOutput ) success &= int(testValid(gRealRes.get(), "result")); } else if (opName=="getinteriorpoint") { geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); GeomAutoPtr gRealRes(gT->getInteriorPoint()); if ( gRealRes.get() ) gRealRes->normalize(); else gRealRes.reset(factory->createPoint()); if (gRes->compareTo(gRealRes.get())==0) success=1; actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); if ( testValidOutput ) success &= int(testValid(gRealRes.get(), "result")); } else if (opName=="iswithindistance") { double dist=std::atof(opArg3.c_str()); if (gA->isWithinDistance(gB, dist)) { actual_result="true"; } else { actual_result="false"; } if (actual_result==opRes) success=1; } else if (opName=="polygonize") { GeomAutoPtr gRes(wktreader->read(opRes)); gRes->normalize(); Polygonizer plgnzr; plgnzr.add(gA); std::vector<geos::geom::Polygon *>*polys = plgnzr.getPolygons(); std::vector<geom::Geometry *>*newgeoms = new std::vector<geom::Geometry *>; for (unsigned int i=0; i<polys->size(); i++) newgeoms->push_back((*polys)[i]); delete polys; GeomAutoPtr gRealRes(factory->createGeometryCollection(newgeoms)); gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); if ( testValidOutput ) success &= int(testValid(gRealRes.get(), "result")); } else if (opName=="linemerge") { GeomAutoPtr gRes(wktreader->read(opRes)); gRes->normalize(); geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; LineMerger merger; merger.add(gT); std::auto_ptr< std::vector<geom::LineString *> > lines ( merger.getMergedLineStrings() ); std::vector<geom::Geometry *>*newgeoms = new std::vector<geom::Geometry *>(lines->begin(), lines->end()); GeomAutoPtr gRealRes(factory->createGeometryCollection(newgeoms)); gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); if ( testValidOutput ) success &= int(testValid(gRealRes.get(), "result")); } else if (opName=="areatest") { char* rest; double toleratedDiff = std::strtod(opRes.c_str(), &rest); int validOut = 1; if ( rest == opRes.c_str() ) { throw std::runtime_error("malformed testcase: missing tolerated area difference in 'areatest' op"); } if ( verbose > 1 ) { std::cerr << "Running intersection for areatest" << std::endl; } #ifndef USE_BINARYOP GeomAutoPtr gI(gA->intersection(gB)); #else GeomAutoPtr gI = BinaryOp(gA, gB, overlayOp(OverlayOp::opINTERSECTION)); #endif if ( testValidOutput ) { validOut &= int(testValid(gI.get(), "areatest intersection")); } if ( verbose > 1 ) { std::cerr << "Running difference(A,B) for areatest" << std::endl; } #ifndef USE_BINARYOP GeomAutoPtr gDab(gA->difference(gB)); #else GeomAutoPtr gDab = BinaryOp(gA, gB, overlayOp(OverlayOp::opDIFFERENCE)); #endif if ( testValidOutput ) { validOut &= int(testValid(gI.get(), "areatest difference(a,b)")); } if ( verbose > 1 ) { std::cerr << "Running difference(B,A) for areatest" << std::endl; } #ifndef USE_BINARYOP GeomAutoPtr gDba(gB->difference(gA)); #else GeomAutoPtr gDba = BinaryOp(gB, gA, overlayOp(OverlayOp::opDIFFERENCE)); #endif if ( testValidOutput ) { validOut &= int(testValid(gI.get(), "areatest difference(b,a)")); } if ( verbose > 1 ) { std::cerr << "Running symdifference for areatest" << std::endl; } #ifndef USE_BINARYOP GeomAutoPtr gSD(gA->symDifference(gB)); #else GeomAutoPtr gSD = BinaryOp(gA, gB, overlayOp(OverlayOp::opSYMDIFFERENCE)); #endif if ( testValidOutput ) { validOut &= int(testValid(gI.get(), "areatest symdifference")); } if ( verbose > 1 ) { std::cerr << "Running union for areatest" << std::endl; } #ifndef USE_BINARYOP GeomAutoPtr gU(gA->Union(gB)); #else GeomAutoPtr gU = BinaryOp(gA, gB, overlayOp(OverlayOp::opUNION)); #endif double areaA = gA->getArea(); double areaB = gB->getArea(); double areaI = gI->getArea(); double areaDab = gDab->getArea(); double areaDba = gDba->getArea(); double areaSD = gSD->getArea(); double areaU = gU->getArea(); double maxdiff = 0; std::string maxdiffop; // @ : symdifference // - : difference // + : union // ^ : intersection // A == ( A ^ B ) + ( A - B ) double diff = std::fabs ( areaA - areaI - areaDab ); if ( diff > maxdiff ) { maxdiffop = "A == ( A ^ B ) + ( A - B )"; maxdiff = diff; } // B == ( A ^ B ) + ( B - A ) diff = std::fabs ( areaB - areaI - areaDba ); if ( diff > maxdiff ) { maxdiffop = "B == ( A ^ B ) + ( B - A )"; maxdiff = diff; } // ( A @ B ) == ( A - B ) + ( B - A ) diff = std::fabs ( areaDab + areaDba - areaSD ); if ( diff > maxdiff ) { maxdiffop = "( A @ B ) == ( A - B ) + ( B - A )"; maxdiff = diff; } // ( A u B ) == ( A ^ B ) + ( A @ B ) diff = std::fabs ( areaI + areaSD - areaU ); if ( diff > maxdiff ) { maxdiffop = "( A u B ) == ( A ^ B ) + ( A @ B )"; maxdiff = diff; } if ( maxdiff <= toleratedDiff ) { success = 1 && validOut; } std::stringstream tmp; tmp << maxdiffop << ": " << maxdiff; actual_result=tmp.str(); expected_result=opRes; } else if (opName=="distance") { char* rest; double distE = std::strtod(opRes.c_str(), &rest); if ( rest == opRes.c_str() ) { throw std::runtime_error("malformed testcase: missing expected result in 'distance' op"); } geom::Geometry *g1 = opArg1 == "B" ? gB : gA; geom::Geometry *g2 = opArg2 == "B" ? gB : gA; double distO = g1->distance(g2); std::stringstream ss; ss << distO; actual_result = ss.str(); // TODO: Use a tolerance ? success = ( distO == distE ) ? 1 : 0; } else { std::cerr << *curr_file << ":"; std::cerr << " case" << caseCount << ":"; std::cerr << " test" << testCount << ": " << opName << "(" << opSig << ")"; std::cerr << ": skipped (unrecognized)." << std::endl; return; } } catch (const std::exception &e) { std::cerr<<"EXCEPTION on case "<<caseCount <<" test "<<testCount<<": "<<e.what() <<std::endl; actual_result = e.what(); } catch (...) { std::cerr << "Unknown EXEPTION on case " << caseCount << std::endl; actual_result = "Unknown exception thrown"; } if ( success ) ++succeeded; else ++failed; if ((!success && verbose) || verbose > 1) { printTest(!!success, expected_result, actual_result); } if (test_predicates && gB && gA) { runPredicates(gA, gB); } }
// Start reading here void do_all() { vector<Geometry *> *geoms = new vector<Geometry *>; vector<Geometry *> *newgeoms; // Define a precision model using 0,0 as the reference origin // and 2.0 as coordinates scale. PrecisionModel *pm = new PrecisionModel(2.0, 0, 0); // Initialize global factory with defined PrecisionModel // and a SRID of -1 (undefined). global_factory = new GeometryFactory(pm, -1); // We do not need PrecisionMode object anymore, it has // been copied to global_factory private storage delete pm; //////////////////////////////////////////////////////////////////////// // GEOMETRY CREATION //////////////////////////////////////////////////////////////////////// // Read function bodies to see the magic behind them geoms->push_back(create_point(150, 350)); geoms->push_back(create_square_linearring(0,0,100)); geoms->push_back(create_ushaped_linestring(60,60,100)); geoms->push_back(create_square_linearring(0,0,100)); geoms->push_back(create_square_polygon(0,200,300)); geoms->push_back(create_square_polygon(0,250,300)); geoms->push_back(create_simple_collection(geoms)); #if GEOMETRIC_SHAPES // These ones use a GeometricShapeFactory geoms->push_back(create_circle(0, 0, 10)); geoms->push_back(create_ellipse(0, 0, 8, 12)); geoms->push_back(create_rectangle(-5, -5, 10, 10)); // a square geoms->push_back(create_rectangle(-5, -5, 10, 20)); // a rectangle // The upper-right quarter of a vertical ellipse geoms->push_back(create_arc(0, 0, 10, 20, 0, M_PI/2)); geoms->push_back(create_sinestar(10, 10, 100, 5, 2).release()); // a sine star #endif // Print all geoms. cout<<"--------HERE ARE THE BASE GEOMS ----------"<<endl; wkt_print_geoms(geoms); #if UNARY_OPERATIONS //////////////////////////////////////////////////////////////////////// // UNARY OPERATIONS //////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////// // CENTROID ///////////////////////////////////////////// // Find centroid of each base geometry newgeoms = new vector<Geometry *>; for (unsigned int i=0; i<geoms->size(); i++) { Geometry *g = (*geoms)[i]; newgeoms->push_back( g->getCentroid() ); } // Print all convex hulls cout<<endl<<"------- AND HERE ARE THEIR CENTROIDS -----"<<endl; wkt_print_geoms(newgeoms); // Delete the centroids for (unsigned int i=0; i<newgeoms->size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; ///////////////////////////////////////////// // BUFFER ///////////////////////////////////////////// newgeoms = new vector<Geometry *>; for (unsigned int i=0; i<geoms->size(); i++) { Geometry *g = (*geoms)[i]; try { Geometry *g2 = g->buffer(10); newgeoms->push_back(g2); } catch (const GEOSException& exc) { cerr <<"GEOS Exception: geometry "<<i<<"->buffer(10): "<<exc.what()<<"\n"; } } cout<<endl<<"--------HERE COMES THE BUFFERED GEOMS ----------"<<endl; wkt_print_geoms(newgeoms); for (unsigned int i=0; i<newgeoms->size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; ///////////////////////////////////////////// // CONVEX HULL ///////////////////////////////////////////// // Make convex hulls of geometries newgeoms = new vector<Geometry *>; for (unsigned int i=0; i<geoms->size(); i++) { Geometry *g = (*geoms)[i]; newgeoms->push_back( g->convexHull() ); } // Print all convex hulls cout<<endl<<"--------HERE COMES THE HULLS----------"<<endl; wkt_print_geoms(newgeoms); // Delete the hulls for (unsigned int i=0; i<newgeoms->size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; #endif // UNARY_OPERATIONS #if RELATIONAL_OPERATORS //////////////////////////////////////////////////////////////////////// // RELATIONAL OPERATORS //////////////////////////////////////////////////////////////////////// cout<<"-------------------------------------------------------------------------------"<<endl; cout<<"RELATIONAL OPERATORS"<<endl; cout<<"-------------------------------------------------------------------------------"<<endl; ///////////////////////////////////////////// // DISJOINT ///////////////////////////////////////////// cout<<endl; cout<<" DISJOINT "; for (unsigned int i=0; i<geoms->size(); i++) { cout<<"\t["<<i<<"]"; } cout<<endl; for (unsigned int i=0; i<geoms->size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<<i<<"]\t"; for (unsigned int j=0; j<geoms->size(); j++) { Geometry *g2 = (*geoms)[j]; try { if ( g1->disjoint(g2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (const IllegalArgumentException& exc) { cout<<" X\t"; } catch (const std::exception& exc) { cerr<<exc.what()<<endl; } } cout<<endl; } ///////////////////////////////////////////// // TOUCHES ///////////////////////////////////////////// cout<<endl; cout<<" TOUCHES "; for (unsigned int i=0; i<geoms->size(); i++) { cout<<"\t["<<i<<"]"; } cout<<endl; for (unsigned int i=0; i<geoms->size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<<i<<"]\t"; for (unsigned int j=0; j<geoms->size(); j++) { Geometry *g2 = (*geoms)[j]; try { if ( g1->touches(g2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (const IllegalArgumentException& exc) { cout<<" X\t"; } catch (const std::exception& exc) { cerr<<exc.what()<<endl; } } cout<<endl; } ///////////////////////////////////////////// // INTERSECTS ///////////////////////////////////////////// cout<<endl; cout<<" INTERSECTS "; for (unsigned int i=0; i<geoms->size(); i++) { cout<<"\t["<<i<<"]"; } cout<<endl; for (unsigned int i=0; i<geoms->size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<<i<<"]\t"; for (unsigned int j=0; j<geoms->size(); j++) { Geometry *g2 = (*geoms)[j]; try { if ( g1->intersects(g2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (const IllegalArgumentException& exc) { cout<<" X\t"; } catch (const std::exception& exc) { cerr<<exc.what()<<endl; } } cout<<endl; } ///////////////////////////////////////////// // CROSSES ///////////////////////////////////////////// cout<<endl; cout<<" CROSSES "; for (unsigned int i=0; i<geoms->size(); i++) { cout<<"\t["<<i<<"]"; } cout<<endl; for (unsigned int i=0; i<geoms->size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<<i<<"]\t"; for (unsigned int j=0; j<geoms->size(); j++) { Geometry *g2 = (*geoms)[j]; try { if ( g1->crosses(g2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (const IllegalArgumentException& exc) { cout<<" X\t"; } catch (const std::exception& exc) { cerr<<exc.what()<<endl; } } cout<<endl; } ///////////////////////////////////////////// // WITHIN ///////////////////////////////////////////// cout<<endl; cout<<" WITHIN "; for (unsigned int i=0; i<geoms->size(); i++) { cout<<"\t["<<i<<"]"; } cout<<endl; for (unsigned int i=0; i<geoms->size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<<i<<"]\t"; for (unsigned int j=0; j<geoms->size(); j++) { Geometry *g2 = (*geoms)[j]; try { if ( g1->within(g2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (const IllegalArgumentException& exc) { cout<<" X\t"; } catch (const std::exception& exc) { cerr<<exc.what()<<endl; } } cout<<endl; } ///////////////////////////////////////////// // CONTAINS ///////////////////////////////////////////// cout<<endl; cout<<" CONTAINS "; for (unsigned int i=0; i<geoms->size(); i++) { cout<<"\t["<<i<<"]"; } cout<<endl; for (unsigned int i=0; i<geoms->size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<<i<<"]\t"; for (unsigned int j=0; j<geoms->size(); j++) { Geometry *g2 = (*geoms)[j]; try { if ( g1->contains(g2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (const IllegalArgumentException& exc) { cout<<" X\t"; } catch (const std::exception& exc) { cerr<<exc.what()<<endl; } } cout<<endl; } ///////////////////////////////////////////// // OVERLAPS ///////////////////////////////////////////// cout<<endl; cout<<" OVERLAPS "; for (unsigned int i=0; i<geoms->size(); i++) { cout<<"\t["<<i<<"]"; } cout<<endl; for (unsigned int i=0; i<geoms->size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<<i<<"]\t"; for (unsigned int j=0; j<geoms->size(); j++) { Geometry *g2 = (*geoms)[j]; try { if ( g1->overlaps(g2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (const IllegalArgumentException& exc) { cout<<" X\t"; } catch (const std::exception& exc) { cerr<<exc.what()<<endl; } } cout<<endl; } ///////////////////////////////////////////// // RELATE ///////////////////////////////////////////// cout<<endl; cout<<" RELATE "; for (unsigned int i=0; i<geoms->size(); i++) { cout<<"\t["<<i<<"]"; } cout<<endl; for (unsigned int i=0; i<geoms->size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<<i<<"]\t"; for (unsigned int j=0; j<geoms->size(); j++) { Geometry *g2 = (*geoms)[j]; IntersectionMatrix *im=NULL; try { // second argument is intersectionPattern string pattern = "212101212"; if ( g1->relate(g2, pattern) ) cout<<" 1\t"; else cout<<" 0\t"; // get the intersectionMatrix itself im=g1->relate(g2); delete im; // delete afterwards } // Geometry Collection is not a valid argument catch (const IllegalArgumentException& exc) { cout<<" X\t"; } catch (const std::exception& exc) { cerr<<exc.what()<<endl; } } cout<<endl; } ///////////////////////////////////////////// // EQUALS ///////////////////////////////////////////// cout<<endl; cout<<" EQUALS "; for (unsigned int i=0; i<geoms->size(); i++) { cout<<"\t["<<i<<"]"; } cout<<endl; for (unsigned int i=0; i<geoms->size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<<i<<"]\t"; for (unsigned int j=0; j<geoms->size(); j++) { Geometry *g2 = (*geoms)[j]; try { if ( g1->equals(g2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (const IllegalArgumentException& exc) { cout<<" X\t"; } catch (const std::exception& exc) { cerr<<exc.what()<<endl; } } cout<<endl; } ///////////////////////////////////////////// // EQUALS_EXACT ///////////////////////////////////////////// cout<<endl; cout<<"EQUALS_EXACT "; for (unsigned int i=0; i<geoms->size(); i++) { cout<<"\t["<<i<<"]"; } cout<<endl; for (unsigned int i=0; i<geoms->size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<<i<<"]\t"; for (unsigned int j=0; j<geoms->size(); j++) { Geometry *g2 = (*geoms)[j]; try { // second argument is a tolerance if ( g1->equalsExact(g2, 0.5) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (const IllegalArgumentException& exc) { cout<<" X\t"; } catch (const std::exception& exc) { cerr<<exc.what()<<endl; } } cout<<endl; } ///////////////////////////////////////////// // IS_WITHIN_DISTANCE ///////////////////////////////////////////// cout<<endl; cout<<"IS_WITHIN_DIST"; for (unsigned int i=0; i<geoms->size(); i++) { cout<<"\t["<<i<<"]"; } cout<<endl; for (unsigned int i=0; i<geoms->size(); i++) { Geometry *g1 = (*geoms)[i]; cout<<" ["<<i<<"]\t"; for (unsigned int j=0; j<geoms->size(); j++) { Geometry *g2 = (*geoms)[j]; try { // second argument is the distance if ( g1->isWithinDistance(g2,2) ) cout<<" 1\t"; else cout<<" 0\t"; } // Geometry Collection is not a valid argument catch (const IllegalArgumentException& exc) { cout<<" X\t"; } catch (const std::exception& exc) { cerr<<exc.what()<<endl; } } cout<<endl; } #endif // RELATIONAL_OPERATORS #if COMBINATIONS //////////////////////////////////////////////////////////////////////// // COMBINATIONS //////////////////////////////////////////////////////////////////////// cout<<endl; cout<<"-------------------------------------------------------------------------------"<<endl; cout<<"COMBINATIONS"<<endl; cout<<"-------------------------------------------------------------------------------"<<endl; ///////////////////////////////////////////// // UNION ///////////////////////////////////////////// // Make unions of all geoms newgeoms = new vector<Geometry *>; for (unsigned int i=0; i<geoms->size()-1; i++) { Geometry *g1 = (*geoms)[i]; for (unsigned int j=i+1; j<geoms->size(); j++) { Geometry *g2 = (*geoms)[j]; try { Geometry *g3 = g1->Union(g2); newgeoms->push_back(g3); } // It's illegal to union a collection ... catch (const IllegalArgumentException& ill) { //cerr <<ill.toString()<<"\n"; } catch (const std::exception& exc) { cerr<<exc.what()<<endl; } } } // Print all unions cout<<endl<<"----- AND HERE ARE SOME UNION COMBINATIONS ------"<<endl; wkt_print_geoms(newgeoms); // Delete the resulting geoms for (unsigned int i=0; i<newgeoms->size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; ///////////////////////////////////////////// // INTERSECTION ///////////////////////////////////////////// // Compute intersection of adhiacent geometries newgeoms = new vector<Geometry *>; for (unsigned int i=0; i<geoms->size()-1; i++) { Geometry *g1 = (*geoms)[i]; for (unsigned int j=i+1; j<geoms->size(); j++) { Geometry *g2 = (*geoms)[j]; try { Geometry *g3 = g1->intersection(g2); newgeoms->push_back(g3); } // Collection are illegal as intersection argument catch (const IllegalArgumentException& ill) { //cerr <<ill.toString()<<"\n"; } catch (const std::exception& exc) { cerr<<exc.what()<<endl; } } } cout<<endl<<"----- HERE ARE SOME INTERSECTIONS COMBINATIONS ------"<<endl; wkt_print_geoms(newgeoms); // Delete the resulting geoms for (unsigned int i=0; i<newgeoms->size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; ///////////////////////////////////////////// // DIFFERENCE ///////////////////////////////////////////// // Compute difference of adhiacent geometries newgeoms = new vector<Geometry *>; for (unsigned int i=0; i<geoms->size()-1; i++) { Geometry *g1 = (*geoms)[i]; for (unsigned int j=i+1; j<geoms->size(); j++) { Geometry *g2 = (*geoms)[j]; try { Geometry *g3 = g1->difference(g2); newgeoms->push_back(g3); } // Collection are illegal as difference argument catch (const IllegalArgumentException& ill) { //cerr <<ill.toString()<<"\n"; } catch (const std::exception& exc) { cerr<<exc.what()<<endl; } } } cout<<endl<<"----- HERE ARE SOME DIFFERENCE COMBINATIONS ------"<<endl; wkt_print_geoms(newgeoms); // Delete the resulting geoms for (unsigned int i=0; i<newgeoms->size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; ///////////////////////////////////////////// // SYMMETRIC DIFFERENCE ///////////////////////////////////////////// // Compute symmetric difference of adhiacent geometries newgeoms = new vector<Geometry *>; for (unsigned int i=0; i<geoms->size()-1; i++) { Geometry *g1 = (*geoms)[i]; for (unsigned int j=i+1; j<geoms->size(); j++) { Geometry *g2 = (*geoms)[j]; try { Geometry *g3 = g1->symDifference(g2); newgeoms->push_back(g3); } // Collection are illegal as symdifference argument catch (const IllegalArgumentException& ill) { //cerr <<ill.toString()<<"\n"; } catch (const std::exception& exc) { cerr<<exc.what()<<endl; } } } cout<<endl<<"----- HERE ARE SYMMETRIC DIFFERENCES ------"<<endl; wkt_print_geoms(newgeoms); // Delete the resulting geoms for (unsigned int i=0; i<newgeoms->size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; #endif // COMBINATIONS #if LINEMERGE ///////////////////////////////////////////// // LINEMERGE ///////////////////////////////////////////// LineMerger lm; lm.add(geoms); vector<LineString *> *mls = lm.getMergedLineStrings(); newgeoms = new vector<Geometry *>; for (unsigned int i=0; i<mls->size(); i++) newgeoms->push_back((*mls)[i]); delete mls; cout<<endl<<"----- HERE IS THE LINEMERGE OUTPUT ------"<<endl; wkt_print_geoms(newgeoms); // Delete the resulting geoms for (unsigned int i=0; i<newgeoms->size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; #endif // LINEMERGE #if POLYGONIZE ///////////////////////////////////////////// // POLYGONIZE ///////////////////////////////////////////// Polygonizer plgnzr; plgnzr.add(geoms); vector<Polygon *> *polys = plgnzr.getPolygons(); newgeoms = new vector<Geometry *>; for (unsigned int i=0; i<polys->size(); i++) newgeoms->push_back((*polys)[i]); delete polys; cout<<endl<<"----- HERE IS POLYGONIZE OUTPUT ------"<<endl; wkt_print_geoms(newgeoms); // Delete the resulting geoms for (unsigned int i=0; i<newgeoms->size(); i++) { delete (*newgeoms)[i]; } delete newgeoms; #endif // POLYGONIZE ///////////////////////////////////////////// // CLEANUP ///////////////////////////////////////////// // Delete base geometries for (unsigned int i=0; i<geoms->size(); i++) { delete (*geoms)[i]; } delete geoms; delete global_factory; }
void filter(const Geometry *geom) { const LineString *ls = dynamic_cast<const LineString *>(geom); if ( ls ) lm->add(ls); }
void XMLTester::parseTest() { using namespace operation::overlay; typedef std::auto_ptr< geom::Geometry > GeomAutoPtr; int success=0; // no success by default std::string opName; std::string opArg1; std::string opArg2; std::string opArg3; std::string opRes; //string opSig; ++testCount; xml.IntoElem(); xml.FindChildElem("op"); opName=xml.GetChildAttrib("name"); opArg1=xml.GetChildAttrib("arg1"); opArg2=xml.GetChildAttrib("arg2"); opArg3=xml.GetChildAttrib("arg3"); //opSig=xml.GetChildAttrib("arg3"); opRes=xml.GetChildData(); // trim blanks opRes=trimBlanks(opRes); opName=trimBlanks(opName); tolower(opName); std::string opSig=""; if ( opArg1 != "" ) opSig=opArg1; if ( opArg2 != "" ) { if ( opSig != "" ) opSig += ", "; opSig += opArg2; } if ( opArg3 != "" ) { if ( opSig != "" ) opSig += ", "; opSig += opArg3; } opSignature = opName + "(" + opSig + ")"; std::string actual_result="NONE"; // expected_result will be modified by specific tests // if needed (geometry normalization, for example) std::string expected_result=opRes; try { util::Profile profile("op"); if (opName=="relate") { std::auto_ptr<geom::IntersectionMatrix> im(gA->relate(gB)); assert(im.get()); if (im->matches(opArg3)) actual_result="true"; else actual_result="false"; if (actual_result==opRes) success=1; } else if (opName=="isvalid") { geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) { gT=gB; } if (gT->isValid()) actual_result="true"; else actual_result="false"; if (actual_result==opRes) success=1; } else if (opName=="intersection") { GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); //GeomAutoPtr gRealRes(gA->intersection(gB)); GeomAutoPtr gRealRes = BinaryOp(gA, gB, overlayOp(OverlayOp::opINTERSECTION)); gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; if ( testValidOutput ) testValid(gRes.get(), "result"); actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); } else if (opName=="union") { GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); //GeomAutoPtr gRealRes(gA->Union(gB)); GeomAutoPtr gRealRes = BinaryOp(gA, gB, overlayOp(OverlayOp::opUNION)); gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; if ( testValidOutput ) testValid(gRes.get(), "result"); actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); } else if (opName=="difference") { GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); //GeomAutoPtr gRealRes(gA->difference(gB)); GeomAutoPtr gRealRes = BinaryOp(gA, gB, overlayOp(OverlayOp::opDIFFERENCE)); gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; if ( testValidOutput ) testValid(gRes.get(), "result"); actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); } else if (opName=="symdifference") { GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); //GeomAutoPtr gRealRes(gA->symDifference(gB)); GeomAutoPtr gRealRes = BinaryOp(gA, gB, overlayOp(OverlayOp::opSYMDIFFERENCE)); gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; if ( testValidOutput ) testValid(gRes.get(), "result"); actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); } else if (opName=="intersects") { if (gA->intersects(gB)) actual_result="true"; else actual_result="false"; if (actual_result==opRes) success=1; } else if (opName=="getboundary") { geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); GeomAutoPtr gRealRes(gT->getBoundary()); gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; if ( testValidOutput ) testValid(gRes.get(), "result"); actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); } else if (opName=="getcentroid") { geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); GeomAutoPtr gRealRes(gT->getCentroid()); if ( gRealRes.get() ) gRealRes->normalize(); else gRealRes.reset(factory->createGeometryCollection()); gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; if ( testValidOutput ) testValid(gRes.get(), "result"); actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); } else if (opName=="issimple") { geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; if (gT->isSimple()) actual_result="true"; else actual_result="false"; if (actual_result==opRes) success=1; } else if (opName=="convexhull") { geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); GeomAutoPtr gRealRes(gT->convexHull()); gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; if ( testValidOutput ) testValid(gRes.get(), "result"); actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); } else if (opName=="buffer") { geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); profile.start(); GeomAutoPtr gRealRes; double dist = atof(opArg3.c_str()); if ( opArg2 != "" ) { gRealRes.reset(gT->buffer(dist, atoi(opArg2.c_str()))); } else { gRealRes.reset(gT->buffer(dist)); } profile.stop(); gRealRes->normalize(); // Assume a success and check for obvious failures success=1; do { // TODO: Is a buffer always an area ? // we might check geometry type.. if ( gRes->getGeometryTypeId() != gRealRes->getGeometryTypeId() ) { std::cerr << "Expected result is of type " << gRes->getGeometryType() << "; obtained result is of type " << gRealRes->getGeometryType() << std::endl; success=0; break; } if ( gRes->isEmpty() && gRealRes->isEmpty() ) { // Success ! break; } if ( gRes->getDimension() != 2 ) { std::cerr << "Don't know how to validate " << "result of buffer operation " << "when expected result is not an " << "areal type." << std::endl; } double expectedArea = gRes->getArea(); /// Allow area difference being at most /// 1/1000 of the area of the expected result. double areatol = expectedArea / 1e3; GeomAutoPtr gDiff = BinaryOp(gRes.get(), gRealRes.get(), overlayOp(OverlayOp::opDIFFERENCE)); double areaDiff = gDiff->getArea(); if ( areaDiff > areatol ) { std::cerr << "Area of difference between " << "obtained and expected: " << areaDiff << " - Tolerated diff: " << areatol << std::endl; success=0; break; } else { std::cerr << "Area of difference between " << "obtained and expected: " << areaDiff << " - Tolerated diff: " << areatol << " (SUCCESS!)" << std::endl; } } while (0); if ( testValidOutput ) testValid(gRes.get(), "result"); actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); } else if (opName=="getinteriorpoint") { geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; GeomAutoPtr gRes(parseGeometry(opRes, "expected")); gRes->normalize(); GeomAutoPtr gRealRes(gT->getInteriorPoint()); if ( gRealRes.get() ) gRealRes->normalize(); else gRealRes.reset(factory->createGeometryCollection()); if (gRes->compareTo(gRealRes.get())==0) success=1; if ( testValidOutput ) testValid(gRes.get(), "result"); actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); } else if (opName=="iswithindistance") { float dist=atof(opArg3.c_str()); if (gA->isWithinDistance(gB, dist)) { actual_result="true"; } else { actual_result="false"; } if (actual_result==opRes) success=1; } else if (opName=="polygonize") { GeomAutoPtr gRes(wktreader->read(opRes)); gRes->normalize(); Polygonizer plgnzr; plgnzr.add(gA); std::vector<geos::geom::Polygon *>*polys = plgnzr.getPolygons(); std::vector<geom::Geometry *>*newgeoms = new std::vector<geom::Geometry *>; for (unsigned int i=0; i<polys->size(); i++) newgeoms->push_back((*polys)[i]); delete polys; GeomAutoPtr gRealRes(factory->createGeometryCollection(newgeoms)); gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; if ( testValidOutput ) testValid(gRes.get(), "result"); actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); } else if (opName=="linemerge") { GeomAutoPtr gRes(wktreader->read(opRes)); gRes->normalize(); geom::Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; LineMerger merger; merger.add(gT); std::auto_ptr< std::vector<geom::LineString *> > lines ( merger.getMergedLineStrings() ); std::vector<geom::Geometry *>*newgeoms = new std::vector<geom::Geometry *>(lines->begin(), lines->end()); GeomAutoPtr gRealRes(factory->createGeometryCollection(newgeoms)); gRealRes->normalize(); if (gRes->compareTo(gRealRes.get())==0) success=1; if ( testValidOutput ) testValid(gRes.get(), "result"); actual_result=printGeom(gRealRes.get()); expected_result=printGeom(gRes.get()); } else if (opName=="areatest") { char* rest; double toleratedDiff = strtod(opRes.c_str(), &rest); if ( rest == opRes.c_str() ) { throw std::runtime_error("malformed testcase: missing tolerated area difference in 'areatest' op"); } if ( verbose > 1 ) { std::cerr << "Running intersection for areatest" << std::endl; } GeomAutoPtr gI = BinaryOp(gA, gB, overlayOp(OverlayOp::opINTERSECTION)); if ( testValidOutput ) { testValid(gI.get(), "areatest intersection"); } if ( verbose > 1 ) { std::cerr << "Running difference(A,B) for areatest" << std::endl; } GeomAutoPtr gDab = BinaryOp(gA, gB, overlayOp(OverlayOp::opDIFFERENCE)); if ( verbose > 1 ) { std::cerr << "Running difference(B,A) for areatest" << std::endl; } GeomAutoPtr gDba = BinaryOp(gB, gA, overlayOp(OverlayOp::opDIFFERENCE)); if ( testValidOutput ) { testValid(gI.get(), "areatest difference"); } if ( verbose > 1 ) { std::cerr << "Running symdifference for areatest" << std::endl; } GeomAutoPtr gSD = BinaryOp(gA, gB, overlayOp(OverlayOp::opSYMDIFFERENCE)); if ( verbose > 1 ) { std::cerr << "Running union for areatest" << std::endl; } GeomAutoPtr gU = BinaryOp(gA, gB, overlayOp(OverlayOp::opUNION)); double areaA = gA->getArea(); double areaB = gB->getArea(); double areaI = gI->getArea(); double areaDab = gDab->getArea(); double areaDba = gDba->getArea(); double areaSD = gSD->getArea(); double areaU = gU->getArea(); double maxdiff = 0; std::string maxdiffop; // @ : symdifference // - : difference // + : union // ^ : intersection // A == ( A ^ B ) + ( A - B ) double diff = fabs ( areaA - areaI - areaDab ); if ( diff > maxdiff ) { maxdiffop = "A == ( A ^ B ) + ( A - B )"; maxdiff = diff; } // B == ( A ^ B ) + ( B - A ) diff = fabs ( areaB - areaI - areaDba ); if ( diff > maxdiff ) { maxdiffop = "B == ( A ^ B ) + ( B - A )"; maxdiff = diff; } // ( A @ B ) == ( A - B ) + ( B - A ) diff = fabs ( areaDab + areaDba - areaSD ); if ( diff > maxdiff ) { maxdiffop = "( A @ B ) == ( A - B ) + ( B - A )"; maxdiff = diff; } // ( A u B ) == ( A ^ B ) + ( A @ B ) diff = fabs ( areaI + areaSD - areaU ); if ( diff > maxdiff ) { maxdiffop = "( A u B ) == ( A ^ B ) + ( A @ B )"; maxdiff = diff; } if ( maxdiff <= toleratedDiff ) { success=1; } std::stringstream tmp; tmp << maxdiffop << ": " << maxdiff; actual_result=tmp.str(); expected_result=opRes; } else { std::cerr << *curr_file << ":"; std::cerr << " case" << caseCount << ":"; std::cerr << " test" << testCount << ": " << opName << "(" << opSig << ")"; std::cerr << ": skipped (unrecognized)." << std::endl; return; } } catch (const std::exception &e) { std::cerr<<"EXCEPTION on case "<<caseCount <<" test "<<testCount<<": "<<e.what() <<std::endl; actual_result = e.what(); } catch (...) { std::cerr<<"EXEPTION"<<std::endl; actual_result = "Unknown exception thrown"; } if ( success ) ++succeeded; else ++failed; if ((!success && verbose) || verbose > 1) { printTest(success, expected_result, actual_result); } if (test_predicates && gB && gA) { runPredicates(gA, gB); } xml.OutOfElem(); }
size_t build_geometry(osmid_t osm_id, struct osmNode **xnodes, int *xcount, int make_polygon, int enable_multi, double split_at) { size_t wkt_size = 0; std::auto_ptr<std::vector<Geometry*> > lines(new std::vector<Geometry*>); GeometryFactory gf; geom_ptr geom; #ifdef HAS_PREPARED_GEOMETRIES geos::geom::prep::PreparedGeometryFactory pgf; #endif try { for (int c=0; xnodes[c]; c++) { std::auto_ptr<CoordinateSequence> coords(gf.getCoordinateSequenceFactory()->create((size_t)0, (size_t)2)); for (int i = 0; i < xcount[c]; i++) { struct osmNode *nodes = xnodes[c]; Coordinate c; c.x = nodes[i].lon; c.y = nodes[i].lat; coords->add(c, 0); } if (coords->getSize() > 1) { geom = geom_ptr(gf.createLineString(coords.release())); lines->push_back(geom.release()); } } //geom_ptr segment(0); geom_ptr mline (gf.createMultiLineString(lines.release())); //geom_ptr noded (segment->Union(mline.get())); LineMerger merger; //merger.add(noded.get()); merger.add(mline.get()); std::auto_ptr<std::vector<LineString *> > merged(merger.getMergedLineStrings()); WKTWriter writer; // Procces ways into lines or simple polygon list polygondata* polys = new polygondata[merged->size()]; unsigned totalpolys = 0; for (unsigned i=0 ;i < merged->size(); ++i) { std::auto_ptr<LineString> pline ((*merged ) [i]); if (make_polygon && pline->getNumPoints() > 3 && pline->isClosed()) { polys[totalpolys].polygon = gf.createPolygon(gf.createLinearRing(pline->getCoordinates()),0); polys[totalpolys].ring = gf.createLinearRing(pline->getCoordinates()); polys[totalpolys].area = polys[totalpolys].polygon->getArea(); polys[totalpolys].iscontained = 0; polys[totalpolys].containedbyid = 0; if (polys[totalpolys].area > 0.0) totalpolys++; else { delete(polys[totalpolys].polygon); delete(polys[totalpolys].ring); } } else { //std::cerr << "polygon(" << osm_id << ") is no good: points(" << pline->getNumPoints() << "), closed(" << pline->isClosed() << "). " << writer.write(pline.get()) << std::endl; double distance = 0; std::auto_ptr<CoordinateSequence> segment; segment = std::auto_ptr<CoordinateSequence>(gf.getCoordinateSequenceFactory()->create((size_t)0, (size_t)2)); segment->add(pline->getCoordinateN(0)); for(unsigned i=1; i<pline->getNumPoints(); i++) { segment->add(pline->getCoordinateN(i)); distance += pline->getCoordinateN(i).distance(pline->getCoordinateN(i-1)); if ((distance >= split_at) || (i == pline->getNumPoints()-1)) { geom = geom_ptr(gf.createLineString(segment.release())); std::string wkt = writer.write(geom.get()); wkts.push_back(wkt); areas.push_back(0); wkt_size++; distance=0; segment = std::auto_ptr<CoordinateSequence>(gf.getCoordinateSequenceFactory()->create((size_t)0, (size_t)2)); segment->add(pline->getCoordinateN(i)); } } //std::string text = writer.write(pline.get()); //wkts.push_back(text); //areas.push_back(0.0); //wkt_size++; } } if (totalpolys) { qsort(polys, totalpolys, sizeof(polygondata), polygondata_comparearea); unsigned toplevelpolygons = 0; int istoplevelafterall; for (unsigned i=0 ;i < totalpolys; ++i) { if (polys[i].iscontained != 0) continue; toplevelpolygons++; #ifdef HAS_PREPARED_GEOMETRIES const geos::geom::prep::PreparedGeometry* preparedtoplevelpolygon = pgf.create(polys[i].polygon); #endif for (unsigned j=i+1; j < totalpolys; ++j) { #ifdef HAS_PREPARED_GEOMETRIES // Does preparedtoplevelpolygon contain the smaller polygon[j]? if (polys[j].containedbyid == 0 && preparedtoplevelpolygon->contains(polys[j].polygon)) #else // Does polygon[i] contain the smaller polygon[j]? if (polys[j].containedbyid == 0 && polys[i].polygon->contains(polys[j].polygon)) #endif { // are we in a [i] contains [k] contains [j] situation // which would actually make j top level istoplevelafterall = 0; for (unsigned k=i+1; k < j; ++k) { if (polys[k].iscontained && polys[k].containedbyid == i && polys[k].polygon->contains(polys[j].polygon)) { istoplevelafterall = 1; break; } #if 0 else if (polys[k].polygon->intersects(polys[j].polygon) || polys[k].polygon->touches(polys[j].polygon)) { // FIXME: This code does not work as intended // It should be setting the polys[k].ring in order to update this object // but the value of polys[k].polygon calculated is normally NULL // Add polygon this polygon (j) to k since they intersect // Mark ourselfs to be dropped (2), delete the original k Geometry* polyunion = polys[k].polygon->Union(polys[j].polygon); delete(polys[k].polygon); polys[k].polygon = dynamic_cast<Polygon*>(polyunion); polys[j].iscontained = 2; // Drop istoplevelafterall = 2; break; } #endif } if (istoplevelafterall == 0) { polys[j].iscontained = 1; polys[j].containedbyid = i; } } } #ifdef HAS_PREPARED_GEOMETRIES pgf.destroy(preparedtoplevelpolygon); #endif } // polys now is a list of ploygons tagged with which ones are inside each other // List of polygons for multipolygon std::auto_ptr<std::vector<Geometry*> > polygons(new std::vector<Geometry*>); // For each top level polygon create a new polygon including any holes for (unsigned i=0 ;i < totalpolys; ++i) { if (polys[i].iscontained != 0) continue; // List of holes for this top level polygon std::auto_ptr<std::vector<Geometry*> > interior(new std::vector<Geometry*>); for (unsigned j=i+1; j < totalpolys; ++j) { if (polys[j].iscontained == 1 && polys[j].containedbyid == i) { interior->push_back(polys[j].ring); } } Polygon* poly(gf.createPolygon(polys[i].ring, interior.release())); poly->normalize(); polygons->push_back(poly); } // Make a multipolygon if required if ((toplevelpolygons > 1) && enable_multi) { std::auto_ptr<MultiPolygon> multipoly(gf.createMultiPolygon(polygons.release())); //if (multipoly->isValid()) //{ std::string text = writer.write(multipoly.get()); wkts.push_back(text); areas.push_back(multipoly->getArea()); wkt_size++; //} } else { for(unsigned i=0; i<toplevelpolygons; i++) { Polygon* poly = dynamic_cast<Polygon*>(polygons->at(i));; //if (poly->isValid()) //{ std::string text = writer.write(poly); wkts.push_back(text); areas.push_back(poly->getArea()); wkt_size++; //} delete(poly); } } } for (unsigned i=0; i < totalpolys; ++i) { delete(polys[i].polygon); } delete[](polys); } catch (std::exception& e) { std::cerr << std::endl << "Standard exception processing way_id "<< osm_id << ": " << e.what() << std::endl; wkt_size = 0; } catch (...) { std::cerr << std::endl << "Exception caught processing way id=" << osm_id << std::endl; wkt_size = 0; } return wkt_size; }
/*public*/ Geometry* BufferBuilder::bufferLineSingleSided( const Geometry* g, double distance, bool leftSide ) { // Returns the line used to create a single-sided buffer. // Input requirement: Must be a LineString. const LineString* l = dynamic_cast< const LineString* >( g ); if ( !l ) throw util::IllegalArgumentException("BufferBuilder::bufferLineSingleSided only accept linestrings"); // Get geometry factory and precision model. const PrecisionModel* precisionModel = workingPrecisionModel; if ( !precisionModel ) precisionModel = l->getPrecisionModel(); assert( precisionModel ); assert( l ); geomFact = l->getFactory(); // First, generate the two-sided buffer using a butt-cap. BufferParameters modParams = bufParams; modParams.setEndCapStyle(BufferParameters::CAP_FLAT); Geometry* buf = 0; // This is a (temp?) hack to workaround the fact that // BufferBuilder BufferParamaters are immutable after // construction, while we want to force the end cap // style to FLAT for single-sided buffering { BufferBuilder tmp(modParams); buf = tmp.buffer( l, distance ); } // Create MultiLineStrings from this polygon. Geometry* bufLineString = buf->getBoundary(); #ifdef GEOS_DEBUG_SSB std::cerr << "input|" << *l << std::endl; std::cerr << "buffer|" << *bufLineString << std::endl; #endif // Then, get the raw (i.e. unnoded) single sided offset curve. OffsetCurveBuilder curveBuilder( precisionModel, modParams ); std::vector< CoordinateSequence* > lineList; std::auto_ptr< CoordinateSequence > coords ( g->getCoordinates() ); curveBuilder.getSingleSidedLineCurve( coords.get(), distance, lineList, leftSide, !leftSide ); coords.reset(); // Create a SegmentString from these coordinates. SegmentString::NonConstVect curveList; for ( unsigned int i = 0; i < lineList.size(); ++i ) { CoordinateSequence* seq = lineList[i]; SegmentString* ss = new NodedSegmentString(seq, NULL); curveList.push_back( ss ); } // Node these SegmentStrings. Noder* noder = getNoder( precisionModel ); noder->computeNodes( &curveList ); SegmentString::NonConstVect* nodedEdges = noder->getNodedSubstrings(); // Create a geometry out of the noded substrings. std::vector< Geometry* >* singleSidedNodedEdges = new std::vector< Geometry * >(); for ( unsigned int i = 0, n = nodedEdges->size(); i < n; ++i ) { SegmentString* ss = ( *nodedEdges )[i]; Geometry* tmp = geomFact->createLineString( ss->getCoordinates()->clone() ); singleSidedNodedEdges->push_back( tmp ); } if ( nodedEdges != &curveList ) delete nodedEdges; for (size_t i=0, n=curveList.size(); i<n; ++i) delete curveList[i]; curveList.clear(); for (size_t i=0, n=lineList.size(); i<n; ++i) delete lineList[i]; lineList.clear(); Geometry* singleSided = geomFact->createMultiLineString( singleSidedNodedEdges ); #ifdef GEOS_DEBUG_SSB std::cerr << "edges|" << *singleSided << std::endl; #endif // Use the boolean operation intersect to obtain the line segments lying // on both the butt-cap buffer and this multi-line. //Geometry* intersectedLines = singleSided->intersection( bufLineString ); // NOTE: we use Snapped overlay because the actual buffer boundary might // diverge from original offset curves due to the addition of // intersections with caps and joins curves using geos::operation::overlay::snap::SnapOverlayOp; Geometry* intersectedLines = SnapOverlayOp::overlayOp(*singleSided, *bufLineString, OverlayOp::opINTERSECTION).release(); #ifdef GEOS_DEBUG_SSB std::cerr << "intersection" << "|" << *intersectedLines << std::endl; #endif // Merge result lines together. LineMerger lineMerge; lineMerge.add( intersectedLines ); std::auto_ptr< std::vector< LineString* > > mergedLines ( lineMerge.getMergedLineStrings() ); // Convert the result into a std::vector< Geometry* >. std::vector< Geometry* >* mergedLinesGeom = new std::vector< Geometry* >(); const Coordinate& startPoint = l->getCoordinatesRO()->front(); const Coordinate& endPoint = l->getCoordinatesRO()->back(); while( !mergedLines->empty() ) { // Remove end points if they are a part of the original line to be // buffered. CoordinateSequence::AutoPtr coords(mergedLines->back()->getCoordinates()); if ( NULL != coords.get() ) { // Use 98% of the buffer width as the point-distance requirement - this // is to ensure that the point that is "distance" +/- epsilon is not // included. const double ptDistAllowance = 0.98 * distance; // Use 102% of the buffer width as the line-length requirement - this // is to ensure that line segments that is length "distance" +/- // epsilon is removed. const double segLengthAllowance = 1.02 * distance; // Clean up the front of the list. // Loop until the line's end is not inside the buffer width from // the startPoint. while ( coords->size() > 1 && coords->front().distance( startPoint ) < ptDistAllowance ) { // Record the end segment length. double segLength = coords->front().distance( ( *coords )[1] ); // Stop looping if there are no more points, or if the segment // length is larger than the buffer width. if ( coords->size() <= 1 || segLength > segLengthAllowance ) { break; } // If the first point is less than buffer width away from the // reference point, then delete the point. coords->deleteAt( 0 ); } while ( coords->size() > 1 && coords->front().distance( endPoint ) < ptDistAllowance ) { double segLength = coords->front().distance( ( *coords )[1] ); if ( coords->size() <= 1 || segLength > segLengthAllowance ) { break; } coords->deleteAt( 0 ); } // Clean up the back of the list. while ( coords->size() > 1 && coords->back().distance( startPoint ) < ptDistAllowance ) { double segLength = coords->back().distance( ( *coords )[coords->size()-2] ); if ( coords->size() <= 1 || segLength > segLengthAllowance ) { break; } coords->deleteAt( coords->size()-1 ); } while ( coords->size() > 1 && coords->back().distance( endPoint ) < ptDistAllowance ) { double segLength = coords->back().distance( ( *coords )[coords->size()-2] ); if ( coords->size() <= 1 || segLength > segLengthAllowance ) { break; } coords->deleteAt( coords->size()-1 ); } // Add the coordinates to the resultant line string. if ( coords->size() > 1 ) { mergedLinesGeom->push_back( geomFact->createLineString( coords.release() ) ); } } geomFact->destroyGeometry( mergedLines->back() ); mergedLines->pop_back(); } // Clean up. if ( noder != workingNoder ) delete noder; geomFact->destroyGeometry( buf ); geomFact->destroyGeometry( bufLineString ); geomFact->destroyGeometry( singleSided ); geomFact->destroyGeometry( intersectedLines ); if ( mergedLinesGeom->size() > 1 ) return geomFact->createMultiLineString( mergedLinesGeom ); else { // Must be a single line Geometry* single = (*mergedLinesGeom)[0]; delete mergedLinesGeom; return single; } }