/* ---- This file is part of SECONDO. Copyright (C) 2019, University in Hagen, Faculty of Mathematics and 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 "IrregularGrid2D.h" #include "Algebras/Relation-C++/RelationAlgebra.h" #include "Algebras/Collection/IntSet.h" #include #include Cell::Cell() { cellId = -1; valFrom = -1; valTo = -1; nbrPoints = -1; } void Cell::setCellId(int cell_id) { this->cellId = cell_id; } int Cell::getCellId() { return cellId; } void Cell::setValFrom(double val_from) { valFrom = val_from; } double Cell::getValFrom() { return valFrom; } void Cell::setValTo(double val_to) { valTo = val_to; } double Cell::getValTo() { return valTo; } int Cell::getNbrOfPoints() { return nbrPoints; } void Cell::setNbrOfPoints(int nbr_points) { nbrPoints = nbr_points; } Cell::~Cell() { } VCell::VCell() { } std::vector& VCell::getRow() { return row; } VCell::~VCell() { } HCell::HCell() { upper = nullptr; } void HCell::setUpper(HCell* upper_) { upper = upper_; } HCell* HCell::getUpper() { return upper; } HCell::~HCell() { } IrregularGrid2D::IrregularGrid2D() { boundingBox = nullptr; rowCount = 0; cellCount = 0; } IrregularGrid2D::IrregularGrid2D(const IrregularGrid2D& g) { boundingBox = g.boundingBox; rowCount = g.rowCount; cellCount = g.cellCount; } IrregularGrid2D::IrregularGrid2D(Rectangle<2> &bounding_box, int row_count, int cell_count) { boundingBox = &bounding_box; rowCount = row_count; cellCount = cell_count; } void IrregularGrid2D::Set(Stream> rStream, Rectangle<2> &bounding_box, int row_count, int cell_count) { boundingBox = &bounding_box; rowCount = row_count; cellCount = cell_count; createIrgrid2D(rStream); } void IrregularGrid2D::SetVector(std::vector>* rVector, Rectangle<2> &bounding_box, int row_count, int cell_count) { boundingBox = &bounding_box; rowCount = row_count; cellCount = cell_count; createIrgrid2DVector(rVector); } std::vector IrregularGrid2D::getCellInfoVector(IrregularGrid2D *in_irgrid2d) { std::vector cell_info_vect {}; std::vector* col = &in_irgrid2d->getColumnVector(); for(size_t colIdx = 0; colIdx < col->size(); colIdx++) { VCell* vcell = &col->at(colIdx); double vf = vcell->getValFrom(); double vt = vcell->getValTo(); std::vector* row_vect = &vcell->getRow(); for(size_t cellIdx = 0; cellIdx < row_vect->size(); cellIdx++) { HCell* cell = &row_vect->at(cellIdx); int cid = cell->getCellId(); int np = cell->getNbrOfPoints(); double hf = cell->getValFrom(); double ht = cell->getValTo(); CellInfo* ci = new CellInfo(cid, np, hf, ht, vf, vt); cell_info_vect.push_back(ci); } } return cell_info_vect; } void IrregularGrid2D::createIrgrid2D(Stream> rStream) { // sort input points by y-coordinates processInput(rStream); // create irregular grid 2d by point density buildGrid(); } void IrregularGrid2D::createIrgrid2DVector(std::vector>* rVector) { // sort input points by y-coordinates processInputVector(rVector); // create irregular grid 2d by point density buildGrid(); } bool pointComparisonX(RPoint p1, RPoint p2) { return p1.x < p2.x; } void IrregularGrid2D::buildGrid() { // create grid structure double bb_top = boundingBox->getMaxY(); double bb_bot = boundingBox->getMinY(); double colOffset = (bb_top - bb_bot) / rowCount; double bb_right = boundingBox->getMaxX(); double bb_left = boundingBox->getMinX(); double hOffset = (bb_right - bb_left) / cellCount; double col_boundary_val = bb_bot; int hcell_id = 1; for(int c = 0; c < rowCount; c++) { VCell vcell = VCell(); vcell.setValFrom(col_boundary_val); col_boundary_val += colOffset; vcell.setValTo(col_boundary_val); double cell_boundary_val = bb_left; for(int r = 0; r < cellCount; r++) { HCell hcell = HCell(); hcell.setValFrom(cell_boundary_val); cell_boundary_val += hOffset; hcell.setValTo(cell_boundary_val); hcell.cellId = hcell_id; hcell_id++; // will be determined later hcell.upper = nullptr; vcell.getRow().push_back(hcell); } columnVector.push_back(vcell); } // adjust boundaries by point distribution int nbrOfPoints = points.size(); int pointsPerRow = nbrOfPoints / rowCount; std::vector tmp_row_points {}; int pointIdx = 0; int point_counter = 0; for(int colIdx = 0; colIdx < rowCount; colIdx++) { for(size_t dp_idx = pointIdx; dp_idx < points.size(); dp_idx++) { RPoint rp = points[dp_idx]; tmp_row_points.push_back(rp); point_counter ++; if ((point_counter == pointsPerRow) || (dp_idx == points.size()-1)) { // adjust y-boundaries if (colIdx > 0) { getColumnVector()[colIdx].setValFrom( getColumnVector()[colIdx-1].getValTo()); } double new_val_to_y; if (dp_idx == points.size()-1) { new_val_to_y = bb_top; } else { new_val_to_y = rp.y; } getColumnVector()[colIdx].setValTo(new_val_to_y); getColumnVector()[colIdx].setNbrOfPoints(point_counter); point_counter = 0; // adjust x-boundaries std::sort(tmp_row_points.begin(), tmp_row_points.end(), pointComparisonX); std::vector c_row = columnVector[colIdx].getRow(); int pointsPerCell = tmp_row_points.size() / cellCount; int tmpPointIdx = 0; for(int h = 0; h < cellCount; h++) { std::vector* hcel_vec_ptr = &columnVector[colIdx].getRow(); for(size_t tmp_rp_idx = tmpPointIdx; tmp_rp_idx < tmp_row_points.size(); tmp_rp_idx++) { RPoint rp_t = tmp_row_points[tmp_rp_idx]; point_counter ++; if((point_counter == pointsPerCell) || (tmp_rp_idx == tmp_row_points.size()-1) /* || (h == cellCount-1 ) */) { if (h > 0) { hcel_vec_ptr->at(h).setValFrom( hcel_vec_ptr->at(h-1).getValTo()); } double new_val_to_x; if ((tmp_rp_idx == tmp_row_points.size()-1) || (h == cellCount-1)) { new_val_to_x = bb_right; } else { new_val_to_x = rp_t.x; } hcel_vec_ptr->at(h).setValTo(new_val_to_x); tmpPointIdx = tmp_rp_idx + 1; hcel_vec_ptr->at(h).setNbrOfPoints(point_counter); // Smoothing in case of odd number of points per cell if (h+1 < cellCount) { pointsPerCell = (tmp_row_points.size()-tmpPointIdx) / (cellCount-1-h); } point_counter = 0; // next cell break; } } } tmp_row_points.clear(); pointIdx = dp_idx + 1; // Smoothing in case of odd number of points per row if (colIdx+1 < rowCount) { pointsPerRow = (points.size()-pointIdx) / (rowCount-1-colIdx); } point_counter = 0; // one row up break; } } } // clear aux. vectors if (points.size() > 0) { points.clear(); } if (tmp_row_points.size() > 0) { tmp_row_points.clear(); } // update cell pointer if (rowCount > 1 && cellCount > 0) { for(int c = 0; c < rowCount-1; c++) { std::vector* row_lower = &getColumnVector().at(c).getRow(); std::vector* row_upper = &getColumnVector().at(c+1).getRow(); int pointToCellIdx = 0; for(int h = 0; h < cellCount; h++) { HCell* lower_cell_ptr = &row_lower->at(h); HCell* upper_cell_ptr = &row_upper->at(pointToCellIdx); if (lower_cell_ptr->getValFrom() <= upper_cell_ptr->getValTo()) { lower_cell_ptr->setUpper(upper_cell_ptr); } else { HCell* next_upper_cell_ptr; do { pointToCellIdx ++; next_upper_cell_ptr = &row_upper->at(pointToCellIdx); lower_cell_ptr->setUpper(next_upper_cell_ptr); } while (lower_cell_ptr->getValFrom() >= next_upper_cell_ptr->getValTo()); } } } } const double min[] { boundingBox->getMinX(), boundingBox->getMinY() }; const double max[] { boundingBox->getMaxX(), boundingBox->getMaxY() }; box.Set(true, min, max); } bool pointComparisonY(RPoint p1, RPoint p2) { return p1.y < p2.y; } RPoint getRectangleCentre(Rectangle<2>* r) { double a = (r->getMaxY() - r->getMinY()) / (double)2; double b = (r->getMaxX() - r->getMinX()) / (double)2; RPoint r_c { (r->getMinX())+b, (r->getMinY())+a }; return r_c; } // check if a rectangle is inside the irgrid2d bounding box bool insideBoundingBox(Rectangle<2>* bbox, Rectangle<2>* r) { double le = bbox->getMinX(); double ri = bbox->getMaxX(); double bo = bbox->getMinY(); double to = bbox->getMaxY(); if (r->getMinX() >= le && r->getMaxX() <= ri && r->getMinY() >= bo && r->getMaxY() <=to) { return true; } return false; } void IrregularGrid2D::processInput(Stream> rStream) { rStream.open(); Rectangle<2>* next = rStream.request(); while(next != 0){ if (!insideBoundingBox(boundingBox, next)) { // rectangle (partially) outside the bounding box is discarded next = rStream.request(); continue; } points.push_back(getRectangleCentre(next)); next = rStream.request(); } rStream.close(); // sort point vector by y-coordinates std::sort(points.begin(), points.end(), pointComparisonY); } void IrregularGrid2D::processInputVector(std::vector>* rVector) { for (Rectangle<2> bbox : *rVector) { if (!insideBoundingBox(boundingBox, &bbox)) { // rectangle (partially) outside the bounding box is discarded continue; } points.push_back(getRectangleCentre(&bbox)); } // sort point vector by y-coordinates std::sort(points.begin(), points.end(), pointComparisonY); } Rectangle<2> * IrregularGrid2D::getBoundingBox() { return boundingBox; } int IrregularGrid2D::getRowCount() { return rowCount; } int IrregularGrid2D::getCellCount() { return cellCount; } void IrregularGrid2D::setColumnVector(std::vector column_vect) { this->columnVector = column_vect; } std::vector& IrregularGrid2D::getColumnVector() { return this->columnVector; } IrregularGrid2D::~IrregularGrid2D() {} // Type Constructor irgrid2d ListExpr IrregularGrid2D::PropertyIrGrid2D() { ListExpr desclst = nl->TextAtom(); nl->AppendText(desclst, "A bounding box followed by list of rows.\n" "A row consists of two-element list ( ) " "followed by list of cells.\n" "A cell consists of four-element list\n( )."); ListExpr formatlst = nl->TextAtom(); nl->AppendText(formatlst, "((0.0 2.0 0.0 2.0)(\n(0.0 0.45)((0.0 0.4 1 3)(0.4 2.0 2 4))\n" "(0.45 2.0)((0.0 0.3 3 -1)(0.3 2.0 4 -1))))"); return (nl->TwoElemList( nl->FourElemList(nl->StringAtom("Signature"), nl->StringAtom("Example Type List"), nl->StringAtom("List Rep"), nl->StringAtom("Example List")), nl->FourElemList(nl->StringAtom("-> DATA"), nl->StringAtom(IrregularGrid2D::BasicType()), desclst, formatlst))); } // Out function ListExpr IrregularGrid2D::OutIrGrid2D( ListExpr typeInfo, Word value ) { IrregularGrid2D* irgrid2d = static_cast( value.addr ); if (irgrid2d != nullptr) { Rectangle<2> * b_box = irgrid2d->getBoundingBox(); ListExpr bboxLstExpr = nl->FourElemList( nl->RealAtom(b_box->getMinX()), nl->RealAtom(b_box->getMaxX()), nl->RealAtom(b_box->getMinY()), nl->RealAtom(b_box->getMaxY())); std::vector* col = &irgrid2d->getColumnVector(); ListExpr rowLstExpr = nl->Empty(); ListExpr lastRowLstExpr; if (col->size() > 0) { for(size_t colIdx = 0; colIdx < col->size(); colIdx++) { VCell* vcell = &col->at(colIdx); if (colIdx > 0) { lastRowLstExpr = nl->Append(lastRowLstExpr, nl->TwoElemList(nl->RealAtom(vcell->getValFrom()), nl->RealAtom(vcell->getValTo()))); } else { rowLstExpr = nl->OneElemList( nl->TwoElemList(nl->RealAtom(vcell->getValFrom()), nl->RealAtom(vcell->getValTo()))); lastRowLstExpr = rowLstExpr; } std::vector* row_vect = &col->at(colIdx).getRow(); if (row_vect->size() > 0) { ListExpr cellLstExpr; ListExpr lastCellLstExpr; for(size_t rowIdx = 0; rowIdx < row_vect->size(); rowIdx++) { HCell* row_cell = &row_vect->at(rowIdx); if (rowIdx > 0) { lastCellLstExpr = nl->Append(lastCellLstExpr, nl->FourElemList(nl->RealAtom(row_cell->getValFrom()), nl->RealAtom(row_cell->getValTo()), nl->IntAtom(row_cell->getCellId()), nl->IntAtom((row_cell->getUpper() != nullptr ? row_cell->getUpper()->getCellId() : -1)))); } else { cellLstExpr = nl->OneElemList(nl->FourElemList (nl->RealAtom(row_cell->getValFrom()), nl->RealAtom(row_cell->getValTo()), nl->IntAtom(row_cell->getCellId()), nl->IntAtom((row_cell->getUpper() != nullptr ? row_cell->getUpper()->getCellId() : -1)))); lastCellLstExpr = cellLstExpr; } } lastRowLstExpr = nl->Append(lastRowLstExpr, cellLstExpr); } } } ListExpr irgrid2dLstExpr = nl->TwoElemList(bboxLstExpr, rowLstExpr); return irgrid2dLstExpr; } else { return (nl->SymbolAtom(Symbol::UNDEFINED())); } } // In function Word IrregularGrid2D::InIrGrid2D( const ListExpr typeInfo, const ListExpr instance, const int errorPos, ListExpr& errorInfo, bool& correct ) { Word w = SetWord(Address(0)); try { Rectangle<2>* bbox; ListExpr bboxLstExpr; ListExpr rowLstExpr; if ( nl->ListLength( instance ) == 2 ) { bboxLstExpr = nl->First(instance); rowLstExpr = nl->Second(instance); } else { throw 1; } // fetch bounding box information from input if (nl->ListLength( bboxLstExpr ) == 4 ) { ListExpr left = nl->First(bboxLstExpr); ListExpr right = nl->Second(bboxLstExpr); ListExpr bottom = nl->Third(bboxLstExpr); ListExpr top = nl->Fourth(bboxLstExpr); if ( nl->IsAtom(left) && nl->AtomType(left) == RealType && nl->IsAtom(right) && nl->AtomType(right) == RealType && nl->IsAtom(bottom) && nl->AtomType(bottom) == RealType && nl->IsAtom(top) && nl->AtomType(top) == RealType) { double min[2], max[2]; min[0] = nl->RealValue(left); min[1] = nl->RealValue(bottom); max[0] = nl->RealValue(right); max[1] = nl->RealValue(top); bbox = new Rectangle<2>(true, min, max); } else { throw 3; } } else { throw 2; } // fetch row information from input // temporary support structures std::map cellRef; std::map cellIds; std::vector column_vec {}; int row_cnt = 0; int cell_cnt = 0; if (nl->ListLength( rowLstExpr ) > 1 ) { VCell vc; VCell* vc_ptr; while(!nl->IsEmpty(rowLstExpr)) { ListExpr lstElem = nl->First(rowLstExpr); if ((nl->ListLength(lstElem)) == 2 && (nl->IsAtom(nl->First(lstElem)) && nl->IsAtom(nl->Second(lstElem))) ) { // a two-element double list initiates a new row row_cnt ++; ListExpr fLst = nl->First(lstElem); ListExpr tLst = nl->Second(lstElem); if ( nl->AtomType(fLst) == RealType && nl->AtomType(tLst) == RealType) { vc = VCell(); vc.setValFrom(nl->RealValue(fLst)); vc.setValTo(nl->RealValue(tLst)); column_vec.push_back(vc); vc_ptr = &(column_vec.back()); } } else { ListExpr rowLstExpr = lstElem; // row while(!nl->IsEmpty(rowLstExpr)) { // cell information ListExpr cellLstExpr = nl->First(rowLstExpr); if (nl->ListLength( cellLstExpr ) == 4) { // a four-element list initiates a new cell ListExpr cv1Lst = nl->First(cellLstExpr); ListExpr cv2Lst = nl->Second(cellLstExpr); ListExpr cv3Lst = nl->Third(cellLstExpr); ListExpr cv4Lst = nl->Fourth(cellLstExpr); if ( nl->IsAtom(cv1Lst) && nl->AtomType(cv1Lst) == RealType && nl->IsAtom(cv2Lst) && nl->AtomType(cv2Lst) == RealType && nl->IsAtom(cv3Lst) && nl->AtomType(cv3Lst) == IntType && nl->IsAtom(cv4Lst) && nl->AtomType(cv4Lst) == IntType) { HCell* hc = new HCell(); hc->setValFrom(nl->RealValue(cv1Lst)); hc->setValTo(nl->RealValue(cv2Lst)); hc->setCellId(nl->IntValue(cv3Lst)); // will be determined later hc->setUpper(nullptr); vc_ptr->getRow().push_back(*hc); int cellRefId = nl->IntValue(cv4Lst); if (cellRefId != -1) { cellRef.insert(std::make_pair( ((int)nl->IntValue(cv3Lst)), cellRefId)); } cellIds.insert(std::make_pair( ((int)nl->IntValue(cv3Lst)), hc)); } else { throw 5; } } rowLstExpr = nl->Rest(rowLstExpr); } } // determine number of cells (one-time) if (row_cnt > 0 && cell_cnt == 0) { cell_cnt = vc_ptr->getRow().size(); } rowLstExpr = nl->Rest(rowLstExpr); } } else { throw 4; } // update pointer if (row_cnt > 0 && cell_cnt > 0) { for(int colIdx = 0; colIdx < row_cnt-1; colIdx++) { VCell* vcell = &column_vec.at(colIdx); std::vector* row_vect = &vcell->getRow(); for(int cIdx = 0; cIdx < cell_cnt; cIdx++) { HCell* hcell = &(*row_vect).at(cIdx); if(cellRef.find(hcell->getCellId()) != cellRef.end()) { int cell_ref = cellRef.at(hcell->getCellId()); if(cellIds.find(cell_ref) != cellIds.end()) { hcell->setUpper(cellIds.at(cell_ref)); } } } } } correct = true; IrregularGrid2D* irgrid = new IrregularGrid2D(*bbox, row_cnt, cell_cnt); irgrid->setColumnVector(column_vec); irgrid->box = *bbox; w.addr = irgrid; return w; } catch (int e) { correct = false; cmsg.inFunError("Expecting a irgrid2d list representation. Exit code " + std::to_string(e)); return w; } } bool IrregularGrid2D::OpenIrGrid2D(SmiRecord& valueRecord, size_t& offset, const ListExpr typeInfo, Word& value) { size_t size = sizeof(int); size_t sizeD = sizeof(double); int xr = 0, yb = 0; size_t cols = 0, rows = 0; double vf = 0.0, vt = 0.0; //column values double rvf = 0.0, rvt = 0.0; // row values int rid = 0, cellu = 0; double xmin=0.0, xmax=0.0, ymin=0.0, ymax=0.0; std::map cellRef; std::map cellIds; std::vector column_vec {}; VCell vc; VCell* vc_ptr; bool ok = true; ok = ok && valueRecord.Read( &xmin, sizeD, offset ); offset += sizeD; ok = ok && valueRecord.Read( &xmax, sizeD, offset ); offset += sizeD; ok = ok && valueRecord.Read( &ymin, sizeD, offset ); offset += sizeD; ok = ok && valueRecord.Read( &ymax, sizeD, offset ); offset += sizeD; ok = ok && valueRecord.Read( &xr, size, offset ); offset += size; ok = ok && valueRecord.Read( &yb, size, offset ); offset += size; // colsize ok = ok && valueRecord.Read( &cols, sizeof(size_t), offset ); offset += sizeof(size_t); for(size_t i = 0; i < cols; i++) { vc = VCell(); ok = ok && valueRecord.Read( &vf, sizeD, offset ); offset += sizeD; ok = ok && valueRecord.Read( &vt, sizeD, offset ); offset += sizeD; vc.setValFrom(vf); vc.setValTo(vt); column_vec.push_back(vc); vc_ptr = &(column_vec.back()); //rowsize ok = ok && valueRecord.Read( &rows, sizeof(size_t), offset ); offset += sizeof(size_t); for(size_t j = 0; j < rows; j++) { HCell* hc = new HCell(); ok = ok && valueRecord.Read( &rvf, sizeD, offset ); offset += sizeD; ok = ok && valueRecord.Read( &rvt, sizeD, offset ); offset += sizeD; ok = ok && valueRecord.Read( &rid, size, offset ); offset += size; ok = ok && valueRecord.Read( &cellu, size, offset ); offset += size; hc->setValFrom(rvf); hc->setValTo(rvt); hc->setCellId(rid); hc->setUpper(nullptr); vc_ptr->getRow().push_back(*hc); int cellRefId = cellu; if (cellRefId != -1) { cellRef.insert(std::make_pair( rid, cellRefId)); } cellIds.insert(std::make_pair( rid, hc)); } } // update pointer if (xr > 0 && yb > 0) { for(int colIdx = 0; colIdx < xr; colIdx++) { VCell* vcell = &column_vec.at(colIdx); std::vector* row_vect = &vcell->getRow(); for(int cIdx = 0; cIdx < yb; cIdx++) { HCell* hcell = &(*row_vect).at(cIdx); if(cellRef.find(hcell->getCellId()) != cellRef.end()) { int cell_ref = cellRef.at(hcell->getCellId()); if(cellIds.find(cell_ref) != cellIds.end()) { hcell->setUpper(cellIds.at(cell_ref)); } } } } } const double min[] { xmin, ymin }; const double max[] { xmax, ymax }; Rectangle<2> *bbox = new Rectangle<2>(true, min, max); IrregularGrid2D* irgrid = new IrregularGrid2D(*bbox, xr, yb); irgrid->setColumnVector(column_vec); irgrid->box = *bbox; value.addr = irgrid; return ok; } bool IrregularGrid2D::SaveIrGrid2D(SmiRecord& valueRecord, size_t& offset, const ListExpr typeInfo, Word& value) { IrregularGrid2D* r = static_cast( value.addr ); size_t size = sizeof(int); size_t sizeD = sizeof(double); bool ok = true; double minx = r->box.getMinX();//->getMaxX(); double maxx = r->box.getMaxX();//->getMaxX(); double miny = r->box.getMinY();// b_box->getMinY(); double maxy = r->box.getMaxY(); // b_box->getMaxY(); ok = ok && valueRecord.Write(&minx, sizeD, offset ); offset += sizeD; ok = ok && valueRecord.Write(&maxx, sizeD, offset ); offset += sizeD; ok = ok && valueRecord.Write(&miny, sizeD, offset ); offset += sizeD; ok = ok && valueRecord.Write(&maxy, sizeD, offset ); offset += sizeD; ok = ok && valueRecord.Write(&r->rowCount, size, offset ); offset += size; ok = ok && valueRecord.Write(&r->cellCount, size, offset ); offset += size; std::vector* col = &r->getColumnVector(); size_t cols = col->size(); if (col->size() > 0) { ok = ok && valueRecord.Write(&cols, sizeof(size_t), offset ); offset += sizeof(size_t); for(size_t colIdx = 0; colIdx < col->size(); colIdx++) { VCell* vcell = &col->at(colIdx); double vf = vcell->getValFrom(); double vt = vcell->getValTo(); ok = ok && valueRecord.Write(&vf, sizeD, offset ); offset += sizeD; ok = ok && valueRecord.Write(&vt, sizeD, offset ); offset += sizeD; std::vector* row_vect = &col->at(colIdx).getRow(); size_t rows = row_vect->size(); if (row_vect->size() > 0) { ok = ok && valueRecord.Write(&rows, sizeof(size_t), offset ); offset += sizeof(size_t); for(size_t rowIdx = 0; rowIdx < row_vect->size(); rowIdx++) { HCell* row_cell = &row_vect->at(rowIdx); double rvf = row_cell->getValFrom(); double rvt = row_cell->getValTo(); int ri = row_cell->getCellId(); int ru = row_cell->getUpper() != nullptr ? row_cell->getUpper()->getCellId() : -1; ok = ok && valueRecord.Write(&rvf, sizeD, offset ); offset += sizeD; ok = ok && valueRecord.Write(&rvt, sizeD, offset ); offset += sizeD; ok = ok && valueRecord.Write(&ri, size, offset ); offset += size; ok = ok && valueRecord.Write(&ru, size, offset ); offset += size; } } } } return ok; } // This function checks whether the type constructor is applied correctly. bool IrregularGrid2D::KindCheckIrGrid2D( ListExpr type, ListExpr& errorInfo ) { return (nl->IsEqual( type, IrregularGrid2D::BasicType() )); } // Close -function void IrregularGrid2D::CloseIrGrid2D( const ListExpr typeInfo, Word& w ) { delete (IrregularGrid2D *)w.addr; w.addr = 0; } // Clone function Word IrregularGrid2D::CloneIrGrid2D( const ListExpr typeInfo, const Word& w ) { IrregularGrid2D *g = new IrregularGrid2D( *((IrregularGrid2D *)w.addr) ); return SetWord( g ); } // Create function Word IrregularGrid2D::CreateIrGrid2D( const ListExpr typeInfo ) { return SetWord( new IrregularGrid2D() ); } // Delete function void IrregularGrid2D::DeleteIrGrid2D( const ListExpr typeInfo, Word& w ) { delete (IrregularGrid2D *)w.addr; w.addr = 0; } // SizeOf function int IrregularGrid2D::SizeOfIrGrid2D() { return sizeof(IrregularGrid2D); } /* Type mapping function ~IrGrid2dFeedTypeMap~ It is used for the ~feed~ operator. */ ListExpr IrregularGrid2D::IrGrid2dFeedTypeMap( ListExpr args ) { if(nl->HasLength(args, 1)) { ListExpr first = nl->First(args); if (IrregularGrid2D::checkType(first)) { ListExpr resAttrList = nl->ThreeElemList( nl->TwoElemList( nl->SymbolAtom("Id"), nl->SymbolAtom(CcInt::BasicType())), nl->TwoElemList( nl->SymbolAtom("Count"), nl->SymbolAtom(CcInt::BasicType())), nl->TwoElemList( nl->SymbolAtom("Cell"), nl->SymbolAtom(Rectangle<2>::BasicType()))); return nl->TwoElemList(listutils::basicSymbol>(), nl->TwoElemList( listutils::basicSymbol(), resAttrList)); } } const std::string errMsg = "The following argument is expected:" " irgrid2d"; return listutils::typeError(errMsg); } // for value mapping function of ~feed~ operator struct IrGridTupleInfo { std::vector cell_info_vect; unsigned int currentTupleIdx; ListExpr numTupleTypeList; void init(IrregularGrid2D *irgrid2d_in) { currentTupleIdx = 0; cell_info_vect = IrregularGrid2D::getCellInfoVector(irgrid2d_in); ListExpr tupleTypeLst = nl->TwoElemList( nl->SymbolAtom(Tuple::BasicType()), nl->ThreeElemList( nl->TwoElemList( nl->SymbolAtom("Id"), nl->SymbolAtom(CcInt::BasicType())), nl->TwoElemList( nl->SymbolAtom("Count"), nl->SymbolAtom(CcInt::BasicType())), nl->TwoElemList( nl->SymbolAtom("Cell"), nl->SymbolAtom(Rectangle<2>::BasicType())))); SecondoCatalog* sc = SecondoSystem::GetCatalog(); numTupleTypeList = sc->NumericType(tupleTypeLst); } TupleType* getTupleType() { TupleType *tupleType = new TupleType(numTupleTypeList); return tupleType; } Tuple* getNext(TupleType *ttype) { if (currentTupleIdx < cell_info_vect.size()) { CellInfo * cell_info = cell_info_vect.at(currentTupleIdx); int tp_p1 = cell_info->cellId; int tp_p2 = cell_info->statNbrOfPoints; Rectangle<2> tp_p3 = *cell_info->cell; Tuple *tuple = new Tuple(ttype); tuple->PutAttribute(0, new CcInt(true, tp_p1)); tuple->PutAttribute(1, new CcInt(true, tp_p2)); tuple->PutAttribute(2, new Rectangle<2> (tp_p3)); currentTupleIdx++; return tuple; } else { return nullptr; } } }; /* Value mapping function of operator ~feed~ */ int IrregularGrid2D::IrGrid2dValueMapFeed( Word* args, Word& result, int message, Word& local, Supplier s ) { IrregularGrid2D *input_irgrid2d_ptr = static_cast( args[0].addr ); IrGridTupleInfo* tp_info = static_cast(local.addr); TupleType* tupleType = nullptr; Tuple* tuple = nullptr; switch (message) { case OPEN: { tp_info = new IrGridTupleInfo(); tp_info->init(input_irgrid2d_ptr); local.addr = tp_info; return 0; } case REQUEST: { if (local.addr) { tp_info = ((IrGridTupleInfo*)local.addr); tupleType = tp_info->getTupleType(); } else { return CANCEL; } // get next tuple tuple = tp_info->getNext(tupleType); if (tuple != nullptr) { result.addr = tuple; return YIELD; } else { result.addr = 0; return CANCEL; } } case CLOSE: { if (local.addr) { tp_info = ((IrGridTupleInfo*)local.addr); delete tp_info; local.addr = 0; } return 0; } } return -1; } /* Type mapping function ~IrGrid2dCellnosTypeMap~ It is used for the ~cellnos\_ir~ operator. */ ListExpr IrregularGrid2D::IrGrid2dCellnosTypeMap( ListExpr args ) { if(nl->HasLength(args, 2)) { ListExpr first = nl->First(args); ListExpr second = nl->Second(args); if (IrregularGrid2D::checkType(first) && Rectangle<2>::checkType(second)) { return nl->SymbolAtom(collection::IntSet::BasicType()); } } const std::string errMsg = "The following two arguments are expected:" " irgrid2d x rect"; return listutils::typeError(errMsg); } ListExpr IrregularGrid2D::IrGrid2dSCCTypeMap( ListExpr args ) { if(nl->HasLength(args, 4)) { ListExpr first = nl->First(args); ListExpr second = nl->Second(args); ListExpr third = nl->Third(args); ListExpr fourth = nl->Fourth(args); if (IrregularGrid2D::checkType(first) && Rectangle<2>::checkType(second) && Rectangle<2>::checkType(third) && CcInt::checkType(fourth)) { return nl->SymbolAtom(CcBool::BasicType()); } } const std::string errMsg = "The following four arguments are expected:" " irgrid2d x rect x rect x int"; return listutils::typeError(errMsg); } ListExpr IrregularGrid2D::IrGrid2dGetCellTypeMap( ListExpr args ) { if(nl->HasLength(args, 2)) { ListExpr first = nl->First(args); ListExpr second = nl->Second(args); if (IrregularGrid2D::checkType(first) && CcInt::checkType(second)) { return nl->SymbolAtom(Rectangle<2>::BasicType()); } } const std::string errMsg = "The following two arguments are expected:" " irgrid2d x int"; return listutils::typeError(errMsg); } template bool InCell(C cell, double val) { return (val >= cell.getValFrom() && val < cell.getValTo()); } template bool GtCell(C cell, double val) { return (cell.getValFrom() >= val); } template int CellBS(const std::vector* c_vec, int start, int end, const double val) { if (start > end) { return -1; } const int mid = start + ((end - start) / 2); if (InCell(c_vec->at(mid), val)) { return mid; } else if (GtCell(c_vec->at(mid), val)) { return CellBS(c_vec, start, mid-1, val); } return CellBS(c_vec, mid+1, end, val); } void cellNum( IrregularGrid2D *input_irgrid2d_ptr, Rectangle<2> *search_window_ptr, std::set *cell_ids) { std::vector* col = &input_irgrid2d_ptr->getColumnVector(); double le = search_window_ptr->getMinX(); double ri = search_window_ptr->getMaxX(); double bo = search_window_ptr->getMinY(); double to = search_window_ptr->getMaxY(); int pos_bo = CellBS(col, 0, col->size(), bo); if (pos_bo != -1) { VCell vCell = col->at(pos_bo); std::vector* row = &vCell.getRow(); int pos_le = CellBS(row, 0, row->size(), le); if (pos_le != -1) { // collect ids unsigned int cellIdx = pos_le; while (cellIdx < row->size()) { HCell i = row->at(cellIdx); cell_ids->insert(i.getCellId()); if ((ri >= i.getValFrom() && ri < i.getValTo()) || (cellIdx == row->size()-1 && ri >= i.getValFrom())) { HCell fi = row->at(pos_le); if (to >= vCell.getValTo() && fi.getUpper() != nullptr) { vCell = col->at(++pos_bo); row = &vCell.getRow(); HCell * u = fi.getUpper(); int nbr_cpr = input_irgrid2d_ptr->getCellCount(); int cid_pos = (u->getCellId()) % nbr_cpr; pos_le = cid_pos == 0 ? nbr_cpr-1 : cid_pos-1; cellIdx = pos_le-1; } else if (to < vCell.getValTo() || fi.getUpper() == nullptr) { break; } } cellIdx++; } } } } /* Value mapping function of operator ~cellnos\_ir~ */ int IrregularGrid2D::IrGrid2dValueMapCellnos( Word* args, Word& result, int message, Word& local, Supplier s ) { IrregularGrid2D *input_irgrid2d_ptr = static_cast( args[0].addr ); Rectangle<2> *search_window_ptr = static_cast*>( args[1].addr ); if (input_irgrid2d_ptr != nullptr && search_window_ptr != nullptr) { std::set cell_ids; result = qp->ResultStorage(s); collection::IntSet* res = (collection::IntSet*) result.addr; Rectangle<2> * b_box = input_irgrid2d_ptr->getBoundingBox(); if (!search_window_ptr->Intersects(*b_box)) { cell_ids.insert(0); res->setTo(cell_ids); return 0; } // 'truncate' search window in case of partial cutting if (!b_box->Contains(*search_window_ptr)) { search_window_ptr = new Rectangle<2>( search_window_ptr->Intersection(*b_box)); cell_ids.insert(0); } cellNum(input_irgrid2d_ptr, search_window_ptr, &cell_ids); res->setTo(cell_ids); return 0; } return -1; } int IrregularGrid2D::IrGrid2dValueMapSCC( Word* args, Word& result, int message, Word& local, Supplier s) { IrregularGrid2D *input_irgrid2d_ptr = static_cast( args[0].addr ); Rectangle<2> *search_window_ptr = static_cast*>( args[1].addr ); Rectangle<2> *search_window_ptr2 = static_cast*>( args[2].addr ); CcInt* cellno_ptr = static_cast(args[3].addr); int cellno = cellno_ptr->GetIntval(); std::set cell_ids; std::set cell_ids2; if (input_irgrid2d_ptr != nullptr && search_window_ptr != nullptr && search_window_ptr2 != nullptr) { result = qp->ResultStorage( s ); CcBool *res = (CcBool*) result.addr; bool boolval = false; Rectangle<2> * b_box = input_irgrid2d_ptr->getBoundingBox(); if (!search_window_ptr->Intersects(*b_box) || !search_window_ptr2->Intersects(*b_box)) { return 0; } // 'truncate' search window in case of partial cutting if (!b_box->Contains(*search_window_ptr)) { search_window_ptr = new Rectangle<2>( search_window_ptr->Intersection(*b_box)); cell_ids.insert(0); } if (!b_box->Contains(*search_window_ptr2)) { search_window_ptr2 = new Rectangle<2>( search_window_ptr2->Intersection(*b_box)); cell_ids2.insert(0); } cellNum(input_irgrid2d_ptr, search_window_ptr, &cell_ids); cellNum(input_irgrid2d_ptr, search_window_ptr2, &cell_ids2); std::vector v(sizeof(cell_ids)+ sizeof(cell_ids2)); std::vector::iterator it; it=std::set_intersection (cell_ids.begin(), cell_ids.end(), cell_ids2.begin(), cell_ids2.end(), v.begin()); v.resize(it-v.begin()); if(v.empty()) { //no intersection between rectangles res->Set( true, boolval); return 0; } if(v[0] == cellno) { boolval = true; res->Set( true, boolval); return 0; } res->Set( true, boolval); return 0; } return -1; } int IrregularGrid2D::IrGrid2dValueMapGetCell(Word* args, Word& result, int message, Word& local, Supplier s) { IrregularGrid2D *input_irgrid2d_ptr = static_cast( args[0].addr ); CcInt* cellno_ptr = static_cast(args[1].addr); int cellno = cellno_ptr->GetIntval(); if (input_irgrid2d_ptr != nullptr) { result = qp->ResultStorage( s ); Rectangle<2> *res = (Rectangle<2>*) result.addr; std::vector* column = &input_irgrid2d_ptr->getColumnVector(); for(size_t i = 0; i < column->size(); i++) { VCell vCell = column->at(i); std::vector* row = &vCell.getRow(); for(size_t ii=0; ii < row->size(); ii++) { HCell hCell = row->at(ii); if(cellno == hCell.getCellId()) { double min[2], max[2]; min[0] = hCell.getValFrom(); min[1] = vCell.getValFrom(); max[0] = hCell.getValTo(); max[1] = vCell.getValTo(); res->Set(true, min, max); return 0; } } } } return -1; }