/*public*/ std::auto_ptr<geom::Geometry> UnaryUnionOp::Union() { using geom::Puntal; typedef std::auto_ptr<geom::Geometry> GeomAutoPtr; GeomAutoPtr ret; if ( ! geomFact ) return ret; /** * For points and lines, only a single union operation is * required, since the OGC model allowings self-intersecting * MultiPoint and MultiLineStrings. * This is not the case for polygons, so Cascaded Union is required. */ GeomAutoPtr unionPoints; if (!points.empty()) { GeomAutoPtr ptGeom = geomFact->buildGeometry( points.begin(), points.end() ); unionPoints = unionNoOpt(*ptGeom); } GeomAutoPtr unionLines; if (!lines.empty()) { /* JTS compatibility NOTE: * we use cascaded here for robustness [1] * but also add a final unionNoOpt step to deal with * self-intersecting lines [2] * * [1](http://trac.osgeo.org/geos/ticket/392 * [2](http://trac.osgeo.org/geos/ticket/482 * */ unionLines.reset( CascadedUnion::Union( lines.begin(), lines.end() ) ); unionLines = unionNoOpt(*unionLines); } GeomAutoPtr unionPolygons; if (!polygons.empty()) { unionPolygons.reset( CascadedPolygonUnion::Union( polygons.begin(), polygons.end() ) ); } /** * Performing two unions is somewhat inefficient, * but is mitigated by unioning lines and points first */ GeomAutoPtr unionLA = unionWithNull(unionLines, unionPolygons); assert(!unionLines.get()); assert(!unionPolygons.get()); if ( ! unionPoints.get() ) { ret = unionLA; assert(!unionLA.get()); } else if ( ! unionLA.get() ) { ret = unionPoints; assert(!unionPoints.get()); } else { Puntal& up = dynamic_cast<Puntal&>(*unionPoints); ret = PointGeometryUnion::Union(up, *unionLA); } if ( ! ret.get() ) { ret.reset( geomFact->createGeometryCollection() ); } return ret; }
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); } }
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(); }