Files
secondo/Algebras/Rectangle/CellGrid2D.cpp

371 lines
10 KiB
C++
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
----
This file is part of SECONDO.
Copyright (C) 2004, 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
----
Implementation of methods for class ~CellGrid2D~
*/
#include "CellGrid.h"
CellGrid2D::CellGrid2D() {}
CellGrid2D::CellGrid2D(const int dummy):
Attribute(false),
x0(0),y0(0),wx(0),wy(0),no_cells_x(0) {}
CellGrid2D::CellGrid2D(const double &x0_, const double &y0_,
const double &wx_, const double &wy_, const int32_t &nox_)
: x0(x0_), y0(y0_), wx(wx_), wy(wy_), no_cells_x(nox_) {
// Defines a structure for a three-side bounded grid, open to one
// Y-direction. The grid is specified by an origin (x0_,x0_), a cell-width
// wx_, a cell-height wy_ and a number of cells in X-direction nox_.
// If wy_ is positive, the grid is open to +X, if it is negative, to -X.
// If wx_ is positive, the grid extends to the "left", otherwise to the
// "right" side of the origin.
// The cells are numbered sequentially starting with 1 for the cell
// nearest to the origin.
// Cell Bounderies. Point located on the bounderies between cells are
// contained by the cell with the lower cell number. Thus, the origin
// itself is never located on the grid!
SetDefined( (no_cells_x > 0)
&& !AlmostEqual(wx,0.0)
&& !AlmostEqual(wy,0.0));
}
CellGrid2D::CellGrid2D(
const double &wx_, const double &wy_, const int32_t &nox_)
: x0(0.0), y0(0.0), wx(wx_), wy(wy_), no_cells_x(nox_) {
//Defines the grid with the constant origin
SetDefined( (no_cells_x > 0)
&& !AlmostEqual(wx,0.0)
&& !AlmostEqual(wy,0.0));
}
CellGrid2D::CellGrid2D(const CellGrid2D& other):
Attribute(other.IsDefined()),
x0(other.x0), y0(other.y0), wx(other.wx),wy(other.wy),
no_cells_x(other.no_cells_x) {}
CellGrid2D& CellGrid2D::operator=(const CellGrid2D& other){
Attribute::operator=(other);
x0 = other.x0;
y0 = other.y0;
wx = other.wx;
wy = other.wy;
no_cells_x = other.no_cells_x;
return *this;
}
CellGrid2D::~CellGrid2D(){}
bool CellGrid2D::set(const double x0, const double y0,
const double wx, const double wy,
const int no_cells_x){
this->x0 = x0;
this->y0 = y0;
this->wx = wx;
this->wy = wy;
this->no_cells_x = no_cells_x;
SetDefined( (no_cells_x > 0)
&& !AlmostEqual(wx,0.0)
&& !AlmostEqual(wy,0.0));
return IsDefined();
}
bool CellGrid2D::set(const double wx, const double wy,
const int no_cells_x){
this->x0 = 0.0;
this->y0 = 0.0;
this->wx = wx;
this->wy = wy;
this->no_cells_x = no_cells_x;
SetDefined( (no_cells_x > 0)
&& !AlmostEqual(wx,0.0)
&& !AlmostEqual(wy,0.0));
return IsDefined();
}
double CellGrid2D::getX0() const{
return x0;
}
double CellGrid2D::getY0() const{
return y0;
}
double CellGrid2D::getXw() const{
return wx;
}
double CellGrid2D::getYw() const{
return wy;
}
int CellGrid2D::getNx() const{
return no_cells_x;
}
double CellGrid2D::getMaxX() const {
// returns the maximum X-coordinate lying on the grid
return wx < 0.0 ? x0 : x0 + wx * no_cells_x;
}
double CellGrid2D::getMaxY() const {
// returns the maximum Y-coordinate lying on the grid
return wy < 0.0 ? y0 : std::numeric_limits<double>::max();
}
double CellGrid2D::getMinX() const {
// returns the minimum X-coordinate lying on the grid
return wx > 0.0 ? x0 : x0 + wx * no_cells_x;
}
double CellGrid2D::getMinY() const {
// returns the minimum Y-coordinate lying on the grid
return wy > 0.0 ? y0 : std::numeric_limits<double>::min();
}
bool CellGrid2D::onGrid(const double &x, const double &y) const {
// returns true iff (x,y) is located on the grid
if(!IsDefined()) {
return false;
}
int32_t xIndex = static_cast<int32_t>(floor((x - x0) / wx));
int32_t yIndex = static_cast<int32_t>(floor((y - y0) / wy));
return ( (xIndex>=0) && (xIndex<=no_cells_x) && (yIndex>=0) );
}
int32_t CellGrid2D::getCellNo(const double &x, const double &y) const {
// returns the cell number for a given point (x,y)
// Only positive cell numbers are valid. Negative result indicates
// that (x,y) is not located on the grid.
if(!IsDefined()) {
return getInvalidCellNo();
}
int32_t xIndex = static_cast<int32_t>(floor((x - x0) / wx));
int32_t yIndex = static_cast<int32_t>(floor((y - y0) / wy));
if( (xIndex>=0) && (xIndex<=no_cells_x) && (yIndex>=0) ) {
return xIndex + yIndex * no_cells_x + 1;
} else {
return getInvalidCellNo();
}
}
int32_t CellGrid2D::getXIndex(const double &x) const {
if(IsDefined()) {
return static_cast<int32_t>(floor((x - x0) / wx));
} else {
return getInvalidCellNo();
}
}
int32_t CellGrid2D::getYIndex(const double &y) const {
if(IsDefined()) {
return static_cast<int32_t>(floor((y - y0) / wy));
} else {
return getInvalidCellNo();
}
}
Rectangle<2> CellGrid2D::getMBR() const {
// returns the grid's MBR as a 2D-rectangle
if(IsDefined()){
double min[2], max[2];
min[0] = getMinX(); min[1] = getMinY();
max[0] = getMaxX(); max[1] = getMaxY();
return Rectangle<2>( true, min, max );
} else {
return Rectangle<2>( false );
}
}
Rectangle<2> CellGrid2D::getRowMBR(const int32_t &n) const {
// returns the grid's nth row as a 2D-rectangle
// row numbering starts with 0
if( IsDefined() ){
double min_val[2], max_val[2];
double y1 = y0 + n * wy;
double y2 = y0 + (n+1) * wy;
min_val[0] = getMinX(); min_val[1] = std::min(y1,y2);
max_val[0] = getMaxX(); max_val[1] = std::max(y1,y2);
return Rectangle<2>( true, min_val, max_val );
} else {
return Rectangle<2>( false );
}
}
Rectangle<2> CellGrid2D::getColMBR(const int32_t &n) const {
// returns the grid's nth column as a 2D-rectangle
// column numbering starts with 0 and ends with no_cells_x - 1
if( IsDefined() ){
double min_val[2], max_val[2];
double x1 = x0 + n * wx;
double x2 = x0 + (n+1) * wx;
min_val[0] = std::min(x1,x2); min_val[1] = getMinY();
max_val[0] = std::max(x1,x2); max_val[1] = getMaxY();
return Rectangle<2>( true, min_val, max_val );
} else {
return Rectangle<2>( false );
}
}
bool CellGrid2D::isValidCellNo(const int32_t &n) const {
// returns true iff n is a valid grid cell number
return IsDefined() && (n>0);
}
int32_t CellGrid2D::getInvalidCellNo() const {
// returns an invalid cell number
return -666;
}
std::ostream& CellGrid2D::Print( std::ostream &os ) const {
if( !IsDefined() )
{
return os << "(CellGrid2D: undefined)";
}
os << "(CellGrid2D: defined, "
<< " origin: (" << x0 << "," << y0 << "), "
<< " cellwidths: " << wx << " x " << wy << " (X x Y), "
<< " cells along X-axis: " << no_cells_x
<< ")" << endl;
return os;
}
size_t CellGrid2D::Sizeof() const{
return sizeof(*this);
}
int CellGrid2D::Compare(const Attribute* other) const{
const CellGrid2D* g = static_cast<const CellGrid2D*> (other);
if(!IsDefined()){
return g->IsDefined()?-1:0;
}
if(!g->IsDefined()){
return 1;
}
// both are defined
if(!AlmostEqual(x0,g->x0)){
return x0<g->x0?-1:1;
}
if(!AlmostEqual(y0,g->y0)){
return y0<g->y0?-1:1;
}
if(no_cells_x!=g->no_cells_x){
return no_cells_x<g->no_cells_x?-1:1;
}
if(!AlmostEqual(wx,g->wx)){
return wx<g->wx?-1:1;
}
if(!AlmostEqual(wy,g->wy)){
return wy<g->wy?-1:1;
}
return 0;
}
bool CellGrid2D::Adjacent(const Attribute* other) const{
return false;
}
Attribute* CellGrid2D::Clone() const{
return new CellGrid2D(*this);
}
size_t CellGrid2D::HashValue() const{
return static_cast<size_t>(x0+y0+no_cells_x*wx);
}
void CellGrid2D::CopyFrom(const Attribute* other) {
operator=(*(static_cast<const CellGrid2D*>(other)));
}
const std::string CellGrid2D::BasicType(){
return "cellgrid2d";
}
ListExpr CellGrid2D::Property(){
return gentc::GenProperty("-> DATA",
BasicType(),
"(x0 y0 xw yw n_x)",
"(14.0 15.0 2.0 2.0 37)");
}
bool CellGrid2D::CheckKind(ListExpr type, ListExpr& errorInfo){
return nl->IsEqual(type,BasicType());
}
ListExpr CellGrid2D::ToListExpr(const ListExpr typeInfo)const{
if(!IsDefined()){
return nl->SymbolAtom(Symbol::UNDEFINED());
} else {
return nl->FiveElemList( nl->RealAtom(x0),
nl->RealAtom(y0),
nl->RealAtom(wx),
nl->RealAtom(wy),
nl->IntAtom(no_cells_x));
}
}
bool CellGrid2D::ReadFrom(const ListExpr value,const ListExpr typeInfo){
if(listutils::isSymbolUndefined(value)){
SetDefined(false);
return true;
}
if(!nl->HasLength(value,5)){
return false;
}
ListExpr l1 = nl->First(value);
ListExpr l2 = nl->Second(value);
ListExpr l3 = nl->Third(value);
ListExpr l4 = nl->Fourth(value);
ListExpr l5 = nl->Fifth(value);
if(!listutils::isNumeric(l1) ||
!listutils::isNumeric(l2) ||
!listutils::isNumeric(l3) ||
!listutils::isNumeric(l4) ||
(nl->AtomType(l5) != IntType)){
return false;
}
x0 = listutils::getNumValue(l1);
y0 = listutils::getNumValue(l2);
wx = listutils::getNumValue(l3);
wy = listutils::getNumValue(l4);
no_cells_x = nl->IntValue(l5);
SetDefined( (no_cells_x > 0)
&& !AlmostEqual(wx,0.0)
&& !AlmostEqual(wy,0.0));
return true;
}
std::ostream& operator<<(std::ostream& o, const CellGrid2D& u){
return u.Print(o);
}