/* This file is part of SECONDO. Copyright (C) 2011, University in Hagen, Department of Computer Science, Database Systems for New Applications. SECONDO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SECONDO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with SECONDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "map2.h" #include "../sint.h" #include "../sreal.h" #include "../sbool.h" #include "../sstring.h" #include "../msint.h" #include "../msreal.h" #include "../msbool.h" #include "../msstring.h" #include "../util/parse_error.h" #include "../util/types.h" namespace raster2 { /* The following declarations are used by the type mapping to check whether the grids of the operator arguments are compatible. */ ListExpr map2TypeMap(ListExpr args) { if(!nl->HasLength(args,3)){ return listutils::typeError("3 arguments expected"); } ListExpr arg1 = nl->First(args); ListExpr arg2 = nl->Second(args); ListExpr arg3 = nl->Third(args); //cout << "args = " << nl->ToString(args) << endl; //cout << "arg1 = " << nl->ToString(arg1) << endl; //cout << "arg2 = " << nl->ToString(arg2) << endl; //cout << "arg3 = " << nl->ToString(arg3) << endl; std::string err = "raster x raster x fun expected" ; if(!util::isSType(arg1) && !util::isMSType(arg1)){ return listutils::typeError( err + " (first arg is not a raster type)"); } if(!util::isSType(arg2) && !util::isMSType(arg2)){ return listutils::typeError( err + " (second arg is not a raster type)"); } if(!listutils::isMap<2>(arg3)){ return listutils::typeError( err + " (third arg is not a function with 2 arguments)"); } bool static1 = util::isSType(arg1); bool static2 = util::isSType(arg2); // if(static1!=static2){ // return listutils::typeError("mix of static and moving " // "rasters not allowed"); // } std::string bt1 = util::getValueBasicType(nl->ToString(arg1)); std::string bt2 = util::getValueBasicType(nl->ToString(arg2)); ListExpr funarg1 = nl->Second(arg3); ListExpr funarg2 = nl->Third(arg3); ListExpr funres = nl->Fourth(arg3); if(!listutils::isSymbol(funarg1,bt1)){ return listutils::typeError("fun argument 1 and raster 1 " "type does not match"); } if(!listutils::isSymbol(funarg2,bt2)){ return listutils::typeError("fun argument 2 and raster 2 " "type does not match"); } std::string restype=""; if(static1 && static2){ restype=util::getSpatialBasicType(nl->ToString(funres)); } else { restype = util::getMovingSpatialBasicType(nl->ToString(funres)); } if(restype==""){ return listutils::typeError("Functionresult does not corresponds" " to a raster type"); } return nl->SymbolAtom(restype); } int map2SelectFun(ListExpr args) { int offset = 0; int i; NList types(args); std::string first = types.first().str(); std::string second = types.second().str(); std::string result = types.third().fourth().str(); std::string idf = first.substr(first.length()-2, 2); std::string ids = second.substr(second.length()-2, 2); std::string idr = result.substr(result.length()-2, 2); if (idf == "nt") i = 0; else if (idf == "ol") i = 1; else if (idf == "al") i = 2; else i = 3; offset += util::isSType(first) ? 32 * i : 32 * i + 128; if (ids == "nt") i = 0; else if (ids == "ol") i = 1; else if (ids == "al") i = 2; else i = 3; offset += util::isSType(second) ? 4 * i : 4 * i + 16; if (idr == "nt") i = 0; else if (idr == "ol") i = 1; else if (idr == "al") i = 2; else i = 3; offset += i; return offset; } template int map2FunSS(Word* args, Word& result, int message, Word& local, Supplier s) { result = qp->ResultStorage(s); S1* s1 = static_cast(args[0].addr); S2* s2 = static_cast(args[1].addr); Address function = args[2].addr; Result* r = static_cast(result.addr); if(!s1->isDefined() || !s2->isDefined()){ r->setDefined(false); return 0; } grid2 g1 = s1->getGrid(); grid2 g2 = s2->getGrid(); if(!g1.matches(g2)){ r->setDefined(false); return 0; } r->clear(); double dx = (g1.getOriginX() - g2.getOriginX()) / g1.getLength(); double dy = (g1.getOriginY() - g2.getOriginY()) / g1.getLength(); int dc = dx + 0.5; int dr = dy + 0.5; assert(g1.getLength() == g2.getLength()); assert(AlmostEqual(dx, dc) && AlmostEqual(dy, dr)); BBox<2> bb1 = s1->bbox(); BBox<2> bb2 = s2->bbox(); BBox<2> bb = bb1.Union(bb2); r->setGrid(g1); ArgVector& arguments = *qp->Argument(function); Word fresult; // Determine the first and last region of concern. const typename S1::index_type& region_size = S1::riter_type::region_size; typename S1::index_type from = g1.getIndex(bb.MinD(0), bb.MinD(1)); typename S1::index_type to = g1.getIndex(bb.MaxD(0), bb.MaxD(1)); // Iterate over regions in the first argument. for (typename S1::riter_type rit = s1->iterate_regions(from, to), re = s1->end_regions(); rit != re; ++rit) { typename S1::index_type rfrom = *rit; typename S1::index_type rto = *rit + region_size; // Iterate over the cells in the current region. for (typename S1::index_type i1 = rfrom, e = rto; i1 != e; i1.increment(rfrom, rto)) { // Calculate the corresponding cell in the second argument typename S2::index_type i2 = (int[]){i1[0] + dc, i1[1] + dr}; if (!S1::isUndefined(s1->get(i1)) || !S2::isUndefined(s2->get(i2))) { typename S1::wrapper_type w1 = S1::wrap(s1->get(i1)); typename S2::wrapper_type w2 = S2::wrap(s2->get(i2)); // Apply function arguments[0].setAddr(&w1); arguments[1].setAddr(&w2); qp->Request(function, fresult); // Set result typename Result::wrapper_type* mapped = static_cast(fresult.addr); r->set(i1, Result::unwrap(*mapped)); } } } return 0; } template int map2FunSM(Word* args, Word& result, int message, Word& local, Supplier s) { result = qp->ResultStorage(s); S* sobj = static_cast(args[0].addr); M* mobj = static_cast(args[1].addr); Address function = args[2].addr; Result* r = static_cast(result.addr); grid2 g1 = sobj->getGrid(); grid3 g2 = mobj->getGrid(); if(!g2.matches(g1)){ r->setDefined(false); return 0; } r->clear(); double dx = (g1.getOriginX() - g2.getOriginX()) / g1.getLength(); double dy = (g1.getOriginY() - g2.getOriginY()) / g1.getLength(); int dc = dx + 0.5; int dr = dy + 0.5; assert(g1.getLength() == g2.getLength()); assert(AlmostEqual(dx, dc) && AlmostEqual(dy, dr)); BBox<2> bbs = sobj->bbox(); BBox<3> bbm = mobj->bbox(); double minMax[] = {bbm.MinD(0), bbm.MaxD(0), bbm.MinD(1), bbm.MaxD(1)}; BBox<2> bbm_proj(true,minMax ); BBox<2> bb = bbs.Union(bbm_proj); r->setGrid(g2); ArgVector& arguments = *qp->Argument(function); Word fresult; // Determine the first and last region of concern. const typename M::index_type& region_size = M::riter_type::region_size; typename M::index_type from = g2.getIndex( bb.MinD(0), bb.MinD(1), bb.MinD(2)); typename M::index_type to = g2.getIndex( bb.MaxD(0), bb.MaxD(1), bb.MaxD(2)); // Iterate over regions in the moving spatial argument. for (typename M::riter_type rit = mobj->iterate_regions(from, to), re = mobj->end_regions(); rit != re; ++rit) { typename M::index_type rfrom = *rit; typename M::index_type rto = *rit + region_size; // Iterate over the cells in the current region. for (typename M::index_type i1 = rfrom, e = rto; i1 != e; i1.increment(rfrom, rto)) { // Calculate the corresponding cell in the second argument typename S::index_type i2 = (int[]){i1[0] + dc, i1[1] + dr}; if (!M::isUndefined(mobj->get(i1)) || !S::isUndefined(sobj->get(i2))) { typename S::wrapper_type w1 = S::wrap(sobj->get(i2)); typename M::wrapper_type w2 = M::wrap(mobj->get(i1)); // Apply function arguments[0].setAddr(&w1); arguments[1].setAddr(&w2); qp->Request(function, fresult); // Set result typename Result::wrapper_type& mapped = *static_cast(result.addr); r->set(i1, Result::unwrap(mapped)); } } } return 0; } template int map2FunMS(Word* args, Word& result, int message, Word& local, Supplier s) { result = qp->ResultStorage(s); M* mobj = static_cast(args[0].addr); S* sobj = static_cast(args[1].addr); Address function = args[2].addr; Result* r = static_cast(result.addr); grid3 g1 = mobj->getGrid(); grid2 g2 = sobj->getGrid(); if(!g1.matches(g2)){ r->setDefined(false); return 0; } r->clear(); double dx = (g1.getOriginX() - g2.getOriginX()) / g1.getLength(); double dy = (g1.getOriginY() - g2.getOriginY()) / g1.getLength(); int dc = dx + 0.5; int dr = dy + 0.5; assert(g1.getLength() == g2.getLength()); assert(AlmostEqual(dx, dc) && AlmostEqual(dy, dr)); BBox<3> bbm = mobj->bbox(); BBox<2> bbs = sobj->bbox(); double minMax[] = {bbm.MinD(0), bbm.MaxD(0), bbm.MinD(1), bbm.MaxD(1)}; BBox<2> bbm_proj(true,minMax ); BBox<2> bb = bbs.Union(bbm_proj); r->setGrid(g1); ArgVector& arguments = *qp->Argument(function); Word fresult; // Determine the first and last region of concern. const typename M::index_type& region_size = M::riter_type::region_size; typename M::index_type from = g1.getIndex( bb.MinD(0), bb.MinD(1), bb.MinD(2)); typename M::index_type to = g1.getIndex( bb.MaxD(0), bb.MaxD(1), bb.MaxD(2)); // Iterate over regions in the moving spatial argument. for (typename M::riter_type rit = mobj->iterate_regions(from, to), re = mobj->end_regions(); rit != re; ++rit) { typename M::index_type rfrom = *rit; typename M::index_type rto = *rit + region_size; // Iterate over the cells in the current region. for (typename M::index_type i1 = rfrom, e = rto; i1 != e; i1.increment(rfrom, rto)) { // Calculate the corresponding cell in the second argument typename S::index_type i2 = (int[]){i1[0] + dc, i1[1] + dr}; if (!M::isUndefined(mobj->get(i1)) || !S::isUndefined(sobj->get(i2))) { typename M::wrapper_type w1 = M::wrap(mobj->get(i1)); typename S::wrapper_type w2 = S::wrap(sobj->get(i2)); // Apply function arguments[0].setAddr(&w1); arguments[1].setAddr(&w2); qp->Request(function, fresult); // Set result typename Result::wrapper_type& mapped = *static_cast(result.addr); r->set(i1, Result::unwrap(mapped)); } } } return 0; } template int map2FunMM(Word* args, Word& result, int message, Word& local, Supplier s) { result = qp->ResultStorage(s); M1* m1 = static_cast(args[0].addr); M2* m2 = static_cast(args[1].addr); Address function = args[2].addr; Result* r = static_cast(result.addr); grid3 g1 = m1->getGrid(); grid3 g2 = m2->getGrid(); if(!g1.matches(g2)){ r->setDefined(false); return 0; } r->clear(); double dx = (g1.getOriginX() - g2.getOriginX()) / g1.getLength(); double dy = (g1.getOriginY() - g2.getOriginY()) / g1.getLength(); int dc = dx + 0.5; int dr = dy + 0.5; assert(g1.getLength() == g2.getLength()); assert(AlmostEqual(dx, dc) && AlmostEqual(dy, dr)); // If one value is undefined, the mapped value is undefined. This means we // only need to consider the intersection of the two bounding boxes. BBox<3> bb1 = m1->bbox(); BBox<3> bb2 = m2->bbox(); BBox<3> bb = bb1.Union(bb2); // If the intersection of the bboxes is empty, we are done. if (bb.IsDefined()) { r->setGrid(g1); ArgVector& arguments = *qp->Argument(function); Word result; // Determine the first and last region of concern. const typename M1::index_type& region_size = M1::riter_type::region_size; typename M1::index_type from = g1.getIndex(bb.MinD(0), bb.MinD(1), bb.MinD(2)); typename M1::index_type to = g1.getIndex(bb.MaxD(0), bb.MaxD(1), bb.MaxD(2)); // Iterate over regions in the first argument. for (typename M1::riter_type rit = m1->iterate_regions(from, to), re = m1->end_regions(); rit != re; ++rit) { typename M1::index_type rfrom = *rit; typename M1::index_type rto = *rit + region_size; // Iterate over the cells in the current region. for (typename M1::index_type i1 = rfrom, e = rto; i1 != e; i1.increment(rfrom, rto)) { // Calculate the corresponding cell in the second argument and check // whether both have defined values typename M2::index_type i2 = (int[]){i1[0] + dc, i1[1] + dr, i1[2]}; if (!M1::isUndefined(m1->get(i1)) || !M2::isUndefined(m2->get(i2))) { typename M1::wrapper_type w1 = M1::wrap(m1->get(i1)); typename M2::wrapper_type w2 = M2::wrap(m2->get(i2)); arguments[0].setAddr(&w1); arguments[1].setAddr(&w2); qp->Request(function, result); typename Result::wrapper_type& mapped = *static_cast(result.addr); r->set(i1, Result::unwrap(mapped)); } } } } return 0; } ValueMapping map2Funs[] = { map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSS, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunSM, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMS, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, map2FunMM, 0 }; }