Files
secondo/Algebras/Rectangle/RectangleAlgebra.cpp

4086 lines
117 KiB
C++
Raw Permalink 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
----
//paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}]
[1] Implementation of the Rectangle Algebra
October, 2003. Victor Teixeira de Almeida
December 2005, Victor Almeida deleted the deprecated algebra levels
(~executable~, ~descriptive~, and ~hibrid~). Only the executable
level remains. Models are also removed from type constructors.
1 Overview
This implementation file essentially contains the implementation of the
struct ~Rectangle~, and the definitions of the type constructur
~rect~, ~rect3~, and ~rect4~ with its associated operations.
2 Defines and Includes
*/
#include "Algebra.h"
#include "NestedList.h"
#include "QueryProcessor.h"
#include "RectangleAlgebra.h"
#include "StandardTypes.h"
#include "ListUtils.h"
#include "Symbols.h"
#include "CellGrid.h"
#include "Algebras/Geoid/GeoDist.h"
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
using namespace std;
extern NestedList* nl;
extern QueryProcessor* qp;
double geoDistance(const Rectangle<2>& r1, const Rectangle<2>& r2,
const Geoid* geoid){
// in this case dim is two
// step one: determine the position of r
// Q1 | Q2 | Q3
// ---------------
// Q4 | Q5 | Q6
// ----------------
// Q7 | Q8 | Q9
// where Q5 correponds to this
// with some priorities:
// Q5 > Q2 = Q4 = Q6 = Q8 > Q1 = Q3 = Q7 = Q9
double xmin1 = r1.MinD(0);
double xmax1 = r1.MaxD(0);
double ymin1 = r1.MinD(1);
double ymax1 = r1.MaxD(1);
double xmin2 = r2.MinD(0);
double xmax2 = r2.MaxD(0);
double ymin2 = r2.MinD(1);
double ymax2 = r2.MaxD(1);
int Q = 0;
if(ymin2 >= ymax1){ // 2 above 1
// Q1 - Q3
if(xmax2 < xmin1){ // left
Q = 1;
} else if(xmax1 < xmin2){ // right
Q = 3;
} else {
Q = 2;
}
} else if (ymin1 >= ymax2){ // 2 below 2
// Q7 - Q9
if(xmax2 < xmin1){
Q = 7;
} else if(xmax1 < xmin2){
Q = 9;
} else {
Q = 8;
}
} else {
// Q4 - Q5
if(xmax2 < xmin1){
Q = 4;
} else if(xmax1 < xmin2){
Q = 6;
} else {
Q = 5;
}
}
if(Q==5){ // found intersection
return 0;
}
bool valid;
if(Q==1 || Q == 3){ // above but not direct
double d1 = geodist::getDist(xmin1, ymax1, xmax1, ymax1,
xmin2, ymin2,geoid);
double d2 = geodist::getDist(xmin1, ymax1, xmax1, ymax1,
xmax2, ymin2, geoid);
return std::min(d1,d2);
}
if(Q==7 || Q==9){ // below but not direct
double d1 = geodist::getDist(xmin2,ymax2, xmax2, ymax2,
xmin1, ymin1, geoid);
double d2 = geodist::getDist(xmin2,ymax2, xmax2, ymax2,
xmax1, ymin1, geoid);
return std::min(d1,d2);
}
if(Q==2){ // direct above
double d = geoid->DistanceOrthodrome(xmin2, ymax1,xmin2, ymin2,valid);
if(!valid) return -1;
return d;
}
if(Q==8){ // direct above
double d = geoid->DistanceOrthodrome(xmin2, ymin1,xmin2, ymax2, valid);
if(!valid){ return -1; }
return d;
}
// Q4 or Q6
// restrict y to common partA
// TODO use distance computation using halfsegments
double ymin = ymin1 < ymin2 ? ymin2 : ymin1;
double ymax = ymax1 > ymax2 ? ymax2 : ymax1;
// get the y value farther from the aquator to
// minimize the distance
double y = abs(ymin) > abs(ymax) ? ymin : ymax;
if(Q==4){
double d1 = geoid->DistanceOrthodrome(xmax2,y,xmin1,y, valid);
if(!valid) return -1;
double d2 = geoid->DistanceOrthodrome(xmin2,y, xmax1,y, valid);
if(!valid) return -1;
return std::min(d1,d2);
}
if(Q==6){
double d1 = geoid->DistanceOrthodrome(xmax1, y, xmin2, y, valid);
if(!valid) return -1;
double d2 = geoid->DistanceOrthodrome(xmin1,y, xmax2,y, valid);
if(!valid) return -1;
return std::min(d1,d2);
}
assert(false); // forgetten case
return -1;
}
namespace rectangle{
/*
3 Type Constructor ~rect1~
A value of type ~rect1~ represents a 1-dimensional rectangle aligned with
the x-axis. A rectangle in such a way can be represented by two
numbers, the left and the right limit.
3.1 List Representation
The list representation of a 1D rectangle is
---- (x1 x2)
----
3.3 ~Out~-function
See RectangleAlgebra.h
3.4 ~In~-function
See RectangleAlgebra.h
3.9 Function describing the signature of the type constructor
*/
ListExpr
Rectangle1Property()
{
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(Rectangle<1>::BasicType()),
nl->StringAtom("(<left> <right>)"),
nl->StringAtom("(0.0 1.0)"))));
}
/*
3.10 Kind Checking Function
This function checks whether the type constructor is applied correctly. Since
type constructor ~rect1~ does not have arguments, this is trivial.
*/
bool
CheckRectangle1( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, Rectangle<1>::BasicType() ));
}
/*
3.12 Creation of the type constructor instance
*/
TypeConstructor rect1(
Rectangle<1>::BasicType(), //name
Rectangle1Property, //property function
//describing signature
OutRectangle<1>, InRectangle<1>, //Out and In functions
0, 0, //SaveToList and
//RestoreFromList functions
CreateRectangle<1>, DeleteRectangle<1>, //object creation and deletion
OpenAttribute<Rectangle<1> >,
SaveAttribute<Rectangle<1> >, //open and save functions
CloseRectangle<1>, CloneRectangle<1>, //object close, and clone
CastRectangle<1>, //cast function
SizeOfRectangle<1>, //sizeof function
CheckRectangle1 ); //kind checking function
/*
3 Type Constructor ~rect~
A value of type ~rect~ represents a 2-dimensional rectangle alligned with
the axes x and y. A rectangle in such a way can be represented by four
numbers, the upper and lower values for the two dimensions.
3.1 List Representation
The list representation of a 2D rectangle is
---- (x1 x2 y1 y2)
----
3.3 ~Out~-function
See RectangleAlgebra.h
3.4 ~In~-function
See RectangleAlgebra.h
3.9 Function describing the signature of the type constructor
*/
ListExpr
Rectangle2Property()
{
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(Rectangle<2>::BasicType()),
nl->StringAtom("(<left> <right> <bottom> <top>)"),
nl->StringAtom("(0.0 1.0 0.0 1.0)"))));
}
/*
3.10 Kind Checking Function
This function checks whether the type constructor is applied correctly. Since
type constructor ~rect~ does not have arguments, this is trivial.
*/
bool
CheckRectangle2( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, Rectangle<2>::BasicType() ));
}
/*
3.12 Creation of the type constructor instance
*/
TypeConstructor rect(
Rectangle<2>::BasicType(), //name
Rectangle2Property, //property function
//describing signature
OutRectangle<2>, InRectangle<2>, //Out and In functions
0, 0, //SaveToList and
//RestoreFromList functions
CreateRectangle<2>, DeleteRectangle<2>, //object creation and deletion
OpenAttribute<Rectangle<2> >,
SaveAttribute<Rectangle<2> >, //open and save functions
CloseRectangle<2>, CloneRectangle<2>, //object close, and clone
CastRectangle<2>, //cast function
SizeOfRectangle<2>, //sizeof function
CheckRectangle2 ); //kind checking function
/*
3 Type Constructor ~rect3~
A value of type ~rect3~ represents a 3-dimensional rectangle alligned with
the axes x, y and z. A rectangle in such a way can be represented by six
numbers, the upper and lower values for the three dimensions.
3.1 List Representation
The list representation of a 3D rectangle is
---- (x1 x2 y1 y2 z1 z2)
----
3.3 ~Out~-function
See RectangleAlgeba.h
3.4 ~In~-function
See RectangleAlgebra.h
3.9 Function describing the signature of the type constructor
*/
ListExpr
Rectangle3Property()
{
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, RECT34"),
nl->StringAtom(Rectangle<3>::BasicType()),
nl->StringAtom(
"(list of six <value>). l/r for 3 dimensions."),
nl->StringAtom("(0.0 1.0 10.0 11.0 20.0 21.0)"))));
}
/*
3.10 Kind Checking Function
This function checks whether the type constructor is applied correctly. Since
type constructor ~rect3~ does not have arguments, this is trivial.
*/
bool
CheckRectangle3( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, Rectangle<3>::BasicType() ));
}
/*
3.12 Creation of the type constructor instance
*/
TypeConstructor rect3(
Rectangle<3>::BasicType(), //name
Rectangle3Property, //property function
//describing signature
OutRectangle<3>, InRectangle<3>, //Out and In functions
0, 0, //SaveToList and
//RestoreFromList functions
CreateRectangle<3>, DeleteRectangle<3>, //object creation and deletion
OpenAttribute<Rectangle<3> >,
SaveAttribute<Rectangle<3> >, //open and save functions
CloseRectangle<3>, CloneRectangle<3>, //object close, and clone
CastRectangle<3>, //cast function
SizeOfRectangle<3>, //sizeof function
CheckRectangle3 ); //kind checking function
/*
3 Type Constructor ~rect4~
A value of type ~rect4~ represents a 4-dimensional rectangle alligned with
the axes w, x, y and z. A rectangle in such a way can be represented by eight
numbers, the upper and lower values for the four dimensions.
3.1 List Representation
The list representation of a 4D rectangle is
---- (w1 w2 x1 x2 y1 y2 z1 z2)
----
3.3 ~Out~-function
See RectangleAlgebra.h
3.4 ~In~-function
See RectangleAlgebra.h
3.9 Function describing the signature of the type constructor
*/
ListExpr
Rectangle4Property()
{
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(Rectangle<4>::BasicType()),
nl->StringAtom(
"(list of eight <value>). l/r for 4 dimensions."),
nl->StringAtom(
"(0.0 1.0 10.0 11.0 20.0 21.0 0.0 0.4)"))));
}
/*
3.10 Kind Checking Function
This function checks whether the type constructor is applied correctly. Since
type constructor ~rect4~ does not have arguments, this is trivial.
*/
bool
CheckRectangle4( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, Rectangle<4>::BasicType() ));
}
/*
3.12 Creation of the type constructor instance
*/
TypeConstructor rect4(
Rectangle<4>::BasicType(), //name
Rectangle4Property, //property function
//describing signature
OutRectangle<4>, InRectangle<4>, //Out and In functions
0, 0, //SaveToList and
//RestoreFromList functions
CreateRectangle<4>, DeleteRectangle<4>, //object creation and deletion
OpenAttribute<Rectangle<4> >,
SaveAttribute<Rectangle<4> >, //open and save functions
CloseRectangle<4>, CloneRectangle<4>, //object close, and clone
CastRectangle<4>, //cast function
SizeOfRectangle<4>, //sizeof function
CheckRectangle4 ); //kind checking function
/*
3 Type Constructor ~rect8~
A value of type ~rect8~ represents a 8-dimensional rectangle alligned with
the axes. A rectangle in such a way can be represented by sixteen
numbers, the upper and lower values for the eight dimensions.
3.1 List Representation
The list representation of a 8D rectangle is
---- (x1 x2 ... x15 x16)
----
3.3 ~Out~-function
See RectangleAlgebra.h
3.4 ~In~-function
See RectangleAlgebra.h
3.9 Function describing the signature of the type constructor
*/
ListExpr
Rectangle8Property()
{
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(Rectangle<8>::BasicType()),
nl->StringAtom(
"(list of sixteen <value>). l/r for "
"8 dimensions."),
nl->StringAtom(
"(0 1 10 11 20 21 0 4 4"
" 5 6 7 1 3 4 6)"))));
}
/*
3.10 Kind Checking Function
This function checks whether the type constructor is applied correctly. Since
type constructor ~rect4~ does not have arguments, this is trivial.
*/
bool
CheckRectangle8( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, Rectangle<8>::BasicType() ));
}
/*
3.12 Creation of the type constructor instance
*/
TypeConstructor rect8(
Rectangle<8>::BasicType(), //name
Rectangle8Property, //property function
//describing signature
OutRectangle<8>, InRectangle<8>, //Out and In functions
0, 0, //SaveToList and
//RestoreFromList functions
CreateRectangle<8>, DeleteRectangle<8>, //object creation and deletion
OpenAttribute<Rectangle<8> >,
SaveAttribute<Rectangle<8> >, //open and save functions
CloseRectangle<8>, CloneRectangle<8>, //object close, and clone
CastRectangle<8>, //cast function
SizeOfRectangle<8>, //sizeof function
CheckRectangle8 ); //kind checking function
/*
4 Operators
Definition of operators is similar to definition of type constructors. An
operator is defined by creating an instance of class ~Operator~. Again we
have to define some functions before we are able to create an ~Operator~
instance.
4.1 Type mapping functions
A type mapping function takes a nested list as argument. Its contents are
type descriptions of an operator's input parameters. A nested list describing
the output type of the operator is returned.
4.1.2 Type mapping function ~RectTypeMapBool~
It is for the operator ~isempty~ which have ~rect~, ~rect3~, or ~rect4~
as input and ~bool~ as result type.
*/
ListExpr
RectTypeMapBool( ListExpr args )
{
ListExpr arg1;
if ( nl->ListLength( args ) == 1 )
{
arg1 = nl->First( args );
if( nl->IsEqual( arg1, Rectangle<2>::BasicType() ) ||
nl->IsEqual( arg1, Rectangle<3>::BasicType() ) ||
nl->IsEqual( arg1, Rectangle<4>::BasicType() ) ||
nl->IsEqual( arg1, Rectangle<8>::BasicType() ))
return (nl->SymbolAtom( CcBool::BasicType() ));
}
return (nl->SymbolAtom( Symbol::TYPEERROR() ));
}
/*
4.1.2 Type mapping function ~RectTypeMapReal~
It is for the operator ~isempty~ which have ~rect~, ~rect3~, or ~rect4~
as input and ~real~ as result type.
*/
ListExpr
RectTypeMapReal( ListExpr args )
{
ListExpr arg1;
if ( nl->ListLength( args ) == 1 )
{
arg1 = nl->First( args );
if( nl->IsEqual( arg1, Rectangle<2>::BasicType() ) ||
nl->IsEqual( arg1, Rectangle<3>::BasicType() ) ||
nl->IsEqual( arg1, Rectangle<4>::BasicType() ) ||
nl->IsEqual( arg1, Rectangle<8>::BasicType() ))
return (nl->SymbolAtom( CcReal::BasicType() ));
}
return (nl->SymbolAtom( Symbol::TYPEERROR() ));
}
/*
4.1.3 Type mapping function ~RectRectTypeMapRect~
It is for the operator ~union~ and ~intersection~, which takes
two rectangles as arguments and return a rectangle.
*/
ListExpr
RectRectTypeMapRect( ListExpr args )
{
ListExpr arg1, arg2;
if ( nl->ListLength( args ) == 2 )
{
arg1 = nl->First( args );
arg2 = nl->Second( args );
if( nl->IsEqual( arg1, Rectangle<2>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<2>::BasicType() ) )
return nl->SymbolAtom( Rectangle<2>::BasicType() );
if( nl->IsEqual( arg1, Rectangle<3>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<3>::BasicType() ) )
return nl->SymbolAtom( Rectangle<3>::BasicType() );
if( nl->IsEqual( arg1, Rectangle<4>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<4>::BasicType() ) )
return nl->SymbolAtom( Rectangle<4>::BasicType() );
if( nl->IsEqual( arg1, Rectangle<8>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<8>::BasicType() ) )
return nl->SymbolAtom( Rectangle<8>::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
4.1.3 Type mapping function ~RectRectTypeMapBool~
It is for the operator like ~equal~, which takes
two rectangles as arguments and return a bool.
*/
ListExpr
RectRectTypeMapBool( ListExpr args )
{
ListExpr arg1, arg2;
if ( nl->ListLength( args ) == 2 )
{
arg1 = nl->First( args );
arg2 = nl->Second( args );
if( nl->IsEqual( arg1, Rectangle<2>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<2>::BasicType() ) )
return nl->SymbolAtom( CcBool::BasicType() );
if( nl->IsEqual( arg1, Rectangle<3>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<3>::BasicType() ) )
return nl->SymbolAtom( CcBool::BasicType() );
if( nl->IsEqual( arg1, Rectangle<4>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<4>::BasicType() ) )
return nl->SymbolAtom( CcBool::BasicType() );
if( nl->IsEqual( arg1, Rectangle<8>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<8>::BasicType() ) )
return nl->SymbolAtom( CcBool::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
4.1.4 Type mapping function ~TranslateTypeMap~
It is used for the ~translate~ operator.
*/
ListExpr TranslateTypeMap( ListExpr args )
{
ListExpr arg1, arg2;
if( nl->ListLength( args ) == 2 )
{
arg1 = nl->First( args );
arg2 = nl->Second( args );
if( nl->IsEqual( arg1, Rectangle<2>::BasicType() ) &&
nl->ListLength( arg2 ) == 2 &&
nl->IsEqual( nl->First( arg2 ), CcReal::BasicType() ) &&
nl->IsEqual( nl->Second( arg2 ), CcReal::BasicType() ) )
return nl->SymbolAtom( Rectangle<2>::BasicType() );
if( nl->IsEqual( arg1, Rectangle<3>::BasicType() ) &&
nl->ListLength( arg2 ) == 3 &&
nl->IsEqual( nl->First( arg2 ), CcReal::BasicType() ) &&
nl->IsEqual( nl->Second( arg2 ), CcReal::BasicType() ) &&
nl->IsEqual( nl->Third( arg2 ), CcReal::BasicType() ) )
return nl->SymbolAtom( Rectangle<3>::BasicType() );
if( nl->IsEqual( arg1, Rectangle<4>::BasicType() ) &&
nl->ListLength( arg2 ) == 4 &&
nl->IsEqual( nl->First( arg2 ), CcReal::BasicType() ) &&
nl->IsEqual( nl->Second( arg2 ), CcReal::BasicType() ) &&
nl->IsEqual( nl->Third( arg2 ), CcReal::BasicType() ) &&
nl->IsEqual( nl->Fourth( arg2 ), CcReal::BasicType() ) )
return nl->SymbolAtom( Rectangle<4>::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
4.1.5 Type mapping function ~rectanglex~
It is used for the ~rectanglex~ operator.
*/
template< int dim>
ListExpr RectangleTypeMap( ListExpr args )
{
ListExpr arg[2*dim];
bool checkint = true, checkreal = true;
if( (nl->ListLength( args ) == 2*dim) )
{
for(unsigned int i = 1; i <= 2*dim; i++) {
arg[i-1] = nl->Nth(i,args);
}
for(int j = 0; j < 2*dim; j++) {
if( !(nl->IsEqual( arg[j], CcInt::BasicType() )) ) {
checkint = false;
break;
}
}
for(int k = 0; k < 2*dim; k++) {
if( !(nl->IsEqual( arg[k], CcReal::BasicType() )) ) {
checkreal = false;
break;
}
}
if( checkint || checkreal )
switch(dim) {
case 1: return nl->SymbolAtom( Rectangle<1>::BasicType() );
case 2: return nl->SymbolAtom( Rectangle<2>::BasicType() );
case 3: return nl->SymbolAtom( Rectangle<3>::BasicType() );
case 4: return nl->SymbolAtom( Rectangle<4>::BasicType() );
default: return nl->SymbolAtom( Symbol::TYPEERROR() );
}
else ErrorReporter::ReportError("All argument types must be either"
" int or real!");
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
4.1.6 Type mapping function ~rectangle8size~
It is used for the ~rectangle8size~ operator.
*/
template< int dim>
ListExpr Rectangle8TypeMap( ListExpr args )
{
ListExpr arg[dim+1];
bool checkint = true, checkreal = true;
if( (nl->ListLength( args ) == dim+1) )
{
for(unsigned int i = 1; i <= dim+1; i++) {
arg[i-1] = nl->Nth(i,args);
}
for(int j = 0; j < dim; j++) {
if( !(nl->IsEqual( arg[j], CcInt::BasicType() )) ) {
checkint = false;
break;
}
}
for(int k = 0; k < dim; k++) {
if( !(nl->IsEqual( arg[k], CcReal::BasicType() )) ) {
checkreal = false;
break;
}
}
if ( (checkint || checkreal) && nl->IsEqual(arg[dim], CcReal::BasicType() ))
return nl->SymbolAtom( Rectangle<8>::BasicType() );
else ErrorReporter::ReportError("All argument types must be either"
" int or real!");
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
4.1.7 Type mapping function ~RectRectTypeMapReal~
Used for ~distance~.
*/
ListExpr
RectRectTypeMapReal( ListExpr args )
{
ListExpr arg1, arg2;
if ( nl->ListLength( args ) == 2 )
{
arg1 = nl->First( args );
arg2 = nl->Second( args );
if( ( nl->IsEqual( arg1, Rectangle<2>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<2>::BasicType() ) ) ||
( nl->IsEqual( arg1, Rectangle<3>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<3>::BasicType() ) ) ||
( nl->IsEqual( arg1, Rectangle<4>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<4>::BasicType() ) ) )
return nl->SymbolAtom( CcReal::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
4.1.7 Type mapping function ~RectRectTypeMapInt~
Used for ~toprightclass~.
*/
ListExpr
RectRectTypeMapInt( ListExpr args )
{
ListExpr arg1, arg2;
if ( nl->ListLength( args ) == 2 )
{
arg1 = nl->First( args );
arg2 = nl->Second( args );
if( ( nl->IsEqual( arg1, Rectangle<2>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<2>::BasicType() ) ) ||
( nl->IsEqual( arg1, Rectangle<3>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<3>::BasicType() ) ) ||
( nl->IsEqual( arg1, Rectangle<4>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<4>::BasicType() ) ) )
return nl->SymbolAtom( CcInt::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
4.1.7 Type mapping function ~RectProjectTypeMap~
Used for ~rectproject~.
*/
ListExpr
RectProjectTypeMap( ListExpr args )
{
ListExpr arg1, arg2, arg3;
string argstr;
int dim = -1;
if ( !( nl->ListLength( args ) == 3 ) )
{
nl->WriteToString (argstr, args);
ErrorReporter::ReportError("operator rectproject expects a list "
"a list of length 3, but gets '" + argstr + "'.");
return nl->SymbolAtom(Symbol::TYPEERROR());\
}
arg1 = nl->First( args );
arg2 = nl->Second( args );
arg3 = nl->Third( args );
if( nl->IsEqual( arg1, Rectangle<2>::BasicType() ) ) dim = 2;
else if( nl->IsEqual( arg1, Rectangle<3>::BasicType() ) ) dim = 3;
else if( nl->IsEqual( arg1, Rectangle<4>::BasicType() ) ) dim = 4;
else if( nl->IsEqual( arg1, Rectangle<8>::BasicType() ) ) dim = 8;
else dim = -1;
if ( !(dim > 0) ||
!nl->IsEqual( arg2, CcInt::BasicType() ) ||
!nl->IsEqual( arg3, CcInt::BasicType() )
)
{
nl->WriteToString (argstr, args);
ErrorReporter::ReportError("operator rectproject expects a list "
"'(rect<D> int int)' as input, but gets a list '" + argstr + "'.");
return nl->SymbolAtom(Symbol::TYPEERROR());\
}
return nl->SymbolAtom( Rectangle<2>::BasicType() );
}
/*
4.1.7 Type mapping function ~RectangleMinMaxTypeMap~
Used for ~minD~, ~maxD~.
*/
ListExpr
RectangleMinMaxTypeMap( ListExpr args )
{
ListExpr arg1, arg2;
string argstr;
int dim = -1;
AlgebraManager* am = SecondoSystem::GetAlgebraManager();
ListExpr errorInfo = nl->OneElemList( nl->SymbolAtom( "ERRORS" ) );
if ( !( nl->ListLength( args ) == 2 ) )
{
nl->WriteToString (argstr, args);
ErrorReporter::ReportError("operator minD/MaxD expects a list "
"a list of length 2, but gets '" + argstr + "'.");
return nl->SymbolAtom(Symbol::TYPEERROR());\
}
arg1 = nl->First( args );
arg2 = nl->Second( args );
if( nl->IsEqual( arg1, Rectangle<2>::BasicType() ) ||
am->CheckKind(Kind::SPATIAL2D(), arg1, errorInfo) ) dim = 2;
else if( nl->IsEqual( arg1, Rectangle<3>::BasicType() ) ||
am->CheckKind(Kind::SPATIAL2D(), arg1, errorInfo) ) dim = 3;
else if( nl->IsEqual( arg1, Rectangle<4>::BasicType() ) ||
am->CheckKind(Kind::SPATIAL2D(), arg1, errorInfo) ) dim = 4;
else if( nl->IsEqual( arg1, Rectangle<8>::BasicType() ) ||
am->CheckKind(Kind::SPATIAL2D(), arg1, errorInfo)) dim = 8;
else if( nl->IsEqual( arg1, Rectangle<1>::BasicType() ) ||
am->CheckKind(Kind::SPATIAL1D(), arg1, errorInfo)) dim = 1;
else dim = -1;
if ( !(dim > 0) ||
!nl->IsEqual( arg2, CcInt::BasicType() )
)
{
nl->WriteToString (argstr, args);
ErrorReporter::ReportError("operator minD/maxD expects a list "
"'(T int)' as input, where T in {rect<D>, SPATIAL<D>D}, "
"but gets a list '" + argstr + "'.");
return nl->SymbolAtom(Symbol::TYPEERROR());\
}
return nl->SymbolAtom( CcReal::BasicType() );
}
ListExpr RectangleTypeMapRectRect( ListExpr args )
{
ListExpr arg1;
if ( nl->ListLength( args ) == 1 )
{
arg1 = nl->First( args );
if( nl->IsEqual( arg1, Rectangle<2>::BasicType() ) ||
nl->IsEqual( arg1, Rectangle<3>::BasicType() ) ||
nl->IsEqual( arg1, Rectangle<4>::BasicType() ) ||
nl->IsEqual( arg1, Rectangle<8>::BasicType() )
)
return (arg1);
}
return (nl->SymbolAtom( Symbol::TYPEERROR() ));
}
/*
4.1.7 Type Mapping for scale rect
*/
ListExpr scalerectTypeMap(ListExpr args){
string err = " rect_d x real_1 x ... x real_d expected ";
int len = nl->ListLength(args);
int dim = len - 1;
if(dim<2){
ErrorReporter::ReportError(err);
return nl->TypeError();
}
ListExpr arg1 = nl->First(args);
if(nl->AtomType(arg1)!=SymbolType){
ErrorReporter::ReportError(err);
return nl->TypeError();
}
if(!listutils::isRectangle(arg1)){
ErrorReporter::ReportError(err);
return nl->TypeError();
}
string a1 = nl->SymbolValue(arg1);
if(a1==Rectangle<2>::BasicType()){
if(dim !=2){
ErrorReporter::ReportError("Expected 2 scale factors.");
return nl->TypeError();
}
} else if(a1==Rectangle<3>::BasicType()){
if(dim!=3){
ErrorReporter::ReportError("Expected 3 scale factors.");
return nl->TypeError();
}
} else if(a1==Rectangle<4>::BasicType()){
if( dim!=4){
ErrorReporter::ReportError("Expected 4 scale factors.");
return nl->TypeError();
}
} else if(a1==Rectangle<8>::BasicType()){
if( dim!=8){
ErrorReporter::ReportError("Expected 8 scale factors.");
return nl->TypeError();
}
} else {
ErrorReporter::ReportError("The 1st argument must be of one of {rect,rect3,"
"rect4,rect8}.");
return nl->TypeError();
}
ListExpr rest = nl->Rest(args);
while(!nl->IsEmpty(rest)){
if(!nl->IsEqual(nl->First(rest),CcReal::BasicType())){
ErrorReporter::ReportError("Only 'real' allowed as scale factors.");
return nl->TypeError();
}
rest = nl->Rest(rest);
}
return arg1;
}
/*
4.1.8 Type mapping function ~RectangleTypeMapEnlargeRect~
It is used for the ~enlargeRect~ operator.
*/
ListExpr RectangleTypeMapEnlargeRect( ListExpr args )
{
bool ok = true;
unsigned int noArgs = nl->ListLength( args );
switch(noArgs) {
case 3: ok &= nl->IsEqual( nl->First(args), Rectangle<2>::BasicType() );
break;
case 4: ok &= nl->IsEqual( nl->First(args), Rectangle<3>::BasicType() );
break;
case 5: ok &= nl->IsEqual( nl->First(args), Rectangle<4>::BasicType() );
break;
case 9: ok &= nl->IsEqual( nl->First(args), Rectangle<8>::BasicType() );
break;
default: ok = false;
}
if(ok){
for(unsigned int i = 2; i <= noArgs; i++) {
if ( !nl->IsEqual(nl->Nth(i,args), CcReal::BasicType()) ) {
ok = false;
break;
}
}
}
if(ok){
return nl->First(args);
}
ErrorReporter::ReportError("Expected rect<Dim> x real^<Dim>.");
return (nl->SymbolAtom( Symbol::TYPEERROR() ));
}
/*
4.1.1.1 Type mapping function ~RectangleTypeMapBool2~
It is for the operator ~bboxintersects~ which has two ~rect~, ~rect3~, or ~rect4~
as input and ~bool~ as result type.
*/
ListExpr
RectangleTypeMapBool2( ListExpr args )
{
ListExpr arg1, arg2;
if ( nl->ListLength( args ) == 2 )
{
arg1 = nl->First( args );
arg2 = nl->Second( args );
if( (nl->IsEqual( arg1, Rectangle<2>::BasicType() ) ||
nl->IsEqual( arg1, Rectangle<3>::BasicType() ) ||
nl->IsEqual( arg1, Rectangle<4>::BasicType() ) ||
nl->IsEqual( arg1, Rectangle<8>::BasicType() )) &&
(nl->IsEqual( arg2, Rectangle<2>::BasicType() ) ||
nl->IsEqual( arg2, Rectangle<3>::BasicType() ) ||
nl->IsEqual( arg2, Rectangle<4>::BasicType() ) ||
nl->IsEqual( arg2, Rectangle<8>::BasicType() )))
return (nl->SymbolAtom( CcBool::BasicType() ));
}
ErrorReporter::ReportError("Expected rect<Dim1> x rect<Dim2>.");
return (nl->SymbolAtom( Symbol::TYPEERROR() ));
}
/*
4.1.9 Type mapping function ~cellNumberTM~
rect x real x real x real x real x int -> stream(int)
The parameter list contains:
rect2, x0, y0, x-width, y-width, nx.
rect2 is a 2D rectangle.
Point (x0, y0) is the left-bottom point of the whole grid.
x-width and y-width is the length and width of each cell in this grid.
nx is the number of cells in every row of the gird.
The grid can be endless along with y-axis.
This operator also support 3D grid, and the map becomes:
rect3 x real x real x real x real x real x real x int x int -> stream(int)
The parameter list of 3D version contains:
rect3, x0, y0, z0, x-width, y-width, z-width, nx, ny
rect3 is a 3D rectangle.
Point (x0, y0, z0) is the left buttom point of the 3D grid.
x-width, y-width and z-width is the length, width and hight of each cell.
nx is the number of cells on every row,
ny is the number of cells on every column.
The grid can be endless along with z-axis.
Update by Christian D[ue]ntgen
Accept cellgrid2D data type
Update by Jiamin Lu at 2th Apr.
Accept cellgrid3D data type,
and use CellGrid class to replace the CellGrid2D class for 2-dimension.
*/
ListExpr
cellNumberTM( ListExpr args )
{
NList l(args);
string err = "cellnumber expects(rect, real, real, real, real, int) "
"or (rect3, real, real, real, real, real, real, int, int) "
"or (rect, cellgrid2d)"
"or (rect3, cellgrid3d)";
bool is3D = false;
int len = l.length();
if(len==2){ // rect x gridcell2d -> stream(int)
ListExpr first = nl->First(args);
ListExpr second = nl->Second(args);
if( (listutils::isSymbol(first, Rectangle<2>::BasicType()) &&
listutils::isSymbol(second, CellGrid<2>::BasicType()))
// listutils::isSymbol(second, CellGrid2D::BasicType()))
||(listutils::isSymbol(first, Rectangle<3>::BasicType()) &&
listutils::isSymbol(second, CellGrid<3>::BasicType()))){
return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
nl->SymbolAtom(CcInt::BasicType()));
}
}
if (len == 9){
is3D = true;
} else if (len != 6){
return l.typeError(err);
}
NList tRect;
tRect = l.first();
if ((is3D && !tRect.isSymbol(Rectangle<3>::BasicType()))
|| (!is3D && !tRect.isSymbol(Rectangle<2>::BasicType())))
return l.typeError(err);
int np = is3D ? 2 : 1;
for (int i = 0; i < np; i++)
{
if (!l.elem(len--).isSymbol(CcInt::BasicType()))
return l.typeError(err);
}
for(int i = 2; i <= len; i++)
{
if (!l.elem(i).isSymbol(CcReal::BasicType()))
return l.typeError(err);
}
return NList(Symbol::STREAM(), CcInt::BasicType()).listExpr();
}
/*
4.1.20 Type mapping function ~gridIntersectsTM~
----
real x real x real x real x int x rect x rect x int -> boolean
----
This operator is used to check whether the current grid cell is the
common smallest cell of two inputed rectangle.
The parameter list contains:
x0, y0, xw, yw, nx, rectA, rectB, cn.
Point(x0, y0) is the left-buttom point of the grid,
xw and yw is the length and width of each cell,
nx is the number of cells on every row,
the grid is endless in y-axis.
Two continuous rectangles are participated reactangle,
and the cn is the number of the cell that need to be verified.
The operator also can support 3D grid, and the map becomes
real x real x real x real x real x real
x int x int x rect3 x rect3 x int -> bool
The parameter list contains:
x0, y0, z0, x-width, y-width, z-width, nx, ny, rectA, rectB, cn.
Point (x0, y0, z0) is the left-buttom point of the whole grid.
x-width, y-width and z-width describe the size of each cell.
nx and ny decides the amount of cells on every row and column of the grid.
The grid is end-less in z-axis.
cn is also the number of the cell that need to be verified.
Update by Christian D[ue]ntgen
Accept CellGrid2D data type, maps
----
cellgrid2d x rect x rect x int -> bool
----
Update by Jiamin Lu
Accept CellGrid3D data type, maps
----
cellgrid3d x rect3 x rect3 x int -> bool
----
*/
ListExpr
gridIntersectsTM( ListExpr args )
{
NList l(args);
string err = "gridIntersects expects "
"(x0, y0, xw, yw, nx, rectA, rectB, cn) or "
"(x0, y0, z0, xw, yw, zw, nx, ny, rect3A, rect3B, cn) or"
"(cellgrid2d, rectA, rectB, cn) or"
"(cellgrid3d, rect3A, rect3B, cn)";
bool is3D = false;
int len = l.length();
if(len==4){ // 2D - using cellgrid
ListExpr first = nl->First(args);
ListExpr second = nl->Second(args);
ListExpr third = nl->Third(args);
ListExpr fourth = nl->Fourth(args);
// if ( ( listutils::isSymbol(first, CellGrid2D::BasicType()) &&
if ( ( listutils::isSymbol(first, CellGrid<2>::BasicType()) &&
listutils::isSymbol(second, Rectangle<2>::BasicType()) &&
listutils::isSymbol(third, Rectangle<2>::BasicType()) &&
listutils::isSymbol(fourth, CcInt::BasicType()) )
|| ( listutils::isSymbol(first, CellGrid<3>::BasicType()) &&
listutils::isSymbol(second, Rectangle<3>::BasicType()) &&
listutils::isSymbol(third, Rectangle<3>::BasicType()) &&
listutils::isSymbol(fourth, CcInt::BasicType()) ) )
{
return nl->SymbolAtom(CcBool::BasicType());
}
else
{
return listutils::typeError(err);
}
}
if (len == 11)
is3D = true;
else if (len != 8)
return l.typeError(err);
int gpl = is3D ? 6 : 4; //grid parameter length
int np = is3D ? 8 : 5;
int ei = 1; //element index
for (; ei <= gpl; ei++)
{
if (!(l.elem(ei).isSymbol(CcReal::BasicType())))
return l.typeError(err);
}
for (; ei <= np; ei++)
{
if(!(l.elem(ei).isSymbol(CcInt::BasicType())))
return l.typeError(err);
}
for (int i=0; i < 2; i++)
{
if(!(l.elem(ei++).isSymbol((is3D ? Rectangle<3>::BasicType()
: Rectangle<2>::BasicType()))))
return l.typeError(err);
}
if (!l.elem(ei).isSymbol(CcInt::BasicType()))
return l.typeError(err);
return NList(CcBool::BasicType()).listExpr();
}
/*
4.1.21 Type Mapping for operator ~gridcell2rect~
The operator has following signatures:
----
int x real x real x real x real x int --> rect
int x real real x real x real x real x real x int x int --> rect3
----
*/
ListExpr
GridCell2Rect_TM( ListExpr args )
{
NList l(args);
bool is3D = false;
int len = l.length();
if(len==2){
if(!listutils::isSymbol(nl->First(args), CcInt::BasicType()) ||
!listutils::isSymbol(nl->Second(args), CellGrid2D::BasicType())){
return listutils::typeError("int x cellgrid3d expected");
}
return nl->SymbolAtom(Rectangle<2>::BasicType());
}
if (len == 9) {
is3D = true;
} else if(len != 6){
return l.typeError("gridcell2rect expects 6 or 9 arguments.");
}
if(is3D){
if( !l.elem(1).isSymbol(CcInt::BasicType())
|| !l.elem(2).isSymbol(CcReal::BasicType())
|| !l.elem(3).isSymbol(CcReal::BasicType())
|| !l.elem(4).isSymbol(CcReal::BasicType())
|| !l.elem(5).isSymbol(CcReal::BasicType())
|| !l.elem(6).isSymbol(CcReal::BasicType())
|| !l.elem(7).isSymbol(CcReal::BasicType())
|| !l.elem(8).isSymbol(CcInt::BasicType())
|| !l.elem(9).isSymbol(CcInt::BasicType()) )
{
return l.typeError("gridcell2rect expects int x real x real x real x "
"real x real x real x int x int.");
} else {
return NList(Rectangle<3>::BasicType()).listExpr();
}
}
if( !l.elem(1).isSymbol(CcInt::BasicType())
|| !l.elem(2).isSymbol(CcReal::BasicType())
|| !l.elem(3).isSymbol(CcReal::BasicType())
|| !l.elem(4).isSymbol(CcReal::BasicType())
|| !l.elem(5).isSymbol(CcReal::BasicType())
|| !l.elem(6).isSymbol(CcInt::BasicType()) )
{
return l.typeError("gridcell2rect expects int x real x real x real x "
"real x int.");
} else {
return NList(Rectangle<2>::BasicType()).listExpr();
}
return l.typeError("gridcell2rect: Unknown typemapproblem.");
}
//4.1.22 Type mapping for operator ~toprightreport~
ListExpr
toprightreportTM(ListExpr args )
{
NList l(args);
int len = l.length();
if(len==2){
if(!listutils::isSymbol(nl->First(args), CcInt::BasicType()) ||
!listutils::isSymbol(nl->Second(args), CcInt::BasicType())){
return listutils::typeError("two int values expected");
}
}
else {
return listutils::typeError("only two int values expected");
}
return nl->SymbolAtom(CcBool::BasicType());
}
/*
4.2 Selection functions
A selection function is quite similar to a type mapping function. The only
difference is that it doesn't return a type but the index of a value
mapping function being able to deal with the respective combination of
input parameter types.
Note that a selection function does not need to check the correctness of
argument types; it has already been checked by the type mapping function that it
is applied to correct arguments.
4.3.1 Selection function ~RectangleUnarySelect~
Is used for all unary operators.
*/
int
RectangleUnarySelect( ListExpr args )
{
ListExpr arg1 = nl->First( args );
if( nl->IsEqual( arg1, Rectangle<2>::BasicType() ) )
return 0;
if( nl->IsEqual( arg1, Rectangle<3>::BasicType() ) )
return 1;
if( nl->IsEqual( arg1, Rectangle<4>::BasicType() ) )
return 2;
if( nl->IsEqual( arg1, Rectangle<8>::BasicType() ) )
return 3;
return -1; // should never occur
}
/*
4.3.1 Selection function ~RectangleBinarySelect~
Is used for all binary operators.
*/
int
RectangleBinarySelect( ListExpr args )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( nl->IsEqual( arg1, Rectangle<2>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<2>::BasicType() ) )
return 0;
if( nl->IsEqual( arg1, Rectangle<3>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<3>::BasicType() ) )
return 1;
if( nl->IsEqual( arg1, Rectangle<4>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<4>::BasicType() ) )
return 2;
if( nl->IsEqual( arg1, Rectangle<8>::BasicType() )
&& nl->IsEqual( arg2, Rectangle<8>::BasicType() ) )
return 3;
return -1; // should never occur
}
/*
4.3.2 Selection function ~RectangleBinarySelect1~
Is used for the ~bboxintersects~ operator.
*/
int
RectangleBinarySelect1( ListExpr args )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
int d1 = 0;
int d2 = 0;
if( nl->IsEqual( arg2, Rectangle<2>::BasicType() ) ) d1 = 0;
else if( nl->IsEqual( arg2, Rectangle<3>::BasicType() )) d1 = 1;
else if( nl->IsEqual( arg2, Rectangle<4>::BasicType() )) d1 = 2;
else if( nl->IsEqual( arg2, Rectangle<8>::BasicType() )) d1 = 3;
else return -1; // should never occur
if( nl->IsEqual( arg1, Rectangle<2>::BasicType() ) ) d1 = 0;
else if( nl->IsEqual( arg1, Rectangle<3>::BasicType() )) d1 = 4;
else if( nl->IsEqual( arg1, Rectangle<4>::BasicType() )) d1 = 8;
else if( nl->IsEqual( arg1, Rectangle<8>::BasicType() )) d1 = 12;
else return -1; // should never occur
return (d1 + d2);
}
/*
4.3.2 Selection function ~RectangleSelect~
Is used for the ~rectanglex~ operator.
*/
template< int dim>
int RectangleSelect( ListExpr args )
{
ListExpr arg[2*dim];
bool checkint = true, checkreal = true;
for(unsigned int i = 1; i <= 2*dim; i++)
{
arg[i-1] = nl->Nth(i,args);
}
for(int j = 0; j < 2*dim; j++)
{
if( !(nl->IsEqual( arg[j], CcInt::BasicType() )) ) {
checkint = false;
break;
}
}
for(int k = 0; k < 2*dim; k++)
{
if( !(nl->IsEqual( arg[k], CcReal::BasicType() )) ) {
checkreal = false;
break;
}
}
if( checkint ) return 0;
if( checkreal ) return 1;
return -1; // should never occur
}
/*
4.3.2 Selection function ~Rectangle8Select~
Is used for the ~rectangle8size~ operator.
*/
template< int dim>
int Rectangle8Select( ListExpr args )
{
ListExpr arg[dim];
bool checkint = true, checkreal = true;
for(unsigned int i = 1; i <= dim; i++)
{
arg[i-1] = nl->Nth(i,args);
}
for(int j = 0; j < dim; j++)
{
if( !(nl->IsEqual( arg[j], CcInt::BasicType() )) ) {
checkint = false;
break;
}
}
for(int k = 0; k < dim; k++)
{
if( !(nl->IsEqual( arg[k], CcReal::BasicType() )) ) {
checkreal = false;
break;
}
}
if( checkint ) return 0;
if( checkreal ) return 1;
return -1; // should never occur
}
/*
1.1.1 Selection Function for ~gridcell2rect~
*/
int GridCell2Rect_Select( ListExpr args )
{
int len = nl->ListLength(args);
if(len == 6 || len == 2 ){ return 0; }
if(len == 9){ return 1; }
return -1; // should never happen
}
/*
4.3.3 Selection function ~RectangleMinMaxDSelect~
Is used for the ~minD~ and ~maxD~ operators.
*/
int RectangleMinMaxDSelect( ListExpr args )
{
ListExpr arg1 = nl->First(args);
AlgebraManager* am = SecondoSystem::GetAlgebraManager();
ListExpr errorInfo = nl->OneElemList( nl->SymbolAtom( Symbol::ERRORS() ) );
if(nl->IsEqual(arg1, Rectangle<2>::BasicType() ) ||
am->CheckKind(Kind::SPATIAL2D(), arg1, errorInfo) ) return 0;
if(nl->IsEqual(arg1, Rectangle<3>::BasicType()) ||
am->CheckKind(Kind::SPATIAL3D(), arg1, errorInfo) ) return 1;
if(nl->IsEqual(arg1, Rectangle<4>::BasicType()) ||
am->CheckKind(Kind::SPATIAL4D(), arg1, errorInfo) ) return 2;
if(nl->IsEqual(arg1, Rectangle<8>::BasicType()) ||
am->CheckKind(Kind::SPATIAL8D(), arg1, errorInfo) ) return 3;
if(nl->IsEqual(arg1, Rectangle<1>::BasicType()) ||
am->CheckKind(Kind::SPATIAL1D(), arg1, errorInfo) ) return 4;
return -1; // should never occur
}
/*
4.4 Value mapping functions
A value mapping function implements an operator's main functionality: it takes
input arguments and computes the result. Each operator consists of at least
one value mapping function. In the case of overloaded operators there are
several value mapping functions, one for each possible combination of input
parameter types.
4.4.1 Value mapping functions of operator ~isempty~
*/
template <unsigned dim>
int RectangleIsEmpty( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
if( ((Rectangle<dim>*)args[0].addr)->IsDefined() )
{
((CcBool*)result.addr)->Set( true, false );
}
else
{
((CcBool *)result.addr)->Set( true, true );
}
return (0);
}
/*
4.4.2 Value mapping functions of operator ~$=$~
*/
template <unsigned dim>
int RectangleEqual( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
if ( ((Rectangle<dim>*)args[0].addr)->IsDefined() &&
((Rectangle<dim>*)args[1].addr)->IsDefined() )
{
((CcBool *)result.addr)->
Set( true, ((Rectangle<dim>*)args[0].addr)->AlmostEqual(
*((Rectangle<dim>*)args[1].addr)) );
}
else
{
((CcBool *)result.addr)->Set( false, false );
}
return (0);
}
/*
4.4.3 Value mapping functions of operator ~$\neq$~
*/
template <unsigned dim>
int RectangleNotEqual( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
if ( ((Rectangle<dim>*)args[0].addr)->IsDefined() &&
((Rectangle<dim>*)args[1].addr)->IsDefined() )
{
((CcBool *)result.addr)->
Set( true, *((Rectangle<dim>*)args[0].addr) !=
*((Rectangle<dim>*)args[1].addr) );
}
else
{
((CcBool *)result.addr)->Set( false, false );
}
return (0);
}
/*
4.4.4 Value mapping functions of operator ~intersects~
*/
template <unsigned dim>
int RectangleIntersects( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
if ( ((Rectangle<dim>*)args[0].addr)->IsDefined() &&
((Rectangle<dim>*)args[1].addr)->IsDefined() )
{
((CcBool *)result.addr)->
Set( true, ((Rectangle<dim>*)args[0].addr)->
Intersects( *((Rectangle<dim>*)args[1].addr) ) );
}
else
{
((CcBool *)result.addr)->Set( false, false );
}
return (0);
}
/*
4.4.5 Value mapping functions of operator ~inside~
*/
template <unsigned dim>
int RectangleInside( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
if ( ((Rectangle<dim>*)args[0].addr)->IsDefined() &&
((Rectangle<dim>*)args[1].addr)->IsDefined() )
{ // A inside B <=> B contains A
((CcBool *)result.addr)->
Set( true, ((Rectangle<dim>*)args[1].addr)->
Contains( *((Rectangle<dim>*)args[0].addr) ) );
}
else
{
((CcBool *)result.addr)->Set( false, false );
}
return (0);
}
/*
4.4.6 Value mapping functions of operator ~union~
*/
template <unsigned dim>
int RectangleUnion( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
*((Rectangle<dim> *)result.addr) =
((Rectangle<dim>*)args[1].addr)->
Union( *((Rectangle<dim>*)args[0].addr) );
return (0);
}
/*
4.4.7 Value mapping functions of operator ~intersection~
*/
template <unsigned dim>
int RectangleIntersection( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
*((Rectangle<dim> *)result.addr) =
((Rectangle<dim>*)args[1].addr)->
Intersection( *((Rectangle<dim>*)args[0].addr) );
return (0);
}
/*
10.4.26 Value mapping functions of operator ~translate~
*/
template <unsigned dim>
int RectangleTranslate( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
Rectangle<dim> *pResult = (Rectangle<dim> *)result.addr;
Rectangle<dim> *r = ((Rectangle<dim>*)args[0].addr);
double t[dim];
Supplier son;
Word arg;
for( unsigned d = 0; d < dim; d++ )
{
son = qp->GetSon( args[1].addr, d );
qp->Request( son, arg );
t[d] = ((CcReal *)arg.addr)->GetRealval();
}
if( r->IsDefined() )
{
*pResult = *r;
pResult->Translate( t );
return (0);
}
else
{
pResult->SetDefined( false );
return (0);
}
}
/*
4.4.5 Value mapping functions of operator ~rectanglex~
*/
template<class T, unsigned int dim>
int RectangleValueMap( Word* args, Word& result, int message,
Word& local, Supplier s )
{
double min[dim];
double max[dim];
bool alldefined = true, checkminmax = true;
result = qp->ResultStorage( s );
for(unsigned int i=0; i < dim*2-1; i++) {
if ( !(((T*)(args[i].addr))->IsDefined()) ) alldefined = false;
}
if ( alldefined )
{
for(unsigned int j=0; j < dim; j++) {
min[j] = (double)(((T*)args[2*j].addr)->GetValue());
max[j] = (double)(((T*)args[2*j+1].addr)->GetValue());
}
for(unsigned int k=0; k < dim; k++) {
if ( !(min[k] <= max[k]) ) checkminmax =false;
}
if ( checkminmax )
{
((Rectangle<dim> *)result.addr)->Set( true, min, max );
return 0;
}
}
((Rectangle<dim> *)result.addr)->SetDefined( false );
return (0);
}
/*
4.4.5 Value mapping functions of operator ~rectangle8size~
*/
template<class T, unsigned int dim>
int Rectangle8ValueMap( Word* args, Word& result, int message,
Word& local, Supplier s )
{
double min[dim+1];
double max[dim+1];
bool alldefined = true;
result = qp->ResultStorage( s );
for(unsigned int i=0; i <= dim; i++) {
if ( !(((T*)(args[i].addr))->IsDefined()) ) alldefined = false;
}
if ( alldefined )
{
for(unsigned int j=0; j < dim; j++) {
min[j] = (double)(((T*)args[j].addr)->GetValue());
max[j] = ((double)(((T*)args[j].addr)->GetValue())) +
((double)(((CcReal*)args[dim].addr)->GetValue()));
}
((Rectangle<dim> *)result.addr)->Set( true, min, max );
}
else
{
((Rectangle<dim> *)result.addr)->Set( false, min, max );
}
return (0);
}
/*
4.4.6 Value mapping functions of operator ~distance~
*/
template<unsigned int dim>
int RectangleDistanceValueMap( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
CcReal *res = (CcReal*) result.addr;
Rectangle<dim> *r1, *r2;
r1 = (Rectangle<dim> *) args[0].addr;
r2 = (Rectangle<dim> *) args[1].addr;
if( !r1->IsDefined() || !r2->IsDefined() )
res->Set( false, 0.0 );
else
{
res->Set( true, r1->Distance(*r2) );
}
return 0;
}
/*
4.4.7 Value mapping functions of operator ~rectproject~
*/
template<unsigned int dim>
int RectangleRectprojectValueMap( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
Rectangle<2> *res = (Rectangle<2> *) result.addr;
Rectangle<dim> *r;
CcInt *ci1, *ci2;
r = (Rectangle<dim> *) args[0].addr;
ci1 = (CcInt*) args[1].addr;
ci2 = (CcInt*) args[2].addr;
if( !r->IsDefined() || !ci1->IsDefined() || !ci1->IsDefined())
res->SetDefined( false );
else
{
unsigned int i1 = ci1->GetIntval();
unsigned int i2 = ci2->GetIntval();
if( i1 <= dim && i1>0 && i2 <= dim && i2>0 )
{
double min[2] = {r->MinD(i1-1), r->MinD(i2-1)};
double max[2] = {r->MaxD(i1-1), r->MaxD(i2-1)};
res->Set( true, min, max );
}
else
{
ErrorReporter::ReportError("operator rectproject: dimension index "
"out of bound!\n");
res->SetDefined( false );
}
}
return 0;
}
/*
4.4.8 Value mapping functions of operator ~minD~
*/
template<unsigned int dim>
int RectangleMinDValueMap( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
CcReal *res = (CcReal *) result.addr;
StandardSpatialAttribute<dim> *r
= (StandardSpatialAttribute<dim> *) args[0].addr;
CcInt *ci1 = (CcInt*) args[1].addr;
if( !r->IsDefined() || !ci1->IsDefined() )
res->SetDefined( false );
unsigned int i1 = ci1->GetIntval();
if ( i1 <= dim && i1>0 )
{
Rectangle<dim> bbx = r->BoundingBox();
res->Set( true, bbx.MinD(i1-1) );
}
else
{
ErrorReporter::ReportError("operator minD: dimension index "
"out of bounds!\n");
res->SetDefined( false );
}
return 0;
}
/*
4.4.9 Value mapping functions of operator ~maxD~
*/
template<unsigned int dim>
int RectangleMaxDValueMap( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
CcReal *res = (CcReal *) result.addr;
StandardSpatialAttribute<dim> *r
= (StandardSpatialAttribute<dim> *) args[0].addr;
CcInt *ci1 = (CcInt*) args[1].addr;
if( !r->IsDefined() || !ci1->IsDefined() )
res->SetDefined( false );
unsigned int i1 = ci1->GetIntval();
if ( i1 <= dim && i1>0 )
{
Rectangle<dim> bbx = r->BoundingBox();
res->Set( true, bbx.MaxD(i1-1) );
}
else
{
ErrorReporter::ReportError("operator maxD: dimension index "
"out of bounds!\n");
res->SetDefined( false );
}
return 0;
}
/*
4.4.10 Value mapping functions of operator ~bbox~
*/
template<unsigned int dim>
int RectangleBboxValueMap( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
Rectangle<dim> *arg = static_cast<Rectangle<dim> *>(args[0].addr);
Rectangle<dim> *res = static_cast<Rectangle<dim> *>(result.addr);
*res = arg->BoundingBox();
return 0;
}
/*
4.4.11 Value mapping functions of operator ~enlargeRect~
*/
template<unsigned int dim>
int RectangleEnlargeRectValueMap( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
Rectangle<dim> *arg = static_cast<Rectangle<dim> *>(args[0].addr);
Rectangle<dim> *res = static_cast<Rectangle<dim> *>(result.addr);
if(!arg->IsDefined()){
res->SetDefined(false);
return 0;
}
double newMin[dim], newMax[dim];
for(unsigned int i = 0; i<dim; i++){
newMin[i] = 0.0;
newMax[i] = 0.0;
}
for(unsigned int i = 0; i<dim; i++){
CcReal* deltaC = static_cast<CcReal*>(args[i+1].addr);
if(!deltaC->IsDefined()){ // return undef result
res->SetDefined(false);
return 0;
}
double deltaD = deltaC->GetRealval();
double minD = arg->MinD(i);
double maxD = arg->MaxD(i);
if( (deltaD < 0) && ((maxD-minD+2*deltaD) <= 0) ){
// interval too small, set result to UNDEF
res->SetDefined(false);
return 0;
} else {
newMin[i] = minD - deltaD;
newMax[i] = maxD + deltaD;
}
}
res->Set(true, newMin, newMax);
return 0;
}
/*
4.4.10 Value mapping functions of operator ~size~
*/
template<unsigned int dim>
int RectangleSizeValueMap( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
Rectangle<dim> *arg = static_cast<Rectangle<dim> *>(args[0].addr);
CcReal *res = static_cast<CcReal*>(result.addr);
double resval = arg->Size();
res->Set( (resval >= -0.1), resval);
return 0;
}
/*
4.4.12 Value Mapping for ~scalerect~
*/
template<unsigned int dim>
int scalerectValueMap( Word* args, Word& result, int message,
Word& local, Supplier s ){
result = qp->ResultStorage(s);
Rectangle<dim>* res = static_cast<Rectangle<dim>*>(result.addr);
Rectangle<dim>* arg1 = static_cast<Rectangle<dim>*>(args[0].addr);
if(!arg1->IsDefined()){
res->SetDefined(false);
return 0;
}
double min[dim];
double max[dim];
for(unsigned int i=1; i<=dim; i++){
CcReal* f = static_cast<CcReal*>(args[i].addr);
if(!f->IsDefined()){
res->SetDefined(false);
return 0;
}
double factor = f->GetValue();
if(factor<0){
res->SetDefined(false);
return 0;
}
min[i-1] = arg1->MinD(i-1)*factor;
max[i-1] = arg1->MaxD(i-1)*factor;
}
res->Set(true,min,max);
return 0;
}
/*
4.4.13 Value mapping functions of operator ~toprightclass~
*/
template<unsigned int dim>
int RectangleToprightclassValueMap ( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
CcInt *res = (CcInt*) result.addr;
Rectangle<dim> *r1, *r2;
r1 = (Rectangle<dim> *) args[0].addr;
r2 = (Rectangle<dim> *) args[1].addr;
int value = 0;
if ( r1->MaxD(0) >= r2->MaxD(0) )
{value++;}
if ( r1->MaxD(1) >= r2->MaxD(1) ) {
value += 2;}
res->Set( true, value);
return 0;
}
// 4.4.14 Value Mapping for operator ~toprightreport~
int toprightreportVM ( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
CcBool *res = (CcBool*) result.addr;
CcInt* firstarg = static_cast<CcInt*>(args[0].addr);
CcInt* secondarg = static_cast<CcInt*>(args[1].addr);
bool boolval = false;
int value;
if ( (!firstarg->IsDefined()) ||
(!secondarg->IsDefined()) )
{
res->SetDefined(false);
return 0;
}
int first = firstarg->GetIntval();
int second = secondarg->GetIntval();
value = first & second;
if (value == 0)
{boolval = true;
res->Set( true, boolval);
return 0;
}
res->Set( true, boolval);
return 0;
}
/*
4.4.4.1 Value mapping functions of operator ~bboxintersects~
*/
template <unsigned int d1, unsigned int d2>
int RectangleBboxIntersects( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
CcBool* res = static_cast<CcBool*>(result.addr);
Rectangle<d1>* arg1 = static_cast<Rectangle<d1>*>(args[0].addr);
Rectangle<d2>* arg2 = static_cast<Rectangle<d2>*>(args[1].addr);
if ( ((Rectangle<d1>*)args[0].addr)->IsDefined() &&
((Rectangle<d2>*)args[1].addr)->IsDefined() )
{
bool inter = true;
for(unsigned int d = 0; ( inter && (d < min(d1,d2)) ); d++){
if( arg1->MaxD((int)d) < arg2->MinD((int)d)
|| arg2->MaxD((int)d) < arg1->MinD((int)d) )
inter = false;
}
res->Set( true, inter );
}
else
{
res->Set( false, false );
}
return (0);
}
/*
4.4.13 Value mapping functions of operator ~cellnumber~
Build a cell grid located in first quadrant,
and return the number of cells that the rectangle object covers.
4.4.13.1 Auxiliary functions for ~cellnumber~ and ~gridintersects~
~ptQuadrant~ method returns which quadrant a point locates,
inside 2D or 3D space.
Only if the point locates in the first quadrant,
the returned quadrant number is positive 1.
Or else, the quadrant number is a negative.
*/
int ptQuadrant(double x, double y)
{
int quadrant = 0;
if (x < 0.0)
{
if (y < 0.0)
quadrant = 3;
else
quadrant = 2;
} else
{
if (y < 0.0)
quadrant = 4;
else
quadrant = 1;
}
quadrant = (quadrant > 1) ? (0 - quadrant) : quadrant;
return quadrant;
}
int ptQuadrant(double x, double y, double z)
{
int quadrant = abs(ptQuadrant(x, y));
if (z < 0.0)
quadrant += 4;
quadrant = (quadrant > 1) ? (0 - quadrant) : quadrant;
return quadrant;
}
/*
~cellCord~ function is used to get the coordinate number of a
specific point in one axis.
It contains some necessary parameters, like:
* p0: the value of the original point value
* pq: the position of the query point
* cw: the width of a cell
the optional parameter:
* isRT: whether the point is the right top point of the given rectangle
*/
int cellCord(double p0, double pq, double cw, bool isRT = false)
{
int CORD = 0;
double dt = pq - p0;
if (!AlmostEqual(0.0, dt)){
CORD = static_cast<int>(floor(dt / cw));
if (isRT && AlmostEqual(dt, CORD * cw)){
CORD = CORD > 0 ? CORD-1 : CORD+1;
}
}
return CORD;
}
int
cellNumberVM(Word* args, Word& result,
int message, Word& local, Supplier s)
{
struct InCellGrid{
//Internal Cell Grid,
//to different from the CellGrid class in TemporalAlgebra
InCellGrid(double _x0, double _y0, double _z0,
double _xw, double _yw, double _zw,
int _nx, int _ny, bool _3D):
nx(_nx), ny(_ny),
x0(_x0), y0(_y0), z0(_z0),
xWidth(_xw), yWidth(_yw), zWidth(_zw),
cx(0), cy(0), cz(0),
outGrid(false), finished(false), is3D(_3D)
{}
//Set the MBR of the rectangle in the grid
void setBoundBox(double lbx, double rtx,
double lby, double rty,
double lbz = 0.0, double rtz = 0.0)
{
//Make sure the widths of the grid all are not 0
if ( fabs(xWidth - 0.0) <= 1e-10
|| fabs(yWidth - 0.0) <= 1e-10
|| (is3D && fabs(zWidth - 0.0) <= 1e-10))
{
cerr << "Unacceptable grid width: " <<
xWidth << "," << yWidth << "," << zWidth << endl;
return;
}
/*
For 2D space,
the cell grid grows infinitely in Y-axis,
but is limited in X-axis by parameter ~nx~.
For 3D space, the cell grid is limited in both X and Y axises,
but grows infinitely in Z-axis.
The cell grid sits in a limit area in the first quadrant.
If the query rectangle locates outside this scope,
then the cell grid is duplicated.
*/
LBX = cellCord(x0, lbx, xWidth);
LBY = cellCord(y0, lby, yWidth);
LBZ = cellCord(z0, lbz, zWidth);
RTX = cellCord(x0, rtx, xWidth, true);
RTY = cellCord(y0, rty, yWidth, true);
RTZ = cellCord(z0, rtz, zWidth, true);
int maxX = RTX > (nx - 1) ? (nx - 1) : RTX;
int maxY = RTY > (ny - 1) ? (ny - 1) : RTY;
int maxN = max(maxX, maxY);
maxN = (is3D) ? (max(maxN, RTZ)) : maxN;
if ((!is3D && (maxN > sqrt(INT_MAX))) ||
( is3D && (maxN > pow(INT_MAX, 1.0/3.0))))
cerr << "WARNING2!! The grid is too dense, "
"part cell number may exceed the range of Integer type.\n";
cx = LBX;
cy = LBY;
cz = LBZ;
}
int getNextCellNum()
{
int cellNum = -1;
while(!finished)
{
int acx = cx >= 0 ? (cx % nx) : ( (0 - cx) % nx - 1);
int acy = cy >= 0 ? (is3D ? cy % ny : cy) :
(is3D ? ((0 - cy) % ny - 1) : (0 - cy - 1));
int acz = cz >= 0 ? cz : (0 - cz - 1);
cellNum = acx + acy * nx + acz * nx * ny + 1;
if (cx < RTX)
cx++;
else if (cy < RTY)
{
cx = LBX;
cy++;
}
else if (cz < RTZ)
{
cx = LBX;
cy = LBY;
cz++;
}
else
{
finished = true;
}
if (outputCells.find(cellNum) != outputCells.end()){
//already output the cell
cellNum = -1;
continue;
}
outputCells.insert(cellNum);
break;
}
return cellNum;
}
int nx, ny;
double x0, y0, z0, xWidth, yWidth, zWidth;
int LBX, LBY, LBZ, RTX, RTY, RTZ; //LB: left-buttom; RT: right-top
int cx, cy, cz; //Current cell coordinate number
bool outGrid; //Whether the rectangle is outside the given grid
bool finished;
bool is3D;
set<int> outputCells;
};
InCellGrid* grid = static_cast<InCellGrid*>(local.addr);
switch (message) {
case OPEN: {
if(grid){
delete grid;
grid = 0;
}
double x0 = 0.0, y0 = 0.0, z0 = 0.0;
double xw = 0.0, yw = 0.0, zw = 0.0;
int nx = 0, ny = INT_MAX;
int len = qp->GetNoSons(s);
for(int arg=0; arg<len; arg++){
if(!(static_cast<Attribute*>(args[arg].addr))->IsDefined()) {
cerr << "Undefined argument used in cellnumber." << endl;
return CANCEL;
}
}
if(len==2)
{
ListExpr rectType = qp->GetSupplierTypeExpr(qp->GetSon(s, 0));
if (listutils::isSymbol(rectType, Rectangle<2>::BasicType()))
{
Rectangle<2> *rect = (Rectangle<2> *)args[0].addr;
const CellGrid<2>* g = static_cast<CellGrid<2>*>(args[1].addr);
x0 = g->getOrigin(0);
y0 = g->getOrigin(1);
xw = g->getCellWidth(0);
yw = g->getCellWidth(1);
nx = g->getCellNum(0);
grid = new InCellGrid(x0, y0, z0, xw, yw, zw, nx, ny, false);
grid->setBoundBox(rect->MinD(0), rect->MaxD(0),
rect->MinD(1),rect->MaxD(1));
}
else if (listutils::isSymbol(rectType, Rectangle<3>::BasicType()))
{
Rectangle<3> *rect = (Rectangle<3> *)args[0].addr;
const CellGrid<3>* g = static_cast<CellGrid<3>*>(args[1].addr);
x0 = g->getOrigin(0);
y0 = g->getOrigin(1);
z0 = g->getOrigin(2);
xw = g->getCellWidth(0);
yw = g->getCellWidth(1);
zw = g->getCellWidth(2);
nx = g->getCellNum(0);
ny = g->getCellNum(1);
grid = new InCellGrid(x0, y0, z0, xw, yw, zw, nx, ny, true);
grid->setBoundBox(rect->MinD(0), rect->MaxD(0),
rect->MinD(1), rect->MaxD(1),
rect->MinD(2), rect->MaxD(2));
}
} else if (6 == len) {
Rectangle<2> *rect = (Rectangle<2> *)args[0].addr;
x0 = ((CcReal *)args[1].addr)->GetValue();
y0 = ((CcReal *)args[2].addr)->GetValue();
xw = ((CcReal *)args[3].addr)->GetValue();
yw = ((CcReal *)args[4].addr)->GetValue();
nx = ((CcInt *)args[5].addr)->GetValue();
grid = new InCellGrid(x0, y0, z0, xw, yw, zw, nx, ny, false);
grid->setBoundBox(rect->MinD(0), rect->MaxD(0),
rect->MinD(1),rect->MaxD(1));
} else { // len = 9
Rectangle<3> *rect = (Rectangle<3> *)args[0].addr;
x0 = ((CcReal *)args[1].addr)->GetValue();
y0 = ((CcReal *)args[2].addr)->GetValue();
z0 = ((CcReal *)args[3].addr)->GetValue();
xw = ((CcReal *)args[4].addr)->GetValue();
yw = ((CcReal *)args[5].addr)->GetValue();
zw = ((CcReal *)args[6].addr)->GetValue();
nx = ((CcInt *)args[7].addr)->GetValue();
ny = ((CcInt *)args[8].addr)->GetValue();
grid = new InCellGrid(x0, y0, z0, xw, yw, zw, nx, ny, true);
grid->setBoundBox(rect->MinD(0), rect->MaxD(0),
rect->MinD(1), rect->MaxD(1),
rect->MinD(2), rect->MaxD(2));
}
local.addr = grid;
return 0;
}
case REQUEST: {
if (!grid){
return CANCEL;
}else{
int nextCellNum = grid->getNextCellNum();
if (nextCellNum >= 0)
{
CcInt* res = new CcInt(true, nextCellNum);
result.addr = res;
return YIELD;
}
else
{
result.addr = 0;
return CANCEL;
}
}
}
case CLOSE: {
if (grid != 0){
delete grid;
local.addr = 0;
}
return 0;
}
default: {
/* should never happen */
assert(false);
return -1;
}
}
}
/*
4.4.13 Value mapping functions of operator ~gridintersects~
The inputs are:
(x0, y0, xW, yW, nx, rectA, rectB, cellno).
Divide the first quadrant space of point(x0, y0) into grids,
cell width is ~xW~ and cell height is ~yW~, every line has ~nx~ cells.
Then return whether the serial number of the ~common smallest cell~ of
two rectangles ~rectA~ and ~rectB~ is ~cellno~.
*/
int
gridIntersectsVM(Word* args, Word& result,
int message, Word& local, Supplier s)
{
result = qp->ResultStorage( s );
CcBool* res = static_cast<CcBool*>(result.addr);
bool is3D = false;
int nx = 0, ny = INT_MAX;
int LBX = 0, LBY = 0, LBZ = 0;
double x0 = 0.0, y0 = 0.0, z0 = 0.0;
double xw = 0.0, yw = 0.0, zw = 0.0;
double interx = 0.0, intery = 0.0, interz = 0.0;
int cscNo = 0, cellno = -1;
int noSons = qp->GetNoSons(s);
// check for undefined arguments
for(int arg=0; arg<noSons; arg++) {
if(!static_cast<Attribute*>(args[arg].addr)->IsDefined()){
ErrorReporter::ReportError("RectangleAlgebra::gridIntersects: "
"Undefined argument used");
res->Set( false, false );
return 0;
}
}
if(noSons==4){
ListExpr gridType = qp->GetSupplierTypeExpr(qp->GetSon(s, 0));
if (listutils::isSymbol(gridType, CellGrid<2>::BasicType()))
{
// 2d grid using cellgrid2d
const CellGrid<2>* grid = static_cast<CellGrid<2>*>(args[0].addr);
const Rectangle<2>* rectA =
static_cast<const Rectangle<2>*>(args[1].addr);
const Rectangle<2>* rectB =
static_cast<const Rectangle<2>*>(args[2].addr);
cellno = (static_cast<CcInt*>(args[3].addr))->GetValue();
if (!rectA->Intersects(*rectB)) {
res->Set( true, false );
return 0;
} else {
x0 = grid->getOrigin(0);
y0 = grid->getOrigin(1);
xw = grid->getCellWidth(0);
yw = grid->getCellWidth(1);
nx = grid->getCellNum(0);
interx = max(rectA->MinD(0), rectB->MinD(0));
intery = max(rectA->MinD(1), rectB->MinD(1));
}
}
else
{
// 3d grid using cellgrid3d
is3D = true;
Rectangle<3> *rectA = (Rectangle<3> *)args[1].addr;
Rectangle<3> *rectB = (Rectangle<3> *)args[2].addr;
cellno = ((CcInt *)args[3].addr)->GetValue();
if (!rectA->Intersects(*rectB)) {
res->Set(true, false);
return 0;
} else {
const CellGrid<3>* grid = static_cast<CellGrid<3>*>(args[0].addr);
x0 = grid->getOrigin(0);
y0 = grid->getOrigin(1);
z0 = grid->getOrigin(2);
xw = grid->getCellWidth(0);
yw = grid->getCellWidth(1);
zw = grid->getCellWidth(2);
nx = grid->getCellNum(0);
ny = grid->getCellNum(1);
interx = max(rectA->MinD(0), rectB->MinD(0));
intery = max(rectA->MinD(1), rectB->MinD(1));
interz = max(rectA->MinD(2), rectB->MinD(2));
}
}
} else if (noSons == 8) { // 2D grid, using definition of grid
Rectangle<2> *rectA = (Rectangle<2> *)args[5].addr;
Rectangle<2> *rectB = (Rectangle<2> *)args[6].addr;
if (!rectA->Intersects(*rectB))
{
res->Set( true, false );
return 0;
}
else
{
x0 = ((CcReal *)args[0].addr)->GetValue();
y0 = ((CcReal *)args[1].addr)->GetValue();
xw = ((CcReal *)args[2].addr)->GetValue();
yw = ((CcReal *)args[3].addr)->GetValue();
nx = ((CcInt *)args[4].addr)->GetValue();
cellno = ((CcInt *)args[7].addr)->GetValue();
interx = max(rectA->MinD(0), rectB->MinD(0));
intery = max(rectA->MinD(1), rectB->MinD(1));
}
} else if(noSons==11 ){
is3D = true;
Rectangle<3> *rectA = (Rectangle<3> *)args[8].addr;
Rectangle<3> *rectB = (Rectangle<3> *)args[9].addr;
if (!rectA->Intersects(*rectB)) {
res->Set(true, false);
return 0;
} else {
x0 = ((CcReal *)args[0].addr)->GetValue();
y0 = ((CcReal *)args[1].addr)->GetValue();
z0 = ((CcReal *)args[2].addr)->GetValue();
xw = ((CcReal *)args[3].addr)->GetValue();
yw = ((CcReal *)args[4].addr)->GetValue();
zw = ((CcReal *)args[5].addr)->GetValue();
nx = ((CcInt *)args[6].addr)->GetValue();
ny = ((CcInt *)args[7].addr)->GetValue();
cellno = ((CcInt *)args[10].addr)->GetValue();
interx = max(rectA->MinD(0), rectB->MinD(0));
intery = max(rectA->MinD(1), rectB->MinD(1));
interz = max(rectA->MinD(2), rectB->MinD(2));
}
} else {
cerr << "wrong number of arguments" << endl;
assert(false);
}
if (fabs(xw - 0.0) <= 1e-10
|| fabs(yw - 0.0) <= 1e-10
|| (is3D && fabs(zw - 0.0) <= 1e-10)) {
cerr << "RectangleAlgebra::gridIntersects:"
"Unacceptable grid width (" <<
xw << "," << yw << "," << zw << ")" << endl;
res->Set( true, false );
return 0;
}
LBX = cellCord(x0, interx, xw);
LBY = cellCord(y0, intery, yw);
LBZ = cellCord(z0, interz, zw);
//duplicate the grid when the query point is out of the scope
int albx = LBX >= 0 ? (LBX % nx) : ((0 - LBX) % nx - 1);
int alby = LBY >= 0 ? (is3D ? LBY % ny : LBY) :
(is3D ? ((0 - LBY)%ny - 1) : (0 - LBY - 1));
int albz = LBZ >= 0 ? LBZ : (0 - LBZ - 1);
cscNo = albx + alby*nx + albz*nx*ny + 1;
res->Set(true, (cscNo == cellno));
return 0;
}
/*
1.1.1 Value Mapping for operator ~gridcell2rect~
*/
template<int DIM>
int gridcell2rect_vm(Word* args, Word& result,
int message, Word& local, Supplier s) {
result = qp->ResultStorage( s );
Rectangle<DIM>* res = static_cast<Rectangle<DIM>*>(result.addr);
int cellNo = 0;
double x0 = 0.0, y0 = 0.0, z0 = 0.0;
double xw = 0.0, yw = 0.0, zw = 0.0;
int nx = 0, ny = 0;
int col=0, row=0, level=0;
double min[DIM], max[DIM];
int noArgs = qp->GetNoSons(s);
bool is3D = (noArgs==9);
// check for undefined values
for(int arg=0; arg<noArgs; arg++) {
if(!static_cast<Attribute*>(args[arg].addr)->IsDefined()){
res->SetDefined( false );
return 0;
}
}
cellNo = (static_cast<CcInt*>(args[0].addr))->GetValue();
if(cellNo < 1){
res->SetDefined( false );
return 0;
}
if(is3D && (DIM>2)){ // 3D grid
x0 = (static_cast<CcReal*>(args[1].addr))->GetValue();
y0 = (static_cast<CcReal*>(args[2].addr))->GetValue();
z0 = (static_cast<CcReal*>(args[3].addr))->GetValue();
xw = (static_cast<CcReal*>(args[4].addr))->GetValue();
yw = (static_cast<CcReal*>(args[5].addr))->GetValue();
zw = (static_cast<CcReal*>(args[6].addr))->GetValue();
nx = (static_cast<CcInt*>(args[7].addr))->GetValue();
ny = (static_cast<CcInt*>(args[8].addr))->GetValue();
if( (nx < 1) || (ny < 1) || AlmostEqual(xw,0.0)
|| AlmostEqual(yw,0.0) || AlmostEqual(zw,0.0) ){
res->SetDefined( false );
return 0;
}
level = (cellNo-1) / (nx*ny);
row = ((cellNo-1) % (nx*ny)) / nx;
col = ((cellNo-1) % (nx*ny)) % nx;
min[0] = MIN(x0 + col * xw, x0 + (col+1) * xw);
max[0] = MAX(x0 + col * xw, x0 + (col+1) * xw);
min[1] = MIN(y0 + row * yw, y0 + (row+1) * yw);
max[1] = MAX(y0 + row * yw, y0 + (row+1) * yw);
min[2] = MIN(z0 + level * zw, z0 + (level+1) * zw);
max[2] = MAX(z0 + level * zw, z0 + (level+1) * zw);
} else { // 2D grid
if(noArgs==2){
CellGrid2D* grid = static_cast<CellGrid2D*>(args[1].addr);
x0 = grid->getX0();
y0 = grid->getY0();
xw = grid->getXw();
yw = grid->getYw();
nx = grid->getNx();
} else {
x0 = (static_cast<CcReal*>(args[1].addr))->GetValue();
y0 = (static_cast<CcReal*>(args[2].addr))->GetValue();
xw = (static_cast<CcReal*>(args[3].addr))->GetValue();
yw = (static_cast<CcReal*>(args[4].addr))->GetValue();
nx = (static_cast<CcInt*>(args[5].addr))->GetValue();
if( (nx < 1) || AlmostEqual(xw,0.0) || AlmostEqual(yw,0.0) ){
res->SetDefined( false );
return 0;
}
}
col = (cellNo-1) % nx;
row = (cellNo-1) / nx;
min[0] = MIN(x0 + col * xw, x0 + (col+1) * xw);
max[0] = MAX(x0 + col * xw, x0 + (col+1) * xw);
min[1] = MIN(y0 + row * yw, y0 + (row+1) * yw);
max[1] = MAX(y0 + row * yw, y0 + (row+1) * yw);
}
res->Set(true, min, max);
return 0;
}
/*
4.5 Definition of operators
Definition of operators is done in a way similar to definition of
type constructors: an instance of class ~Operator~ is defined.
Because almost all operators are overloaded, we have first do define an array of value
mapping functions for each operator. For nonoverloaded operators there is also such and array
defined, so it easier to make them overloaded.
4.5.1 Definition of value mapping vectors
*/
ValueMapping rectangleisemptymap[] = { RectangleIsEmpty<2>,
RectangleIsEmpty<3>,
RectangleIsEmpty<4>,
RectangleIsEmpty<8> };
ValueMapping rectangleequalmap[] = { RectangleEqual<2>,
RectangleEqual<3>,
RectangleEqual<4>,
RectangleEqual<8> };
ValueMapping rectanglenotequalmap[] = { RectangleNotEqual<2>,
RectangleNotEqual<3>,
RectangleNotEqual<4>,
RectangleNotEqual<8>};
ValueMapping rectangleintersectsmap[] = { RectangleIntersects<2>,
RectangleIntersects<3>,
RectangleIntersects<4>,
RectangleIntersects<8> };
ValueMapping rectangleinsidemap[] = { RectangleInside<2>,
RectangleInside<3>,
RectangleInside<4>,
RectangleInside<8> };
ValueMapping rectangletranslatemap[] = { RectangleTranslate<2>,
RectangleTranslate<3>,
RectangleTranslate<4> };
ValueMapping rectangleunionmap[] = { RectangleUnion<2>,
RectangleUnion<3>,
RectangleUnion<4>,
RectangleUnion<8> };
ValueMapping rectangleintersectionmap[] = { RectangleIntersection<2>,
RectangleIntersection<3>,
RectangleIntersection<4>,
RectangleIntersection<4> };
ValueMapping rectanglerectangle1map[] = { RectangleValueMap<CcInt, 1>,
RectangleValueMap<CcReal, 1> };
ValueMapping rectanglerectangle2map[] = { RectangleValueMap<CcInt, 2>,
RectangleValueMap<CcReal, 2> };
ValueMapping rectanglerectangle3map[] = { RectangleValueMap<CcInt, 3>,
RectangleValueMap<CcReal, 3> };
ValueMapping rectanglerectangle4map[] = { RectangleValueMap<CcInt, 4>,
RectangleValueMap<CcReal, 4> };
ValueMapping rectanglerectangle8map[] = { Rectangle8ValueMap<CcInt, 8>,
Rectangle8ValueMap<CcReal, 8> };
ValueMapping rectangletoprightclassmap[] = { RectangleToprightclassValueMap<2>,
RectangleToprightclassValueMap<3>,
RectangleToprightclassValueMap<4>,
RectangleToprightclassValueMap<8>};
ValueMapping rectangledistancemap[] = { RectangleDistanceValueMap<2>,
RectangleDistanceValueMap<3>,
RectangleDistanceValueMap<4>,
RectangleDistanceValueMap<8> };
ValueMapping rectanglerectprojectmap[] =
{
RectangleRectprojectValueMap<2>,
RectangleRectprojectValueMap<3>,
RectangleRectprojectValueMap<4>,
RectangleRectprojectValueMap<8>};
ValueMapping rectangleMaxDmap[] =
{
RectangleMaxDValueMap<2>,
RectangleMaxDValueMap<3>,
RectangleMaxDValueMap<4>,
RectangleMaxDValueMap<8>
};
ValueMapping rectangleMinDmap[] =
{
RectangleMinDValueMap<2>,
RectangleMinDValueMap<3>,
RectangleMinDValueMap<4>,
RectangleMinDValueMap<8>,
RectangleMinDValueMap<1>
};
ValueMapping rectangleBboxmap[] =
{
RectangleBboxValueMap<2>,
RectangleBboxValueMap<3>,
RectangleBboxValueMap<4>,
RectangleBboxValueMap<8>
};
ValueMapping rectangleEnlargeRectmap[] =
{
RectangleEnlargeRectValueMap<2>,
RectangleEnlargeRectValueMap<3>,
RectangleEnlargeRectValueMap<4>,
RectangleEnlargeRectValueMap<8>
};
ValueMapping rectangleSizemap[] =
{
RectangleSizeValueMap<2>,
RectangleSizeValueMap<3>,
RectangleSizeValueMap<4>,
RectangleSizeValueMap<8>
};
ValueMapping scalerectMap[] =
{
scalerectValueMap<2>,
scalerectValueMap<3>,
scalerectValueMap<4>,
scalerectValueMap<8>
};
ValueMapping rectanglebboxintersectsmap[] = {
RectangleBboxIntersects<2,2>,
RectangleBboxIntersects<2,3>,
RectangleBboxIntersects<2,4>,
RectangleBboxIntersects<2,8>,
RectangleBboxIntersects<3,2>,
RectangleBboxIntersects<3,3>,
RectangleBboxIntersects<3,4>,
RectangleBboxIntersects<3,8>,
RectangleBboxIntersects<4,2>,
RectangleBboxIntersects<4,3>,
RectangleBboxIntersects<4,4>,
RectangleBboxIntersects<4,8>,
RectangleBboxIntersects<8,2>,
RectangleBboxIntersects<8,3>,
RectangleBboxIntersects<8,4>,
RectangleBboxIntersects<8,8>
};
ValueMapping GridCell2Rect_VM[] = {
gridcell2rect_vm<2>,
gridcell2rect_vm<3>
};
/*
4.5.2 Definition of specification strings
*/
const string RectangleSpecIsEmpty =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>rect<d> -> bool</text---> <text>isempty ( _ )</text--->"
"<text>Returns whether the value is defined or not.</text--->"
"<text>query isempty ( rect1 )</text--->"
") )";
const string RectangleSpecEqual =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>(rect<d> x rect<d>) -> bool</text--->"
"<text>_ = _</text--->"
"<text>Equal.</text--->"
"<text>query rect1 = rect</text--->"
") )";
const string RectangleSpecNotEqual =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>(rect<d> x rect<d>) -> bool</text--->"
"<text>_ # _</text--->"
"<text>Not equal.</text--->"
"<text>query rect1 # rect</text--->"
") )";
const string RectangleSpecIntersects =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>(rect<d> x rect<d>) -> bool </text--->"
"<text>_ intersects _</text--->"
"<text>Intersects.</text--->"
"<text>query rect1 intersects rect</text--->"
") )";
const string RectangleSpecInside =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>(rect<d> x rect<d>) -> bool</text--->"
"<text>_ inside _</text--->"
"<text>Inside.</text--->"
"<text>query rect1 inside rect</text--->"
") )";
const string RectangleSpecUnion =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>(rect<d> x rect<d>) -> rect<d></text--->"
"<text>_ union _</text--->"
"<text>return the union of two rectangles.</text--->"
"<text>query rect1 union rect2</text--->"
") )";
const string RectangleSpecIntersection =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>(rect<d> x rect<d>) -> rect<d></text--->"
"<text>_ intersection _</text--->"
"<text>return the intersection of two rectangles.</text--->"
"<text>query rect1 intersection rect2</text--->"
") )";
const string RectangleSpecTranslate =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>(rect (real real)) -> rect "
"(rect3 (real real real)) -> rect3 "
"(rect4 (real real real real)) -> rect4</text--->"
"<text> _ translate[list]</text--->"
"<text> move the rectangle parallely for some distance.</text--->"
"<text> query rect1 translate[3.5, 15.1]</text--->"
") )";
const string RectangleSpecRectangle1 =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" \"Remarks\")"
"( <text>(int x int -> rect) or (real x real -> rect)</text--->"
"<text>rectangle1( xmin, xmax)</text--->"
"<text>creates a rect from the given parameters.</text--->"
"<text>query rectangle1(17.0, 24.3)</text--->"
"<text>The sequence of parameters must be "
"(minx, maxx) with (minx < maxx)</text--->"
") )";
const string RectangleSpecRectangle2 =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" \"Remarks\")"
"( <text>(int x int x int x int -> rect) or"
" (real x real x real x real -> rect)</text--->"
"<text>rectangle2( xmin, xmax, ymin, ymax)</text--->"
"<text>creates a rect from the given parameters.</text--->"
"<text>query rectangle2(17.0, 24.3, 12.0, 13.1)</text--->"
"<text>The sequence of parameters must be "
"(minx, maxx, miny, maxy) with (minx < maxx) and"
" (miny < maxy).</text--->"
") )";
const string RectangleSpecRectangle3 =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" \"Remarks\")"
"( <text>(int x int x int x int x int x int -> rect3) or"
" (real x real x real x real x real x real -> rect3)</text--->"
"<text>rectangle3( xmin, xmax, ymin, ymax, zmin, zmax)</text--->"
"<text>creates a rect3 from the given parameters.</text--->"
"<text>query rectangle3(17.0, 24.0, 12.0, 13.1, 4.41, 6.18)</text--->"
"<text>The sequence of parameters must be "
"(minx, maxx, miny, maxy, minz, maxz) with (minx < maxx) and"
" (miny < maxy) and (minz < maxz).</text--->"
") )";
const string RectangleSpecRectangle4 =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" \"Remarks\")"
"( <text>(int^8 -> rect4) or (real^8 -> rect4)"
"</text--->"
"<text>rectangle4( d1min,d1max,d2min,d2max,d3min,d3max,d4min,d4max)"
"</text--->"
"<text>creates a rect4 from the given parameters.</text--->"
"<text>query rectangle3(17.0, 24.0, 12.0, 13.1, "
"4.41, 6.18, 2.3, 3.74)</text--->"
"<text>The sequence of parameters must be "
"(minx, maxx, miny, maxy, minz, maxz, min4d, max4d)"
" with (minx < maxx) and (miny < maxy) and (minz < maxz)"
" and (min4d < max4d).</text--->"
") )";
/*
const string RectangleSpecRectangle8 =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" \"Remarks\")"
"( <text>(int^16 -> rect8) or (real^16 -> rect8)</text--->"
"<text>rectangle8( d1min,d1max,d2min,d2max,d3min,d3max,d4min,d4max, "
"d5min,d5max,d6min,d6max,d7min,d7max,d8min,d8max)</text--->"
"<text>creates a rect8 from the given parameters.</text--->"
"<text>query rectangle8(1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8)</text--->"
"<text>The sequence of parameters must be "
"(d1min,d1max,d2min,d2max,d3min,d3max,d4min,d4max, d5min,d5max,d6min,"
"d6max,d7min,d7max,d8min,d8max).</text--->"
") )";
*/
const string RectangleSpecRectangle8 =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" \"Remarks\")"
"( <text>(int x int x int x int x int x int x int x int x real -> "
"rect8) or (real x real x real x real x real x real x real x "
"real x real -> rect8)</text--->"
"<text>rectangle8( min1d,min2d,min3d,min4d,min5d,min6d,min7d,min8d, "
"size )</text--->"
"<text>creates a rect8 from the given parameters with minxd as lower "
"bound and size computing the upper bound (minxd+size) of the "
"respective axis intervals.</text--->"
"<text>query rectangle8(1,2,3,4,5,6,7,8, 1.2)</text--->"
"<text>The sequence of parameters must be "
"(min1d, min2d, min3d, min4d, min5d, min6d, min7d, min8d, size)"
" with minxd as lower bound and size computing the upper bound "
"(minxd+size) of the respective axis intervals.</text--->"
") )";
const string RectangleSpecDistance =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" \"Remarks\")"
"( <text>(rect<d> x rect<d>) -> real</text--->"
"<text>distance( _ , _ )</text--->"
"<text>return the euclidean distance of two rectangles.</text--->"
"<text>query distance(rect1, rect2)</text--->"
"<text></text--->"
") )";
const string RectangleSpecRectproject =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" \"Remarks\")"
"( <text>(rect<d> x int x int) -> rect</text--->"
"<text>rectproject( rect , d1 , d2 )</text--->"
"<text>projects the rectangle 'rect' to its dimensions "
"'d1' and 'd2'. 1 <= d1, d2 <= D.</text--->"
"<text>query rectproject([const rect3 value "
"(1.0 2.0 3.0 4.0 5.0 6.0) ], 1, 3)</text--->"
"<text></text--->"
") )";
const string RectangleSpecMinD =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" \"Remarks\")"
"( <text>(rect<d> x int) -> real</text--->"
"<text>minD( rect , d )</text--->"
"<text>Return the minimum value of the object's bounding box with "
"respect to the Dth dimension. "
"1 <= d <= D.</text--->"
"<text>query minD([const rect3 value "
"(1.0 2.0 3.0 4.0 5.0 6.0) ], 2)</text--->"
"<text></text--->"
") )";
const string RectangleSpecMaxD =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" \"Remarks\")"
"( <text>(rect<d> x int) -> real</text--->"
"<text>maxD( rect , d )</text--->"
"<text>Return the maximum value of the value's bounding box "
"with respect to the Dth dimension. "
"1 <= d <= D.</text--->"
"<text>query maxD([const rect3 value "
"(1.0 2.0 3.0 4.0 5.0 6.0) ], 2)</text--->"
"<text></text--->"
") )";
const string RectangleSpecBbox =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" \"Remarks\")"
"( <text>rect<d> -> rect<d></text--->"
"<text>bbox( rect )</text--->"
"<text>Returns the minimum bounding box of the n-dimensional rectangle "
"'rect', which is a clone of the argument.</text--->"
"<text>query bbox([const rect3 value "
"(1.0 2.0 3.0 4.0 5.0 6.0) ], 2)</text--->"
"<text></text--->"
") )";
const string RectangleSpecEnlargeRect =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" \"Remarks\")"
"( <text>rect<d> x real^d -> rect<d></text--->"
"<text>enlargeRect( rect, m1, ... , md )</text--->"
"<text>Enlarges (shrinks) the rectangle by a value mi to each side "
"in each dimension.</text--->"
"<text>query enlargeRect([const rect3 value "
"(1.0 2.0 3.0 4.0 5.0 6.0) ], 2.0, 3.0, -1.0)</text--->"
"<text></text--->"
") )";
const string RectangleSpecSize =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" \"Remarks\")"
"( <text>rect<d> -> real</text--->"
"<text>size( rect )</text--->"
"<text>Caculates the rectangle's area (resp. D-dimensional volume)."
"</text--->"
"<text>query size([const rect3 value "
"(1.0 2.0 3.0 4.0 5.0 6.0) ], 2.0, 3.0, -1.0)</text--->"
"<text></text--->"
") )";
const string scalerectSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" \"Remarks\")"
"( <text>rect<d> x real^d -> rect<d></text--->"
"<text>scaleRect( rect, f1, ... , fd )</text--->"
"<text>scale the rectangle by the factor given for "
" each dimension.</text--->"
"<text>query scalerect([const rect3 value "
"(1.0 2.0 3.0 4.0 5.0 6.0) ], 1.0, 1.0, 2.0)</text--->"
"<text></text--->"
") )";
const string RectangleSpecBboxIntersects =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>(rect<D1> x rect<D2>) -> bool </text--->"
"<text>_ bboxintersects _</text--->"
"<text>Tests, whether the projections of both rectangles to their "
"first min{D1mD2} dimensions intersect.</text--->"
"<text>query rect1 bboxintersects rect</text--->"
") )";
const string RectangleSpecToprightclass =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" \"Remarks\")"
"( <text>(rect<d> x rect<d>) -> int</text--->"
"<text>toprightclass( _ , _ )</text--->"
"<text>returns the Top-Right-Class Value of two rectangles. "
"whereat the first rect references the second one: "
"Scoring 2 if the first rect intersects the Top-Edge "
"of the second rect,"
"scoring 1 for Right-Edge intersection,"
"scoring 3 for both "
"and scoring 0 for none of this.</text--->"
"<text>query toprightclass(rect1, rect2)</text--->"
"<text></text--->"
") )";
/*
4.5.3 Definition of the operators
*/
Operator rectangleisempty( "isempty",
RectangleSpecIsEmpty,
4,
rectangleisemptymap,
RectangleUnarySelect,
RectTypeMapBool );
Operator rectangleequal( "=",
RectangleSpecEqual,
4,
rectangleequalmap,
RectangleBinarySelect,
RectRectTypeMapBool );
Operator rectanglenotequal( "#",
RectangleSpecNotEqual,
4,
rectanglenotequalmap,
RectangleBinarySelect,
RectRectTypeMapBool );
Operator rectangleintersects( "intersects",
RectangleSpecIntersects,
4,
rectangleintersectsmap,
RectangleBinarySelect,
RectRectTypeMapBool );
Operator rectangleinside( "inside",
RectangleSpecInside,
4,
rectangleinsidemap,
RectangleBinarySelect,
RectRectTypeMapBool );
Operator rectangleunion( "union",
RectangleSpecUnion,
4,
rectangleunionmap,
RectangleBinarySelect,
RectRectTypeMapRect );
Operator rectangleintersection( "intersection",
RectangleSpecIntersection,
4,
rectangleintersectionmap,
RectangleBinarySelect,
RectRectTypeMapRect );
Operator rectangletranslate( "translate",
RectangleSpecTranslate,
3,
rectangletranslatemap,
RectangleUnarySelect,
TranslateTypeMap );
Operator rectanglerectangle1( "rectangle1",
RectangleSpecRectangle1,
2,
rectanglerectangle1map,
RectangleSelect<1>,
RectangleTypeMap<1> );
Operator rectanglerectangle2( "rectangle2",
RectangleSpecRectangle2,
2,
rectanglerectangle2map,
RectangleSelect<2>,
RectangleTypeMap<2> );
Operator rectanglerectangle3( "rectangle3",
RectangleSpecRectangle3,
2,
rectanglerectangle3map,
RectangleSelect<3>,
RectangleTypeMap<3> );
Operator rectanglerectangle4( "rectangle4",
RectangleSpecRectangle4,
2,
rectanglerectangle4map,
RectangleSelect<4>,
RectangleTypeMap<4> );
Operator rectanglerectangle8( "rectangle8",
RectangleSpecRectangle8,
2,
rectanglerectangle8map,
Rectangle8Select<8>,
Rectangle8TypeMap<8> );
Operator rectangledistance( "distance",
RectangleSpecDistance,
4,
rectangledistancemap,
RectangleBinarySelect,
RectRectTypeMapReal );
Operator rectangletoprightclass( "toprightclass",
RectangleSpecToprightclass,
4,
rectangletoprightclassmap,
RectangleBinarySelect,
RectRectTypeMapInt );
Operator rectanglerectproject( "rectproject",
RectangleSpecRectproject,
4,
rectanglerectprojectmap,
RectangleUnarySelect,
RectProjectTypeMap );
Operator rectangleminD( "minD",
RectangleSpecMinD,
5,
rectangleMinDmap,
RectangleMinMaxDSelect,
RectangleMinMaxTypeMap );
Operator rectanglemaxD( "maxD",
RectangleSpecMaxD,
4,
rectangleMaxDmap,
RectangleMinMaxDSelect,
RectangleMinMaxTypeMap );
Operator rectanglebbox( "bbox",
RectangleSpecBbox,
4,
rectangleBboxmap,
RectangleUnarySelect,
RectangleTypeMapRectRect );
Operator rectangleextendrect( "enlargeRect",
RectangleSpecEnlargeRect,
4,
rectangleEnlargeRectmap,
RectangleUnarySelect,
RectangleTypeMapEnlargeRect );
Operator rectanglesize( "size",
RectangleSpecSize,
4,
rectangleSizemap,
RectangleUnarySelect,
RectTypeMapReal );
Operator scalerect( "scalerect",
scalerectSpec,
4,
scalerectMap,
RectangleUnarySelect,
scalerectTypeMap );
Operator rectanglebboxintersects( "bboxintersects",
RectangleSpecBboxIntersects,
16,
rectanglebboxintersectsmap,
RectangleBinarySelect1,
RectangleTypeMapBool2 );
struct cellnumber_Info : OperatorInfo {
cellnumber_Info() : OperatorInfo()
{
name = "cellnumber";
signature =
"rect x real x real x real x real x int -> stream(int)\n"
"rect3 x real x real x real x real x real x real x int x int"
"-> stream(int)\n"
"rect x cellgrid2d -> stream(int)\n"
"rect3 x cellgrid3d -> stream(int)";
syntax = "cellnumber( box, x0, y0, [z0,] wx, wy, [wz,] nx, [ny] )";
meaning = "Returns a stream of numbers of all cells intersected by box "
"with respect to a regular 2D- [3D-] grid starting at (x0,y0 [,z0]) and"
"--- for positive widths --- extending to the first quadrant (octant). "
"Each cell has widths wx, wy [and wz]. nx [and ny] determine the "
"grid's number of columns [and rows] available in the grip. The grid "
"is one-side unbounded in the remaining dimension. Cell numbering "
"starts in the lower left corner.";
}
};
struct gridintersects_Info : OperatorInfo {
gridintersects_Info() : OperatorInfo()
{
name = "gridintersects";
signature =
"real x real x real x real x int x rect x rect -> bool\n"
"real x real x real x real x real x real x int x int "
"x rect3 x rect3 x int -> bool\n"
"cellgrid2d x rect x rect x int ->bool\n"
"cellgrid3d x rect3 x rect3 x int ->bool";
syntax = "op ( x0, y0, [z0,] wx, wy, [wz,] nx, [ny,] box1, box2)";
meaning = "Return whether the current cell is "
"the smallest common grid cell overlapped by these two rectangles. For "
"comments on grid specification see operator 'cellnumber'.";
}
};
OperatorInfo GridCell2Rect_INFO(
"gridcell2rect",
"int x real x real x real x real x int -> rect\n"
"int x real x real x real x real x real x real x int x int -> rect3",
"gridcell2rect(cellno , x0, y0, [, z0] wx, wy [, wz], nx [, ny] )",
"Given a cell number and a grid description, return a rectangle"
"representing that cell. If any parameter is UNDEF, or cellno is an invalid"
"cell number (cellno>0), the result is UNDEF.",
""
);
Operator gridcell2rect( GridCell2Rect_INFO,
GridCell2Rect_VM,
GridCell2Rect_Select,
GridCell2Rect_TM
);
struct toprightreport_Info : OperatorInfo {
toprightreport_Info() : OperatorInfo()
{
name = "toprightreport";
signature =
"int x int -> bool\n";
syntax = "toprightreport(int1, int2)";
meaning = "Return TRUE if the bitwise logical and "
"of the two integers is false for all bit positions. "
"Otherwise FALSE is returned.";
}
};
/*
3.27 partitionRect
This operator devides a rectangle into x [*] y pieces as a regular grid.
So, a call partionRect(R,x,y) will create a grid of size x[*]y where the
rectanglesi (grid cells) are regular, semi-disjoint (may share borders) and cover R.
3.27.1 Type Mapping
Signature: rect x int x int -> stream(rect)
*/
ListExpr partitionRectTM(ListExpr args){
string err = "rect x int x int expected";
if(!nl->HasLength(args,3)){
return listutils::typeError(err);
}
if(!Rectangle<2>::checkType(nl->First(args)) ||
!CcInt::checkType(nl->Second(args)) ||
!CcInt::checkType(nl->Third(args))){
return listutils::typeError(err);
}
return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
nl->SymbolAtom(Rectangle<2>::BasicType()));
}
/*
3.27.2 Value Mapping
The value mapping is more generic than the type mapping. It can anly any
dimension.
3.27.2.1 LocalInfo
*/
template<int dim>
class PartitionRectInfo{
public:
PartitionRectInfo(Rectangle<dim>* r, Word* args){
rect = r;
numbers = 0;
currentNumbers = 0;
if(!rect->IsDefined()){
rect = 0;
return;
}
numbers = new int[dim];
for(int i=0;i<dim && rect!=0; i++){
CcInt* ci = (CcInt*) args[i].addr;
if(!ci->IsDefined()){
rect = 0;
} else {
int n = ci->GetValue();
if(n<=0){
rect = 0;
} else {
numbers[i] = n;
}
}
}
if(rect==0){
delete[] numbers;
numbers = 0;
return;
}
currentNumbers = new int[dim];
for(int i=0;i<dim;i++){
currentNumbers[i] = 0;
}
}
~PartitionRectInfo(){
if(numbers){
delete[] numbers;
}
if(currentNumbers){
delete[] currentNumbers;
}
}
Rectangle<dim>* nextRect(){
if(!rect){
return 0;
}
if(currentNumbers[dim-1] == numbers[dim-1]) { // all rectangles created
rect = 0;
return 0;
}
// create the output rectangle
double min[dim];
double max[dim];
for(int i=0;i<dim;i++){
min[i] = getPos(i,currentNumbers[i] , numbers[i]);
max[i] = getPos(i,currentNumbers[i] + 1, numbers[i]);
}
Rectangle<dim>* result = new Rectangle<dim>(true,min,max);
// increase the numbers
double found = false;
int pos = 0;
while(!found){
currentNumbers[pos]++;
if(currentNumbers[pos] == numbers[pos]){
if(pos<dim-1){
currentNumbers[pos] = 0;
}
pos++;
found = pos == dim;
} else {
found = true;
}
}
return result;
}
private:
Rectangle<dim>* rect;
int* numbers;
int* currentNumbers;
double getPos(int d, int cur, int end){
double min = rect->MinD(d);
double max = rect->MaxD(d);
double length = max - min;
return min + (length * (double)cur) / (double) end;
}
};
/*
27.2.2.2 Value Mapping
*/
template<int dim>
int partitionRectVM(Word* args, Word& result,
int message, Word& local, Supplier s){
PartitionRectInfo<dim>* li = (PartitionRectInfo<dim>*) local.addr;
switch(message){
case OPEN : {
if(li){
delete li;
}
local.addr = new
PartitionRectInfo<dim>((Rectangle<dim>*)args[0].addr,
&args[1]);
return 0;
}
case REQUEST : {
if(!li) {
return CANCEL;
}
result.addr = li->nextRect();
return result.addr?YIELD:CANCEL;
}
case CLOSE : {
if(li){
delete li;
local.addr = 0;
}
return 0;
}
}
return -1;
}
/*
27.2.3 Specification
*/
const string partitionRectSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" \"Remarks\")"
"( <text>rect x int x int -> stream(rect)</text--->"
"<text>partitionRect(r,x,y)</text--->"
"<text>iCreates a regular x * y grid from r. "
"</text--->"
"<text>query partitionRect(BGrenzenLine, 3,3) count = 9</text--->"
"<text></text--->"
") )";
/*
27.3.3 Operator instance
*/
Operator partitionRect( "partitionRect",
partitionRectSpec,
partitionRectVM<2>,
Operator::SimpleSelect,
partitionRectTM);
/*
28 Operator ~extendGeo~
This operator extends an rectangle with about x meters if the rectangle
is given in geo coordinates.
*/
ListExpr extendGeoTM(ListExpr args){
string err = "rect x {real,int} or "
"rect3 x {real,int} [x {real,int} expected";
if(!nl->HasLength(args,2) && !nl->HasLength(args,3)){
return listutils::typeError(err+" (invalid number of args)");
}
if( !CcInt::checkType(nl->Second(args))
&&!CcReal::checkType(nl->Second(args))){
return listutils::typeError(err + " (invalid type in 2nd arg.)");
}
if(Rectangle<2>::checkType(nl->First(args))){
if(!nl->HasLength(args,2)){
return listutils::typeError("for a rect only one further "
"argument is allowed");
}
return nl->First(args);
}
if(!Rectangle<3>::checkType(nl->First(args))){
return listutils::typeError("the first arg must be "
"of type rect or rect3");
}
if(nl->HasLength(args,3)){
if( !CcInt::checkType(nl->Third(args))
&&!CcReal::checkType(nl->Third(args))){
return listutils::typeError(err + " (invalid type in 3nd arg.)");
}
return nl->First(args);
}
// rect3 with one further argument
return nl->ThreeElemList(nl->SymbolAtom(Symbols::APPEND()),
nl->OneElemList(nl->RealAtom(0.0)),
nl->First(args));
}
static double earthradius = 6378137.0; // eath radius in meters
static double earthperimeter = 2.0*M_PI*earthradius;
template<class R, class E, class E2>
int extendGeoVMT(Word* args, Word& result,
int message, Word& local, Supplier s){
R* rect = (R*) args[0].addr;
E* Eps = (E*) args[1].addr;
result = qp->ResultStorage(s);
R* res = (R*) result.addr;
if(!rect->IsDefined() || !Eps->IsDefined()){
res->SetDefined(0);
return 0;
}
double minX = rect->MinD(0);
double maxX = rect->MaxD(0);
double minY = rect->MinD(1);
double maxY = rect->MaxD(1);
if(minX < -180 || maxX>180 || minY<-90 || maxY>90){
res->SetDefined(false);
return 0;
}
double eps = Eps->GetValue();
// the distances in y-direction are proportional to the
// latitude, 1 degree has earthperimeter / 360 meter
double dy = (360 * eps) / earthperimeter;
minY -= dy;
maxY += dy;
if(minY >= maxY){
res->SetDefined(false);
return 0;
}
// take the y-value nearer to the aquator
double ay = std::abs(minY) < std::abs(maxY)? minY : maxY;
ay = (ay * M_PI)/180.0;
double k = std::cos(ay);
if(k==0){
res->SetDefined(false);
return 0;
}
double dx = dy / std::cos(ay);
minX -= dx;
maxX += dx;
if(minX>=maxX){
res->SetDefined(false);
return 0;
}
if(R::GetDim()==2){
double Min[] = {minX,minY};
double Max[] = {maxX,maxY};
res->Set(true,Min,Max);
return 0;
}
// 3d version
E2* e2 = (E2*) args[2].addr;
if(!e2->IsDefined()){
res->SetDefined(false);
return 0;
}
double e = e2->GetValue();
double minZ = rect->MinD(2);
double maxZ = rect->MaxD(2);
minZ -= e;
maxZ += e;
if(minZ>=maxZ){
res->SetDefined(false);
return 0;
}
double Min[] = {minX,minY,minZ};
double Max[] = {maxX,maxY,maxZ};
res->Set(true,Min,Max);
return 0;
}
ValueMapping extendGeoVM[] = {
extendGeoVMT<Rectangle<2>,CcInt,CcInt>, //3rd arg does'n matter
extendGeoVMT<Rectangle<2>,CcReal,CcInt>, // for rectangle 2D
extendGeoVMT<Rectangle<3>, CcInt, CcInt>,
extendGeoVMT<Rectangle<3>, CcInt, CcReal>,
extendGeoVMT<Rectangle<3>, CcReal, CcInt>,
extendGeoVMT<Rectangle<3>, CcReal, CcReal>
};
int extendGeoSelect(ListExpr args){
if(Rectangle<2>::checkType(nl->First(args))){
return CcInt::checkType(nl->Second(args))?0:1;
}
// rectangle 3 version
int offset = 2;
int n1 = CcInt::checkType(nl->Second(args))?0:2;
int n2 = 1; // default for not present value is real
if(nl->HasLength(args,3)){
n2 = CcInt::checkType(nl->Third(args))?0:1;
}
return offset + n1 + n2;
}
OperatorSpec extendGeoSpec(
" rext x {int,real} -> rect || rect3 x {int,real} [ x {int,real] -> rect3 ",
" _ extendGeo [_,_] ",
" Extends a rectangle using geographic coordinates "
" approximative with a border given in meters. For a 3 dimensional rectangle,"
"the first two dimensions are extended in this way, the third diemsnion is"
" extended by the given optional value or 0 if not present.",
" query bbox(geoobj) extendGeo[300]"
);
Operator extendGeoOp(
"extendGeo",
extendGeoSpec.getStr(),
6,
extendGeoVM,
extendGeoSelect,
extendGeoTM
);
/*
Operator perimeter
*/
ListExpr perimeterTM(ListExpr args){
if(!nl->HasLength(args,1)){
return listutils::typeError("one arg expected");
}
if(!Rectangle<2>::checkType(nl->First(args))){
return listutils::typeError("one arg expected");
}
return listutils::basicSymbol<CcReal>();
}
int perimeterVM(Word* args, Word& result,
int message, Word& local, Supplier s){
result = qp->ResultStorage(s);
Rectangle<2>* rect = (Rectangle<2>*) args[0].addr;
CcReal* res = (CcReal*) result.addr;
if(!rect->IsDefined()){
res->SetDefined(false);
return 0;
}
double p = 2* ( (rect->MaxD(0) - rect->MinD(0))
+ (rect->MaxD(1) - rect->MinD(1)));
res->Set(true,p);
return 0;
}
OperatorSpec perimeterSpec(
" rect -> real",
" perimeter(_)",
" Compuetes the perimeter of a rectangle.",
" query perimeter(bbox(thecenter))"
);
Operator perimeterOp(
"perimeter",
perimeterSpec.getStr(),
perimeterVM,
Operator::SimpleSelect,
perimeterTM
);
/*
Operator ~scale~
*/
ListExpr scaleTM(ListExpr args){
if(!nl->HasLength(args,2)){
return listutils::typeError("expected 2 arguments");
}
bool ok = false;
ListExpr a1 = nl->First(args);
ok = ok || Rectangle<1>::checkType(a1);
ok = ok || Rectangle<2>::checkType(a1);
ok = ok || Rectangle<3>::checkType(a1);
ok = ok || Rectangle<4>::checkType(a1);
ok = ok || Rectangle<8>::checkType(a1);
if(!ok){
return listutils::typeError("first arg is not a rectangle "
"with supported dimension");
}
if(!CcInt::checkType(nl->Second(args))
&& !CcReal::checkType(nl->Second(args))){
return listutils::typeError("second arg must be of real or int");
}
return nl->First(args);
}
template<unsigned dim, class F>
int scaleVMT(Word* args, Word& result,
int message, Word& local, Supplier s){
result = qp->ResultStorage(s);
Rectangle<dim>* res = (Rectangle<dim>*) result.addr;
Rectangle<dim>* arg1 = (Rectangle<dim>*) args[0].addr;
F* sf = (F*) args[1].addr;
if(!sf->IsDefined() || !arg1->IsDefined()){
res->SetDefined(false);
return 0;
}
res->CopyFrom(arg1);
res->scale(sf->GetValue());
return 0;
}
ValueMapping scaleVM[] = {
scaleVMT<1,CcInt>,
scaleVMT<1,CcReal>,
scaleVMT<2,CcInt>,
scaleVMT<2,CcReal>,
scaleVMT<3,CcInt>,
scaleVMT<3,CcReal>,
scaleVMT<4,CcInt>,
scaleVMT<4,CcReal>,
scaleVMT<8,CcInt>,
scaleVMT<8,CcReal>
};
int scaleSelect(ListExpr args){
int n1 = -100;
int n2 = CcInt::checkType(nl->Second(args))?0:1;
ListExpr a1 = nl->First(args);
if( Rectangle<1>::checkType(a1)) n1 = 0;
else if(Rectangle<2>::checkType(a1)) n1 = 2;
else if(Rectangle<3>::checkType(a1)) n1 = 4;
else if(Rectangle<4>::checkType(a1)) n1 = 6;
else if(Rectangle<8>::checkType(a1)) n1 = 8;
return n1+n2;
}
OperatorSpec scaleSpec(
" rect? x {int,real} -> rect?",
" _ scale[_] ",
"Scales a rectangle uniformely into all dimensions.",
" query bbox(thecenter) scale[2] = bbox(thecenter scale[2.0])"
);
Operator scaleOp(
"scale",
scaleSpec.getStr(),
10,
scaleVM,
scaleSelect,
scaleTM
);
/*
5 Creating the Algebra
*/
class RectangleAlgebra : public Algebra
{
public:
RectangleAlgebra() : Algebra()
{
AddTypeConstructor( &rect1 );
rect1.AssociateKind(Kind::DATA());
rect1.AssociateKind(Kind::SPATIAL1D());
AddTypeConstructor( &rect );
rect.AssociateKind(Kind::DATA());
rect.AssociateKind(Kind::SPATIAL2D());
rect.AssociateKind(Kind::DELIVERABLE());
AddTypeConstructor( &rect3 );
rect3.AssociateKind(Kind::DATA());
rect3.AssociateKind(Kind::SPATIAL3D());
AddTypeConstructor( &rect4 );
rect4.AssociateKind(Kind::DATA());
rect4.AssociateKind(Kind::SPATIAL4D());
AddTypeConstructor( &rect8 );
rect8.AssociateKind(Kind::DATA());
rect8.AssociateKind(Kind::SPATIAL8D());
AddOperator( &rectangleisempty );
AddOperator( &rectangleequal );
AddOperator( &rectanglenotequal );
AddOperator( &rectangleintersects );
AddOperator( &rectangleinside );
AddOperator( &rectangleunion );
AddOperator( &rectangleintersection );
AddOperator( &rectangletranslate );
AddOperator( &rectangledistance );
AddOperator( &rectangletoprightclass);
AddOperator( &rectanglerectangle1 );
AddOperator( &rectanglerectangle2 );
AddOperator( &rectanglerectangle3 );
AddOperator( &rectanglerectangle4 );
AddOperator( &rectanglerectangle8 );
AddOperator( &rectanglerectproject );
AddOperator( &rectangleminD );
AddOperator( &rectanglemaxD );
AddOperator( &rectanglebbox );
AddOperator( &rectangleextendrect );
AddOperator( &rectangleextendrect );
AddOperator( &rectanglesize );
AddOperator( &scalerect);
AddOperator( &rectanglebboxintersects );
AddOperator(cellnumber_Info(), cellNumberVM, cellNumberTM);
AddOperator(gridintersects_Info(), gridIntersectsVM, gridIntersectsTM);
AddOperator( &gridcell2rect);
AddOperator( &partitionRect);
AddOperator( &extendGeoOp);
AddOperator( &perimeterOp);
AddOperator( &scaleOp);
AddOperator (toprightreport_Info(), toprightreportVM, toprightreportTM);
}
~RectangleAlgebra() {};
};
} // end of namespace rectangle
/*
6 Initialization
Each algebra module needs an initialization function. The algebra manager
has a reference to this function if this algebra is included in the list
of required algebras, thus forcing the linker to include this module.
The algebra manager invokes this function to get a reference to the instance
of the algebra class and to provide references to the global nested list
container (used to store constructor, type, operator and object information)
and to the query processor.
The function has a C interface to make it possible to load the algebra
dynamically at runtime.
*/
extern "C"
Algebra*
InitializeRectangleAlgebra( NestedList* nlRef, QueryProcessor* qpRef )
{
nl = nlRef;
qp = qpRef;
return (new rectangle::RectangleAlgebra());
}