Files
secondo/Algebras/Temporal/TemporalAlgebra.cpp
2026-01-23 17:03:45 +08:00

22485 lines
655 KiB
C++

/*
----
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}}]
//paragraph [10] Footnote: [{\footnote{] [}}]
//[TOC] [\tableofcontents]
//[bl] [\\]
[1] Implementation of Module
January 2004 Victor Almeida
March - April 2004 Zhiming Ding
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.
12.03.2006 Juergen Schmidt seperated the ~=~ and ~\#~ Operater
because of wrong syntax of these operators.
For T in (bool, int, real, point) it should be mT x mT -> mbool,
but it was mT x mT -> bool. The new operators ~equal~ and
~nonequal~ represents the old meaning. The operators with the
"right" syntax can be found in TemporalLiftedAlgebra.
(Some formating work is done to re-check in the algebra to cvs)
09.04.2006 seperated the ~isempty~ Operater
because of wrong syntax of this operators.
For T in (bool, int, real, point) it should be mT -> mbool with
TRUE as result if the argument is defined and FALSE when the
argument is not defined, but it was mT -> bool with TRUE when it is
defined somewhere in time. (The total implementation has been left in
place.)
The operator with the "right" syntax can be found in
TemporalLiftedAlgebra.
04.06.2009 Christian D[ue]ntgen
renamed ~bbox~: ~rT~ [->] ~rT~ to ~mbrange~: ~rT~ [->] ~rT~
Added operators ~bbox~:
~periods~ [->] ~rect3~, ~bbox~: ~instant~ [->] ~rect3~.
01.06.2006 Christian D[ue]ntgen added operator ~bbox~ for ~range~-types.
Sept 2006 Christian D[ue]ntgen implemented ~defined~ flag for unit types
Febr 2007 Christian D[ue]ntgen implemented ~bbox~ for mpoint and ipoint.
Added operator ~bbox2d~ to save time when creating spatial indexes
September 2009 Simone Jandt: UReal new Member CompUReal implemented.
29.09.2009 Mahmoud Sakr: Added the operators: delay, distancetraversed, and
mint2mbool
27.09.2010 Christian D[ue]ntgen added operator ~turns~.
30.11.2011 Mahmoud Sakr added operator ~when~.
[TOC]
1 Overview
This file contains the implementation of the type constructors ~instant~,
~range~, ~intime~, ~const~, and ~mapping~. The memory data structures
used for these type constructors are implemented in the TemporalAlgebra.h
file.
2 Defines, includes, and constants
*/
#include <cmath>
#include <limits>
#include <iostream>
#include <sstream>
#include <string>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include "Algebras/Spatial/LineT.h"
#include "Algebras/Spatial/LineTImpl.h"
#include "NestedList.h"
#include "QueryProcessor.h"
#include "Algebra.h"
#include "StandardTypes.h"
#include "Algebras/Spatial/SpatialAlgebra.h"
#include "PolySolver.h"
#include "Algebras/Relation-C++/RelationAlgebra.h"
#include <math.h>
#include "MMRTree.h"
#include <time.h>
#include "AlmostEqual.h"
#include "ListUtils.h"
#include "Symbols.h"
#include "Algebras/Geoid/GeoDist.h"
#include "Algebras/MovingRegion/MovingRegionAlgebra.h"
#include "RefinementStream.h"
#include "Algebras/TemporalUnit/TemporalUnitAlgebra.h"
#include "DateTime.h"
#include "TemporalAlgebra.h"
#include "GenericTC.h"
#include "GenOps.h"
#include "Stream.h"
#include "Algebras/Spatial/DLine.h"
#include "Algebras/SymbolicTrajectoryBasic/SymbolicTrajectoryBasicAlgebra.h"
extern NestedList* nl;
extern QueryProcessor* qp;
using namespace datetime;
namespace temporalalgebra{
#ifdef SECONDO_WIN32
double asinh(double z)
{
return log(z + sqrt(z*z +1));
}
bool isnan(double x)
{
return ((x!=x) || ((x==1) && (x == 0)));
}
#endif
static int counter;
std::string int2string(const int& number)
{
std::ostringstream oss;
oss << number;
return oss.str();
}
double roundToNPlaces(const double value, const int noPlaces) {
double places = pow(10.0, noPlaces);
return round(value * places) / places;
}
bool IsMaximumPeriods(const Periods& p)
{
if(p.GetNoComponents() != 1) return false;
Interval<Instant> I;
p.Get(0, I);
return (I.start.IsMinimum() && I.end.IsMaximum());
}
/*
1.1 Definition of some constants
*/
const bool TA_DEBUG = false; // debugging off
// const bool TA_DEBUG = true; // debugging on
const double MAXDOUBLE = std::numeric_limits<double>::max();
const double MINDOUBLE = -1.0 * std::numeric_limits<double>::max();
/*
3 Implementation of C++ Classes
3.1 Class ~UReal~
*/
template<class alpha>
std::ostream& operator<<(std::ostream& o, const Interval<alpha>& u){
return u.Print(o);
}
std::ostream& operator<<(std::ostream& o, const UPoint& u){
std::ios_base::fmtflags oldOptions = o.flags();
o.setf(std::ios_base::fixed,std::ios_base::floatfield);
o.precision(8);
if(!u.IsDefined()){
o << "Undefined";
} else {
o << "UPoint[" << u.timeInterval
<< ", " << u.p0 << ", " << u.p1 << "]";
}
o.flags(oldOptions);
return o;
}
void UReal::TemporalFunction( const Instant& t,
CcReal& result,
bool ignoreLimits ) const
{
if ( !this->IsDefined() ||
!t.IsDefined() ||
(!this->timeInterval.Contains( t ) && !ignoreLimits) )
{
result.Set(false, 0.0);
}
else
{
DateTime T2(durationtype);
T2 = t - timeInterval.start;
double t2 = T2.ToDouble();
double res = a * pow( t2, 2 ) +
b * t2 +
c;
if( r ){
if(res>=0.0){
res = sqrt( res );
} else {
if(res > -0.001){ // correction of rounding errors
res = 0.0;
} else {
cout << *this << endl << t << " " << res << endl;
assert(false);
}
}
}
result.Set( true, res );
}
}
bool UReal::Passes( const CcReal& val ) const
{
assert( IsDefined() && val.IsDefined() );
Periods times(2);
int no_res = PeriodsAtVal( val.GetRealval(), times);
for(int i=0; i<no_res; i++)
{
Interval<DateTime> iv;
times.Get(i, iv);
// only return true, iff the value is *REALLY* reached!
if( iv.Inside(timeInterval) )
return true;
}
return false;
}
bool UReal::At( const CcReal& val, TemporalUnit<CcReal>& result )
const
// CD - Implementation causes problem, as the result could be a set
// of 0-2 Units!
// Use UReal::PeriodAtValue() or UReal::AtValue() instead!
{
std::cerr << "UReal::At() is not implementable! "
"Use UReal::AtValue() instead!"
<< endl;
assert( false );
return false;
}
void UReal::AtInterval( const Interval<Instant>& i,
TemporalUnit<CcReal>& result ) const
{
UReal *pResult = (UReal*)&result;
if( !IsDefined() || !timeInterval.Intersects(i) ){
pResult->SetDefined( false );
return;
}
pResult->SetDefined(true);
TemporalUnit<CcReal>::AtInterval( i, result );
pResult->a = a;
pResult->b = b;
pResult->c = c;
pResult->r = r;
// Now, we need to translate the result to the starting instant
DateTime tmp = pResult->timeInterval.start;
tmp.SetType(durationtype);
double tx = -((timeInterval.start - tmp).ToDouble());
pResult->TranslateParab(tx);
}
// translate the parabolic/linear/constant curve within a ureal
// by (t) on the x/time-axes
// the ROOT flag is not considered at all!
void UReal::TranslateParab(const double& t)
{
c = a*pow(t,2) + b*t + c;
b = 2*a*t + b ;
// a = a;
if(timeInterval.start == timeInterval.end)
{
a = 0; b = 0;
}
if( r && (a==0.0) && (b==0.0) )
{
r = false;
if(c<0){
if( AlmostEqual(c,0.0) )
{
c = 0;
} else
{
bool valid= false;
assert(valid);
}
}
c = sqrt(c);
}
}
double AntiderivativeSQRTpoly2(const double a, const double b,
const double c, const double x)
{ // Bronstein, Taschenbuch der Mathematik 21.5.2.8 (245)
assert(a != 0);
double X = x*(a*x+b)+c;
double Delta = 4*a*c - b*b;
double h1 = 2*a*x+b;
double Xr = sqrt(X);
double t1 = (h1*Xr)/(4*a);
double f = 0.5*c - (b*b) / (8*a); // 1 / 2k
double t2 = 0;
// Bronstein (241)
double anti2;
//int ucase = -1;
if((a>0) && (Delta>0)) {
// ucase = 1;
//anti2 = (1/sqrt(a)) * asinh(h1 / sqrt(Delta));
//t2 = f*anti2;
t2 = (Delta / (8*pow(a,1.5))) * asinh(h1/sqrt(Delta));
} else if((a>0) && (Delta==0)){
// ucase = 2;
anti2 = (1/sqrt(a)) * log(h1);
t2 = f * anti2;
} else if((a<0) && (Delta<0)){
// ucase = 3;
anti2 = -1.0 * (1/ sqrt(-1.0*a)) * asin( h1 / sqrt(-1.0*Delta));
t2 = f * anti2;
} else if (a>0) { // && Delta < 0
// ucase = 4;
anti2 = (1 / sqrt(a)) * log ( 2.0 * sqrt(a*X) + h1);
t2 = f*anti2;
} else {
std::cerr << " invalid case reached " << endl;
anti2 = 0;
}
double result = t1 + t2;
/*
Unfortunately , small rounding errors in the anti2 computation
are often multiplied with very large numbers for (f) in many
datasets. This leads to very wrong results if these data are used.
For this reason, we compute the valid range of the result. If the
computed result is outside of this value, we approximate the integral
by the integral of a linear function between the values at the boundaries.
(the same as integrate(linearize2(unit))
*/
// compute the minimum and the maximum value
double xs = -1.0*b / (2*a);
double v1 = sqrt(c);
double v2 = sqrt(a*x*x+b*x+c);
double v3 = v1;
if(xs>0 && xs < x){
v3 = sqrt(a*xs*xs+b*xs+c);
} else {
xs = -1.0;
}
double min = v1;
if(v2 < min){
min = v2;
}
if(v3<min){
min = v3;
}
double max = v1;
if(v2 > max){
max = v2;
}
if(v3>max){
max = v3;
}
double minint = min*x;
double maxint = max*x;
if( (result < minint) || (result > maxint)){
//std::cerr << " approximate used case:" << ucase << endl;
if(xs<=0){ // approximate lineary between 0 and x
double h = (x==0)?0:(v2-v1)/x;
result = (0.5*h*x + v1)*x;
} else {
// integrate 0..xs
double h = (v3-v1)/x;
double res1 = (0.5*h*xs + v1)*xs;
// integrate xs .. x
double diff = x-xs;
h = (v2-v3)/diff;
double res2 = (0.5*h*diff+v3)*diff;
result = res1+res2;
}
if( (result < minint) || (result > maxint)){
std::cerr << " error in approximation " << endl;
std::cerr << " range is " << minint << " , " << maxint << endl;
std::cerr << " but result is " << result << endl;
}
}
return result;
}
double AntiderivativeSQRTpoly2new(const double a, const double b,
const double c, const double x, const int f) {
long double result = 0.0;
switch (f) {
case 0: { // Springer - Taschenbuch der Mathematik, 3rd edition, p. 161
long double Q = a * x * x + b * x + c;
long double D = 4.0 * a * c - b * b;
long double f1 = D / (8.0 * a);
long double f2 = 2 * a * x + b;
long double i1 = 0.0;
if (a > 0.0 && D < 0.0) {
i1 = 1.0 / sqrt(a) * log(2 * sqrt(a * Q) + f2);
}
else if (a > 0.0 && D > 0.0) {
i1 = 1.0 / sqrt(a) * asinh(f2 / sqrt(D));
}
else if (a > 0.0 && D == 0.0) {
i1 = 1.0 / sqrt(a) * log(f2);
}
else if (a < 0.0 && D < 0.0) {
i1 = -1.0 / sqrt(-a) * asin(f2 / sqrt(-D));
}
else { // invalid case
return 1.0 / 0.0; // nan
}
result = f2 * sqrt(Q) / (4.0 * a) + f1 * i1;
break;
}
case 1: { // mathe-online.at
long double f1 = b + 2.0 * a * x;
long double f2 = sqrt(c + x * (b + a * x));
long double f3 = b * b - 4.0 * a * c;
long double den = 8.0 * pow(a, 1.5);
long double l1 = log(f1 + 2.0 * sqrt(a) * f2);
result = (2.0 * sqrt(a) * f1 * f2 - f3 * l1) / den;
break;
}
case 2: { // integralrechner.de, 1st result
long double f1 = 4 * a * c - pow(b, 2);
long double sqr1 = x * (a * x + b) + c;
long double f2 = log(abs(2 * (sqrt(a) * sqrt(sqr1) + a * x) + b));
long double s2 = 2 * sqrt(f1) * (2 * a * x + b) * sqrt(a * sqr1 / f1);
long double den = 8 * pow(a, 1.5);
result = (f1 * f2 + s2) / den;
break;
}
case 3: { // integralrechner.de, 2nd result
long double f1 = 4 * pow(a, 2) * c - a * pow(b, 2);
long double f2 = asinh((2 * a * x + b) / sqrt(4 * a * c - pow(b, 2)));
long double f3 = 4 * pow(a, 2.5) * x + 2 * pow(a, 1.5) * b;
long double f4 = sqrt(a * pow(x, 2) + b * x + c);
long double den = 8 * pow(a, 2.5);
result = (f1 * f2 + f3 * f4) / den;
break;
}
default: {
assert(false);
return -1.0;
}
}
return result;
}
// integrate an ureal over its deftime
// Precondition: this is defined
double UReal::Integrate() const
{
assert ( IsDefined() );
double t = (timeInterval.end - timeInterval.start).ToDouble();
if(!r) { // simple case without square root
// form: ax^2 + bx + c
return a*t*t*t/3.0 + 0.5*b*t*t + c*t;
}
// square root
if ( a == 0.0 && b == 0.0)
{ // form: sqrt(c)
return sqrt(c) * t;
}
if ( a == 0.0 && b != 0.0 )
{ // form : sqrt(bx + c)
double X = b*t+c;
return (2/ (3*b))* sqrt(X*X*X);
}
// form : sqrt ( ax^2 + bx + c)
double antiderivValueStart = AntiderivativeSQRTpoly2new(a, b, c,
timeInterval.start.ToDouble(), 0);
double antiderivValueEnd = AntiderivativeSQRTpoly2new(a, b, c,
timeInterval.end.ToDouble(), 0);
double res = antiderivValueEnd - antiderivValueStart;
// if (res < 0.0) {
// cout << " (1) NEGATIVE difference: " << antiderivValueEnd << " - "
// << antiderivValueStart << " = " << res << endl;
// }
// if (isnan(antiderivValueStart)) {
// cout << " (1) NaN found at START " << timeInterval.start.ToDouble()
// << endl;
// }
// if (isnan(antiderivValueEnd)) {
// cout << " (1) NaN found at END " << timeInterval.end.ToDouble()
// << endl;
// }
// cout << " integral value is " << antiderivValueEnd << " - "
// << antiderivValueStart << " = " << res << endl;
return res;
}
/*
This function computes the maximum of this UReal.
*/
double UReal::Max(bool& correct) const{
if(!IsDefined()){
correct=false;
return 0.0;
}
double t = (timeInterval.end - timeInterval.start).ToDouble();
correct = true;
double v1 = c; // == TemporalFunction(t0);
double v2 = a*t*t + b*t + c; // TemporalFunction (t1);
double v3 = c; // value for extremum
if(!AlmostEqual(a,0)){
double ts = (-1.0*b)/(2.0*a);
if( (ts>0) && (ts < t)){
v3 = a*ts*ts + b*ts + c;
}
}
// debug
//if(isnan(v1) || isnan(v2) || isnan(v3)){
// cerr << " cannot determine the value within a unit" << endl;
//}
// determine the maximum of v1 .. v3
double max = v1;
if(v2>max){
max = v2;
}
if(v3 > max){
max = v3;
}
if(r){
return sqrt(max);
} else {
return max;
}
}
/*
This function computes the minimum of this UReal.
*/
double UReal::Min(bool& correct) const{
if(!IsDefined()){
correct=false;
return 0.0;
}
double t = (timeInterval.end - timeInterval.start).ToDouble();
correct = true;
double v1 = c; // == TemporalFunction(t0);
double v2 = a*t*t + b*t + c; // TemporalFunction (t1);
double v3 = c; // value for extremum
if(!AlmostEqual(a,0)){
double ts = (-1.0*b)/(2.0*a);
if( (ts>0) && (ts < t)){
// v3 = a*ts*ts + b*ts + c;
v3 = -0.25*b*b/a + c;
}
}
// debug
//if(isnan(v1) || isnan(v2) || isnan(v3)){
// cerr << "UReal::Min(): cannot determine the value within a unit"
// << endl;
//}
// determine the minimum of v1 .. v3
double min = v1;
if(v2<min){
min = v2;
}
if(v3 < min){
min = v3;
}
if(r){
if(min<0){
return 0;
}
return sqrt(min);
} else {
return min;
}
}
/*
Replaces this uReal by a linear approximation between the value at the start
and the end.
*/
void UReal::Linearize(UReal& result) const{
if(!IsDefined()){
result.SetDefined(false);
return;
}
CcReal V;
TemporalFunction(timeInterval.start,V,true);
double v1 = V.GetRealval();
TemporalFunction(timeInterval.end,V,true);
double v2 = V.GetRealval();
result = UReal(timeInterval,v1,v2);
}
/*
Computes a linear approximation of this ureal.
If the extremum of the represented function is contained in
the corresponding interval, the unit is split into two ones.
*/
void UReal::Linearize(UReal& result1, UReal& result2) const{
if(!IsDefined()){
result1.SetDefined(false);
result2.SetDefined(false);
return;
}
if((a==0) && !r){ // already linear
result1.CopyFrom(this);
result2.SetDefined(false);
return;
}
CcReal V;
TemporalFunction(timeInterval.start,V,true);
double v1 = V.GetRealval();
TemporalFunction(timeInterval.end,V,true);
double v2 = V.GetRealval();
if( a==0 ) { // sqrt of a linear function
result1 = UReal(timeInterval,v1,v2);
result1.SetDefined(true);
result2.SetDefined(false);
return;
}
double xs = (-1.0*b) / (2.0*a);
Instant ixs(durationtype);
ixs.ReadFrom(xs); // convert the double into an instant
Instant ixst(instanttype);
ixst = timeInterval.start + ixs; // translate into the interval
if( (ixst <= timeInterval.start) || (ixst>=timeInterval.end) ||
ixst.Adjacent(&timeInterval.end)){
// extremum outside or very close to the bounds
result1 = UReal(timeInterval,v1,v2);
result1.SetDefined(true);
result2.SetDefined(false);
return;
}
// extremum found inside this interval
TemporalFunction(ixst,V,true);
double v3 = V.GetRealval();
Interval<Instant> interval1(
timeInterval.start,ixst,timeInterval.lc,true);
Interval<Instant> interval2(
ixst,timeInterval.end,false,timeInterval.rc);
result1 = UReal(interval1,v1,v3);
result1.SetDefined(true);
result2 = UReal(interval2,v3,v2);
result2.SetDefined(true);
}
/*
Sets the Periods value to the times, where this takes the
specified value. Returns the number of results (0-2).
WARNING: May return points, that are not inside this->timeInterval,
if a value is located at an open start/end instant.
*/
int UReal::PeriodsAtVal( const double& value, Periods& times) const
{
double inst_d[2]; // instants as double
int no_res = 0;
DateTime t0(durationtype), t1(instanttype);
Interval<Instant> iv;
//cout << "UReal::PeriodsAtVal("<< value << ", ...) called." << endl;
//cout << "\ta=" << a << " b=" << b << " c=" <<c<< " r=" <<r << endl;
//cout << "\tstart=" << timeInterval.start.ToDouble()
// << " end=" << timeInterval.end.ToDouble()
// << " lc=" << timeInterval.lc
// << " rc=" << timeInterval.rc << endl;
times.Clear();
if( !IsDefined() )
{
//cout<<"UReal::PeriodsAtVal(): Undefined UReal -> 0 results."<<endl;
times.SetDefined( false );
return 0;
}
times.SetDefined( true );
if( a==0.0 && b==0.0 )
// special case: constant ureal
{
// cout << "UReal::PeriodsAtVal(): constant case" << endl;
if ( (!r && AlmostEqual(c, value)) ||
(r && (AlmostEqual(sqrt(c), value)
|| AlmostEqual(c, value*value) ) ) )
{
times.StartBulkLoad();
times.Add(timeInterval);
times.EndBulkLoad();
//cout<<"UReal::PeriodsAtVal(): constant UReal -> 1 result." << endl;
return times.GetNoComponents();
}
else // no result
{
//cout<<"UReal::PeriodsAtVal(): constant UReal -> 0 results."<< endl;
return 0;
}
}
if( !r )
{
// cout << "UReal::PeriodsAtVal(): r==false" << endl;
no_res = SolvePoly(a, b, (c-value), inst_d, true);
}
else
{
// cout << "UReal::PeriodsAtVal(): r==true" << endl;
if (value < 0.0)
{
//cout<<"UReal::PeriodsAtVal(): radix cannot become <0. -> 0 results."
// << endl;
return 0;
}
else
no_res = SolvePoly(a, b, (c-(value*value)), inst_d, true);
}
// times.Print(cout);
// cout << "SolvePoly found no_res=" << no_res << " results."
//<< endl;
for(int i=0; i<no_res; i++)
{
// cout << "Processing inst_d[" << i << "]=" << inst_d[i] << endl;
t0.ReadFrom(inst_d[i]);
t1 = timeInterval.start + t0;
// cout << "\tt1=" << t1.ToDouble() << endl;
// cout << "\tt1.IsDefined()=" << t1.IsDefined() << endl;
if( (t1 == timeInterval.start) ||
(t1 == timeInterval.end) ||
timeInterval.Contains(t1) )
{
// cout << "\ttimes.IsValid()=" << times.IsValid() << endl;
if( !times.Contains( t1 ) )
{
iv = Interval<Instant>(t1, t1, true, true);
times.StartBulkLoad();
times.Add(iv); // add only once
times.EndBulkLoad();
}
// else
// cout << "UReal::PeriodsAtVal(): not added instant (doublet)" << endl;
}
// cout << "UReal::PeriodsAtVal(): not added instant (outside)" << endl;
}
// cout << "UReal::PeriodsAtVal(): Calculated "
// << times.GetNoComponents() << "results." << endl;
return times.GetNoComponents();
}
/*
Sets the Periods value to the times, where this takes the
minimum value. Returns the number of results (0-2).
WARNING: May return points, that are not inside this->timeInterval,
if a value is located at an open start/end instant.
*/
double UReal::PeriodsAtMin(bool& correct, Periods& times) const
{
times.Clear();
if( !IsDefined() )
{
correct = false;
times.SetDefined( false );
return std::numeric_limits<double>::infinity();
}
times.SetDefined( true );
double t = (timeInterval.end - timeInterval.start).ToDouble();
double ts = 0.0;
correct = true;
double min = std::numeric_limits<double>::infinity();
Interval<Instant> iv;
double v0 = c; // TemporalFunction(t0);
double v1 = a*t*t + b*t + c; // TemporalFunction(t1);
// TemporalFunction for extremum:
double v2 = std::numeric_limits<double>::infinity();
if(!AlmostEqual(a,0)){
ts = (-1.0*b)/(2.0*a);
if( (ts>0) && (ts < t)){
v2 = a*ts*ts + b*ts + c;
}
}
if(std::isnan(v0) || std::isnan(v1) || std::isnan(v2))
{
std::cerr << "UReal::Min(): cannot determine the value within a unit"
<< endl;
correct = false;
return std::numeric_limits<double>::infinity();
}
// determine the minimum of v0 .. v2
min = v0;
if(v1<min){
min = v1;
}
if(v2 < min){
min = v2;
}
if( AlmostEqual(a, 0.0) && AlmostEqual(b, 0.0))
{ // constant unit - return complete deftime
times.StartBulkLoad();
times.Add(timeInterval);
times.EndBulkLoad();
}
else // 1 or 2 minima
{
times.StartBulkLoad();
if(v0 <= min)
{
iv = Interval<Instant>(timeInterval.start,timeInterval.start,true,true);
times.Add(iv);
}
if(v1 <= min)
{
iv = Interval<Instant>(timeInterval.end,timeInterval.end,true,true);
times.Add(iv);
}
if(v2 <= min)
{
DateTime TS(durationtype);
TS.ReadFrom(ts);
DateTime T1(instanttype);
T1 = timeInterval.start + TS;
if( !(T1<timeInterval.start) && !(T1>timeInterval.end) )
{
iv = Interval<Instant>(T1,T1,true,true);
times.Add(iv);
}
}
times.EndBulkLoad();
}
// return the minimum value
correct = true;
return ( r ? sqrt(min) : min );
}
/*
Sets the Periods value to the times, where this takes the
maximum value. Returns the number of results (0-2).
WARNING: May return points, that are not inside this->timeInterval,
if a value is located at an open start/end instant.
*/
double UReal::PeriodsAtMax(bool& correct, Periods& times) const
{
times.Clear();
if( !IsDefined() )
{
correct = false;
times.SetDefined( false );
return -std::numeric_limits<double>::infinity();
}
times.SetDefined( true );
double t = (timeInterval.end - timeInterval.start).ToDouble();
double ts = 0.0;
correct = true;
double max = -std::numeric_limits<double>::infinity();
Interval<Instant> iv;
double v0 = c; // TemporalFunction(t0);
double v1 = a*t*t + b*t + c; // TemporalFunction(t1);
// TemporalFunction for extremum:
double v2 = -std::numeric_limits<double>::infinity();
if(!AlmostEqual(a,0)){
ts = (-1.0*b)/(2.0*a);
if( (ts>0) && (ts < t)){
v2 = a*ts*ts + b*ts + c;
}
}
if(std::isnan(v0) || std::isnan(v1) || std::isnan(v2)){
std::cerr << "UReal::Max(): cannot determine the value within a unit"
<< endl;
correct = false;
return std::numeric_limits<double>::infinity();
}
// determaxe the maximum of v0 .. v2
max = v0;
if(v1 > max){
max = v1;
}
if(v2 > max){
max = v2;
}
if( AlmostEqual(a, 0.0) && AlmostEqual(b, 0.0))
{ // constant unit - return complete deftime
times.StartBulkLoad();
times.Add(timeInterval);
times.EndBulkLoad();
}
else // 1 or 2 maxima
{
times.StartBulkLoad();
if(v0 >= max)
{
iv = Interval<Instant>(timeInterval.start,timeInterval.start,true,true);
times.Add(iv);
}
if(v1 >= max)
{
iv = Interval<Instant>(timeInterval.end,timeInterval.end,true,true);
times.Add(iv);
}
if(v2 >= max)
{
DateTime TS(durationtype);
TS.ReadFrom(ts);
DateTime T1(instanttype);
T1 = timeInterval.start + TS;
if( !(T1<timeInterval.start) && !(T1>timeInterval.end) )
{
iv = Interval<Instant>(T1,T1,true,true);
times.Add(iv);
}
}
times.EndBulkLoad();
}
// return the maximum value
correct = true;
return ( r ? sqrt(max) : max );
}
/*
Creates a vector of units, which are the restriction of this to
the periods, where it takes its minimum value.
*Precondition*: this[->]IsDefined()
*Result*: stores the resultununit into vector result and returns
the number of results (1-2) found.
*WARNING*: AtMin may return points, that are not inside this[->]timeInterval,
if a minimum is located at an open start/end instant.
*/
int UReal::AtMin(std::vector<UReal>& result) const
{
assert( IsDefined() );
result.clear();
bool correct = true;
Periods minTimesPeriods(2);
minTimesPeriods.Clear();
// double minVal = PeriodsAtMin(correct, minTimesPeriods);
PeriodsAtMin(correct, minTimesPeriods);
if(!correct)
return 0;
// cout << "UReal::AtMin(): minVal=" << minVal << endl;
for(int i=0; i<minTimesPeriods.GetNoComponents(); i++)
{
Interval<DateTime> iv;
minTimesPeriods.Get(i, iv);
UReal unit = UReal( *this );
correct = false;
if( iv.Inside(timeInterval) )
{
AtInterval( iv, unit );
correct = true;
}
else
{ // solve problem with min at open interval start/end!
if( (iv.start == timeInterval.start) || (iv.end == timeInterval.end) )
{
UReal unit2(
Interval<DateTime>(timeInterval.start, timeInterval.end, true, true),
a, b, c, r );
unit2.AtInterval( iv, unit );
correct = true;
}
}
if( correct )
result.push_back(unit);
else
std::cerr << "UReal::AtMin(): This should not happen!" << endl;
}
return result.size();
}
/*
Creates a vector of units, which are the restriction of this to
the periods, where it takes its maximum value.
*Precondition*: this[->]IsDefined()
*Result*: stores the resultununit into vector result and returns
the number of results (1-2) found.
*WARNING*: AtMax may return points, that are not inside this[->]timeInterval,
if a maximum is located at an open start/end instant.
*/
int UReal::AtMax( std::vector<UReal>& result) const
{
assert( IsDefined() );
result.clear();
bool correct = true;
Periods maxTimesPeriods(2);
maxTimesPeriods.Clear();
// double maxVal = PeriodsAtMax(correct, maxTimesPeriods);
PeriodsAtMax(correct, maxTimesPeriods);
if(!correct)
return 0;
// cout << "UReal::AtMax(): maxVal=" << maxVal << endl;
// cout << "timeInterval = (" << timeInterval.start.ToString() << " "
// << timeInterval.end.ToString() << " "
// << timeInterval.lc << " " << timeInterval.rc << ")" << endl;*/*/
for(int i=0; i<maxTimesPeriods.GetNoComponents(); i++)
{
Interval<DateTime> iv;
maxTimesPeriods.Get(i, iv);
// cout << "iv = (" << iv->start.ToString() << " " << iv->end.ToString()
// << " " << iv->lc << " " << iv->rc << ")" << endl;*/
UReal unit = UReal( *this );
correct = false;
if( iv.Inside(timeInterval) )
{
AtInterval( iv, unit );
correct = true;
}
else if( (iv.start==timeInterval.start) || (iv.end==timeInterval.end) )
{ // solve problem with max at open interval start/end!
UReal unit2(
Interval<DateTime>(timeInterval.start, timeInterval.end, true, true),
a, b, c, r );
unit2.AtInterval( iv, unit );
correct = true;
}
if( correct )
result.push_back(unit);
else
std::cerr << "UReal::AtMax(): This should not happen!" << endl;
}
return result.size();
}
/*
Creates a vector of units, which are the restriction of this to
the periods, where it takes a certain value.
*Precondition*: this[->]IsDefined() AND value.IsDefined()
*Result*: stores the resultununit into vector result and returns
the number of results (1-2) found.
*WARNING*: AtMax may return points, that are not inside this[->]timeInterval,
if a maximum is located at an open start/end instant.
*/
int UReal::AtValue(CcReal value, std::vector<UReal>& result) const
{
assert( IsDefined() && value.IsDefined() );
result.clear();
Periods valTimesPeriods(2);
int no_res = 0;
double theVal = value.GetRealval();
// cout << "UReal::AtVal(): theVal=" << theVal << endl;
no_res = PeriodsAtVal( theVal, valTimesPeriods );
for(int i=0; i<no_res; i++)
{
Interval<DateTime> iv;
valTimesPeriods.Get(i, iv);
// cout << (iv.lc ? "UReal::AtValue: iv=[ " : "iv=[ ")
// << iv.start.ToString() << " "
// << iv.end.ToString()
// << (iv.rc ? " ]" : " [") << endl;
UReal unit(true);
unit = UReal(iv, 0.0, 0.0, theVal, false); // making things easier...
// cout << " Unit = ";
// unit.Print(cout); cout << endl;
result.push_back(unit);
}
return result.size();
}
/*
Sets the Periods value to the times, where both UReals takes the
same value. Returns the number of results (0-2).
*/
int UReal::PeriodsAtEqual( const UReal& other, Periods& times) const
{
assert( IsDefined() );
assert( other.IsDefined() );
times.Clear();
if( !IsDefined() || !other.IsDefined() ){
times.SetDefined( false );
return 0;
}
times.SetDefined( true );
int no_res = 0;
double inst_d[4];
DateTime t0(durationtype), t1(instanttype);
Interval<Instant> iv;
Interval<Instant> commonIv;
UReal u1(true), u2(true), udiff(true);
if( !IsDefined() ||
!other.IsDefined() ||
!timeInterval.Intersects(other.timeInterval) )
return 0;
timeInterval.Intersection(other.timeInterval, commonIv);
// restrict units to common deftime
AtInterval(commonIv, u1);
other.AtInterval(commonIv, u2);
if( u1.r == u2.r &&
AlmostEqual(u1.a, u2.a) &&
AlmostEqual(u1.b, u2.b) &&
AlmostEqual(u1.c, u2.c) )
{ // case 0: U1 and U2 implement same function
times.StartBulkLoad();
times.Add(commonIv);
times.EndBulkLoad();
return 1;
}
if( u1.r == u2.r )
{ // case 1: r1 == r2 (use UReal::PeriodsAtVal(0.0,...))
udiff = UReal(commonIv, (u1.a-u2.a), (u1.b-u2.b), (u1.c-u2.c), u1.r);
return udiff.PeriodsAtVal(0.0, times);
}
// case 2: r1 != r2 similar, but solve Polynom of degree=4
// normalize, such that u1r==false and u2.r==true
if (u1.r)
{ udiff = u1; u1 = u2; u2 = udiff; }
// solve u1^2 = u2^2 <=> u1^2 - u2^2 = 0
double A = u1.a;
double B = u1.b;
double C = u1.c;
double D = u2.a;
double E = u2.b;
double F = u2.c;
no_res = SolvePoly(A*A,
2*A*B,
2*A*C+B*B-D,
2*B*C-E,
C*C-F,
inst_d);
for(int i=0; i<no_res; i++)
{
t0.ReadFrom(inst_d[i]);
t1 = commonIv.start + t0;
if( (t1 == commonIv.start) ||
(t1 == commonIv.end) ||
commonIv.Contains(t1) )
{
// cout << "\tt1=" << t1.ToDouble() << endl;
// cout << "\tt1.IsDefined()=" << t1.IsDefined() << endl;
// cout << "\ttimes.IsValid()=" << times.IsValid() << endl;
if( !times.Contains( t1 ) )
{
// cout << "UReal::PeriodsAtEqual(): add instant" << endl;
iv = Interval<Instant>(t1, t1, true, true);
times.StartBulkLoad();
times.Add(iv); // add only once
times.EndBulkLoad();
}
// else
// cout << "UReal::PeriodsAtEqual(): not added instant" << endl;
}
}
//cout << "UReal::PeriodsAtEqual(): Calculated "
// << times.GetNoComponents() << "results." << endl;
return times.GetNoComponents();
}
/*
Creates a vector of ubool, that cover the UReals common deftime and
indicate whether their temporal values are equal or not.
*Precondition*: this[->]IsDefined() AND value.IsDefined()
*Result*: stores the resultunit into vector result and returns
the number of results found.
*/
int UReal::IsEqual(const UReal& other, std::vector<UBool>& result) const
{
result.clear();
std::cerr << "UReal::IsEqual() Not Yet Implemented!" << endl;
return 0;
}
/*
Creates the absolute value for an UReal value.
~result~ may contain 0-3 UReal values.
*Precondition*: this[->]IsDefined()
*Result*: stores the resultunits into vector result and returns
the number of results.
*/
int UReal::Abs(std::vector<UReal>& result) const
{
assert( IsDefined() );
result.clear();
if( r )
{ // return the complete unit, as it should be positive
result.push_back(UReal(timeInterval, a, b, c, r));
return 1;
} // else: r == false
UReal newunit(true);
Interval<Instant>
iv(DateTime(0,0,instanttype), DateTime(0,0,instanttype), false, false),
ivnew(DateTime(0,0,instanttype), DateTime(0,0,instanttype), false, false);
Interval<Instant> actIntv;
Instant
start(instanttype),
end(instanttype),
testInst(instanttype);
Periods *eqPeriods;
std::vector< Interval<DateTime> > resPeriods;
int i=0, numEq=0, cmpres=0;
bool lc, rc;
CcReal fccr1(true, 0.0), fccr2(true,0.0);
// get times of intersection with time-axis
// for each interval generated: if <0 invert all parameters
resPeriods.clear();
eqPeriods = new Periods(4);
eqPeriods->Clear();
PeriodsAtVal( 0.0, *eqPeriods);
numEq = eqPeriods->GetNoComponents();// 1 instant herein (start==end)
// cout << " numEq=" << numEq << endl;
// divide deftime into a vector of intervals
if ( numEq == 0 )
{ // single result: complete timeInterval
resPeriods.push_back(timeInterval);
}
else
{ //otherwise: numEq > 0
// create periods value for single result units
start = timeInterval.start;
end = timeInterval.start;
lc = true;
rc = false;
for(i=0; i<numEq; i++)
{
rc = false;
eqPeriods->Get(i, actIntv);
end = actIntv.start;
if(start == timeInterval.start)
{ // truncate at beginning
lc = timeInterval.lc;
}
if(end == timeInterval.end)
{ // truncate at right end
rc = timeInterval.rc;
}
if( (start == end) && !(lc && rc) )
{ // invalid instant: skip
start = end;
lc = !rc;
continue;
}
ivnew = Interval<Instant>(start, end, lc, rc);
resPeriods.push_back(ivnew);
start = end;
lc = !rc;
}
// do last interval
if(end < timeInterval.end)
{ // add last interval
ivnew = Interval<Instant>(end, timeInterval.end, lc, timeInterval.rc);
resPeriods.push_back(ivnew);
}
else if( (end == timeInterval.end) &&
!rc &&
timeInterval.rc &&
(resPeriods.size()>0)
)
{ // close last interval
resPeriods[resPeriods.size()-1].rc = true;
}
}
// for each interval create one result unit
for(i=0; i< (int) resPeriods.size();i++)
{ // for each interval test, whether one has to invert it
AtInterval(resPeriods[i], newunit);
testInst = resPeriods[i].start
+ ((resPeriods[i].end - resPeriods[i].start) / 2);
TemporalFunction(testInst, fccr1, false);
cmpres = fccr1.Compare( &fccr2 );
if( cmpres < 0 )
{
newunit.a *= -1.0; newunit.b *= -1.0; newunit.c *= -1.0;
}
result.push_back(newunit);
}
eqPeriods->DeleteIfAllowed();
return result.size();
}
/*
Creates the distance to an other UReal value.
~result~ may contain 0-3 UReal values.
*Precondition*: this[->]IsDefined() AND other.IsDefined()
this[->]r $==$ other.r $==$ false
*Result*: stores the resultunits into vector result and returns
the number of results.
*/
int UReal::Distance(const UReal& other, std::vector<UReal>& result) const
{
assert( IsDefined() );
assert( other.IsDefined() );
assert( !r );
assert( !other.r );
result.clear();
if( timeInterval.Intersects(other.timeInterval) )
{
UReal ur1(true);
UReal ur2(true);
UReal diff(true);
Interval<Instant>
iv(DateTime(0,0,instanttype), DateTime(0,0,instanttype), true, true);
timeInterval.Intersection(other.timeInterval, iv);
AtInterval(iv, ur1);
other.AtInterval(iv, ur2);
diff.timeInterval = iv;
diff.a = ur1.a - ur2.a;
diff.b = ur1.b - ur2.b;
diff.c = ur1.c - ur2.c;
diff.r = false;
diff.Abs(result);
}
return result.size();
}
void UReal::CompUReal(UReal& ur2, int opcode, std::vector<UBool>& res)
{
UReal *u1 = this;
UReal *u2 = &ur2;
res.clear();
if ( !u1->IsDefined() ||!u2->IsDefined() ||
!u1->timeInterval.Intersects(u2->timeInterval))
{
return ;
}
// common deftime --> some result exists
UReal un1(true), un2(true);
UBool newunit(true);
Interval<Instant>
iv(DateTime(0,0,instanttype), DateTime(0,0,instanttype), false, false),
ivnew(DateTime(0,0,instanttype), DateTime(0,0,instanttype), false, false);
bool compresult, lc;
u1->timeInterval.Intersection(u2->timeInterval, iv);
u1->AtInterval(iv, un1);
u2->AtInterval(iv, un2);
if ( un1.r == un2.r &&
AlmostEqual(un1.a, un2.a) &&
AlmostEqual(un1.b, un2.b) &&
AlmostEqual(un1.c, un2.c))
{ // equal ureals return single unit: TRUE for =, <=, >=; FALSE otherwise
compresult = (opcode == 0 || opcode == 4 || opcode == 5);
newunit = UBool(iv, CcBool(true, compresult));
res.push_back(newunit);
return ;
}
Periods *eqPeriods = new Periods(4);
Interval<Instant> actIntv;
Instant start(instanttype), end(instanttype), testInst(instanttype);
int i, numEq, cmpres;
CcReal fccr1(true, 0.0), fccr2(true,0.0);
un1.PeriodsAtEqual(un2, *eqPeriods); // only intervals of length
numEq = eqPeriods->GetNoComponents();// 1 instant herein (start==end)
if ( numEq == 0 )
{ // special case: no equality -> only one result unit
testInst = iv.start + ((iv.end - iv.start) / 2);
un1.TemporalFunction(testInst, fccr1, false);
un2.TemporalFunction(testInst, fccr2, false);
cmpres = fccr1.Compare( &fccr2 );
compresult = ( (opcode == 0 && cmpres == 0) || // ==
(opcode == 1 && cmpres != 0) || // #
(opcode == 2 && cmpres < 0) || // <
(opcode == 3 && cmpres > 0) || // >
(opcode == 4 && cmpres <= 0) || // <=
(opcode == 5 && cmpres >= 0) );// >=
newunit = UBool(iv, CcBool(true, compresult));
res.push_back(newunit);
eqPeriods->DeleteIfAllowed();
return ;
}
// case: numEq > 0, at least one instant of equality
// iterate the Periods and create result units
start = iv.start; // the ending instant for the next interval
lc = iv.lc;
i = 0; // counter for instants of equality
eqPeriods->Get(i, actIntv);
// handle special case: first equality in first instant
if (start == actIntv.start)
{
if (iv.lc)
{
un1.TemporalFunction(un1.timeInterval.start, fccr1, false);
un2.TemporalFunction(un2.timeInterval.start, fccr2, false);
cmpres = fccr1.Compare( &fccr2 );
compresult = ( (opcode == 0 && cmpres == 0) ||
(opcode == 1 && cmpres != 0) ||
(opcode == 2 && cmpres < 0) ||
(opcode == 3 && cmpres > 0) ||
(opcode == 4 && cmpres <= 0) ||
(opcode == 5 && cmpres >= 0) );
ivnew = Interval<Instant>(start, start, true, true);
newunit = UBool(ivnew, CcBool(true, compresult));
res.push_back(newunit);
lc = false;
} // else: equal instant not in interval!
i++;
}
while ( i < numEq )
{
eqPeriods->Get(i, actIntv);
end = actIntv.start;
ivnew = Interval<Instant>(start, end, lc, false);
testInst = start + ((end - start) / 2);
un1.TemporalFunction(testInst, fccr1, false);
un2.TemporalFunction(testInst, fccr2, false);
cmpres = fccr1.Compare( &fccr2 );
compresult = ( (opcode == 0 && cmpres == 0) ||
(opcode == 1 && cmpres != 0) ||
(opcode == 2 && cmpres < 0) ||
(opcode == 3 && cmpres > 0) ||
(opcode == 4 && cmpres <= 0) ||
(opcode == 5 && cmpres >= 0) );
newunit = UBool(ivnew, CcBool(true, compresult));
res.push_back(newunit);
if ( !(end == iv.end) || iv.rc )
{
ivnew = Interval<Instant>(end, end, true, true);
compresult = (opcode == 0 || opcode == 4 || opcode == 5);
newunit = UBool(ivnew, CcBool(true, compresult));
res.push_back(newunit);
}
start = end;
i++;
lc = false;
}
if ( start < iv.end )
{ // handle teq[numEq-1] < iv.end
ivnew = Interval<Instant>(start, iv.end, false, iv.rc);
testInst = start + ((iv.end - start) / 2);
un1.TemporalFunction(testInst, fccr1, false);
un2.TemporalFunction(testInst, fccr2, false);
cmpres = fccr1.Compare( &fccr2 );
compresult = ( (opcode == 0 && cmpres == 0) ||
(opcode == 1 && cmpres != 0) ||
(opcode == 2 && cmpres < 0) ||
(opcode == 3 && cmpres > 0) ||
(opcode == 4 && cmpres <= 0) ||
(opcode == 5 && cmpres >= 0) );
newunit = UBool(ivnew, CcBool(true, compresult));
res.push_back(newunit);
}
eqPeriods->DeleteIfAllowed();
return ;
}
void UReal::Recompute(const UPoint& up1, const UPoint& up2, const Geoid* geoid){
Instant mid = up1.timeInterval.start +
(up1.timeInterval.end - up1.timeInterval.start) / 2;
double x1 = 0.0;
double x2 = ((up1.timeInterval.end - up1.timeInterval.start) / 2).ToDouble();
double x3 = (up1.timeInterval.end - up1.timeInterval.start).ToDouble();
Point pMid1(true), pMid2(true);
up1.TemporalFunction(mid, pMid1, true);
up2.TemporalFunction(mid, pMid2, true);
double y1 = up1.p0.Distance(up2.p0, geoid);
double y2 = pMid1.Distance(pMid2, geoid);
double y3 = up1.p1.Distance(up2.p1, geoid);
// cout << " " << up1 << ", " << up2 << "; Start: (" << x1 << ", " << y1
// << "), Mid: (" << x2 << ", " << y2 << "), End: (" << x3 << ", " << y3
// << ")" << endl;
if (AlmostEqual(x1, x2) || AlmostEqual(x2, x3)) {
a = 0.0;
b = 0.0;
c = 0.0;
r = false;
return;
}
std::vector<double> eq1 {std::pow(x1, 2), x1, 1.0, y1};
std::vector<double> eq2 {std::pow(x2, 2), x2, 1.0, y2};
std::vector<double> eq3 {std::pow(x3, 2), x3, 1.0, y3};
std::vector<double> eq4 {eq2[0]-eq1[0], eq2[1]-eq1[1], 0.0, eq2[3]-eq1[3]};
std::vector<double> eq5 {eq3[0]-eq1[0], eq3[1]-eq1[1], 0.0, eq3[3]-eq1[3]};
std::vector<double> eq6 = {eq4[0]-(eq4[1]/eq5[1])*eq5[0], 0.0, 0.0,
eq4[3]-(eq4[1]/eq5[1])*eq5[3]};
a = eq6[3] / eq6[0];
b = (eq4[3] - eq4[0] * a) / eq4[1];
c = eq1[3] - eq1[0] * a - eq1[1] * b;
// cout << "y = "<< a << "x^2 + " << b << "x + " << c << endl;
r = false;
}
void UReal::Split(const datetime::DateTime& duration,
std::vector<UReal>& result) const {
result.clear();
if (!IsDefined()) {
return;
}
UReal res(true);
datetime::DateTime durTemp(0, 0, datetime::durationtype);
datetime::DateTime durSrc(timeInterval.end - timeInterval.start);
Interval<Instant> iv;
while (durTemp < durSrc) {
iv.start = timeInterval.start + durTemp;
iv.end = iv.start + duration;
durTemp += duration;
if (durTemp > durSrc) {
iv.end -= durTemp - durSrc;
}
AtInterval(iv, res);
result.push_back(res);
}
}
/*
3.1 Class ~UPoint~
*/
void UPoint::TemporalFunction( const Instant& t,
Point& result,
bool ignoreLimits ) const
{
TemporalFunction(t, result, 0, ignoreLimits);
}
void UPoint::TemporalFunction( const Instant& t,
Point& result,
const Geoid* geoid,
bool ignoreLimits /*=false*/) const
{
if( !IsDefined() ||
!t.IsDefined() ||
(geoid && !geoid->IsDefined()) ||
(!timeInterval.Contains( t ) && !ignoreLimits) ){
result.SetDefined(false);
} else if( t == timeInterval.start ){
result = p0;
result.SetDefined(true);
} else if( t == timeInterval.end ){
result = p1;
result.SetDefined(true);
} else if(geoid){ // spherical geometry case
Instant t0 = timeInterval.start;
Instant t1 = timeInterval.end;
Coord f = ((t-t0)/(t1-t0));
result = p0.MidpointTo(p1, f, geoid);
} else {// euclidean geometry cases
Instant t0 = timeInterval.start;
Instant t1 = timeInterval.end;
double x = ((p1.GetX() - p0.GetX()) * ((t - t0) / (t1 - t0))) + p0.GetX();
double y = ((p1.GetY() - p0.GetY()) * ((t - t0) / (t1 - t0))) + p0.GetY();
result.Set( x, y );
result.SetDefined(true);
}
}
bool UPoint::Passes( const Point& p ) const
{
/*
VTA - I could use the spatial algebra like this
---- HalfSegment hs;
hs.Set( true, p0, p1 );
return hs.Contains( p );
----
but the Spatial Algebra admit rounding errors (floating point operations). It
would then be very hard to return a true for this function.
*/
assert( p.IsDefined() );
assert( IsDefined() );
if( (timeInterval.lc && AlmostEqual( p, p0 )) ||
(timeInterval.rc && AlmostEqual( p, p1 )) )
return true;
if( AlmostEqual( p0.GetX(), p1.GetX() ) &&
AlmostEqual( p0.GetX(), p.GetX() ) )
// If the segment is vertical
{
if( ( p0.GetY() <= p.GetY() && p1.GetY() >= p.GetY() ) ||
( p0.GetY() >= p.GetY() && p1.GetY() <= p.GetY() ) )
return true;
}
else if( AlmostEqual( p0.GetY(), p1.GetY() ) &&
AlmostEqual( p0.GetY(), p.GetY() ) )
// If the segment is horizontal
{
if( ( p0.GetX() <= p.GetX() && p1.GetX() >= p.GetX() ) ||
( p0.GetX() >= p.GetX() && p1.GetX() <= p.GetX() ) )
return true;
}
else
{
double k1 = ( p.GetX() - p0.GetX() ) / ( p.GetY() - p0.GetY() ),
k2 = ( p1.GetX() - p0.GetX() ) / ( p1.GetY() - p0.GetY() );
if( AlmostEqual( k1, k2 ) &&
( ( p0.GetX() < p.GetX() && p1.GetX() > p.GetX() ) ||
( p0.GetX() > p.GetX() && p1.GetX() < p.GetX() ) ) )
return true;
}
return false;
}
bool UPoint::Passes( const Point& val, const Geoid* geoid ) const {
if(!geoid){
return Passes( val );
} else {
UPoint result(false);
bool retval = At( val, result, geoid );
return retval && result.IsDefined();
}
}
bool UPoint::Passes( const Region& r ) const
{
assert( IsDefined() );
assert( r.IsDefined() );
if( AlmostEqual( p0, p1 ) )
return r.Contains( p0 );
HalfSegment hs( true, p0, p1 );
return r.Intersects( hs );
}
bool UPoint::Passes( const Rectangle<2> &rect ) const
{
assert( IsDefined() );
assert( rect.IsDefined() );
if( AlmostEqual( p0, p1 ) )
return p0.Inside(rect);
HalfSegment uHs( true, p0, p1 );
if( rect.Intersects( uHs.BoundingBox() ) )
{
if( p0.Inside(rect) || p1.Inside( rect) )
return true;
Point rP0(true, rect.MinD(0), rect.MinD(1));
Point rP1(true, rect.MaxD(0), rect.MinD(1));
Point rP2(true, rect.MaxD(0), rect.MaxD(1));
Point rP3(true, rect.MinD(0), rect.MaxD(1));
HalfSegment hs(true, rP0, rP1);
if( hs.Intersects( uHs ) ) return true;
hs.Set(true, rP1, rP2);
if( hs.Intersects( uHs ) ) return true;
hs.Set(true, rP2, rP3);
if( hs.Intersects( uHs ) ) return true;
hs.Set(true, rP3, rP1);
if( hs.Intersects( uHs ) ) return true;
}
return false;
}
bool UPoint::At( const Point& p, TemporalUnit<Point>& res ) const {
return At(p, res, 0);
}
bool UPoint::At( const Point& p,
TemporalUnit<Point>& res,
const Geoid* geoid ) const {
assert(p.IsDefined());
assert(this->IsDefined());
assert( !geoid || geoid->IsDefined() );
UPoint* result = static_cast<UPoint*>(&res);
*result = *this;
Instant t0 = timeInterval.start,
t1 = timeInterval.end;
if(AlmostEqual(p0,p1)){// special case: static unit
if(AlmostEqual(p,p0) || AlmostEqual(p,p1)){
result->SetDefined(true);
result->timeInterval = timeInterval;
result->p0 = p0;
result->p1 = p1;
return true;
} else {
result->SetDefined(false);
return false;
}
}
if(AlmostEqual(p0,p)){// special case p on p0
if(!timeInterval.lc){
result->SetDefined(false);
return false;
} else {
result->SetDefined(true);
result->p0 = p0;
result->p1 = p0;
result->timeInterval.lc = true;
result->timeInterval.rc = true;
result->timeInterval.start = t0;
result->timeInterval.end = t0;
return true;
}
}
if(AlmostEqual(p,p1)){// special case p on p1
if(!timeInterval.rc){
result->SetDefined(false);
return false;
} else {
result->SetDefined(true);
result->p0 = p1;
result->p1 = p1;
result->timeInterval.lc = true;
result->timeInterval.rc = true;
result->timeInterval.start = t1;
result->timeInterval.end = t1;
return true;
}
}
if(!geoid){// euclidean geometry case:
double d_x = p1.GetX() - p0.GetX();
double d_y = p1.GetY() - p0.GetY();
double delta;
bool useX;
if(fabs(d_x)> fabs(d_y)){
delta = (p.GetX()-p0.GetX() ) / d_x;
useX = true;
} else {
delta = (p.GetY()-p0.GetY() ) / d_y;
useX = false;
}
if(AlmostEqual(delta,0)){
delta = 0;
}
if(AlmostEqual(delta,1)){
delta = 1;
}
if( (delta<0) || (delta>1)){
result->SetDefined(false);
return false;
}
if(useX){ // check y-value
double y = p0.GetY() + delta*d_y;
if(!AlmostEqual(y,p.GetY())){
result->SetDefined(false);
return false;
}
} else { // check x-value
double x = p0.GetX() + delta*d_x;
if(!AlmostEqual(x,p.GetX())){
result->SetDefined(false);
return false;
}
}
Instant time = t0+(t1-t0)*delta;
result->SetDefined(true);
result->p0 = p;
result->p1 = p;
result->timeInterval.lc = true;
result->timeInterval.rc = true;
result->timeInterval.start = time;
result->timeInterval.end = time;
return true;
} else { // spherical geometry case:
// get possible LON for given LAT
double lonMinDEG = -1, lonMaxDEG = -1;
int numCross = p0.orthodromeAtLatitude( p1, p.GetY(),lonMinDEG, lonMaxDEG);
if(numCross<1){ // no crossing with given LON
result->SetDefined(false);
return false;
}
double dist01 = p0.Distance(p1, geoid);
double dist0cross = -1;
Instant tcross1(instanttype);
tcross1.SetDefined(false);
if(AlmostEqual(lonMinDEG,p.GetX())){ // calculate instant
dist0cross = p0.Distance(Point(true, lonMinDEG, p.GetX()),geoid);
tcross1 = t0 + (t1-t0)*(dist0cross/dist01);
tcross1.SetDefined(timeInterval.Contains(tcross1));
}
Instant tcross2(instanttype);
tcross2.SetDefined(false);
if( ( numCross>=2) && AlmostEqual(lonMinDEG,p.GetX()) ){
dist0cross = p0.Distance(Point(true, lonMaxDEG, p.GetX()),geoid);
tcross2 = t0 + (t1-t0)*(dist0cross/dist01);
tcross2.SetDefined(timeInterval.Contains(tcross2));
}
if( !tcross1.IsDefined() && !tcross2.IsDefined()){
result->SetDefined(false);
return false;
}
result->SetDefined(true);
result->p0 = p;
result->p1 = p;
result->timeInterval.lc = true;
result->timeInterval.rc = true;
result->timeInterval.start = tcross1.IsDefined()?tcross1:tcross2;
result->timeInterval.end = tcross1.IsDefined()?tcross1:tcross2;
return true;
}
}
void UPoint::At(const Rectangle<2>& rect, UPoint& result) const{
// both arguments have to be defined
if(!IsDefined() || !rect.IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined( true );
double minX = rect.MinD(0);
double minY = rect.MinD(1);
double maxX = rect.MaxD(0);
double maxY = rect.MaxD(1);
double x1 = p0.GetX();
double y1 = p0.GetY();
// check for stationary unit
if(AlmostEqual(p0,p1)){
if( (x1>=minX) && (x1<=maxX) && // rect contains point
(y1>=minY) && (y1<=maxY) ){
result = *this;
} else {
result.SetDefined(false);
}
return;
}
double x2 = p1.GetX();
double y2 = p1.GetY();
Instant s = timeInterval.start;
Instant e = timeInterval.end;
bool lc = timeInterval.lc;
bool rc = timeInterval.rc;
// clip vertical
if( ((x1 < minX) && (x2 < minX) ) ||
((x1 > maxX) && (x2 > maxX))) {
result.SetDefined(false);
return;
}
result = *this;
double dx = x2 - x1;
double dy = y2 - y1;
DateTime dt = e - s;
if((x1 < minX) || (x2 < minX) ) {
// trajectory intersects the left vertical line
double delta = (minX-x1)/dx;
double y = y1 + delta*dy;
Instant i = s + dt*delta;
// cut the unit
if(x1 < minX){ // unit enters rect
x1 = minX;
y1 = y;
s = i;
lc = true;
} else { // unit leave rect
x2 = minX;
y2 = y;
e = i;
rc = true;
}
dx = x2 - x1;
dy = y2 - y1;
dt = e - s;
}
// do the same thing for maxX
if((x1 > maxX) || (x2 > maxX) ) {
// trajectory intersects the right vertical line
double delta = (maxX-x1)/dx;
double y = y1 + delta*dy;
Instant i = s + dt*delta;
// cut the unit
if(x1 > maxX){ // unit enters rect
x1 = maxX;
y1 = y;
s = i;
lc = true;
} else { // unit leave rect
x2 = maxX;
y2 = y;
e = i;
rc = true;
}
dx = x2 - x1;
dy = y2 - y1;
dt = e - s;
}
// clip at the horizontal lines
if( ((y1<minY) && (y2<minY)) ||
((y1>maxY) && (y2>maxY))){
// nothing left
result.SetDefined(false);
return;
}
// clip at the bottom line
if( (y1 < minY) || (y2<minY)){
double delta = (minY-y1)/dy;
double x = x1 + delta*dx;
Instant i = s + dt*delta;
if(y1 < minY){ // unit enters rect
x1 = x;
y1 = minY;
s = i;
lc = true;
} else { // unit leave rect
x2 = x;
y2 = minY;
e = i;
rc = true;
}
dx = x2 - x1;
dy = y2 - y1;
dt = e - s;
}
if( (y1 > maxY) || (y2>maxY)){
double delta = (maxY-y1)/dy;
double x = x1 + delta*dx;
Instant i = s + dt*delta;
if(y1 > maxY){ // unit enters rect
x1 = x;
y1 = maxY;
s = i;
lc = true;
} else { // unit leave rect
x2 = x;
y2 = maxY;
e = i;
rc = true;
}
}
// handle rounding errors
if(s<=timeInterval.start){
s = timeInterval.start;
lc = timeInterval.lc;
}
if(e>=timeInterval.end){
e = timeInterval.end;
rc = timeInterval.rc;
}
if(e<s){
std::cerr << "Warning e < s ; s = " << s << ", e = " << e << endl;
result.SetDefined(false);
return;
}
if( (e == s) && (!lc || !rc)){
result.SetDefined(false);
return;
}
Interval<Instant> tmp(s,e,lc,rc);
result.timeInterval=tmp;
result.p0.Set(x1,y1);
result.p1.Set(x2,y2);
}
void UPoint::AtInterval( const Interval<Instant>& i,
TemporalUnit<Point>& result ) const
{
AtInterval( i, result, 0);
}
void UPoint::AtInterval( const Interval<Instant>& i,
TemporalUnit<Point>& result,
const Geoid* geoid) const
{
assert( IsDefined() );
assert( i.IsValid() );
assert( !geoid || geoid->IsDefined() );
TemporalUnit<Point>::AtInterval( i, result );
UPoint *pResult = (UPoint*)&result;
pResult->SetDefined( IsDefined() );
if( !IsDefined() ){
return;
}
if( timeInterval.start == result.timeInterval.start ){
pResult->p0 = p0;
pResult->timeInterval.start = timeInterval.start;
pResult->timeInterval.lc = (pResult->timeInterval.lc && timeInterval.lc);
} else {
TemporalFunction( result.timeInterval.start, pResult->p0, geoid );
}
if( timeInterval.end == result.timeInterval.end ){
pResult->p1 = p1;
pResult->timeInterval.end = timeInterval.end;
pResult->timeInterval.rc = (pResult->timeInterval.rc && timeInterval.rc);
} else {
TemporalFunction( result.timeInterval.end, pResult->p1, geoid );
}
}
void UPoint::Distance( const Point& p, UReal& result ) const {
result.SetDefined(false);
std::vector<UReal> resvector;
resvector.clear();
Distance( p, resvector );
for(std::vector<UReal>::iterator i=resvector.begin();
i!=resvector.end(); i++){
if(i->IsDefined()){
result = *i;
return;
}
}
}
void UPoint::DistanceOrthodrome( const Point& p,
std::vector<UReal>& result,
const Geoid geoid,
const double epsilon, /*= 0.00001 */
const Instant* tMin, /*= 0 */
const double distMin, /*= -666.666 */
const double distStart,/*= -666.666 */
const double distEnd /*= -666.666 */) const {
UReal resunit(true);
bool ok(false);
resunit.timeInterval = timeInterval;
if( !IsDefined() || !p.IsDefined() || !geoid.IsDefined() ) {
resunit.SetDefined(false);
result.push_back(resunit);
return;
}
DateTime DT = timeInterval.end - timeInterval.start;
double dt = DT.ToDouble();
if ( AlmostEqual(dt, 0.0) || AlmostEqual(p0,p1)) { // constant/instant unit
resunit.a = 0;
resunit.b = 0;
resunit.c = p.DistanceOrthodrome(p0,geoid,ok);
resunit.c *= resunit.c;
resunit.r = true; // draw square root
resunit.SetDefined(ok);
result.push_back(resunit);
return;
}
double d0 = distStart;
if(d0<0){ // need to calculate distance to p at start of unit
d0 = p0.DistanceOrthodrome(p, geoid, ok);
assert(ok);
}
double d1 = distEnd;
if(d1<0){ // need to calculate distance to p at end of unit
d1 = p1.DistanceOrthodrome(p, geoid, ok);
assert(ok);
}
if(fabs(d1-d0)<epsilon){ // precision reached --> return single constant unit
resunit.a = 0;
resunit.b = 0;
resunit.c = d0;
resunit.c *= resunit.c;
resunit.r = true; // draw square root
resunit.SetDefined(ok);
result.push_back(resunit);
return;
} // else: precision not yet reached --> refine
// choose split point for refinement
double dMin = distMin;
Instant iMin(0.0);
if(tMin){
iMin = *tMin;
} else {
iMin.SetDefined(false);
}
Instant iSplit(instanttype);
iSplit.SetDefined(false);
if( (dMin<0) || !iMin.IsDefined() ){ // need to calculate minimum distance
HalfSegment hs(true, p0, p1);
dMin = hs.Distance( p, &geoid );
assert(dMin>=0);
// compute instant of nearest approach
// TODO
}
if( (iMin>timeInterval.start) && (iMin<timeInterval.end) ){ //use minInstant
iSplit = iMin;
} else { // use middle of interval
iSplit = timeInterval.start + (timeInterval.end - timeInterval.start)/2;
}
// recursive call to refine (start,splitpoint)
Interval<Instant> i0(timeInterval.start,iSplit,timeInterval.lc,false);
Interval<Instant> i1(iSplit,timeInterval.end,true,timeInterval.rc);
UPoint u0(false);
AtInterval(i0,u0);
u0.DistanceOrthodrome( p,result,geoid,epsilon,&iMin,dMin,d0,d1 );
// recursive call to refine (splitpoint,end)
UPoint u1(false);
AtInterval(i1,u1);
u1.DistanceOrthodrome( p,result,geoid,epsilon,&iMin,dMin,d0,d1 );
}
void UPoint::Distance( const Point& p,
std::vector<UReal>& result,
const Geoid* geoid /*=0*/,
const double epsilon /*=0.00001*/) const
{
if( !IsDefined() || !p.IsDefined() || (geoid && !geoid->IsDefined()) ) {
UReal resunit(false);
result.push_back(resunit);
} else {
UReal resunit(false);
DateTime DT = timeInterval.end - timeInterval.start;
double dt = DT.ToDouble();
double
x0 = p0.GetX(), y0 = p0.GetY(),
x1 = p1.GetX(), y1 = p1.GetY(),
x = p.GetX(), y = p.GetY();
if ( AlmostEqual(dt, 0.0) || AlmostEqual(p0,p1)) {
// single-instant or constant unit
resunit.SetDefined(true);
resunit.timeInterval = timeInterval;
resunit.a = 0.0;
resunit.b = 0.0;
if(geoid){ // spherical distance squared
bool ok=false;
resunit.c = p.DistanceOrthodrome(p0,*geoid,ok);
//resunit.c *= resunit.c;
} else { // euclidean distance squared
resunit.c = sqrt((pow(x0-x,2) + pow(y0-y,2)));
}
resunit.r = false; // square root encoded in c
result.push_back(resunit);
} else { // non-constant, non-instant unit
if(geoid){ // spherical distance squared
DistanceOrthodrome( p, result, *geoid, epsilon );
} else { // euclidean distance squared
resunit.SetDefined(true);
resunit.timeInterval = timeInterval;
resunit.a = pow((x1-x0)/dt,2)+pow((y1-y0)/dt,2);
resunit.b = 2*((x1-x0)*(x0-x)+(y1-y0)*(y0-y))/dt;
resunit.c = pow(x0-x,2)+pow(y0-y,2);
resunit.r = true; // draw square root
result.push_back(resunit);
}
}
}
}
double UPoint::DistanceIntegral(const UPoint& up, const bool upperBound,
const Geoid* geoid /* = 0 */) const {
// cout << "compare " << *this << endl << " and " << up << endl;
datetime::DateTime beginOfTime(0, 0, datetime::instanttype);
datetime::DateTime diffToBeginOfTime = timeInterval.start - beginOfTime;
datetime::DateTime duration = timeInterval.end - timeInterval.start;
UPoint up1(*this), up2(up);
up1.timeInterval.start -= diffToBeginOfTime;
up1.timeInterval.end = up1.timeInterval.start + duration;
up2.timeInterval.start -= diffToBeginOfTime;
up2.timeInterval.end = up2.timeInterval.start + duration;
UReal dist(true);
if (geoid) {
dist.timeInterval = up1.timeInterval;
dist.Recompute(up1, up2, geoid);
}
else {
up1.Distance(up2, dist);
}
if (!dist.IsDefined()) {
std::cerr << __PRETTY_FUNCTION__ << "Invalid geographic coord!" << endl;
return -1.0;
}
double result = dist.Integrate();
if (isnan(result) || result < 0.0 || isinf(result)) { // linearize dist fun
Interval<Instant> iv = dist.timeInterval;
UReal linPart1(true), linPart2(true);
dist.Linearize(linPart1, linPart2);
result = linPart1.Integrate() +
(linPart2.IsDefined() ? linPart2.Integrate() : 0.0);
// cout << " approx by " << linPart1.Integrate() << " + "
// << (linPart2.IsDefined() ? linPart2.Integrate() : 0.0) << endl;
if (isnan(result)) { // use mean of start and end point distance
cout << "######$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" << endl;
result = (this->p0.Distance(up.p0, geoid) +
this->p1.Distance(up.p1, geoid)) / 2 * (iv.end - iv.start).ToDouble();
}
}
// cout << "added value " << result << " from " << dist << endl << endl;
return result;
}
double UPoint::Distance(const Rectangle<3>& rect,
const Geoid* geoid /*=0*/) const{
std::cerr << "UPoint::Distance(const Rectangle<3>&) not implemented yet"
<< endl;
if( !IsDefined() || !rect.IsDefined() || (geoid && !geoid->IsDefined()) ){
return -1;
}
return BoundingBox().Distance(rect,geoid);
}
bool UPoint::Intersects(const Rectangle<3>& rect,
const Geoid* geoid) const{
bool implemented = false; // not implemented yet
assert(implemented);
return false;
}
void UPoint::Distance( const UPoint& up,
UReal& result,
const Geoid* geoid ) const
{
assert( IsDefined() );
assert( up.IsDefined() );
if(geoid){
assert( geoid->IsDefined() );
std::cerr << "Spherical distance computation not implemented!" << endl;
assert( false ); // TODO: implement spherical geometry
// use HalfSegment::Distance(HalfSegment) to find DISTmin
// use UPoint::AtValue(VALUEmin) to get Tmin
// approximate the distance function by binary splits
// TODO: implementation
}
assert( timeInterval.Intersects(up.timeInterval) );
if( !IsDefined()
|| !up.IsDefined()
|| !timeInterval.Intersects(up.timeInterval)
|| (geoid && !geoid->IsDefined() ) ) {
result.SetDefined( false );
return;
}
result.SetDefined( true );
if((timeInterval.start==timeInterval.end) &&
(up.timeInterval.start == up.timeInterval.end)){
// only for two points at the same time
result.timeInterval = timeInterval;
result.a = 0.0;
result.b = 0.0;
result.c = p0.Distance(up.p0);
result.r = false;
return;
}
if(timeInterval.start == timeInterval.end){
// this is joint an ipoint
result.timeInterval = timeInterval;
Distance(up.p0,result);
return;
}
if(up.timeInterval.start == up.timeInterval.end){
// up is just an ipoint
result.timeInterval = up.timeInterval;
up.Distance(p0,result);
return;
}
Interval<Instant>iv;
DateTime DT(durationtype);
Point rp10, rp11, rp20, rp21;
double
x10, x11, x20, x21,
y10, y11, y20, y21,
dx1, dy1,
dx2, dy2,
dx12, dy12,
dt;
timeInterval.Intersection(up.timeInterval, iv);
result.timeInterval = iv;
// ignore closedness for TemporalFunction:
TemporalFunction( iv.start, rp10, true);
TemporalFunction( iv.end, rp11, true);
up.TemporalFunction(iv.start, rp20, true);
up.TemporalFunction(iv.end, rp21, true);
if ( AlmostEqual(rp10,rp20) && AlmostEqual(rp11,rp21) )
{ // identical points -> zero distance!
result.a = 0.0;
result.b = 0.0;
result.c = 0.0;
result.r = false;
return;
}
DT = iv.end - iv.start;
dt = DT.ToDouble();
x10 = rp10.GetX(); y10 = rp10.GetY();
x11 = rp11.GetX(); y11 = rp11.GetY();
x20 = rp20.GetX(); y20 = rp20.GetY();
x21 = rp21.GetX(); y21 = rp21.GetY();
dx1 = x11 - x10; // x-difference final-initial for u1
dy1 = y11 - y10; // y-difference final-initial for u1
dx2 = x21 - x20; // x-difference final-initial for u2
dy2 = y21 - y20; // y-difference final-initial for u2
dx12 = x10 - x20; // x-distance at initial instant
dy12 = y10 - y20; // y-distance at initial instant
if ( AlmostEqual(dt, 0) )
{ // almost equal start and end time -> constant distance
result.a = 0.0;
result.b = 0.0;
result.c = sqrt( pow( ( (x11-x10) - (x21-x20) ) / 2, 2)
+ pow( ( (y11-y10) - (y21-y20) ) / 2, 2));
result.r = false;
return;
}
double a1 = (pow((dx1-dx2),2)+pow(dy1-dy2,2))/pow(dt,2);
double b1 = dx12 * (dx1-dx2);
double b2 = dy12 * (dy1-dy2);
result.a = a1;
result.b = 2*(b1+b2)/dt;
result.c = pow(dx12,2) + pow(dy12,2);
result.r = true;
return;
}
// scalar velocity
void UPoint::USpeed( UReal& result, const Geoid* geoid ) const
{
double duration = 0.0;;
double dist = 0.0;
bool valid = true;
if ( !IsDefined() ) {
valid = false;
} else {
result.timeInterval = timeInterval;
DateTime dt = timeInterval.end - timeInterval.start;
duration = dt.millisecondsToNull() / 1000.0; // value in seconds
if( duration > 0.0 ){
if(!geoid){ // (X,Y)-coords
double x0 = p0.GetX(), y0 = p0.GetY(),
x1 = p1.GetX(), y1 = p1.GetY();
/*
The point unit is represented as a function
f(t) = (x0 + x1 * t, y0 + y1 * t).
The result of the derivation is the constant (x1,y1).
*/
dist = sqrt(pow( (x1-x0), 2 ) + pow( (y1- y0), 2 ));
valid = true;
} else { // (LON.LAT)-coords
dist = p0.DistanceOrthodrome(p1,*geoid, valid);
}
/*
The speed is constant in each time interval.
Its value is represented by variable c. The variables a and b
are set to zero.
*/
result.a = 0; // speed is constant in the interval
result.b = 0;
result.c = dist/duration;
result.r = false;
} else { // duration <= 0.0
valid = false;
}
}
result.SetDefined(valid);
}
// component-wise velocity
void UPoint::UVelocity( UPoint& result ) const
{
double x0, y0, x1, y1;
double duration;
if ( ! IsDefined() )
result.SetDefined( false );
else
{
x0 = p0.GetX();
y0 = p0.GetY();
x1 = p1.GetX();
y1 = p1.GetY();
DateTime dt = timeInterval.end - timeInterval.start;
duration = dt.millisecondsToNull() / 1000.0; // value in seconds
if( duration > 0.0 )
{
UPoint p(timeInterval,
(x1-x0)/duration,(y1-y0)/duration, // velocity is constant
(x1-x0)/duration,(y1-y0)/duration // throughout the unit
);
p.SetDefined( true );
result.CopyFrom( &p );
result.SetDefined( true );
}
else
{
UPoint p(timeInterval,0,0,0,0);
result.CopyFrom( &p );
result.SetDefined( false );
}
}
}
void UPoint::UTrajectory( Line& line ) const
{
line.Clear();
if( !IsDefined() ){
line.SetDefined( false );
return;
}
line.SetDefined( true );
HalfSegment hs;
int edgeno = 0;
line.StartBulkLoad();
if( !AlmostEqual( p0, p1 ) )
{
hs.Set( true, p0, p1 );
hs.attr.edgeno = edgeno++;
line += hs;
hs.SetLeftDomPoint( !hs.IsLeftDomPoint() );
line += hs;
}
line.EndBulkLoad(true,false); // avoid realminize
}
void UPoint::Length( CcReal& result ) const
{
if( !this->IsDefined() || !p0.IsDefined() || !p0.IsDefined() ){
result.Set(false, 0.0);
return;
}
result.Set(true, p0.Distance(p1));
return;
}
void UPoint::Length( const Geoid& g, CcReal& result ) const
{
if( !this->IsDefined() || !p0.IsDefined() || !p0.IsDefined() ){
result.Set(false, 0.0);
return;
}
bool valid = true;
result.Set(true, p0.DistanceOrthodrome(p1, g, valid));
result.SetDefined(valid);
return;
}
void UPoint::Direction( std::vector<UReal> &result,
const bool useHeading /*= false*/,
const Geoid* geoid /*= 0*/,
const double epsilon /*= 0.00001*/) const
{
UReal uresult(true);
if( !IsDefined() || (geoid && ( (epsilon<=0.0) || !geoid->IsDefined()) ) ) {
return; // no result
}
if( (timeInterval.end == timeInterval.start) || AlmostEqual(p0,p1) ){
// undefined result!
uresult.a = 0.;
uresult.b = 0.;
uresult.c = 0.;
uresult.r = false;
uresult.timeInterval = timeInterval;
uresult.SetDefined(false);
result.push_back(uresult);
return;
}
if(!geoid) { // euclidean case
uresult.a = 0.;
uresult.b = 0.;
uresult.c = p0.Direction(p1,useHeading,geoid);
uresult.r = false;
uresult.timeInterval = timeInterval;
uresult.SetDefined( uresult.c>=0 );
result.push_back(uresult);
return;
}
// spherical case:
assert(epsilon > 0);
//compute directions at start/end point
bool valid = false;
double head0, head1;
p0.DistanceOrthodromePrecise( p1, *geoid, valid, head0, head1);
if( !valid || (head0<0) || (head1<0) ){ // ERROR!
std::cerr << __PRETTY_FUNCTION__ << ": Error computing directions." << endl;
assert(false);
return;
}
if(!useHeading){
head0 = headingToDirection(head0);
head1 = headingToDirection(head1);
}
cout << __PRETTY_FUNCTION__ << ": head0 = " << head0 << endl;
cout << __PRETTY_FUNCTION__ << ": head1 = " << head0 << endl;
double deltaHead = head1 - head0;
cout << __PRETTY_FUNCTION__ << ": deltaHead = " << deltaHead << endl;
if( (fabs(deltaHead)<=epsilon) ){ // sufficiently precise
DateTime dt = timeInterval.end - timeInterval.start;
uresult.a = 0.;
uresult.b = deltaHead/dt.ToDouble();
uresult.c = head0;
uresult.r = false;
uresult.timeInterval = timeInterval;
uresult.SetDefined( true );
result.push_back(uresult);
} else { // preciseness not yet reached
// split the unit, recurse into both parts. append the resulting
// unit vectors to result.
Instant t0(timeInterval.start);
Instant t1(timeInterval.end);
Instant t05 = t0+((t1-t0)/2);
if( (t0==t05) || (t1==t05) ){ // invalid interval -> cannot split!
uresult.a = 0.;
uresult.b = deltaHead/(t1-t0).ToDouble();
uresult.c = head0;
uresult.r = false;
uresult.timeInterval = timeInterval;
uresult.SetDefined( true );
result.push_back(uresult);
return;
}
Interval<Instant> iv0(t0,t05,timeInterval.lc,false);
Interval<Instant> iv1(t05,t1,true,timeInterval.rc);
UPoint up0(false), up1(false);
AtInterval(iv0,up0);
AtInterval(iv1,up1);
up0.Direction(result,useHeading,geoid,epsilon); // append results
up1.Direction(result,useHeading,geoid,epsilon); // append results
}
return;
}
// This function will return the intersection of two upoint values as
// an upoint value. If the common timeInterval iv is open bounded, and
// both units would intersect at the open interval limit, there WILL
// be passed a result, though it is not inside iv!
void UPoint::Intersection(const UPoint &other, UPoint &result) const
{
if ( !IsDefined() ||
!other.IsDefined() ||
!timeInterval.Intersects( other.timeInterval ) )
{
result.SetDefined( false );
if (TA_DEBUG)
std::cerr << "No intersection (0): deftimes do not overlap" << endl;
assert ( !result.IsDefined() || result.IsValid() );
return; // nothing to do
}
Interval<Instant> iv;
Instant t;
Point p_intersect, d1, d2, p1;
UPoint p1norm(true), p2norm(true);
double t_x, t_y, t1, t2, dxp1, dxp2, dyp1, dyp2, dt;
bool intersectionfound = false;
result.timeInterval.start = DateTime(0,0,instanttype);
result.timeInterval.end = DateTime(0,0,instanttype);
result.timeInterval.start.SetDefined(true);
result.timeInterval.end.SetDefined(true);
result.SetDefined(false);
if (timeInterval == other.timeInterval)
{ // identical timeIntervals
p1norm = *this;
p2norm = other;
iv = timeInterval;
}
else
{ // get common time interval
timeInterval.Intersection(other.timeInterval, iv);
// normalize both starting and ending points to interval
AtInterval(iv, p1norm);
other.AtInterval(iv, p2norm);
}
if (TA_DEBUG)
{
std::cerr << " p1norm=";
p1norm.Print(std::cerr);
std::cerr << endl << " p2norm=";
p2norm.Print(std::cerr);
std::cerr << endl;
}
// test for identity:
if ( p1norm.EqualValue( p2norm ))
{ // both upoints have the same linear function
result = p1norm;
if (TA_DEBUG)
{
std::cerr << "Found intersection (1): equal upoints" << endl
<< " Result=";
result.Print(std::cerr);
std::cerr << endl;
}
assert ( !result.IsDefined() || result.IsValid() );
return;
}
// test for ordinary intersection of the normalized upoints
d1 = p2norm.p0 - p1norm.p0; // difference vector at starting instant
d2 = p2norm.p1 - p1norm.p1; // difference vector at ending instant
if ( ((d1.GetX() > 0) && (d2.GetX() > 0)) ||
((d1.GetX() < 0) && (d2.GetX() < 0)) ||
((d1.GetY() > 0) && (d2.GetY() > 0)) ||
((d1.GetY() < 0) && (d2.GetY() < 0)))
{ // no intersection (projections to X/Y do not cross each other)
if (TA_DEBUG)
std::cerr << "No intersection (1) - projections do not intersect:"
<< endl
<< " d1X=" << d1.GetX() << " d2X=" << d2.GetX() << endl
<< " d1Y=" << d1.GetY() << " d2Y=" << d2.GetY() << endl;
result.SetDefined( false );
assert ( !result.IsDefined() || result.IsValid() );
return; // nothing to do
}
// Some intersection is possible, as projections intersect...
dxp1 = (p1norm.p1 - p1norm.p0).GetX(); // arg1: X-difference
dyp1 = (p1norm.p1 - p1norm.p0).GetY(); // arg1: Y-difference
dxp2 = (p2norm.p1 - p2norm.p0).GetX(); // arg2: X-difference
dyp2 = (p2norm.p1 - p2norm.p0).GetY(); // arg2: Y-difference
/*
Trying to find an intersection point $t$ with $A_1t + B_1 = A_2t + B_2$
we get:
\[ t_x = \frac{px_{21} - px_{11}}{dxp_1 - dxp_2} \quad
t_y = \frac{py_{21} - py_{11}}{dyp_1 - pyp_2} \]
where $t = t_x = t_y$. If $t_x \neq t_y$, then there is no intersection!
*/
dt = (iv.end - iv.start).ToDouble();
t1 = iv.start.ToDouble();
t2 = iv.end.ToDouble();
t_x = (dt*d1.GetX() + t1*(dxp1-dxp2)) / (dxp1-dxp2);
t_y = (dt*d1.GetY() + t1*(dyp1-dyp2)) / (dyp1-dyp2);
if (TA_DEBUG)
std::cerr << " dt=" << dt << " t1=" << t1 << " t2=" << t2 << endl
<< " (dxp1-dxp2)=" << (dxp1-dxp2)
<< " (dyp1-dyp2)=" << (dyp1-dyp2) << endl
<< " t_x=" << t_x << " t_y=" << t_y << endl;
// Standard case: (dxp1-dxp2) != 0.0 != (dyp1-dyp2)
if ( AlmostEqual(t_x, t_y) && ( t_x >= t1) && ( t_x <= t2) )
{ // We found an intersection
if (TA_DEBUG) std::cerr << " Case 1: X/Y variable" << endl;
t.ReadFrom(t_x); // create Instant
intersectionfound = true;
}
// Special case: (dxp1-dxp2) == 0.0 -- constant X
else if ( AlmostEqual(dxp1-dxp2, 0.0) )
{
if (TA_DEBUG) std::cerr << " Case 2: constant X" << endl;
t_y = t1 + d1.GetY() * dt / (dyp1 - dyp2);
t.ReadFrom(t_y); // create Instant
intersectionfound = true;
}
// Special case: (dyp1-dyp2) == 0.0 -- constant Y
else if ( AlmostEqual(dyp1-dyp2, 0.0) )
{
if (TA_DEBUG) std::cerr << " Case 3: constant Y" << endl;
t_x = t1 + d1.GetX() * dt / (dxp1 - dxp2);
t.ReadFrom(t_x); // create Instant
intersectionfound = true;
}
if ( intersectionfound )
{
t.SetType(instanttype); // force instanttype
iv = Interval<Instant>( t, t, true, true ); // create Interval
TemporalFunction(t, p1, true);
result = UPoint(iv, p1, p1);
if (TA_DEBUG)
{
std::cerr << "Found intersection (2): intersection point" << endl
<< " Result=";
result.Print(std::cerr);
std::cerr << endl;
}
assert ( !result.IsDefined() || result.IsValid() );
return;
}
// else: no result
if (TA_DEBUG) std::cerr << "No intersection (2)." << endl;
result.SetDefined( false );
assert ( !result.IsDefined() || result.IsValid() );
return;
}
void UPoint::Translate(const double xdiff, const double ydiff,
const DateTime& timediff)
{
assert( IsDefined() );
assert( timediff.IsDefined() );
p0.Set(p0.GetX()+xdiff,p0.GetY()+ydiff);
p1.Set(p1.GetX()+xdiff, p1.GetY()+ydiff);
timeInterval.start = timeInterval.start + timediff;
timeInterval.end = timeInterval.end + timediff;
}
bool UPoint::AtRegion(const Region *r, std::vector<UPoint> &result) const {
result.clear();
if(!IsDefined() || !r->IsDefined() ) {
return false;
}
if(r->IsEmpty()) {
return true;
}
if(!r->BoundingBox().Intersects(BoundingBoxSpatial())) { // total MBR-check
return true;
}
if(AlmostEqual(p0,p1)){
// this unit is static
if( r->Contains(p0) ){ // this unit is completely within the region
result.push_back(*this);
}
return true;
}
// create a halfsegment hs using Trajectory() and compute intersection
std::vector<UPoint> tmpresult;
UPoint ures(false);
Instant t_left(instanttype), t_right(instanttype),
t_start(instanttype), t_end(instanttype);
// handle linear intersections
Line segs1(2);
Line traj(2); // buffer for trajectory
UTrajectory(traj); // get trajectory (may be empty)
r->Intersection(traj, segs1); // compute linear intersections
Line segs(segs1.Size());
Points* ps = new Points(0);
segs1.Simplify(segs, FACTOR,*ps);
ps->DeleteIfAllowed();
if(!segs.IsDefined()){
std::cerr << __PRETTY_FUNCTION__
<< " WARNING: r->Intersection(traj, segs) is UNDEF for traj="
<< traj << "." <<endl;
} else {
HalfSegment hs; // buffer for the halfsegment
for(int i=0; i<segs.Size(); i++){ // for each halfsegment hs in segs
// compute instants t_left, t_right from segment's start and endpoint
segs.Get(i,hs);
if(hs.IsLeftDomPoint()){ // only use left dominating points
UPoint tmpUnit(*this); // UPoint::At() will use lc, rc strictly
tmpUnit.timeInterval.lc=true; // Make a left- and rightclosed copy
tmpUnit.timeInterval.rc=true; // by bypass this problem...
tmpUnit.At( hs.GetLeftPoint(), ures );
if(!ures.IsDefined()){
std::cerr << __PRETTY_FUNCTION__
<<" WARNING: (1) undef linear intersection unit for hs=" <<hs<<endl;
continue;
}
t_left = ures.timeInterval.start;
tmpUnit.At( hs.GetRightPoint(), ures );
if(!ures.IsDefined()){
std::cerr << __PRETTY_FUNCTION__
<<" WARNING: (2) undef linear intersection unit for hs=" <<hs<<endl;
} else {
t_right = ures.timeInterval.start;
// create a UPoint
Point p_start (true), p_end(true);
if(t_left<t_right) {
t_start = t_left;
t_end = t_right;
p_start = hs.GetLeftPoint();
p_end = hs.GetRightPoint();
} else {
t_start = t_right;
t_end = t_left;
p_start = hs.GetRightPoint();
p_end = hs.GetLeftPoint();
}
Interval<Instant> interval(t_start,t_end,true,true);
ures = UPoint(interval,p_start,p_end);
tmpresult.push_back(ures); // add the UPoint to tmpresult
} // else
} // is LeftDomPoint
}// for each halfsegment hs in segs
}
// handle point intersections
Points points(0);
r->TouchPoints(traj, points); // compute point intersections
if(!points.IsDefined()){
std::cerr << __PRETTY_FUNCTION__
<< " WARNING: r->TouchPoints(traj, points) is UNDEF for traj="
<< traj << "." << endl;
} else {
Point p(true,0.0,0.0); // buffer for the point
int nosegres = tmpresult.size(); // no of linear results
for(int i=0; i<points.Size(); i++){ // for each point p in points
points.Get(i,p);
bool found = false;
int j = 0;
while(j<nosegres && !found){
found = AlmostEqual(tmpresult[j].p0,p)||AlmostEqual(tmpresult[j].p1,p);
j++;
}
if(!found) { // p is not already contained by segs --> keep it!
At( p, ures ); // compute UPoint from position
if(!ures.IsDefined()){
std::cerr << __PRETTY_FUNCTION__
<< " WARNING: undef point intersection unit for p=" << p << endl;
} else {
tmpresult.push_back(ures); // add the UPoint to tmpresult
}
}
} // for each point p in points
}
// adapt closedness within tmpresult and copy tmpresult to result
return
ConsolidateUnitVector<UPoint,Point>(this->timeInterval,tmpresult,result);
}
/*
1.1 Implementation of functions for the class ~CUPoint~
*/
void CUPoint::AtIntervalCU(const Interval<Instant>& i, CUPoint& result) const {
AtIntervalCU(i, result, 0);
}
void CUPoint::AtIntervalCU(const Interval<Instant>& i, CUPoint& result,
const Geoid* geoid) const {
((UPoint*)this)->AtInterval(i, *((UPoint*)&result));
result.SetRadius(this->GetRadius());
}
void CUPoint::TemporalFunctionCU(const Instant& t, CPoint& result,
bool ignoreLimits /* = false */) const {
Point p(true);
((UPoint*)this)->TemporalFunction(t, p, ignoreLimits);
result.Set(p, this->GetRadius());
}
const Rectangle<3> CUPoint::BoundingBox(const Geoid* geoid) const {
if (geoid) {
if (!geoid->IsDefined() || !IsDefined()) {
return Rectangle<3>(false);
}
}
double PI = 3.1415926535;
double dir = 0.0;
Point p0shifted(true), p1shifted(true);
if (AlmostEqual(p0, p1)) {
p0shifted = Point(true, p0.GetX() - radius, p0.GetY() - radius);
p1shifted = Point(true, p1.GetX() + radius, p1.GetY() + radius);
if (geoid) {
Rectangle<2> geobbox(false);
geobbox = p0shifted.GeographicBBox(p1shifted, *geoid);
double minMax[] = {geobbox.MinD(0), geobbox.MaxD(0),
geobbox.MinD(1), geobbox.MaxD(1),
timeInterval.start.ToDouble(),
timeInterval.end.ToDouble()};
return Rectangle<3>(true, minMax);
}
if (this->IsDefined()) {
double minMax[] = {MIN(p0shifted.GetX(), p1shifted.GetX()),
MAX(p0shifted.GetX(), p1shifted.GetX()),
MIN(p0shifted.GetY(), p1shifted.GetY()),
MAX(p0shifted.GetY(), p1shifted.GetY()),
timeInterval.start.ToDouble(),
timeInterval.end.ToDouble()};
return Rectangle<3>(true, minMax);
}
else {
return Rectangle<3>(false);
}
}
else {
try {
dir = p0.Direction(p1, false, geoid) * PI / 180;
}
catch (SecondoException *e) {
delete e;
return Rectangle<3>(false);
}
int hSign = p0.GetX() < p1.GetX() ? 1 : -1;
int vSign = p0.GetY() < p1.GetY() ? 1 : -1;
double yfact = (geoid ? 1.0 / geodist::getMetersPerDegree(p0.GetY(), true)
: 1.0);
double xfact = (geoid ? 1.0 / geodist::getMetersPerDegree(p0.GetY(), false)
: 1.0);
p0shifted = Point(true, p0.GetX() - hSign * abs(sin(dir)) * radius * xfact,
p0.GetY() - vSign * abs(cos(dir)) * radius * yfact);
p1shifted = Point(true, p1.GetX() + hSign * abs(sin(dir)) * radius * xfact,
p1.GetY() + vSign * abs(cos(dir)) * radius * yfact);
if (geoid) {
Rectangle<2> geobbox =
HalfSegment(true, p0shifted, p1shifted).BoundingBox(geoid);
double minMax[] = {geobbox.MinD(0), geobbox.MaxD(0),
geobbox.MinD(1), geobbox.MaxD(1),
timeInterval.start.ToDouble(),
timeInterval.end.ToDouble()};
return Rectangle<3>(true, minMax);
} // else: euclidean geometry
double minMax[] = {MIN(p0shifted.GetX(), p1shifted.GetX()),
MAX(p0shifted.GetX(), p1shifted.GetX()),
MIN(p0shifted.GetY(), p1shifted.GetY()),
MAX(p0shifted.GetY(), p1shifted.GetY()),
timeInterval.start.ToDouble(),
timeInterval.end.ToDouble()};
return Rectangle<3>(true, minMax);
}
}
const Rectangle<3> CUPoint::BoundingBox(const double scaleTime,
const Geoid* geoid) const {
Rectangle<3> bbx = this->BoundingBox(geoid);
if (bbx.IsDefined()) {
double minMax[] = {bbx.MinD(0), bbx.MaxD(0), bbx.MinD(1), bbx.MaxD(1),
timeInterval.start.ToDouble()*scaleTime,
timeInterval.end.ToDouble()*scaleTime};
return Rectangle<3>(true, minMax);
}
else {
return Rectangle<3>(false);
}
}
const Rectangle<2> CUPoint::BoundingBoxSpatial(const Geoid* geoid) const {
Rectangle<3> bbx = this->BoundingBox(geoid);
if (bbx.IsDefined()) {
double minMax[] = {bbx.MinD(0), bbx.MaxD(0), bbx.MinD(1), bbx.MaxD(1)};
return Rectangle<2>(true, minMax);
}
else {
return Rectangle<2>(false);
}
}
std::ostream& operator<<(std::ostream& o, const CUPoint& u){
u.Print(o);
return o;
}
void CUPoint::ConvertFrom(const UPoint& up, const Geoid* geoid /* = 0 */) {
((UPoint*)this)->CopyFrom(&up);
}
double CUPoint::GetToleranceFactor() {
return 1.0;
}
void CUPoint::ConvertFrom(const MPoint& mp, const Geoid* geoid /* = 0 */) {
if (!mp.IsDefined() || mp.IsEmpty()) {
SetDefined(false);
return;
}
SetDefined(true);
mp.GetFullInterval(timeInterval);
IPoint ip(true);
mp.Initial(ip);
p0 = ip.value;
mp.Final(ip);
p1 = ip.value;
UPoint up(timeInterval, p0, p1);
MPoint approx(true);
approx.Add(up);
bool correct = true;
if (!geoid) {
MReal dist(true), distScaled(true);
mp.SquaredDistance(approx, dist);
radius = sqrt(dist.Max(correct));
}
else {
radius = 0.0;
UPoint upSrc(true), upDest(true);
UReal ur(true);
for (int i = 0; i < mp.GetNoComponents(); i++) {
mp.Get(i, upSrc);
upDest.timeInterval = upSrc.timeInterval;
up.TemporalFunction(upSrc.timeInterval.start, upDest.p0, true);
up.TemporalFunction(upSrc.timeInterval.end, upDest.p1, true);
ur.timeInterval = upDest.timeInterval;
ur.Recompute(upSrc, upDest, geoid);
double maxDist = ur.Max(correct);
assert(correct);
if (maxDist > radius) {
radius = maxDist;
}
}
}
datetime::DateTime duration(datetime::durationtype);
mp.GetDuration(duration);
timeInterval.end = timeInterval.start + duration;
assert(correct);
}
void CUPoint::ConvertFrom(const CMPoint& cmp, const Geoid* geoid /* = 0 */) {
if (!cmp.IsDefined() || cmp.IsEmpty()) {
SetDefined(false);
return;
}
SetDefined(true);
cmp.GetFullInterval(timeInterval);
CIPoint cip(true);
cmp.Initial(cip);
p0 = *((Point*)&(cip.value));
cmp.Final(cip);
p1 = *((Point*)&(cip.value));
MPoint mp1unit(true), mpSrc(true);
mp1unit.Add(*this);
cmp.GetMPoint(mpSrc);
bool correct = false;
if (!geoid) {
MReal dist(true), distAtMax(true);
mpSrc.SquaredDistance(mp1unit, dist);
dist.AtMax(distAtMax);
IReal ir(true);
distAtMax.Initial(ir);
cmp.AtInstant(ir.instant, cip);
radius = sqrt(dist.Max(correct)) + cip.value.getRadius();
}
else {
radius = 0.0;
UPoint up(timeInterval, p0, p1);
CUPoint cup(true);
UPoint upSrc(true), upDest(true);
UReal ur(true);
for (int i = 0; i < cmp.GetNoComponents(); i++) {
cmp.Get(i, cup);
cup.GetUPoint(upSrc);
upDest.timeInterval = upSrc.timeInterval;
up.TemporalFunction(upSrc.timeInterval.start, upDest.p0, true);
up.TemporalFunction(upSrc.timeInterval.end, upDest.p1, true);
ur.timeInterval = upDest.timeInterval;
ur.Recompute(upSrc, upDest, geoid);
assert(correct);
double maxDist = ur.Max(correct);
if (maxDist + cup.GetRadius() > radius) {
radius = maxDist + cup.GetRadius();
}
}
}
datetime::DateTime duration(datetime::durationtype);
cmp.GetDuration(duration);
timeInterval.end = timeInterval.start + duration;
assert(correct);
}
void CUPoint::Split(const datetime::DateTime& duration,
std::vector<CUPoint>& result) const {
result.clear();
if (!IsDefined()) {
return;
}
CUPoint res(true);
datetime::DateTime durTemp(0, 0, datetime::durationtype);
datetime::DateTime durSrc(timeInterval.end - timeInterval.start);
Interval<Instant> iv;
while (durTemp < durSrc) {
iv.start = timeInterval.start + durTemp;
iv.end = iv.start + duration;
durTemp += duration;
if (durTemp > durSrc) {
iv.end -= durTemp - durSrc;
}
AtIntervalCU(iv, res);
result.push_back(res);
}
}
double CUPoint::DistanceStartEnd(const CUPoint& cup, const Geoid* geoid /*=0*/){
CPoint start1(true), start2(true), end1(true), end2(true);
this->TemporalFunctionCU(this->timeInterval.start, start1, true);
this->TemporalFunctionCU(this->timeInterval.end, end1, true);
cup.TemporalFunctionCU(cup.timeInterval.start, start2, true);
cup.TemporalFunctionCU(cup.timeInterval.end, end2, true);
return (start1.Distance(start2, geoid) + end1.Distance(end2, geoid)) / 2.0;
}
double CUPoint::DistanceIntegral(const CUPoint& cup, const bool upperBound,
const Geoid* geoid /* = 0 */) const {
// cout << "compare " << *this << endl << " and " << cup << endl;
datetime::DateTime beginOfTime(0, 0, datetime::instanttype);
datetime::DateTime diffToBeginOfTime = timeInterval.start - beginOfTime;
datetime::DateTime duration = timeInterval.end - timeInterval.start;
CUPoint cup1(*this), cup2(cup);
cup1.timeInterval.start -= diffToBeginOfTime;
cup1.timeInterval.end = cup1.timeInterval.start + duration;
cup2.timeInterval.start -= diffToBeginOfTime;
cup2.timeInterval.end = cup2.timeInterval.start + duration;
bool correct = false;
Periods per(true);
double sumOfRadii = this->GetRadius() + cup.GetRadius();
Interval<Instant> ivMin(true);
Instant instMin, instNull1, instNull2;
double integralValue1, integralValue2, result;
UReal dist(true), urNull(true);
if (!geoid) {
((UPoint*)&cup1)->Distance(*((UPoint*)(&cup2)), dist);
}
else {
cup1.timeInterval.Intersection(cup2.timeInterval, dist.timeInterval);
dist.Recompute(*(UPoint*)(&cup1), *(UPoint*)(&cup2), geoid);
}
double dur = (dist.timeInterval.end - dist.timeInterval.start).ToDouble();
if (!upperBound) { // prune sections below sumOfRadii
if (!geoid && !dist.r) {
return 0.0;
}
double minDist = dist.PeriodsAtMin(correct, per);
if (!correct) {
return (upperBound ? DBL_MAX : 0.0);
}
if (minDist < sumOfRadii) {
per.Get(0, ivMin); // contains only one interval
instMin = ivMin.start; // same as end
// cout << "distance between " << cup1 << " and " << cup2 << " is "
// << urDist << endl << " minimum "
// << urDist.PeriodsAtMin(correct, per) << " at " << instMin;
CcReal ccSumOfRadii(true, sumOfRadii);
std::vector<UReal> urNulls;
int numOfNulls = dist.AtValue(ccSumOfRadii, urNulls);
// cout << " sumOfRadii " << sumOfRadii << " reached "
// << numOfNulls << " times:" << endl << " "
// << (numOfNulls > 0 ?
// (urNulls[0].IsDefined() ? urNulls[0] : "UNDEF") : 0)
// << endl << " "
// << (numOfNulls > 1 ?
// (urNulls[1].IsDefined() ? urNulls[1] : "UNDEF") : 1)
// << endl;
if (numOfNulls == 0) { // sumOfRadii not assumed; no relevant section
return 0.0;
}
else if (numOfNulls == 1) {
instNull1 = urNulls[0].timeInterval.start; // same as end
if (instNull1 < instMin) { // left of minimum
dist.timeInterval.end = instNull1;
}
else {
dist.timeInterval.start = instNull1;
}
integralValue1 = dist.Integrate();
if (isnan(integralValue1)) {
return 0.0;
}
dur = (dist.timeInterval.end - dist.timeInterval.start).ToDouble();
// cout << " RESULT 1 = " << integralValue1 << " - " << sumOfRadii
// << " * " << dur << " = "
// << std::max(0.0, integralValue1 - sumOfRadii * dur) << endl;
result = std::max(0.0, integralValue1 - sumOfRadii * dur);
}
else { // numOfNulls == 2; left of instNull1, right of instNull2
instNull1 = urNulls[0].timeInterval.start; // same as end
instNull2 = urNulls[1].timeInterval.start; // same as end
urNull = dist;
urNull.timeInterval.end = instNull1;
integralValue1 = urNull.Integrate();
urNull.timeInterval.start = instNull2;
urNull.timeInterval.end = dist.timeInterval.end;
integralValue2 = urNull.Integrate();
if (isnan(integralValue1) || isnan(integralValue2)) {
return 0.0;
}
result = std::max(0.0, integralValue1 - sumOfRadii *
(instNull1 - dist.timeInterval.start).ToDouble())
+ std::max(0.0, integralValue2 - sumOfRadii *
(dist.timeInterval.end - instNull2).ToDouble());
// cout << " RES 2 = " << integralValue1 << " - " << sumOfRadii
// << " * " << (instNull1 - dist.timeInterval.start) << " + "
// << integralValue2 << " - " << sumOfRadii << " * "
// << (dist.timeInterval.end - instNull2) << " = " << result
// << endl;
}
}
else { // no shifting required because min >= sumOfRadii
integralValue1 = dist.Integrate();
if (isnan(integralValue1)) {
return 0.0;
}
result = std::max(0.0, integralValue1 - sumOfRadii * dur);
DateTime dura(durationtype);
dura.ReadFrom(dur);
// cout << *this << endl << cup << endl << dist << endl
// << "min distance during " << per << " is "
// << dist.PeriodsAtMin(correct, per) << endl;
// cout << " RESULT = " << integralValue1 << " - " << sumOfRadii
// << " * " << dura << " = "
// << std::max(0.0, integralValue1 - sumOfRadii * dur) << endl;
}
}
else { // case upperbound starts here
if (!dist.IsDefined()) {
std::cerr << __PRETTY_FUNCTION__ << "Invalid geographic coord!" << endl;
return DBL_MAX;
}
double integralValue(0.0), integralPart(0.0);
// cout << "Integrate sqrt(" << dist.a << " * x^2 + " << dist.b
// << " * x + " << dist.c << ")" << endl;
// datetime::DateTime splitDur(0, 3000, datetime::durationtype);
// std::vector<UReal> parts;
// dist.Split(splitDur, parts);
// for (unsigned int i = 0; i < parts.size(); i++) {
// integralPart = parts[i].Integrate();
integralPart = dist.Integrate();
if (isnan(integralPart) || integralPart < 0.0 || isinf(integralPart)) {
UReal linPart1(true), linPart2(true);
dist.Linearize(linPart1, linPart2);
integralPart = linPart1.Integrate() +
(linPart2.IsDefined() ? linPart2.Integrate() : 0.0);
// cout << " approx by " << linPart1.Integrate() << " + "
// << (linPart2.IsDefined() ? linPart2.Integrate() : 0.0) << endl;
if (isnan(integralPart) || integralPart < 0.0) {
cout << "#################§§§§§§§§§" << endl;
assert(false);
}
}
integralValue += integralPart;
// cout << "integralSum is now " << integralSum << endl;
// }
DateTime dura(durationtype);
dura.ReadFrom(dur);
result = integralValue + sumOfRadii * dur;
// cout << " urDist = " << dist << " ==> RESULTub = " << integralValue
// << " + " << sumOfRadii << " * " << dura << " = " << result
// << endl << endl;
}
return result;
}
double CUPoint::DistanceAvg(const CUPoint& cup, const DateTime& duration,
const bool upperBound, const Geoid* geoid /* = 0 */) const {
if (!IsDefined() && !cup.IsDefined()) {
return 0.0;
}
if (!IsDefined() || !cup.IsDefined()) {
return DBL_MAX;
}
if (*this == cup) {
return 0.0;
}
CMPoint cm1(true), cm2(true);
cm1.Add(*this);
cm2.Add(cup);
return DistanceComputation<CMPoint, CUPoint>::DistanceAvg(cm1, cm2, duration,
upperBound, geoid);
}
void CUPoint::DistanceAvg(const CUPoint& cup, const DateTime& duration,
const bool upperBound, CcReal& result, const Geoid* geoid /* = 0 */) const {
if (!IsDefined() || !cup.IsDefined() || (geoid && !geoid->IsDefined())) {
result.SetDefined(false);
return;
}
result.Set(true, roundToNPlaces(this->DistanceAvg(cup, duration, upperBound,
geoid), 6));
}
void CUPoint::SetToConstantUnit(const Point& p, const double r) {
((UPoint*)this)->SetToConstantUnit(p);
SetRadius(r);
}
/*
Implementation of methods for class ~GridCellSeq~
*/
GridCellSeq::GridCellSeq() :
my_enterTime(instanttype),
my_leaveTime(instanttype),
my_cellNo(0),
defined(false){}
GridCellSeq::GridCellSeq(const DateTime &enter,
const DateTime &leave, const int32_t &cellNo)
: my_enterTime(enter), my_leaveTime(leave), my_cellNo(cellNo)
{
defined = my_enterTime.IsDefined()
&& my_leaveTime.IsDefined()
&& (my_enterTime <= my_leaveTime);
}
GridCellSeq::GridCellSeq(const GridCellSeq &other) :
my_enterTime(other.my_enterTime),
my_leaveTime(other.my_leaveTime),
my_cellNo(other.my_cellNo),
defined(other.defined){
}
GridCellSeq& GridCellSeq::operator=(const GridCellSeq &other){
my_enterTime = other.my_enterTime;
my_leaveTime = other.my_leaveTime;
my_cellNo = other.my_cellNo;
defined = other.defined;
return *this;
}
GridCellSeq::~GridCellSeq(){}
DateTime GridCellSeq::getEnterTime() const {return my_enterTime;}
DateTime GridCellSeq::getLeaveTime() const {return my_leaveTime;}
int32_t GridCellSeq::getCellNo() const {return my_cellNo;}
void GridCellSeq::setCellNo(const int32_t &n) { my_cellNo = n; }
void GridCellSeq::setEnterTime(const DateTime &t) {
my_enterTime = t;
defined = my_enterTime.IsDefined()
&& my_leaveTime.IsDefined()
&& (my_enterTime <= my_leaveTime);
}
void GridCellSeq::setLeaveTime(const DateTime &t) {
my_leaveTime = t;
defined = my_enterTime.IsDefined()
&& my_leaveTime.IsDefined()
&& (my_enterTime <= my_leaveTime);
}
void GridCellSeq::setUndefined(){ defined = false; }
bool GridCellSeq::IsDefined() const{ return defined; }
void GridCellSeq::set(const int32_t &c, const DateTime &s, const DateTime &e){
my_cellNo = c;
my_enterTime = s;
my_leaveTime = e;
defined = my_enterTime.IsDefined()
&& my_leaveTime.IsDefined()
&& (my_enterTime <= my_leaveTime);
}
std::ostream& GridCellSeq::Print( std::ostream &os ) const{
if( !IsDefined() )
{
return os << "(GridCellSeq: undefined)";
}
os << "(GridCellSeq: defined, Cell:" << my_cellNo << ", Tenter:"
<< my_enterTime << ", Tleave:" << my_leaveTime << ")" << endl;
return os;
}
std::ostream& operator<<(std::ostream& o, const GridCellSeq& u){
return u.Print(o);
}
bool myCompare (DateTime i, DateTime j) { return (i<j); }
void UPoint::GetGridCellSequence(CellGrid2D &g, std::vector<GridCellSeq> &res){
// cout << __PRETTY_FUNCTION__ << " called..." << endl;
// cout << "\t*this = " << *this << endl;
res.clear();
res.resize(0);
if(!IsDefined() && !g.IsDefined()){
// cout << "\t*this is undefined." << endl;
// cout << __PRETTY_FUNCTION__ << " finished." << endl;
return;
}
double minX = std::min(p0.GetX(),p1.GetX());
double minY = std::min(p0.GetY(),p1.GetY());
double maxX = std::max(p0.GetX(),p1.GetX());
double maxY = std::max(p0.GetY(),p1.GetY());
if( (minX > g.getMaxX()) || (minY > g.getMaxY())
|| (maxX < g.getMinX()) || (maxY < g.getMinY())){
// p0 and p1 outside the grid and unit does not cross the grid.
// Complete unit out of grid: return empty result.
// cout << "\t*this located completely off the grid. No result!" << endl;
// cout << __PRETTY_FUNCTION__ << " finished." << endl;
return;
}
if(AlmostEqual(p0,p1)){
// special case: static unit
// cout << "\tSpecial case: static unit." << endl;
double x = (p0.GetX() + p1.GetX())/2;
double y = (p0.GetY() + p1.GetY())/2;
if(g.onGrid(x,y)){
GridCellSeq event( timeInterval.start,
timeInterval.end,
g.getCellNo(x,y)
);
res.push_back(event);
// cout << "\t\tAdded to Result: " << event << endl;
}
// cout << __PRETTY_FUNCTION__ << " finished." << endl;
return;
}
UPoint unit_before(false);
UPoint unit_inside(false);
UPoint unit_after(false);
// get unit restricted to period while moving inside the grid
// cout << "\t\tMBR(g) = " << g.getMBR() << endl;
At(g.getMBR(), unit_inside);
// cout << "\t\tunit_inside = " << unit_inside << endl;
if( unit_inside.IsDefined()
&& (timeInterval.start < unit_inside.timeInterval.start) ){
// get unit restricted to period before entering the grid
Interval<Instant> i( timeInterval.start,
unit_inside.timeInterval.start,
timeInterval.lc,
!unit_inside.timeInterval.rc);
if(i.IsValid()){
unit_before.SetDefined(true);
AtInterval( i, unit_before );
}
}
// cout << "\t\tunit_before = " << unit_before << endl;
if( unit_inside.IsDefined()
&& (timeInterval.end > unit_inside.timeInterval.end) ){
// get unit restricted to period after leaving the grid
Interval<Instant> i( unit_inside.timeInterval.end,
timeInterval.end,
!unit_inside.timeInterval.rc,
timeInterval.rc);
if(i.IsValid()){
unit_after.SetDefined(true);
AtInterval( i, unit_after );
}
}
// cout << "\t\tunit_after = " << unit_after << endl;
// (1) handle part of unit before entering the grid (if present)
// cout << "\t(1) handle part of unit before entering the grid (if present)"
// << endl;
if(unit_before.IsDefined()){
GridCellSeq event( unit_before.timeInterval.start,
unit_before.timeInterval.end,
g.getInvalidCellNo() );
res.push_back(event);
// cout << "\t\tAdded to Result: " << event << endl;
}
// (2) handle part of unit fully within the grid (if present)
// this part of the unit may cover several grid cells.
// cout << "\t(2) handle part of unit fully within the grid (if present)"
// << endl;
if(unit_inside.IsDefined()){
// create a vector of events where the unit crosses horizontal or vertical
// grid lines and oder them by increasing time.
minX = std::min(unit_inside.p0.GetX(),unit_inside.p1.GetX());
minY = std::min(unit_inside.p0.GetY(),unit_inside.p1.GetY());
maxX = std::max(unit_inside.p0.GetX(),unit_inside.p1.GetX());
maxY = std::max(unit_inside.p0.GetY(),unit_inside.p1.GetY());
int32_t startRow = g.getYIndex(minY);
int32_t endRow = g.getYIndex(maxY);
int32_t startCol = g.getXIndex(minX);
int32_t endCol = g.getXIndex(maxX);
std::vector<DateTime> events;
events.push_back(unit_inside.timeInterval.start); // add start
// cout << "\t\tAdded initial instant: " << unit_inside.timeInterval.start
// << endl;
events.push_back(unit_inside.timeInterval.end); // add end;
// cout << "\t\tAdded final instant: " << unit_inside.timeInterval.end
// << endl;
// create horizontal events
// cout << "\tProcessing crossings of horizontal grid lines..." << endl;
for(int32_t row=startRow; row<=endRow; row++){
Rectangle<2> rowRect = g.getRowMBR(row);
// cout << "\t\tRect for row " << row << ": " << rowRect << endl;
if(rowRect.IsDefined()){
UPoint rowUnit(true);
unit_inside.At(rowRect, rowUnit);
// cout << "\t\trowUnit after At(): " << rowUnit << endl;;
if(rowUnit.IsDefined()){
events.push_back(rowUnit.timeInterval.end);
// cout << "\t\tAdded 'vertical' instant " << rowUnit.timeInterval.end
// << endl;
} else { // drop the unit
// cout << endl << "\t\trow " << row << ": undefined rowUnit"
// << " dropped." << endl;
}
} else {
// cout << endl << "\t\trow " << row << ": undefined rowRect!" << endl;
assert( false );
}
}
// create vertical events
// cout << "\tProcessing crossings of vertical grid lines..." << endl;
for(int32_t col=startCol; col<=endCol; col++){
Rectangle<2> colRect = g.getColMBR(col);
// cout << "\t\tRect for col " << col << ": " << colRect << endl;
if(colRect.IsDefined()){
UPoint colUnit(true);
unit_inside.At(colRect, colUnit);
// cout << "\t\tcolUnit after At(): " << colUnit << endl;;
if(colUnit.IsDefined()){
events.push_back(colUnit.timeInterval.end);
// cout << "\t\tAdded 'horizontal' instant "
// << colUnit.timeInterval.end << endl;
} else { // drop the unit
// cout << endl << "\t\tcolumn " << col << ": undefined colUnit"
// << " dropped." << endl;
}
} else {
// cout << endl << "\t\tcolumn " << col << ": undefined colRect!"
// << endl;
assert( false );
}
}
// sort all events
// cout << "\n\tevents before sorting:" << endl;
// for(vector<DateTime>::iterator j = events.begin(); j< events.end(); j++){
// cout << "\t\t" << *j << endl;
// }
// cout << endl;
// cout << "\tSorting instants..." << endl;
sort(events.begin(), events.end(), myCompare);
// cout << "\n\tevents after sorting:" << endl;
// for(vector<DateTime>::iterator j = events.begin(); j< events.end(); j++){
// cout << "\t\t" << *j << endl;
// }
// cout << endl;
// Handle all events. If two consecutive events have almost the same time,
// merge them into a single event. For each remaining event create a result
// entry. Use midpoints between two consecutive events to compute according
// cell number
// cout << "\tProcessing instants..." << endl;
std::vector<DateTime>::iterator curr;
std::vector<DateTime>::iterator last = events.begin();
for(curr = events.begin(); curr< events.end(); curr++){
if(*curr == *last){
// for 1st entry: just proceed
// cout << "\t\tFound equal instants: *curr=" << *curr << " *last="
// << *last << endl;
continue;
}
// create output
DateTime midtime(instanttype);
midtime = *last + ((*curr - *last)/2);
Point midpoint(true);
TemporalFunction(midtime, midpoint, true);
int32_t cellno = midpoint.IsDefined()? g.getCellNo(midpoint.GetX(),
midpoint.GetY())
: g.getInvalidCellNo();
if(g.isValidCellNo(cellno)){
GridCellSeq event( *last, *curr, cellno);
res.push_back(event);
// cout << "\t\tAdded to Result: " << event << endl;
}
last = curr;
}
}
// (3) handle part of unit after leaving the grid (if present)
// cout << "\t(3) handle part of unit after leaving the grid (if present)"
// << endl;
if(unit_after.IsDefined()){
GridCellSeq event( unit_after.timeInterval.start,
unit_after.timeInterval.end,
g.getInvalidCellNo());
res.push_back(event);
// cout << "\t\tAdded to Result: " << event << endl;
}
// cout << "\n\tFinal result: res = :" << endl;
// for(vector<GridCellSeq>::iterator i = res.begin(); i < res.end(); i++){
// cout << "\t\t" << *i << endl;
// }
// cout << endl;
// cout << __PRETTY_FUNCTION__ << " finished." << endl;
return;
}
/*
3.2 Class ~MInt~
*/
void MInt::ReadFrom(const MBool& arg){
// remove all units
Clear();
if(!arg.IsDefined()){
SetDefined(false);
return;
}
SetDefined(true);
int size = arg.GetNoComponents();
if(size>0){
Resize(size);
}
UBool ubool;
StartBulkLoad();
CcInt currentValue;
for(int i=0;i<size;i++){
arg.Get(i,ubool);
bool v;
v = ubool.constValue.GetBoolval();
currentValue.Set(true,v?1:0);
UInt unit(ubool.timeInterval,currentValue);
Add(unit);
}
EndBulkLoad(false);
}
void MInt::WriteTo(MBool& arg){
// remove all units
arg.Clear();
if(!IsDefined()){
arg.SetDefined(false);
return;
}
arg.SetDefined(true);
int size = GetNoComponents();
if(size>0){
arg.Resize(size);
}
UInt uint;
//arg.StartBulkLoad();
CcBool currentValue;
for(int i=0;i<size;i++){
Get(i,uint);
int v;
v = uint.constValue.GetIntval();
currentValue.Set(true,(v==0)?false:true);
UBool unit(uint.timeInterval,currentValue);
arg.Add(unit);
}
//EndBulkLoad(false);
}
void MInt::WriteTo(MReal& arg){
// remove all units
arg.Clear();
if(!IsDefined()){
arg.SetDefined(false);
return;
}
arg.SetDefined(true);
int size = GetNoComponents();
if(size>0){
arg.Resize(size);
}
UInt uint;
//arg.StartBulkLoad();
for(int i=0;i<size;i++){
Get(i,uint);
double v = (double)uint.constValue.GetIntval();
UReal ureal(uint.timeInterval, v, v);
arg.Add(ureal);
}
//EndBulkLoad(false);
}
bool compareuint(const UInt& u1,const UInt& u2)
{
if( !u1.IsDefined() && u1.IsDefined() )
return true;
if( !u1.IsDefined() || !u1.IsDefined() )
return false;
if(u1.timeInterval.start < u2.timeInterval.start)
return true;
if(u1.timeInterval.start == u2.timeInterval.start)
if(u1.timeInterval.end <= u2.timeInterval.end)
return true;
return false;
}
void MInt::SortbyUnitTime()
{
units.Sort(UnitCompare<UInt>);
}
void MInt::Hat(MInt& mint)
{
mint.Clear();
if( !IsDefined() ){
mint.SetDefined( false );
return;
}
mint.SetDefined( true );
std::stack<UInt> uintstack;
UInt upi;
UInt last,curuint;
CcInt cur,top;
last.SetDefined(true);
curuint.SetDefined(false);
float lastarea = 0.0;
Get(0,upi);
std::string starttime = upi.timeInterval.start.ToString();
Get(GetNoComponents() - 1,upi);
std::string endtime = upi.timeInterval.end.ToString();
int nocomponents;
int i;
bool defstart;
if(starttime == "begin of time" && endtime == "end of time"){
i = 1;
nocomponents = GetNoComponents() - 1;
assert(GetNoComponents() >= 3);
defstart = true;
}else{
i = 0;
nocomponents = GetNoComponents();
assert(GetNoComponents() >= 1);
defstart = false;
}
for(;i < nocomponents;i++){
Get(i,upi);
if(!uintstack.empty()){
cur.Set(upi.constValue.GetValue());
top.Set(uintstack.top().constValue.GetValue());
if(cur.GetIntval() >= top.GetIntval()){
uintstack.push(upi);
}
else{
Instant end = upi.timeInterval.start;
Instant start = upi.timeInterval.start;
int lastvalue = 0;
while(!uintstack.empty() && cur.GetIntval() < top.GetIntval()){
UInt topelem = uintstack.top();
lastvalue = topelem.constValue.GetValue();
start = topelem.timeInterval.start;
uintstack.pop();
if(!uintstack.empty())
top.Set(uintstack.top().constValue.GetValue());
if(lastarea == 0.0){
lastarea = (end-topelem.timeInterval.start).ToDouble()*lastvalue;
curuint.timeInterval.start = topelem.timeInterval.start;
curuint.timeInterval.end = end;
curuint.timeInterval.lc = true;
curuint.timeInterval.rc = false;
curuint.constValue.Set(lastvalue);
curuint.SetDefined(true);
}else{
double curarea =
lastvalue*(end-topelem.timeInterval.start).ToDouble();
if(curarea > lastarea){
lastarea = curarea;
curuint.timeInterval.start = topelem.timeInterval.start;
curuint.timeInterval.end = end;
curuint.timeInterval.lc = true;
curuint.timeInterval.rc = false;
curuint.constValue.Set(lastvalue);
curuint.SetDefined(true);
}
}
}
UInt* tempuint = new UInt(upi);
// (const_cast<UInt*>(upi))->timeInterval.start = start;
tempuint->timeInterval.start = start;
uintstack.push(*tempuint);
delete tempuint;
// uintstack.push(upi);
}
}else
uintstack.push(upi);
}
// curuint.Print(cout);
// cout<<endl;
while(!uintstack.empty())
uintstack.pop();//clear stack
if(curuint.IsDefined() == true){//find hat
UInt begin,end;
begin.SetDefined(true);
if(defstart){//define "begin of time"
Get(0,upi);
begin = upi;
mint.Add(begin);
Get(1,upi);
}else
Get(0,upi);
begin.timeInterval.start = upi.timeInterval.start;
begin.timeInterval.lc = true;
begin.timeInterval.end = curuint.timeInterval.start;
begin.timeInterval.rc = false;
int value = upi.constValue.GetValue();
int i;
for(i = 1;i < nocomponents;i++){
Get(i,upi);
if(upi.timeInterval.start >= curuint.timeInterval.start)
break;
if(upi.constValue.GetValue() < value)
value = upi.constValue.GetValue();//the minimum value before hat
}
begin.constValue.Set(value);
// assert(begin.timeInterval.start != begin.timeInterval.end);
if(begin.timeInterval.IsValid())
mint.Add(begin);
if(curuint.timeInterval.IsValid())//start != curuint.timeInterval.end)
mint.Add(curuint);
end.SetDefined(true);
if(defstart){//define "end of time"
Get(GetNoComponents() - 2,upi);
end.timeInterval.start = curuint.timeInterval.end;
end.timeInterval.lc = true;
end.timeInterval.end = upi.timeInterval.end;
end.timeInterval.rc = false;
value = curuint.constValue.GetValue();
for(;i < nocomponents;i++){
Get(i,upi);
if(upi.timeInterval.start < curuint.timeInterval.end)
continue;
if(upi.constValue.GetValue() < value)
value = upi.constValue.GetValue();
}
end.constValue.Set(value);
// assert(end.timeInterval.start != end.timeInterval.end);
if(end.timeInterval.IsValid())
mint.Add(end);
Get(GetNoComponents() - 1,upi);
end = upi;
mint.Add(end);
}else{
Get(GetNoComponents() - 1,upi);
end.timeInterval.start = curuint.timeInterval.end;
end.timeInterval.lc = true;
end.timeInterval.end = upi.timeInterval.end;
end.timeInterval.rc = false;
value = curuint.constValue.GetValue();
for(;i < GetNoComponents();i++){
Get(i,upi);
if(upi.timeInterval.start < curuint.timeInterval.end)
continue;
if(upi.constValue.GetValue() < value)
value = upi.constValue.GetValue();
}
end.constValue.Set(value); //the same as hat threshold
// assert(end.timeInterval.start != end.timeInterval.end);
if(end.timeInterval.IsValid())
mint.Add(end);
}
}
else{ //hat does not exist,return the first and last
UInt begin,end;
UInt upi1;
UInt upi2;
begin.SetDefined(true);
end.SetDefined(true);
if(defstart){
Get(0,upi1);
begin = upi1;
mint.Add(begin);
Get(1,upi1);
}else
Get(0,upi1);
int firstvalue = upi.constValue.GetValue();
if(defstart)
Get(GetNoComponents() - 2,upi2);
else
Get(GetNoComponents() - 1,upi2);
int lastvalue = upi2.constValue.GetValue();
if(firstvalue != lastvalue){
begin = upi1;
mint.Add(begin);
end = upi2;
mint.Add(end);
if(defstart){
Get(GetNoComponents() - 1,upi2);
end = upi2;
mint.Add(end);
}
}else{
if(defstart){
begin.constValue.Set(firstvalue);
begin.timeInterval.start = upi1.timeInterval.start;
begin.timeInterval.end = upi2.timeInterval.end;
begin.timeInterval.lc = true;
begin.timeInterval.rc = false;
mint.Add(begin);
Get(GetNoComponents() - 1,upi2);
end = upi2;
mint.Add(end);
}else{
begin = upi1;
begin.timeInterval.end = upi2.timeInterval.end;
mint.Add(begin);
}
}
}
}
void MInt::Restrict(MInt& result,
const bool useValue /*= false */,
const int value /*= 0*/ ) const{
result.Clear();
if(!IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined(true);
int size = GetNoComponents();
if(size==0){
return;
}
result.Resize(size);
int last = size-1;
for(int i=0;i<size;i++){
UInt unit;
Get(i,unit);
if(i==0 || i==last){
if(unit.timeInterval.start.IsMinimum() ||
unit.timeInterval.end.IsMaximum()){
if(useValue && unit.constValue.GetIntval()!=value){
result.Add(unit);
}
} else {
result.Add(unit);
}
} else {
result.Add(unit);
}
}
}
/*
~PlusExtend~
This function adds the moving integer values. In contrast to the
usual '+' function, the result will only be undefined, if both
arguments are undefined. If only a single argeument is undefined,
the value of the second parameter build the resulting unit.
*/
void MInt::PlusExtend(const MInt* arg2, MInt& result) const
{
result.Clear();
if(!this->IsDefined() && !arg2->IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined(true);
UInt uInt(true);
RefinementStream<MInt, MInt, UInt, UInt> rp(this, arg2);
result.StartBulkLoad();
Interval<Instant> iv;
int u1Pos;
int u2Pos;
UInt u1;
UInt u2;
while(rp.hasNext()){
rp.getNext(iv, u1Pos, u2Pos);
if(u1Pos!=-1 || u2Pos!=-1){
uInt.timeInterval = iv;
if(u1Pos == -1 ){
arg2->Get(u2Pos,u2);
uInt.constValue.Set(true, u2.constValue.GetIntval());
} else if(u2Pos == -1){
this->Get(u1Pos,u1);
uInt.constValue.Set(true, u1.constValue.GetIntval());
} else {
this->Get(u1Pos, u1);
arg2->Get(u2Pos, u2);
uInt.constValue.Set(true,
u1.constValue.GetIntval() + u2.constValue.GetIntval());
}
result.MergeAdd(uInt);
}
}
result.EndBulkLoad(false);
}
void MInt::MergeAddFillUp(const UInt& unit, const int fillValue){
assert(IsDefined());
assert(unit.IsDefined());
if(!this->IsDefined() || !unit.IsDefined()){
Clear();
SetDefined(false);
return;
}
int size = units.Size();
if(size==0){
units.Append(unit);
} else {
UInt lastUnitp;
units.Get(size-1, &lastUnitp);
UInt lastUnit(lastUnitp);
int lastValue = lastUnit.constValue.GetIntval();
int newValue = unit.constValue.GetIntval();
if(lastUnit.timeInterval.end == unit.timeInterval.start){
if(lastValue == newValue){
lastUnit.timeInterval.end = unit.timeInterval.end;
lastUnit.timeInterval.rc = unit.timeInterval.rc;
units.Put(size-1,lastUnit);
} else {
// don't allow overlapping intervals
assert(!(lastUnit.timeInterval.rc && unit.timeInterval.lc));
// no gap in time
if(lastUnit.timeInterval.rc || unit.timeInterval.lc){
units.Append(unit);
} else { // gap in time
if(lastValue==fillValue){
lastUnit.timeInterval.rc = true;
units.Put(size-1, lastUnit);
units.Append(unit);
} else if(newValue==fillValue){
UInt copy(unit);
copy.timeInterval.lc = true;
units.Append(copy);
} else {
Interval<Instant> iv(unit.timeInterval.start,
unit.timeInterval.start,
true, true);
CcInt aValue(true,fillValue);
UInt aUnit(iv,aValue);
units.Append(aUnit);
units.Append(unit);
}
}
}
} else { // a "real" gap in time
assert(lastUnitp.timeInterval.end < unit.timeInterval.start);
if(lastValue==fillValue){
if(fillValue==newValue){ // merge three units
lastUnit.timeInterval.end = unit.timeInterval.end;
lastUnit.timeInterval.rc = unit.timeInterval.rc;
units.Put(size-1,lastUnit);
} else {
lastUnit.timeInterval.end = unit.timeInterval.start;
lastUnit.timeInterval.rc = !unit.timeInterval.lc;
units.Put(size-1, lastUnit);
units.Append(unit);
}
} else { // lastUnit and fillUnit cannot be merged
if(newValue==fillValue){ // fillUnit and newUnit can be merged
UInt copy(unit);
copy.timeInterval.start = lastUnit.timeInterval.end;
copy.timeInterval.lc = !lastUnit.timeInterval.rc;
units.Append(copy);
} else { // nothing can be merged
Interval<Instant> iv(lastUnit.timeInterval.end,
unit.timeInterval.start,
!lastUnit.timeInterval.rc,
!unit.timeInterval.lc);
CcInt v(true,fillValue);
UInt fill(iv,v);
units.Append(fill);
units.Append(unit);
}
}
}
}
}
void MInt::fillUp(int value, MInt& result) const{
result.Clear();
if(!IsDefined()){
result.Clear();
result.SetDefined(false);
return;
}
int size = units.Size();
UInt unit;
for(int i=0;i<size;i++){
units.Get(i,&unit);
result.MergeAddFillUp(unit, value);
}
}
int MInt::maximum() const{
int max = std::numeric_limits<int>::min();
if(!IsDefined()){
return max;
}
UInt unit;
int v;
for(int i=0;i<units.Size();i++){
units.Get(i,&unit);
v = unit.constValue.GetIntval();
if(v>max){
max = v;
}
}
return max;
}
int MInt::minimum() const{
int min = std::numeric_limits<int>::max();
if(!IsDefined()){
return min;
}
UInt unit;
int v;
for(int i=0;i<units.Size();i++){
units.Get(i,&unit);
v = unit.constValue.GetIntval();
if(v<min){
min = v;
}
}
return min;
}
int MInt::Min(bool &correct) const
{
correct = IsDefined();
return minimum();
}
int MInt::Max(bool &correct) const
{
correct = IsDefined();
return maximum();
}
/*
3.1 Class ~MReal~
3.1 ~Integrate~
3.1.1 Helper structure
*/
struct ISC{
double value;
unsigned int level;
};
/*
3.1.2 ~Integrate~ Implementation
The integrate function sums all integrate value for the single units.
To avoid adding big and small integer values, we compute the sum
balanced similar to the aggregateB operator of teh ExtRelationAlgebra.
*/
double MReal::Integrate(){
if(!IsDefined()){
return 0;
}
int size = GetNoComponents();
UReal unit;
std::stack<ISC> theStack;
for(int i=0;i < size;i++){
Get(i,unit);
ISC isc;
isc.value = unit.Integrate();
//if(isnan(isc.value)) cout << " value = " << isc.value << endl;
isc.level = 0;
while(!theStack.empty() && (theStack.top().level == isc.level)){
isc.value = isc.value + theStack.top().value;
isc.level = isc.level + 1;
theStack.pop();
}
theStack.push(isc);
}
// summarize the stack content
double sum = 0.0;
while(!theStack.empty()){
sum += theStack.top().value;
theStack.pop();
}
return sum;
}
double MReal::Max(bool& correct) const{
if(!IsDefined()){
correct=false;
return 0.0;
}
int size = GetNoComponents();
if(size<=0){
correct=false;
return 0.0;
}
correct = true;
UReal unit;
Get(0,unit);
bool dummy;
double max = unit.Max(dummy);
for(int i=1;i<size;i++){
Get(i,unit);
double umax = unit.Max(dummy);
if(umax>max){
max = umax;
}
}
return max;
}
double MReal::Min(bool& correct) const{
if(!IsDefined()){
correct=false;
return 0.0;
}
int size = GetNoComponents();
if(size<=0){
correct=false;
return 0.0;
}
correct = true;
UReal unit;
Get(0,unit);
bool dummy;
double min = unit.Min(dummy);
for(int i=1;i<size;i++){
Get(i,unit);
double umin = unit.Min(dummy);
if(umin<min){
min = umin;
}
}
return min;
}
// restrict to periods with minimum value
void MReal::AtMin( MReal& result ) const
{
result.Clear();
if(!IsDefined()){
result.SetDefined( false );
return;
}
result.SetDefined( true );
double globalMin = std::numeric_limits<double>::infinity();
double localMin = 0.0;
int noLocalMin = 0;
bool correct = true;
UReal actual_ur(false);
UReal last_ur(false);
UReal last_candidate(true);
bool firstCall = true;
result.StartBulkLoad();
for(int i=0; i<GetNoComponents(); i++)
{
// std::cerr << "MReal::AtMin(): Processing unit "
// << i << "..." << endl;
last_ur = actual_ur;
Get( i, actual_ur );
localMin = actual_ur.Min(correct);
if(!correct)
{
std::cerr << "MReal::AtMin(): Cannot compute minimum value for unit "
<< i << "." << endl;
continue;
}
if( localMin < globalMin )
{ // found new global min, invalidate actual result
globalMin = localMin;
result.Clear();
result.StartBulkLoad(); // we have to repeat this alter Clear()
firstCall = true;
last_ur.SetDefined(false);
// std::cerr << "MReal::AtMin(): New globalMin=" << globalMin << endl;
}
if( localMin <= globalMin )
{ // this ureal contains global minima
std::vector<UReal> localMinimaVec;
noLocalMin = actual_ur.AtMin( localMinimaVec );
// std::cerr << "MReal::AtMin(): Unit " << i << " has "
// << noLocalMin << " minima" << endl;
for(int j=0; j< noLocalMin; j++)
{
UReal candidate = localMinimaVec[j];
// test, whether candidate overlaps last_inserted one
if( j==0 && // check only unit's first local min!
!firstCall && // don't check if there is no last_candidate
last_candidate.Intersects(candidate) &&
( !last_ur.Intersects(last_candidate) ||
!actual_ur.Intersects(candidate)
)
)
{
// std::cerr << "MReal::AtMin(): unit overlaps last one." << endl;
if( last_candidate.timeInterval.start
== last_candidate.timeInterval.end )
{ // case 1: drop last_candidate (which is an instant-unit)
// std::cerr << "MReal::AtMin(): drop last unit." << endl;
last_candidate = candidate;
continue;
}
else if( candidate.timeInterval.start
== candidate.timeInterval.end )
{ // case 2: drop candidate
// std::cerr << "MReal::AtMin(): drop actual unit." << endl;
continue;
}
else
std::cerr << "MReal::AtMin(): This should not happen!" << endl;
}
else
{ // All is fine. Just insert last_candidate.
if(firstCall)
{
firstCall = false;
}
else
{
// std::cerr << "MReal::AtMin(): Added last unit" << endl;
result.MergeAdd(last_candidate);
}
last_candidate = candidate;
}
}
}
// else
// {
// std::cerr << "MReal::AtMin(): Unit " << i
// << " has no global minimum." << endl;
// }
}
if(!firstCall)
{
result.MergeAdd(last_candidate);
// std::cerr << "MReal::AtMin(): Added final unit" << endl;
}
// else
// std::cerr << "MReal::AtMin(): Skipping insertion of final unit." << endl;
result.EndBulkLoad();
}
// restrict to periods with maximum value
void MReal::AtMax( MReal& result ) const
{
result.Clear();
if(!IsDefined()){
result.SetDefined( false );
return;
}
result.SetDefined( true );
double globalMax = -std::numeric_limits<double>::infinity();
double localMax = 0.0;
int noLocalMax = 0;
bool correct = true;
UReal actual_ur(false);
UReal last_ur(false);
UReal last_candidate(true);
bool firstCall = true;
result.StartBulkLoad();
for(int i=0; i<GetNoComponents(); i++)
{
// std::cerr << "MReal::AtMax(): Processing unit "
// << i << "..." << endl;
last_ur = actual_ur;
Get( i, actual_ur );
localMax = actual_ur.Max(correct);
if(!correct)
{
std::cerr << "MReal::AtMax(): Cannot compute maximum value for unit "
<< i << "." << endl;
continue;
}
if( localMax > globalMax )
{ // found new global max, invalidate actual result
globalMax = localMax;
result.Clear();
result.StartBulkLoad(); // we have to repeat this alter Clear()
firstCall = true;
last_ur.SetDefined(false);
// std::cerr << "MReal::AtMax(): New globalMax=" << globalMax << endl;
}
if( localMax >= globalMax )
{ // this ureal contains global maxima
std::vector<UReal> localMaximaVec;
noLocalMax = actual_ur.AtMax( localMaximaVec );
// std::cerr << "MReal::AtMax(): Unit " << i << " has "
// << noLocalMax << " maxima" << endl;
for(int j=0; j< noLocalMax; j++)
{
UReal candidate = localMaximaVec[j];
// test, whether candidate overlaps last_inserted one
if( j==0 && // check only unit's first local max!
!firstCall && // don't check if there is no last_candidate
last_candidate.Intersects(candidate) &&
( !last_ur.Intersects(last_candidate) ||
!actual_ur.Intersects(candidate)
)
)
{
// std::cerr << "MReal::AtMax(): unit overlaps last one." << endl;
if( last_candidate.timeInterval.start
== last_candidate.timeInterval.end )
{ // case 1: drop last_candidate (which is an instant-unit)
// std::cerr << "MReal::AtMax(): drop last unit." << endl;
last_candidate = candidate;
continue;
}
else if( candidate.timeInterval.start
== candidate.timeInterval.end )
{ // case 2: drop candidate
// std::cerr << "MReal::AtMax(): drop actual unit." << endl;
continue;
}
else
std::cerr << "MReal::AtMax(): This should not happen!" << endl;
}
else
{ // All is fine. Just insert last_candidate.
if(firstCall)
{
firstCall = false;
}
else
{
// std::cerr << "MReal::AtMax(): Added last unit" << endl;
result.MergeAdd(last_candidate);
}
last_candidate = candidate;
}
}
}
// else
// {
// std::cerr << "MReal::AtMax(): Unit " << i
// << " has no global maximum." << endl;
// }
}
if(!firstCall)
{
result.MergeAdd(last_candidate);
// std::cerr << "MReal::AtMax(): Added final unit" << endl;
}
// else
// std::cerr << "MReal::AtMax(): Skipping insertion of final unit." << endl;
result.EndBulkLoad();
}
// restrict to periods with certain value
void MReal::AtValue( const CcReal& ccvalue, MReal& result ) const
{
result.Clear();
if(!IsDefined() || !ccvalue.IsDefined()){
result.SetDefined( false );
return;
}
result.SetDefined( true );
int noLocalResults = 0;
UReal actual_ur(false);
UReal last_ur(false);
UReal last_candidate(false);
bool firstCall = true;
result.StartBulkLoad();
for(int i=0; i<GetNoComponents(); i++)
{
// std::cerr << "MReal::AtValue(): Processing unit "
// << i << "..." << endl;
last_ur = actual_ur;
// cout << __PRETTY_FUNCTION__ << ": last_ur ="; last_ur.Print(cout);
// cout << endl;
Get( i, actual_ur );
// cout << __PRETTY_FUNCTION__ << ": actual_ur ="; actual_ur.Print(cout);
// cout << endl;
assert( actual_ur.IsDefined() );
std::vector<UReal> localResultVec;
noLocalResults = actual_ur.AtValue( ccvalue, localResultVec );
// std::cerr << "MReal::AtValue(): Unit " << i << " has "
// << noLocalResults << " results" << endl;
for(int j=0; j< noLocalResults; j++)
{
UReal candidate = localResultVec[j];
// cout << "\t" << __PRETTY_FUNCTION__ << ": candidate=";
// candidate.Print(cout); cout << endl;
// test, whether candidate overlaps last_inserted one
if( j==0 && // check only unit's first local max!
!firstCall && // don't check if there is no last_candidate
last_candidate.Intersects(candidate) &&
( !last_ur.Intersects(last_candidate) ||
!actual_ur.Intersects(candidate)
)
)
{
// std::cerr << "MReal::AtValue(): unit overlaps last one." << endl;
if( last_candidate.timeInterval.start
== last_candidate.timeInterval.end )
{ // case 1: drop last_candidate (which is an instant-unit)
// std::cerr << "MReal::AtValue(): drop last unit." << endl;
last_candidate = candidate;
continue;
}
else if( candidate.timeInterval.start
== candidate.timeInterval.end )
{ // case 2: drop candidate
// std::cerr << "MReal::AtValue(): drop actual unit." << endl;
continue;
}
else {
std::cerr << __PRETTY_FUNCTION__ << ": This should not happen!"
<< endl;
}
}
else
{ // All is fine. Just insert last_candidate.
if(firstCall) {
// std::cerr << "MReal::AtValue(): Skipping insertion of last unit."
// << endl;
firstCall = false;
} else {
// std::cerr << "MReal::AtValue(): Adding last unit" << endl;
result.MergeAdd(last_candidate);
}
last_candidate = candidate;
}
}
// else
// {
// std::cerr << "MReal::AtValue(): Unit " << i
// << " does never take the value." << endl;
// }
}
if(!firstCall){
result.MergeAdd(last_candidate);
// std::cerr << "MReal::AtValue(): Added final unit" << endl;
}
// else{
// }
result.EndBulkLoad();
//cout << __PRETTY_FUNCTION__ << "result = "; Print(cout); cout << endl << endl;
}
/*
This function replaces all units by linear approximations between their
start and end value.
*/
void MReal::Linearize(MReal& result) const{
result.Clear();
if(!IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined(true);
int size = GetNoComponents();
if(size<1){
return;
}
result.Resize(size);
UReal unitptr;
UReal unit;
result.StartBulkLoad();
for(int i=0;i<size;i++){
Get(i,unitptr);
unitptr.Linearize(unit);
result.Add(unit);
}
result.EndBulkLoad(false);
}
/*
This function replaces all units by linear approximations between their
start and end value and possible the extremum.
*/
void MReal::Linearize2(MReal& result) const{
result.Clear();
if(!IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined(true);
int size = GetNoComponents();
if(size<1){
return;
}
result.Resize(size);
UReal unitptr;
UReal unit1;
UReal unit2;
result.StartBulkLoad();
for(int i=0;i<size;i++){
Get(i,unitptr);
unitptr.Linearize(unit1,unit2);
result.Add(unit1);
if(unit2.IsDefined()){
result.Add(unit2);
}
}
result.EndBulkLoad(false);
}
void MReal::Recompute(const MPoint& mp1, const MPoint& mp2, const Geoid* geoid){
UReal ur(true), urPart(true);
Periods per(true);
MPoint mp1Part(true), mp2Part(true);
UPoint up1(true), up2(true);
for (int i = 0; i < GetNoComponents(); i++) {
Get(i, ur);
per.Add(ur.timeInterval);
mp1.AtPeriods(per, mp1Part);
mp2.AtPeriods(per, mp2Part);
mp1Part.Get(0, up1);
mp2Part.Get(0, up2);
ur.Recompute(up1, up2, geoid);
Put(i, ur);
per.Clear();
}
}
/*
Helper function for the ~simplify~ operator
We keep a unit if it is no linear representation.
*/
bool keep(const UReal* unit){
if(unit->a != 0) { // square included
return true;
}
if(unit->r){ // square-root
return true;
}
return false; // linear or constant function
}
/*
~connected~
Checks whether two ureal values build a continious function.
*/
bool connected(const UReal* ur1, const UReal* ur2){
Instant end = ur1->timeInterval.end;
Instant start = ur2->timeInterval.start;
if(start!=end){
return false;
}
bool rc = ur1->timeInterval.rc;
bool lc = ur2->timeInterval.lc;
if(!(lc ^ rc)){
return false;
}
CcReal endValue(true,0);
CcReal startValue(true,0);
ur1->TemporalFunction(end,endValue,true);
ur2->TemporalFunction(start,startValue,true);
if(!AlmostEqual(endValue.GetRealval(), startValue.GetRealval())){
return false;
}
return true;
}
/*
Simplifies the connected linear approximated parts of this moving real.
*/
void MReal::Simplify(const double epsilon, MReal& result) const{
result.Clear();
if(!IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined(true);
unsigned int size = GetNoComponents();
if(epsilon < 0 || size<2){
result.CopyFrom(this);
return;
}
bool useleft[size];
bool useright[size];
for(unsigned int i=0;i<size;i++){
useleft[i] = false;
useright[i] = false;
}
unsigned int first = 0;
unsigned int last = 1;
UReal ur1;
UReal ur2;
while(last < size){
Get(last-1,ur1);
Get(last, ur2);
if(keep(&ur1)){
if(last-1 > first){
Simplify(first,last-2,useleft,useright,epsilon);
}
Simplify(last-1, last-1, useleft, useright, epsilon);
first = last;
last++;
} else if( keep(&ur2)){
Simplify(first,last-1,useleft,useright,epsilon);
last++;
Simplify(last-1, last-1,useleft,useright,epsilon);
first = last;
last++;
} else if(connected(&ur1,&ur2)){ // enlarge the sequence
last++;
} else {
Simplify(first,last-1,useleft, useright, epsilon);
first=last;
last++;
}
}
Simplify(first,last-1,useleft,useright,epsilon);
// build the result
int count = 1; // count the most right sample point
for( unsigned int i=0;i<size;i++){
if( useleft[i]){
count++;
}
}
result.Resize(count); // prepare enough memory
// scan the units
UReal unit;
Instant start(instanttype);
Instant end(instanttype);
bool lc = false, rc = false;
CcReal startValue(true,0);
CcReal endValue(true,0);
bool leftDefined = false;
result.StartBulkLoad();
for(unsigned int i=0;i<size;i++){
Get(i,unit);
if(useleft[i] && useright[i]){ // copy this unit
result.Add(unit);
} else {
if(useleft[i]){
if(leftDefined){ // debug
std::cerr << "Overwrite left part of a ureal " << endl;
}
start = unit.timeInterval.start;
lc = unit.timeInterval.lc;
unit.TemporalFunction(start,startValue,true);
leftDefined = true;
}
if(useright[i]){
if(!leftDefined){ // debug
std::cerr << "Close ureal without left definition " << endl;
} else{
end = unit.timeInterval.end;
rc = unit.timeInterval.rc;
unit.TemporalFunction(end,endValue,true);
UReal newUnit(Interval<Instant>(start,end,lc,rc),
startValue.GetRealval(),
endValue.GetRealval());
result.Add(newUnit);
leftDefined=false;
}
}
}
}
result.EndBulkLoad(true,true);
}
// A private auxiliary function:
void MReal::Simplify(const int min, const int max,
bool* useleft, bool* useright,
const double epsilon) const{
// the endpoints are used in each case
useleft[min] = true;
useright[max] = true;
if(min==max){ // no intermediate sampling points -> nothing to simplify
return;
}
UReal u1;
UReal u2;
// build a UReal from the endpoints
Get(min,u1);
Get(max,u2);
CcReal cr1(true,0.0);
CcReal cr2(true,0.0);
u1.TemporalFunction(u1.timeInterval.start,cr1,true);
u2.TemporalFunction(u2.timeInterval.end,cr2,true);
double r1 = cr1.GetRealval();
double r2 = cr2.GetRealval();
// build the approximating unit
UReal ureal(Interval<Instant>(u1.timeInterval.start,
u2.timeInterval.end,true,true),
r1,
r2);
// search for the real with the highest distance to this unit
double maxDist = 0;
int maxIndex=0;
CcReal r_orig(true,0);
CcReal r_simple(true,0);
UReal u;
double distance;
for(int i=min+1;i<=max;i++){
Get(i,u);
ureal.TemporalFunction(u.timeInterval.start,r_simple, true);
u.TemporalFunction(u.timeInterval.start,r_orig,true);
distance = std::abs(r_simple.GetRealval()- r_orig.GetRealval());
if(distance>maxDist){ // new maximum found
maxDist = distance;
maxIndex = i;
}
}
if(maxIndex==0){ // no difference found
return;
}
if(maxDist<=epsilon){ // difference is in allowed range
return;
}
// split at the left point of maxIndex
Simplify(min,maxIndex-1,useleft,useright,epsilon);
Simplify(maxIndex,max,useleft,useright,epsilon);
}
/*
3.2 Class ~MPoint~
We need to overwrite some methods from template class ~Mapping~, as we need
to maintain the object's MBR in ~bbox~.
*/
void MPoint::Clear()
{
Mapping<UPoint, Point>::Clear(); // call super
bbox.SetDefined(false); // invalidate bbox
}
void MPoint::Add( const UPoint& unit )
{
// cout << "CALLED: MPoint::Add" << endl;
assert( unit.IsDefined() );
assert( unit.IsValid() );
if(!IsDefined() || !unit.IsDefined()){
SetDefined( false );
return;
}
units.Append( unit );
if(units.Size() == 1)
{
// cout << " MPoint::Add FIRST ADD" << endl;
// cout << "\t Old bbox = "; bbox.Print(cout);
bbox.SetDefined( true );
bbox = unit.BoundingBox();
// cout << "\n\t New bbox = "; bbox.Print(cout);
} else {
// cout << "\t Old bbox = "; bbox.Print(cout);
bbox = bbox.Union(unit.BoundingBox());
// cout << "\n\t New bbox = "; bbox.Print(cout);
}
RestoreBoundingBox(false);
}
void MPoint::Restrict( const std::vector< std::pair<int, int> >& intervals )
{
if(!IsDefined()){
Clear();
bbox.SetDefined(false);
SetDefined( false );
return;
}
units.Restrict( intervals, units ); // call super
bbox.SetDefined(false); // invalidate bbox
RestoreBoundingBox(); // recalculate it
}
std::ostream& MPoint::Print( std::ostream &os ) const
{
if( !IsDefined() )
{
return os << "(MPoint: undefined)";
}
os << "(MPoint: defined, MBR = ";
bbox.Print(os);
os << ", contains " << GetNoComponents() << " units: ";
for(int i=0; i<GetNoComponents(); i++)
{
UPoint unit;
Get( i , unit );
os << "\n\t";
unit.Print(os);
}
os << "\n)" << endl;
return os;
}
bool MPoint::EndBulkLoad(const bool sort, const bool checkvalid)
{
bool res = Mapping<UPoint, Point>::EndBulkLoad( sort, checkvalid );
if(res){
RestoreBoundingBox();
}
return res;
}
bool MPoint::operator==( const MPoint& r ) const
{
if(!IsDefined()){
return !r.IsDefined();
}
if(!r.IsDefined()){
return false;
}
assert( IsOrdered() && r.IsOrdered() );
if(IsEmpty()){
return r.IsEmpty();
}
if(r.IsEmpty()){
return false;
}
if(bbox != r.bbox)
return false;
return Mapping<UPoint, Point>::operator==(r);
}
bool MPoint::Present( const Instant& t ) const
{
assert( IsDefined() );
assert( IsOrdered() );
assert( t.IsDefined() );
if(bbox.IsDefined())
{ // do MBR-check
double instd = t.ToDouble();
double mint = bbox.MinD(2);
double maxt = bbox.MaxD(2);
if( (instd < mint && !AlmostEqual(instd,mint)) ||
(instd > maxt && !AlmostEqual(instd,maxt))
)
{
// cout << __PRETTY_FUNCTION__<< "(" << __FILE__ << __LINE__
// << "): Bounding box check failed:" << endl;
// cout << "\tInstant : "; t.Print(cout); cout << endl;
// cout << "\tinstd : " << instd << endl;
// cout << "\tmint/maxt :" << mint << "\t/\t" << maxt << endl;
// cout << "\tBBox = "; bbox.Print(cout); cout << endl;
return false;
}
}
int pos = Position(t);
if( pos == -1 ) //not contained in any unit
return false;
return true;
}
bool MPoint::Present( const Periods& t ) const
{
assert( IsDefined() );
assert( IsOrdered() );
assert( t.IsDefined() );
assert( t.IsOrdered() );
if(bbox.IsDefined())
{ // do MBR-check
double MeMin = bbox.MinD(2);
double MeMax = bbox.MaxD(2);
Instant tmin; t.Minimum(tmin);
Instant tmax; t.Maximum(tmax);
double pmin = tmin.ToDouble();
double pmax = tmax.ToDouble();
if( (pmax < MeMin && !AlmostEqual(pmax,MeMin)) ||
(pmin > MeMax && !AlmostEqual(pmin,MeMax))
)
{
// cout << __PRETTY_FUNCTION__<< "(" << __FILE__ << __LINE__
// << "): Bounding box check failed:" << endl;
// cout << "\tPeriod : "; t.Print(cout); cout << endl;
// cout << "\tpmin/pmax : " << pmin << "\t/\t" << pmax << endl;
// cout << "\ttmin/tmax :" << tmin << "\t/\t" << tmax << endl;
// cout << "\tMPoint : " << MeMin << "\t---\t" << MeMax << endl;
// cout << "\tBBox = "; bbox.Print(cout); cout << endl;
return false;
}
}
Periods defTime( 0 );
DefTime( defTime );
return t.Intersects( defTime );
}
void MPoint::AtInstant( const Instant& t, Intime<Point>& result ) const
{
if( IsDefined() && t.IsDefined() )
{
if( !bbox.IsDefined() )
{ // result is undefined
result.SetDefined(false);
} else if( IsEmpty() )
{ // result is undefined
result.SetDefined(false);
} else
{ // compute result
double instd = t.ToDouble();
double mind = bbox.MinD(2);
double maxd = bbox.MaxD(2);
if( (mind > instd && !AlmostEqual(mind,instd)) ||
(maxd < instd && !AlmostEqual(maxd,instd))
)
{
// cout << __PRETTY_FUNCTION__<< "(" << __FILE__ << __LINE__
// << "): Bounding box check failed:" << endl;
// cout << "\tInstant : "; t.Print(cout); cout << endl;
// cout << "\tinstd : " << instd << endl;
// cout << "\tmind/maxd :" << mind << "\t/\t" << maxd << endl;
// cout << "\tBBox = "; bbox.Print(cout); cout << endl;
result.SetDefined(false);
} else
{
assert( IsOrdered() );
int pos = Position( t );
if( pos == -1 ) // not contained in any unit
result.SetDefined( false );
else
{
UPoint posUnit;
units.Get( pos, &posUnit );
result.SetDefined( true );
posUnit.TemporalFunction( t, result.value );
result.instant.CopyFrom( &t );
}
}
}
} else
{
result.SetDefined(false);
}
}
void MPoint::AtPeriods( const Periods& p, MPoint& result ) const
{
result.Clear();
result.SetDefined(true);
if( IsDefined() && p.IsDefined() )
{
if( !bbox.IsDefined())
{ // result is undefined
result.SetDefined(false);
} else if( IsEmpty() || p.IsEmpty())
{ // result is defined but empty
result.SetDefined(true);
} else if( IsMaximumPeriods(p) )
{ // p is [begin of time, end of time]. Copy the input into result.
result.CopyFrom(this);
}
else
{ // compute result
assert( IsOrdered() );
assert( p.IsOrdered() );
Instant perMinInst; p.Minimum(perMinInst);
Instant perMaxInst; p.Maximum(perMaxInst);
double permind = perMinInst.ToDouble();
double permaxd = perMaxInst.ToDouble();
double mind = bbox.MinD(2);
double maxd = bbox.MaxD(2);
if( (mind > permaxd && !AlmostEqual(mind,permaxd)) ||
(maxd < permind && !AlmostEqual(maxd,permind)))
{
// cout << __PRETTY_FUNCTION__<< "(" << __FILE__ << __LINE__
// << "): Bounding box check failed:" << endl;
// cout << "\tPeriod : "; p.Print(cout); cout << endl;
// cout << "\tperMinInst : "; perMinInst.Print(cout); cout << endl;
// cout << "\tperMaxInst : "; perMaxInst.Print(cout); cout << endl;
// cout << "\tpermind/permaxd : " << permind << "\t/\t"
// << permaxd << endl;
// cout << "\tmind/maxd :" << mind << "\t/\t" << maxd << endl;
// cout << "\tBBox = "; bbox.Print(cout); cout << endl;
result.SetDefined(true);
} else
{
result.StartBulkLoad();
UPoint unit;
Interval<Instant> interval;
int i = 0, j = 0;
Get( i, unit );
p.Get( j, interval );
while( 1 )
{
if( unit.timeInterval.Before( interval ) )
{
if( ++i == GetNoComponents() )
break;
Get( i, unit );
}
else if( interval.Before( unit.timeInterval ) )
{
if( ++j == p.GetNoComponents() )
break;
p.Get( j, interval );
}
else
{ // we have overlapping intervals, now
UPoint r(1);
unit.AtInterval( interval, r );
assert( r.IsDefined() );
assert( r.IsValid() );
result.Add( r );
// cout << "\n\tunit = "; unit.Print(cout); cout << endl;
// cout << "\tinterval = "; interval.Print(cout); cout << endl;
// cout << "\tr = "; r.Print(cout); cout << endl;
if( interval.end == unit.timeInterval.end )
{ // same ending instant
if( interval.rc == unit.timeInterval.rc )
{ // same ending instant and rightclosedness: Advance both
if( ++i == GetNoComponents() )
break;
Get( i, unit );
if( ++j == p.GetNoComponents() )
break;
p.Get( j, interval );
}
else if( interval.rc == true )
{ // Advanve in mapping
if( ++i == GetNoComponents() )
break;
Get( i, unit );
}
else
{ // Advance in periods
assert( unit.timeInterval.rc == true );
if( ++j == p.GetNoComponents() )
break;
p.Get( j, interval );
}
}
else if( interval.end > unit.timeInterval.end )
{ // Advance in mpoint
if( ++i == GetNoComponents() )
break;
Get( i, unit );
}
else
{ // Advance in periods
assert( interval.end < unit.timeInterval.end );
if( ++j == p.GetNoComponents() )
break;
p.Get( j, interval );
}
}
}
result.EndBulkLoad();
}
}
} else
{
result.SetDefined(false);
}
}
/*
RestoreBoundingBox() checks, whether the MPoint's MBR ~bbox~ is ~undefined~
and thus may needs to be recalculated and if, does so.
*/
void MPoint::RestoreBoundingBox(const bool force)
{
if(!IsDefined() || GetNoComponents() == 0)
{ // invalidate bbox
bbox.SetDefined(false);
}
else if(force || !bbox.IsDefined())
{ // construct bbox
UPoint unit;
int size = GetNoComponents();
Get( 0, unit ); // safe, since (this) contains at least 1 unit
bbox = unit.BoundingBox();
for( int i = 1; i < size; i++ ){
Get( i, unit );
bbox = bbox.Union(unit.BoundingBox());
}
} // else: bbox unchanged and still correct
}
// Class functions
Rectangle<3u> MPoint::BoundingBox(const Geoid* geoid /*=0*/) const
{
if(geoid){ // spherical geometry case:
if(!IsDefined() || (GetNoComponents()<=0) ){
return Rectangle<3>(false);
}
UPoint u;
Rectangle<3> bbx(false);
for(int i=0; i<GetNoComponents(); i++){
Get(i,u);
assert( u.IsDefined() );
if(bbx.IsDefined()){
bbx.Union(u.BoundingBox(geoid));
} else {
bbx = u.BoundingBox(geoid);
}
}
return bbx;
} // else: euclidean case
return bbox;
}
// return the spatial bounding box (2D: X/Y)
const Rectangle<2> MPoint::BoundingBoxSpatial(const Geoid* geoid) const {
Rectangle<2u> result(false);
if(!IsDefined() || (GetNoComponents()<=0) ){
return result;
} else {
Rectangle<3> bbx = this->BoundingBox(geoid);
result = bbx.Project2D(0,1); // project to X/Y
return result;
}
};
void MPoint::Trajectory( Line& line ) const
{
line.Clear();
if(!IsDefined()){
line.SetDefined( false );
return;
}
line.SetDefined( true );
line.StartBulkLoad();
HalfSegment hs;
UPoint unit;
int edgeno = 0;
int size = GetNoComponents();
if (size>0)
line.Resize(size);
Point p0(false); // starting point
Point p1(false); // end point of the first unit
Point p_last(false); // last point of the connected segment
for( int i = 0; i < size; i++ ) {
Get( i, unit );
if( !AlmostEqual( unit.p0, unit.p1 ) ) {
if(!p0.IsDefined()){ // first unit
p0 = unit.p0;
p1 = unit.p1;
p_last = unit.p1;
} else { // segment already exists
if(p_last!=unit.p0){ // spatial jump
hs.Set(true,p0,p_last);
hs.attr.edgeno = ++edgeno;
line += hs;
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
line += hs;
p0 = unit.p0;
p1 = unit.p1;
p_last = unit.p1;
} else { // an extension, check direction
if(!AlmostEqual(p0,unit.p1)){
HalfSegment tmp(true,p0,unit.p1);
double dist = tmp.Distance(p1);
double dist2 = tmp.Distance(p_last);
if(AlmostEqual(dist,0.0) && AlmostEqual(dist2,0.0)){
p_last = unit.p1;
} else {
hs.Set(true,p0,p_last);
hs.attr.edgeno = ++edgeno;
line += hs;
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
line += hs;
p0 = unit.p0;
p1 = unit.p1;
p_last = unit.p1;
}
}
}
}
}
}
if(p0.IsDefined() && p_last.IsDefined() && !AlmostEqual(p0,p_last)){
hs.Set(true,p0,p_last);
hs.attr.edgeno = ++edgeno;
line += hs;
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
line += hs;
}
line.EndBulkLoad();
}
void MPoint::Distance( const Point& p, MReal& result, const Geoid* geoid ) const
{
result.Clear();
if( !IsDefined() || !p.IsDefined() || (geoid && !geoid->IsDefined()) ){
result.SetDefined( false );
return;
}
result.SetDefined( true );
UPoint uPoint;
result.Resize(GetNoComponents());
result.StartBulkLoad();
for( int i = 0; i < GetNoComponents(); i++ ){
Get( i, uPoint );
std::vector<UReal> resvec;
uPoint.Distance( p, resvec, geoid );
for(std::vector<UReal>::iterator it=resvec.begin();
it!=resvec.end(); it++ ){
if(it->IsDefined()){
result.MergeAdd( *it );
}
}
}
result.EndBulkLoad( false, false );
}
void MPoint::SquaredDistance( const Point& p, MReal& result,
const Geoid* geoid ) const
{
result.Clear();
if( !IsDefined() || !p.IsDefined() || (geoid && !geoid->IsDefined()) ){
result.SetDefined( false );
return;
}
result.SetDefined( true );
UPoint uPoint;
result.Resize(GetNoComponents());
result.StartBulkLoad();
for( int i = 0; i < GetNoComponents(); i++ ){
Get( i, uPoint );
std::vector<UReal> resvec;
uPoint.Distance( p, resvec, geoid );
for(std::vector<UReal>::iterator it(resvec.begin());
it!=resvec.end(); it++ ){
if(it->IsDefined()){
UReal resunit(*it);
if( resunit.r ) {
resunit.r = false;
} else {
assert(resunit.a==0);
assert(resunit.b==0);
resunit.c = resunit.c * resunit.c;
}
result.MergeAdd( resunit );
}
}
}
result.EndBulkLoad( false, false );
}
void MPoint::SquaredDistance( const MPoint& p, MReal& result,
const Geoid* geoid ) const
{
result.Clear();
if( !IsDefined() || !p.IsDefined() || (geoid && !geoid->IsDefined()) ){
result.SetDefined( false );
return;
}
result.SetDefined( true );
UReal uReal(true);
RefinementPartition<MPoint, MPoint, UPoint, UPoint> rp(*this, p);
result.Resize(rp.Size());
result.StartBulkLoad();
for( unsigned int i = 0; i < rp.Size(); i++ )
{
Interval<Instant> iv;
int u1Pos, u2Pos;
UPoint u1;
UPoint u2;
rp.Get(i, iv, u1Pos, u2Pos);
if (u1Pos == -1 || u2Pos == -1)
continue;
else {
Get(u1Pos, u1);
p.Get(u2Pos, u2);
}
if(u1.IsDefined() && u2.IsDefined())
{ // do not need to test for overlapping deftimes anymore...
u1.Distance( u2, uReal, geoid );
if(!uReal.IsDefined()){
std::cerr << __PRETTY_FUNCTION__
<< "Invalid geographic coord found!" << endl;
result.EndBulkLoad( false, false );
result.Clear();
result.SetDefined(false);
return;
}
uReal.r= false;
result.MergeAdd( uReal );
}
}
result.EndBulkLoad();
}
double MPoint::DistanceStartEnd(const MPoint& p, const int geoDistFun,
const Geoid* geoid /* = 0 */) const {
if (geoDistFun < 0 || geoDistFun > 2) {
return -1.0;
}
if (!IsDefined() && !p.IsDefined()) {
return 0.0;
}
if (!IsDefined() || !p.IsDefined()) {
return std::numeric_limits<double>::max();
}
if (geoid && !geoid->IsDefined()) {
return -1.0;
}
if (IsEmpty() && p.IsEmpty()) {
return 0.0;
}
if (IsEmpty() || p.IsEmpty()) {
return std::numeric_limits<double>::max();
}
UPoint u1(true), u2(true);
if (geoDistFun == 2) {
Get(0, u1);
p.Get(0, u2);
double startdist = u1.p0.Distance(u2.p0, geoid);
if (GetNoComponents() > 1) {
Get(GetNoComponents() - 1, u1);
}
if (p.GetNoComponents() > 1) {
p.Get(p.GetNoComponents() - 1, u2);
}
double enddist = u1.p1.Distance(u2.p1, geoid);
return (startdist + enddist) / 2;
}
if (geoDistFun == 0) {
Get(0, u1);
p.Get(0, u2);
return u1.p0.Distance(u2.p0, geoid);
}
else {
Get(GetNoComponents() - 1, u1);
p.Get(p.GetNoComponents() - 1, u2);
return u1.p1.Distance(u2.p1, geoid);
}
}
void MPoint::getPointSequence(std::vector<Point>& result) const {
result.clear();
if (!IsDefined()) {
return;
}
if (IsEmpty()) {
return;
}
UPoint up(true);
Point lastpt(false);
for (int i = 0; i < GetNoComponents(); i++) {
Get(i, up);
if (!AlmostEqual(up.p0, up.p1)) {
if (!lastpt.IsDefined()) { // first unit
result.push_back(up.p0);
result.push_back(up.p1);
lastpt = up.p1;
}
else {
if (!AlmostEqual(lastpt, up.p0)) { // spatial jump
result.push_back(up.p0);
result.push_back(up.p1);
lastpt = up.p1;
}
else { // extension
result.push_back(up.p1);
lastpt = up.p1;
}
}
}
}
}
double MPoint::FrechetDistance(const MPoint* mp, const Geoid* geoid) const {
if (!IsDefined() || !mp->IsDefined()) {
return -1.0;
}
if (IsEmpty() && mp->IsEmpty()) {
return 0.0;
}
if (IsEmpty() || mp->IsEmpty()) {
return INT_MAX;
}
std::vector<Point> pts1, pts2;
getPointSequence(pts1);
mp->getPointSequence(pts2);
if (pts1.empty() || pts2.empty()) {
return -1.0;
}
unsigned int m = pts1.size();
unsigned int n = pts2.size();
double *dp = new double[m * n];
dp[0] = pts1[0].Distance(pts2[0], geoid);
for (unsigned int j = 1; j < n; j++) {
dp[j*m] = std::max(dp[(j - 1)*m], pts1[0].Distance(pts2[j], geoid));
// y*sizeX + x
}
for (unsigned int i = 1; i < m; i++) {
dp[i] = std::max(dp[i - 1], pts1[i].Distance(pts2[0], geoid));
for (unsigned int j = 1; j < n; j++) {
dp[i+j*m] = std::max(std::min(std::min(dp[i+(j - 1)*m], dp[i - 1 + j*m]),
dp[i - 1 + (j - 1)*m]),
pts1[i].Distance(pts2[j], geoid));
}
}
double result = dp[m - 1 + (n - 1)*m];
delete[] dp;
return result;
}
void MPoint::removeNoise(const double maxspeed, const double maxdist,
const Geoid *geoid, MPoint &result) const {
result.SetDefined(IsDefined());
if (!IsDefined()) {
return;
}
result.Clear();
if (GetNoComponents() <= 1) {
return;
}
UPoint up(true);
UReal urspeed(true);
Point startpos(true);
Instant starttime(instanttype);
CcReal speed(true), length(true);
bool lc(true);
int noExceeded = 0;
for (int i = 0; i < GetNoComponents(); i++) {
Get(i, up);
if (geoid == 0 ||
(up.p0.checkGeographicCoord() && up.p1.checkGeographicCoord())) {
Instant mid = up.timeInterval.start
+ ((up.timeInterval.end - up.timeInterval.start) / 2);
up.USpeed(urspeed, geoid);
urspeed.TemporalFunction(mid, speed);
if (geoid != 0) {
up.Length(*geoid, length);
}
else {
up.Length(length);
}
// cout << up.timeInterval.start << ": " << up.p0 << " ---> " << up.p1
// << " |" << noExceeded << "| " << speed.GetValue() << " ### "
// << length.GetValue() << endl;
if (speed.GetValue() > maxspeed || length.GetValue() > maxdist) {
if (noExceeded == 0 && !result.IsEmpty()) { // first exceeded unit
startpos = up.p0;
starttime = up.timeInterval.start;
lc = up.timeInterval.lc;
}
noExceeded++;
}
else { // correct unit
if (noExceeded > 1 && !result.IsEmpty()) { // after >= 2 invalid units
if (length.GetValue() > 0) {
up.p0 = startpos;
up.timeInterval.start = starttime;
up.timeInterval.lc = lc;
up.USpeed(urspeed, geoid);
mid = up.timeInterval.start
+ ((up.timeInterval.end - up.timeInterval.start) / 2);
urspeed.TemporalFunction(mid, speed);
if (geoid != 0) {
up.Length(*geoid, length);
}
else {
up.Length(length);
}
// cout << " speed: " << speed.GetValue() << ", length "
// << length.GetValue() << endl;
if (speed.GetValue() <= maxspeed && length.GetValue() <= maxdist) {
result.MergeAdd(up);
}
noExceeded = 0;
}
}
else if (noExceeded == 0) {
result.MergeAdd(up);
}
}
// cout << "stored startpos: " << startpos << endl;
}
}
}
// Output an interval
std::string iv2string(Interval<Instant> iv){
std::string res ="";
res += iv.lc?"[":"(";
res += iv.start.ToString();
res += ", ";
res += iv.end.ToString();
res += iv.rc?"]":")";
return res;
}
void MPoint::MergeAdd(const UPoint& unit){
assert( IsDefined() );
assert( unit.IsDefined() );
assert( unit.IsValid() );
int size = GetNoComponents();
if(size==0){ // the first unit
Add(unit); // Add() unit as first unit to empty mapping; bbox is updated.
return;
}
UPoint last;
Get(size-1,last);
assert(last.timeInterval.end <= unit.timeInterval.start);
if(last.timeInterval.end!=unit.timeInterval.start ||
!( (last.timeInterval.rc ) ^ (unit.timeInterval.lc))){
// intervals are not connected
Add(unit); // also adopts bbox
return;
}
if(!AlmostEqual(last.p1, unit.p0)){
// jump in spatial dimension
Add(unit); // also adopts bbox
return;
}
Interval<Instant> complete(last.timeInterval.start,
unit.timeInterval.end,
last.timeInterval.lc,
unit.timeInterval.rc);
UPoint upoint(complete,last.p0, unit.p1);
Point p;
upoint.TemporalFunction(last.timeInterval.end, p, true);
if(!AlmostEqual(p,last.p0)){
Add(unit); // also adopts bbox
return;
}
assert( upoint.IsValid() );
assert( upoint.IsDefined() );
bbox = bbox.Union(upoint.BoundingBox()); // update bbox
units.Put(size-1,upoint); // overwrite the last unit by a connected one
}
/*
This function checks whether the end point of the first unit is equal
to the start point of the second unit and if the time difference is
at most a single instant
*/
static bool connected(const UPoint* u1, const UPoint* u2){
if(u1->p1 != u2->p0){ // spatial connected
return false;
}
// temporal connection
if(! ((u1->timeInterval.end) == (u2->timeInterval.start))){
return false;
}
return true;
}
static bool IsBreakPoint(const UPoint* u,const DateTime& duration){
if(u->p0 != u->p1){ // equal points required
return false;
}
DateTime dur = u->timeInterval.end - u->timeInterval.start;
return (dur > duration);
}
/*
~serialize~
*/
void MPoint::serialize(size_t &size, char *&bytes) const {
size = 0;
bytes = 0;
if (!IsDefined()) {
return;
}
size_t rootSize = Sizeof();
// size = sizeof(size_t) + rootSize + units.GetFlobSize() + 6 * sizeof(double)
// + sizeof(bool);
size = sizeof(size_t) + rootSize + units.GetFlobSize();
bytes = new char[size];
size_t offset = 0;
memcpy(bytes + offset, (void*)&rootSize, sizeof(size_t));
offset += sizeof(size_t);
memcpy(bytes + offset, (void*)this, rootSize);
offset += rootSize;
char* data = units.getData();
memcpy(bytes + offset, data, units.GetFlobSize());
delete[] data;
offset += units.GetFlobSize();
// double coord;
// for (int d = 0; d < 3; d++) {
// coord = bbox.MinD(d);
// memcpy(bytes + offset, (void*)(&coord), sizeof(double));
// offset += sizeof(double);
// coord = bbox.MaxD(d);
// memcpy(bytes + offset, (void*)(&coord), sizeof(double));
// offset += sizeof(double);
// }
// bool isdefined = bbox.IsDefined();
// memcpy(bytes + offset, (void*)(&isdefined), sizeof(bool));
}
/*
~deserialize~
*/
MPoint* MPoint::deserialize(const char *bytes) {
ListExpr typeExpr = nl->SymbolAtom(BasicType());
int algebraId, typeId;
std::string typeName;
SecondoCatalog* sc = SecondoSystem::GetCatalog();
sc->LookUpTypeExpr(typeExpr, typeName, algebraId, typeId);
size_t rootSize;
size_t offset = 0;
memcpy((void*)&rootSize, bytes, sizeof(size_t));
offset += sizeof(size_t);
char* root = new char[rootSize];
memcpy(root, bytes + sizeof(size_t), rootSize);
offset += rootSize;
AlgebraManager* am = SecondoSystem::GetAlgebraManager();
ListExpr nType = sc->NumericType(typeExpr);
Attribute* attr = (Attribute*)(am->CreateObj(algebraId, typeId)(nType)).addr;
attr = attr->Create(attr, root, rootSize, algebraId, typeId);
delete[] root;
Flob* flob = attr->GetFLOB(0);
size_t size = flob->getSize();
flob->kill();
char* fb = new char[size];
memcpy(fb, bytes + offset, size);
flob->createFromBlock(*flob, fb, size, false);
delete[] fb;
offset += size;
return (MPoint*)attr;
}
/**
~Simplify~
This function removes some sampling points from a moving point
to get simpler data. It's implemented using an algorithm based
on the Douglas Peucker algorithm for line simplification.
**/
void MPoint::Simplify(const double epsilon, MPoint& result,
const bool checkBreakPoints,
const DateTime& dur,
const Geoid* geoid) const{
result.Clear();
// check for defined state
if( !IsDefined() || !dur.IsDefined() ){
result.SetDefined(false);
return;
}
if(geoid && !geoid->IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined(true);
unsigned int size = GetNoComponents();
// no simplification possible if epsilon < 0
// or if at most one unit present
if(epsilon<0 || size < 2){
result.CopyFrom(this);
return;
}
// create an boolean array which represents all sample points
// contained in the result
bool useleft[size];
bool useright[size];
// at start, no sampling point is used
for(unsigned int i=0;i<size;i++){
useleft[i] = false;
useright[i] =false;
}
unsigned int first=0;
unsigned int last=1;
UPoint u1(false);
UPoint u2(false);
while(last<size){
// check whether last and last -1 are connected
Get(last-1,u1);
Get(last,u2);
if( checkBreakPoints && IsBreakPoint(&u1,dur)){
if(last-1 > first){
Simplify(first,last-2,useleft,useright,epsilon,geoid);
}
Simplify(last-1, last-1, useleft, useright, epsilon,geoid);
first = last;
last++;
} else if( checkBreakPoints && IsBreakPoint(&u2,dur)){
Simplify(first,last-1,useleft,useright,epsilon,geoid);
last++;
Simplify(last-1, last-1,useleft,useright,epsilon,geoid);
first = last;
last++;
} else if(connected(&u1,&u2)){ // enlarge the sequence
last++;
} else {
Simplify(first,last-1,useleft, useright, epsilon,geoid);
first=last;
last++;
}
}
// process the last recognized sequence
Simplify(first,last-1,useleft, useright,epsilon,geoid);
// count the number of units
int count = 1; // count the most right sample point
for( unsigned int i=0;i<size;i++){
if( useleft[i]){
count++;
}
}
result.Resize(count); // prepare enough memory
result.StartBulkLoad();
Instant start;
Point p0;
bool closeLeft = false;
bool leftDefined = false;
for(unsigned int i=0; i< size; i++){
UPoint upoint(false);
Get(i,upoint);
if(useleft[i]){
// debug
if(leftDefined){
std::cerr << " error in mpoint simplification,"
<< " overwrite an existing leftPoint " << endl;
}
// end of debug
p0 = upoint.p0;
closeLeft = upoint.timeInterval.lc;
start = upoint.timeInterval.start;
leftDefined=true;
}
if(useright[i]){
// debug
if(!leftDefined){
std::cerr << " error in mpoint simplification,"
<< " rightdefined before leftdefined " << endl;
}
Interval<Instant> interval(start,upoint.timeInterval.end,closeLeft,
upoint.timeInterval.rc);
UPoint newUnit(interval,p0,upoint.p1);
result.Add(newUnit);
leftDefined=false;
}
}
result.EndBulkLoad(false,false);
}
/**
~Simplify~
Recursive implementation of simplifying movements.
**/
void MPoint::Simplify(const int min,
const int max,
bool* useleft,
bool* useright,
const double epsilon,
const Geoid* geoid) const {
// the endpoints are used in each case
useleft[min] = true;
useright[max] = true;
if(min==max){ // no intermediate sampling points -> nothing to simplify
return;
}
UPoint u1;
UPoint u2;
// build a UPoint from the endpoints
Get(min,u1);
Get(max,u2);
UPoint upoint(Interval<Instant>(u1.timeInterval.start,
u2.timeInterval.end,true,true),
u1.p0,
u2.p1);
// search for the point with the highest distance to its simplified position
double maxDist = 0;
int maxIndex=0;
Point p_orig;
Point p_simple;
UPoint u;
double distance;
for(int i=min+1;i<=max;i++){
Get(i,u);
upoint.TemporalFunction(u.timeInterval.start,p_simple, true);
distance = p_simple.Distance(u.p0,geoid);
if(distance>maxDist){ // new maximum found
maxDist = distance;
maxIndex = i;
}
}
if(maxIndex==0){ // no difference found
return;
}
if(maxDist<=epsilon){ // differnce is in allowed range
return;
}
// split at the left point of maxIndex
Simplify(min,maxIndex-1,useleft,useright,epsilon,geoid);
Simplify(maxIndex,max,useleft,useright,epsilon,geoid);
}
void MPoint::BreakPoints(Points& result, const DateTime& dur) const{
result.Clear();
if( !IsDefined() || !dur.IsDefined() ){
result.SetDefined(false);
return;
}
result.SetDefined(true);
int size = GetNoComponents();
result.StartBulkLoad();
UPoint unit;
for(int i=0;i<size;i++){
Get(i,unit);
if(IsBreakPoint(&unit,dur)){
result += (unit.p0);
}
}
result.EndBulkLoad();
}
void MPoint::BreakPoints(Points& result, const DateTime& dur,
const CcReal& epsilon,
const Geoid* geoid /*=0*/ ) const{
result.Clear();
if(!IsDefined() || !dur.IsDefined() || !epsilon.IsDefined()){
result.SetDefined(false);
return;
}
double eps = epsilon.GetValue();
if(eps<0){
return; // we cannot find distances smaller than zero
}
result.SetDefined(true);
int size = GetNoComponents();
result.StartBulkLoad();
UPoint unit;
UPoint firstUnit;
Point firstPoint;
int firstIndex=0;
int index = 0;
DateTime currentDur(datetime::durationtype);
while(firstIndex < size){
if(index == firstIndex){
Get(firstIndex,firstUnit);
if(firstUnit.p0.Distance(firstUnit.p1,geoid) > eps){
// this units overcomes the maximum epsilon value
index++;
firstIndex++;
} else { // try to find more points for this break
firstPoint = firstUnit.p0;
currentDur = firstUnit.timeInterval.end -
firstUnit.timeInterval.start;
index++;
if(index>=size){
if(currentDur >= dur){
result += firstPoint;
}
firstIndex = index;
}
}
} else {
assert(index > firstIndex);
UPoint lastUnit;
Get(index-1, lastUnit);
Get(index, unit);
if(!lastUnit.Adjacent(&unit)){ // gap found, close chain
if(currentDur >= dur){
result += firstPoint;
}
firstIndex = index; // start a new try
} else {
Point rp = unit.p1;
if(firstPoint.Distance(rp,geoid) > eps){
// next unit does not contribute to break
if(currentDur >= dur){
result += firstPoint;
firstIndex = index;
} else {
// start a new try
firstIndex++;
index = firstIndex;
}
} else {
// extend the possible break
currentDur += (unit.timeInterval.end - unit.timeInterval.start);
index++;
if(index >= size){
firstIndex = index;
if(currentDur >= dur){
result += firstPoint;
}
}
}
}
}
}
result.EndBulkLoad();
}
void MPoint::Breaks(Periods& result, const DateTime& dur,
const CcReal& epsilon,
const Geoid* geoid /*=0*/ ) const{
result.Clear();
if(!IsDefined() || !dur.IsDefined() || !epsilon.IsDefined()){
result.SetDefined(false);
return;
}
double eps = epsilon.GetValue();
if(eps<0){
return; // we cannot find distances smaller than zero
}
result.SetDefined(true);
Periods tmp(0);
int size = GetNoComponents();
//result.StartBulkLoad();
UPoint unit;
UPoint firstUnit;
Point firstPoint;
DateTime firstTime;
int firstIndex=0;
int index = 0;
DateTime currentDur(datetime::durationtype);
while(firstIndex < size){
if(index == firstIndex){
Get(firstIndex,firstUnit);
if(firstUnit.p0.Distance(firstUnit.p1,geoid) > eps){
// this units overcomes the maximum epsilon value
index++;
firstIndex++;
} else { // try to find more points for this break
firstPoint = firstUnit.p0;
firstTime = firstUnit.timeInterval.start;
currentDur = firstUnit.timeInterval.end -
firstUnit.timeInterval.start;
index++;
if(index>=size){
if(currentDur >= dur){
Interval<Instant> iv(firstTime, firstTime+currentDur,true,true);
result.Union(iv, tmp);
result.CopyFrom(&tmp);
}
firstIndex = index;
}
}
} else {
assert(index > firstIndex);
UPoint lastUnit;
Get(index-1, lastUnit);
Get(index, unit);
if(!lastUnit.Adjacent(&unit)){ // gap found, close chain
if(currentDur >= dur){
Interval<Instant> iv(firstTime,firstTime + currentDur,
true, true);
result.Union(iv, tmp);
result.CopyFrom(&tmp);
}
firstIndex = index; // start a new try
} else {
Point rp = unit.p1;
if(firstPoint.Distance(rp,geoid) > eps){
// next unit does not contribute to break
if(currentDur >= dur){
Interval<Instant> iv(firstTime,firstTime + currentDur,
true, true);
result.Union(iv, tmp);
result.CopyFrom(&tmp);
firstIndex = index;
} else {
// start a new try
firstIndex++;
index = firstIndex;
}
} else {
// extend the possible break
currentDur += (unit.timeInterval.end - unit.timeInterval.start);
index++;
if(index >= size){
firstIndex = index;
if(currentDur >= dur){
Interval<Instant> iv(firstTime,firstTime + currentDur,
true, true);
result.Union(iv, tmp);
result.CopyFrom(&tmp);
}
}
}
}
}
}
//result.EndBulkLoad();
}
void MPoint::TranslateAppend(const MPoint& mp, const DateTime& dur){
if( !IsDefined() || !mp.IsDefined() || !dur.IsDefined() ){
Clear();
SetDefined(false);
return;
}
if(mp.GetNoComponents()==0){ // nothing to do (already defined)
return;
}
if(GetNoComponents()==0){
this->CopyFrom(&mp);
return;
}
int newSize = GetNoComponents()+mp.GetNoComponents();
Resize(newSize);
UPoint lastUnit;
StartBulkLoad();
UPoint firstUnit;
mp.Get(0,firstUnit);
// add a staying unit
if(!dur.IsZero() && !dur.LessThanZero()){
Get(GetNoComponents()-1,lastUnit);
Interval<Instant> interval = lastUnit.timeInterval;
Point lastPoint = lastUnit.p1;
// append a unit of staying
Interval<Instant> gapInterval(interval.end,interval.end +dur,
!interval.rc,!firstUnit.timeInterval.lc);
UPoint gap(gapInterval,lastPoint,lastPoint);
Add(gap);
}
Get(GetNoComponents()-1,lastUnit);
Instant end = lastUnit.timeInterval.end;
DateTime timediff = end - firstUnit.timeInterval.start;
double xdiff = lastUnit.p1.GetX() - firstUnit.p0.GetX();
double ydiff = lastUnit.p1.GetY() - firstUnit.p0.GetY();
UPoint Punit;
mp.Get(0,Punit);
UPoint unit = Punit;
unit.Translate(xdiff,ydiff,timediff);
if(!(lastUnit.timeInterval.rc)){
unit.timeInterval.lc = true;
} else {
unit.timeInterval.lc = false;
}
Add(unit);
for(int i=1; i< mp.GetNoComponents(); i++){
mp.Get(i,Punit);
unit = Punit;
unit.Translate(xdiff,ydiff,timediff);
Add(unit);
}
EndBulkLoad(false);
}
void MPoint::Reverse(MPoint& result){
result.Clear();
if(!IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined(true);
int size = GetNoComponents();
if(size==0){
return;
}
UPoint unit;
Get(size-1,unit);
Instant end = unit.timeInterval.end;
Get(0,unit);
Instant start = unit.timeInterval.start;
result.StartBulkLoad();
for(int i=size-1; i>=0; i--){
Get(i,unit);
Instant newEnd = (end - unit.timeInterval.start) + start;
Instant newStart = (end - unit.timeInterval.end) + start;
Interval<Instant> interval(newStart,newEnd,
unit.timeInterval.rc,
unit.timeInterval.lc);
UPoint newUnit(interval,unit.p1,unit.p0);
result.Add(newUnit);
}
result.EndBulkLoad(false);
}
void MPoint::Direction( MReal* result,
const bool useHeading /*=false*/,
const Geoid* geoid /*=0*/,
const double epsilon /*=0.0000001*/ ) const
{
if( !IsDefined() || ( geoid && (!geoid->IsDefined() || (epsilon<=0.0)) ) ) {
result->SetDefined(false);
return;
}
std::vector<UReal> resvector;
UPoint unitin;
for(int i=0;i<GetNoComponents();i++) {
Get(i, unitin);
unitin.Direction( resvector, useHeading, geoid, epsilon );
}
result->Clear();
result->SetDefined(true);
result->StartBulkLoad();
for(std::vector<UReal>::iterator iter = resvector.begin();
iter != resvector.end(); iter++){
if( iter->IsDefined() && iter->IsValid() ){
result->MergeAdd(*iter);
}
}
result->EndBulkLoad( false );
return;
}
/*
~qdist~
This funtion returns the square of the distance between ~p1~ and ~p2~.
*/
double qdist(const Point& p1, const Point& p2){
double x1 = p1.GetX();
double y1 = p1.GetY();
double x2 = p2.GetX();
double y2 = p2.GetY();
double dx = x2-x1;
double dy = y2-y1;
return dx*dx + dy*dy;
}
/*
~qdist~
This function returns the square of the distance of the points defined by
(~x1~, ~y1~) and (~x2~, ~y2~).
*/
double qdist(const double& x1, const double& y1,
const double& x2, const double& y2){
double dx = x2-x1;
double dy = y2-y1;
return dx*dx + dy*dy;
}
/*
struct ~intset~
This class allows reference counting for a set of integers.
*/
struct intset{
intset():member(),refs(1){}
void deleteIfAllowed(){
refs--;
if(refs<1){
delete this;
}
}
std::set<int> member;
int refs;
};
/*
~cluster~
A cluster is defined by the contained points (stored in ~member~),
the center (defined by (~cx~, ~cy~) ) and a flag ~forbidden~ indicating
whether it's allowed to change the content of this cluster.
To save memory, instead of points only indexes of the points within an external
point vector or similar are stored.
Members are always copied by reference.
*/
struct cluster{
/*
~Default constructor~
*/
cluster(){
cx = 0.0;
cy = 0.0;
member = new intset();
forbidden = false;
}
/*
~Copy Constructor~
*/
cluster(const cluster& c){
cx = c.cx;
cy = c.cy;
forbidden = c.forbidden;
member = c.member;
member->refs++;
}
/*
~Assignment Operator~
*/
cluster& operator=(const cluster& c){
cx = c.cx;
cy = c.cy;
forbidden = c.forbidden;
member = c.member;
member->refs++;
return *this;
}
/*
~Destructor~
*/
~cluster(){
member->deleteIfAllowed();
}
/*
~begin~
This function returns an iterator pointing to the begin of the
contained intset.
*/
std::set<int>::iterator begin() const{
return member->member.begin();
}
/*
~end~
This function returns an iterator pointing to the end of the contained intset.
*/
std::set<int>::iterator end() const {
return member->member.end();
}
/*
~size~
Tells, how many integers are contained in this cluster.
*/
size_t size() const {
return member->member.size();
}
/*
~insert~
Inserts a new point index into the cluster.
There is no correction of the center.
*/
void insert(int i){
member->member.insert(i);
}
/*
~erase~
Erases a point index without correcting the center.
*/
void erase(int i){
member->member.erase(i);
}
/*
~clear~
Removes all point indexes.
*/
void clear(){
member->member.clear();
}
/*
~recomputeCenter~
Recomputes the cluster's center.
*/
void recomputeCenter(const std::vector<Point>& points){
std::set<int>::iterator it;
double x = 0.0;
double y = 0.0;
for(it=begin();it!=end();it++){
Point p = points[*it];
x += p.GetX();
y += p.GetY();
}
double s = size();
cx = x / s;
cy = y / s;
}
/*
~Data Members~
(cx, cy) : center of the cluster [nl]
member : intset storing the iindexes of the contained points [nl]
forbidding : flag indicating whether changes are allowed
*/
double cx;
double cy;
intset* member; // avoid copying of this set !!!!
bool forbidden;
};
/*
~indexOfNearestCluster~
Returns the index of the cluster closest to ~p~ within ~clusters~
within a range of ~eps~. If no center of any cluster
ios nearer than ~eps~ to ~p~ , -1 is returned. To accelerate the
search, the centers of the clusters are stored in the rtree ~tree~.
*/
int indexOfNearestCluster( const mmrtree::Rtree<2>& tree,
const Point& p,
const std::vector<cluster>& clusters,
const double& eps){
double eps2 = eps*eps;
int res = -1;
double bestDist = eps2 + 10.0; // a value greater than eps2
// build a rectangle around p
double min[2];
double max[2];
double x = p.GetX();
double y = p.GetY();
min[0] = x - eps - FACTOR;
min[1] = y - eps - FACTOR;
max[0] = x + eps + FACTOR;
max[1] = y + eps + FACTOR;
Rectangle<2> searchbox(true,min,max);
std::set<long> cands;
tree.findAll(searchbox, cands);
std::set<long>::iterator it;
for(it = cands.begin(); it!=cands.end(); it++){
cluster c = clusters[*it];
double d = qdist(c.cx,c.cy,x,y);
if((d <= eps2) && (d < bestDist) && !c.forbidden){
bestDist = d;
res = *it;
}
}
return res;
}
// forward declaration
void insertPoint(mmrtree::Rtree<2>& tree,
const std::vector<Point>& points,
const int pos,
std::vector<cluster>& clusters,
const double& eps);
/*
~repairClusterAt~
This function removes all points from the cluster, whose distance to the
cluster's center is greater than ~eps~.
*/
void repairClusterAt(const int index,
mmrtree::Rtree<2>& tree,
std::vector<cluster>& clusters,
const std::vector<Point>& points,
const double& eps){
double eps2 = eps*eps;
clusters[index].forbidden = true;
double cx = clusters[index].cx;
double cy = clusters[index].cy;
// store all invalid points to wrong
std::set<int>wrong;
std::set<int>::iterator it;
for(it = clusters[index].begin();
it != clusters[index].end();
it++){
Point p = points[*it];
double d = qdist(cx,cy,p.GetX(),p.GetY());
if(d>eps2){
wrong.insert(*it);
}
}
// remove invalid points
for(it=wrong.begin();it!=wrong.end();it++){
clusters[index].erase(*it);
}
// insert points again
for(it =wrong.begin(); it!=wrong.end(); it++){
insertPoint(tree,points,*it,clusters,eps);
}
clusters[index].forbidden = false;
}
/*
~insertPoint~
This function searches the nearest cluster withing ~clusters~.
If the center's distance is greater than ~eps~, a new cluster
is created containing exactly this point. Otherwise, the point is
inserted into this cluster. The cluster's center is corrected and all
'bad points' are moved into other clusters.
*/
void insertPoint(mmrtree::Rtree<2>& tree,
const std::vector<Point>& points,
const int pos,
std::vector<cluster>& clusters,
const double& eps){
Point p = points[pos];
int index = indexOfNearestCluster(tree, p, clusters, eps);
double x = p.GetX();
double y = p.GetY();
double min[2];
double max[2];
if(index < 0){ // no matching cluster exists, create a new one
cluster c;
c.cx = x;
c.cy = y;
c.insert(pos);
c.forbidden = false;
clusters.push_back(c);
min[0] = x - FACTOR;
max[0] = x + FACTOR;
min[1] = y - FACTOR;
max[1] = y + FACTOR;
Rectangle<2> box(true,min,max);
tree.insert(box, clusters.size()-1);
return;
}
clusters[index].insert(pos);
double cx = clusters[index].cx;
double cy = clusters[index].cy;
int s = clusters[index].size();
clusters[index].cx = ((cx * (s - 1.0) + x) / s);
clusters[index].cy = ((cy * (s - 1.0) + y) / s);
// clusters[index].recomputeCenter(points);
min[0] = cx - FACTOR;
min[1] = cy - FACTOR;
max[0] = cx + FACTOR;
max[1] = cy + FACTOR;
Rectangle<2> erasebox(true,min,max);
tree.erase(erasebox,index);
min[0] = clusters[index].cx - FACTOR;
min[1] = clusters[index].cy - FACTOR;
max[0] = clusters[index].cx + FACTOR;
max[1] = clusters[index].cy + FACTOR;
Rectangle<2> newCenter(true,min,max);
tree.insert(newCenter,index);
repairClusterAt(index, tree, clusters, points, eps);
}
/*
~getCenter~
Computes the center of the cluster and stored it in ~x~ and ~y~.
*/
void getCenter(const cluster& cl,
const std::vector<Point>& points,
double& x, double& y){
x = 0;
y = 0;
int size = cl.size();
if(size==0){
std::cerr << "indexes smaller than zero" << endl;
return;
}
std::set<int>::const_iterator it;
for(it=cl.begin();it!=cl.end();it++){
x += points[*it].GetX();
y += points[*it].GetY();
}
x = x / size;
y = y / size;
}
/*
~recomputeCenter~
Computes the center of a cluster from the members.
*/
void recomputeCenters(std::vector<cluster>& clusters,
const std::vector<Point>& points){
std::vector<cluster>::iterator it;
for(it = clusters.begin(); it!=clusters.end();it++){
getCenter(*it,points,it->cx,it->cy);
}
}
/*
This class is only needed, because the Point class of Secondo
does no initialisation within in the standard constructor which is
required to use a class within an STL set instance.
*/
class DefPoint:public Point{
public:
DefPoint(){
SetDefined(false);
del.refs=1;
del.SetDelete();
}
DefPoint(const Point& p){
Set(p.IsDefined(),p.GetX(),p.GetY());
}
DefPoint(const DefPoint& p){
Set(p.IsDefined(),p.GetX(),p.GetY());
del.refs=1;del.SetDelete();
}
~DefPoint(){}
DefPoint& operator=(const DefPoint& p){
Set(p.IsDefined(),p.GetX(),p.GetY());
return *this;
}
inline void Set(bool def, const Coord& x, const Coord& y){
if(def){
Point::Set(x,y);
} else {
SetDefined(false);
}
}
inline Point GetPoint(){
Point p(IsDefined(),GetX(),GetY());
return p;
}
};
/*
~assignCluster~
Creates a map point -> point where each point within the points vector
is assigned to the nearest cluster center.
*/
std::map<DefPoint, DefPoint>* assignCluster(const std::vector<Point>& points,
const double& eps,
std::vector<Point>& centers){
std::vector<cluster> clusters;
mmrtree::Rtree<2> tree(2,5);
for(unsigned int i=0;i<points.size();i++){
insertPoint(tree, points, i, clusters,eps);
}
// redistribute points
for(unsigned int i = 0; i< clusters.size();i++){
clusters[i].clear();
}
for(unsigned int i=0;i<points.size();i++){
int index = indexOfNearestCluster(tree, points[i], clusters, eps);
clusters[index].insert(i);
}
// correct the centers
recomputeCenters(clusters,points);
// store as a map
std::map<DefPoint, DefPoint>* result= new std::map<DefPoint, DefPoint>();
for(unsigned int i=0;i<clusters.size();i++){
cluster c = clusters[i];
Point center(true,c.cx,c.cy);
std::set<int>::iterator it;
centers.push_back(center);
for(it=clusters[i].begin(); it!=clusters[i].end(); it++){
Point p = points.at(*it);
DefPoint p1(p);
DefPoint c1(center);
(*result)[p1] = c1;
}
}
return result;
}
/*
~DoublePoint~
This class collects a Point and a double.
*/
class DoublePoint{
public:
DoublePoint(const double d1, const Point p1):d(d1),p(p1){}
DoublePoint(const DoublePoint& dp):d(dp.d),p(dp.p){}
DoublePoint& operator=(const DoublePoint& dp){
this->d = dp.d;
this->p = dp.p;
return *this;
}
bool operator<(const DoublePoint& dp)const{
return !AlmostEqual(d,dp.d) && d < dp.d;
}
bool operator==(const DoublePoint& dp)const{
return AlmostEqual(d,dp.d);
}
double d;
Point p;
};
/*
~Split~
Determines such points within ~cands~ whose distance to the
trajectory (a segment) of the unit is smaller than ~eps~ div 2. If so, the
foot of the point to the segment is determined. If the foot is located
on the segment, the unit is split at that position and the parts are
inserted into result. If no such point is found, the complete unit is inserted
into the result.
*/
void split(const UPoint unit,
const std::set<long>& cands,
const std::vector<Point>& points,
MPoint& result,
const double eps){
// special case, not a segment
if(AlmostEqual(unit.p0, unit.p1)){
// nothing to split, just copy the unit
result.Add(unit);
return;
}
// at least the end points must be contained in cands
if(cands.size() < 3 ){ // only the two endpoints
result.Add(unit);
return;
}
std::set<DoublePoint> splitElements;
Point p0 = unit.p0;
Point p1 = unit.p1;
HalfSegment hs(true,unit.p0,unit.p1);
double len = p0.Distance(p1);
// determine the split positions as set of double values
std::set<long>::iterator cit;
for(cit=cands.begin(); cit!=cands.end(); cit++){
// check this computation
Point R = points[*cit];
if(hs.Contains(R)){
if(!AlmostEqual(R,p0)){
double splitPos = p0.Distance(R) / len;
DoublePoint dp(splitPos,R);
splitElements.insert(dp);
}
} else {
double x = p0.GetX();
double y = p0.GetY();
double dx = p1.GetX()-x;
double dy = p1.GetY()-y;
double dx2,dy2;
if(AlmostEqual(dy,0)){
dx2 = 0;
dy2 = 1;
} else if(AlmostEqual(dx,0)){
dx2 = 1;
dy2 = 0;
} else {
dx2 = 1;
dy2 = -dx/dy;
}
double x2 = R.GetX();
double y2 = R.GetY();
double t1,t2;
if(!AlmostEqual(dx,0)){
t2 = (y2*dx + x*dy -x2*dy - dx*y) / (dx2*dy - dy2*dx);
t1 = (x2+t2*dx2-x)/dx;
} else {
t1 = (y2*dx2 + x*dy2 -x2*dy2 - y*dx2) / (dy*dx2 - dx*dy2);
t2 = (x+t1*dx-x2)/dx2;
}
double fx = x + t1*dx;
double fy = y + t1*dy;
Point f(true,fx,fy);
if( (R.Distance(f) < eps) && (t1>=0) && (t1<=1)){
DoublePoint dp(t1,R);
splitElements.insert(dp);
} // foot outside hs
} // point outside hs
} // for all candidates
if(splitElements.size()<2){ // only the endpoint is member of splitPoints
result.Add(unit);
return;
}
std::set<DoublePoint>::iterator it;
// split the unit
bool lastLC = unit.timeInterval.lc;
double lastSplit = 0;
Point lastPoint = p0;
Instant lastTime = unit.timeInterval.start;
Instant startTime = unit.timeInterval.start;
DateTime dur = unit.timeInterval.end - unit.timeInterval.start;
DateTime tmp(durationtype);
for(it = splitElements.begin(); it!=splitElements.end();it++){
DoublePoint dp = *it;
double sE = dp.d;
if(!AlmostEqual(lastSplit,sE)){
// compute the splitPoint
Point sP = dp.p;
if(!AlmostEqual(sP,lastPoint)){
DateTime copy(dur);
copy.Split(sE,tmp);
if(!copy.IsZero()){
DateTime end = startTime + copy;
if(lastTime!=end ||
(AlmostEqual(sP,p1) &&
lastLC != unit.timeInterval.rc)){
Interval<Instant> interval(lastTime,end,
lastLC, !lastLC);
if(AlmostEqual(sP,p1)){
interval.rc = (unit.timeInterval.rc);
}
UPoint u(interval,lastPoint,sP);
result.Add(u);
lastSplit = sE;
lastPoint = sP;
lastTime = end;
}
}
}
}
}
}
void eqTimes(MPoint& mpoint,
std::vector<int>& indexes,
MPoint& changed,
DbArray<bool>& used,
DateTime& eps) {
// first collect the different durations within a set
//vector<int>::iterator it;
//vector<UPoint> units;
//DateTime minDur(durationtype);
//DateTime maxDur(durationtype);
//const UPoint* unit;
}
/*
~ChangeTimes~
This function tries to equalize the durations of units covering the
same space. The maximum deviation is given by ~eps~.
*/
void changeTimes(MPoint& mpoint, const DateTime& eps){
assert( mpoint.IsDefined() );
assert( eps.IsDefined() );
if( !mpoint.IsDefined() || !eps.IsDefined() ){
mpoint.Clear();
mpoint.SetDefined( false );
return;
}
// step 1: collect the rectangles of all units into an rtree
mmrtree::Rtree<2> tree(3,7);
UPoint unit=0;
for(int i=0;i<mpoint.GetNoComponents();i++){
mpoint.Get(i,unit);
tree.insert(unit.BoundingBoxSpatial(),i);
}
cout << " There are " << tree.noObjects() << " stored in the tree " << endl;
/*
DbArray<bool> used(mpoint.GetNoComponents);
MPoint changed(mpoint);
for(int i=0;i<mpoint.GetNoComponents()){
used.Append(false);
}
bool u;
UPoint unit;
for(int i=0;i<mpoint.NoComponents();i++){
used.Get(i,u);
if(!u){ // not used unit
mpoint.Get(i,unit);
Rectangle2D box(unit.GetSpatialBoundingBox());
vector<long> c;
tree.findAllExact(box,c);
vector<long>::iterator it;
vector<int> indexes;
bool u2;
UPoint unit2;
for(it i=c.begin();i!=c.end();it++){
used.Get(*it,u2);
if(!u2){
mpoint.Get(*it,unit2);
if(AlmostEqual(unit.p0,unit2.p0) &&
AlmostEqual(unit.p1,unit2.p1)){
indexes.push_back(*it);
}
}
}
eqTimes(mpoint,indexes,changed,used,eps);
}
}
*/
}
/*
~EqualizeUnitsSpatial~
This function tries to equalize similar units in spatial dimension.
This means if the segments of two (or more) units are similiar, the
endpoints of the units are changed to cover the same segment.
*/
void MPoint::EqualizeUnitsSpatial(const double epsilon,
MPoint& result,
bool skipSplit/* = false*/) const{
result.Clear();
if(!IsDefined()){
result.SetDefined( false );
return;
}
result.SetDefined( true );
int size = GetNoComponents();
if(size<2){ // no or a single unit
return;
}
// step 1: collect all start and endpoints of units within a set
std::set<Point> endPoints1;
UPoint unit;
for(int i=0;i< GetNoComponents(); i++){
Get(i,unit);
Point p0(unit.p0);
endPoints1.insert(p0);
Point p1(unit.p1);
endPoints1.insert(p1);
}
// copy points from the set to a vector
std::vector<Point> endPoints;
std::set<Point>::iterator it;
for(it=endPoints1.begin(); it!=endPoints1.end(); it++){
endPoints.push_back(*it);
}
// step 2: build cluster and move the endpoints to the centers
std::vector<Point> centers;
std::map<DefPoint , DefPoint>* clusters;
clusters = assignCluster(endPoints,epsilon,centers);
if(skipSplit){
UPoint resUnit(0);
//result.StartBulkLoad();
for(int i=0;i<GetNoComponents(); i++){
Get(i,unit);
resUnit = unit;
Point p = unit.p0;
resUnit.p0 = (*clusters)[p].GetPoint();
resUnit.p1 = (*clusters)[unit.p1].GetPoint();
result.MergeAdd(resUnit);
}
//result.EndBulkLoad();
delete clusters;
}
MPoint tmp(GetNoComponents());
UPoint resUnit(0);
tmp.StartBulkLoad();
for(int i=0;i<GetNoComponents(); i++){
Get(i,unit);
resUnit = unit;
Point p = unit.p0;
resUnit.p0 = (*clusters)[p].GetPoint();
resUnit.p1 = (*clusters)[unit.p1].GetPoint();
tmp.MergeAdd(resUnit);
}
tmp.EndBulkLoad();
// split units at center
mmrtree::Rtree<2> tree(10,30);
for(unsigned int i=0;i<centers.size();i++){
tree.insert(centers[i].BoundingBox(),i);
}
std::set<long> cands;
for(int i=0;i<tmp.GetNoComponents();i++){
tmp.Get(i,unit);
if(AlmostEqual(unit.p0,unit.p1)){
result.Add(unit);
} else {
HalfSegment hs(true,unit.p0,unit.p1);
Rectangle<2> box = hs.BoundingBox();
tree.findAll(box.Extend(epsilon),cands);
split(unit,cands,centers,result,epsilon);
}
}
changeTimes(result, DateTime(0,2000,durationtype));
delete clusters;
}
/*
~isCut~
Helping function for the Sample operator. This function returns __true__
iff
* there is a gap in the definition time between u1 and u2
* there is a spatial jump between u1 and u2
* the direction is changed
* the first unit is a break (stationary unit)
*/
bool isCut(const UPoint* u1, const UPoint* u2){
assert( u1->IsDefined() );
assert( u2->IsDefined() );
DateTime end = u1->timeInterval.end;
DateTime start = u2->timeInterval.start;
if(end!=start){ // gap in definition time
return true;
}
if(!AlmostEqual(u1->p1,u2->p0)){ // jump
return true;
}
Point p1 = u1->p0;
Point p2 = u1->p1;
Point p3 = u2->p1;
double dx1 = p2.GetX()-p1.GetX();
double dy1 = p2.GetY()-p1.GetY();
double dx2 = p3.GetX()-p2.GetX();
double dy2 = p3.GetY()-p2.GetY();
bool res = !AlmostEqual(dx1*dy2, dx2*dy1);
if(!res){
if(AlmostEqual(dx1,0) && AlmostEqual(dy1,0)){ // first unit is a break
res = !( AlmostEqual(dx2,0) && AlmostEqual(dy2,0));
}
}
return res;
}
void MPoint::Sample(const DateTime& duration,
MPoint& result,
const bool KeepEndPoint, /*=false*/
const bool exactPath /*=false*/ ) const{
result.Clear();
// special case: undefined parameter
if(!IsDefined() || !duration.IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined( true );
int size = GetNoComponents();
// special case: empty mpoint
if(size==0){ // empty
return;
}
bool isFirst = true;
int currentUnit = 0;
Instant currentTime;
Instant lastTime;
Point lastPoint;
Point point;
UPoint unit; // the unit corresponding to the currentUnit
bool lc = false;
while(currentUnit < size ){ // there are remaining units
bool cut = false;
if(isFirst){ // set the start values
Get(currentUnit,unit);
currentTime = unit.timeInterval.start;
lastPoint = unit.p0;
isFirst=false;
lc = unit.timeInterval.lc;
} else {
lc = true;
}
Interval<Instant> interval(unit.timeInterval);
lastTime = currentTime;
currentTime += duration; // the next sampling instant
// search the unit having endtime for currentTime
while(interval.end < currentTime &&
currentUnit < size &&
(!cut || !exactPath)){
currentUnit++;
if(currentUnit<size){
Get(currentUnit,unit);
if(exactPath && (currentUnit>0)){
UPoint lastUnit;
Get(currentUnit-1,lastUnit);
cut = isCut(&lastUnit,&unit);
if(!cut){
interval = unit.timeInterval;
}
}else{
interval = unit.timeInterval;
}
}
}
if(cut){ // cut detected
UPoint lastUnit;
Get(currentUnit-1,lastUnit);
currentTime = lastUnit.timeInterval.end;
Interval<Instant> newint(lastTime,currentTime,lc,false);
UPoint nextUnit(newint,lastPoint,lastUnit.p1);
if(nextUnit.IsValid()){
result.MergeAdd(nextUnit);
}
isFirst = true;
} else if(currentUnit<size){
if(interval.start>currentTime){ // gap detected
isFirst=true;
} else {
unit.TemporalFunction(currentTime, point, true);
Interval<Instant> newint(lastTime,currentTime,lc,false);
UPoint nextUnit(newint,lastPoint,point);
if(nextUnit.IsValid()){
result.MergeAdd(nextUnit);
}
lastPoint = point;
}
}
}
if(KeepEndPoint || exactPath){
Get(size-1,unit);
if(lastTime < unit.timeInterval.end){ // gap between end of the unit
// and last sample point
Interval<Instant> newint(lastTime,unit.timeInterval.end,
lc,unit.timeInterval.rc);
UPoint nextUnit(newint,lastPoint,unit.p1);
result.MergeAdd(nextUnit);
}
}
}
void MPoint::MVelocity( MPoint& result ) const
{
result.Clear();
if( !IsDefined() ){
result.SetDefined( false );
return;
}
result.SetDefined( true );
UPoint uPoint(false);
UPoint p(true);
// int counter = 0;
result.StartBulkLoad();
for( int i = 0; i < GetNoComponents(); i++ ){
Get( i, uPoint );
/*
Definition of a new point unit p. The velocity is constant
at all times of the interval of the unit. This is exactly
the same as within operator ~speed~. The result is a vector
and can be represented as a upoint.
*/
uPoint.UVelocity( p );
if( p.IsDefined() ){
result.Add( p );
// counter++;
}
}
result.EndBulkLoad( true );
}
void MPoint::MSpeed( MReal& result, const Geoid* geoid ) const
{
result.Clear();
if( !IsDefined() ){
result.SetDefined( false );
return;
}
result.SetDefined( true );
UPoint uPoint(false);
UReal uReal(true);
result.StartBulkLoad();
bool valid = true;
for( int i = 0; valid && (i < GetNoComponents()); i++ ){
Get( i, uPoint );
uPoint.USpeed( uReal, geoid );
if( uReal.IsDefined() ){
result.Add( uReal ); // append ureal to mreal
} else {
valid = false;
}
}
result.EndBulkLoad( true );
result.SetDefined( valid );
}
bool MPoint::Append(const MPoint& p, const bool autoresize /*=true*/){
if(!IsDefined()){
return false;
}
if(!p.IsDefined()){
Clear();
SetDefined(false);
return false;
}
int size1 = this->GetNoComponents();
int size2 = p.GetNoComponents();
if(size1>0 && size2>0){
// check whether p starts after the end of this
UPoint u1;
UPoint u2;
this->Get(size1-1,u1);
p.Get(0,u2);
if((u1.timeInterval.end > u2.timeInterval.start) ||
( (u1.timeInterval.end == u2.timeInterval.start) &&
(u1.timeInterval.rc && u2.timeInterval.lc))){
this->Clear();
this->SetDefined(false);
return false;
}
}
UPoint up;
UPoint u;
if(size2>0){ // process the first unit of p
if(autoresize){
units.resize(size1+size2);
}
p.Get(0,up);
this->MergeAdd(up);
}
StartBulkLoad();
for(int i=1; i<size2; i++){
p.Get(i,up);
this->Add(up);
}
EndBulkLoad(false);
return true;
}
void MPoint::Disturb(MPoint& result,
const double maxDerivation,
double maxDerivationPerStep){
result.Clear();
if(!IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined( true );
assert(IsOrdered());
int size = GetNoComponents();
if(size>0){
result.Resize(size);
}
if(maxDerivationPerStep>maxDerivation){
maxDerivationPerStep=maxDerivation;
}
if(maxDerivationPerStep<=0){
result.CopyFrom(this);
return;
}
double errx = 2*maxDerivation * (double)rand()/(double)RAND_MAX -
maxDerivation;
double erry = 2*maxDerivation * (double)rand()/(double)RAND_MAX -
maxDerivation;
UPoint unit1;
Point lastPoint;
for(int i=0;i<size;i++){
Get(i,unit1);
Point p0(true,unit1.p0.GetX()+errx,unit1.p0.GetY()+erry);
double dx = 2*maxDerivationPerStep * (double)rand()/(double)RAND_MAX -
maxDerivationPerStep;
double dy = 2*maxDerivationPerStep * (double)rand()/(double)RAND_MAX -
maxDerivationPerStep;
errx += dx;
erry += dy;
if(errx>maxDerivation){
errx = maxDerivation;
}
if(errx < -maxDerivation){
errx = -maxDerivation;
}
if(erry>maxDerivation){
erry = maxDerivation;
}
if(erry < -maxDerivation){
erry = -maxDerivation;
}
Point p1(true,unit1.p1.GetX()+errx,unit1.p1.GetY()+erry);
UPoint unit(unit1.timeInterval, p0,p1);
result.MergeAdd(unit);
}
}
double MPoint::Length() const{
assert( IsDefined() );
if(!IsDefined()){
return -1;
}
double res = 0;
UPoint unit;
int size = GetNoComponents();
for(int i=0;i<size;i++){
Get(i,unit);
res += unit.p0.Distance(unit.p1);
}
return res;
}
double MPoint::Length(const Geoid& g, bool& valid) const{
valid = IsDefined();
if(!valid){
return -1;
}
double res = 0;
UPoint unit;
int size = GetNoComponents();
for(int i=0; (valid && (i<size)); i++){
Get(i,unit);
res += unit.p0.DistanceOrthodrome(unit.p1, g, valid);
}
return res;
}
void MPoint::Vertices(Points& result) const{
result.Clear();
if(!IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined( true );
result.StartBulkLoad();
UPoint unit;
int size = units.Size();
for(int i=0;i<size;i++){
units.Get(i,&unit);
Point p0(unit.p0);
Point p1(unit.p1);
result += p0;
result += p1;
}
result.EndBulkLoad();
}
void MPoint::gk(const int &zone, MPoint& result) const{
result.Clear();
if( !IsDefined() || (zone < 0) || (zone > 119) ) {
result.SetDefined(false);
return;
}
result.SetDefined( true );
result.StartBulkLoad();
UPoint unit;
WGSGK gk;
gk.setMeridian(zone);
int size = units.Size();
for(int i=0;i<size;i++){
units.Get(i,&unit);
UPoint u(unit);
if(!gk.project(unit.p0, u.p0) || !gk.project(unit.p1, u.p1)){
// error detected
result.EndBulkLoad();
result.Clear();
result.SetDefined(false);
return;
} else {
result.MergeAdd(u);
}
}
result.EndBulkLoad();
}
/*
Private helper function for the delay operator
*/
double* MPoint::MergePartitions(double* first, int firstSize, double* second,
int secondSize, int& count )
{
double* res= new double[firstSize + secondSize ];
count=0;
int index1=0, index2=0;
double candidate,last=-1;
while(index1 < firstSize && index2< secondSize){
if (first[index1] < second[index2])
candidate= first[index1++];
else if(first[index1] > second[index2])
candidate= second[index2++];
else {
candidate= second[index2++];
index1++;
}
if(!AlmostEqual(candidate , last))
last= res[count++]= candidate;
}
while(index1< firstSize){
if( !AlmostEqual((candidate = first[index1++]) , last))
last=res[count++]=candidate;
}
while(index2<secondSize){
if( !AlmostEqual((candidate = second[index2++]) , last))
last=res[count++]=candidate;
}
return res;
}
/*
Private helper function for the delay operator
*/
int MPoint::IntervalRelation(Interval<Instant> &int_a_b,
Interval<Instant> &int_c_d ) const
{
Instant a= int_a_b.start;
Instant b= int_a_b.end;
Instant c= int_c_d.start;
Instant d= int_c_d.end;
assert(a < b && c < d );
/*
The assertion will fail in case of numerical instability (i.e: rounding error)
*/
if(b < c) // a----b----c----d
return 1;
if(a > d) // c----d----a----b
return 2;
if(b == c) // a----bc----d
return 3;
if(d == a) // c----da----b
return 4;
if(a < c && c < b && b < d) //a----c----b----d
return 5;
if(c < a && a < d && d < b) //c----a----d----b
return 6;
if(a==c && b==d) //ac----bd
return 7;
if(a==c && b< d) //ac----b----d
return 8;
if(a==c && d< b) //ac----d----b
return 9;
if(c< a && b==d) //c----a----bd
return 10;
if(a <c && b==d) //a----c----bd
return 11;
if(c <a && b <d) //c----a----b----d
return 12;
if(a <c && d <b) //a----c----d----b
return 13;
assert(false); //can not be other value
return 666;
}
/*
Helper function for the delay operator
Only for use with linear units (a==0, r==false)!
*/
int AtValue(const UReal* unit, double val, Instant& inst,
Interval<Instant>& intr,bool ignorelimits)
{
assert( unit->IsDefined() );
assert( AlmostEqual(unit->a,0) );
assert( !unit->r );
if(AlmostEqual(unit->b,0))
{
if(AlmostEqual(unit->c, val))
{
intr= unit->timeInterval;
return 2; //result is the whole unit interval
}
else
{
return 0; //result is outside the unit interval
}
}
inst= unit->timeInterval.start;
double fraction= (val - unit->c)/unit->b;
Instant at(durationtype);
at.ReadFrom(fraction);
inst+= at;
if( !ignorelimits && ((inst == unit->timeInterval.start &&
!unit->timeInterval.lc) || (inst == unit->timeInterval.end &&
!unit->timeInterval.rc)))
return 0;
if(inst < unit->timeInterval.start || inst > unit->timeInterval.end)
return 0; //result is outside the unit interval
return 1; // result is a certain time instant within the unit interval
}
/*
The following macros help make the code of the ~MPoint::DelayOperator~ more
readable. They are common code snippets that appear several times within the
operator. The ~\_startunit~ macro does the necessary variable settings for
starting a new delay unit. The ~\_endunit~ macro does the necessary variable
settings for closing a new delay unit. The ~\_createunit~ macro uses the
local variables to generate a delay unit and appends it to the result. The
~\_createunitpar~ macro, creates a delay unit from the parameters and appends
it to the result.
*/
#define _startunit(val , t) \
delayValueAtUnitStartTime = val; \
delayUnitStartTime = t; \
atUnitStart = false; \
if(debugme) cout<<"\n\t\tStartUnit ("<<val<<" @ "; t.Print(cout); cout<<" )";
#define _endunit(val, t) \
delayValueAtUnitEndTime=val; \
delayUnitEndTime=t; \
atUnitStart = true; \
if(debugme) cout<<"\n\t\tEndUnit ("<<val<<" @ "; t.Print(cout); cout<<" )";
#define _createunitpar(val1, t1, val2, t2) \
intr.start=t1; intr.end=t2; \
runit= new UReal(intr, val1 * 86400, val2 * 86400); \
delayRes->Add(*runit); \
delete runit; \
if(debugme) cout<<"\n\t\tCreateUnit" ;
#define _createunit \
intr.start= delayUnitStartTime; intr.end=delayUnitEndTime; \
runit= new UReal(intr, delayValueAtUnitStartTime * 86400, \
delayValueAtUnitEndTime * 86400); \
delayRes->Add(*runit); \
if(debugme) cout<<"\n\t\tCreateIntermediateUnit ("; \
runit->Print(cout); cout<<" )"; \
delete runit;
MReal* MPoint::DelayOperator(const MPoint* actual, const Geoid* geoid)
{
bool debugme=false;
if(!this->IsDefined() || !actual->IsDefined() ||
(geoid && !geoid->IsDefined()))
{ MReal* res= new MReal(0); res->SetDefined(false); return res;}
if(this->GetNoComponents()<1 || actual->GetNoComponents()<1)
return new MReal(0);
double* partitionActual=new double[actual->GetNoComponents()+1];
double* partitionSchedule=new double[this->GetNoComponents()+1];
MReal* DTActual= actual->DistanceTraversed(partitionActual, geoid);
MReal* DTSchedule= this->DistanceTraversed(partitionSchedule, geoid);
if(!DTActual->IsDefined() || !DTSchedule->IsDefined())
{ MReal* res= new MReal(0); res->SetDefined(false); return res;}
int DTActualSize= DTActual->GetNoComponents();
int DTScheduleSize= DTSchedule->GetNoComponents();
int partitionSize;
double* partition=
MergePartitions(partitionActual,DTActualSize+1,partitionSchedule,
DTScheduleSize+1,partitionSize);
if(debugme)
{
cout.flush();
cout<<"\n ActualPartition: ";
for(int i=0; i<= DTActualSize; i++)
cout<<partitionActual[i]<<" ";
cout<<"\n SchedulePartition: ";
for(int i=0; i<= DTScheduleSize; i++)
cout<<partitionSchedule[i]<<" ";
cout<<"\n MergedPartition: ";
for(int i=0; i< partitionSize; i++)
cout<<partition[i]<<" ";
cout.flush();
}
UReal actualScanUnit, scheduleScanUnit;
UReal* runit;
int actualScanIndex=0, scheduleScanIndex=0;
DTActual->Get(actualScanIndex, actualScanUnit);
DTSchedule->Get(scheduleScanIndex,scheduleScanUnit);
MReal* delayRes= new MReal(partitionSize);
Intime<CcReal> temp;
DTActual->Initial(temp);
Instant delayUnitStartTime(temp.instant);
Instant delayUnitEndTime(instanttype);
Instant scheduledTime(instanttype),actualTime(instanttype);
Interval<Instant> scheduledInterval, actualInterval, intr;
double delayValueAtUnitStartTime = 0.0, delayValueAtUnitEndTime = 0.0;
bool atUnitStart=true, isInstantActual=true, isInstantSchedule=true;
double distVal = 0.0;
int test = 0;
intr.lc=true;
intr.rc=false;
for(int i=0; i<partitionSize; i++)
{
distVal=partition[i];
/*
The coming steps assumes that DistanceTraversed return an
MReal satisfying the minimal presentation condition
*/
if(scheduleScanIndex < DTScheduleSize -1)
test = AtValue(&scheduleScanUnit, distVal, scheduledTime,
scheduledInterval,false);
else
test = AtValue(&scheduleScanUnit, distVal, scheduledTime,
scheduledInterval,true);
while( test==0 )
{
scheduleScanIndex++;
assert(scheduleScanIndex < DTSchedule->GetNoComponents());
DTSchedule->Get(scheduleScanIndex,scheduleScanUnit);
if(scheduleScanIndex < DTScheduleSize -1)
test = AtValue(&scheduleScanUnit, distVal, scheduledTime,
scheduledInterval,false);
else
test = AtValue(&scheduleScanUnit, distVal, scheduledTime,
scheduledInterval,true);
}
isInstantSchedule = (test==1)? true : false;
if(actualScanIndex < DTActualSize -1)
test = AtValue(&actualScanUnit, distVal, actualTime,
actualInterval,false);
else
test = AtValue(&actualScanUnit, distVal, actualTime,
actualInterval,true);
while( test==0 )
{
actualScanIndex++;
assert(actualScanIndex < DTActual->GetNoComponents());
DTActual->Get(actualScanIndex,actualScanUnit);
if(actualScanIndex < DTActualSize -1)
test = AtValue(&actualScanUnit, distVal, actualTime,
actualInterval,false);
else
test = AtValue(&actualScanUnit, distVal, actualTime,
actualInterval,true);
}
isInstantActual = (test==1)? true : false;
if(debugme)
{
cout<<endl;
cout<<"At iteration: "<<i<<" traversed distance: "<< distVal;
cout<<"\n\tActual traversed this distance at: ";
if(isInstantActual) actualTime.Print(cout);
else actualInterval.Print(cout);
cout<<"\n\tSchedule traversed this distance at: ";
if(isInstantSchedule) scheduledTime.Print(cout);
else scheduledInterval.Print(cout);
cout<<endl<<"\tActions taken:";
}
if(isInstantActual && isInstantSchedule)
{
if(atUnitStart)
{
_startunit( (actualTime - scheduledTime).ToDouble(),
actualTime );
}
else
{
_endunit( (actualTime - scheduledTime).ToDouble(), actualTime );
_createunit;
_startunit(delayValueAtUnitEndTime, delayUnitEndTime);
}
}
else if (isInstantActual && !isInstantSchedule)
{
if(atUnitStart)
/*
Can happen only if the schedule started with immobile units (distVal==0)
*/
{
assert(distVal==0);
_startunit( (actualTime - scheduledInterval.end).ToDouble() ,
actualTime);
}
else
{
_endunit((actualTime - scheduledInterval.start).ToDouble() ,
actualTime);
_createunit;
_startunit( (actualTime - scheduledInterval.end).ToDouble() ,
actualTime);
}
}
else if (!isInstantActual && isInstantSchedule)
{
if(atUnitStart)
/*
Can happen only if the actual started with immobile units
*/
{
assert(distVal==0);
//add a delay unit corresponding to the immobile unit
_createunitpar(
(actualInterval.start - scheduledTime).ToDouble(),
actualInterval.start,
(actualInterval.end - scheduledTime).ToDouble(),
actualInterval.end);
//start the next unit
_startunit((actualInterval.end - scheduledTime).ToDouble(),
actualInterval.end);
}
else
{
//close the current unit
_endunit((actualInterval.start - scheduledTime).ToDouble(),
actualInterval.start);
_createunit;
//add a delay unit corresponding to the immobile unit
_createunitpar(
(actualInterval.start - scheduledTime).ToDouble(),
actualInterval.start,
(actualInterval.end - scheduledTime).ToDouble(),
actualInterval.end);
//start the next unit
_startunit((actualInterval.end - scheduledTime).ToDouble(),
actualInterval.end);
}
}
else if(!isInstantActual && !isInstantSchedule)
{
int intervalRelation= IntervalRelation(actualInterval,
scheduledInterval);
Instant a(actualInterval.start), b(actualInterval.end);
Instant c(scheduledInterval.start), d(scheduledInterval.end);
switch(intervalRelation)
{
case 1:
case 3:
{
if(!atUnitStart) {_endunit((a-c).ToDouble() ,a); _createunit;}
_createunitpar((a-c).ToDouble(),a,(b-c).ToDouble(),b);
_startunit((b-d).ToDouble(),b);
break;
}
case 2:
case 4:
{
if(!atUnitStart) {_endunit((a-c).ToDouble() ,a); _createunit;}
_createunitpar((a-d).ToDouble(),a,(b-d).ToDouble(),b);
_startunit((b-d).ToDouble(),b);
break;
}
case 5:
{
if(!atUnitStart) {_endunit((a-c).ToDouble() ,a); _createunit;}
_createunitpar((a-c).ToDouble(), a, 0, c);
_createunitpar(0, c, 0, b);
_startunit((b-d).ToDouble(),b);
break;
}
case 6:
{
if(!atUnitStart) {_endunit((a-c).ToDouble() ,a); _createunit;}
_createunitpar(0, a, 0, d);
_createunitpar(0, d, (b-d).ToDouble(), b);
_startunit((b-d).ToDouble(),b);
break;
}
case 7:
{
if(!atUnitStart) {_endunit((a-c).ToDouble() ,a); _createunit;}
_createunitpar((a-c).ToDouble(),a,(b-d).ToDouble(),b);
_startunit((b-d).ToDouble(),b);
break;
}
case 8:
{
if(!atUnitStart) {_endunit((a-c).ToDouble() ,a); _createunit;}
_createunitpar((a-c).ToDouble(), a, 0, b);
_startunit((b-d).ToDouble(),b);
break;
}
case 9:
{
if(!atUnitStart) {_endunit((a-c).ToDouble() ,a); _createunit;}
_createunitpar((a-c).ToDouble(), a, 0, d);
_createunitpar(0, d, (b-d).ToDouble(), b);
_startunit((b-d).ToDouble(),b);
break;
}
case 10:
{
if(!atUnitStart) {_endunit((a-c).ToDouble() ,a); _createunit;}
_createunitpar(0, a, (b-d).ToDouble(),b);
_startunit((b-d).ToDouble(),b);
break;
}
case 11:
{
if(!atUnitStart) {_endunit((a-c).ToDouble() ,a); _createunit;}
_createunitpar((a-c).ToDouble(), a, 0, c);
_createunitpar(0, c, (b-d).ToDouble(), b);
_startunit((b-d).ToDouble(),b);
break;
}
case 12:
{
if(!atUnitStart) {_endunit((a-c).ToDouble() ,a); _createunit;}
_createunitpar(0, a, 0 ,b);
_startunit((b-d).ToDouble(),b);
break;
}
case 13:
{
if(!atUnitStart) {_endunit((a-c).ToDouble() ,a); _createunit;}
_createunitpar((a-c).ToDouble(), a, 0, c);
_createunitpar(0, c, 0, d);
_createunitpar(0, d, (b-d).ToDouble(), b);
_startunit((b-d).ToDouble(),b);
break;
}
default:
assert(false);
}
}
}
delete[] partitionActual;
delete[] partitionSchedule;
delete DTActual;
delete DTSchedule;
delete[] partition;
return delayRes;
}
MReal* MPoint::DistanceTraversed( const Geoid* geoid ) const
{
if( !IsDefined() || (geoid && !geoid->IsDefined()) ) {
MReal* res = new MReal(0);
res->SetDefined( false );
return res;
}
double * p= new double[GetNoComponents()+1];
MReal* res= DistanceTraversed(p, geoid);
delete[] p;
return res;
}
MReal* MPoint::DistanceTraversed(double* partition, const Geoid* geoid ) const
{
bool debugme= false;
bool ok = true; // flag for DistanceOrthodrome
UPoint uPoint;
Point last;
MReal* dist= new MReal(GetNoComponents());
double dist1=0, dist2=0, unitstart=0, unitend=0,lastslope=0,curslope=0;
Interval<Instant> interval;
UReal* unit=0;
int partitionIndex=0;
/*
The movement must be continuous in time (i.e. without intervals of undefined),
otherwise, the result is undefined
*/
Periods defTime( 0 );
DefTime( defTime );
if(defTime.GetNoComponents()>1 )
{
dist->Clear();
dist->SetDefined(false);
return dist;
}
try
{
Get( 0, uPoint );
dist1=0;
dist2= uPoint.p0.Distance(uPoint.p1);
last= uPoint.p1;
lastslope= (dist2-dist1)/((uPoint.timeInterval.end -
uPoint.timeInterval.start).millisecondsToNull() / 1000.0);
unitstart = dist1;
unitend= dist2;
interval=uPoint.timeInterval;
for( int i = 1; i < GetNoComponents(); i++ )
{
Get( i, uPoint );
if(last != uPoint.p0)
throw(1); // The trajectory is not continuous
dist1= dist2;
dist2= dist1 + (geoid?uPoint.p0.DistanceOrthodrome(uPoint.p1,*geoid,ok)
:uPoint.p0.Distance(uPoint.p1));
if(!ok){ // found invalid geographic coordinates
cout << "\nFound invalid geographic coordinates: uPoint.p0="
<< uPoint.p0 << ", uPoint.p1=" << uPoint.p1 << "." << endl
<< "Returning undefined result!" << endl;
dist->SetDefined(false);
return dist;
}
last= uPoint.p1;
//Assure minimal representation
curslope= (dist2-dist1)/((uPoint.timeInterval.end -
uPoint.timeInterval.start).millisecondsToNull()/ 1000.0);
if(debugme)
{
cout.flush();
cout<<"\nlastSlope: " <<lastslope << " curSlope:"<<curslope;
cout.flush();
}
if(curslope != lastslope)
{
unit = new UReal(interval, unitstart, unitend);
if(debugme)
{
cout.flush();
cout<<"\nAdding new UReal";
// cout<<"\n\tAt time "<<
// unit->timeInterval.start.GetAllMilliSeconds();
// cout<<" the distance traversed is "<< unit->Min(dummy);
// cout<<"\n\tAt time "<<
// unit->timeInterval.end.GetAllMilliSeconds();
// cout<<" the distance traversed is "<< unit->Max(dummy);
cout.flush();
}
dist->Add(*unit);
delete unit;
partition[partitionIndex]= unitstart;
partitionIndex++;
unitstart = dist1;
unitend= dist2;
interval=uPoint.timeInterval;
lastslope= curslope;
}
else
{
interval.end= uPoint.timeInterval.end;
unitend= dist2;
}
}
unit = new UReal(interval, unitstart, unitend);
dist->Add(*unit);
delete unit;
partition[partitionIndex]= unitstart;
partitionIndex++;
partition[partitionIndex]= unitend;
dist->TrimToSize();
return dist;
}
catch(int i)
{
dist->TrimToSize();
dist->SetDefined(false);
return dist;
}
}
void MPoint::AtRegion(const Region *r, MPoint &result) const {
result.Clear();
if(!IsDefined() || !r->IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined(true);
if(IsEmpty() || r->IsEmpty()) {
return;
}
// check for intersection of total MBRs
Rectangle<2u> rMBR = r->BoundingBox();
if(!rMBR.Intersects(BoundingBoxSpatial())) {
return;
}
// iterate through all units
UPoint uPoint;
std::vector<UPoint> uResultVector;
for( int i = 1; i < GetNoComponents(); i++ ){
Get( i, uPoint );
if(!uPoint.AtRegion(r, uResultVector)) {
std::cerr << __PRETTY_FUNCTION__ << " WARNING: no result for UPoint ("
<< i << "): uPoint = " << uPoint << endl;
continue;
}
for(unsigned int j=0; j<uResultVector.size(); j++) {
result.MergeAdd(uResultVector[j]);
}
}
return;
}
void MPoint::AtRect(const Rectangle<2>& rect, MPoint& result) const{
result.Clear();
if(!IsDefined() || !rect.IsDefined()){
result.SetDefined(false);
return;
}
Rectangle<2u> bbox = BoundingBoxSpatial();
if(!bbox.Intersects(rect)){
return; // dijoint, return empty
}
if(rect.Contains(bbox)){
result.CopyFrom(this);
return;
}
// Bounding boxes overlap, check units
UPoint src;
UPoint dest(false);
result.StartBulkLoad();
for(int i=0;i<GetNoComponents();i++){
Get(i,src);
src.At(rect,dest);
if(dest.IsDefined()){
assert(dest.timeInterval.start.GetType()==datetime::instanttype);
assert(dest.timeInterval.end.GetType()==datetime::instanttype);
result.Add(dest);
}
}
result.EndBulkLoad(false);
}
const bool Periods::Contains(const SecInterval& iv) const {
if (!IsDefined() || !iv.IsDefined()) {
return false;
}
int startIvPos = GetIndexOf(iv.start, true);
if (startIvPos < 0) {
return false;
}
Interval<Instant> startIv;
Get(startIvPos, startIv);
if (startIv.lc < iv.lc) {
return false;
}
return startIv.Contains(iv);
}
const bool Periods::Contains(const Periods& per) const {
RefinementStream<Periods, Periods, Interval<Instant>, Interval<Instant> >
rs(this, &per);
int p1, p2;
Interval<Instant> iv;
while (rs.getNext(iv, p1, p2)) {
if(p1 < 0) {
return false;
}
if(rs.finished2()) {
return true;
}
}
return true;
}
/*
3.2 Class ~CMPoint~
We need to overwrite some methods from template class ~Mapping~, as we need
to maintain the object's MBR in ~bbox~.
*/
void CMPoint::GetMPoint(MPoint& result) const {
result.Clear();
result.SetDefined(IsDefined());
if (!IsDefined() || IsEmpty()) {
return;
}
UPoint up(true);
for (int i = 0; i < GetNoComponents(); i++) {
GetUPoint(i, up);
result.Add(up);
}
}
void CMPoint::GetUPoint(const int pos, UPoint& result) const {
assert(IsDefined());
assert(pos >= 0 && pos < GetNoComponents());
CUPoint cup(true);
Get(pos, cup);
cup.GetUPoint(result);
}
void CMPoint::ConvertFrom(const MPoint& src, const DateTime dur,
const Geoid *geoid /* = 0 */) {
if (!src.IsDefined() || dur.GetType() != durationtype) {
SetDefined(false);
return;
}
SetDefined(true);
Clear();
if (src.IsEmpty()) {
return;
}
CUPoint cup(true);
UPoint upSrc(true), upDest(true);;
DateTime durTemp(durationtype), beginOfTime(instanttype),
diffToBeginOfTime(durationtype), firstInst(instanttype),
lastInst(instanttype), durCurIv(durationtype);
durTemp.SetToZero();
beginOfTime.SetToZero();
src.InitialInstant(firstInst);
src.FinalInstant(lastInst);
diffToBeginOfTime = firstInst - beginOfTime;
if (lastInst - firstInst < dur) { // one cupoint suffices
cup.ConvertFrom(src, geoid);
cup.timeInterval.start.SetToZero();
cup.timeInterval.end -= diffToBeginOfTime;
Add(cup);
RestoreBoundingBox(true, geoid);
return;
}
Point p0(true), p1(true);
MPoint mpTemp(true), mpTempShifted(true), srcPart(true);
MReal dist(true);
Periods per(true);
src.TemporalFunction(firstInst, upDest.p0, true);
upDest.timeInterval.start = beginOfTime;
upDest.timeInterval.lc = false;
bool correct = true;
CcReal distCC(true);
for (DateTime i = firstInst + dur; i < lastInst; i += dur) {
src.TemporalFunction(i, upDest.p1, true);
upDest.timeInterval.end = i - diffToBeginOfTime;
upDest.timeInterval.rc = true;
mpTemp.Add(upDest);
mpTemp.timeMove(diffToBeginOfTime, mpTempShifted);
per.Add(Interval<Instant>(i - dur, i, true, false));
src.AtPeriods(per, srcPart);
srcPart.SquaredDistance(mpTempShifted, dist);
if (!geoid) {
cup.Set(upDest, sqrt(dist.Max(correct)));
}
else {
dist.Recompute(srcPart, mpTempShifted, geoid);
cup.Set(upDest, dist.Max(correct));
}
cup.SetRadius(cup.GetRadius());
assert(correct);
// cout << "sqdist between " << mpTempShifted << " and " << srcPart
// << " amounts to " << dist << ", max is " << sqrt(dist.Max(correct))
// << endl;
Add(cup);
mpTemp.Clear();
mpTempShifted.Clear();
per.Clear();
dist.Clear();
srcPart.Clear();
upDest.p0 = upDest.p1; // prepare next cupoint
upDest.timeInterval.start = upDest.timeInterval.end;
upDest.timeInterval.lc = false;
}
DateTime destFinalInst(instanttype);
FinalInstant(destFinalInst);
if (destFinalInst.IsDefined() &&
destFinalInst < lastInst - diffToBeginOfTime) { // process end of src
src.Get(src.GetNoComponents() - 1, upSrc);
upDest.p1 = upSrc.p1;
upDest.timeInterval.end = lastInst - diffToBeginOfTime;
upDest.timeInterval.rc = true;
mpTemp.Add(upDest);
mpTemp.timeMove(diffToBeginOfTime, mpTempShifted);
Interval<Instant> iv(destFinalInst + diffToBeginOfTime, lastInst, true,
false);
per.Add(iv);
src.AtPeriods(per, srcPart);
srcPart.SquaredDistance(mpTempShifted, dist);
if (!geoid) {
cup.Set(upDest, sqrt(dist.Max(correct)));
}
else {
dist.Recompute(srcPart, mpTempShifted, geoid);
cup.Set(upDest, dist.Max(correct));
}
cup.SetRadius(cup.GetRadius());
assert(correct);
Add(cup);
}
RestoreBoundingBox(true, geoid);
}
void CMPoint::ConvertFrom(const MPoint& src, const CcReal& threshold,
const Geoid *geoid /* = 0 */) {
if (!src.IsDefined() || !threshold.IsDefined()) {
SetDefined(false);
return;
}
SetDefined(true);
Clear();
if (src.IsEmpty()) {
return;
}
DateTime beginOfTime(instanttype), diffToBeginOfTime(durationtype),
firstInst(instanttype);
beginOfTime.SetToZero();
src.InitialInstant(firstInst);
diffToBeginOfTime = firstInst - beginOfTime;
double thresh = threshold.GetValue();
MPoint mpSimplified(true), mpSimplePart(true), srcPart(true),
srcFinalPart(true), simpleFinalPart(true);
src.Simplify(thresh, mpSimplified, false, DateTime(0.0), geoid);
UPoint upSimplified(true);
CUPoint cup(true);
MReal dist(true);
Periods per(true);
bool correct = true;
for (int i = 0; i < mpSimplified.GetNoComponents() - 1; i++) {
mpSimplified.Get(i, upSimplified);
per.Add(upSimplified.timeInterval);
src.AtPeriods(per, srcPart);
mpSimplePart.Add(upSimplified);
srcPart.SquaredDistance(mpSimplePart, dist);
if (!geoid) {
cup.Set(upSimplified, std::min(thresh, sqrt(dist.Max(correct))));
}
else {
dist.Recompute(srcPart, mpSimplePart, geoid);
cup.Set(upSimplified, std::min(thresh, dist.Max(correct)));
}
cup.timeInterval.start -= diffToBeginOfTime;
cup.timeInterval.end -= diffToBeginOfTime;
Add(cup);
per.Clear();
mpSimplePart.Clear();
}
if (!mpSimplified.IsEmpty()) { // radius of final (or only) cyl may be smaller
mpSimplified.Get(mpSimplified.GetNoComponents() - 1, upSimplified);
per.Add(upSimplified.timeInterval);
src.AtPeriods(per, srcFinalPart);
mpSimplified.AtPeriods(per, simpleFinalPart);
srcFinalPart.SquaredDistance(simpleFinalPart, dist);
if (!geoid) {
cup.Set(upSimplified, std::min(thresh, sqrt(dist.Max(correct))));
}
else {
dist.Recompute(srcFinalPart, simpleFinalPart, geoid);
cup.Set(upSimplified, std::min(thresh, dist.Max(correct)));
}
cup.SetRadius(cup.GetRadius());
assert(correct);
cup.timeInterval.start -= diffToBeginOfTime;
cup.timeInterval.end -= diffToBeginOfTime;
Add(cup);
}
RestoreBoundingBox(true, geoid);
}
void CMPoint::Clear() {
Mapping<CUPoint, CPoint>::Clear(); // call super
bbox.SetDefined(false); // invalidate bbox
}
void CMPoint::Add(const CUPoint& unit) {
assert(unit.IsDefined());
assert(unit.IsValid());
if (!IsDefined() || !unit.IsDefined()) {
SetDefined(false);
return;
}
units.Append(unit);
if (units.Size() == 1) {
// cout << " MPoint::Add FIRST ADD" << endl;
// cout << "\t Old bbox = "; bbox.Print(cout);
bbox.SetDefined(true);
bbox = unit.BoundingBox();
// cout << "\n\t New bbox = "; bbox.Print(cout);
}
else {
// cout << "\t Old bbox = "; bbox.Print(cout);
bbox = bbox.Union(unit.BoundingBox());
// cout << "\n\t New bbox = "; bbox.Print(cout);
}
RestoreBoundingBox(false);
}
void CMPoint::Restrict(const std::vector<std::pair<int, int> >& intervals) {
if (!IsDefined()) {
Clear();
bbox.SetDefined(false);
SetDefined(false);
return;
}
units.Restrict(intervals, units); // call super
bbox.SetDefined(false); // invalidate bbox
RestoreBoundingBox(false); // recalculate it
}
std::ostream& CMPoint::Print(std::ostream &os) const {
if (!IsDefined()) {
return os << "(CMPoint: undefined)";
}
os << "(CMPoint: defined, MBR = ";
bbox.Print(os);
os << ", contains " << GetNoComponents() << " units: ";
CUPoint unit(true);
for (int i = 0; i < GetNoComponents(); i++) {
Get(i, unit);
os << "\n\t";
unit.Print(os);
}
os << "\n)" << endl;
return os;
}
bool CMPoint::EndBulkLoad(const bool sort, const bool checkvalid) {
bool res = Mapping<CUPoint, CPoint>::EndBulkLoad(sort, checkvalid);
if (res) {
RestoreBoundingBox(false);
}
return res;
}
bool CMPoint::operator==(const CMPoint& r) const {
if (!IsDefined()) {
return !r.IsDefined();
}
if (!r.IsDefined()) {
return false;
}
assert(IsOrdered() && r.IsOrdered());
if (IsEmpty()) {
return r.IsEmpty();
}
if (r.IsEmpty()) {
return false;
}
if (bbox != r.bbox) {
return false;
}
return Mapping<CUPoint, CPoint>::operator==(r);
}
bool CMPoint::Present(const Instant& t) const {
assert(IsDefined());
assert(IsOrdered());
assert(t.IsDefined());
if (bbox.IsDefined()) { // do MBR-check
double instd = t.ToDouble();
double mint = bbox.MinD(2);
double maxt = bbox.MaxD(2);
if ((instd < mint && !AlmostEqual(instd,mint)) ||
(instd > maxt && !AlmostEqual(instd,maxt))) {
// cout << __PRETTY_FUNCTION__<< "(" << __FILE__ << __LINE__
// << "): Bounding box check failed:" << endl;
// cout << "\tInstant : "; t.Print(cout); cout << endl;
// cout << "\tinstd : " << instd << endl;
// cout << "\tmint/maxt :" << mint << "\t/\t" << maxt << endl;
// cout << "\tBBox = "; bbox.Print(cout); cout << endl;
return false;
}
}
int pos = Position(t);
if (pos == -1) { //not contained in any unit
return false;
}
return true;
}
bool CMPoint::Present(const Periods& t) const {
assert(IsDefined());
assert(IsOrdered());
assert(t.IsDefined());
assert(t.IsOrdered());
if (bbox.IsDefined()) { // do MBR-check
double MeMin = bbox.MinD(2);
double MeMax = bbox.MaxD(2);
Instant tmin; t.Minimum(tmin);
Instant tmax; t.Maximum(tmax);
double pmin = tmin.ToDouble();
double pmax = tmax.ToDouble();
if ((pmax < MeMin && !AlmostEqual(pmax,MeMin)) ||
(pmin > MeMax && !AlmostEqual(pmin,MeMax))) {
// cout << __PRETTY_FUNCTION__<< "(" << __FILE__ << __LINE__
// << "): Bounding box check failed:" << endl;
// cout << "\tPeriod : "; t.Print(cout); cout << endl;
// cout << "\tpmin/pmax : " << pmin << "\t/\t" << pmax << endl;
// cout << "\ttmin/tmax :" << tmin << "\t/\t" << tmax << endl;
// cout << "\tMPoint : " << MeMin << "\t---\t" << MeMax << endl;
// cout << "\tBBox = "; bbox.Print(cout); cout << endl;
return false;
}
}
Periods defTime(0);
DefTime(defTime);
return t.Intersects(defTime);
}
void CMPoint::AtInstant(const Instant& t, Intime<CPoint>& result) const {
if(IsDefined() && t.IsDefined()) {
if (!bbox.IsDefined()) { // result is undefined
result.SetDefined(false);
}
else if (IsEmpty()) { // result is undefined
result.SetDefined(false);
}
else
{ // compute result
double instd = t.ToDouble();
double mind = bbox.MinD(2);
double maxd = bbox.MaxD(2);
if ((mind > instd && !AlmostEqual(mind,instd)) ||
(maxd < instd && !AlmostEqual(maxd,instd))) {
// cout << __PRETTY_FUNCTION__<< "(" << __FILE__ << __LINE__
// << "): Bounding box check failed:" << endl;
// cout << "\tInstant : "; t.Print(cout); cout << endl;
// cout << "\tinstd : " << instd << endl;
// cout << "\tmind/maxd :" << mind << "\t/\t" << maxd << endl;
// cout << "\tBBox = "; bbox.Print(cout); cout << endl;
result.SetDefined(false);
}
else {
assert(IsOrdered());
int pos = Position(t);
if (pos == -1) { // not contained in any unit
result.SetDefined(false);
}
else {
CUPoint posUnit(true);
units.Get(pos, &posUnit);
result.SetDefined(true);
posUnit.TemporalFunction(t, result.value);
result.instant.CopyFrom(&t);
}
}
}
}
else {
result.SetDefined(false);
}
}
void CMPoint::AtPeriods(const Periods& p, CMPoint& result) const {
result.Clear();
result.SetDefined(true);
if (IsDefined() && p.IsDefined()) {
if (!bbox.IsDefined()) { // result is undefined
result.SetDefined(false);
}
else if (IsEmpty() || p.IsEmpty()) { // result is defined but empty
result.SetDefined(true);
}
else if (IsMaximumPeriods(p)) { // p is [begin of time, end of time].
result.CopyFrom(this);
}
else { // compute result
assert(IsOrdered());
assert(p.IsOrdered());
Instant perMinInst; p.Minimum(perMinInst);
Instant perMaxInst; p.Maximum(perMaxInst);
double permind = perMinInst.ToDouble();
double permaxd = perMaxInst.ToDouble();
double mind = bbox.MinD(2);
double maxd = bbox.MaxD(2);
if ((mind > permaxd && !AlmostEqual(mind,permaxd)) ||
(maxd < permind && !AlmostEqual(maxd,permind))) {
// cout << __PRETTY_FUNCTION__<< "(" << __FILE__ << __LINE__
// << "): Bounding box check failed:" << endl;
// cout << "\tPeriod : "; p.Print(cout); cout << endl;
// cout << "\tperMinInst : "; perMinInst.Print(cout); cout << endl;
// cout << "\tperMaxInst : "; perMaxInst.Print(cout); cout << endl;
// cout << "\tpermind/permaxd : " << permind << "\t/\t"
// << permaxd << endl;
// cout << "\tmind/maxd :" << mind << "\t/\t" << maxd << endl;
// cout << "\tBBox = "; bbox.Print(cout); cout << endl;
result.SetDefined(true);
}
else {
result.StartBulkLoad();
CUPoint unit;
Interval<Instant> interval;
int i = 0, j = 0;
Get(i, unit);
p.Get(j, interval);
while(1) {
if (unit.timeInterval.Before(interval)) {
if (++i == GetNoComponents()) {
break;
}
Get(i, unit);
}
else if (interval.Before(unit.timeInterval)) {
if (++j == p.GetNoComponents()) {
break;
}
p.Get(j, interval);
}
else { // we have overlapping intervals, now
CUPoint r(true);
unit.AtInterval(interval, r);
assert(r.IsDefined());
assert(r.IsValid());
result.Add(r);
// cout << "\n\tunit = "; unit.Print(cout); cout << endl;
// cout << "\tinterval = "; interval.Print(cout); cout << endl;
// cout << "\tr = "; r.Print(cout); cout << endl;
if (interval.end == unit.timeInterval.end) { // same ending instant
if(interval.rc == unit.timeInterval.rc) { // and rightclosedness
if (++i == GetNoComponents()) {
break;
}
Get(i, unit);
if (++j == p.GetNoComponents()) {
break;
}
p.Get(j, interval);
}
else if (interval.rc == true) { // Advanve in mapping
if (++i == GetNoComponents()) {
break;
}
Get(i, unit);
}
else { // Advance in periods
assert(unit.timeInterval.rc == true);
if (++j == p.GetNoComponents()) {
break;
}
p.Get(j, interval);
}
}
else if (interval.end > unit.timeInterval.end) { // Adv in cmpoint
if (++i == GetNoComponents()) {
break;
}
Get(i, unit);
}
else { // Advance in periods
assert(interval.end < unit.timeInterval.end);
if (++j == p.GetNoComponents()) {
break;
}
p.Get(j, interval);
}
}
}
result.EndBulkLoad();
}
}
}
else {
result.SetDefined(false);
}
}
/*
RestoreBoundingBox() checks, whether the CMPoint's MBR ~bbox~ is ~undefined~
and thus may need to be recalculated and if, does so.
*/
void CMPoint::RestoreBoundingBox(const bool force, const Geoid* geoid) {
if (!IsDefined() || GetNoComponents() == 0) { // invalidate bbox
bbox.SetDefined(false);
}
else if (force || !bbox.IsDefined()) { // construct bbox
bbox.SetDefined(true);
CUPoint unit;
int size = GetNoComponents();
Get(0, unit); // safe, since (this) contains at least 1 unit
bbox = unit.BoundingBox(geoid);
for (int i = 1; i < size; i++) {
Get(i, unit);
bbox = bbox.Union(unit.BoundingBox(geoid));
}
} // else: bbox unchanged and still correct
}
// Class functions
Rectangle<3u> CMPoint::BoundingBox(const Geoid* geoid /*=0*/) const {
if (geoid) { // spherical geometry case:
if (!IsDefined() || (GetNoComponents() <= 0)) {
return Rectangle<3>(false);
}
CUPoint u;
Rectangle<3> bbx(false);
for (int i = 0; i < GetNoComponents(); i++) {
Get(i,u);
assert(u.IsDefined());
if (bbx.IsDefined()) {
bbx = bbx.Union(u.BoundingBox(geoid));
}
else {
bbx = u.BoundingBox(geoid);
}
}
return bbx;
} // else: euclidean case
return bbox;
}
// return the spatial bounding box (2D: X/Y)
const Rectangle<2> CMPoint::BoundingBoxSpatial(const Geoid* geoid) const {
Rectangle<2u> result(false);
if (!IsDefined() || (GetNoComponents() <= 0)) {
return result;
}
else {
Rectangle<3> bbx = this->BoundingBox(geoid);
result = bbx.Project2D(0,1); // project to X/Y
return result;
}
};
void CMPoint::Trajectory(Line& line) const {
MPoint mp(true);
GetMPoint(mp);
mp.Trajectory(line);
}
void CMPoint::MergeAdd(const CUPoint& unit) {
assert(IsDefined());
assert(unit.IsDefined());
assert(unit.IsValid());
int size = GetNoComponents();
if (size==0) { // the first unit
Add(unit); // Add() unit as first unit to empty mapping; bbox is updated.
return;
}
CUPoint last;
Get(size-1, last);
assert(last.timeInterval.end <= unit.timeInterval.start);
if (last.timeInterval.end != unit.timeInterval.start ||
!((last.timeInterval.rc ) ^ (unit.timeInterval.lc))) {
// intervals are not connected
Add(unit); // also adopts bbox
return;
}
if (!AlmostEqual(last.p1, unit.p0)) { // jump in spatial dimension
Add(unit); // also adopts bbox
return;
}
Interval<Instant> complete(last.timeInterval.start, unit.timeInterval.end,
last.timeInterval.lc, unit.timeInterval.rc);
CUPoint cupoint(complete, last.p0, unit.p1, unit.GetRadius());
CPoint cp;
cupoint.TemporalFunction(last.timeInterval.end, cp, true);
if (!AlmostEqual(*((Point*)&cp), last.p0)) {
Add(unit); // also adopts bbox
return;
}
assert(cupoint.IsValid());
assert(cupoint.IsDefined());
bbox = bbox.Union(cupoint.BoundingBox()); // update bbox
units.Put(size - 1, cupoint); // overwrite the last unit by a connected one
}
void CMPoint::Direction(MReal* result,
const bool useHeading /*=false*/,
const Geoid* geoid /*=0*/,
const double epsilon /*=0.0000001*/ ) const {
if (!IsDefined() || (geoid && (!geoid->IsDefined() || (epsilon <= 0.0)))) {
result->SetDefined(false);
return;
}
std::vector<UReal> resvector;
CUPoint unit(true);
for(int i = 0; i < GetNoComponents(); i++) {
Get(i, unit);
((UPoint*)&unit)->Direction(resvector, useHeading, geoid, epsilon);
}
result->Clear();
result->SetDefined(true);
result->StartBulkLoad();
for(std::vector<UReal>::iterator iter = resvector.begin();
iter != resvector.end(); iter++) {
if (iter->IsDefined() && iter->IsValid()) {
result->MergeAdd(*iter);
}
}
result->EndBulkLoad(false);
}
bool CMPoint::Append(const CMPoint& p, const bool autoresize /*=true*/) {
if (!IsDefined()) {
return false;
}
if (!p.IsDefined()) {
Clear();
SetDefined(false);
return false;
}
int size1 = this->GetNoComponents();
int size2 = p.GetNoComponents();
if (size1 > 0 && size2 > 0) { // check whether p starts after the end of this
CUPoint u1(true), u2(true);
this->Get(size1 - 1, u1);
p.Get(0, u2);
if ((u1.timeInterval.end > u2.timeInterval.start) ||
((u1.timeInterval.end == u2.timeInterval.start) &&
(u1.timeInterval.rc && u2.timeInterval.lc))) {
this->Clear();
this->SetDefined(false);
return false;
}
}
CUPoint up(true), u(true);
if (size2 > 0) { // process the first unit of p
if (autoresize) {
units.resize(size1 + size2);
}
p.Get(0, up);
this->MergeAdd(up);
}
StartBulkLoad();
for (int i = 1; i < size2; i++) {
p.Get(i, up);
this->Add(up);
}
EndBulkLoad(false);
return true;
}
double CMPoint::Length() const {
assert(IsDefined());
if (!IsDefined()) {
return -1.0;
}
double res = 0.0;
CUPoint unit(true);
int size = GetNoComponents();
for(int i = 0; i < size; i++) {
Get(i, unit);
res += unit.p0.Distance(unit.p1);
}
return res;
}
double CMPoint::Length(const Geoid& g, bool& valid) const {
valid = IsDefined();
if (!valid) {
return -1.0;
}
double res = 0.0;
CUPoint unit(true);
int size = GetNoComponents();
for (int i = 0; (valid && (i < size)); i++) {
Get(i, unit);
res += unit.p0.DistanceOrthodrome(unit.p1, g, valid);
}
return res;
}
void CMPoint::AtRegion(const Region *r, CMPoint &result) const {
result.Clear();
if (!IsDefined() || !r->IsDefined()) {
result.SetDefined(false);
return;
}
result.SetDefined(true);
if (IsEmpty() || r->IsEmpty()) {
return;
}
// check for intersection of total MBRs
Rectangle<2u> rMBR = r->BoundingBox();
if (!rMBR.Intersects(BoundingBoxSpatial())) {
return;
}
// iterate through all units
CUPoint unit(true);
std::vector<UPoint> uResultVector;
for (int i = 1; i < GetNoComponents(); i++) {
Get(i, unit);
if (!((UPoint*)&unit)->AtRegion(r, uResultVector)) {
std::cerr << __PRETTY_FUNCTION__ << " WARNING: no result for CUPoint ("
<< i << "): cupoint = " << unit << endl;
continue;
}
for (unsigned int j = 0; j < uResultVector.size(); j++) {
CUPoint cup(uResultVector[j], unit.GetRadius());
result.MergeAdd(cup);
}
}
}
void CMPoint::AtRect(const Rectangle<2>& rect, CMPoint& result) const {
result.Clear();
if (!IsDefined() || !rect.IsDefined()) {
result.SetDefined(false);
return;
}
Rectangle<2u> bbox = BoundingBoxSpatial();
if (!bbox.Intersects(rect)) {
return; // disjoint, return empty
}
if (rect.Contains(bbox)) {
result.CopyFrom(this);
return;
}
// Bounding boxes overlap, check units
CUPoint src(true);
UPoint up(false);
result.StartBulkLoad();
for (int i = 0; i < GetNoComponents(); i++) {
Get(i, src);
((UPoint*)&src)->At(rect, up);
if (up.IsDefined()) {
assert(up.timeInterval.start.GetType() == datetime::instanttype);
assert(up.timeInterval.end.GetType() == datetime::instanttype);
result.Add(CUPoint(up, src.GetRadius()));
}
}
result.EndBulkLoad(false);
}
void CMPoint::GetRadii(MReal& result) const {
result.Clear();
if (!IsDefined()) {
result.SetDefined(false);
}
CUPoint cup(true);
UReal ur(true);
for (int i = 0; i < GetNoComponents(); i++) {
Get(i, cup);
ur.timeInterval = cup.timeInterval;
ur.a = 0.0;
ur.b = 0.0;
ur.c = cup.GetRadius();
ur.r = false;
result.Add(ur);
}
}
/*
4 Type Constructors
4.1 Type Constructor ~rint~
This type constructor implements the carrier set for ~range(int)~.
4.1.1 List Representation
The list representation of a ~rint~ is
---- ( (i1b i1e lc1 rc1) (i2b i2e lc2 rc2) ... (inb ine lcn rcn) )
----
For example:
---- ( (1 5 TRUE FALSE) (6 9 FALSE FALSE) (11 11 TRUE TRUE) )
----
4.1.2 function Describing the Signature of the Type Constructor
*/
ListExpr
RangeIntProperty()
{
ListExpr remarkslist = nl->TextAtom();
nl->AppendText(remarkslist,
"lci means left closed interval, rci respectively right closed interval,"
" e.g. (0 1 TRUE FALSE) means the range [0, 1[");
return (nl->TwoElemList(
nl->FiveElemList(nl->StringAtom("Signature"),
nl->StringAtom("Example Type List"),
nl->StringAtom("List Rep"),
nl->StringAtom("Example List"),
nl->StringAtom("Remarks")),
nl->FiveElemList(nl->StringAtom("-> RANGE"),
nl->StringAtom("(rint) "),
nl->StringAtom("((b1 e1 lci rci) ... (bn en lci rci))"),
nl->StringAtom("((0 1 TRUE FALSE) (2 5 TRUE TRUE))"),
remarkslist)));
}
/*
4.1.3 Kind Checking Function
*/
bool
CheckRangeInt( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, RInt::BasicType() ));
}
/*
4.1.4 Creation of the type constructor ~rint~
*/
TypeConstructor rangeint(
RInt::BasicType(), //name
RangeIntProperty, //property function describing signature
OutRange<CcInt, OutCcInt>,
InRange<CcInt, InCcInt>, //Out and In functions
0, 0, //SaveToList and RestoreFromList functions
CreateRange<CcInt>,DeleteRange<CcInt>, //object creation and deletion
OpenRange<CcInt>, SaveRange<CcInt>, // object open and save
CloseRange<CcInt>, CloneRange<CcInt>, //object close and clone
CastRange<CcInt>, //cast function
SizeOfRange<CcInt>, //sizeof function
CheckRangeInt ); //kind checking function
/*
4.2 Type Constructor ~rreal~
This type constructor implements the carrier set for ~range(real)~.
4.2.1 List Representation
The list representation of a ~rreal~ is
---- ( (r1b r1e lc1 rc1) (r2b r2e lc2 rc2) ... (rnb rne lcn rcn) )
----
For example:
---- ( (1.01 5 TRUE FALSE) (6.37 9.9 FALSE FALSE) (11.93 11.99 TRUE TRUE) )
----
4.2.2 function Describing the Signature of the Type Constructor
*/
ListExpr
RangeRealProperty()
{
ListExpr remarkslist = nl->TextAtom();
nl->AppendText(remarkslist,
"lci means left closed interval, rci respectively right closed interval,"
" e.g. (0.5 1.1 TRUE FALSE) means the range [0.5, 1.1[");
return (nl->TwoElemList(
nl->FiveElemList(nl->StringAtom("Signature"),
nl->StringAtom("Example Type List"),
nl->StringAtom("List Rep"),
nl->StringAtom("Example List"),
nl->StringAtom("Remarks")),
nl->FiveElemList(nl->StringAtom("-> RANGE"),
nl->StringAtom("(rreal) "),
nl->StringAtom("((b1 e1 lci rci) ... (bn en lci rci))"),
nl->StringAtom("((0.5 1.1 TRUE FALSE) (2 5.04 TRUE TRUE))"),
remarkslist)));
}
/*
4.2.3 Kind Checking Function
*/
bool
CheckRangeReal( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, RReal::BasicType() ));
}
/*
4.2.4 Creation of the type constructor ~rreal~
*/
TypeConstructor rangereal(
RReal::BasicType(), //name
RangeRealProperty, //property function describing signature
OutRange<CcReal, OutCcReal>,
InRange<CcReal, InCcReal>, //Out and In functions
0, 0, //SaveToList and RestoreFromList functions
CreateRange<CcReal>,DeleteRange<CcReal>, //object creation and deletion
OpenRange<CcReal>,SaveRange<CcReal>, // object open and save
CloseRange<CcReal>,CloneRange<CcReal>, //object close and clone
CastRange<CcReal>, //cast function
SizeOfRange<CcReal>, //sizeof function
CheckRangeReal ); //kind checking function
/*
4.3 Type Constructor ~periods~
This type constructor implements the carrier set for ~range(instant)~, which is
called ~periods~.
4.3.1 List Representation
The list representation of a ~periods~ is
---- ( (i1b i1e lc1 rc1) (i2b i2e lc2 rc2) ... (inb ine lcn rcn) )
----
For example:
---- ( ( (instant 1.01) (instant 5) TRUE FALSE)
( (instant 6.37) (instant 9.9) FALSE FALSE)
( (instant 11.93) (instant 11.99) TRUE TRUE) )
----
4.3.2 function Describing the Signature of the Type Constructor
*/
ListExpr
PeriodsProperty()
{
ListExpr remarkslist = nl->TextAtom();
nl->AppendText(remarkslist,
"lci means left closed interval, rci respectively right closed interval,"
" e.g. ((instant 0.5) (instant 1.1) TRUE FALSE) means the interval [0.5, 1.1[");
return (nl->TwoElemList(
nl->FourElemList(nl->StringAtom("Signature"),
nl->StringAtom("Example Type List"),
nl->StringAtom("List Rep"),
nl->StringAtom("Example List")),
nl->FourElemList(nl->StringAtom("-> RANGE"),
nl->StringAtom("(periods) "),
nl->StringAtom("( (b1 e1 lci rci) ... (bn en lci rci) )"),
nl->StringAtom("((i1 i2 TRUE FALSE) ...)"))));
}
/*
4.3.3 Kind Checking Function
*/
bool
CheckPeriods( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, Periods::BasicType() ));
}
/*
4.3.4 Creation of the type constructor ~periods~
*/
TypeConstructor periods(
Periods::BasicType(), //name
PeriodsProperty, //property function describing signature
OutRange<Instant, OutDateTime>,
InRange<Instant, InInstant>, //Out and In functions
0, 0, //SaveToList and RestoreFromList functions
CreateRange<Instant>, DeleteRange<Instant>,
//object creation and deletion
OpenRange<Instant>, SaveRange<Instant>, // object open and save
CloseRange<Instant>, CloneRange<Instant>, //object close and clone
CastRange<Instant>, //cast function
SizeOfRange<Instant>, //sizeof function
CheckPeriods ); //kind checking function
/*
4.4 Type Constructor ~ibool~
Type ~ibool~ represents an (instant, value)-pair of booleans.
4.4.1 List Representation
The list representation of an ~ibool~ is
---- ( t bool-value )
----
For example:
---- ( (instant 1.0) FALSE )
----
4.4.2 function Describing the Signature of the Type Constructor
*/
ListExpr
IntimeBoolProperty()
{
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("-> TEMPORAL"),
nl->StringAtom("(ibool) "),
nl->StringAtom("(instant bool-value) "),
nl->StringAtom("((instant 0.5) FALSE)"))));
}
/*
4.4.3 Kind Checking Function
*/
bool
CheckIntimeBool( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, IBool::BasicType() ));
}
/*
4.4.4 Creation of the type constructor ~ibool~
*/
TypeConstructor intimebool(
IBool::BasicType(), //name
IntimeBoolProperty, //property function describing signature
OutIntime<CcBool, OutCcBool>,
InIntime<CcBool, InCcBool>, //Out and In functions
0,
0, //SaveToList and RestoreFromList functions
CreateIntime<CcBool>,
DeleteIntime<CcBool>, //object creation and deletion
OpenAttribute<Intime<CcBool> >,
SaveAttribute<Intime<CcBool> >, // object open and save
CloseIntime<CcBool>,
CloneIntime<CcBool>, //object close and clone
CastIntime<CcBool>, //cast function
SizeOfIntime<CcBool>, //sizeof function
CheckIntimeBool ); //kind checking function
/*
4.4 Type Constructor ~iint~
Type ~iint~ represents an (instant, value)-pair of integers.
4.4.1 List Representation
The list representation of an ~iint~ is
---- ( t int-value )
----
For example:
---- ( (instant 1.0) 5 )
----
4.4.2 function Describing the Signature of the Type Constructor
*/
ListExpr
IntimeIntProperty()
{
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("-> TEMPORAL"),
nl->StringAtom("(iint) "),
nl->StringAtom("(instant int-value) "),
nl->StringAtom("((instant 0.5) 1)"))));
}
/*
4.4.3 Kind Checking Function
*/
bool
CheckIntimeInt( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, IInt::BasicType() ));
}
/*
4.4.4 Creation of the type constructor ~iint~
*/
TypeConstructor intimeint(
IInt::BasicType(), //name
IntimeIntProperty, //property function describing signature
OutIntime<CcInt, OutCcInt>,
InIntime<CcInt, InCcInt>, //Out and In functions
0,
0, //SaveToList and RestoreFromList functions
CreateIntime<CcInt>,
DeleteIntime<CcInt>, //object creation and deletion
OpenAttribute<Intime<CcInt> >,
SaveAttribute<Intime<CcInt> >, // object open and save
CloseIntime<CcInt>,
CloneIntime<CcInt>, //object close and clone
CastIntime<CcInt>, //cast function
SizeOfIntime<CcInt>, //sizeof function
CheckIntimeInt ); //kind checking function
/*
4.5 Type Constructor ~ireal~
Type ~ireal~ represents an (instant, value)-pair of reals.
4.5.1 List Representation
The list representation of an ~ireal~ is
---- ( t real-value )
----
For example:
---- ( (instant 1.0) 5.0 )
----
4.5.2 function Describing the Signature of the Type Constructor
*/
ListExpr
IntimeRealProperty()
{
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("-> TEMPORAL"),
nl->StringAtom("(ireal) "),
nl->StringAtom("(instant real-value)"),
nl->StringAtom("((instant 0.5) 1.0)"))));
}
/*
4.5.3 Kind Checking Function
This function checks whether the type constructor is applied correctly.
*/
bool
CheckIntimeReal( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, IReal::BasicType() ));
}
/*
4.5.4 Creation of the type constructor ~ireal~
*/
TypeConstructor intimereal(
IReal::BasicType(), //name
IntimeRealProperty, //property function describing signature
OutIntime<CcReal, OutCcReal>,
InIntime<CcReal, InCcReal>, //Out and In functions
0,
0, //SaveToList and RestoreFromList functions
CreateIntime<CcReal>,
DeleteIntime<CcReal>, //object creation and deletion
OpenAttribute<Intime<CcReal> >,
SaveAttribute<Intime<CcReal> >, // object open and save
CloseIntime<CcReal>,
CloneIntime<CcReal>, //object close and clone
CastIntime<CcReal>, //cast function
SizeOfIntime<CcReal>, //sizeof function
CheckIntimeReal ); //kind checking function
/*
4.6 Type Constructor ~ipoint~
Type ~ipoint~ represents an (instant, value)-pair of points.
4.6.1 List Representation
The list representation of an ~ipoint~ is
---- ( t point-value )
----
For example:
---- ( (instant 1.0) (5.0 0.0) )
----
4.6.2 function Describing the Signature of the Type Constructor
*/
ListExpr
IntimePointProperty()
{
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("-> TEMPORAL"),
nl->StringAtom("(ipoint) "),
nl->StringAtom("(instant point-value)"),
nl->StringAtom("((instant 0.5) (1.0 2.0))"))));
}
/*
4.6.3 Kind Checking Function
*/
bool
CheckIntimePoint( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, IPoint::BasicType() ));
}
/*
4.6.4 Creation of the type constructor ~ipoint~
*/
TypeConstructor intimepoint(
IPoint::BasicType(), //name
IntimePointProperty, //property function describing signature
OutIntime<Point, OutPoint>,
InIntime<Point, InPoint>, //Out and In functions
0,
0, //SaveToList and RestoreFromList functions
CreateIntime<Point>,
DeleteIntime<Point>, //object creation and deletion
OpenAttribute<Intime<Point> >,
SaveAttribute<Intime<Point> >, // object open and save
CloseIntime<Point>,
CloneIntime<Point>, //object close and clone
CastIntime<Point>, //cast function
SizeOfIntime<Point>, //sizeof function
CheckIntimePoint ); //kind checking function
/*
4.6 Type Constructor ~cipoint~
Type ~cipoint~ represents an (instant, value)-pair of cpoint.
4.6.1 List Representation
The list representation of a ~cipoint~ is
---- ( t cpoint-value )
----
For example:
---- ( (instant 1.0) ((5.0 0.0) 1.9) )
----
4.6.2 function Describing the Signature of the Type Constructor
*/
ListExpr IntimeCPointProperty() {
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("-> TEMPORAL"),
nl->StringAtom("(cipoint) "),
nl->StringAtom("(instant cpoint-value)"),
nl->StringAtom("((instant 0.5) ((1.0 2.0) 1.9))"))));
}
/*
4.6.3 Kind Checking Function
*/
bool CheckIntimeCPoint(ListExpr type, ListExpr& errorInfo) {
return (nl->IsEqual(type, "cipoint"));
}
/*
4.6.4 Creation of the type constructor ~ipoint~
*/
TypeConstructor intimecpoint(
"cipoint", //name
IntimeCPointProperty, //property function describing signature
OutIntime<CPoint, OutCPoint>,
InIntime<CPoint, InCPoint>, //Out and In functions
0,
0, //SaveToList and RestoreFromList functions
CreateIntime<CPoint>,
DeleteIntime<CPoint>, //object creation and deletion
OpenAttribute<Intime<CPoint> >,
SaveAttribute<Intime<CPoint> >, // object open and save
CloseIntime<CPoint>,
CloneIntime<CPoint>, //object close and clone
CastIntime<CPoint>, //cast function
SizeOfIntime<CPoint>, //sizeof function
CheckIntimeCPoint); //kind checking function
/*
4.7 Type Constructor ~ubool~
Type ~ubool~ represents an (tinterval, boolvalue)-pair.
4.7.1 List Representation
The list representation of an ~ubool~ is
---- ( timeinterval bool-value )
----
For example:
---- ( ((instant 6.37) (instant 9.9) TRUE FALSE) TRUE )
----
4.7.2 function Describing the Signature of the Type Constructor
*/
ListExpr
UBoolProperty()
{
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("-> UNIT"),
nl->StringAtom("(ubool) "),
nl->StringAtom("(timeInterval bool) "),
nl->StringAtom("((i1 i2 FALSE FALSE) TRUE)"))));
}
/*
4.7.3 Kind Checking Function
*/
bool
CheckUBool( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, UBool::BasicType() ));
}
/*
4.7.4 Creation of the type constructor ~ubool~
*/
TypeConstructor unitbool(
UBool::BasicType(), //name
UBoolProperty, //property function describing signature
OutConstTemporalUnit<CcBool, OutCcBool>,
InConstTemporalUnit<CcBool, InCcBool>, //Out and In functions
0, 0, //SaveToList and RestoreFromList functions
CreateConstTemporalUnit<CcBool>,
DeleteConstTemporalUnit<CcBool>, //object creation and deletion
OpenAttribute<UBool>,
SaveAttribute<UBool>, // object open and save
CloseConstTemporalUnit<CcBool>,
CloneConstTemporalUnit<CcBool>, //object close and clone
CastConstTemporalUnit<CcBool>, //cast function
SizeOfConstTemporalUnit<CcBool>, //sizeof function
CheckUBool ); //kind checking function
/*
4.7 Type Constructor ~uint~
Type ~uint~ represents an (tinterval, intvalue)-pair.
4.7.1 List Representation
The list representation of an ~uint~ is
---- ( timeinterval int-value )
----
For example:
---- ( ( (instant 6.37) (instant 9.9) TRUE FALSE) 5 )
----
4.7.2 function Describing the Signature of the Type Constructor
*/
ListExpr
UIntProperty()
{
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("-> UNIT"),
nl->StringAtom("(uint) "),
nl->StringAtom("(timeInterval int) "),
nl->StringAtom("((i1 i2 FALSE FALSE) 1)"))));
}
/*
4.7.3 Kind Checking Function
*/
bool
CheckUInt( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, UInt::BasicType() ));
}
/*
4.7.4 Creation of the type constructor ~uint~
*/
TypeConstructor unitint(
UInt::BasicType(), //name
UIntProperty, //property function describing signature
OutConstTemporalUnit<CcInt, OutCcInt>,
InConstTemporalUnit<CcInt, InCcInt>, //Out and In functions
0, 0,//SaveToList and RestoreFromList functions
CreateConstTemporalUnit<CcInt>,
DeleteConstTemporalUnit<CcInt>, //object creation and deletion
OpenAttribute<UInt>,
SaveAttribute<UInt>, // object open and save
CloseConstTemporalUnit<CcInt>,
CloneConstTemporalUnit<CcInt>, //object close and clone
CastConstTemporalUnit<CcInt>, //cast function
SizeOfConstTemporalUnit<CcInt>, //sizeof function
CheckUInt ); //kind checking function
/*
4.8 Type Constructor ~ureal~
Type ~ureal~ represents an (tinterval, (a, b, c, r))-pair, where
a, b, c are real numbers, r is a boolean flag indicating which
function to use.
11.1 List Representation
The list representation of an ~ureal~ is
---- ( timeinterval (a b c r) )
----
For example:
---- ( ( (instant 6.37) (instant 9.9) TRUE FALSE) (1.0 2.3 4.1 TRUE) )
----
4.8.2 Function Describing the Signature of the Type Constructor
*/
ListExpr
URealProperty()
{
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("-> UNIT"),
nl->StringAtom("("+UReal::BasicType()+") "),
nl->StringAtom("( timeInterval (real1 real2 real3 bool)) "),
nl->StringAtom("((i1 i2 TRUE FALSE) (1.0 2.2 2.5 TRUE))"))));
}
/*
4.8.3 Kind Checking Function
*/
bool
CheckUReal( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, UReal::BasicType() ));
}
/*
4.8.4 ~Out~-function
*/
ListExpr OutUReal( ListExpr typeInfo, Word value )
{
UReal* ureal = (UReal*)(value.addr);
if ( !ureal->IsDefined() )
return (nl->SymbolAtom(Symbol::UNDEFINED()));
else
{
ListExpr timeintervalList = nl->FourElemList(
OutDateTime( nl->TheEmptyList(),
SetWord(&ureal->timeInterval.start) ),
OutDateTime( nl->TheEmptyList(),
SetWord(&ureal->timeInterval.end) ),
nl->BoolAtom( ureal->timeInterval.lc ),
nl->BoolAtom( ureal->timeInterval.rc));
ListExpr realfunList = nl->FourElemList(
nl->RealAtom( ureal->a),
nl->RealAtom( ureal->b),
nl->RealAtom( ureal->c ),
nl->BoolAtom( ureal->r));
return nl->TwoElemList(timeintervalList, realfunList );
}
}
/*
4.8.5 ~In~-function
The Nested list form is like this:
----
( ( 6.37 9.9 TRUE FALSE) (1.0 2.3 4.1 TRUE) )
or: undef
----
*/
Word InUReal( const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr& errorInfo, bool& correct )
{
std::string errmsg;
correct = true;
if ( nl->ListLength( instance ) == 2 )
{
ListExpr first = nl->First( instance );
if( nl->ListLength( first ) == 4 &&
nl->IsAtom( nl->Third( first ) ) &&
nl->AtomType( nl->Third( first ) ) == BoolType &&
nl->IsAtom( nl->Fourth( first ) ) &&
nl->AtomType( nl->Fourth( first ) ) == BoolType )
{
Instant *start = (Instant *)InInstant( nl->TheEmptyList(),
nl->First( first ),
errorPos, errorInfo, correct ).addr;
if( !correct || !start->IsDefined() )
{
errmsg = "InUReal(): Error in first instant (Must be defined!).";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
delete start;
return SetWord( Address(0) );
}
Instant *end = (Instant *)InInstant( nl->TheEmptyList(),
nl->Second( first ),
errorPos, errorInfo, correct ).addr;
if( !correct || !end->IsDefined() )
{
errmsg = "InUReal(): Error in second instant (Must be defined!).";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
delete start;
delete end;
return SetWord( Address(0) );
}
Interval<Instant> tinterval( *start, *end,
nl->BoolValue( nl->Third( first ) ),
nl->BoolValue( nl->Fourth( first ) ) );
delete start;
delete end;
correct = tinterval.IsValid();
if ( !correct )
{
errmsg = "InUReal(): Non valid time interval.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
return SetWord( Address(0) );
}
ListExpr second = nl->Second( instance );
if( nl->ListLength( second ) == 4 &&
nl->IsAtom( nl->First( second ) ) &&
nl->AtomType( nl->First( second ) ) == RealType &&
nl->IsAtom( nl->Second( second ) ) &&
nl->AtomType( nl->Second( second ) ) == RealType &&
nl->IsAtom( nl->Third( second ) ) &&
nl->AtomType( nl->Third( second ) ) == RealType &&
nl->IsAtom( nl->Fourth( second ) ) &&
nl->AtomType( nl->Fourth( second ) ) == BoolType )
{
UReal *ureal =
new UReal( tinterval,
nl->RealValue( nl->First( second ) ),
nl->RealValue( nl->Second( second ) ),
nl->RealValue( nl->Third( second ) ),
nl->BoolValue( nl->Fourth( second ) ) );
if( ureal->IsValid() )
{
correct = true;
return SetWord( ureal );
}
delete ureal;
}
}
}
else if ( listutils::isSymbolUndefined(instance) )
{
UReal *ureal = new UReal();
ureal->SetDefined(false);
ureal->timeInterval=
Interval<DateTime>(DateTime(instanttype),
DateTime(instanttype),true,true);
correct = ureal->timeInterval.IsValid();
if ( correct )
return (SetWord( ureal ));
}
errmsg = "InUReal(): Non valid representation.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
correct = false;
return SetWord( Address(0) );
}
/*
4.8.6 ~Create~-function
*/
Word CreateUReal( const ListExpr typeInfo )
{
return (SetWord( new UReal(false) ));
}
/*
4.8.7 ~Delete~-function
*/
void DeleteUReal( const ListExpr typeInfo, Word& w )
{
delete (UReal *)w.addr;
w.addr = 0;
}
/*
4.8.8 ~Close~-function
*/
void CloseUReal( const ListExpr typeInfo, Word& w )
{
delete (UReal *)w.addr;
w.addr = 0;
}
/*
4.8.9 ~Clone~-function
*/
Word CloneUReal( const ListExpr typeInfo, const Word& w )
{
UReal *ureal = (UReal *)w.addr;
return SetWord( new UReal( *ureal ) );
}
/*
4.8.10 ~Sizeof~-function
*/
int SizeOfUReal()
{
return sizeof(UReal);
}
/*
4.8.11 ~Cast~-function
*/
void* CastUReal(void* addr)
{
return new (addr) UReal;
}
/*
4.8.12 Creation of the type constructor ~ureal~
*/
TypeConstructor unitreal(
UReal::BasicType(), //name
URealProperty, //property function describing signature
OutUReal, InUReal, //Out and In functions
0, 0, //SaveToList and RestoreFromList functions
CreateUReal,
DeleteUReal, //object creation and deletion
OpenAttribute<UReal>,
SaveAttribute<UReal>, // object open and save
CloseUReal, CloneUReal, //object close and clone
CastUReal, //cast function
SizeOfUReal, //sizeof function
CheckUReal ); //kind checking function
/*
4.9 Type Constructor ~upoint~
Type ~upoint~ represents an (tinterval, (x0, y0, x1, y1))-pair.
4.9.1 List Representation
The list representation of an ~upoint~ is
---- ( timeinterval (x0 yo x1 y1) )
----
For example:
---- ( ( (instant 6.37) (instant 9.9) TRUE FALSE) (1.0 2.3 4.1 2.1) )
----
4.9.2 function Describing the Signature of the Type Constructor
*/
ListExpr
UPointProperty()
{
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("-> UNIT"),
nl->StringAtom("("+UPoint::BasicType()+") "),
nl->TextAtom("( timeInterval (real_x0 real_y0 real_x1 real_y1) ) "),
nl->StringAtom("((i1 i2 TRUE FALSE) (1.0 2.2 2.5 2.1))"))));
}
/*
4.9.3 Kind Checking Function
*/
bool
CheckUPoint( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, UPoint::BasicType() ));
}
/*
4.9.4 ~Out~-function
*/
ListExpr OutUPoint( ListExpr typeInfo, Word value )
{
UPoint* upoint = (UPoint*)(value.addr);
if( !(((UPoint*)value.addr)->IsDefined()) )
return (nl->SymbolAtom(Symbol::UNDEFINED()));
else
{
ListExpr timeintervalList = nl->FourElemList(
OutDateTime( nl->TheEmptyList(),
SetWord(&upoint->timeInterval.start) ),
OutDateTime( nl->TheEmptyList(), SetWord(&upoint->timeInterval.end) ),
nl->BoolAtom( upoint->timeInterval.lc ),
nl->BoolAtom( upoint->timeInterval.rc));
ListExpr pointsList = nl->FourElemList(
nl->RealAtom( upoint->p0.GetX() ),
nl->RealAtom( upoint->p0.GetY() ),
nl->RealAtom( upoint->p1.GetX() ),
nl->RealAtom( upoint->p1.GetY() ));
return nl->TwoElemList( timeintervalList, pointsList );
}
}
/*
4.9.5 ~In~-function
The Nested list form is like this:( ( 6.37 9.9 TRUE FALSE) (1.0 2.3 4.1 2.1) )
*/
Word InUPoint( const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr& errorInfo, bool& correct )
{
std::string errmsg;
if ( nl->ListLength( instance ) == 2 )
{
ListExpr first = nl->First( instance );
if( nl->ListLength( first ) == 4 &&
nl->IsAtom( nl->Third( first ) ) &&
nl->AtomType( nl->Third( first ) ) == BoolType &&
nl->IsAtom( nl->Fourth( first ) ) &&
nl->AtomType( nl->Fourth( first ) ) == BoolType )
{
correct = true;
Instant *start = (Instant *)InInstant( nl->TheEmptyList(),
nl->First( first ), errorPos, errorInfo, correct ).addr;
if( !correct || start == NULL || !start->IsDefined())
{
// "InUPoint(): Error in first instant (Must be defined!).";
errmsg = "InUPoint(): first instant must be defined!.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
delete start;
return SetWord( Address(0) );
}
Instant *end = (Instant *)InInstant( nl->TheEmptyList(),
nl->Second( first ),
errorPos, errorInfo, correct ).addr;
if( !correct || end == NULL || !end->IsDefined() )
{
// errmsg = "InUPoint(): Error in second instant (Must be defined!).";
errmsg = "InUPoint(): second instant must be defined!.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
delete start;
delete end;
return SetWord( Address(0) );
}
Interval<Instant> tinterval( *start, *end,
nl->BoolValue( nl->Third( first ) ),
nl->BoolValue( nl->Fourth( first ) ) );
delete start;
delete end;
correct = tinterval.IsValid();
if (!correct)
{
errmsg = "InUPoint(): Non valid time interval.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
return SetWord( Address(0) );
}
ListExpr second = nl->Second( instance );
if( nl->ListLength( second ) == 4 &&
nl->IsAtom( nl->First( second ) ) &&
nl->AtomType( nl->First( second ) ) == RealType &&
nl->IsAtom( nl->Second( second ) ) &&
nl->AtomType( nl->Second( second ) ) == RealType &&
nl->IsAtom( nl->Third( second ) ) &&
nl->AtomType( nl->Third( second ) ) == RealType &&
nl->IsAtom( nl->Fourth( second ) ) &&
nl->AtomType( nl->Fourth( second ) ) == RealType )
{
UPoint *upoint = new UPoint( tinterval,
nl->RealValue( nl->First( second ) ),
nl->RealValue( nl->Second( second ) ),
nl->RealValue( nl->Third( second ) ),
nl->RealValue( nl->Fourth( second ) ) );
correct = upoint->IsValid();
if( correct )
return SetWord( upoint );
errmsg = "InUPoint(): Error in start/end point.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
delete upoint;
}
}
}
else if ( listutils::isSymbolUndefined(instance) )
{
UPoint *upoint = new UPoint(true);
upoint->SetDefined(false);
upoint->timeInterval=
Interval<DateTime>(DateTime(instanttype),
DateTime(instanttype),true,true);
correct = upoint->timeInterval.IsValid();
if ( correct )
return (SetWord( upoint ));
}
errmsg = "InUPoint(): Error in representation.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
correct = false;
return SetWord( Address(0) );
}
/*
4.9.6 ~Create~-function
*/
Word CreateUPoint( const ListExpr typeInfo )
{
return (SetWord( new UPoint(false) ));
}
/*
4.9.7 ~Delete~-function
*/
void DeleteUPoint( const ListExpr typeInfo, Word& w )
{
delete (UPoint *)w.addr;
w.addr = 0;
}
/*
4.9.8 ~Close~-function
*/
void CloseUPoint( const ListExpr typeInfo, Word& w )
{
delete (UPoint *)w.addr;
w.addr = 0;
}
/*
4.9.9 ~Clone~-function
*/
Word CloneUPoint( const ListExpr typeInfo, const Word& w )
{
UPoint *upoint = (UPoint *)w.addr;
return SetWord( new UPoint( *upoint ) );
}
/*
4.9.10 ~Sizeof~-function
*/
int SizeOfUPoint()
{
return sizeof(UPoint);
}
/*
4.9.11 ~Cast~-function
*/
void* CastUPoint(void* addr)
{
return new (addr) UPoint;
}
/*
4.9.12 Creation of the type constructor ~upoint~
*/
TypeConstructor unitpoint(
UPoint::BasicType(), //name
UPointProperty, //property function describing signature
OutUPoint, InUPoint, //Out and In functions
0, 0, //SaveToList and RestoreFromList functions
CreateUPoint,
DeleteUPoint, //object creation and deletion
OpenAttribute<UPoint>,
SaveAttribute<UPoint>, // object open and save
CloseUPoint, CloneUPoint, //object close and clone
CastUPoint, //cast function
SizeOfUPoint, //sizeof function
CheckUPoint ); //kind checking function
/*
4.9 Type Constructor ~cupoint~
Type ~cupoint~ represents an (tinterval, (x0, y0, x1, y1), radius)-triple.
4.9.1 List Representation
The list representation of a ~cupoint~ is
---- ( timeinterval (x0 y0 x1 y1) r )
----
For example:
---- ( ( (instant 6.37) (instant 9.9) TRUE FALSE) (1.0 2.3 4.1 2.1) 1.9)
----
4.9.2 function Describing the Signature of the Type Constructor
*/
ListExpr CUPointProperty() {
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("-> UNIT"),
nl->StringAtom("("+CUPoint::BasicType()+") "),
nl->TextAtom("( timeInterval (real_x0 real_y0 real_x1 real_y1) radius) "),
nl->StringAtom("((i1 i2 TRUE FALSE) (1.0 2.2 2.5 2.1) 1.9)"))));
}
/*
4.9.3 Kind Checking Function
*/
bool CheckCUPoint(ListExpr type, ListExpr& errorInfo) {
return (nl->IsEqual(type, CUPoint::BasicType()));
}
/*
4.9.4 ~Out~-function
*/
ListExpr OutCUPoint(ListExpr typeInfo, Word value) {
CUPoint* cupoint = (CUPoint*)(value.addr);
if (!(((CUPoint*)value.addr)->IsDefined())) {
return (nl->SymbolAtom(Symbol::UNDEFINED()));
}
else {
ListExpr timeintervalList = nl->FourElemList(
OutDateTime(nl->TheEmptyList(), SetWord(&cupoint->timeInterval.start)),
OutDateTime(nl->TheEmptyList(), SetWord(&cupoint->timeInterval.end)),
nl->BoolAtom(cupoint->timeInterval.lc),
nl->BoolAtom(cupoint->timeInterval.rc));
ListExpr pointsList = nl->FourElemList(
nl->RealAtom(cupoint->p0.GetX() ), nl->RealAtom(cupoint->p0.GetY()),
nl->RealAtom(cupoint->p1.GetX() ), nl->RealAtom(cupoint->p1.GetY()));
return nl->ThreeElemList(timeintervalList, pointsList,
nl->RealAtom(cupoint->GetRadius()));
}
}
/*
4.9.5 ~In~-function
The Nested list form is like this: ((6.37 9.9 TRUE FALSE) (1.0 2.3 4.1 2.1) 1.9)
*/
Word InCUPoint(const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr& errorInfo, bool& correct) {
std::string errmsg;
if (nl->ListLength(instance) == 3) {
ListExpr first = nl->First(instance);
if (nl->ListLength(first) == 4 && nl->IsAtom(nl->Third(first))
&& nl->AtomType(nl->Third(first)) == BoolType
&& nl->IsAtom(nl->Fourth(first))
&& nl->AtomType(nl->Fourth(first)) == BoolType) {
correct = true;
Instant *start = (Instant*)InInstant(nl->TheEmptyList(), nl->First(first),
errorPos, errorInfo, correct).addr;
if (!correct || start == NULL || !start->IsDefined()) {
errmsg = "InCUPoint(): first instant must be defined!.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
delete start;
return SetWord(Address(0));
}
Instant *end = (Instant*)InInstant(nl->TheEmptyList(), nl->Second(first),
errorPos, errorInfo, correct).addr;
if (!correct || end == NULL || !end->IsDefined()) {
errmsg = "InUPoint(): second instant must be defined!.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
delete start;
delete end;
return SetWord(Address(0));
}
Interval<Instant> tinterval(*start, *end, nl->BoolValue(nl->Third(first)),
nl->BoolValue(nl->Fourth(first)));
delete start;
delete end;
correct = tinterval.IsValid();
if (!correct) {
errmsg = "InUPoint(): invalid time interval.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
return SetWord(Address(0));
}
ListExpr second = nl->Second(instance);
if (nl->ListLength(second) == 4) {
if (nl->IsAtom(nl->Third(instance))
&& nl->AtomType(nl->First(second)) == RealType
&& nl->IsAtom(nl->First(second))
&& nl->AtomType(nl->First(second)) == RealType
&& nl->IsAtom( nl->Second(second))
&& nl->AtomType(nl->Second(second)) == RealType
&& nl->IsAtom(nl->Third(second))
&& nl->AtomType(nl->Third(second)) == RealType
&& nl->IsAtom(nl->Fourth(second))
&& nl->AtomType(nl->Fourth(second)) == RealType) {
CUPoint *cupoint = new CUPoint(tinterval,
nl->RealValue(nl->First(second)),
nl->RealValue(nl->Second(second)),
nl->RealValue(nl->Third(second)),
nl->RealValue(nl->Fourth(second)),
nl->RealValue(nl->Third(instance)));
correct = cupoint->IsValid();
if (correct) {
return SetWord(cupoint);
}
errmsg = "InUPoint(): Error in start/end point.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
delete cupoint;
}
}
}
}
else if (listutils::isSymbolUndefined(instance)) {
CUPoint *cupoint = new CUPoint(true);
cupoint->SetDefined(false);
cupoint->timeInterval= Interval<DateTime>(DateTime(instanttype),
DateTime(instanttype),true,true);
correct = cupoint->timeInterval.IsValid();
if (correct) {
return (SetWord(cupoint));
}
}
errmsg = "InCUPoint(): Error in representation.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
correct = false;
return SetWord(Address(0));
}
/*
4.9.6 ~Create~-function
*/
Word CreateCUPoint(const ListExpr typeInfo) {
return (SetWord(new CUPoint(false)));
}
/*
4.9.7 ~Delete~-function
*/
void DeleteCUPoint(const ListExpr typeInfo, Word& w) {
delete (CUPoint*)w.addr;
w.addr = 0;
}
/*
4.9.8 ~Close~-function
*/
void CloseCUPoint(const ListExpr typeInfo, Word& w) {
delete (CUPoint*)w.addr;
w.addr = 0;
}
/*
4.9.9 ~Clone~-function
*/
Word CloneCUPoint(const ListExpr typeInfo, const Word& w) {
CUPoint *cupoint = (CUPoint*)w.addr;
return SetWord(new CUPoint(*cupoint));
}
/*
4.9.10 ~Sizeof~-function
*/
int SizeOfCUPoint() {
return sizeof(CUPoint);
}
/*
4.9.11 ~Cast~-function
*/
void* CastCUPoint(void* addr) {
return new (addr)CUPoint;
}
/*
4.9.12 Creation of the type constructor ~cupoint~
*/
TypeConstructor cupointTC (
CUPoint::BasicType(), //name
CUPointProperty, //property function describing signature
OutCUPoint, InCUPoint, //Out and In functions
0, 0, //SaveToList and RestoreFromList functions
CreateCUPoint,
DeleteCUPoint, //object creation and deletion
OpenAttribute<CUPoint>,
SaveAttribute<CUPoint>, // object open and save
CloseCUPoint, CloneCUPoint, //object close and clone
CastCUPoint, //cast function
SizeOfCUPoint, //sizeof function
CheckCUPoint ); //kind checking function
/*
4.9.3 Kind Checking Function
*/
bool CheckCUPointRegion(ListExpr type, ListExpr& errorInfo) {
return (nl->IsEqual(type, CUPoint::BasicType() + "region"));
}
/*
4.9.12 Creation of the type constructor ~cupointregion~
*/
TypeConstructor cupointregionTC (
CUPoint::BasicType() + "region", //name
CUPointProperty, //property function describing signature
OutCUPoint, InCUPoint, //Out and In functions
0, 0, //SaveToList and RestoreFromList functions
CreateCUPoint,
DeleteCUPoint, //object creation and deletion
OpenAttribute<CUPoint>,
SaveAttribute<CUPoint>, // object open and save
CloseCUPoint, CloneCUPoint, //object close and clone
CastCUPoint, //cast function
SizeOfCUPoint, //sizeof function
CheckCUPointRegion ); //kind checking function
/*
4.10 Type Constructor ~mbool~
Type ~mbool~ represents a moving boolean.
4.10.1 List Representation
The list representation of a ~mbool~ is
---- ( u1 ... un )
----
,where u1, ..., un are units of type ~ubool~.
For example:
---- (
( (instant 6.37) (instant 9.9) TRUE FALSE) TRUE )
( (instant 11.4) (instant 13.9) FALSE FALSE) FALSE )
)
----
4.10.2 function Describing the Signature of the Type Constructor
*/
ListExpr
MBoolProperty()
{
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("-> MAPPING"),
nl->StringAtom("(mbool) "),
nl->StringAtom("( u1 ... un)"),
nl->StringAtom("(((i1 i2 TRUE TRUE) TRUE) ...)"))));
}
/*
4.10.3 Kind Checking Function
This function checks whether the type constructor is applied correctly.
*/
bool
CheckMBool( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, MBool::BasicType() ));
}
/*
4.10.4 Creation of the type constructor ~mbool~
*/
TypeConstructor movingbool(
MBool::BasicType(), //name
MBoolProperty, //property function describing signature
OutMapping<MBool, UBool, OutConstTemporalUnit<CcBool, OutCcBool> >,
InMapping<MBool, UBool, InConstTemporalUnit<CcBool, InCcBool> >,
//Out and In functions
0,
0, //SaveToList and RestoreFromList functions
CreateMapping<MBool>,
DeleteMapping<MBool>, //object creation and deletion
OpenAttribute<MBool>,
SaveAttribute<MBool>, // object open and save
CloseMapping<MBool>,
CloneMapping<MBool>, //object close and clone
CastMapping<MBool>, //cast function
SizeOfMapping<MBool>, //sizeof function
CheckMBool ); //kind checking function
/*
4.10 Type Constructor ~mint~
Type ~mint~ represents a moving integer.
4.10.1 List Representation
The list representation of a ~mint~ is
---- ( u1 ... un )
----
,where u1, ..., un are units of type ~uint~.
For example:
---- (
( (instant 6.37) (instant 9.9) TRUE FALSE) 1 )
( (instant 11.4) (instant 13.9) FALSE FALSE) 4 )
)
----
4.10.2 function Describing the Signature of the Type Constructor
*/
ListExpr
MIntProperty()
{
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("-> MAPPING"),
nl->StringAtom("(mint) "),
nl->StringAtom("( u1 ... un)"),
nl->StringAtom("(((i1 i2 TRUE TRUE) 1) ...)"))));
}
/*
4.10.3 Kind Checking Function
This function checks whether the type constructor is applied correctly.
*/
bool
CheckMInt( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, MInt::BasicType() ));
}
/*
4.10.4 Creation of the type constructor ~mint~
*/
TypeConstructor movingint(
MInt::BasicType(), //name
MIntProperty, //property function describing signature
OutMapping<MInt, UInt, OutConstTemporalUnit<CcInt, OutCcInt> >,
InMapping<MInt, UInt, InConstTemporalUnit<CcInt, InCcInt> >,
//Out and In functions
0,
0, //SaveToList and RestoreFromList functions
CreateMapping<MInt>,
DeleteMapping<MInt>, //object creation and deletion
OpenAttribute<MInt>,
SaveAttribute<MInt>, // object open and save
CloseMapping<MInt>,
CloneMapping<MInt>, //object close and clone
CastMapping<MInt>, //cast function
SizeOfMapping<MInt>, //sizeof function
CheckMInt ); //kind checking function
/*
4.11 Type Constructor ~mreal~
Type ~mreal~ represents a moving real.
4.11.1 List Representation
The list representation of a ~mreal~ is
---- ( u1 ... un )
----
,where u1, ..., un are units of type ~ureal~.
For example:
---- (
( (instant 6.37) (instant 9.9) TRUE FALSE) (1.0 2.3 4.1 TRUE) )
( (instant 11.4) (instant 13.9) FALSE FALSE) (1.0 2.3 4.1 FALSE) )
)
----
4.11.2 function Describing the Signature of the Type Constructor
*/
ListExpr
MRealProperty()
{
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("-> MAPPING"),
nl->StringAtom("(mreal) "),
nl->StringAtom("( u1 ... un) "),
nl->StringAtom("(((i1 i2 TRUE FALSE) (1.0 2.2 2.5 FALSE)) ...)"))));
}
/*
4.11.3 Kind Checking Function
*/
bool
CheckMReal( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, MReal::BasicType() ));
}
/*
4.11.4 Creation of the type constructor ~mreal~
*/
TypeConstructor movingreal(
MReal::BasicType(), //name
MRealProperty, //property function describing signature
OutMapping<MReal, UReal, OutUReal>,
InMapping<MReal, UReal, InUReal>, //Out and In functions
0,
0, //SaveToList and RestoreFromList functions
CreateMapping<MReal>,
DeleteMapping<MReal>, //object creation and deletion
OpenAttribute<MReal>,
SaveAttribute<MReal>, // object open and save
CloseMapping<MReal>,
CloneMapping<MReal>, //object close and clone
CastMapping<MReal>, //cast function
SizeOfMapping<MReal>, //sizeof function
CheckMReal ); //kind checking function
/*
4.12 Type Constructor ~mpoint~
Type ~mpoint~ represents a moving point.
4.12.1 List Representation
The list representation of a ~mpoint~ is
---- ( u1 ... un )
----
,where u1, ..., un are units of type ~upoint~.
For example:
---- (
( (instant 6.37) (instant 9.9) TRUE FALSE) (1.0 2.3 4.1 2.1) )
( (instant 11.4) (instant 13.9) FALSE FALSE) (4.1 2.1 8.9 4.3) )
)
----
4.12.2 function Describing the Signature of the Type Constructor
*/
ListExpr
MPointProperty()
{
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("-> MAPPING"),
nl->StringAtom("(mpoint) "),
nl->StringAtom("( u1 ... un ) "),
nl->StringAtom("(((i1 i2 TRUE FALSE) (1.0 2.2 2.5 2.1)) ...)"))));
}
/*
4.12.3 Kind Checking Function
*/
bool
CheckMPoint( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, MPoint::BasicType() ));
}
/*
4.12.4 Creation of the type constructor ~mpoint~
*/
TypeConstructor movingpoint(
MPoint::BasicType(), //name
MPointProperty, //property function describing signature
OutMapping<MPoint, UPoint, OutUPoint>,
InMapping<MPoint, UPoint, InUPoint>,//Out and In functions
0,
0, //SaveToList and RestoreFromList functions
CreateMapping<MPoint>,
DeleteMapping<MPoint>, //object creation and deletion
OpenAttribute<MPoint>,
SaveAttribute<MPoint>, // object open and save
CloseMapping<MPoint>,
CloneMapping<MPoint>, //object close and clone
CastMapping<MPoint>, //cast function
SizeOfMapping<MPoint>, //sizeof function
CheckMPoint ); //kind checking function
/*
4.12 Type Constructor ~cmpoint~
Type ~cmpoint~ represents a moving cpoint.
4.12.1 List Representation
The list representation of a ~cmpoint~ is
---- ( u1 ... un )
----
,where u1, ..., un are units of type ~cupoint~.
For example:
---- (
( (instant 6.37) (instant 9.9) TRUE FALSE) (1.0 2.3 4.1 2.1) 1.9)
( (instant 11.4) (instant 13.9) FALSE FALSE) (4.1 2.1 8.9 4.3) -0.2)
)
----
4.12.2 function Describing the Signature of the Type Constructor
*/
ListExpr CMPointProperty() {
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("-> MAPPING"),
nl->StringAtom("(cmpoint) "),
nl->StringAtom("( u1 ... un ) "),
nl->StringAtom("(((i1 i2 TRUE FALSE) (1 2 5 6) -0.9) ...)")));
}
/*
4.12.3 Kind Checking Function
*/
bool CheckCMPoint(ListExpr type, ListExpr& errorInfo) {
return (nl->IsEqual(type, CMPoint::BasicType()));
}
ListExpr OutCMPoint(ListExpr typeInfo, Word value) {
CMPoint* m = (CMPoint*)(value.addr);
if(! m->IsDefined()){
return nl->SymbolAtom(Symbol::UNDEFINED());
} else
if( m->IsEmpty() )
return (nl->TheEmptyList());
else
{
assert( m->IsOrdered() );
ListExpr l = nl->TheEmptyList();
ListExpr lastElem = nl->TheEmptyList();
ListExpr unitList;
for( int i = 0; i < m->GetNoComponents(); i++ )
{
CUPoint unit;
m->Get( i, unit );
unitList = OutCUPoint( nl->TheEmptyList(), SetWord(&unit) );
if( l == nl->TheEmptyList() )
{
l = nl->Cons( unitList, nl->TheEmptyList() );
lastElem = l;
}
else
lastElem = nl->Append( lastElem, unitList );
}
std::stringstream strstr;
m->BoundingBox().Print(strstr);
return nl->TwoElemList(nl->TextAtom(strstr.str()), l);
}
}
/*
4.12.4 Creation of the type constructor ~cmpoint~
*/
TypeConstructor cmpointTC(
CMPoint::BasicType(), //name
CMPointProperty, //property function describing signature
// OutCMPoint,
OutMapping<CMPoint, CUPoint, OutCUPoint>,
InMapping<CMPoint, CUPoint, InCUPoint>,//Out and In functions
0,
0, //SaveToList and RestoreFromList functions
CreateMapping<CMPoint>,
DeleteMapping<CMPoint>, //object creation and deletion
OpenAttribute<CMPoint>,
SaveAttribute<CMPoint>, // object open and save
CloseMapping<CMPoint>,
CloneMapping<CMPoint>, //object close and clone
CastMapping<CMPoint>, //cast function
SizeOfMapping<CMPoint>, //sizeof function
CheckCMPoint); //kind checking function
/*
4.12.3 Kind Checking Function
*/
bool CheckCMPointRegion(ListExpr type, ListExpr& errorInfo) {
return (nl->IsEqual(type, CMPoint::BasicType() + "region"));
}
/*
4.12.4 Creation of the type constructor ~cmpointregion~
*/
TypeConstructor cmpointregionTC(
CMPoint::BasicType() + "region", //name
CMPointProperty, //property function describing signature
OutMapping<CMPoint, CUPoint, OutCUPoint>,
InMapping<CMPoint, CUPoint, InCUPoint>,//Out and In functions
0,
0, //SaveToList and RestoreFromList functions
CreateMapping<CMPoint>,
DeleteMapping<CMPoint>, //object creation and deletion
OpenAttribute<CMPoint>,
SaveAttribute<CMPoint>, // object open and save
CloseMapping<CMPoint>,
CloneMapping<CMPoint>, //object close and clone
CastMapping<CMPoint>, //cast function
SizeOfMapping<CMPoint>, //sizeof function
CheckCMPointRegion); //kind checking function
/*
4.12.5 Creation of the type constructore ~cellgrid2d~
*/
GenTC<CellGrid2D> cellgrid2d;
/*
4.12.6 Creation of the type constructore ~cellgrid3d~
*/
GenTC<CellGrid<3> > cellgrid3d;
/*
16 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.
16.1 Type mapping function
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.
16.1.1 Type mapping function ~TemporalTypeMapBool~
Is used for the ~isempty~ operator.
*/
ListExpr
TemporalTypeMapBool( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
ListExpr arg1 = nl->First( args );
if( nl->IsEqual( arg1, Instant::BasicType() ) ||
nl->IsEqual( arg1, RInt::BasicType() ) ||
nl->IsEqual( arg1, RReal::BasicType() ) ||
nl->IsEqual( arg1, Periods::BasicType() ) ||
nl->IsEqual( arg1, UBool::BasicType() ) ||
nl->IsEqual( arg1, UInt::BasicType() ) ||
nl->IsEqual( arg1, UReal::BasicType() ) ||
nl->IsEqual( arg1, UPoint::BasicType() ) ||
// nl->IsEqual( arg1, MBool::BasicType() ) ||
// nl->IsEqual( arg1, MInt::BasicType() ) ||
// nl->IsEqual( arg1, MReal::BasicType() ) ||
// nl->IsEqual( arg1, MPoint::BasicType() ) ||
nl->IsEqual( arg1, IBool::BasicType() ) ||
nl->IsEqual( arg1, IInt::BasicType() ) ||
nl->IsEqual( arg1, IReal::BasicType() ) ||
nl->IsEqual( arg1, IPoint::BasicType() ))
return nl->SymbolAtom( CcBool::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.1 Type mapping function ~TemporalTemporalTypeMapBool~
Is used for the ~=~, and ~\#~ operators.
*/
ListExpr
TemporalTemporalTypeMapBool( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( (nl->IsEqual( arg1, Instant::BasicType() )
&& nl->IsEqual( arg2, Instant::BasicType() )) ||
(nl->IsEqual( arg1, RInt::BasicType() )
&& nl->IsEqual( arg2, RInt::BasicType() )) ||
(nl->IsEqual( arg1, RReal::BasicType() )
&& nl->IsEqual( arg2, RReal::BasicType() )) ||
(nl->IsEqual( arg1, Periods::BasicType() )
&& nl->IsEqual( arg2, Periods::BasicType() )) ||
(nl->IsEqual( arg1, IBool::BasicType() )
&& nl->IsEqual( arg2, IBool::BasicType() )) ||
(nl->IsEqual( arg1, IInt::BasicType() )
&& nl->IsEqual( arg2, IInt::BasicType() )) ||
(nl->IsEqual( arg1, IReal::BasicType() )
&& nl->IsEqual( arg2, IReal::BasicType() )) ||
(nl->IsEqual( arg1, IPoint::BasicType() )
&& nl->IsEqual( arg2, IPoint::BasicType() )))
return nl->SymbolAtom( CcBool::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
ListExpr
TemporalTemporalTypeMapBool2( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( (nl->IsEqual( arg1, MBool::BasicType() )
&& nl->IsEqual( arg2, MBool::BasicType() )) ||
(nl->IsEqual( arg1, MInt::BasicType() )
&& nl->IsEqual( arg2, MInt::BasicType() )) ||
(nl->IsEqual( arg1, MReal::BasicType() )
&& nl->IsEqual( arg2, MReal::BasicType() )) ||
(nl->IsEqual( arg1, MPoint::BasicType() )
&& nl->IsEqual( arg2, MPoint::BasicType() )) )
return nl->SymbolAtom( CcBool::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
Type Mapping for the mbool2mint function
*/
ListExpr TemporalMBool2MInt(ListExpr args){
if(nl->ListLength(args)!=1){
ErrorReporter::ReportError("Single argument expected");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
if(nl->IsEqual(nl->First(args),MBool::BasicType())){
return nl->SymbolAtom(MInt::BasicType());
}
ErrorReporter::ReportError("mbool expected");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
Type Mapping for the mint2mbool function
*/
ListExpr TemporalMInt2MBool(ListExpr args){
if(nl->ListLength(args)!=1){
ErrorReporter::ReportError("Single argument expected");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
if(nl->IsEqual(nl->First(args),MInt::BasicType())){
return nl->SymbolAtom(MBool::BasicType());
}
ErrorReporter::ReportError("mint expected");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
Type Mapping for the mint2mreal function
*/
ListExpr TemporalMInt2MReal(ListExpr args){
if(nl->ListLength(args)!=1){
ErrorReporter::ReportError("Single argument expected");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
if(nl->IsEqual(nl->First(args),MInt::BasicType())){
return nl->SymbolAtom(MReal::BasicType());
}
ErrorReporter::ReportError("mint expected");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.1 Type Mapping for the ~ExtendDeftime~ function
*/
ListExpr ExtDeftimeTypeMap(ListExpr args){
if(nl->ListLength(args)!=2){
ErrorReporter::ReportError("two argument expected");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
ListExpr arg1 = nl->First(args);
ListExpr arg2 = nl->Second(args);
if(nl->AtomType(arg1)!=SymbolType || nl->AtomType(arg2)!=SymbolType){
ErrorReporter::ReportError("simple types required");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
std::string sarg1 = nl->SymbolValue(arg1);
std::string sarg2 = nl->SymbolValue(arg2);
if( (sarg1==MInt::BasicType()
&& sarg2==UInt::BasicType() ) ||
(sarg1==MBool::BasicType()
&& sarg2==UBool::BasicType()) ){
return nl->SymbolAtom(sarg1);
}
ErrorReporter::ReportError("(mint x uint) or (mbool x ubool) needed");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.1 Type mapping function ~InstantInstantTypeMapBool~
Is used for the ~<~, ~<=~, ~>~, and ~>=~ operators.
*/
ListExpr
InstantInstantTypeMapBool( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( nl->IsEqual( arg1, Instant::BasicType() )
&& nl->IsEqual( arg2, Instant::BasicType() ) )
return nl->SymbolAtom( CcBool::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.2 Type mapping function ~RangeRangeTypeMapBool~
It is for the ~intersects~, which have two
~ranges~ as input and a ~bool~ result type.
*/
ListExpr
RangeRangeTypeMapBool( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( (nl->IsEqual( arg1, RInt::BasicType() )
&& nl->IsEqual( arg2, RInt::BasicType() )) ||
(nl->IsEqual( arg1, RReal::BasicType() )
&& nl->IsEqual( arg2, RReal::BasicType() )) ||
(nl->IsEqual( arg1, Periods::BasicType() )
&& nl->IsEqual( arg2, Periods::BasicType() )) )
return nl->SymbolAtom( CcBool::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.3 Type mapping function ~RangeBaseTypeMapBool1~
It is for the operator ~inside~ which have two ~ranges~ as input or a
~BASE~ and a ~range~ in this order as arguments and ~bool~ as the result type.
*/
ListExpr
RangeBaseTypeMapBool1( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( (nl->IsEqual( arg1, RInt::BasicType() )
&& nl->IsEqual( arg2, RInt::BasicType() )) ||
(nl->IsEqual( arg1, RReal::BasicType() )
&& nl->IsEqual( arg2, RReal::BasicType() )) ||
(nl->IsEqual( arg1, Periods::BasicType() )
&& nl->IsEqual( arg2, Periods::BasicType() )) ||
(nl->IsEqual( arg1, CcInt::BasicType() )
&& nl->IsEqual( arg2, RInt::BasicType() )) ||
(nl->IsEqual( arg1, CcReal::BasicType() )
&& nl->IsEqual( arg2, RReal::BasicType() )) ||
(nl->IsEqual( arg1, Instant::BasicType() )
&& nl->IsEqual( arg2, Periods::BasicType() )) )
return nl->SymbolAtom( CcBool::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.4 Type mapping function ~RangeBaseTypeMapBool2~
It is for the operator ~before~ which have two ~ranges~ as input or a
~BASE~ and a ~range~ in any order as arguments and ~bool~ as the result type.
*/
ListExpr
RangeBaseTypeMapBool2( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( (nl->IsEqual( arg1, RInt::BasicType() )
&& nl->IsEqual( arg2, RInt::BasicType() )) ||
(nl->IsEqual( arg1, RReal::BasicType() )
&& nl->IsEqual( arg2, RReal::BasicType() )) ||
(nl->IsEqual( arg1, Periods::BasicType() )
&& nl->IsEqual( arg2, Periods::BasicType() )) ||
(nl->IsEqual( arg1, CcInt::BasicType() )
&& nl->IsEqual( arg2, RInt::BasicType() )) ||
(nl->IsEqual( arg1, CcReal::BasicType() )
&& nl->IsEqual( arg2, RReal::BasicType() )) ||
(nl->IsEqual( arg1, Instant::BasicType() )
&& nl->IsEqual( arg2, Periods::BasicType() )) ||
(nl->IsEqual( arg1, RInt::BasicType() )
&& nl->IsEqual( arg2, CcInt::BasicType() )) ||
(nl->IsEqual( arg1, RReal::BasicType() )
&& nl->IsEqual( arg2, CcReal::BasicType() )) ||
(nl->IsEqual( arg1, Periods::BasicType() )
&& nl->IsEqual( arg2, Instant::BasicType() )) )
return nl->SymbolAtom( CcBool::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.5 Type mapping function ~RangeRangeTypeMapRange~
It is for the operators ~intersection~, ~union~, and ~minus~ which have two
~ranges~ as input and a ~range~ as result type.
*/
ListExpr
RangeRangeTypeMapRange( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( nl->IsEqual( arg1, RInt::BasicType() )
&& nl->IsEqual( arg2, RInt::BasicType() ) )
return nl->SymbolAtom( RInt::BasicType() );
if( nl->IsEqual( arg1, RReal::BasicType() )
&& nl->IsEqual( arg2, RReal::BasicType() ) )
return nl->SymbolAtom( RReal::BasicType() );
if( nl->IsEqual( arg1, Periods::BasicType() )
&& nl->IsEqual( arg2, Periods::BasicType() ) )
return nl->SymbolAtom( Periods::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.6 Type mapping function ~RangeTypeMapBase~
It is for the aggregate operators ~min~, ~max~, and ~avg~ which have one
~range~ as input and a ~BASE~ as result type.
*/
ListExpr
RangeTypeMapBase( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
ListExpr arg1 = nl->First( args );
if( nl->IsEqual( arg1, RInt::BasicType() ) )
return nl->SymbolAtom( CcInt::BasicType() );
if( nl->IsEqual( arg1, RReal::BasicType() ) )
return nl->SymbolAtom( CcReal::BasicType() );
if( nl->IsEqual( arg1, Periods::BasicType() ) )
return nl->SymbolAtom( Instant::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.7 Type mapping function ~TemporalSetValueTypeMapInt~
It is for the ~no\_components~ operator.
*/
ListExpr
TemporalSetValueTypeMapInt( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
ListExpr arg1 = nl->First( args );
if( nl->IsEqual( arg1, RInt::BasicType() ) ||
nl->IsEqual( arg1, RReal::BasicType() ) ||
nl->IsEqual( arg1, Periods::BasicType() ) ||
nl->IsEqual( arg1, MBool::BasicType() ) ||
nl->IsEqual( arg1, MInt::BasicType() ) ||
nl->IsEqual( arg1, MReal::BasicType() ) ||
nl->IsEqual( arg1, MPoint::BasicType() ) ||
nl->IsEqual( arg1, CMPoint::BasicType() ) )
return nl->SymbolAtom( CcInt::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.6 Type mapping function ~IntimeTypeMapBase~
It is for the operator ~val~.
*/
ListExpr
IntimeTypeMapBase( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
ListExpr arg1 = nl->First( args );
if( nl->IsEqual( arg1, IBool::BasicType() ) )
return nl->SymbolAtom( CcBool::BasicType() );
if( nl->IsEqual( arg1, IInt::BasicType() ) )
return nl->SymbolAtom( CcInt::BasicType() );
if( nl->IsEqual( arg1, IReal::BasicType() ) )
return nl->SymbolAtom( CcReal::BasicType() );
if( nl->IsEqual( arg1, IPoint::BasicType() ) )
return nl->SymbolAtom( Point::BasicType() );
if (nl->IsEqual(arg1, "cipoint")) {
return nl->SymbolAtom(CPoint::BasicType());
}
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.6 Type mapping function ~UIntimeTypeMapBase~
It is for the operator ~val~.
*/
ListExpr
UIntimeTypeMapBase( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
ListExpr arg1 = nl->First( args );
if( nl->IsEqual( arg1, UInt::BasicType() ) )
return nl->SymbolAtom( CcInt::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.6 Type mapping function ~IntimeTypeMapInstant~
It is for the operator ~inst~.
*/
ListExpr
IntimeTypeMapInstant( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
ListExpr arg1 = nl->First( args );
if( nl->IsEqual( arg1, IBool::BasicType() ) ||
nl->IsEqual( arg1, IInt::BasicType() ) ||
nl->IsEqual( arg1, IReal::BasicType() ) ||
nl->IsEqual( arg1, IPoint::BasicType() ) ||
nl->IsEqual( arg1, "cipoint" ) )
return nl->SymbolAtom( Instant::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.7 Type mapping function ~MovingInstantTypeMapIntime~
It is for the operator ~atinstant~.
*/
ListExpr
MovingInstantTypeMapIntime( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( nl->IsEqual( arg2, Instant::BasicType() ) )
{
if( nl->IsEqual( arg1, MBool::BasicType() ) )
return nl->SymbolAtom( IBool::BasicType() );
if( nl->IsEqual( arg1, MInt::BasicType() ) )
return nl->SymbolAtom( IInt::BasicType() );
if( nl->IsEqual( arg1, MReal::BasicType() ) )
return nl->SymbolAtom( IReal::BasicType() );
if( nl->IsEqual( arg1, MPoint::BasicType() ) )
return nl->SymbolAtom( IPoint::BasicType() );
if (CMPoint::checkType(arg1)) {
return nl->SymbolAtom("cipoint");
}
}
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.7 Type mapping function ~WhenTM~
It is for the operator ~when~.
*/
ListExpr WhenTM( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr mx = nl->First( args ),
mb = nl->Second( args );
if( nl->IsEqual( mb, MBool::BasicType() ) )
{
if( nl->IsEqual( mx, MBool::BasicType() ) ||
nl->IsEqual( mx, MInt::BasicType() ) ||
nl->IsEqual( mx, MReal::BasicType() ) ||
nl->IsEqual( mx, MPoint::BasicType() ))
return mx;
}
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.7 Type mapping function ~MovingPeriodsTypeMapMoving~
It is for the operator ~atperiods~.
*/
ListExpr
MovingPeriodsTypeMapMoving( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( nl->IsEqual( arg2, Periods::BasicType() ) )
{
if( nl->IsEqual( arg1, MBool::BasicType() ) )
return nl->SymbolAtom( MBool::BasicType() );
if( nl->IsEqual( arg1, MInt::BasicType() ) )
return nl->SymbolAtom( MInt::BasicType() );
if( nl->IsEqual( arg1, MReal::BasicType() ) )
return nl->SymbolAtom( MReal::BasicType() );
if( nl->IsEqual( arg1, MPoint::BasicType() ) )
return nl->SymbolAtom( MPoint::BasicType() );
if (CMPoint::checkType(arg1)) {
return nl->SymbolAtom(CMPoint::BasicType());
}
}
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.8 Type mapping function ~MovingTypeMapRange~
It is for the operator ~deftime~.
*/
ListExpr
MovingTypeMapPeriods( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
ListExpr arg1 = nl->First( args );
if( nl->IsEqual( arg1, MBool::BasicType() ) ||
nl->IsEqual( arg1, MInt::BasicType() ) ||
nl->IsEqual( arg1, MReal::BasicType() ) ||
nl->IsEqual( arg1, MPoint::BasicType() ) ||
nl->IsEqual( arg1, CMPoint::BasicType() ) )
return nl->SymbolAtom( Periods::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.8 Type mapping function ~MovingTypeMapSpatial~
It is for the operator ~trajectory~.
*/
ListExpr
MovingTypeMapSpatial( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
ListExpr arg1 = nl->First( args );
if( nl->IsEqual( arg1, MPoint::BasicType() ) )
return nl->SymbolAtom( Line::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.9 Type mapping function ~MovingInstantPeriodsTypeMapBool~
It is for the operator ~present~.
*/
ListExpr
MovingInstantPeriodsTypeMapBool( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( nl->IsEqual( arg2, Instant::BasicType() ) ||
nl->IsEqual( arg2, Periods::BasicType() ) )
{
if( nl->IsEqual( arg1, MBool::BasicType() ) ||
nl->IsEqual( arg1, MInt::BasicType() ) ||
nl->IsEqual( arg1, MReal::BasicType() ) ||
nl->IsEqual( arg1, MPoint::BasicType() ) )
return nl->SymbolAtom( CcBool::BasicType() );
}
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.10 Type mapping function ~MovingBaseTypeMapBool~
It is for the operator ~passes~.
*/
ListExpr
MovingBaseTypeMapBool( ListExpr args )
{
ListExpr arg1, arg2;
if( nl->ListLength( args ) == 2 )
{
arg1 = nl->First( args );
arg2 = nl->Second( args );
if( (nl->IsEqual( arg1, MBool::BasicType() )
&& nl->IsEqual( arg2, CcBool::BasicType() )) ||
(nl->IsEqual( arg1, MInt::BasicType() )
&& nl->IsEqual( arg2, CcInt::BasicType() )) ||
(nl->IsEqual( arg1, MReal::BasicType() )
&& nl->IsEqual( arg2, CcReal::BasicType() )) ||
(nl->IsEqual( arg1, MPoint::BasicType() )
&& nl->IsEqual( arg2, Point::BasicType() )) ||
(nl->IsEqual( arg1, MPoint::BasicType() )
&& nl->IsEqual( arg2, Region::BasicType() )) ||
(nl->IsEqual( arg1, MPoint::BasicType() )
&& nl->IsEqual( arg2, Rectangle<2>::BasicType() )) )
return nl->SymbolAtom( CcBool::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.10 Type mapping function ~MovingBaseTypeMapBool~
It is for the operator ~at~.
*/
ListExpr
MovingBaseTypeMapMoving( ListExpr args )
{
ListExpr arg1, arg2;
if( nl->ListLength( args ) == 2 )
{
arg1 = nl->First( args );
arg2 = nl->Second( args );
if( nl->IsEqual( arg1, MBool::BasicType() )
&& nl->IsEqual( arg2, CcBool::BasicType() ) )
return nl->SymbolAtom( MBool::BasicType() );
if( nl->IsEqual( arg1, MInt::BasicType() )
&& nl->IsEqual( arg2, CcInt::BasicType() ) )
return nl->SymbolAtom( MInt::BasicType() );
if( nl->IsEqual( arg1, MReal::BasicType() )
&& nl->IsEqual( arg2, CcReal::BasicType() ) )
return nl->SymbolAtom( MReal::BasicType() );
if( nl->IsEqual( arg1, MPoint::BasicType() )
&& nl->IsEqual( arg2, Point::BasicType() ) )
return nl->SymbolAtom( MPoint::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.11 Type mapping function ~MovingTypeMapeIntime~
It is for the operators ~initial~ and ~final~.
*/
ListExpr
MovingTypeMapIntime( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
ListExpr arg1 = nl->First( args );
if( nl->IsEqual( arg1, MBool::BasicType() ) )
return nl->SymbolAtom( IBool::BasicType() );
if( nl->IsEqual( arg1, MInt::BasicType() ) )
return nl->SymbolAtom( IInt::BasicType() );
if( nl->IsEqual( arg1, MReal::BasicType() ) )
return nl->SymbolAtom( IReal::BasicType() );
if( nl->IsEqual( arg1, MPoint::BasicType() ) )
return nl->SymbolAtom( IPoint::BasicType() );
if( nl->IsEqual( arg1, CMPoint::BasicType() ) )
return nl->SymbolAtom( CIPoint::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.11 Type mapping function ~MovingTypeMapeIntime~
It is for the operators ~initial~ and ~final~.
*/
ListExpr
MovingBaseTypeMapMReal( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( nl->IsEqual( arg1, MPoint::BasicType() )
&& nl->IsEqual( arg2, Point::BasicType() ) )
return nl->SymbolAtom( MReal::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.12 Type Mapping Function ~MovingTypeMapUnits~
It is used for the operator ~units~
Type mapping for ~units~ is
---- (mbool) -> (stream ubool)
(mint) -> (stream uint)
(mreal) -> (stream ureal)
(mpoint) -> (stream upoint)
(cmpoint) -> (stream cupoint)
----
*/
ListExpr MovingTypeMapUnits( ListExpr args )
{
if ( nl->ListLength(args) == 1 )
{
ListExpr arg1 = nl->First(args);
if( nl->IsEqual( arg1, MBool::BasicType() ) )
return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
nl->SymbolAtom(UBool::BasicType()));
if( nl->IsEqual( arg1, MInt::BasicType() ) )
return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
nl->SymbolAtom(UInt::BasicType()));
if( nl->IsEqual( arg1, MReal::BasicType() ) )
return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
nl->SymbolAtom(UReal::BasicType()));
if( nl->IsEqual( arg1, MPoint::BasicType() ) )
return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
nl->SymbolAtom(UPoint::BasicType()));
if( nl->IsEqual( arg1, CMPoint::BasicType() ) )
return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
nl->SymbolAtom(CUPoint::BasicType()));
}
return nl->SymbolAtom(Symbol::TYPEERROR());
}
/*
16.1.12 Type Mapping Function ~MovingTypeMapGetUnit~
It is used for the operator ~getunit~
Type mapping for ~getunit~ is
---- (mbool) -> (ubool)
(mint) -> (uint)
(mreal) -> (ureal)
(mpoint) -> (upoint)
(cmpoint) -> (cupoint)
----
*/
ListExpr MovingTypeMapGetUnit( ListExpr args )
{
if ( nl->ListLength(args) == 2
&& nl->IsEqual(nl->Second(args), CcInt::BasicType()))
{
ListExpr arg1 = nl->First(args);
if( nl->IsEqual( arg1, MBool::BasicType() ) )
return nl->SymbolAtom(UBool::BasicType());
if( nl->IsEqual( arg1, MInt::BasicType() ) )
return nl->SymbolAtom(UInt::BasicType());
if( nl->IsEqual( arg1, MReal::BasicType() ) )
return nl->SymbolAtom(UReal::BasicType());
if( nl->IsEqual( arg1, MPoint::BasicType() ) )
return nl->SymbolAtom(UPoint::BasicType());
if( nl->IsEqual( arg1, CMPoint::BasicType() ) )
return nl->SymbolAtom(CUPoint::BasicType());
}
return nl->SymbolAtom(Symbol::TYPEERROR());
}
/*
16.1.13 Type Mapping Function ~TemporalGetPositionTypeMap~
It is used for the operator ~getposition~
Type mapping for ~getposition~ is
---- (mbool) x instant -> (int)
(mint) x instant -> (int)
(mreal) x instant -> (int)
(mpoint) x instant -> (int)
(mstring) x instant -> (int)
(mregion) x instant -> (int)
(cmpoint) x instant -> (int)
----
*/
ListExpr TemporalGetPositionTypeMap(ListExpr args) {
if (nl->ListLength(args) == 2 && Instant::checkType(nl->Second(args))) {
ListExpr arg1 = nl->First(args);
if (MBool::checkType(arg1) || MInt::checkType(arg1) ||
MReal::checkType(arg1) || MPoint::checkType(arg1) ||
MString::checkType(arg1) || MRegion::checkType(arg1) ||
CMPoint::checkType(arg1) ) {
return nl->SymbolAtom(CcInt::BasicType());
}
}
return listutils::typeError("Expects a moving(alpha) and an instant.");
}
/*
16.1.12 Type mapping for simplify operator
*/
ListExpr MovingTypeMapSimplify(ListExpr args){
// Signatures are
// mpoint x real [x geoid] -> mpoint
// mpoint x real x duration [x geoid]
// mreal x real -> mreal
int len = nl->ListLength(args);
if(len<2 || len > 4){
return listutils::typeError("2 until 4 arguments required");
}
if(!CcReal::checkType(nl->Second(args))){
return listutils::typeError("second argument has to be a real");
}
ListExpr first = nl->First(args);
if(MReal::checkType(first)){
if(len!=2){
return listutils::typeError("simplifying an mreal requires "
"exactly 2 arguments");
}
return first;
}
if(!MPoint::checkType(first)){
return listutils::typeError("simplify requires an mreal or an "
"mpoint as it's first argument");
}
if(len==2){
return first;
}
ListExpr third = nl->Third(args);
if(len==3){
if(!Duration::checkType(third) && !Geoid::checkType(third)){
return listutils::typeError("third argument must be a "
"duration or an mpoint");
}
return first;
}
// len = 4
if(!Duration::checkType(third) || !Geoid::checkType(nl->Fourth(args))){
return listutils::typeError("third arg not of type duration or "
"fourth arg not of type geoid");
}
return first;
}
/*
16.1.12 Type mapping for the breakpoints operator
*/
ListExpr MovingTypeMapBreakPoints(ListExpr args){
int len = nl->ListLength(args);
std::string err = "mpoint x duration [ x real] expected";
if( (len!=2) && (len!=3)){
return listutils::typeError(err + " (wrong number of args)");
}
if(!MPoint::checkType(nl->First(args)) ||
!Duration::checkType(nl->Second(args))){
return listutils::typeError(err );
}
if((len==3) && !CcReal::checkType(nl->Third(args))){
return listutils::typeError(err);
}
return nl->SymbolAtom(Points::BasicType());
}
/*
16.1.12 Type Mapping for Operator ~breaks~
Signature: mpoint x duration x real -> periods
*/
ListExpr breaksTM(ListExpr args){
std::string err = " mpoint x duration x real expected";
if(!nl->HasLength(args,3)){
return listutils::typeError(err);
}
if(!MPoint::checkType(nl->First(args)) ||
!Duration::checkType(nl->Second(args)) ||
!CcReal::checkType(nl->Third(args))){
return listutils::typeError(err);
}
return nl->SymbolAtom(Periods::BasicType());
}
/*
16.1.12 Type mapping for the gk operator
*/
ListExpr MovingTypeMapgk(ListExpr args){
int len = nl->ListLength(args);
if( (len < 1) || (len > 2) ){
ErrorReporter::ReportError("One or two arguments expected.");
return nl->TypeError();
}
ListExpr arg1 = nl->First(args);
if(!MPoint::checkType(arg1) && !UPoint::checkType(arg1)){
ErrorReporter::ReportError("mpoint expected");
return nl->TypeError();
}
if( (len==2) && nl->IsEqual(nl->Second(args),CcInt::BasicType()) ) {
return arg1; // Zone provided by user
} else if (len==1){
return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()),
nl->OneElemList(nl->IntAtom(2)), // standard zone for Hagen
arg1);
}
ErrorReporter::ReportError("No match.");
return nl->TypeError();
}
ListExpr DelayOperatorTypeMapping( ListExpr args )
{
int len = nl->ListLength(args);
std::string errmsg = "Expected mpoint x mpoint [x geoid].";
if((len<2) || (len>3)){
return listutils::typeError(errmsg);
}
if(!listutils::isSymbol(nl->First(args),MPoint::BasicType())){
return listutils::typeError(errmsg);
}
if(!listutils::isSymbol(nl->Second(args),MPoint::BasicType())){
return listutils::typeError(errmsg);
}
if((len == 3) && (!listutils::isSymbol(nl->Third(args),Geoid::BasicType()))) {
return listutils::typeError(errmsg);
}
/*
Not implemented:
1- Check that the two moving points have the same trajectory.
2- Check the the trajectory is continuos on the spatial space
(necessary to compute the distance traversed)
*/
return (nl->SymbolAtom(MReal::BasicType()));
}
/*
16.1.12 Type mapping for the ~vertices~ operator
*/
ListExpr MovingTypeMapVertices(ListExpr args){
if(nl->ListLength(args)!=1){
ErrorReporter::ReportError("mpoint expected");
return nl->TypeError();
}
ListExpr arg1 = nl->First(args);
if(nl->IsEqual(arg1,MPoint::BasicType())){
return nl->SymbolAtom(Points::BasicType());
}
ErrorReporter::ReportError("mpoint expected");
return nl->TypeError();
}
/*
16.1.12 Type mapping function of the ~integrate~ Operator
*/
ListExpr TypeMapIntegrate(ListExpr args){
int len = nl->ListLength(args);
if(len!=1){
ErrorReporter::ReportError("one argument expected");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
ListExpr arg = nl->First(args);
if(nl->IsEqual(arg,UReal::BasicType()) ||
nl->IsEqual(arg,MReal::BasicType())){
return nl->SymbolAtom(CcReal::BasicType());
}
ErrorReporter::ReportError(UReal::BasicType()+" or "+MReal::BasicType()+
"expected");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
/*
16.1.12 Type mapping function of the ~min~ and the ~max~ Operator
*/
ListExpr TypeMapMinMax(ListExpr args){
int len = nl->ListLength(args);
if(len!=1){
ErrorReporter::ReportError("one argument expected");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
ListExpr arg = nl->First(args);
if(nl->IsEqual(arg,UReal::BasicType()) ||
nl->IsEqual(arg,MReal::BasicType())){
return nl->SymbolAtom(CcReal::BasicType());
}
else
{
if (nl->IsEqual(arg,MInt::BasicType())){
return nl->SymbolAtom(CcInt::BasicType());
}
}
ErrorReporter::ReportError(UReal::BasicType()+" or "
+MReal::BasicType()+" expected");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
/*
16.1.12 Type mapping function of the ~linearize~ Operator
*/
ListExpr TypeMapLinearize(ListExpr args){
int len = nl->ListLength(args);
if(len!=1){
ErrorReporter::ReportError("one argument expected");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
ListExpr arg = nl->First(args);
if(nl->IsEqual(arg,UReal::BasicType()) ||
nl->IsEqual(arg,MReal::BasicType())){
return nl->SymbolAtom(nl->SymbolValue(arg));
}
ErrorReporter::ReportError(UReal::BasicType()
+" or "+MReal::BasicType()+" expected");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
/*
16.1.12 Type mapping function of the ~linearize2~ Operator
*/
ListExpr TypeMapLinearize2(ListExpr args){
int len = nl->ListLength(args);
if(len!=1){
ErrorReporter::ReportError("one argument expected");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
ListExpr arg = nl->First(args);
if( nl->IsEqual(arg,MReal::BasicType()))
return nl->SymbolAtom(nl->SymbolValue(arg));
if( nl->IsEqual(arg,UReal::BasicType()))
return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ),
nl->SymbolAtom( UReal::BasicType() ));
ErrorReporter::ReportError(MReal::BasicType()+
" or "+UReal::BasicType()+" expected");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
/*
16.1.13 Type mapping function for the ~approximate~ operator
*/
ListExpr TypeMapApproximate(ListExpr args){
int len = nl->ListLength(args);
if( (len != 3) && (len != 4) && (len != 5) && (len!=6)){
return listutils::typeError("three, four, fivei,"
" or six arguments expected");
}
// check needed arguments
int durindex = -1;
int boolIndex = -1;
int breakAttrIndex = -1;
std::string err = "stream(tuple) x attr_1 x attr_2 [ x bool] "
"[ x duration] [ x attr_3] expected";
ListExpr stream = nl->First(args);
ListExpr attrname_time = nl->Second(args);
ListExpr attrname_value = nl->Third(args);
if(!listutils::isTupleStream(stream)){
return listutils::typeError("first parameter must be a tuple stream");
}
if(!listutils::isSymbol(attrname_time)){
return listutils::typeError("second parameter must be an attribute name");
}
if(!listutils::isSymbol(attrname_value)){
return listutils::typeError("third parameter must be an attribute name");
}
ListExpr type;
ListExpr attrList = nl->Second(nl->Second(stream));
std::string name = nl->SymbolValue(attrname_time);
int index1 = listutils::findAttribute(attrList, name, type);
if(index1==0){
return listutils::typeError("attribute name " + name +
" unknown in tuple stream");
}
if(!DateTime::checkType(type)){
return listutils::typeError("attribute '" + name +
"' must be of type 'instant'");
}
name = nl->SymbolValue(attrname_value);
int index2 = listutils::findAttribute(attrList, name, type);
if(index2==0){
return listutils::typeError("attribute name " + name +
" unknown in tuple stream");
}
std::string restype;
if(listutils::isSymbol(type,Point::BasicType())){
restype = MPoint::BasicType();
} else if (listutils::isSymbol(type,CcReal::BasicType())){
restype = MReal::BasicType();
}else if (listutils::isSymbol(type,CcInt::BasicType())){
restype = MInt::BasicType();
} else if (listutils::isSymbol(type,CcBool::BasicType())){
restype = MBool::BasicType();
}else if (listutils::isSymbol(type,CcString::BasicType())){
restype = MString::BasicType();
}else if (listutils::isSymbol(type,stj::Label::BasicType())){
restype = stj::MLabel::BasicType();
} else {
return listutils::typeError("third argument is not an allowed type "
"(point, real, int, bool, string, label)");
}
// check optional arguments
if(len>3){
ListExpr fourth = nl->Fourth(args);
if(CcBool::checkType(fourth)){
boolIndex = 3;
}else if(Duration::checkType(fourth)){
durindex = 3;
} else if(listutils::isSymbol(fourth)){
ListExpr at;
breakAttrIndex = listutils::findAttribute(attrList,
nl->SymbolValue(fourth),at);
if(breakAttrIndex==0){
return listutils::typeError(err);
}
if(!CcBool::checkType(at)){
return listutils::typeError(err);
}
breakAttrIndex--;
} else {
return listutils::typeError(err);
}
}
if(len>4){
ListExpr fifth = nl->Fifth(args);
if(CcBool::checkType(fifth)){
if(boolIndex > 0){
return listutils::typeError(err);
}
boolIndex = 4;
}else if(Duration::checkType(fifth)){
if(durindex>0){
return listutils::typeError(err);
}
durindex = 4;
} else if(listutils::isSymbol(fifth)){
if(breakAttrIndex>=0){
return listutils::typeError(err);
}
ListExpr at;
breakAttrIndex = listutils::findAttribute(attrList,
nl->SymbolValue(fifth),at);
if(breakAttrIndex==0){
return listutils::typeError(err);
}
if(!CcBool::checkType(at)){
return listutils::typeError(err);
}
breakAttrIndex--;
} else {
return listutils::typeError(err);
}
}
if(len>5){
ListExpr sixth = nl->Sixth(args);
if(CcBool::checkType(sixth)){
if(boolIndex > 0){
return listutils::typeError(err);
}
boolIndex = 5;
}else if(Duration::checkType(sixth)){
if(durindex>0){
return listutils::typeError(err);
}
durindex = 5;
} else if(listutils::isSymbol(sixth)){
if(breakAttrIndex>=0){
return listutils::typeError(err);
}
ListExpr at;
breakAttrIndex = listutils::findAttribute(attrList,
nl->SymbolValue(sixth),at);
if(breakAttrIndex==0){
return listutils::typeError(err);
}
if(!CcBool::checkType(at)){
return listutils::typeError(err);
}
breakAttrIndex--;
} else {
return listutils::typeError(err);
}
}
ListExpr indexes = nl->FiveElemList(
nl->IntAtom(index1-1),
nl->IntAtom(index2-1),
nl->IntAtom(durindex),
nl->IntAtom(boolIndex),
nl->IntAtom(breakAttrIndex));
return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()),
indexes,
nl->SymbolAtom(restype));
}
/*
16.1.13 Type mapping function ~IntSetTypeMapPeriods~
It is used for the operators ~theyear~, ~themonth~, ~theday~, ~thehour~,
~theminute~,~thesecond~
*/
ListExpr
IntSetTypeMapPeriods( ListExpr args )
{
ListExpr argi;
bool correct=true;
if( ( nl->ListLength(args) < 1 ) || ( nl->ListLength(args) > 6) )
return nl->SymbolAtom(Symbol::TYPEERROR());
if( nl->ListLength(args) >= 1 )
{
argi = nl->First(args);
if( !nl->IsEqual( argi, CcInt::BasicType() ) )
correct = false;
}
if ( nl->ListLength(args) >= 2 )
{
argi = nl->Second(args);
if( !nl->IsEqual( argi, CcInt::BasicType() ) )
correct = false;
}
if ( nl->ListLength(args) >= 3 )
{
argi = nl->Third(args);
if( !nl->IsEqual( argi, CcInt::BasicType() ) )
correct = false;
}
if ( nl->ListLength(args) >= 4 )
{
argi = nl->Fourth(args);
if( !nl->IsEqual( argi, CcInt::BasicType() ) )
correct=false;
}
if( nl->ListLength(args) >= 5 )
{
argi = nl->Fifth(args);
if( !nl->IsEqual( argi, CcInt::BasicType() ) )
correct=false;
}
if ( nl->ListLength(args) >= 6 )
{
argi = nl->Sixth(args);
if( !nl->IsEqual( argi, CcInt::BasicType() ) )
correct=false;
}
if( correct )
return nl->SymbolAtom( Periods::BasicType() );
return nl->SymbolAtom(Symbol::TYPEERROR());
}
/*
16.1.13 Type mapping function ~PeriodsPeriodsTypeMapPeriods~
It is used for the operator ~theperiod~
*/
ListExpr
PeriodsPeriodsTypeMapPeriods( ListExpr args )
{
if( nl->ListLength(args) == 2 )
{
ListExpr arg1 = nl->First(args),
arg2 = nl->Second(args);
if( nl->IsEqual( arg1, Periods::BasicType() )
&& nl->IsEqual( arg2, Periods::BasicType() ) )
return nl->SymbolAtom( Periods::BasicType() );
}
return nl->SymbolAtom(Symbol::TYPEERROR());
}
/*
16.1.15 Type mapping function "MPointTypeMapTranslate"
This type mapping function is used for the ~translate~ operator.
*/
ListExpr MPointTypeMapTranslate( ListExpr args )
{
ListExpr arg1, arg2;
std::string err = "mpoint x (duration x real x real) expected";
if ( nl->ListLength( args ) == 2 )
{
arg1 = nl->First( args );
arg2 = nl->Second( args );
if(!nl->HasLength(arg2,3)){
return listutils::typeError(err);
}
if( nl->IsEqual( arg1, MPoint::BasicType() ) &&
nl->IsEqual(nl->First( arg2 ), Duration::BasicType()) &&
nl->IsEqual(nl->Second( arg2 ), CcReal::BasicType()) &&
nl->IsEqual(nl->Third( arg2 ), CcReal::BasicType())) {
return (nl->SymbolAtom( MPoint::BasicType() )); }
}
return listutils::typeError(err);
}
/*
16.1.16 Type mapping function "box3d"
*/
ListExpr Box3dTypeMap(ListExpr args){
int len = nl->ListLength(args);
if(len==2){
ListExpr arg1 = nl->First(args);
ListExpr arg2 = nl->Second(args);
if(nl->IsEqual(arg1,Rectangle<2>::BasicType())){
if(nl->IsEqual(arg2,Instant::BasicType())
|| nl->IsEqual(arg2,Periods::BasicType()))
return nl->SymbolAtom(Rectangle<3>::BasicType());
}
ErrorReporter::ReportError(" rect x {instant, periods } expected\n");
return nl->SymbolAtom(Symbol::TYPEERROR());
} else if(len==1){
ListExpr arg = nl->First(args);
if(nl->IsEqual(arg,Rectangle<2>::BasicType())
|| (nl->IsEqual(arg,Instant::BasicType()) ||
nl->IsEqual(arg,Periods::BasicType())))
return nl->SymbolAtom(Rectangle<3>::BasicType());
ErrorReporter::ReportError("rect, instant, or periods required\n");
return nl->SymbolAtom(Symbol::TYPEERROR() );
}
else{
ErrorReporter::ReportError("one or two arguments required");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
}
/*
16.1.17 Type mapping function "box2d"
*/
ListExpr Box2dTypeMap(ListExpr args)
{
ListExpr arg1;
if ( nl->ListLength( args ) == 1 )
{
arg1 = nl->First( args );
if( nl->IsEqual( arg1, Rectangle<2>::BasicType() ) )
return nl->SymbolAtom( Rectangle<2>::BasicType() );
if( nl->IsEqual( arg1, Rectangle<3>::BasicType() ) )
return nl->SymbolAtom( Rectangle<2>::BasicType() );
if( nl->IsEqual( arg1, Rectangle<4>::BasicType() ) )
return nl->SymbolAtom( Rectangle<2>::BasicType() );
if( nl->IsEqual( arg1, Rectangle<8>::BasicType() ) )
return nl->SymbolAtom( Rectangle<2>::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.18 Type mapping function "TemporalBBoxTypeMap"
For operator ~bbox~
*/
ListExpr TemporalBBoxTypeMap( ListExpr args )
{
int noargs = nl->ListLength( args );
std::string errmsg = "Expected (M [x geoid]) OR (T), where M in "
"{upoint, mpoint, cupoint, cmpoint, ipoint}, T in {instant, periods}.";
if ( (noargs<1) || (noargs>2) ){
return listutils::typeError(errmsg);
}
if( (noargs==2) && !listutils::isSymbol(nl->Second(args),Geoid::BasicType())){
return listutils::typeError(errmsg);
}
ListExpr arg1 = nl->First( args );
if (UPoint::checkType(arg1) || MPoint::checkType(arg1)
|| IPoint::checkType(arg1) || Periods::checkType(arg1)
|| Instant::checkType(arg1) || CUPoint::checkType(arg1)
|| CMPoint::checkType(arg1)) {
return nl->SymbolAtom(Rectangle<3>::BasicType());
}
return listutils::typeError(errmsg);
}
/*
16.1.18 Type mapping function "TemporalMBRangeTypeMap"
For operator ~bbox~
*/
ListExpr TemporalMBRangeTypeMap( ListExpr args )
{
ListExpr arg1;
if ( nl->ListLength( args ) == 1 )
{
arg1 = nl->First( args );
if( nl->IsEqual( arg1, RInt::BasicType() ) )
return (nl->SymbolAtom( RInt::BasicType() ));
if( nl->IsEqual( arg1, RReal::BasicType() ) )
return (nl->SymbolAtom( RReal::BasicType() ));
if( nl->IsEqual( arg1, RBool::BasicType() ) )
return (nl->SymbolAtom( RReal::BasicType() ));
if( nl->IsEqual( arg1, RString::BasicType() ) )
return (nl->SymbolAtom( RString::BasicType() ));
if( nl->IsEqual( arg1, Periods::BasicType() ) )
return (nl->SymbolAtom( Periods::BasicType() ));
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.18 Type mapping function ~TemporalBBox2dTypeMap~
For operator ~bbox2d~
*/
ListExpr TemporalBBox2dTypeMap( ListExpr args )
{
int noargs = nl->ListLength( args );
std::string errmsg = "Expected (T [x geoid]), "
"where T in {ipoint, upoint, mpoint, cupoint, cmpoint}";
if( (noargs<1) || (noargs>2) ){
return listutils::typeError(errmsg);
}
if( (noargs == 2) &&
!listutils::isSymbol(nl->Second(args),Geoid::BasicType()) ){
return listutils::typeError(errmsg);
}
ListExpr arg1 = nl->First( args );
if (UPoint::checkType(arg1) || MPoint::checkType(arg1)
|| IPoint::checkType(arg1) || CUPoint::checkType(arg1)
|| CMPoint::checkType(arg1)) {
return nl->SymbolAtom(Rectangle<2>::BasicType());
}
return listutils::typeError(errmsg);
}
/*
16.1.19 Type mapping function ~TemporalTheRangeTM~
For operator ~theRange~
*/
ListExpr TemporalTheRangeTM( ListExpr args )
{
ListExpr arg1, arg2, arg3, arg4;
std::string argstr;
nl->WriteToString(argstr, args);
if ( nl->ListLength( args ) == 4 )
{
arg1 = nl->First( args );
arg2 = nl->Second( args );
arg3 = nl->Third( args );
arg4 = nl->Fourth( args );
if( !nl->Equal(arg1, arg2) )
{
ErrorReporter::ReportError("Operator theRange: First two arguments"
"must have the same type, but argument list is '" + argstr + "'.");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
if( !nl->IsEqual( arg3, CcBool::BasicType())
|| !nl->IsEqual( arg4, CcBool::BasicType()) )
{
ErrorReporter::ReportError("Operator theRange: Third and fourth "
"arguments must have type 'bool', but argument list is '"
+ argstr + "'.");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
if( nl->IsEqual( arg1, Instant::BasicType() ) )
return (nl->SymbolAtom( Periods::BasicType() ));
if( nl->IsEqual( arg1, CcInt::BasicType() ) )
return (nl->SymbolAtom( RInt::BasicType() ));
if( nl->IsEqual( arg1, CcBool::BasicType() ) )
return (nl->SymbolAtom( RBool::BasicType() ));
if( nl->IsEqual( arg1, CcReal::BasicType() ) )
return (nl->SymbolAtom( RReal::BasicType() ));
if( nl->IsEqual( arg1, CcString::BasicType() ) )
return (nl->SymbolAtom( RString::BasicType() ));
ErrorReporter::ReportError("Operator theRange expects as first and "
"second argument one of {instant, int, bool, real, string}, but "
"gets a list '" + argstr + "'.");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
ErrorReporter::ReportError("Operator theRange expects an argument "
"list of length 4, but gets a list '" + argstr + "'.");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
ListExpr TranslateAppendTM(ListExpr args){
if(nl->ListLength(args)!=3){
ErrorReporter::ReportError("two arguments expected");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
if(nl->IsEqual(nl->First(args),MPoint::BasicType()) &&
nl->IsEqual(nl->Second(args),MPoint::BasicType()) &&
nl->IsEqual(nl->Third(args),Duration::BasicType())){
return nl->SymbolAtom(MPoint::BasicType());
}
ErrorReporter::ReportError("mpoint x mpoint x duration expected");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
ListExpr ReverseTM(ListExpr args){
if(nl->ListLength(args)!=1){
ErrorReporter::ReportError("1 argument expected");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
if(nl->IsEqual(nl->First(args),MPoint::BasicType())){
return nl->SymbolAtom(MPoint::BasicType());
}
ErrorReporter::ReportError("mpoint expected");
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.1.20 TranslateAppendS
This operator consumes a stream of tuples having an attribute
x of type mpoint. The attribute name must be given in the second
argument. As third argument, a duration is given which determines
a break between the two movements.
*/
ListExpr TranslateAppendSTM(ListExpr args){
int len = nl->ListLength(args);
if(len != 3 ){
ErrorReporter::ReportError("three arguments expected");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
// check the third argument to be of type duration
if(!nl->IsEqual(nl->Third(args),Duration::BasicType())){
ErrorReporter::ReportError("the third argument has to be a duration");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
// extract the attribute name
ListExpr attrlist = nl->Second(args);
if(nl->AtomType(attrlist)!=SymbolType){
ErrorReporter::ReportError("the second argument has to be a symbol");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
std::string a1 = nl->SymbolValue(attrlist);
int a1index = -1;
// search for attrname in stream definition
ListExpr stype = nl->First(args);
if(nl->AtomType(stype)!=NoAtom){
ErrorReporter::ReportError("stream(tuple(...))"
" expected as the first argument");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
if((nl->ListLength(stype)!=2) ||
(!nl->IsEqual(nl->First(stype),Symbol::STREAM() ))){
ErrorReporter::ReportError("stream(tuple(...))"
" expected as the first argument");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
ListExpr ttype = nl->Second(stype);
if((nl->ListLength(ttype)!=2) ||
(!nl->IsEqual(nl->First(ttype),Tuple::BasicType() ))){
ErrorReporter::ReportError("stream(tuple(...))"
" expected as the first argument");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
ListExpr attributes = nl->Second(ttype);
if(nl->AtomType(attributes)!=NoAtom){
ErrorReporter::ReportError("invalid tuple type");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
int pos = 0;
while(!nl->IsEmpty(attributes)){
ListExpr attr = nl->First(attributes);
if( (nl->AtomType(attr)!=NoAtom) ||
(nl->ListLength(attr)!=2)){
ErrorReporter::ReportError("invalid tuple type");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
ListExpr anl = nl->First(attr);
ListExpr atl = nl->Second(attr);
if( (nl->AtomType(anl)!=SymbolType) ||
(nl->AtomType(atl)!=SymbolType)){
ErrorReporter::ReportError("invalid tuple type");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
std::string aname = nl->SymbolValue(anl);
if(aname==a1){
if(a1index>=0){
ErrorReporter::ReportError("attr name occurs twice");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
if(!nl->IsEqual(atl,MPoint::BasicType())){
ErrorReporter::ReportError("the attribute"
" has to be of type mpoint");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
a1index = pos;
}
pos++;
attributes = nl->Rest(attributes);
}
if(a1index<0){
ErrorReporter::ReportError("first attr name does"
" not occur in the typle");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
// all is correct
ListExpr ind = nl->OneElemList(nl->IntAtom(a1index));
return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()),
ind,
nl->SymbolAtom(MPoint::BasicType()));
}
/*
~SampleMPointTypeMap~
This is the type mapping of the ~samplempoint~ operator.
*/
ListExpr SampleMPointTypeMap(ListExpr args){
int len = nl->ListLength(args);
if(len!=2 && len!=3 && len!=4){
ErrorReporter::ReportError("two up to four arguments required");
return nl->TypeError();
}
if(!nl->IsEqual(nl->First(args),MPoint::BasicType()) ||
!nl->IsEqual(nl->Second(args),Duration::BasicType())){
ErrorReporter::ReportError(" mpoint x durationi"
" [ x bool [x bool]] expected");
return nl->TypeError();
}
if(len==3 && !nl->IsEqual(nl->Third(args),CcBool::BasicType())){
ErrorReporter::ReportError(" mpoint x duration "
"[ x bool [ x bool]] expected");
return nl->TypeError();
}
if(len==4 && !nl->IsEqual(nl->Fourth(args),CcBool::BasicType())){
ErrorReporter::ReportError(" mpoint x duration "
"[ x bool [ x bool]] expected");
return nl->TypeError();
}
return nl->SymbolAtom(MPoint::BasicType());
}
/*
~DistanceAvgTypeMap~
This type mapping is applied by the ~distanceAvg~ operator.
*/
ListExpr DistanceAvgTypeMap(ListExpr args) {
if (!nl->HasLength(args, 2) && !nl->HasLength(args, 3) &&
!nl->HasLength(args, 4)) {
return listutils::typeError("two, three, or four arguments expected");
}
if (!MPoint::checkType(nl->First(args))
|| !MPoint::checkType(nl->Second(args))) {
return listutils::typeError("first two arguments must have type mpoint");
}
if (nl->HasLength(args, 4)) {
if (!Duration::checkType(nl->Third(args))) {
return listutils::typeError("third arg must be a duration");
}
if (!Geoid::checkType(nl->Fourth(args))) {
return listutils::typeError("fourth arg must be a geoid");
}
}
if (nl->HasLength(args, 3)) {
if (!Geoid::checkType(nl->Third(args)) &&
!Duration::checkType(nl->Third(args))) {
return listutils::typeError("third arg must be a geoid or a duration");
}
}
return nl->SymbolAtom(CcReal::BasicType());
}
/*
~DistanceAvgLBUBTypeMap~
This function is applied by the ~distanceAvgLB~ and ~distanceAvgUB~ operators.
*/
ListExpr DistanceAvgLBUBTypeMap(ListExpr args) {
if (!nl->HasLength(args, 2) && !nl->HasLength(args, 3) &&
!nl->HasLength(args, 4)) {
return listutils::typeError("two, three, or four arguments expected");
}
if ((!CUPoint::checkType(nl->First(args))
|| !CUPoint::checkType(nl->Second(args))) &&
(!CMPoint::checkType(nl->First(args))
|| !CMPoint::checkType(nl->Second(args)))) {
return listutils::typeError("both args must have type cupoint or cmpoint");
}
if (nl->HasLength(args, 4)) {
if (!Duration::checkType(nl->Third(args))) {
return listutils::typeError("third arg must be a duration");
}
if (!Geoid::checkType(nl->Fourth(args))) {
return listutils::typeError("fourth arg must be a geoid");
}
}
if (nl->HasLength(args, 3)) {
if (!Geoid::checkType(nl->Third(args)) &&
!Duration::checkType(nl->Third(args))) {
return listutils::typeError("third arg must be a geoid or a duration");
}
}
return nl->SymbolAtom(CcReal::BasicType());
}
/*
~GPSTypeMap~
The GPS operator works very similar to the SampleMPoint operator.
The main differnce is the type of the result. The GPS operator
produces a stream of tuples consisting of the attributes Time
of type instant and Position of the point. Thus the gps operator can be
used to export data coming from an mpoint to a relation. In contrast to
the SampleMPoint operator, the gps operator does not support the keeping
of the final endpoint.
*/
ListExpr GPSTypeMap(ListExpr args){
int len = nl->ListLength(args);
if(len!=2){
ErrorReporter::ReportError("two arguments required");
return nl->TypeError();
}
if(!nl->IsEqual(nl->First(args),MPoint::BasicType()) ||
!nl->IsEqual(nl->Second(args),Duration::BasicType())){
ErrorReporter::ReportError(" mpoint x duration expected");
return nl->TypeError();
}
return nl->TwoElemList(
nl->SymbolAtom(Symbol::STREAM()),
nl->TwoElemList(
nl->SymbolAtom(Tuple::BasicType()),
nl->TwoElemList(
nl->TwoElemList(
nl->SymbolAtom("Time"),
nl->SymbolAtom(Instant::BasicType())
),
nl->TwoElemList(
nl->SymbolAtom("Position"),
nl->SymbolAtom(Point::BasicType())
)
)
)
);
}
/*
~DisturbTypeMap~
*/
ListExpr DisturbTypeMap(ListExpr args){
int len=nl->ListLength(args);
if(len!=3){
ErrorReporter::ReportError("invalid number of arguments");
return nl->TypeError();
}
if(nl->IsEqual(nl->First(args),MPoint::BasicType()) &&
nl->IsEqual(nl->Second(args),CcReal::BasicType()) &&
nl->IsEqual(nl->Third(args),CcReal::BasicType())){
return nl->SymbolAtom(MPoint::BasicType());
}
ErrorReporter::ReportError("mpoint x real x real expected");
return nl->TypeError();
}
/*
~LengthTypeMap~ (also for operator ~avg\_speed~)
---- mpoint [ x string ] --> real
----
*/
ListExpr LengthTypeMap(ListExpr args){
std::string errmsg = "Expected (mpoint) or (mpoint x string).";
int noargs = nl->ListLength(args);
if((noargs<1) || (noargs>2)){
return listutils::typeError(errmsg);
}
if(!listutils::isSymbol(nl->First(args),MPoint::BasicType())){
return listutils::typeError(errmsg);
}
if( (noargs==2)
&& (!listutils::isSymbol(nl->Second(args),CcString::BasicType())) ){
return listutils::typeError(errmsg);
}
return nl->SymbolAtom(CcReal::BasicType());
}
/*
~TypeMapping mpoint x real -> mpoint ~
*/
ListExpr MPointRealTypeMapMPoint(ListExpr args){
std::string err = "mpoint x real expected";
if(nl->ListLength(args)!=2){
ErrorReporter::ReportError(err);
return nl->TypeError();
}
if(nl->IsEqual(nl->First(args),MPoint::BasicType()) &&
nl->IsEqual(nl->Second(args),CcReal::BasicType())){
return nl->SymbolAtom(MPoint::BasicType());
}
ErrorReporter::ReportError(err);
return nl->TypeError();
}
/*
~TypeMapping~ for operator equalizeU
Signature is mpoint x real [ x bool] -> mpoint
*/
ListExpr EqualizeUTM(ListExpr args){
std::string err = "mpoint x real [x bool] expected";
int len = nl->ListLength(args);
if((len!=2) && (len!=3)){
ErrorReporter::ReportError(err);
return nl->TypeError();
}
if(nl->IsEqual(nl->First(args),MPoint::BasicType()) &&
nl->IsEqual(nl->Second(args),CcReal::BasicType())){
if(len==2){
return nl->SymbolAtom(MPoint::BasicType());
} else { // len ==3
if(nl->IsEqual(nl->Third(args),CcBool::BasicType())){
return nl->SymbolAtom(MPoint::BasicType());
}
}
}
ErrorReporter::ReportError(err);
return nl->TypeError();
}
ListExpr MIntHatTypeMap(ListExpr args){
std::string err = "mint expected";
if(nl->ListLength(args)!=1){
ErrorReporter::ReportError(err);
return nl->TypeError();
}
if(nl->IsEqual(nl->First(args),MInt::BasicType()))
return nl->SymbolAtom(MInt::BasicType());
ErrorReporter::ReportError(err);
return nl->TypeError();
}
/*
~RestrictTypeMap~
signatures:
mint -> mint
mint x int -> mint
*/
ListExpr restrictTM(ListExpr args){
std::string err = "mint [x int] expected";
int len = nl->ListLength(args);
if(len!=1 && len!=2){
ErrorReporter::ReportError(err);
return nl->TypeError();
}
if(!nl->IsEqual(nl->First(args),MInt::BasicType())){
ErrorReporter::ReportError(err);
return nl->TypeError();
}
if(len==2 && !nl->IsEqual(nl->Second(args),CcInt::BasicType())){
ErrorReporter::ReportError(err);
return nl->TypeError();
}
return nl->SymbolAtom(MInt::BasicType());
}
/*
~SpeedUpTypeMap~
signatures:
mpoint x real -> mpoint
*/
ListExpr SpeedUpTypeMap(ListExpr args){
std::string err = "mpoint x real expected";
int len = nl->ListLength(args);
if(len!=2){
ErrorReporter::ReportError(err);
return nl->TypeError();
}
if(nl->IsEqual(nl->First(args),MPoint::BasicType()) &&
nl->IsEqual(nl->Second(args),CcReal::BasicType())){
return nl->SymbolAtom(MPoint::BasicType());
}
ErrorReporter::ReportError(err);
return nl->TypeError();
}
/*
~SubMoveTypeMap~
signatures:
mpoint -> mpoint
*/
ListExpr SubMoveTypeMap(ListExpr args){
std::string err = "mpoint x real expected";
int len = nl->ListLength(args);
if(len!=2){
ErrorReporter::ReportError(err);
return nl->TypeError();
}
if(nl->IsEqual(nl->First(args),MPoint::BasicType()) &&
nl->IsEqual(nl->Second(args),CcReal::BasicType())){
return nl->SymbolAtom(MPoint::BasicType());
}
ErrorReporter::ReportError(err);
return nl->TypeError();
}
/*
~Mp2OneMpTypeMap~
signatures:
mpoint -> mpoint
*/
ListExpr Mp2OneMpTypeMap(ListExpr args){
std::string err = "mpoint expected";
int len = nl->ListLength(args);
if(len!=3){
ErrorReporter::ReportError(err);
return nl->TypeError();
}
if(nl->IsEqual(nl->First(args),MPoint::BasicType()) &&
nl->IsEqual(nl->Second(args),Instant::BasicType()) &&
nl->IsEqual(nl->Third(args),Instant::BasicType())){
return nl->SymbolAtom(MPoint::BasicType());
}
ErrorReporter::ReportError(err);
return nl->TypeError();
}
/*
~P2MpTypeMap~
signatures:
point -> mpoint
*/
ListExpr P2MpTypeMap(ListExpr args){
std::string err = "point x instant x instant x int expected";
int len = nl->ListLength(args);
if(len!=4){
ErrorReporter::ReportError(err);
return nl->TypeError();
}
if(nl->IsEqual(nl->First(args),Point::BasicType()) &&
nl->IsEqual(nl->Second(args),Instant::BasicType()) &&
nl->IsEqual(nl->Third(args),Instant::BasicType()) &&
nl->IsEqual(nl->Fourth(args),CcInt::BasicType())){
return nl->SymbolAtom(MPoint::BasicType());
}
ErrorReporter::ReportError(err);
return nl->TypeError();
}
/*
~DistanceTraversedTypeMap~
signatures:
mpoint [ x geoid ]-> mreal
*/
ListExpr DistanceTraversedOperatorTypeMapping( ListExpr args )
{
int len = nl->ListLength(args);
if( (len<1) || (len>2) ){
return listutils::typeError("Expected mpoint [x geoid].");
}
if(!listutils::isSymbol(nl->First(args),MPoint::BasicType())){
return listutils::typeError("Expected mpoint [x geoid].");
}
if((len==2) && (!listutils::isSymbol(nl->Second(args),Geoid::BasicType()))){
return listutils::typeError("Expected mpoint [x geoid].");
}
/*
Not implemented:
1- Check the the trajectory is continuos on the spatial space
(necessary to compute the distance traversed)
*/
return (nl->SymbolAtom(MReal::BasicType()));
}
/*
1.1.1 Type Mapping Function for Operator ~turns~
The signature is:
----
mpoint x real x real [ x duration] [ x bool] [ x geoid]
--> stream(tuple((TimeOld instant)
(TimeNew instant)
(PosOld point)
(PosNew point)
(HeadingOld real)
(HeadingNew real)
(HeadingDiff real)))
@int
----
The appended int argument encodes the usage of optional parameters as a sum of
1: duration present, 2: bool present, 4: geoid present. Valid values are 0-7;
*/
ListExpr TurnsOperatorTypeMapping( ListExpr args ){
int noargs = nl->ListLength(args);
bool durationPassed = false;
bool boolPassed = false;
bool geoidPassed = false;
if( (noargs < 3) || (noargs > 6) ){
return listutils::typeError("Expecting 3, 4, 5 or 6 arguments.");
}
if( !listutils::isSymbol(nl->First(args),MPoint::BasicType()) ){
return listutils::typeError("Expecting 'mpoint' as 1st argument.");
}
if( !listutils::isSymbol(nl->Second(args),CcReal::BasicType()) ){
return listutils::typeError("Expecting 'real' as 2nd argument.");
}
if( !listutils::isSymbol(nl->Third(args),CcReal::BasicType()) ){
return listutils::typeError("Expecting 'real' as 3rd argument.");
}
if( noargs>=4 ){ // 4th argument (duratiopn OR bool OR geoid)
if( listutils::isSymbol(nl->Fourth(args),Duration::BasicType()) ){
durationPassed = true;
} else if( listutils::isSymbol(nl->Fourth(args),CcBool::BasicType()) ){
boolPassed = true;
} else if( listutils::isSymbol(nl->Fourth(args),Geoid::BasicType()) ){
geoidPassed = true;
} else {
return listutils::typeError("Expecting T in {duration, bool, geoid} as "
"4th argument.");
}
}
if( noargs >= 5 ){ // 5th argument (bool or geoid)
if( listutils::isSymbol(nl->Fifth(args),CcBool::BasicType()) ){
boolPassed = true;
} else if( listutils::isSymbol(nl->Fifth(args),Geoid::BasicType()) ){
geoidPassed = true;
} else {
return listutils::typeError("Expecting T in {bool, geoid} as "
"5th argument.");
}
if( nl->Equal(nl->Fourth(args),nl->Fifth(args)) ){
return listutils::typeError("Expecting different types for 4th and 5th "
"argument.");
}
}
if( noargs == 6 ){ // 6th argument (geoid)
if( listutils::isSymbol(nl->Sixth(args),Geoid::BasicType()) ){
geoidPassed = true;
} else {
return listutils::typeError("Expecting geoid as 6th argument.");
}
if( nl->Equal(nl->Fourth(args),nl->Sixth(args)) ){
return listutils::typeError("Expecting different types for 4th and 6th "
"argument.");
}
if( nl->Equal(nl->Fifth(args),nl->Sixth(args)) ){
return listutils::typeError("Expecting different types for 5th and 6th "
"argument.");
}
}
int paramcode = 0;
paramcode += durationPassed?1:0;
paramcode += boolPassed?2:0;
paramcode += geoidPassed?4:0;
NList resTupleType =NList(NList("TimeOld"),
NList(Instant::BasicType())).enclose();
resTupleType.append(NList(NList("TimeNew"),NList(Instant::BasicType())));
resTupleType.append(NList(NList("PosOld"),NList(Point::BasicType())));
resTupleType.append(NList(NList("PosNew"),NList(Point::BasicType())));
resTupleType.append(NList(NList("HeadingOld"),NList(CcReal::BasicType())));
resTupleType.append(NList(NList("HeadingNew"),NList(CcReal::BasicType())));
resTupleType.append(NList(NList("HeadingDiff"),NList(CcReal::BasicType())));
NList resType =
NList(NList(Symbol::STREAM()),
NList(NList(Tuple::BasicType()),resTupleType));
return nl->ThreeElemList( nl->SymbolAtom(Symbol::APPEND()),
nl->OneElemList(nl->IntAtom(paramcode)),
resType.listExpr());
}
/*
Type mapping function ~MappingTimeShift~
It is for the operator ~timeshift~.
*/
ListExpr
MappingTimeShiftTM( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( nl->IsEqual( arg2, Duration::BasicType() ) )
{
if( nl->IsEqual( arg1, MBool::BasicType() ) )
return nl->SymbolAtom( MBool::BasicType() );
if( nl->IsEqual( arg1, MInt::BasicType() ) )
return nl->SymbolAtom( MInt::BasicType() );
if( nl->IsEqual( arg1, MReal::BasicType() ) )
return nl->SymbolAtom( MReal::BasicType() );
if( nl->IsEqual( arg1, MPoint::BasicType() ) )
return nl->SymbolAtom( MPoint::BasicType() );
}
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
1.1.1 Type Mapping Function for Operator ~gridcellevents~
The signature is:
----
{mpoint|upoint} x real x real x real x real x int --> stream(tuple(
(Cell int)
(TimeEntered instant)
(TimeLeft instant)
(CellPrevious int)
(CellNext int)))
{mpoint|upoint} x cellgrid2d --> stream(tuple(
(Cell int)
(TimeEntered instant)
(TimeLeft instant)
(CellPrevious int)
(CellNext int)))
----
*/
ListExpr GridCellEventsTypeMapping (ListExpr args)
{
NList l(args);
int len = l.length();
NList resTupleType =NList(NList("Cell"),NList(CcInt::BasicType())).enclose();
resTupleType.append(NList(NList("TimeEntered"),NList(Instant::BasicType())));
resTupleType.append(NList(NList("TimeLeft"),NList(Instant::BasicType())));
resTupleType.append(NList(NList("CellPrevious"),NList(CcInt::BasicType())));
resTupleType.append(NList(NList("CellNext"),NList(CcInt::BasicType())));
NList resType =
NList(NList(Symbol::STREAM()),NList(NList(Tuple::BasicType()),resTupleType));
if(len==2){ // {upoint, mpoint} x cellgrid2d
if(!listutils::isSymbol(nl->Second(args),CellGrid2D::BasicType())){
return listutils::typeError("second argument must be a cellgrid2d");
}
if(!listutils::isSymbol(nl->First(args), UPoint::BasicType()) &&
!listutils::isSymbol(nl->First(args), MPoint::BasicType())){
return listutils::typeError("first argument must be of type"
+UPoint::BasicType()+" or "+MPoint::BasicType());
}
return resType.listExpr();
}
if( (len != 6) ){
return l.typeError("Operator 'gridcellevents' expects 6 arguments.");
}
if( !(l.elem(1).isSymbol(MPoint::BasicType()))
&& !(l.elem(1).isSymbol(UPoint::BasicType())) ){
return l.typeError("Operator 'gridcellevents' expects an "
+UPoint::BasicType()+" or "
+MPoint::BasicType()+" as 1st argument.");
}
if( !(l.elem(2).isSymbol(CcReal::BasicType())) ){
return l.typeError("Operator 'gridcellevents' expects a 'real' as 2nd "
"argument.");
}
if( !(l.elem(3).isSymbol(CcReal::BasicType())) ){
return l.typeError("Operator 'gridcellevents' expects a 'real' as 3rd "
"argument.");
}
if( !(l.elem(4).isSymbol(CcReal::BasicType())) ){
return l.typeError("Operator 'gridcellevents' expects a 'real' as 4th "
"argument.");
}
if( !(l.elem(5).isSymbol(CcReal::BasicType())) ){
return l.typeError("Operator 'gridcellevents' expects a 'real' as 5th "
"argument.");
}
if( !(l.elem(6).isSymbol(CcInt::BasicType())) ){
return l.typeError("Operator 'gridcellevents' expects an 'int' as 6th "
"argument.");
}
return resType.listExpr();
}
/*
Type mapping function ~SquaredDistance~
It is for the operator ~squareddistance~.
*/
ListExpr
SquaredDistanceTypeMap( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if((nl->IsEqual( arg1, MPoint::BasicType() ) &&
nl->IsEqual( arg2, Point::BasicType() ) ) ||
(nl->IsEqual( arg1, Point::BasicType() ) &&
nl->IsEqual( arg2, MPoint::BasicType() ) ) ||
(nl->IsEqual( arg1, MPoint::BasicType() ) &&
nl->IsEqual( arg2, MPoint::BasicType() ) ))
return nl->SymbolAtom( MReal::BasicType() );
}
return nl->SymbolAtom( Symbol::TYPEERROR() );
}
/*
16.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.
16.2.1 Selection function ~RangeSimpleSelect~
Is used for the ~min~ and ~max~ operators.
*/
int
RangeSimpleSelect( ListExpr args )
{
ListExpr arg1 = nl->First( args );
if( nl->SymbolValue( arg1 ) == RInt::BasicType() )
return 0;
if( nl->SymbolValue( arg1 ) == RReal::BasicType() )
return 1;
if( nl->SymbolValue( arg1 ) == Periods::BasicType() )
return 2;
return -1; // This point should never be reached
}
/*
16.2.1 Selection function ~RangeDualSelect~
Is used for the ~intersects~, ~inside~, ~before~, ~intersection~, ~union~,
and ~minus~ operations.
*/
int
RangeDualSelect( ListExpr args )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( nl->SymbolValue( arg1 ) == RInt::BasicType()
&& nl->SymbolValue( arg2 ) == RInt::BasicType() )
return 0;
if( nl->SymbolValue( arg1 ) == RReal::BasicType()
&& nl->SymbolValue( arg2 ) == RReal::BasicType() )
return 1;
if( nl->SymbolValue( arg1 ) == Periods::BasicType()
&& nl->SymbolValue( arg2 ) == Periods::BasicType() )
return 2;
if( nl->SymbolValue( arg1 ) == CcInt::BasicType()
&& nl->SymbolValue( arg2 ) == RInt::BasicType() )
return 3;
if( nl->SymbolValue( arg1 ) == CcReal::BasicType()
&& nl->SymbolValue( arg2 ) == RReal::BasicType() )
return 4;
if( nl->SymbolValue( arg1 ) == Instant::BasicType()
&& nl->SymbolValue( arg2 ) == Periods::BasicType() )
return 5;
if( nl->SymbolValue( arg1 ) == RInt::BasicType()
&& nl->SymbolValue( arg2 ) == CcInt::BasicType() )
return 6;
if( nl->SymbolValue( arg1 ) == RReal::BasicType()
&& nl->SymbolValue( arg2 ) == CcReal::BasicType() )
return 7;
if( nl->SymbolValue( arg1 ) == Periods::BasicType()
&& nl->SymbolValue( arg2 ) == Instant::BasicType() )
return 8;
return -1; // This point should never be reached
}
/*
16.2.2 Selection function ~TemporalSimpleSelect~
Is used for the ~isempty~ operation.
*/
int
TemporalSimpleSelect( ListExpr args )
{
ListExpr arg1 = nl->First( args );
if( nl->SymbolValue( arg1 ) == Instant::BasicType() )
return 0;
if( nl->SymbolValue( arg1 ) == RInt::BasicType() )
return 1;
if( nl->SymbolValue( arg1 ) == RReal::BasicType() )
return 2;
if( nl->SymbolValue( arg1 ) == Periods::BasicType() )
return 3;
if( nl->SymbolValue( arg1 ) == UBool::BasicType() )
return 4;
if( nl->SymbolValue( arg1 ) == UInt::BasicType() )
return 5;
if( nl->SymbolValue( arg1 ) == UReal::BasicType() )
return 6;
if( nl->SymbolValue( arg1 ) == UPoint::BasicType() )
return 7;
// if( nl->SymbolValue( arg1 ) == MBool::BasicType() )
// return 8;
// if( nl->SymbolValue( arg1 ) == MInt::BasicType() )
// return 9;
// if( nl->SymbolValue( arg1 ) == MReal::BasicType() )
// return 10;
// if( nl->SymbolValue( arg1 ) == MPoint::BasicType() )
// return 11;
if( nl->SymbolValue( arg1 ) == IBool::BasicType() )
return 8;
if( nl->SymbolValue( arg1 ) == IInt::BasicType() )
return 9;
if( nl->SymbolValue( arg1 ) == IReal::BasicType() )
return 10;
if( nl->SymbolValue( arg1 ) == IPoint::BasicType() )
return 11;
return (-1); // This point should never be reached
}
/*
16.2.2 Selection function ~TemporalDualSelect~
Is used for the ~=~, and ~\#~ operation.
*/
int
TemporalDualSelect( ListExpr args )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( nl->SymbolValue( arg1 ) == Instant::BasicType() &&
nl->SymbolValue( arg2 ) == Instant::BasicType() )
return 0;
if( nl->SymbolValue( arg1 ) == RInt::BasicType()
&& nl->SymbolValue( arg2 ) == RInt::BasicType() )
return 1;
if( nl->SymbolValue( arg1 ) == RReal::BasicType()
&& nl->SymbolValue( arg2 ) == RReal::BasicType() )
return 2;
if( nl->SymbolValue( arg1 ) == Periods::BasicType() &&
nl->SymbolValue( arg2 ) == Periods::BasicType() )
return 3;
if( nl->SymbolValue( arg1 ) == IBool::BasicType() &&
nl->SymbolValue( arg2 ) == IBool::BasicType() )
return 4;
if( nl->SymbolValue( arg1 ) == IInt::BasicType()
&& nl->SymbolValue( arg2 ) == IInt::BasicType() )
return 5;
if( nl->SymbolValue( arg1 ) == IReal::BasicType()
&& nl->SymbolValue( arg2 ) == IReal::BasicType() )
return 6;
if( nl->SymbolValue( arg1 ) == IPoint::BasicType() &&
nl->SymbolValue( arg2 ) == IPoint::BasicType() )
return 7;
return -1; // This point should never be reached
}
int
TemporalDualSelect2( ListExpr args )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( nl->SymbolValue( arg1 ) == MBool::BasicType()
&& nl->SymbolValue( arg2 ) == MBool::BasicType() )
return 0;
if( nl->SymbolValue( arg1 ) == MInt::BasicType()
&& nl->SymbolValue( arg2 ) == MInt::BasicType() )
return 1;
if( nl->SymbolValue( arg1 ) == MReal::BasicType()
&& nl->SymbolValue( arg2 ) == MReal::BasicType() )
return 2;
if( nl->SymbolValue( arg1 ) == MPoint::BasicType() && nl->SymbolValue
( arg2 ) == MPoint::BasicType() )
return 3;
return -1; // This point should never be reached
}
/*
16.2.2 Selection function ~TemporalSetValueSelect~
Is used for the ~no\_components~ operation.
*/
int
TemporalSetValueSelect( ListExpr args )
{
ListExpr arg1 = nl->First( args );
if( nl->SymbolValue( arg1 ) == RInt::BasicType() )
return 0;
if( nl->SymbolValue( arg1 ) == RReal::BasicType() )
return 1;
if( nl->SymbolValue( arg1 ) == Periods::BasicType() )
return 2;
if( nl->SymbolValue( arg1 ) == MBool::BasicType() )
return 3;
if( nl->SymbolValue( arg1 ) == MInt::BasicType() )
return 4;
if( nl->SymbolValue( arg1 ) == MReal::BasicType() )
return 5;
if( nl->SymbolValue( arg1 ) == MPoint::BasicType() )
return 6;
if (nl->SymbolValue(arg1) == CMPoint::BasicType()) {
return 7;
}
return (-1); // This point should never be reached
}
/*
16.2.3 Selection function ~IntimeSimpleSelect~
Is used for the ~inst~ and ~val~ operations.
*/
int
IntimeSimpleSelect( ListExpr args )
{
ListExpr arg1 = nl->First( args );
if( nl->SymbolValue( arg1 ) == IBool::BasicType() )
return 0;
if( nl->SymbolValue( arg1 ) == IInt::BasicType() )
return 1;
if( nl->SymbolValue( arg1 ) == IReal::BasicType() )
return 2;
if( nl->SymbolValue( arg1 ) == IPoint::BasicType() )
return 3;
if (nl->SymbolValue(arg1) == "cipoint") {
return 4;
}
return -1; // This point should never be reached
}
/*
16.2.3 Selection function ~UIntimeSimpleSelect~
Is used for the ~inst~ and ~val~ operations.
*/
int
UIntimeSimpleSelect( ListExpr args )
{
ListExpr arg1 = nl->First( args );
if( nl->SymbolValue( arg1 ) == UInt::BasicType() )
return 0;
return -1; // This point should never be reached
}
/*
16.2.3 Selection function ~MovingSimpleSelect~
Is used for the ~deftime~, ~initial~, ~final~, ~inst~, ~val~, ~atinstant~,
~atperiods~, ~getposition~ operations.
*/
int
MovingSimpleSelect( ListExpr args )
{
ListExpr arg1 = nl->First( args );
if( nl->SymbolValue( arg1 ) == MBool::BasicType() )
return 0;
if( nl->SymbolValue( arg1 ) == MInt::BasicType() )
return 1;
if( nl->SymbolValue( arg1 ) == MReal::BasicType() )
return 2;
if( nl->SymbolValue( arg1 ) == MPoint::BasicType() )
return 3;
if (nl->SymbolValue(arg1) == CMPoint::BasicType()) {
return 4;
}
return -1; // This point should never be reached
}
/*
16.2.3 Selection function ~MovingInstantPeriodsSelect~
Is used for the ~present~ operations.
*/
int
MovingInstantPeriodsSelect( ListExpr args )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( nl->SymbolValue( arg1 ) == MBool::BasicType()
&& nl->SymbolValue( arg2 ) == Instant::BasicType() )
return 0;
if( nl->SymbolValue( arg1 ) == MInt::BasicType()
&& nl->SymbolValue( arg2 ) == Instant::BasicType() )
return 1;
if( nl->SymbolValue( arg1 ) == MReal::BasicType()
&& nl->SymbolValue( arg2 ) == Instant::BasicType() )
return 2;
if( nl->SymbolValue( arg1 ) == MPoint::BasicType()
&& nl->SymbolValue( arg2 ) == Instant::BasicType() )
return 3;
if( nl->SymbolValue( arg1 ) == MBool::BasicType()
&& nl->SymbolValue( arg2 ) == Periods::BasicType() )
return 4;
if( nl->SymbolValue( arg1 ) == MInt::BasicType()
&& nl->SymbolValue( arg2 ) == Periods::BasicType() )
return 5;
if( nl->SymbolValue( arg1 ) == MReal::BasicType()
&& nl->SymbolValue( arg2 ) == Periods::BasicType() )
return 6;
if( nl->SymbolValue( arg1 ) == MPoint::BasicType()
&& nl->SymbolValue( arg2 ) == Periods::BasicType() )
return 7;
return -1; // This point should never be reached
}
/*
16.2.2 Selection function ~MovingBaseSelect~
Is used for the ~passes~ operations.
*/
int
MovingBaseSelect( ListExpr args )
{
ListExpr arg1 = nl->First( args ),
arg2 = nl->Second( args );
if( nl->SymbolValue( arg1 ) == MBool::BasicType() &&
nl->SymbolValue( arg2 ) == CcBool::BasicType() )
return 0;
if( nl->SymbolValue( arg1 ) == MInt::BasicType() &&
nl->SymbolValue( arg2 ) == CcInt::BasicType() )
return 1;
if( nl->SymbolValue( arg1 ) == MReal::BasicType() &&
nl->SymbolValue( arg2 ) == CcReal::BasicType() )
return 2;
if( nl->SymbolValue( arg1 ) == MPoint::BasicType() &&
nl->SymbolValue( arg2 ) == Point::BasicType() )
return 3;
if( nl->SymbolValue( arg1 ) == MPoint::BasicType() &&
nl->SymbolValue( arg2 ) == Region::BasicType() )
return 4;
if( nl->SymbolValue( arg1 ) == MPoint::BasicType() &&
nl->SymbolValue( arg2 ) == Rectangle<2>::BasicType() )
return 5;
return -1; // This point should never be reached
}
/*
Selection function for the box3d operator
*/
int Box3dSelect(ListExpr args){
int len = nl->ListLength(args);
if(len==1){
ListExpr arg = nl->First(args);
if(nl->IsEqual(arg,Rectangle<2>::BasicType()))
return 0;
if(nl->IsEqual(arg,Instant::BasicType()))
return 1;
if(nl->IsEqual(arg,Periods::BasicType()))
return 3;
}
if(len==2){
if(nl->IsEqual(nl->First(args),Rectangle<2>::BasicType())){
ListExpr arg2 = nl->Second(args);
if(nl->IsEqual(arg2,Instant::BasicType()))
return 2;
if(nl->IsEqual(arg2,Periods::BasicType()))
return 4;
}
}
return -1; // when this occurs, the type mapping is not correct
}
/*
Selection function for the getPosition operator
*/
int TemporalGetPositionSelect(ListExpr args) {
if (MBool::checkType(nl->First(args))) return 0;
if (MInt::checkType(nl->First(args))) return 1;
if (MReal::checkType(nl->First(args))) return 2;
if (MPoint::checkType(nl->First(args))) return 3;
if (MString::checkType(nl->First(args))) return 4;
if (MRegion::checkType(nl->First(args))) return 5;
if (CMPoint::checkType(nl->First(args))) return 6;
return -1;
}
/*
Selection function for the bbox operator
*/
int TemporalBBoxSelect( ListExpr args )
{
ListExpr arg1 = nl->First( args );
if( nl->SymbolValue( arg1 ) == UPoint::BasicType() )
return 0;
if( nl->SymbolValue( arg1 ) == MPoint::BasicType() )
return 1;
if( nl->SymbolValue( arg1 ) == IPoint::BasicType() )
return 2;
if( nl->SymbolValue( arg1 ) == Periods::BasicType() )
return 3;
if( nl->SymbolValue( arg1 ) == Instant::BasicType() )
return 4;
if (CUPoint::checkType(arg1)) {
return 5;
}
if (CMPoint::checkType(arg1)) {
return 6;
}
return -1; // This point should never be reached
}
/*
Selection function for the bbox operator
*/
int TemporalMBRangeSelect( ListExpr args )
{
ListExpr arg1 = nl->First( args );
if( nl->SymbolValue( arg1 ) == RInt::BasicType() )
return 0;
if( nl->SymbolValue( arg1 ) == RReal::BasicType() )
return 1;
if( nl->SymbolValue( arg1 ) == Periods::BasicType() )
return 2;
if( nl->SymbolValue( arg1 ) == RBool::BasicType() )
return 3;
if( nl->SymbolValue( arg1 ) == RString::BasicType() )
return 4;
return -1; // This point should never be reached
}
/*
Selection function for the bbox2d operator
*/
int TemporalBBox2dSelect( ListExpr args )
{
ListExpr arg1 = nl->First( args );
if( nl->SymbolValue( arg1 ) == UPoint::BasicType() )
return 0;
if( nl->SymbolValue( arg1 ) == MPoint::BasicType() )
return 1;
if( nl->SymbolValue( arg1 ) == IPoint::BasicType() )
return 2;
if (CUPoint::checkType(arg1)) {
return 3;
}
if (CMPoint::checkType(arg1)) {
return 4;
}
return -1; // This point should never be reached
}
/*
16.2.31 Selection function for ~box2d~
*/
int TemporalBox2dSelect( ListExpr args )
{
ListExpr arg1 = nl->First( args );
if( nl->SymbolValue( arg1 ) == Rectangle<2>::BasicType() )
return 0;
if( nl->SymbolValue( arg1 ) == Rectangle<3>::BasicType() )
return 1;
if( nl->SymbolValue( arg1 ) == Rectangle<4>::BasicType() )
return 2;
if( nl->SymbolValue( arg1 ) == Rectangle<8>::BasicType() )
return 3;
return -1; // This point should never be reached
}
/*
16.2.31 Selection function for extdeftime
*/
int ExtDeftimeSelect(ListExpr args){
// the selection is only dependend on the type of the
// first argument
ListExpr arg = nl->First(args);
if(nl->IsEqual(arg,MBool::BasicType()))
return 0;
if(nl->IsEqual(arg,MInt::BasicType()))
return 1;
return -1;
}
/*
16.2.32 Selection function for simplify
*/
int SimplifySelect(ListExpr args){
// Signatures are
// mpoint x real [x geoid] -> mpoint : 0
// mpoint x real x duration [x geoid] : 1
// mreal x real -> mreal : 2
if(MReal::checkType(nl->First(args))) return 2;
if(nl->HasLength(args,2)) return 0;
if(Duration::checkType(nl->Third(args))) return 1;
return 0;
}
/*
16.2.32 Selection function for ~integrate~
*/
int IntegrateSelect(ListExpr args){
ListExpr arg = nl->First(args);
if(nl->IsEqual(arg,UReal::BasicType())){
return 0;
}
if(nl->IsEqual(arg,MReal::BasicType())){
return 1;
}
return -1; // should never occur
}
/*
16.2.32 Selection function for ~Linearize~
*/
int LinearizeSelect(ListExpr args){
ListExpr arg = nl->First(args);
if(nl->IsEqual(arg,UReal::BasicType())){
return 0;
}
if(nl->IsEqual(arg,MReal::BasicType())){
return 1;
}
return -1; // should never occur
}
/*
16.2.32 Selection function for ~Approximate~
*/
int ApproximateSelect(ListExpr args){
ListExpr res = TypeMapApproximate(args);
std::string type = nl->SymbolValue(nl->Third(res));
if(type == MPoint::BasicType()){
return 0;
} else if(type == MReal::BasicType()){
return 1;
} else if(type == MInt::BasicType()){
return 2;
} else if(type == MBool::BasicType()){
return 3;
} else if(type == MString::BasicType()){
return 4;
} else if(type == stj::MLabel::BasicType()){
return 5;
}
return -1;
}
/*
16.2.32 Selection function for ~min~ and ~max~
*/
int MinMaxSelect(ListExpr args){
ListExpr arg = nl->First(args);
if(nl->IsEqual(arg,UReal::BasicType())){
return 0;
}
if(nl->IsEqual(arg,MReal::BasicType())){
return 1;
}
if(nl->IsEqual(arg,MInt::BasicType())){
return 2;
}
return -1; // should never occur
}
/*
16.2.33 Selection function for ~theRange~
*/
int TemporalTheRangeSelect(ListExpr args)
{
ListExpr arg = nl->First(args);
if(nl->IsEqual(arg,Instant::BasicType()))
return 0;
if(nl->IsEqual(arg,CcInt::BasicType()))
return 1;
if(nl->IsEqual(arg,CcBool::BasicType()))
return 2;
if(nl->IsEqual(arg,CcReal::BasicType()))
return 3;
if(nl->IsEqual(arg,CcString::BasicType()))
return 4;
return -1; // should never occur
}
/*
16.2.34 Selection function for ~samplempoint~
*/
int SampleMPointSelect(ListExpr args){
int len = nl->ListLength(args);
if(len==2){
return 0;
} else if(len==3) {
return 1;
} else {
return 2;
}
}
/*
16.2.35 Selection Function for ~distanceAvg~
*/
int DistanceAvgSelect(ListExpr args) {
if (nl->ListLength(args) > 2) {
if (Duration::checkType(nl->Third(args))) {
return 1;
}
}
return 0;
}
/*
16.2.35 Selection Function for ~distanceAvgLB~ and ~distanceAvgUB~
*/
int DistanceAvgLBUBSelect(ListExpr args) {
int durationSpecified = 0;
if (nl->ListLength(args) > 2) {
if (Duration::checkType(nl->Third(args))) {
durationSpecified = 1;
}
}
if (CUPoint::checkType(nl->First(args))) {
return 0 + durationSpecified;
}
if (CMPoint::checkType(nl->First(args))) {
return 2 + durationSpecified;
}
return -1;
}
/*
16.2.35 SelectionFunction for ~restrict~
*/
int restrictSelect(ListExpr args){
return nl->ListLength(args)==1?0:1;
}
/*
16.2.36 Selection function for ~squareddistance~
*/
int SquaredDistanceSelect(ListExpr args){
if(nl->IsEqual(nl->First(args),MPoint::BasicType()) &&
nl->IsEqual(nl->Second(args),Point::BasicType())){
return 0;
}
if(nl->IsEqual(nl->First(args),Point::BasicType()) &&
nl->IsEqual(nl->Second(args),Point::BasicType())){
return 1;
}
if(nl->IsEqual(nl->First(args),MPoint::BasicType()) &&
nl->IsEqual(nl->Second(args),MPoint::BasicType())){
return 2;
}
return -1; // should never occur
}
/*
1.1.1 Selection Function for ~gridcellevents~
*/
int GridCellEventsSelect(ListExpr args){
if(nl->IsEqual(nl->First(args),UPoint::BasicType())){return 0;}
if(nl->IsEqual(nl->First(args),MPoint::BasicType())){return 1;}
return -1;
}
/*
16.3 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.
16.3.1 Value mapping functions of operator ~isempty~
*/
int InstantIsEmpty( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
((CcBool*)result.addr)->Set( true, !((Instant*)args[0].addr)->IsDefined() );
return 0;
}
template <class Range>
int RangeIsEmpty( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
((CcBool*)result.addr)->Set( true, ((Range*)args[0].addr)->IsEmpty() );
return 0;
}
template <class ValueType>
int IntimeIsEmpty( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
((CcBool*)result.addr)->
Set( true, !((Intime<ValueType> *)args[0].addr)->IsDefined() );
return 0;
}
/*
16.3.2 Value mapping for operator ~IntimeComparePredicates~
template parameter ~OPType~ gives the character of the operator:
----
0 =,
1 #,
2 <,
3 >,
4 <=,
5 >=-
----
*/
template <class ValueType, int OPType>
int IntimeComparePredicates( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
Intime<ValueType>* arg0 = (Intime<ValueType> *)args[0].addr;
Intime<ValueType>* arg1 = (Intime<ValueType> *)args[1].addr;
bool boolres = false;
if( arg0->IsDefined() && arg1->IsDefined() ){
int comparevalue = arg0->Compare((Attribute*) arg1);
switch (OPType){
case 0: // is_equal
boolres = (comparevalue == 0);
break;
case 1: // is_not_equal
boolres = (comparevalue != 0);
break;
case 2: // less_than
boolres = (comparevalue > 0);
break;
case 3: // bigger_than
boolres = (comparevalue < 0);
break;
case 4: // less_or_equal
boolres = (comparevalue >= 0);
break;
case 5: // bigger_or_equal
boolres = (comparevalue <= 0);
break;
default:
assert( false );
}
((CcBool*)result.addr)->Set( true, boolres );
} else {
((CcBool *)result.addr)->Set( false, false );
}
return 0;
}
/*
16.3.2 Value mapping functions of operator $=$ (~equal~)
*/
int
InstantEqual( Word* args, Word& result, int message, Word& local,
Supplier s )
{
result = qp->ResultStorage( s );
Instant* I1 = (Instant*) args[0].addr;
Instant* I2 = (Instant*) args[1].addr;
if( !I1->IsDefined() || !I2->IsDefined() ){
((CcBool *)result.addr)->Set( false, false ) ;
} else {
((CcBool *)result.addr)->Set( true, (I1->CompareTo(I2)==0));
}
return 0;
}
template <class Range>
int RangeEqual( Word* args, Word& result, int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
if( ((Range*)(args[0].addr))->IsDefined()
&& ((Range*)(args[1].addr))->IsDefined() ){
((CcBool*)result.addr)->
Set( true, *((Range*)args[0].addr) == *((Range*)args[1].addr) );
} else {
((CcBool*)result.addr)->Set( false, false );
}
return 0;
}
/*
16.3.3 Value mapping functions of operator $\#$ (~not equal~)
*/
int
InstantNotEqual( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
Instant* I1 = (Instant*) args[0].addr;
Instant* I2 = (Instant*) args[1].addr;
if( I1->IsDefined() && I2->IsDefined() ){
((CcBool *)result.addr)->Set( true, (I1->CompareTo(I2)!=0)) ;
} else {
((CcBool *)result.addr)->Set( false, false) ;
}
return 0;
}
template <class Range>
int RangeNotEqual( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
if( ((Range*)args[0].addr)->IsDefined()
&& ((Range*)args[1].addr)->IsDefined() ) {
((CcBool*)result.addr)->
Set( true, *((Range*)args[0].addr) != *((Range*)args[1].addr) );
} else {
((CcBool *)result.addr)->Set( false, false );
}
return 0;
}
/*
16.3.4 Value mapping functions of operator $<$
*/
int
InstantLess( Word* args, Word& result, int message, Word& local,
Supplier s )
{
result = qp->ResultStorage( s );
Instant* I1 = (Instant*) args[0].addr;
Instant* I2 = (Instant*) args[1].addr;
if(I1->IsDefined() && I2->IsDefined()){
((CcBool *)result.addr)->Set( true, (I1->CompareTo(I2)<0)) ;
} else {
((CcBool *)result.addr)->Set( false,false) ;
}
return 0;
}
/*
16.3.5 Value mapping functions of operator $<=$
*/
int
InstantLessEqual( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
Instant* I1 = (Instant*) args[0].addr;
Instant* I2 = (Instant*) args[1].addr;
if(I1->IsDefined() && I2->IsDefined()){
((CcBool *)result.addr)->Set( true, (I1->CompareTo(I2)<=0)) ;
} else {
((CcBool *)result.addr)->Set( false,false) ;
}
return 0;
}
/*
16.3.6 Value mapping functions of operator $>$
*/
int
InstantGreater( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
Instant* I1 = (Instant*) args[0].addr;
Instant* I2 = (Instant*) args[1].addr;
if(I1->IsDefined() && I2->IsDefined()){
((CcBool *)result.addr)->Set( true, (I1->CompareTo(I2)>0)) ;
} else {
((CcBool *)result.addr)->Set( false,false) ;
}
return 0;
}
/*
16.3.7 Value mapping functions of operator $>=$
*/
int
InstantGreaterEqual( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
Instant* I1 = (Instant*) args[0].addr;
Instant* I2 = (Instant*) args[1].addr;
if(I1->IsDefined() && I2->IsDefined()){
((CcBool *)result.addr)->Set( true, (I1->CompareTo(I2)>=0)) ;
} else {
((CcBool *)result.addr)->Set( false,false) ;
}
return 0;
}
/*
16.3.8 Value mapping functions of operator ~intersects~
*/
template <class Range>
int RangeIntersects( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
if( ((Range*)args[0].addr)->IsDefined()
&& ((Range*)args[1].addr)->IsDefined() ) {
((CcBool*)result.addr)->
Set(true,((Range*)args[0].addr)->Intersects(*((Range*)args[1].addr)));
} else {
((CcBool *)result.addr)->Set( false, false );
}
return 0;
}
/*
16.3.9 Value mapping functions of operator ~inside~
*/
template <class Range>
int RangeInside_rr( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
if( ((Range*)args[0].addr)->IsDefined()
&& ((Range*)args[1].addr)->IsDefined() ) {
((CcBool*)result.addr)->
Set( true, ((Range*)args[0].addr)->Inside( *((Range*)args[1].addr) ) );
} else {
((CcBool *)result.addr)->Set( false, false );
}
return 0;
}
template <class Alpha, class Range>
int RangeInside_ar( Word* args, Word& result, int message, Word& local,
Supplier s )
{
result = qp->ResultStorage( s );
if ( ((Alpha*)args[0].addr)->IsDefined() &&
((Range*)args[1].addr)->IsDefined() ){
((CcBool*)result.addr)->
Set( true, ((Range*)args[1].addr)->Contains(*((Alpha*)args[0].addr)) );
} else {
((CcBool *)result.addr)->Set( false, false );
}
return 0;
}
/*
16.3.10 Value mapping functions of operator ~before~
*/
template <class Range>
int RangeBefore_rr( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
if( ((Range*)args[0].addr)->IsDefined()
&& ((Range*)args[1].addr)->IsDefined() ) {
((CcBool*)result.addr)->
Set( true, ((Range*)args[0].addr)->Before( *((Range*)args[1].addr) ) );
} else {
((CcBool*)result.addr)->Set( false, false );
}
return 0;
}
template <class Alpha, class Range>
int RangeBefore_ar( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
if( ((Range*)args[1].addr)->IsDefined()
&& ((Alpha*)args[0].addr)->IsDefined() ) {
((CcBool*)result.addr)->
Set( true, ((Range*)args[1].addr)->After( *((Alpha*)args[0].addr) ) );
} else {
((CcBool *)result.addr)->Set( false, false );
}
return 0;
}
template <class Range, class Alpha>
int RangeBefore_ra( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
if( ((Range*)args[0].addr)->IsDefined()
&& ((Alpha*)args[1].addr)->IsDefined() ) {
((CcBool*)result.addr)->
Set( true, ((Range*)args[0].addr)->Before( *((Alpha*)args[1].addr) ) );
} else {
((CcBool *)result.addr)->Set( false, false );
}
return 0;
}
/*
16.3.11 Value mapping functions of operator ~intersection~
*/
template <class Range>
int RangeIntersection( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
((Range*)args[0].addr)->Intersection( *((Range*)args[1].addr),
(*(Range*)result.addr) );
return 0;
}
/*
16.3.12 Value mapping functions of operator ~union~
*/
template <class Range>
int RangeUnion( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
((Range*)args[0].addr)->Union( *((Range*)args[1].addr),
(*(Range*)result.addr) );
return 0;
}
/*
16.3.13 Value mapping functions of operator ~minus~
*/
template <class Range>
int RangeMinus( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
((Range*)args[0].addr)->Minus( *((Range*)args[1].addr),
(*(Range*)result.addr) );
return 0;
}
/*
16.3.14 Value mapping functions of operator ~min~
*/
template <class Range, class Alpha>
int RangeMinimum( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
if( ((Range*)args[0].addr)->IsEmpty() )
((Alpha*)result.addr)->SetDefined( false );
else
((Range*)args[0].addr)->Minimum( *(Alpha*)result.addr);
return 0;
}
/*
16.3.15 Value mapping functions of operator ~max~
*/
template <class Range, class Alpha>
int RangeMaximum( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
if( ((Range*)args[0].addr)->IsEmpty() )
((Alpha*)result.addr)->SetDefined( false );
else
((Range*)args[0].addr)->Maximum( *(Alpha*)result.addr);
return 0;
}
/*
16.3.16 Value mapping functions of operator ~no\_components~
*/
template <class Range>
int RangeNoComponents( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
if( ((Range*)args[0].addr)->IsDefined() )
((CcInt *)result.addr)->
Set( true, ((Range*)args[0].addr)->GetNoComponents() );
else
((CcInt *)result.addr)->Set( false, 0 );
return 0;
}
/*
16.3.23 Value mapping functions of operator ~trajectory~
*/
int MPointTrajectory( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
Line *line = ((Line*)result.addr);
MPoint *mpoint = ((MPoint*)args[0].addr);
mpoint->Trajectory( *line );
return 0;
}
int MBool2MInt( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
((MInt*)result.addr)->ReadFrom(*((MBool*) args[0].addr));
return 0;
}
int MInt2MBool( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
((MInt*) args[0].addr)->WriteTo(*((MBool*) result.addr));
return 0;
}
int MInt2MReal( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
((MInt*) args[0].addr)->WriteTo(*((MReal*) result.addr));
return 0;
}
/*
16.3.29 Value mapping functions of operator ~distance~
*/
int MPointDistance( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
((MPoint*)args[0].addr)->Distance( *((Point*)args[1].addr),
*((MReal*)result.addr) );
return 0;
}
/*
16.3.29 Value mapping function of operator ~distanceAvg~
*/
template<bool durationSpecified>
int DistanceAvgMap(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
Geoid *geoid = 0;
datetime::DateTime *duration = new datetime::DateTime(0, 3600000,
datetime::durationtype);
if (durationSpecified) {
duration->DeleteIfAllowed();
duration = (datetime::DateTime*)args[2].addr;
if (qp->GetNoSons(s) == 4) {
geoid = (Geoid*)args[3].addr;
}
}
else if (qp->GetNoSons(s) == 3) {
geoid = (Geoid*)args[2].addr;
}
DistanceComputation<MPoint, UPoint>::DistanceAvg(*((MPoint*)args[0].addr),
*((MPoint*)args[1].addr), *duration, true, *((CcReal*)result.addr), geoid);
return 0;
}
template<bool durationSpecified, bool upperBound>
int DistanceAvgCMMap(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
Geoid *geoid = 0;
datetime::DateTime *duration = new datetime::DateTime(0, 3600000,
datetime::durationtype);
if (durationSpecified) {
duration->DeleteIfAllowed();
duration = (datetime::DateTime*)args[2].addr;
if (qp->GetNoSons(s) == 4) {
geoid = (Geoid*)args[3].addr;
}
}
else if (qp->GetNoSons(s) == 3) {
geoid = (Geoid*)args[2].addr;
}
DistanceComputation<CMPoint, CUPoint>::DistanceAvg(*((CMPoint*)args[0].addr),
*((CMPoint*)args[1].addr), *duration,
upperBound, *((CcReal*)result.addr), geoid);
return 0;
}
template<bool durationSpecified, bool upperBound>
int DistanceAvgCUMap(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
Geoid *geoid = 0;
datetime::DateTime *duration = new datetime::DateTime(0, 3600000,
datetime::durationtype);
if (durationSpecified) {
duration->DeleteIfAllowed();
duration = (datetime::DateTime*)args[2].addr;
if (qp->GetNoSons(s) == 4) {
geoid = (Geoid*)args[3].addr;
}
}
else if (qp->GetNoSons(s) == 3) {
geoid = (Geoid*)args[2].addr;
}
((CUPoint*)args[0].addr)->DistanceAvg(*((CUPoint*)args[1].addr), *duration,
upperBound, *((CcReal*)result.addr), geoid);
return 0;
}
/*
16.3.29 Value mappings function for the operator ~simplify~
*/
int MPointSimplify(Word* args, Word& result,
int message, Word& local,
Supplier s){
result = qp->ResultStorage( s );
double epsilon = ((CcReal*)args[1].addr)->GetRealval();
DateTime dur(durationtype);
Geoid* geoid = 0;
if(qp->GetNoSons(s)==3){
geoid = (Geoid*) args[2].addr;
}
((MPoint*)args[0].addr)->Simplify( epsilon,
*((MPoint*)result.addr),
false,dur,geoid );
return 0;
}
int MPointSimplify2(Word* args, Word& result,
int message, Word& local,
Supplier s){
result = qp->ResultStorage( s );
double epsilon = ((CcReal*)args[1].addr)->GetRealval();
DateTime* dur = (DateTime*)args[2].addr;
Geoid* geoid = 0;
if(qp->GetNoSons(s)==4){
geoid = (Geoid*) args[3].addr;
}
((MPoint*)args[0].addr)->Simplify( epsilon,
*((MPoint*)result.addr),
true,*dur, geoid );
return 0;
}
int MRealSimplify(Word* args, Word& result,
int message, Word& local,
Supplier s){
result = qp->ResultStorage(s);
double epsilon = ((CcReal*)args[1].addr)->GetRealval();
((MReal*)args[0].addr)->Simplify( epsilon,
*((MReal*)result.addr));
return 0;
}
/*
16.2.28 Value Mapping function for the operator integrate
*/
template <class mtype>
int Integrate(Word* args, Word& result,
int message, Word& local,
Supplier s){
result = qp->ResultStorage(s);
mtype* arg = (mtype*) args[0].addr;
if(!arg->IsDefined()){
((CcReal*)result.addr)->Set(false,0);
} else {
((CcReal*)result.addr)->Set(true, arg->Integrate());
}
return 0;
}
/*
16.2.28 Value Mapping function for the operator linearize
*/
template <class mtype>
int Linearize(Word* args, Word& result,
int message, Word& local,
Supplier s){
result = qp->ResultStorage(s);
mtype* arg = (mtype*) args[0].addr;
mtype* res = (mtype*) result.addr;
arg->Linearize(*res);
return 0;
}
int Linearize2(Word* args, Word& result,
int message, Word& local,
Supplier s){
result = qp->ResultStorage(s);
MReal* arg = (MReal*) args[0].addr;
MReal* res = (MReal*) result.addr;
arg->Linearize2(*res);
return 0;
}
struct Linearize2_ureal_LocalInfo
{
bool finished;
int NoOfResults;
int NoOfResultsDelivered;
std::vector<UReal> resultVector;
};
int Linearize2_ureal(Word* args, Word& result,
int message, Word& local,
Supplier s)
{
result = qp->ResultStorage(s);
UReal *arg;
Linearize2_ureal_LocalInfo *localinfo;
switch( message )
{
case OPEN:
arg = (UReal*) args[0].addr;
localinfo = new(Linearize2_ureal_LocalInfo);
local.setAddr(localinfo);
localinfo->finished = true;
localinfo->NoOfResults = 0;
localinfo->NoOfResultsDelivered = 0;
localinfo->resultVector.clear();
if( !arg->IsDefined() )
return 0;
else
{
UReal res1, res2;
arg->Linearize(res1, res2);
if( res1.IsDefined() )
{
localinfo->resultVector.push_back(res1);
localinfo->NoOfResults++;
}
if( res2.IsDefined() )
{
localinfo->resultVector.push_back(res2);
localinfo->NoOfResults++;
}
localinfo->finished = (localinfo->NoOfResults <= 0);
return 0;
}
return 0;
case REQUEST:
if(local.addr == 0)
return CANCEL;
localinfo = (Linearize2_ureal_LocalInfo*) local.addr;
if( localinfo->finished ||
localinfo->NoOfResultsDelivered >= localinfo->NoOfResults )
{
localinfo->finished = true;
return CANCEL;
}
result.setAddr(
localinfo->resultVector[localinfo->NoOfResultsDelivered].Clone() );
localinfo->NoOfResultsDelivered++;
return YIELD;
case CLOSE:
if(local.addr)
{
localinfo = (Linearize2_ureal_LocalInfo*) local.addr;
delete localinfo;
local.setAddr(0);
}
return 0;
} // end switch
std::cerr << "Linearize2_ureal(): Unknown message (" << message << ")"
<< endl;
return -1; // should not happen
}
/*
16.2.28 Value Mapping Functions for Approximate
*/
template<typename MType, typename UType, typename VType, bool isContinious>
int ApproximateMvalue(Word* args, Word& result,
int message, Word& local,
Supplier s){
result = qp->ResultStorage(s);
MType* res = static_cast<MType*>(result.addr);
res->Clear();
int noargs = qp->GetNoSons(s);
DateTime dur(durationtype);
int breakAttrIndex = ((CcInt*)args[noargs-1].addr)->GetValue();
int boolIndex = ((CcInt*)args[noargs-2].addr)->GetValue();
int durindex = ((CcInt*)args[noargs-3].addr)->GetValue();
int index2 = ((CcInt*)args[noargs-4].addr)->GetValue();
int index1 = ((CcInt*)args[noargs-5].addr)->GetValue();
//cout << "breakAttrIndex = " << breakAttrIndex << endl;
//cout << "boolIndex = " << boolIndex << endl;
//cout << " durindex = " << durindex << endl;
//cout << " index2 = " << index2 << endl;
//cout << " index1 = " << index1 << endl;
bool split1 = false;
bool split2 = breakAttrIndex>=0;
bool makeContinious = isContinious;
if(boolIndex>=0){
CcBool* MC = static_cast<CcBool*>(args[boolIndex].addr);
if(!MC->IsDefined()){
res->SetDefined(false);
return 0;
}
makeContinious += MC->GetValue();
}
if(durindex>=0){
dur.CopyFrom(static_cast<Attribute*>(args[durindex].addr));
split1 = true;
}
if( !split1 || dur.IsDefined() ){
res->SetDefined(true);
} else { // undefined splitting duration parameter --> return UNDEF mpoint
res->SetDefined(false);
return 0;
}
Word actual;
VType lastValue(false),currentValue(false);
Instant lastInstant(instanttype),currentInstant(instanttype);
bool first = true;
Stream<Tuple> stream(args[0]);
stream.open();
Tuple* tuple = stream.request();
while (tuple!=0) {
currentValue = *((VType*)(tuple->GetAttribute(index2)));
currentInstant = *((Instant*)(tuple->GetAttribute(index1)));
bool splitHere = false;
if(split2){
CcBool* splitHere1 = (CcBool*) tuple->GetAttribute(breakAttrIndex);
splitHere = splitHere1->IsDefined() && splitHere1->GetBoolval();
}
if(currentInstant.IsDefined()){ // ignore undefined instants
if(currentValue.IsDefined()){
if(!first && !splitHere){
// check order of instants - ignore wrong ordered elements
if(currentInstant>lastInstant){
if(!(split1 && (currentInstant - lastInstant) > dur )) {
Interval<Instant> interval(lastInstant, currentInstant,
true ,false);
if(isContinious){
UType unit(interval,lastValue,currentValue);
res->MergeAdd(unit);
} else {
UType unit(interval,lastValue,lastValue);
res->MergeAdd(unit);
}
}
lastValue = currentValue;
lastInstant = currentInstant;
}
} else {
if(first || lastInstant < currentInstant){
lastValue = currentValue;
lastInstant = currentInstant;
}
first = false;
}
}
}
tuple->DeleteIfAllowed();
tuple=stream.request();
}
stream.close();
return 0;
}
/*
16.2.28 Value Mapping function for the operator min
*/
template <class mtype, class rtype>
int VM_Min(Word* args, Word& result,
int message, Word& local,
Supplier s){
result = qp->ResultStorage(s);
mtype* arg = (mtype*) args[0].addr;
bool correct;
typename rtype::ctype res = arg->Min(correct);
((rtype*)result.addr)->Set(correct,res);
return 0;
}
/*
16.2.28 Value Mapping function for the operator min
*/
template <class mtype, class rtype>
int VM_Max(Word* args, Word& result,
int message, Word& local,
Supplier s){
result = qp->ResultStorage(s);
mtype* arg = (mtype*) args[0].addr;
bool correct;
typename rtype::ctype res = arg->Max(correct);
((rtype*)result.addr)->Set(correct,res);
return 0;
}
/*
16.3.29 Value mapping function for the operator ~breakpoints~
*/
int MPointBreakPoints(Word* args, Word& result,
int message, Word& local,
Supplier s){
result = qp->ResultStorage( s );
DateTime* dur = ((DateTime*)args[1].addr);
if(qp->GetNoSons(s) == 2){
((MPoint*)args[0].addr)->BreakPoints(*((Points*)result.addr),*dur );
} else {
CcReal* epsilon = (CcReal*)args[2].addr;
((MPoint*)args[0].addr)->BreakPoints(*((Points*)result.addr),
*dur, *epsilon );
}
return 0;
}
/*
16.3.29 Value mapping function for the operator ~breaks~
*/
int breaksVM(Word* args, Word& result,
int message, Word& local,
Supplier s){
result= qp->ResultStorage(s);
Periods* res = (Periods*) result.addr;
MPoint* mp = (MPoint*) args[0].addr;
DateTime* dur = (DateTime*) args[1].addr;
CcReal* eps = (CcReal*) args[2].addr;
mp->Breaks(*res, *dur, *eps);
return 0;
}
/*
16.3.29 Value mapping function for the operator ~gk~
*/
template<class T>
int gkVMT(Word* args, Word& result,
int message, Word& local,
Supplier s){
result = qp->ResultStorage( s );
T* arg = static_cast<T*>(args[0].addr);
CcInt* zone = static_cast<CcInt*>(args[1].addr);
if(!zone->IsDefined()){
((T*)result.addr)->SetDefined(false);
} else {
arg->gk(zone->GetValue(), *((T*)result.addr));
}
return 0;
}
ValueMapping gkVM[] = {
gkVMT<MPoint>,
gkVMT<UPoint>
};
int gkSelect(ListExpr args){
return MPoint::checkType(nl->First(args))?0:1;
}
/*
16.3.29 Value mapping function for the operator ~vertices~
*/
int Vertices(Word* args, Word& result,
int message, Word& local,
Supplier s){
result = qp->ResultStorage( s );
((MPoint*)args[0].addr)->Vertices(*((Points*)result.addr));
return 0;
}
/*
16.3.30 Value mapping function for the operator ~delay~
*/
int DelayOperatorValueMapping(ArgVector args, Word& result,
int msg, Word& local, Supplier s) {
bool debugme = false;
MPoint* pActual = static_cast<MPoint*>(args[0].addr);
MPoint* pScheduled = static_cast<MPoint*>(args[1].addr);
Geoid* geoid = (qp->GetNoSons(s) == 3) ? static_cast<Geoid*>(args[2].addr):0;
MReal* delay= (MReal*) qp->ResultStorage(s).addr;
MReal* tmp = pScheduled->DelayOperator(pActual,geoid);
delay->CopyFrom(tmp);
tmp->DeleteIfAllowed();
result= SetWord(delay);
if (debugme) {
cout.flush();
delay->Print(cout);
cout.flush();
}
return 0;
// result = qp->ResultStorage(s);
// result.addr= pScheduled->DelayOperator(pActual);
// return 0;
}
/*
16.3.30 Value mapping function for the operator ~distancetraversed~
*/
int DistanceTraversedOperatorValueMapping(ArgVector args, Word& result,
int msg, Word& local, Supplier s) {
bool debugme = false;
MPoint* p = static_cast<MPoint*>(args[0].addr);
MReal* dist = static_cast<MReal*>(qp->ResultStorage(s).addr);
Geoid* geoid = (qp->GetNoSons(s) == 1) ? 0:static_cast<Geoid*>(args[1].addr);
MReal* tmp = p->DistanceTraversed(geoid);
dist->CopyFrom(tmp);
tmp->DeleteIfAllowed();
result = SetWord(dist);
if (debugme) {
cout.flush();
dist->Print(cout);
cout.flush();
}
return 0;
// result = qp->ResultStorage(s);
// result.addr= pScheduled->DelayOperator(pActual);
// return 0;
}
/*
16.3.31 Value mapping functions of operator ~bbox~
*/
int IPointBBox(Word* args, Word& result, int message, Word& local,
Supplier s )
{
result = qp->ResultStorage( s );
Rectangle<3> *res = (Rectangle<3>*) result.addr;
const Intime<Point> *arg = static_cast<const Intime<Point>*>(args[0].addr);
const Geoid* geoid =
(qp->GetNoSons(s)==2)?static_cast<const Geoid*>(args[1].addr):0;
Rectangle<2> pbox(true);
double min[3], max[3];
if( !arg->IsDefined() || (geoid && !geoid->IsDefined()) )
{
res->SetDefined(false);
}
else
{
pbox = arg->value.BoundingBox(geoid);
if( !pbox.IsDefined() || !arg->instant.IsDefined() )
{
res->SetDefined(false);
}
else
{
min[0] = pbox.MinD(0);
min[1] = pbox.MinD(1);
min[2] = arg->instant.ToDouble();
max[0] = min[0];
max[1] = min[1];
max[2] = min[2];
res->Set( true, min, max );
}
}
return 0;
}
/*
Since MPoint is not a subclass of ~SpatialAttribute~, it has no ~BoundingBox()~
function. One could make it inherit from ~SpatialAttribute~, but than one had to
restore all databases and adopt the Add, MergeAdd, +=, -=, etc.
*/
template<class T>
int MTypeBBox(Word* args, Word& result, int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
Rectangle<3>* res = (Rectangle<3>*)result.addr;
const T* arg = static_cast<const T*>(args[0].addr);
const Geoid* geoid =
(qp->GetNoSons(s) == 2) ? static_cast<const Geoid*>(args[1].addr) : 0;
if (!arg->IsDefined() || (arg->GetNoComponents() < 1)) {
res->SetDefined(false);
}
else {
*res = arg->BoundingBox(geoid);
}
return 0;
}
int MPointBBoxOld(Word* args, Word& result, int message, Word& local,
Supplier s )
{
result = qp->ResultStorage( s );
Rectangle<3>* res = (Rectangle<3>*) result.addr;
const MPoint* arg = static_cast<const MPoint*>(args[0].addr);
const Geoid* geoid =
(qp->GetNoSons(s)==2)?static_cast<const Geoid*>(args[1].addr):0;
UPoint uPoint;
double min[3], max[3];
Rectangle<3> accubbox;
if( !arg->IsDefined() || (arg->GetNoComponents() < 1) ||
(geoid && !geoid->IsDefined()) )
{
res->SetDefined(false);
}
else
{
arg->Get( 0, uPoint );
accubbox = uPoint.BoundingBox();
min[2] = uPoint.timeInterval.start.ToDouble(); // mintime
for( int i = 1; i < arg->GetNoComponents(); i++ )
{ // calculate spatial bbox
arg->Get( i, uPoint );
accubbox = accubbox.Union( uPoint.BoundingBox(geoid) );
}
max[2] = uPoint.timeInterval.end.ToDouble(); // maxtime
min[0] = accubbox.MinD(0); // minX
max[0] = accubbox.MaxD(0); // maxX
min[1] = accubbox.MinD(1); // minY
max[1] = accubbox.MaxD(1); // maxY
res->Set( true, min, max );
}
return 0;
}
int PeriodsBBox(Word* args, Word& result, int message, Word& local,
Supplier s )
{
result = qp->ResultStorage( s );
Rectangle<3>* res = (Rectangle<3>*) result.addr;
Periods* arg = (Periods*) args[0].addr;
if( !arg->IsDefined() || arg->IsEmpty() )
{
res->SetDefined(false);
}
else
{
double min[3], max[3];
int64_t zero =0;
Instant minT(zero);
Instant maxT(zero);
arg->Minimum(minT);
arg->Maximum(maxT);
min[0] = MINDOUBLE; // minX
max[0] = MAXDOUBLE; // maxX
min[1] = MINDOUBLE; // minY
max[1] = MAXDOUBLE; // maxY
min[2] = minT.ToDouble(); // min t
max[2] = maxT.ToDouble(); // max t
res->Set( true, min, max );
}
return 0;
}
int InstantBBox(Word* args, Word& result, int message, Word& local,
Supplier s )
{
result = qp->ResultStorage( s );
Rectangle<3>* res = (Rectangle<3>*) result.addr;
Instant* arg = (Instant*) args[0].addr;
if( !arg->IsDefined() )
{
res->SetDefined(false);
}
else
{
double min[3], max[3];
min[0] = MINDOUBLE; // minX
max[0] = MAXDOUBLE; // maxX
min[1] = MINDOUBLE; // minY
max[1] = MAXDOUBLE; // maxY
min[2] = arg->ToDouble(); // min t
max[2] = arg->ToDouble(); // max t
res->Set( true, min, max );
}
return 0;
}
template<class T>
int UnitBBox(Word* args, Word& result, int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
Rectangle<3>* res = (Rectangle<3>*)result.addr;
const T* arg = static_cast<const T*>(args[0].addr);
const Geoid* geoid =
(qp->GetNoSons(s) == 2) ? static_cast<const Geoid*>(args[1].addr) : 0;
if (!arg->IsDefined() || (geoid && !geoid->IsDefined())) {
res->SetDefined(false);
}
else {
*res = arg->BoundingBox(geoid);
}
return 0;
}
template <class Range>
int TempMBRange( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
Range* arg = (Range*)args[0].addr;
if( !arg->IsDefined() || arg->IsEmpty() )
((Range*)result.addr)->SetDefined( false );
else
((Range*)args[0].addr)->RBBox( *(Range*)result.addr);
return 0;
}
/*
16.3.31 Value mapping functions of operator ~bbox2d~
*/
int IPointBBox2d(Word* args, Word& result, int message, Word& local,
Supplier s )
{
result = qp->ResultStorage( s );
Rectangle<2> *res = (Rectangle<2>*) result.addr;
const Intime<Point> *arg = static_cast<const Intime<Point>*>(args[0].addr);
const Geoid* geoid =
(qp->GetNoSons(s)==2)?static_cast<const Geoid*>(args[1].addr):0;
if( !arg->IsDefined() || (geoid && !geoid->IsDefined()) )
{
res->SetDefined(false);
}
else
{
*res = arg->value.BoundingBox(geoid);
}
return 0;
}
template<class T>
int MTypeBBox2d(Word* args, Word& result, int message, Word& local, Supplier s){
result = qp->ResultStorage(s);
Rectangle<2>* res = (Rectangle<2>*) result.addr;
const T* arg = static_cast<const T*>(args[0].addr);
const Geoid* geoid =
(qp->GetNoSons(s) == 2) ? static_cast<const Geoid*>(args[1].addr) : 0;
Rectangle<3> bbox3d = arg->BoundingBox(geoid);
if (bbox3d.IsDefined()) {
double min[2], max[2];
min[0] = bbox3d.MinD(0); // minX
max[0] = bbox3d.MaxD(0); // maxX
min[1] = bbox3d.MinD(1); // minY
max[1] = bbox3d.MaxD(1); // maxY
res->Set(true, min, max);
}
else {
res->SetDefined(false);
}
return 0;
}
template<class T>
int UnitBBox2d(Word* args, Word& result, int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
Rectangle<2>* res = (Rectangle<2>*)result.addr;
const T* arg = static_cast<const T*>(args[0].addr);
const Geoid* geoid =
(qp->GetNoSons(s) == 2) ? static_cast<const Geoid*>(args[1].addr) : 0;
*res = arg->BoundingBoxSpatial(geoid);
return 0;
}
/*
16.3.31 Value mapping functions of operator ~translate~
*/
static int
MPointTranslate( Word* args, Word& result, int message, Word&
local, Supplier s )
{
Word t;
double dx,dy;
DateTime* dd;
UPoint uPoint;
MPoint* mp, *mpResult;
CcReal *DX, *DY;
result = qp->ResultStorage( s );
mp= (MPoint*)args[0].addr,
mpResult = (MPoint*)result.addr;
mpResult->Clear();
Supplier son = qp->GetSupplier( args[1].addr, 0 );
qp->Request( son, t );
dd = (DateTime *)t.addr;
son = qp->GetSupplier( args[1].addr, 1 );
qp->Request( son, t );
DX = (CcReal *)t.addr;
son = qp->GetSupplier( args[1].addr, 2 );
qp->Request( son, t );
DY = (CcReal *)t.addr;
if( DX->IsDefined() &&
DY->IsDefined() &&
dd->IsDefined() &&
mp->IsDefined() )
{
dx = DX->GetRealval();
dy = DY->GetRealval();
mpResult->SetDefined( true );
mpResult->StartBulkLoad();
for( int i = 0; i < mp->GetNoComponents(); i++ )
{
mp->Get( i, uPoint );
UPoint aux( uPoint );
aux.p0.Set( aux.p0.GetX() + dx, aux.p0.GetY() + dy );
aux.p1.Set( aux.p1.GetX() + dx, aux.p1.GetY() + dy );
aux.timeInterval.start.Add(dd);
aux.timeInterval.end.Add(dd);
mpResult->Add(aux);
}
mpResult->EndBulkLoad();
return 0;
}
else
{
mpResult->SetDefined( false );
return 0;
}
}
/*
16.3.32 Value mapping functions of operator ~theyear~
*/
int TheYear( Word* args, Word& result, int message, Word& local,
Supplier s )
{ // int --> periods (=range(instant))
result = qp->ResultStorage( s );
Periods* pResult = (Periods*)result.addr;
pResult->Clear();
if( !((CcInt*)args[0].addr)->IsDefined() ) {
pResult->SetDefined( false );
return 0;
}
pResult->SetDefined( true );
int intyear = ((CcInt*)args[0].addr)->GetIntval();
Instant inst1, inst2;
inst1.SetType( instanttype ) ;
inst1.Set( intyear, 1, 1, 0, 0, 0, 0 );
inst2.SetType( instanttype );
inst2.Set( intyear + 1, 1, 1, 0, 0, 0, 0 );
Interval<Instant> timeInterval(inst1, inst2, true, false);
pResult->StartBulkLoad();
pResult->Add( timeInterval );
pResult->EndBulkLoad( false );
return 0;
}
/*
16.3.33 Value mapping functions of operator ~themonth~
*/
int TheMonth( Word* args, Word& result, int message, Word& local,
Supplier s )
{
result = qp->ResultStorage( s );
Periods *pResult = (Periods*)result.addr;
pResult->Clear();
if( !((CcInt*)args[0].addr)->IsDefined()
|| !((CcInt*)args[1].addr)->IsDefined() ) {
pResult->SetDefined( false );
return 0;
}
pResult->SetDefined( true );
int intyear = ((CcInt*)args[0].addr)->GetIntval(),
intmonth = ((CcInt*)args[1].addr)->GetIntval();
Instant inst1, inst2;
inst1.SetType( instanttype );
inst1.Set( intyear, intmonth, 1, 0, 0, 0, 0 );
inst2.SetType( instanttype );
if( intmonth < 12 )
inst2.Set(intyear, intmonth+1, 1, 0, 0, 0, 0);
else
inst2.Set(intyear+1, 1, 1, 0, 0, 0, 0);
Interval<Instant> timeInterval( inst1, inst2, true, false );
pResult->StartBulkLoad();
pResult->Add( timeInterval );
pResult->EndBulkLoad( false );
return 0;
}
/*
16.3.34 Value mapping functions of operator ~theday~
*/
int TheDay( Word* args, Word& result, int message, Word& local,
Supplier s )
{
result = qp->ResultStorage( s );
Periods *pResult = (Periods*)result.addr;
pResult->Clear();
if( !((CcInt*)args[0].addr)->IsDefined()
|| !((CcInt*)args[1].addr)->IsDefined()
|| !((CcInt*)args[2].addr)->IsDefined() ) {
pResult->SetDefined( false );
return 0;
}
pResult->SetDefined( true );
int intyear = ((CcInt*)args[0].addr)->GetIntval(),
intmonth = ((CcInt*)args[1].addr)->GetIntval(),
intday = ((CcInt*)args[2].addr)->GetIntval();
Instant inst1, inst2,
oneday( 1, 0, durationtype );
inst1.SetType( instanttype );
inst1.Set( intyear, intmonth, intday, 0, 0, 0, 0 );
inst2.SetType( instanttype );
inst2 = inst1 + oneday;
Interval<Instant> timeInterval( inst1, inst2, true, false );
pResult->StartBulkLoad();
pResult->Add( timeInterval );
pResult->EndBulkLoad( false );
return 0;
}
/*
16.3.35 Value mapping functions of operator ~thehour~
*/
int TheHour( Word* args, Word& result, int message, Word& local,
Supplier s )
{
result = qp->ResultStorage( s );
Periods* pResult = (Periods*)result.addr;
pResult->Clear();
if( !((CcInt*)args[0].addr)->IsDefined()
|| !((CcInt*)args[1].addr)->IsDefined()
|| !((CcInt*)args[2].addr)->IsDefined()
|| !((CcInt*)args[3].addr)->IsDefined() ) {
pResult->SetDefined( false );
return 0;
}
pResult->SetDefined( true );
int intyear = ((CcInt*)args[0].addr)->GetIntval(),
intmonth = ((CcInt*)args[1].addr)->GetIntval(),
intday = ((CcInt*)args[2].addr)->GetIntval(),
inthour = ((CcInt*)args[3].addr)->GetIntval();
Instant inst1, inst2,
onehour( 0, 1*60*60*1000, durationtype );
inst1.SetType( instanttype );
inst1.Set( intyear, intmonth, intday, inthour, 0, 0, 0 );
inst2 .SetType( instanttype );
inst2 = inst1 + onehour;
Interval<Instant> timeInterval( inst1, inst2, true, false );
pResult->StartBulkLoad();
pResult->Add( timeInterval );
pResult->EndBulkLoad( false );
return 0;
}
/*
16.3.36 Value mapping functions of operator ~theminute~
*/
int TheMinute( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
Periods *pResult = (Periods*)result.addr;
pResult->Clear();
if( !((CcInt*)args[0].addr)->IsDefined()
|| !((CcInt*)args[1].addr)->IsDefined()
|| !((CcInt*)args[2].addr)->IsDefined()
|| !((CcInt*)args[3].addr)->IsDefined()
|| !((CcInt*)args[4].addr)->IsDefined() ) {
pResult->SetDefined( false );
return 0;
}
pResult->SetDefined( true );
int intyear = ((CcInt*)args[0].addr)->GetIntval(),
intmonth = ((CcInt*)args[1].addr)->GetIntval(),
intday = ((CcInt*)args[2].addr)->GetIntval(),
inthour = ((CcInt*)args[3].addr)->GetIntval(),
intminute = ((CcInt*)args[4].addr)->GetIntval();
Instant inst1, inst2,
oneminute( 0, 1*60*1000, durationtype );
inst1.SetType( instanttype );
inst1.Set( intyear, intmonth, intday, inthour, intminute, 0, 0 );
inst2 .SetType( instanttype );
inst2 = inst1 + oneminute;
Interval<Instant> timeInterval( inst1, inst2, true, false );
pResult->StartBulkLoad();
pResult->Add( timeInterval );
pResult->EndBulkLoad( false );
return 0;
}
/*
16.3.37 Value mapping functions of operator ~thesecond~
*/
int TheSecond( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
Periods *pResult = (Periods*)result.addr;
pResult->Clear();
if( !((CcInt*)args[0].addr)->IsDefined()
|| !((CcInt*)args[1].addr)->IsDefined()
|| !((CcInt*)args[2].addr)->IsDefined()
|| !((CcInt*)args[3].addr)->IsDefined()
|| !((CcInt*)args[4].addr)->IsDefined()
|| !((CcInt*)args[5].addr)->IsDefined() ) {
pResult->SetDefined( false );
return 0;
}
pResult->SetDefined( true );
int intyear = ((CcInt*)args[0].addr)->GetIntval(),
intmonth = ((CcInt*)args[1].addr)->GetIntval(),
intday = ((CcInt*)args[2].addr)->GetIntval(),
inthour = ((CcInt*)args[3].addr)->GetIntval(),
intminute = ((CcInt*)args[4].addr)->GetIntval(),
intsecond = ((CcInt*)args[5].addr)->GetIntval();
Instant inst1, inst2,
onesecond( 0, 1000, durationtype );
inst1.SetType( instanttype );
inst1.Set( intyear, intmonth, intday, inthour, intminute, intsecond, 0 );
inst2.SetType( instanttype );
inst2 = inst1 + onesecond;
Interval<Instant> timeInterval( inst1, inst2, true, false );
pResult->StartBulkLoad();
pResult->Add( timeInterval );
pResult->EndBulkLoad( false );
return 0;
}
/*
16.3.38 Value mapping functions of operator ~theperiod~
*/
int ThePeriod( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
Periods *pResult = (Periods*)result.addr,
*range1 = ((Periods*)args[0].addr),
*range2 = ((Periods*)args[1].addr);
pResult->Clear();
if( !range1->IsDefined() || !range2->IsDefined() ){
pResult->SetDefined( false );
return 0;
}
pResult->SetDefined( true );
if(range1->IsEmpty() && range2->IsEmpty()){
return 0; // return empty periods value
}
// range 1 is empty
if(range1->IsEmpty()){
Interval<Instant> first;
Interval<Instant> last;
range2->Get(0,first);
range2->Get(range2->GetNoComponents()-1,last);
Interval<Instant> iv(first.start,last.end,first.lc,last.rc);
pResult->StartBulkLoad();
pResult->Add( iv );
pResult->EndBulkLoad( false, true );
return 0;
}
// symmetric case , range 2 is empty
if(range2->IsEmpty()){
Interval<Instant> first;
Interval<Instant> last;
range1->Get(0,first);
range1->Get(range1->GetNoComponents()-1,last);
Interval<Instant> iv(first.start,last.end,first.lc,last.rc);
pResult->StartBulkLoad();
pResult->Add( iv );
pResult->EndBulkLoad( false, true );
return 0;
}
// normal case both intervals are defined and non empty
Interval<Instant> first1;
Interval<Instant> last1;
range1->Get(0,first1);
range1->Get(range1->GetNoComponents()-1,last1);
Interval<Instant> first2;
Interval<Instant> last2;
range2->Get(0,first2);
range2->Get(range2->GetNoComponents()-1,last2);
Instant start(datetime::instanttype);
bool lc = false;
if(first1.start < first2.start){
start = first1.start;
lc = first1.lc;
} else if(first1.start > first2.start){
start = first2.start;
lc = first2.lc;
} else { // equal start instants
start = first1.start;
lc = first1.lc || first2.lc;
}
Instant end(datetime::instanttype);
bool rc = false;
if( last1.end > last2.end){
end = last1.end;
rc = last1.rc;
} else if(last1.end < last2.end){
end = last2.end;
rc = last2.rc;
} else { // equal end
end = last2.end;
rc = last1.rc || last2.rc;
}
Interval<Instant> iv(start,end,lc,rc);
pResult->StartBulkLoad();
pResult->Add( iv );
pResult->EndBulkLoad( false, true );
return 0;
}
/*
16.3.39 Value Mappings function for box3d
*/
int Box3d_rect( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
Rectangle<3>* res = (Rectangle<3>*) result.addr;
Rectangle<2>* arg = (Rectangle<2>*) args[0].addr;
if( !arg->IsDefined() )
{
res->SetDefined(false);
}
else
{
double min[3];
double max[3];
min[0] = arg->MinD(0);
min[1] = arg->MinD(1);
min[2] = MINDOUBLE;
max[0] = arg->MaxD(0);
max[1] = arg->MaxD(1);
max[2] = MAXDOUBLE;
res->Set(true,min,max);
}
return 0;
}
int Box3d_instant( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
Rectangle<3>* res = (Rectangle<3>*) result.addr;
Instant* arg = (Instant*) args[0].addr;
if( !arg->IsDefined() )
{
res->SetDefined(false);
}
else
{
double min[3];
double max[3];
double v = arg->ToDouble();
min[0] = MINDOUBLE;
min[1] = MINDOUBLE;
min[2] = v;
max[0] = MAXDOUBLE;
max[1] = MAXDOUBLE;
max[2] = v;
res->Set(true,min,max);
}
return 0;
}
int Box3d_rect_instant( Word* args, Word& result, int message,
Word& local, Supplier s ){
result = qp->ResultStorage(s);
Rectangle<3>* res = (Rectangle<3>*) result.addr;
Rectangle<2>* arg1 = (Rectangle<2>*) args[0].addr;
Instant* arg2 = (Instant*) args[1].addr;
if( !arg1->IsDefined() || !arg2->IsDefined() )
{
res->SetDefined(false);
}
else
{
double v = arg2->ToDouble();
double min[3];
double max[3];
min[0] = arg1->MinD(0);
min[1] = arg1->MinD(1);
min[2] = v;
max[0] = arg1->MaxD(0);
max[1] = arg1->MaxD(1);
max[2] = v;
res->Set(true,min,max);
}
return 0;
}
int Box3d_periods( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
Rectangle<3>* res = (Rectangle<3>*) result.addr;
Periods* per = (Periods*) args[0].addr;
if( per->IsEmpty() ) // includes undefined per
{
res->SetDefined(false);
}
else
{
Instant i1(0,0,instanttype), i2(0,0,instanttype);
per->Minimum(i1);
double v1 = i1.ToDouble();
per->Maximum(i2);
double v2 = i2.ToDouble();
double min[3];
double max[3];
min[0] = MINDOUBLE;
min[1] = MINDOUBLE;
min[2] = v1;
max[0] = MAXDOUBLE;
max[1] = MAXDOUBLE;
max[2] = v2;
res->Set(true,min,max);
}
return 0;
}
int Box3d_rect_periods( Word* args, Word& result, int message,
Word& local, Supplier s ){
result = qp->ResultStorage(s);
Rectangle<3>* res = (Rectangle<3>*) result.addr;
Rectangle<2>* arg1 = (Rectangle<2>*) args[0].addr;
Periods* arg2 = (Periods*) args[1].addr;
if( !arg1->IsDefined() || arg2->IsEmpty() ) // includes undefined arg2
{
res->SetDefined(false);
}
else
{
Instant i1, i2;
arg2->Minimum(i1);
double v1 = i1.ToDouble();
arg2->Maximum(i2);
double v2 = i2.ToDouble();
double min[3];
double max[3];
min[0] = arg1->MinD(0);
min[1] = arg1->MinD(1);
min[2] = v1;
max[0] = arg1->MaxD(0);
max[1] = arg1->MaxD(1);
max[2] = v2;
res->Set(true,min,max);
}
return 0;
}
/*
16.3.40 Value Mapping function for box2d
*/
template <int dim>
int TemporalBox2d( Word* args, Word& result, int message,
Word& local, Supplier s )
{
assert(dim >= 2);
result = qp->ResultStorage(s);
Rectangle<2>* res = (Rectangle<2>*) result.addr;
Rectangle<dim>* arg = (Rectangle<dim>*) args[0].addr;
if( !arg->IsDefined() )
{
res->SetDefined(false);
}
else
{
double min[2], max[2];
min[0] = arg->MinD(0);
min[1] = arg->MinD(1);
max[0] = arg->MaxD(0);
max[1] = arg->MaxD(1);
res->Set( true, min, max );
}
return 0;
}
/*
16.3.41 Value Mapping function for ExtDefTime
*/
template <class Unit,class Alpha>
int TemporalExtDeftime( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage(s);
Mapping<Unit,Alpha>* arg1 = (Mapping<Unit,Alpha>*) args[0].addr;
Unit* arg2 = (Unit*) args[1].addr;
Mapping<Unit,Alpha>* res = (Mapping<Unit,Alpha>*) result.addr;
arg1->ExtendDefTime(*arg2,*res);
return 0;
}
/*
16.3.42 Value Mapping function for ~at~
Here, we only implement the VM for ~mreal x real [->] mreal~. All other
VMs are implemented using a template function from ~TemporalAlgebra.h~.
Since it would use the unimplementable ~UReal::At(...)~
method, we implement this version using ~UReal::AtValue(...)~.
*/
int MappingAt_MReal_CcReal( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage(s);
((MReal*) args[0].addr)->
AtValue( *((CcReal*) args[1].addr), *((MReal*) result.addr) );
return 0;
}
/*
16.3.43 Value mapping function for operator ~theRange~
*/
template<class T>
int TemporalTheRangeTM( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
Range<T> *pResult = (Range<T> *)result.addr;
T *t1 = ((T*)args[0].addr),
*t2 = ((T*)args[1].addr);
CcBool *b1 = ((CcBool*)args[2].addr),
*b2 = ((CcBool*)args[3].addr);
pResult->Clear();
if( !t1->IsDefined() || !t2->IsDefined() ||
!b1->IsDefined() || !b2->IsDefined()
)
{
pResult->SetDefined(false); // not effective by now
}
else
{
pResult->SetDefined(true);
Interval<T> interval;
int cmp = t1->Compare( t2 );
bool bb1 = b1->GetBoolval(),
bb2 = b2->GetBoolval();
if( t1->Adjacent( t2 ) && !bb1 && !bb2 )
{
pResult->SetDefined( false );
return 0;
}
if( cmp < 0 )
{ // t1 < t2
interval = Interval<T>( *t1, *t2, bb1, bb2 );
}
else if ( cmp > 0 )
{ // t1 > t2, swap arguments
interval = Interval<T>( *t2, *t1, bb2, bb1 );
}
else
{ // t1 == t2, enforce left and right closedness
if( !bb1 || !bb2 )
{
pResult->SetDefined( false );
return 0;
}
else
{
interval = Interval<T>( *t1, *t1, true, true );
}
}
pResult->StartBulkLoad();
pResult->Add( interval );
pResult->EndBulkLoad( false );
}
return 0;
}
/*
16.3.44 Value mapping function for operator ~translateappend~
*/
int TranslateAppendVM( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
MPoint* res = (MPoint*) result.addr;
res->CopyFrom( (MPoint*) args[0].addr);
res->TranslateAppend(*((MPoint*) args[1].addr),
*((DateTime*) args[2].addr));
return 0;
}
/*
16.3.45 Value mapping function for ~translateAppendS~
*/
int TranslateAppendSVM(Word* args, Word& result,
int message, Word& local,
Supplier s){
result = qp->ResultStorage(s);
MPoint* res = (MPoint*) result.addr;
int index = ((CcInt*)args[3].addr)->GetIntval();
DateTime* duration = (DateTime*) args[2].addr;
res->Clear();
res->SetDefined(true);
Word current;
MPoint* mpoint=NULL;
qp->Open(args[0].addr);
qp->Request(args[0].addr, current);
while (qp->Received(args[0].addr)) {
Tuple* tuple = (Tuple*)current.addr;
mpoint = (MPoint*)(tuple->GetAttribute(index));
res->TranslateAppend(*mpoint,*duration);
tuple->DeleteIfAllowed();
qp->Request(args[0].addr, current);
}
qp->Close(args[0].addr);
return 0;
}
/*
16.3.44 Value mapping function for operator ~reverse~
*/
int ReverseVM( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
MPoint* res = (MPoint*) result.addr;
((MPoint*)args[0].addr)->Reverse(*res);
return 0;
}
/*
16.3.45 Value mapping function for operator ~samplempoint~
*/
template <bool keepEndPoint, bool exactPath>
int SampleMPointVM( Word* args, Word& result, int message,
Word& local, Supplier s ){
result = qp->ResultStorage(s);
MPoint* res = (MPoint*) result.addr;
res->Clear();
DateTime* duration = (DateTime*) args[1].addr;
bool ke = false; // keep end point
bool ep = false; // exact path
if(keepEndPoint){
CcBool* KE = (CcBool*) args[2].addr;
if(!KE->IsDefined()){
res->SetDefined(false);
return true;
} else {
ke = KE->GetBoolval();
}
}
if(exactPath){
CcBool* EP = (CcBool*) args[3].addr;
if(!EP->IsDefined()){
res->SetDefined(false);
return 0;
} else {
ep = EP->GetBoolval();
}
}
((MPoint*)args[0].addr)->Sample(*duration,*res,ke,ep);
return 0;
}
/*
16.3.46 Value mapping for the gps operator
*/
class GPSLI{
public:
/*
~Constructor~
*/
GPSLI(const MPoint* mp,
const DateTime* duration,
ListExpr tupleType){
if(!mp->IsDefined() || !duration->IsDefined()){
this->tupleType=0;
this->size=0;
this->unit=0;
} else {
this->theMPoint = mp;
this->duration = duration;
this->size = mp->GetNoComponents();
this->unit = 0;
this->tupleType = new TupleType(nl->Second(tupleType));
if(size>0){
UPoint up;
mp->Get(0,up);
instant = up.timeInterval.start;
}
}
}
/*
~Destructor~
*/
~GPSLI(){
if(tupleType){
tupleType->DeleteIfAllowed();
}
tupleType=0;
}
/*
~NextTuple~
*/
Tuple* NextTuple(){
// search the unit containing instant
bool done = false;
UPoint up;
while(unit<size && !done){
theMPoint->Get(unit,up);
if((instant< up.timeInterval.end) ||
(instant==up.timeInterval.end && up.timeInterval.rc) ){
done = true;
} else {
unit++;
}
}
if(!done){
return 0;
}
if(instant<up.timeInterval.start){ // gap
instant = up.timeInterval.start;
}
Point p;
up.TemporalFunction(instant,p,true);
// construct the result from instant,p
Tuple* res = new Tuple(tupleType);
res->PutAttribute(0,instant.Clone());
res->PutAttribute(1,p.Clone());
instant += *duration;
return res;
}
private:
const MPoint* theMPoint;
const DateTime* duration;
Instant instant;
int size;
int unit;
TupleType* tupleType;
};
int GPSVM( Word* args, Word& result, int message,
Word& local, Supplier s ){
Tuple* t;
GPSLI* li;
switch(message){
case OPEN:
local.setAddr(new GPSLI((MPoint*)args[0].addr,
(DateTime*)args[1].addr,
GetTupleResultType(s)));
return 0;
case REQUEST:
if(!local.addr){
return CANCEL;
}
li = (GPSLI*) local.addr;
t = li->NextTuple();
result.setAddr(t);
if(t){
return YIELD;
} else {
return CANCEL;
}
case CLOSE:
if(local.addr)
{
li = (GPSLI*) local.addr;
delete li;
local.setAddr(0);
}
return 0;
}
return 0;
}
/*
16.3.47 ~Disturb~
*/
int DisturbVM(Word* args, Word& result, int message, Word& local, Supplier s){
result = qp->ResultStorage(s);
MPoint* res = static_cast<MPoint*>(result.addr);
MPoint* mp = static_cast<MPoint*>(args[0].addr);
CcReal* md = static_cast<CcReal*>(args[1].addr);
CcReal* mdps = static_cast<CcReal*>(args[2].addr);
res->Clear();
if( !mp->IsDefined() || !md->IsDefined() || !mdps->IsDefined() ){
res->SetDefined(false);
} else {
mp->Disturb(*res, md->GetRealval(), mdps->GetRealval());
}
return 0;
}
/*
16.3.48 ~Length~
*/
int LengthVM(Word* args, Word& result, int message,
Word& local, Supplier s){
result = qp->ResultStorage(s);
CcReal* res = (CcReal*)result.addr;
MPoint* mp = (MPoint*) args[0].addr;
if(!mp->IsDefined()){
res->Set(false, 0.0);
return 0;
}
if(qp->GetNoSons(s)==2){ // variant using (LON,LAT)-coordinates
CcString* geoidCcStr = static_cast<CcString*>(args[1].addr);
if(!geoidCcStr->IsDefined()){
res->Set(false, 0.0);
return 0;
}
std::string geoidstr = geoidCcStr->GetValue();
bool valid = false;
Geoid::GeoidName gn = Geoid::getGeoIdNameFromString(geoidstr,valid);
if(!valid){
res->Set(false, 0.0);
return 0;
}
Geoid geoid(gn);
res->Set(true, mp->Length(geoid,valid));
res->SetDefined(valid);
} else { // normal variant using (X,Y)-coordinates
res->Set(true, mp->Length());
}
return 0;
}
/*
16.3.49 Some specialized valuemappings for type MPoint
*/
// specialized case MPoint: use MBR
// All other cases: template<>MappingNotEqual()
int MPointNotEqual( Word* args, Word& result,
int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
if( ((MPoint*)args[0].addr)->IsDefined()
&& ((MPoint*)args[1].addr)->IsDefined() ) {
((CcBool*)result.addr)->
Set( true, *((MPoint*)args[0].addr) != *((MPoint*)args[1].addr) );
} else {
((CcBool*)result.addr)->Set( false, false );
}
return 0;
}
// specialized case MPoint: use MBR
// All other cases: template<>MappingEqual()
int MPointEqual( Word* args, Word& result,
int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
if( ((MPoint*)args[0].addr)->IsDefined()
&& ((MPoint*)args[1].addr)->IsDefined() ) {
((CcBool*)result.addr)->
Set( true, *((MPoint*)args[0].addr) == *((MPoint*)args[1].addr) );
} else {
((CcBool*)result.addr)->Set( false, false );
}
return 0;
}
// specialized case MPoint: use MBR
// All other cases: template<>MappingPresent_i()
int MPointPresent_i( Word* args, Word& result,
int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
MPoint *m = ((MPoint*)args[0].addr);
Instant* inst = ((Instant*)args[1].addr);
if( !inst->IsDefined() || !m->IsDefined())
((CcBool *)result.addr)->Set( false, false );
else
((CcBool *)result.addr)->Set( true, m->Present( *inst ) );
return 0;
}
// specialized case MPoint: use MBR
// All other cases: template<>MappingPresent_p()
int MPointPresent_p( Word* args, Word& result,
int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
MPoint *m = ((MPoint*)args[0].addr);
Periods* periods = ((Periods*)args[1].addr);
if( periods->IsEmpty() )
((CcBool *)result.addr)->Set( false, false );
else
((CcBool *)result.addr)->Set( true, m->Present( *periods ) );
return 0;
}
template<class M, class P>
int MTypeAtInstant(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
M* src = ((M*)args[0].addr);
Instant* inst = (Instant*)args[1].addr;
Intime<P>* pResult = (Intime<P>*)result.addr;
src->AtInstant(*inst, *pResult);
return 0;
}
template<class T>
int MTypeAtPeriods(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
T* src = ((T*)args[0].addr);
T* pResult = (T*)result.addr;
Periods* per = (Periods*)args[1].addr;
src->AtPeriods(*per, *pResult);
return 0;
}
int MPointEqualize( Word* args, Word& result, int message,
Word& local, Supplier s ) {
result = qp->ResultStorage(s);
MPoint* res = static_cast<MPoint*>(result.addr);
res->Clear();
MPoint* p = static_cast<MPoint*>(args[0].addr);
CcReal* eps = static_cast<CcReal*>(args[1].addr);
CcBool skipUnits(true,false);
if(qp->GetNoSons(s)==3){
skipUnits = * (static_cast<CcBool*>(args[2].addr));
}
if(!p->IsDefined() || !eps->IsDefined() || !skipUnits.IsDefined()){
res->SetDefined(false);
return 0;
}
p->EqualizeUnitsSpatial(eps->GetValue(),*res,skipUnits.GetBoolval());
return 0;
}
int MIntHat( Word* args, Word& result, int message,
Word& local, Supplier s ) {
MInt* mint = (MInt*)args[0].addr;
result = qp->ResultStorage(s);
mint->Hat(*(MInt*)result.addr);
return 0;
}
int restrictVM1( Word* args, Word& result, int message,
Word& local, Supplier s ) {
result = qp->ResultStorage(s);
MInt* res = static_cast<MInt*>(result.addr);
MInt* arg = static_cast<MInt*>(args[0].addr);
arg->Restrict(*res);
return 0;
}
int restrictVM2( Word* args, Word& result, int message,
Word& local, Supplier s ) {
result = qp->ResultStorage(s);
MInt* res = static_cast<MInt*>(result.addr);
MInt* arg1 = static_cast<MInt*>(args[0].addr);
CcInt* arg2 = static_cast<CcInt*>(args[1].addr);
if(!arg2->IsDefined()){
res->Clear();
res->SetDefined(false);
return 0;
}
arg1->Restrict(*res,true,arg2->GetIntval());
return 0;
}
int SpeedUpVM( Word* args, Word& result, int message,
Word& local, Supplier s ) {
result = qp->ResultStorage(s);
MPoint* res = static_cast<MPoint*>(result.addr);
MPoint* arg1 = static_cast<MPoint*>(args[0].addr);
CcReal* arg2 = static_cast<CcReal*>(args[1].addr);
res->Clear();
if(!arg1->IsDefined() || !arg2->IsDefined() ){
res->SetDefined(false);
return 0;
}
if(AlmostEqual(arg2->GetRealval(),0.0)){
*res = *arg1;
return 0;
}
res->SetDefined( true );
UPoint up;
UPoint last;
UPoint* cur;
res->StartBulkLoad();
double factor = 1.0/arg2->GetRealval();
for(int i = 0;i < arg1->GetNoComponents();i++){
arg1->Get(i,up);
if(i == 0){
last = up;
last.timeInterval.end =
(last.timeInterval.end-last.timeInterval.start)*factor+
last.timeInterval.start;
res->MergeAdd(last);
}else{
cur = new UPoint(up);
cur->timeInterval.start = last.timeInterval.end;
cur->timeInterval.end = cur->timeInterval.start +
(up.timeInterval.end - up.timeInterval.start)*factor;
res->MergeAdd(*cur);
last = *cur;
delete cur;
}
}
res->EndBulkLoad();
return 0;
}
/*
ValueMapping for operator ~avg\_speed~
*/
int Avg_SpeedVM( Word* args, Word& result, int message,
Word& local, Supplier s ) {
result = qp->ResultStorage(s);
CcReal* res = static_cast<CcReal*>(result.addr);
MPoint* arg1 = static_cast<MPoint*>(args[0].addr);
if(!arg1->IsDefined() || arg1->IsEmpty()){
res->Set(false, 0.0);
return 0;
}
Geoid* geoidptr = 0;
bool valid = true;
if(qp->GetNoSons(s)==2){ // setting up geoid for (LON,LAT)-variant
CcString* geoidCcStr = static_cast<CcString*>(args[1].addr);
if(!geoidCcStr->IsDefined()){
res->Set(false, 0.0);
return 0;
}
std::string geoidstr = geoidCcStr->GetValue();
Geoid::GeoidName gn = Geoid::getGeoIdNameFromString(geoidstr,valid);
if(!valid){
res->Set(false, 0.0);
return 0;
}
geoidptr = new Geoid(gn);
}
double length = 0;
DateTime totaltime(0,0,durationtype);
UPoint up;
for(int i = 0; valid && (i<arg1->GetNoComponents()); i++){
arg1->Get(i,up);
totaltime += (up.timeInterval.end - up.timeInterval.start);
if(geoidptr) { // (LON,LAT)
length += up.p0.DistanceOrthodrome(up.p1, *geoidptr, valid);
} else { // (X,Y)
length += up.p0.Distance(up.p1);
}
}
res->Set(valid,length/(totaltime.millisecondsToNull()/ 1000.0));
if(geoidptr){
delete geoidptr;
geoidptr = 0;
}
return 0;
}
int SubMoveVM( Word* args, Word& result, int message,
Word& local, Supplier s ) {
result = qp->ResultStorage(s);
MPoint* res = static_cast<MPoint*>(result.addr);
MPoint* arg1 = static_cast<MPoint*>(args[0].addr);
CcReal* arg2 = static_cast<CcReal*>(args[1].addr);
res->Clear();
if(!arg1->IsDefined() || arg2->GetRealval() <= 0.0 ||
arg1->GetNoComponents() == 0){
res->SetDefined( false );
return 0;
}
res->SetDefined( true );
if(arg2->GetRealval() >= 1.0){
res->StartBulkLoad();
UPoint up;
for(int i = 0;i < arg1->GetNoComponents();i++){
arg1->Get(i,up);
res->Add(up);
}
res->EndBulkLoad( true, true );
return 0;
}
UPoint up1;
UPoint up2;
UPoint* cur;
res->StartBulkLoad();
double factor = arg2->GetRealval();
arg1->Get(0,up1);
arg1->Get(arg1->GetNoComponents()-1,up2);
Instant dt = (up2.timeInterval.end - up1.timeInterval.start)*factor;
srand(time(0));
int pos = rand() % arg1->GetNoComponents();
assert(pos < arg1->GetNoComponents());
arg1->Get(pos,up1);
Instant enddt = up1.timeInterval.start + dt;
cur = new UPoint(up1);
if(enddt <= cur->timeInterval.end){
Point p1;
cur->TemporalFunction(enddt,p1,true);
assert(p1.IsDefined());
cur->timeInterval.end = cur->timeInterval.start+dt;
cur->p1 = p1;
res->Add(*cur);
}else{
res->Add(*cur);
UPoint* up;
for(pos++;pos < arg1->GetNoComponents();pos++){
arg1->Get(pos,up1);
if(up1.timeInterval.end < enddt){
res->Add(up1);
}else{
up = new UPoint(up1);
Point p1;
up->TemporalFunction(enddt,p1,true);
assert(p1.IsDefined());
up->timeInterval.end = enddt;
up->p1 = p1;
res->Add(*up);
delete up;
break;
}
}
}
delete cur;
res->EndBulkLoad(true,true);
return 0;
}
int Mp2OneMpVM( Word* args, Word& result, int message,
Word& local, Supplier s ) {
result = qp->ResultStorage(s);
MPoint* res = static_cast<MPoint*>(result.addr);
MPoint* arg = static_cast<MPoint*>(args[0].addr);
Instant* start = (Instant*)args[1].addr;
Instant* end = (Instant*)args[2].addr;
res->Clear();
if( !arg->IsDefined() || arg->GetNoComponents() == 0
|| !start->IsDefined() || !end->IsDefined() || (*end < *start) ){
res->SetDefined(false);
return 0;
}
res->SetDefined(true);
res->StartBulkLoad();
srand(time(0)+counter);
int pos = rand() % arg->GetNoComponents();
assert( 0<= pos );
assert( pos < arg->GetNoComponents() );
UPoint up;
arg->Get(pos,up);
UPoint cur(up);
double x = (cur.p0.GetX() + counter); // XRIS: NONSENSE here!
double y = (cur.p0.GetY() + counter); // XRIS: NONSENSE here!
std::cerr << "WARNING: " << __PRETTY_FUNCTION__
<< " called. This functions does nonsense! Please correct!" << endl;
Point p(true,x,y);
cur.timeInterval.start = *start;
cur.timeInterval.end = *end;
cur.p0 = p;
cur.p1 = p;
res->Add(cur);
counter++;
res->EndBulkLoad(true, true);
return 0;
}
int P2MpVM( Word* args, Word& result, int message,
Word& local, Supplier s ) {
result = qp->ResultStorage(s);
MPoint* res = static_cast<MPoint*>(result.addr);
res->Clear();
Point* arg = static_cast<Point*>(args[0].addr);
Instant* startt = (Instant*)args[1].addr;
Instant* endt = (Instant*)args[2].addr;
if( !arg->IsDefined() || !startt->IsDefined() || !endt->IsDefined()
|| !((CcInt*)args[3].addr)->IsDefined() ) {
res->SetDefined(false);
return 0;
}
unsigned int no = ((CcInt*)args[3].addr)->GetIntval();
if( no<= 0 ) {
res->SetDefined(false);
return 0;
}
res->SetDefined( true );
res->StartBulkLoad();
double delta = (*endt - *startt).ToDouble()/no;
Instant tempstart = *startt;
for(unsigned int i = 0;i < no;i ++){
UPoint* up = new UPoint(true);
// up->timeInterval.start = *startt;
// up->timeInterval.end = *endt;
up->timeInterval.start = tempstart;
Instant end_t(instanttype);
end_t.ReadFrom(tempstart.ToDouble()+delta);
up->timeInterval.end = end_t;
tempstart = end_t;
up->timeInterval.lc = true;
up->timeInterval.rc = false;
up->p0 = *arg;
up->p1 = *arg;
res->Add(*up);
// cout<<*up<<endl;
delete up;
}
res->EndBulkLoad(true,true);
return 0;
}
/*
1.1.1 Value Mapping for Operator ~turns~
Class for the localinfo in operator ~turns~:
*/
class TurnsLocalInfo{
public:
double minDiff;
double maxDiff;
DateTime maxDur;
int currUnitIndex;
int noUnits;
UPoint lastUnit;
UPoint currUnit;
bool finished;
bool isFirstUnit;
bool useMaxDur;
TupleType *resultTupleType;
TurnsLocalInfo( const MPoint &mp_,
const CcReal &minDiff_,
const CcReal &maxDiff_,
const DateTime &maxDur_) :
minDiff(0.0),
maxDiff(0.0),
maxDur(-9999,-9999,durationtype),
currUnitIndex(0),
noUnits(0),
lastUnit(false),
currUnit(false),
finished(false),
isFirstUnit(true),
useMaxDur(false),
resultTupleType(0)
{
if( !mp_.IsDefined() || !minDiff_.IsDefined() || !maxDiff_.IsDefined()
|| !maxDur_.IsDefined() ){
finished = true;
} else {
minDiff = fabs(minDiff_.GetValue());
maxDiff = fabs(maxDiff_.GetValue());
maxDur = maxDur_;
noUnits = mp_.GetNoComponents();
finished = (noUnits <= currUnitIndex);
useMaxDur = !(maxDur.ToDouble() < 0.0);
finished = !(maxDiff >= minDiff);
}
}
~TurnsLocalInfo(){
if(resultTupleType){
resultTupleType->DeleteIfAllowed();
}
}
};
/*
Value mapping Function
*/
int TurnsOperatorValueMapping( Word* args, Word& result, int message,
Word& local, Supplier s ) {
TurnsLocalInfo *li = static_cast<TurnsLocalInfo*>(local.addr);
UPoint u(false);
// extract appended parameter encoding optional parameter info
int no_args = qp->GetNoSons(s);
const CcInt* ccArgcode = static_cast<const CcInt*>(args[no_args-1].addr);
assert(ccArgcode && ccArgcode->IsDefined());
int argcode = ccArgcode->GetIntval();
assert( (argcode>=0) && (argcode<=7) );
// determine presence and location of optional parameters
int iDuration = ((argcode==1)||(argcode==3)||(argcode==5)||(argcode==7))?
3:-1;
int iBool = (argcode==0)?-1:(((argcode==2)||(argcode==6))?
3:(((argcode==3)||(argcode==7))?4:-1));
int iGeoid = (argcode<=0)?-1:((argcode==4)?
3:(((argcode==5)||(argcode==6))?4:((argcode==7)?5:-1)));
// extract parameters
const MPoint* m = static_cast<const MPoint*>(args[0].addr);
const CcReal* minDiff = static_cast<const CcReal*>(args[1].addr);
const CcReal* maxDiff = static_cast<const CcReal*>(args[2].addr);
DateTime* maxDur = (iDuration>=0)?
static_cast<DateTime*>(args[iDuration].addr):0;
const CcBool* useHeading = (iBool>=0)?
static_cast<const CcBool*>(args[iBool].addr):0;
const Geoid* geoid = (iGeoid>=0)?
static_cast<const Geoid*>(args[iGeoid].addr):0;
bool deleteMaxDur = false;
bool useHead = useHeading && useHeading->GetBoolval();
// initialize result attributes
double lastHead = 0.0, currHead = 0.0, diffHead = 0.0;
Point *lastPos=0, *currPos=0;
DateTime *lastTime = 0, *currTime=0;
CcReal *lastHeading=0, *currHeading=0, *diffHeading=0;
bool found = true;
Tuple *newTuple = 0;
switch( message )
{
case OPEN:
if(!maxDur){
maxDur = new DateTime(-9999,-9999,durationtype);
maxDur->SetDefined(true);
deleteMaxDur = true;
} // else maxDur already passed as parameter
li = new TurnsLocalInfo(*m, *minDiff, *maxDiff, *maxDur);
local.addr = li;
if(!li->resultTupleType){
li->resultTupleType =
new TupleType(nl->Second(GetTupleResultType(s)));
}
if(deleteMaxDur){
delete maxDur;
deleteMaxDur = false;
maxDur = 0;
}
return 0;
case REQUEST:
if( !local.addr || li->finished ) {
return CANCEL;
}
found = false;
while( !found && (li->currUnitIndex < li->noUnits) ) {
m->Get( li->currUnitIndex, li->currUnit );
if( li->isFirstUnit ) {
// We just started: save currUnit and continue
li->lastUnit = li->currUnit;
li->isFirstUnit = false;
} else if( li->useMaxDur && ( li->maxDur <
(li->currUnit.timeInterval.start - li->lastUnit.timeInterval.end)))
{
// We encountered a 'time warp': save currUnit and restart
li->lastUnit = li->currUnit;
li->isFirstUnit = true;
} else if( AlmostEqual(li->lastUnit.p0,li->lastUnit.p1) ) {
// The last unit was static: replace by currUnit
li->lastUnit = li->currUnit;
} else if( AlmostEqual(li->currUnit.p0,li->currUnit.p1) ) {
// The current unit is static: don't save and continue
} else {
// now, we have 2 units. Both are non-static and temporally near
// enough...
lastHead = li->lastUnit.p0.Direction(li->lastUnit.p1,useHead,geoid);
currHead = li->currUnit.p0.Direction(li->currUnit.p1,useHead,geoid);
diffHead = currHead - lastHead;
if(diffHead > 180.0) {
diffHead = 360.0 - diffHead;
} else if(diffHead < -180.0){
diffHead = 360.0 + diffHead;
}
if(diffHead <= -180.0){
diffHead *= -1.0;
}
if( (fabs(diffHead) >= li->minDiff)
&& (fabs(diffHead) <= li->maxDiff) ) {
// create attributes for result tuple
double x1= li->lastUnit.p0.GetX(), y1= li->lastUnit.p0.GetY(),
x2= li->lastUnit.p1.GetX(), y2= li->lastUnit.p1.GetY(),
x3= li->currUnit.p1.GetX(), y3= li->currUnit.p1.GetY(),
detA= x2*y3 - x3*y2 - x1*y3 + x3*y1 + x1*y2 - x2*y1;
diffHead= (detA > 0)? fabs(diffHead): -1 * fabs(diffHead);
lastTime = new DateTime(li->lastUnit.timeInterval.end);
currTime = new DateTime(li->currUnit.timeInterval.start);
lastPos = new Point(li->lastUnit.p1);
currPos = new Point(li->currUnit.p0);
lastHeading = new CcReal(true, lastHead);
currHeading = new CcReal(true, currHead);
diffHeading = new CcReal(true, diffHead);
found = true;
} else { ; // nothing to do here
}
li->lastUnit = li->currUnit;
}
li->currUnitIndex++;
} // end while
if(li->currUnitIndex >= li->noUnits){
li->finished = true;
}
if(found){
// create a result tuple
newTuple = new Tuple( li->resultTupleType );
newTuple->PutAttribute( 0,(Attribute*)lastTime );
newTuple->PutAttribute( 1,(Attribute*)currTime );
newTuple->PutAttribute( 2,(Attribute*)lastPos );
newTuple->PutAttribute( 3,(Attribute*)currPos );
newTuple->PutAttribute( 4,(Attribute*)lastHeading );
newTuple->PutAttribute( 5,(Attribute*)currHeading );
newTuple->PutAttribute( 6,(Attribute*)diffHeading );
result.setAddr(newTuple);
return YIELD;
} else {
return CANCEL;
}
case CLOSE:
if(local.addr){
delete li;
local.addr = 0;
}
return 0;
}
/* should not happen */
return -1;
}
/*
1.1.1 Value Mappings for Operator ~gridcellevents~
1.1.1.1 Class ~GridCellEventsLocalInfo~
The class provides an iterator that allows to request the results for all
signatures (mpoint and upoint) of operator ~gridcellevents~ one by one using
function ~getNextResultTuple~
*/
template<class OBJTYPE>
class GridCellEventsLocalInfo{
public:
std::vector<GridCellSeq>::iterator currEvent;
GridCellEventsLocalInfo(OBJTYPE &m_,
const CcReal &x0, const CcReal &y0,
const CcReal &wx, const CcReal &wy,
const CcInt &nx,
const Supplier &s) :
m(&m_),
g(0),
events(0),
resultTupleType(0),
noUnits(0),
currUnitCnt(0),
finished(true),
allUnitsConsumed(true),
eventIter(events.begin()),
cellLast(0),
currentEvent()
{
if( m->IsDefined() && x0.IsDefined() && wx.IsDefined()
&& wy.IsDefined() && nx.IsDefined() )
{
g = new CellGrid2D( x0.GetValue(),y0.GetValue(),
wx.GetValue(),wy.GetValue(),
nx.GetValue());
noUnits = GetNoComponents(m);
finished = !(g->IsDefined() && (noUnits>0));
allUnitsConsumed = (currUnitCnt>=noUnits);
events.clear();
cellLast = g->getInvalidCellNo();
resultTupleType = new TupleType(nl->Second(GetTupleResultType(s)));
}
}
GridCellEventsLocalInfo(OBJTYPE &m_,
const CellGrid2D& grid,
const Supplier &s) :
m(&m_),
g(0),
events(0),
resultTupleType(0),
noUnits(0),
currUnitCnt(0),
finished(true),
allUnitsConsumed(true),
eventIter(events.begin()),
cellLast(0),
currentEvent()
{
if( m->IsDefined() && grid.IsDefined() )
{
g = new CellGrid2D( grid );
noUnits = GetNoComponents(m);
finished = !(g->IsDefined() && (noUnits>0));
allUnitsConsumed = (currUnitCnt>=noUnits);
events.clear();
cellLast = g->getInvalidCellNo();
resultTupleType = new TupleType(nl->Second(GetTupleResultType(s)));
}
}
~GridCellEventsLocalInfo(){
if(resultTupleType){
resultTupleType->DeleteIfAllowed();
resultTupleType = 0;
}
if(g){
delete g;
g = 0;
}
}
uint32_t GetNoComponents(MPoint* m){ return m->GetNoComponents(); }
uint32_t GetNoComponents(UPoint* m){ return 1; }
bool isFinished() const {return finished;}
Tuple* getNextResultTuple() {
// Returns a pointer to the next generated result tuple.
// Returns 0 iff no more result is available
Tuple *newTuple = 0;
if(finished){ // nothing to do
return newTuple;
}
// get the next result using private method
int32_t cell = g->getInvalidCellNo(),
cellprev = g->getInvalidCellNo(),
cellnext = g->getInvalidCellNo();
DateTime timeenter(instanttype),
timeleave(instanttype);
if(next(cell, timeenter, timeleave, cellprev, cellnext)){
CcInt *ccCell = new CcInt(g->isValidCellNo(cell), cell);
DateTime *ccTimeEntered = new DateTime(timeenter);
DateTime *ccTimeLeft = new DateTime(timeleave);
CcInt *ccCellPrevious = new CcInt(g->isValidCellNo(cellprev), cellprev);
CcInt *ccCellNext = new CcInt(g->isValidCellNo(cellnext), cellnext);
// create the result tuple and return it
newTuple = new Tuple( resultTupleType );
newTuple->PutAttribute( 0,(Attribute*)ccCell );
newTuple->PutAttribute( 1,(Attribute*)ccTimeEntered );
newTuple->PutAttribute( 2,(Attribute*)ccTimeLeft );
newTuple->PutAttribute( 3,(Attribute*)ccCellPrevious );
newTuple->PutAttribute( 4,(Attribute*)ccCellNext );
}
return newTuple;
}
std::ostream& Print( std::ostream &os ) {
os << "(GridCellEventsLocalInfo: "
<< "\n\t m: " << *m
<< ",\n\t g: " << *g;
printEvents(os);
os << ",\n\t resultTupleType: " << resultTupleType
<< ",\n\t noUnits: " << noUnits
<< ",\n\t currUnitCnt: " << currUnitCnt
<< ",\n\t finished: " << (finished ? "true" : "false")
<< ",\n\t allUnitsConsumed: " << (allUnitsConsumed ? "true" : "false")
<< ",\n\t eventIter: <unprintable>"
<< ",\n\t cellLast: " << cellLast
<< ",\n\t currentEvent: " << currentEvent
<< "\n)" << endl;
return os;
}
private:
OBJTYPE *m;
CellGrid2D *g;
std::vector<GridCellSeq> events;
TupleType *resultTupleType;
uint32_t noUnits;
uint32_t currUnitCnt;
bool finished;
bool allUnitsConsumed;
std::vector<GridCellSeq>::iterator eventIter;
int32_t cellLast; // number of last visited cell
GridCellSeq currentEvent; // the current cell info
bool next(int32_t &cell,
DateTime &timestart, DateTime &timeend,
int32_t &cellprev, int32_t &cellnext)
{
// returns true iff a result was produced and the result parameters are
// valid. When returning false, the result parameters are invalid.
//
// The functions scanns the event vector for interesting event
// combinations, such as
// (1) consecutive events should be merged,
// (a) consecutive non-valid events should always be merged.
// (b) if there is no temporal gap and both have the same Cell.
// (2) Only events inside the grid (with valid cellNo) qualify for
// being reported as a result. Events in non-valid cell are only
// used to report UNDEF last/next cell numbers.
// cout << __PRETTY_FUNCTION__ << " called." << endl;
assert(!finished);
if(finished){
// cout << __PRETTY_FUNCTION__ << " finished (false)." << endl;
return false;
}
GridCellSeq nextEvent = GridCellSeq();
bool found = false;
bool yield = false;
if( eventIter == events.end() ){ // try to refill event-vector
tryReload(m);
// bool ok = tryReload(m);
// cout << "\tInitial tryRelod: " << (ok ? "succeeded." : "failed.")
// << endl;
}
// merge consecutive events with same cell number and find a nextEvent
while( eventIter < events.end() ){
// cout << "\t\tBegin of while-loop: cellLast=" << cellLast
// << ", currentEvent=" << currentEvent
// << ", nextEvent=" << nextEvent
// << ")" << endl;
assert(eventIter->IsDefined()); // events from vector should be defined
if(currentEvent.IsDefined()){ // initialized with UNDEF event!
if(eventIter->getCellNo() == currentEvent.getCellNo()) {
// cout << "\t\tSame cell: " << eventIter->getCellNo() << endl;
// still within the same cell
Point pcurr(false), pnext(false);
m->TemporalFunction(eventIter->getEnterTime(), pnext, true);
m->TemporalFunction(currentEvent.getLeaveTime(), pcurr, true);
if( !g->isValidCellNo(eventIter->getCellNo())
|| ( eventIter->getEnterTime() == currentEvent.getLeaveTime() )
)
{ // covers the following case: curr and next cell are the same
// and EITHER the cell is off the grid OR the two are temporally
// connected
// --> merge the events
// cout << "\t\tMerged events:\n\t\t\tcurr=" << currentEvent
// << "\t\t\tnext=" << *eventIter;
currentEvent.set( currentEvent.getCellNo(),
currentEvent.getEnterTime(),
eventIter->getLeaveTime());
// cout << "\t\t\tmerged event: curr = " << currentEvent << endl;
} else if( eventIter->getEnterTime()!=currentEvent.getLeaveTime() )
{
// both events are valid with same cell but are temporally
// unconnected (showing a 'timewarp')
// --> set return parameters
nextEvent = *eventIter; // save for terminal call (after loop)
cell = currentEvent.getCellNo();
timestart = currentEvent.getEnterTime();
timeend = currentEvent.getLeaveTime();
cellprev = cellLast;
cellnext = g->getInvalidCellNo(); // to indicate 'timewarp'
yield = true;
currentEvent.setCellNo(g->getInvalidCellNo()); // modify
// cout << "\t\tcurr is valid (warp-case). Result: (Cell=" << cell
// << ", TimeEnter=" << timestart
// << ", TimeLeave=" << timeend
// << ", CellPrevious=" << cellprev
// << ", CellNext=" << cellnext
// << ")." << endl;
cellLast = g->getInvalidCellNo(); // to indicate 'timewarp'
nextEvent = *eventIter; // save for terminal call (after loop)
currentEvent = nextEvent;
} else {
// curr and next are temporally unconnected
nextEvent = *eventIter; // save for terminal call (after loop)
found = true;
// cout << "\t\tFound interesting event (Same cells - "
// << "SHOULD NOT HAPPEN!):\n\t\t\tcurr="
// << currentEvent << "\n\t\t\tnext=" << *eventIter << endl;
}
} else {
nextEvent = *eventIter; // save for terminal call (after the loop)
found = true;
// cout << "\t\tFound interesting event:\n\t\t\tcurr="
// << currentEvent << "\n\t\t\tnext=" << *eventIter << endl;
}
// try handling results
if( found ){
if(g->isValidCellNo(currentEvent.getCellNo())){
// currentEvent valid --> set return parameters
cell = currentEvent.getCellNo();
timestart = currentEvent.getEnterTime();
timeend = currentEvent.getLeaveTime();
cellprev = cellLast;
cellnext = nextEvent.getCellNo();
yield = true; // flag to return at end of this loop!
// cout << "\t\tcurr is valid (normal case). Result: (Cell="
// << cell
// << ", TimeEnter=" << timestart
// << ", TimeLeave=" << timeend
// << ", CellPrevious=" << cellprev
// << ", CellNext=" << cellnext
// << ")." << endl;
} else {
// cout << "\t\tcurr is invalid. Ignore!" << endl;
;
}
cellLast = currentEvent.getCellNo();
currentEvent = nextEvent;
found = false;
}
} else { // currEvent is not defined (first call)
// cout << "\t\tInitial event: shift" << endl;
currentEvent = *eventIter;
}
// advance iterator to next event
eventIter++;
if(eventIter == events.end()){
// no more events generated by this unit - try loading new events
// from the next unit:
tryReload(m);
// bool ok = tryReload(m);
// cout << "\ttryRelod: " << (ok ? "succeeded." : "failed.") << endl;
}
if(yield){
// cout << __PRETTY_FUNCTION__ << " finished (true)." << endl;
return true; // result was generated --> return
}
// cout << "\t\tEnd of while-loop: cellLast=" << cellLast
// << ", currentEvent=" << currentEvent
// << ", nextEvent=" << nextEvent
// << ")" << endl;
} // end while
// no nextEvent found. Try to process current event
if(g->isValidCellNo(currentEvent.getCellNo())){
// No nextEvent, but currentEvent is on the grid --> produce a result
cell = currentEvent.getCellNo();
timestart = currentEvent.getEnterTime();
timeend = currentEvent.getLeaveTime();
cellprev = cellLast;
cellnext = g->getInvalidCellNo();
// cout << "\t\tTerminal event: curr is valid. Result: (Cell=" << cell
// << ", TimeEnter=" << timestart
// << ", TimeLeave=" << timeend
// << ", CellPrevious=" << cellprev
// << ", CellNext=" << cellnext
// << ")." << endl;
finished = true; // because no more events available!
// cout << __PRETTY_FUNCTION__ << " finished (true)." << endl;
return true;
} else {// else: currentEvent not on grid and no more events --> finished!
// cout << "\t\tTerminal event: curr is invalid." << endl;
;
}
finished = true;
// cout << __PRETTY_FUNCTION__ << " finished (false)." << endl;
return false;
}
bool tryReload(UPoint* dummy_) {
// Reloads the event vector with new elements created using the mpoint's
// next unit. The old content of ~event~ is lost!
// Returns true iff reloading was successful.
if(allUnitsConsumed) { return false; }; // do nothing
// UPoint version
m->GetGridCellSequence(*g, events);
currUnitCnt++;
if(currUnitCnt>=noUnits){
allUnitsConsumed = true;
}
eventIter = events.begin();
return true;
}
bool tryReload(MPoint* dummy_) {
// Reloads the event vector with new elements created using the mpoint's
// next unit. The old content of ~event~ is lost!
// Returns true iff reloading was successful.
if(allUnitsConsumed) { return false; }; // do nothing
UPoint u(true);
m->Get(currUnitCnt, u);
u.GetGridCellSequence(*g, events);
currUnitCnt++;
if(currUnitCnt>=noUnits){
allUnitsConsumed = true;
}
eventIter = events.begin();
return true;
}
std::ostream& printEvents( std::ostream &os,
const std::string prefix = "\n\t",
const std::string prefix2 = "\t") {
os << prefix2 << "events: [";
std::vector<GridCellSeq>::iterator i;
for(i = events.begin(); i < events.end(); i++){
os << prefix << prefix2 << *i;
}
os << prefix2 << "]";
return os;
}
};
template<class OBJTYPE>
std::ostream& operator<<(std::ostream& o, GridCellEventsLocalInfo<OBJTYPE>& u){
return u.Print(o);
}
template<class OBJTYPE>
int GridCellEventsVM( Word* args, Word& result, int message,
Word& local, Supplier s ) {
GridCellEventsLocalInfo<OBJTYPE> *li =
static_cast<GridCellEventsLocalInfo<OBJTYPE>*>(local.addr);
switch( message )
{
case OPEN: {
// cout << __PRETTY_FUNCTION__ << ": OPEN called..." << endl;
OBJTYPE* m = static_cast<OBJTYPE*> (args[0].addr);
int noSons = qp->GetNoSons(s);
if(li){ delete li; }
if(noSons==6){
CcReal* x0 = static_cast<CcReal*>(args[1].addr);
CcReal* y0 = static_cast<CcReal*>(args[2].addr);
CcReal* wx = static_cast<CcReal*>(args[3].addr);
CcReal* wy = static_cast<CcReal*>(args[4].addr);
CcInt* nx = static_cast<CcInt*> (args[5].addr);
li = new GridCellEventsLocalInfo<OBJTYPE>(*m, *x0, *y0, *wx,
*wy, *nx, s);
} else if(noSons==2){
li = new GridCellEventsLocalInfo<OBJTYPE>(*m,
*(static_cast<CellGrid2D*>(args[1].addr)),
s);
} else {
assert(false);
}
local.addr = li;
// cout << "li=" << *li;
// cout << __PRETTY_FUNCTION__ << ": finished OPEN." << endl;
return 0;
}
case REQUEST: {
// cout << __PRETTY_FUNCTION__ << ": REQUEST called..." << endl;
if( !local.addr || li->isFinished() ) {
// cout << __PRETTY_FUNCTION__<< ": finished REQUEST (CANCEL)." << endl;
return CANCEL;
}
// cout << "li=" << *li;
Tuple * newTuple = li->getNextResultTuple();
result.setAddr(newTuple);
if( newTuple != 0) {
// cout << __PRETTY_FUNCTION__ << ": finished REQUEST (YIELD)." << endl;
return YIELD;
}
// cout << __PRETTY_FUNCTION__ << ": finished REQUEST (CANCEL)." << endl;
return CANCEL;
}
case CLOSE:{
// cout << __PRETTY_FUNCTION__ << ": CLOSE called..." << endl;
if(local.addr){
// cout << "li=" << *li;
delete li;
li = 0;
local.addr = 0;
}
// cout << __PRETTY_FUNCTION__ << ": finished CLOSE." << endl;
return 0;
}
}
/* should not happen */
return -1;
}
/*
16.3.29 Value mapping functions of operator ~squareddistance~
*/
int SquaredDistanceMPPVM( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
((MPoint*)args[0].addr)->SquaredDistance( *((Point*)args[1].addr),
*((MReal*)result.addr) );
return 0;
}
int SquaredDistancePMPVM( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
((MPoint*)args[1].addr)->SquaredDistance( *((Point*)args[0].addr),
*((MReal*)result.addr) );
return 0;
}
int SquaredDistanceMPMPVM( Word* args, Word& result, int message, Word&
local, Supplier s )
{
result = qp->ResultStorage( s );
((MPoint*)args[0].addr)->SquaredDistance( *((MPoint*)args[1].addr),
*((MReal*)result.addr) );
return 0;
}
/*
16.4 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.
16.4.1 ValueMapping arrays
*/
ValueMapping temporalisemptymap[] = { InstantIsEmpty,
RangeIsEmpty<RInt>,
RangeIsEmpty<RReal>,
RangeIsEmpty<Periods>,
// MappingIsEmpty<MBool>,
// MappingIsEmpty<MInt>,
// MappingIsEmpty<MReal>,
// MappingIsEmpty<MPoint>,
UnitIsEmpty<UBool>,
UnitIsEmpty<UInt>,
UnitIsEmpty<UReal>,
UnitIsEmpty<UPoint>,
IntimeIsEmpty<CcBool>,
IntimeIsEmpty<CcInt>,
IntimeIsEmpty<CcReal>,
IntimeIsEmpty<Point>};
ValueMapping temporalequalmap[] = { InstantEqual,
RangeEqual<RInt>,
RangeEqual<RReal>,
RangeEqual<Periods >,
IntimeComparePredicates<CcBool,0>,
IntimeComparePredicates<CcInt, 0>,
IntimeComparePredicates<CcReal,0>,
IntimeComparePredicates<Point, 0>
};
ValueMapping temporalequalmap2[] = { MappingEqual<MBool>,
MappingEqual<MInt>,
MappingEqual<MReal>,
MPointEqual };
ValueMapping temporalnotequalmap[] = { InstantNotEqual,
RangeNotEqual<RInt>,
RangeNotEqual<RReal>,
RangeNotEqual<Periods>,
IntimeComparePredicates<CcBool, 1>,
IntimeComparePredicates<CcInt, 1>,
IntimeComparePredicates<CcReal, 1>,
IntimeComparePredicates<Point, 1>};
ValueMapping temporalnotequalmap2[] = { MappingNotEqual<MBool>,
MappingNotEqual<MInt>,
MappingNotEqual<MReal>,
MPointNotEqual };
ValueMapping temporalintersectsmap[] = { RangeIntersects<RInt>,
RangeIntersects<RReal>,
RangeIntersects<Periods> };
ValueMapping temporalinsidemap[] = { RangeInside_rr<RInt>,
RangeInside_rr<RReal>,
RangeInside_rr<Periods>,
RangeInside_ar<CcInt, RInt>,
RangeInside_ar<CcReal, RReal>,
RangeInside_ar<Instant, Periods> };
ValueMapping temporalbeforemap[] = { RangeBefore_rr<RInt>,
RangeBefore_rr<RReal>,
RangeBefore_rr<Periods>,
RangeBefore_ar<CcInt, RInt>,
RangeBefore_ar<CcReal, RReal>,
RangeBefore_ar<Instant, Periods>,
RangeBefore_ra<RInt, CcInt>,
RangeBefore_ra<RReal, CcReal>,
RangeBefore_ra<Periods, Instant> };
ValueMapping temporalintersectionmap[] = { RangeIntersection<RInt>,
RangeIntersection<RReal>,
RangeIntersection<Periods> };
ValueMapping temporalunionmap[] = { RangeUnion<RInt>,
RangeUnion<RReal>,
RangeUnion<Periods> };
ValueMapping temporalminusmap[] = { RangeMinus<RInt>,
RangeMinus<RReal>,
RangeMinus<Periods> };
ValueMapping temporalminmap[] = { RangeMinimum<RInt, CcInt>,
RangeMinimum<RReal, CcReal>,
RangeMinimum<Periods, Instant> };
ValueMapping temporalmaxmap[] = { RangeMaximum<RInt, CcInt>,
RangeMaximum<RReal, CcReal>,
RangeMaximum<Periods, Instant> };
ValueMapping temporalnocomponentsmap[] = {RangeNoComponents<RInt>,
RangeNoComponents<RReal>,
RangeNoComponents<Periods>,
MappingNoComponents<MBool, CcBool>,
MappingNoComponents<MInt, CcInt>,
MappingNoComponents<MReal, CcReal>,
MappingNoComponents<MPoint, Point>,
MappingNoComponents<CMPoint, CPoint>};
ValueMapping temporalbboxmap[] = { UnitBBox<UPoint>,
MTypeBBox<MPoint>,
IPointBBox,
PeriodsBBox,
InstantBBox,
UnitBBox<CUPoint>,
MTypeBBox<CMPoint>};
ValueMapping temporalmbrangemap[] = {
TempMBRange<RInt>,
TempMBRange<RReal>,
TempMBRange<Periods>,
TempMBRange<RBool>,
TempMBRange<RString>};
ValueMapping temporalbboxoldmap[] = { UnitBBox<UPoint>,
TempMBRange<RInt>,
TempMBRange<RReal>,
TempMBRange<Periods>,
MPointBBoxOld,
IPointBBox };
ValueMapping temporalbbox2dmap[] = { UnitBBox2d<UPoint>,
MTypeBBox2d<MPoint>,
IPointBBox2d,
UnitBBox2d<CUPoint>,
MTypeBBox2d<CMPoint>};
ValueMapping temporalinstmap[] = { IntimeInst<CcBool>,
IntimeInst<CcInt>,
IntimeInst<CcReal>,
IntimeInst<Point>,
IntimeInst<CPoint>};
ValueMapping temporalvalmap[] = { IntimeVal<CcBool>,
IntimeVal<CcInt>,
IntimeVal<CcReal>,
IntimeVal<Point>,
IntimeVal<CPoint>};
ValueMapping temporaluvalmap[] = { UIntimeVal<UInt,CcInt>};
ValueMapping temporalatinstantmap[] = { MappingAtInstant<MBool, CcBool>,
MappingAtInstant<MInt, CcInt>,
MappingAtInstant<MReal, CcReal>,
MTypeAtInstant<MPoint, Point>,
MTypeAtInstant<CMPoint, CPoint>};
ValueMapping temporalatperiodsmap[] = { MappingAtPeriods<MBool>,
MappingAtPeriods<MInt>,
MappingAtPeriods<MReal>,
MTypeAtPeriods<MPoint>,
MTypeAtPeriods<CMPoint>};
ValueMapping temporalwhenmap[] = { MappingWhen<MBool>,
MappingWhen<MInt>,
MappingWhen<MReal>,
MappingWhen<MPoint> };
ValueMapping temporaldeftimemap[] = { MappingDefTime<MBool>,
MappingDefTime<MInt>,
MappingDefTime<MReal>,
MappingDefTime<MPoint>,
MappingDefTime<CMPoint>};
ValueMapping temporalpresentmap[] = { MappingPresent_i<MBool>,
MappingPresent_i<MInt>,
MappingPresent_i<MReal>,
MPointPresent_i,
MappingPresent_p<MBool>,
MappingPresent_p<MInt>,
MappingPresent_p<MReal>,
MPointPresent_p };
ValueMapping temporalpassesmap[] = { MappingPasses<MBool, CcBool, CcBool>,
MappingPasses<MInt, CcInt, CcInt>,
MappingPasses<MReal, CcReal, CcReal>,
MappingPasses<MPoint, Point, Point>,
MappingPasses<MPoint, Point, Region>,
MappingPasses<MPoint, Point, Rectangle<2> > };
ValueMapping temporalinitialmap[] = { MappingInitial<MBool, UBool, CcBool>,
MappingInitial<MInt, UInt, CcInt>,
MappingInitial<MReal, UReal, CcReal>,
MappingInitial<MPoint, UPoint, Point>,
MappingInitial<CMPoint, CUPoint, CPoint>};
ValueMapping temporalfinalmap[] = { MappingFinal<MBool, UBool, CcBool>,
MappingFinal<MInt, UInt, CcInt>,
MappingFinal<MReal, UReal, CcReal>,
MappingFinal<MPoint, UPoint, Point>,
MappingFinal<CMPoint, CUPoint, CPoint>};
ValueMapping temporalatmap[] = { MappingAt<MBool, UBool, CcBool>,
MappingAt<MInt, UInt, CcInt>,
MappingAt_MReal_CcReal,
MappingAt<MPoint, UPoint, Point> };
ValueMapping temporalunitsmap[] = { MappingUnits<MBool, UBool>,
MappingUnits<MInt, UInt>,
MappingUnits<MReal, UReal>,
MappingUnits<MPoint, UPoint>,
MappingUnits<CMPoint, CUPoint> };
ValueMapping temporalgetunitmap[] = { MappingGetUnit<MBool, UBool>,
MappingGetUnit<MInt, UInt>,
MappingGetUnit<MReal, UReal>,
MappingGetUnit<MPoint, UPoint>,
MappingGetUnit<CMPoint, CUPoint> };
ValueMapping temporalgetpositionmap[] = { MappingGetPosition<MBool>,
MappingGetPosition<MInt>,
MappingGetPosition<MReal>,
MappingGetPosition<MPoint>,
MappingGetPosition<MString>,
MappingGetPosition<MRegion>,
MappingGetPosition<CMPoint>};
ValueMapping temporalbox3dmap[] = { Box3d_rect,
Box3d_instant,
Box3d_rect_instant,
Box3d_periods,
Box3d_rect_periods};
ValueMapping temporalbox2dmap[] = { TemporalBox2d<2>,
TemporalBox2d<3>,
TemporalBox2d<4>,
TemporalBox2d<8> };
ValueMapping extdeftimemap[] = { TemporalExtDeftime<UBool, CcBool>,
TemporalExtDeftime<UInt, CcInt>
};
ValueMapping simplifymap[] = { MPointSimplify, MPointSimplify2,
MRealSimplify };
ValueMapping linearizemap[] = { Linearize<UReal>, Linearize<MReal> };
ValueMapping linearize2map[] = { Linearize2_ureal, Linearize2 };
ValueMapping integratemap[] = { Integrate<UReal>, Integrate<MReal> };
ValueMapping approximatemap[] = {
ApproximateMvalue<MPoint, UPoint, Point, true>,
ApproximateMvalue<MReal, UReal, CcReal, true>,
ApproximateMvalue<MInt, UInt, CcInt, false>,
ApproximateMvalue<MBool, UBool, CcBool, false>,
ApproximateMvalue<MString, UString, CcString, false>,
ApproximateMvalue<stj::MLabel, stj::ULabel, stj::Label, false>
};
ValueMapping minmap[] = { VM_Min<UReal, CcReal>,
VM_Min<MReal, CcReal>,
VM_Min<MInt, CcInt> };
ValueMapping maxmap[] = { VM_Max<UReal, CcReal>,
VM_Max<MReal, CcReal>,
VM_Max<MInt, CcInt> };
ValueMapping samplempointmap[] = { SampleMPointVM<false,false>,
SampleMPointVM<true,false>,
SampleMPointVM<true,true>};
ValueMapping DistanceAvgMaps[] = {DistanceAvgMap<false>,
DistanceAvgMap<true>};
ValueMapping DistanceAvgLBMaps[] = {DistanceAvgCUMap<false, false>,
DistanceAvgCUMap<true, false>,
DistanceAvgCMMap<false, false>,
DistanceAvgCMMap<true, false>
};
ValueMapping DistanceAvgUBMaps[] = {DistanceAvgCUMap<false, true>,
DistanceAvgCUMap<true, true>,
DistanceAvgCMMap<false, true>,
DistanceAvgCMMap<true, true>};
ValueMapping mpointsquareddistancemap[]= {SquaredDistanceMPPVM,
SquaredDistancePMPVM,
SquaredDistanceMPMPVM};
ValueMapping temporaltherangemap[] = {
TemporalTheRangeTM<Instant>, // 0
TemporalTheRangeTM<CcInt>,
TemporalTheRangeTM<CcBool>,
TemporalTheRangeTM<CcReal>,
TemporalTheRangeTM<CcString> // 4
};
ValueMapping restrictVM[] = {
restrictVM1, restrictVM2
};
ValueMapping MappingTimeShiftMap[] = {
MappingTimeShift<MBool, UBool>,
MappingTimeShift<MInt, UInt>,
MappingTimeShift<MReal, UReal>,
MappingTimeShift<MPoint, UPoint>
};
ValueMapping GridCellEventsValueMapping[] = {
GridCellEventsVM<UPoint>,
GridCellEventsVM<MPoint>
};
/*
16.4.2 Specification strings
*/
const std::string TemporalSpecIsEmpty =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>instant -> bool,\n"
"rT -> bool, \n"
"uT -> bool, \n"
"iT -> bool, \n"
"For T in {bool,int,real,point}</text--->"
"<text>isempty ( _ )</text--->"
"<text>Returns TRUE iff the instant/range/unit type value is "
"undefined or empty.</text--->"
"<text>query isempty( mpoint1 )</text--->"
") )";
const std::string MappingTimeShiftSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>moving(x) x duration -> moving(x)</text--->"
"<text>_ timeshift[ _ ]</text--->"
"<text>Shifts the definition time of a moving object.</text--->"
"<text>train7 timeshift[ create_duration(1, 0) ]</text--->"
") )";
const std::string TemporalSpecEQ =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>(instant instant) -> bool, \n"
"(rT rT) -> bool, \n"
"(iT iT) -> bool</text--->"
"<text>_ = _</text--->"
"<text>Is-Equal predicate for instant and range type values.\n"
"Returns UNDEFINED, iff at least one argument is UNDEFINED.</text--->"
"<text>query i1 = i2</text--->"
") )";
const std::string TemporalSpecEQ2 =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>(moving(x) moving(x)) -> bool</text--->"
"<text>_ equal _</text--->"
"<text>Equal. Returns UNDEFINED, iff at least one argument is "
"UNDEFINED.</text--->"
"<text>query mi equal mi2</text--->"
") )";
const std::string TemporalSpecNE =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>(instant instant) -> bool,\n"
"(rT rT)) -> bool, \n"
"(iT iT) -> bool </text--->"
"<text>_ # _</text--->"
"<text>Not-Equal predicate for instant and range type values. Returns "
"UNDEFINED, iff at least one argument is UNDEFINED.</text--->"
"<text>query i1 # i2</text--->"
") )";
const std::string TemporalSpecNE2 =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>(mT mT) -> bool</text--->"
"<text>_ nonequal _</text--->"
"<text>Not-Equal predicate for moving objects. Returns UNDEFINED, iff at "
"least one argument is UNDEFINED.</text--->"
"<text>query mi1 nonequal mi2</text--->"
") )";
const std::string TemporalSpecLT =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>(instant instant) -> bool</text--->"
"<text>_ < _</text--->"
"<text>Less than. Returns UNDEFINED, iff at least one argument is "
"UNDEFINED.</text--->"
"<text>query i1 < i2</text--->"
") )";
const std::string TemporalSpecLE =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>(instant instant) -> bool</text--->"
"<text>_ <= _</text--->"
"<text>Less or equal than. Returns UNDEFINED, iff at least one argument "
"is UNDEFINED.</text--->"
"<text>query i1 <= i2</text--->"
") )";
const std::string TemporalSpecGT =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>(instant instant) -> bool</text--->"
"<text>_ > _</text--->"
"<text>Greater than. Returns UNDEFINED, iff at least one argument is "
"UNDEFINED.</text--->"
"<text>query i1 > i2</text--->"
") )";
const std::string TemporalSpecGE =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>(instant instant) -> bool</text--->"
"<text>_ >= _</text--->"
"<text>Greater or equal than. Returns UNDEFINED, iff at least one argument "
"is UNDEFINED.</text--->"
"<text>query i1 >= i2</text--->"
") )";
const std::string TemporalSpecIntersects =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>(rT rT) -> bool</text--->"
"<text>_ intersects _</text--->"
"<text>Intersects predicate for range type values.</text--->"
"<text>query range1 intersects range2</text--->"
") )";
const std::string TemporalSpecInside =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>(rT rT) -> bool,\n"
"(T rT) -> bool</text--->"
"<text>_ inside _</text--->"
"<text>Inside predicate for range type values.</text--->"
"<text>query 5 inside rint</text--->"
") )";
const std::string TemporalSpecBefore =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>(rT rT) -> bool,\n"
"(T rT) -> bool, (rT T) -> bool</text--->"
"<text>_ before _ for for range type values and value</text--->"
"<text>Before.</text--->"
"<text>query 5 before rint</text--->"
") )";
const std::string TemporalSpecIntersection =
"( ( \"Signature\" \"Syntax\"\"Meaning\" \"Example\" ) "
"( <text>(rT rT) -> rT</text--->"
"<text>_ intersection _</text--->"
"<text>Intersection for range type values</text--->"
"<text>query range1 intersection range2</text--->"
") )";
const std::string TemporalSpecUnion =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>(rT rT) -> rT</text--->"
"<text>_ union _</text--->"
"<text>Union for range type values.</text--->"
"<text>query range1 union range2</text--->"
") )";
const std::string TemporalSpecMinus =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>(rT rT ) -> rT</text--->"
"<text>_ minus _</text--->"
"<text>Minus for range type values.</text--->"
"<text>query range1 minus range2</text--->"
") )";
const std::string TemporalSpecMinimum =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>rT -> T</text--->"
"<text>minimum ( _ )</text--->"
"<text>Minimum of a range type value.</text--->"
"<text>minimum ( range1 )</text--->"
") )";
const std::string TemporalSpecMaximum =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>rT -> T</text--->"
"<text>maximum ( _ )</text--->"
"<text>Maximum of a range type value.</text--->"
"<text>maximum ( range1 )</text--->"
") )";
const std::string TemporalSpecNoComponents =
"( ( \"Signature\" \"Syntax\"\"Meaning\" \"Example\" ) "
"( <text>rT -> int,\n"
"mT -> int</text--->"
"<text>no_components ( _ )</text--->"
"<text>Number of components within a range type value."
"Number of units inside a moving object value. UNDEFINED argument yields "
"an UNDEFINED result.</text--->"
"<text>no_components ( mpoint1 )</text--->"
") )";
const std::string TemporalSpecInst =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>iT -> instant</text--->"
"<text>inst ( _ )</text--->"
"<text>Return an intime values' time instant.</text--->"
"<text>inst ( i1 )</text--->"
") )";
const std::string TemporalSpecVal =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>iT -> x</text--->"
"<text>val ( _ )</text--->"
"<text>Return an intime value's value.</text--->"
"<text>val ( i1 )</text--->"
") )";
const std::string TemporalSpecUVal =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>uint -> int</text--->"
"<text>uval ( _ )</text--->"
"<text>Return an uint's value.</text--->"
"<text>uval ( ui1 )</text--->"
") )";
const std::string TemporalSpecAtInstant =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>(mT instant) -> iT</text--->"
"<text>_ atinstant _ </text--->"
"<text>From a moving object get the intime value "
"corresponding to the temporal value at the given instant.</text--->"
"<text>mpoint1 atinstant instant1</text--->"
") )";
const std::string TemporalSpecAtPeriods =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>(mT periods) -> mT</text--->"
"<text>_ atperiods _ </text--->"
"<text>Restrict the moving object to the given periods.</text--->"
"<text>mpoint1 atperiods periods1</text--->"
") )";
const std::string TemporalSpecWhen =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>(mT mbool) -> mT</text--->"
"<text>_ when[_] </text--->"
"<text>Restrict the moving object to the times on which the mbool is "
"true.</text--->"
"<text>mpoint1 when[speed(mpoint1) > 10.0]</text--->"
") )";
const std::string TemporalSpecDefTime =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>moving(x) -> periods</text--->"
"<text>deftime( _ )</text--->"
"<text>Get the defined time of the corresponding moving data "
"objects.</text--->"
"<text>deftime( mp1 )</text--->"
") )";
const std::string TemporalSpecTrajectory =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint -> line</text--->"
"<text> trajectory( _ )</text--->"
"<text>Get the trajectory of the corresponding moving point object.</text--->"
"<text>trajectory( mp1 )</text--->"
") )";
const std::string TemporalSpecPresent =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>(mT instant) -> bool,\n"
"(mT periods) -> bool</text--->"
"<text>_ present _ </text--->"
"<text>Check, whether the moving object is present at the given "
"instant or period.</text--->"
"<text>mpoint1 present instant1</text--->"
") )";
const std::string TemporalSpecPasses =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>(mT T) -> bool; T in {Region, Rectangle2}"
"</text--->"
"<text>_ passes _ </text--->"
"<text>Check, whether the moving object passes the given value.</text--->"
"<text>mpoint1 passes point1</text--->"
") )";
const std::string TemporalSpecInitial =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mT -> iT</text--->"
"<text>initial( _ )</text--->"
"<text>Get the intime value corresponding to the initial instant.</text--->"
"<text>initial( mpoint1 )</text--->"
") )";
const std::string TemporalSpecFinal =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mT -> iT</text--->"
"<text>final( _ )</text--->"
"<text>From an moving object, get the intime value "
"corresponding to its final instant.</text--->"
"<text>final( mpoint1 )</text--->"
") )";
const std::string TemporalSpecAt =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>(mT T) -> mT</text--->"
"<text> _ at _ </text--->"
"<text>Restrict the moving object to the times where its value "
"equals the given value.</text--->"
"<text>mpoint1 at point1</text--->"
") )";
const std::string TemporalSpecDistance =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>(mpoint point) -> mreal</text--->"
"<text>distance( _, _ ) </text--->"
"<text>Returns the moving distance.</text--->"
"<text>distance( mpoint1, point1 )</text--->"
") )";
const std::string TemporalSpecDistanceAvg =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint x mpoint (x geoid) -> real</text--->"
"<text>distanceAvg( _, _ ) </text--->"
"<text>Returns the average distance based on the integral.</text--->"
"<text>distanceAvg(mpoint1, mpoint2)</text--->"
") )";
const std::string TemporalSpecDistanceAvgLB =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>cXpoint x cXpoint (x geoid) -> real, X = (m|u)</text--->"
"<text>distanceAvgLB( _, _ ) </text--->"
"<text>Returns the lower bound average distance based on the integral, "
"considering the radii of both arguments."
"</text--->"
"<text>distanceAvgLB(cmpoint1, cmpoint2)</text--->"
") )";
const std::string TemporalSpecDistanceAvgUB =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>cXpoint x cXpoint (x geoid) -> real, X = (m|u)</text--->"
"<text>distanceAvgUB( _, _ ) </text--->"
"<text>Returns the upper bound average distance based on the integral, "
"considering the radii of both arguments."
"</text--->"
"<text>distanceAvgUB(cmpoint1, cmpoint2)</text--->"
") )";
const std::string TemporalSpecSquaredDistance =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>(mpoint point) -> mreal, (mpoint mpoint)->mreal</text--->"
"<text>squareddistance( _, _ ) </text--->"
"<text>Returns the squared moving distance.</text--->"
"<text>squareddistance( mpoint1, point1 )</text--->"
") )";
const std::string TemporalSpecSimplify =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint x real [ x duration ] -> mpoint |"
" mreal x real -> mreal</text--->"
"<text>simplify( o, eVal [, eTime]) </text--->"
"<text>Simplifys the argument o allowing a maximum imprecision of eVal on "
"the value scale, and a maximum difference of eT on the temporal scale."
"</text--->"
"<text>simplify( train7, 50.0, [const duration value (0, 10000)] )</text--->"
") )";
const std::string TemporalSpecIntegrate =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>{ureal , mreal} -> real</text--->"
"<text>integrate( _ ) </text--->"
"<text>Computes the determined integral of the argument.</text--->"
"<text>integrate(mreal5000)</text--->"
") )";
const std::string TemporalSpecLinearize =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text> t -> t, where t in {mreal, ureal}</text--->"
"<text>linearize( _ ) </text--->"
"<text>Approximates the argument by a piecewise linear function.</text--->"
"<text>linearize(distance(train7, train6))</text--->"
") )";
const std::string TemporalSpecApproximate =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>stream(tuple(a1: t1) (...(an,tn) x ai x aj [ x bool ] [ x duration ]"
"-> mtj , (ti = instant, tj in {real,point,int,bool,string,label)</text--->"
"<text>_ approximate [ i, j, mc, dt_split ] </text--->"
"<text>Computes a moving type from the time/value pairs of the stream "
"argument. i/j indicate the attribute names for the time/value data within "
"the stream tuples. The optional parameter dt_split sets a maximum duration "
"for unit definition times. If two consecutive data points have longer "
"temporal distance, they are not connected by a unit."
"For real and point data, the result contains units with a linear function "
"describing the temporal evolution between each pair of consecutive data "
"points. For int, bool, and string values, constant units are created, where "
"a value is valid until the next given data point. This means, that the final"
" data point's value is lost. If the optional boolean parameter 'mc' is set "
"to FALSE, this type of constant units is also created for point and real "
"data. The default value for 'mc' is TRUE.</text--->"
"<text> </text--->"
") )";
const std::string TemporalSpecLinearize2 =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text> mreal -> mreal | \n"
" ureal -> (stream ureal)</text--->"
"<text>linearize2( _ ) </text--->"
"<text>Computes a piecewise linear approximation of the argument.</text--->"
"<text>linearize2(distance(train7, train6))</text--->"
") )";
const std::string TemporalSpecMin =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>{ureal,mreal}->real, mint->int</text--->"
"<text>minimum( _ ) </text--->"
"<text>Computes the minimum value of the argument.</text--->"
"<text>minimum(mreal5000)</text--->"
") )";
const std::string TemporalSpecMax =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>{ureal,mreal}->real, mint->int</text--->"
"<text>maximum( _ ) </text--->"
"<text>Computes the maximum value of the argument.</text--->"
"<text>maximum(mreal5000)</text--->"
") )";
const std::string TemporalSpecBreakPoints =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint x duration [x real] -> points</text--->"
"<text>breakpoints( m, d, e ) </text--->"
"<text>Computes all points where the mpoint 'm' stops longer"
" than the given duration 'd'. If the argument e is set, "
" a stop is defined to move not more than e within the "
" duration time."
"</text--->"
"<text>breakpoints( train7, [const duration value (0 1000)] )</text--->"
") )";
const std::string breaksSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint x duration x real -> peridos</text--->"
"<text>breaks( m, d, e ) </text--->"
"<text>Computes all intervals where the mpoint 'm' stops longer"
" than the given duration 'd'.A stop is defined to move not more "
"than e within the duration time."
"</text--->"
"<text>breaks( train7, [const duration value (0 1000), 30.0] )</text--->"
") )";
/*
1.1.1 Spec for ~gk~
*/
const std::string TemporalSpecgk =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>{mpoint,upoint} [ x int ] -> {mpoint,upoint}</text--->"
"<text>gk( mp [, zone] ) </text--->"
"<text>Projects the argument 'mp' using the Gauss Krueger projection "
"with center meridian 'zone'. Zone width is 3°. If 0 <= 'zone' <= 119 is not"
" provided, 2 (center meridian = 6°E, suits the location of Hagen) will be "
"used as a default. 'mp' is expected to have geographic coordinates "
"(LAT/LON) in °, the result's coordinates (NORTHING,EASTING) are in metres."
"</text--->"
"<text> gk( trip )</text--->"
") )";
const std::string TemporalSpecVertices =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint -> points</text--->"
"<text> vertices( _ ) </text--->"
"<text>Stores the end points of all contained units within a points "
"value.</text--->"
"<text> vertices( train7 )</text--->"
") )";
const std::string TemporalSpecUnits =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>For T in {bool, int, real, point}:\n"
" mT -> (stream uT)</text--->"
"<text> units( _ )</text--->"
"<text>Covert a moving type object to a stream of units.</text--->"
"<text>units( mpoint1 )</text--->"
") )";
const std::string TemporalSpecGetUnit =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text> mT x int -> uT, where T in {bool, int, real, point}</text--->"
"<text> getunit( M, N )</text--->"
"<text>Yields the Nth unit from the moving object M."
"</text--->"
"<text>mpoint1 getunit( 0 )</text--->"
") )";
const std::string TemporalSpecGetPosition =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text> mT x instant -> int, where T in {bool, int, real, point, string, "
"region}</text--->"
"<text> getPosition( M, I )</text--->"
"<text>Yields the unit position inside moving object M that corresponds to I."
"</text--->"
"<text>getPosition(train7, [const instant value \"2003-11-20-06:07\"])"
"</text--->"
") )";
const std::string TemporalSpecBBox =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>upoint [x geoid] -> rect3,\n"
"mpoint [x geoid] -> rect3,\n"
"ipoint [x geoid] -> rect3,\n"
"instant -> rect3,\n"
"periods -> rect3,\""
"cupoint -> rect3</text--->"
"<text>bbox ( Obj [, Geoid])</text--->"
"<text>Returns the 3d bounding box of the spatio-temporal object Obj, \n"
"resp. the universe restricted to the definition time of the instant/\n"
"period value. If Geoid is passed, the geographic MBR is computed.</text--->"
"<text>query bbox( upoint1 )</text--->"
") )";
const std::string TemporalSpecMBRange =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>rT -> rT, T in {int, real, bool, string}</text--->"
"<text>mbrange ( _ )</text--->"
"<text>Returns the argument's minimum bounding range (the smallest closed\n"
"interval containing all values within the given range type value).</text--->"
"<text>query mbrange( deftime(train6) )</text--->"
") )";
const std::string TemporalSpecBBoxOld =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>upoint [x geoid] -> rect3,\n"
"mpoint [x geoid] -> rect3,\n"
"ipoint [x geoid] -> rect3,\n"
"rT -> rT</text--->"
"<text>bboxOld ( Obj [, Geoid] )</text--->"
"<text>Returns the 3d bounding box of the spatio-temporal object Obj, \n"
"resp. the range value with the smallest closed interval that contains "
"all intervals of a range-value (for range-value). If Geoid is passed, the "
"geographic MBR is returned.</text--->"
"<text>query bbox( upoint1 )</text--->"
") )";
const std::string TemporalSpecBBox2d =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>upoint [x geoid] -> rect,\n"
"mpoint [x geoid] -> rect,\n"
"ipoint [x geoid] -> rect,\n"
"cupoint [x geoid] -> rect"
"</text--->"
"<text>bbox2d( Obj [, Geoid] )</text--->"
"<text>Returns the 2d bounding box of the spatio-temporal object Obj."
" If Geoid is passed, the geographic MBR is returned.</text--->"
"<text>query bbox2d( upoint1 )</text--->"
") )";
const std::string MPointSpecTranslate =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint x duration x real x real -> mpoint</text--->"
"<text>_ translate[ ot, ox, oy ]</text--->"
"<text>Moves the object by a given temporal (ot) and spatial (ox/oy) offset."
"</text--->"
"<text>query mp1 translate[[const duration value (5 10)],5.0,8.0]</text--->"
") )";
const std::string TemporalSpecTheYear =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>int -> periods</text--->"
"<text> theyear( y )</text--->"
"<text>Create a periods value for the given year 'y'.</text--->"
"<text>theyear(2002)</text--->"
") )";
const std::string TemporalSpecTheMonth =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>int x int -> periods</text--->"
"<text> themonth( y, m )</text--->"
"<text>Create a periods value for the given of the year/month.</text--->"
"<text>themonth(2002, 3)</text--->"
") )";
const std::string TemporalSpecTheDay =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>int x int x int -> periods</text--->"
"<text>theday( y, m, d )</text--->"
"<text>Create a periods value for the given year/month/day.</text--->"
"<text>theday(2002, 6,3)</text--->"
") )";
const std::string TemporalSpecTheHour =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>int x int x int x int -> periods</text--->"
"<text>thehour( y, m, d , h)</text--->"
"<text>Create a periods value for the given year/month/day/hour.</text--->"
"<text>thehour(2002, 2, 28, 8)</text--->"
") )";
const std::string TemporalSpecTheMinute =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( "
"<text>int x int x int x int x int -> periods</text--->"
"<text>theminute( y, m, d , h, min )</text--->"
"<text>Create a periods value for the given year/month/day/hour/minute."
"</text--->"
"<text>theminute(2002, 3, 28, 8, 59)</text--->"
") )";
const std::string TemporalSpecTheSecond =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>int x int x int x int x int x int -> periods</text--->"
"<text>thesecond( y, m, d , h, min, sec )</text--->"
"<text>Create a periods value for the given year/month/day/hour/minute/"
"second.</text--->"
"<text>thesecond(2002, 12, 31, 23, 59, 59)</text--->"
") )";
const std::string TemporalSpecThePeriod =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>(periods periods) -> periods</text--->"
"<text> theperiod( _, _ )</text--->"
"<text>Create a period that spans from the starting instant of the first,"
"to the ending instance of the second periods argument.</text--->"
"<text>theperiod(theyear(2002), theyear(2004))</text--->"
") )";
const std::string Box3dSpec =
"( ( \"Signatures\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>For S in {rect, instant, periods}:\n"
" S -> rect3 \n"
"For T in {instant, periods}:\n"
" rect x T -> rect3 </text--->"
"<text>box3d(_)</text--->"
"<text>returns a threedimensional box which is unlimited "
"in non-specified parts</text--->"
"<text>query box3d(bbox(mehringdamm))</text--->"
") )";
const std::string TemporalBox2dSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>{rect|rect3|rect4|rect8} -> rect</text--->"
"<text>box2d( _ )</text--->"
"<text>Restricts a rect<d> to its 1st and 2nd dimension. Can be used to "
"eliminate the temporal dimension of a 3D bounding box.</text--->"
"<text>box2d(r3)</text--->"
") )";
const std::string TemporalMBool2MIntSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mbool -> mint </text--->"
"<text>mbool2mint( _ ) </text--->"
"<text>Converts a mbool value into a mint value: FALSE -> 0, TRUE -> 1."
"</text--->"
"<text>mbool2mint(mb1)</text--->"
") )";
const std::string TemporalMInt2MBoolSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mint -> mbool </text--->"
"<text>mint2mbool( _ ) </text--->"
"<text>Converts the mint value into a mbool value. Zero (0) units are "
"converted into FALSE units, all others into TRUE units.</text--->"
"<text>mint2mbool(zero())</text--->"
") )";
const std::string TemporalMInt2MRealSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mint -> mreal </text--->"
"<text>mint2mreal( _ ) </text--->"
"<text>Converts the mint value into an mreal value.</text--->"
"<text>mint2mreal(zero())</text--->"
") )";
const std::string TemporalExtDeftimeSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mT x uT -> mT with T in {bool, int} </text--->"
"<text>extenddeftime( m, u) </text--->"
"<text>Extends the moving object m's deftime by that of the unit u's deftime,"
" filling all definition gaps of 'm' with the value taken from 'u'.</text--->"
"<text>query extdeftime(mb ub)</text--->"
") )";
const std::string TemporalTheRangeSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>T x T x bool x bool -> rT with T in {bool, int, real, string}\n"
"instant x instant x bool x bool -> periods</text--->"
"<text>theRange( left, right, lc, rc ) </text--->"
"<text>Creates a rangetype value with a single interval having "
"boundaries 'left' and 'right'. "
"'lc' and 'rc' specify the left/right closedness of the interval.\n"
"If 'left' > 'right, both pairs of arguments are swapped.</text--->"
"<text>query theRange(mb ub)</text--->"
") )";
const std::string TranslateAppendSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint x mpoint x duration -> mpoint</text--->"
"<text> mp1 translateappend [ mp2 dur ]</text--->"
"<text>Appends the second argument to the first one, \n"
" waiting for a duration given by the third argument at the\n"
" last position of the first argument</text--->"
"<text>query mp1 translateappend[mp2 "
"[const duration value(0 10000)]]</text--->"
") )";
const std::string TranslateAppendSSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>stream(tuple((a1 t1)...(an tn))) x ai x duration"
" -> mpoint, where ti = mpoint</text--->"
"<text> _ translateappendS[ _ _ ]</text--->"
"<text>Builds a single moving point from all mpoints in the stream \n"
" translating the mpoints in such a way that a connected movement\n"
" is created. 'Jumps' within stream elements are not removed.</text--->"
"<text>query Trains feed translateappendS[Trip [const"
" duration value(0 10000)]]</text--->"
") )";
const std::string ReverseSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint -> mpoint</text--->"
"<text> reverse( _ )</text--->"
"<text>Computes the reverse movement of the argument</text--->"
"<text>query reverse(Train6) </text--->"
") )";
const std::string SampleMPointSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint x duration [x bool [x bool] ] -> mpoint</text--->"
"<text> samplempoint( m, dur )\n"
" samplempoint( m, dur, ke)\n"
" samplempoint( m, dur, ke, ep )</text--->"
"<text>Simulation of a gps receiver. Resamples mpoint 'm' at intervals "
"defined by duration 'dur'. For 'ke' = TRUE, the endpoint will be kept, "
"for 'ep' = TRUE, the exact path will be kept (additional units); defaults "
"are 'ke' = FALSE, 'ep' = FALSE. The result is an mpoint value.</text--->"
"<text>query samplempoint(Train6,"
" [const duration value (0 2000)] ) </text--->"
") )";
const std::string GPSSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint x duration -> "
"stream(tuple([Time: instant, Position:point])</text--->"
"<text> gps( _ , _ )</text--->"
"<text>Simulation of a gps receiver. The result is a tuplestream with "
"attributes 'Time' (instant the position is taken) and 'Position' "
"(Position at that instant).</text--->"
"<text>query samplempoint(Train6,"
" [const duratione value (0 2000)] ) count </text--->"
") )";
const std::string DisturbSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint x real x real -> mpoint </text---> "
"<text> P disturb [ MD , SD ]</text--->"
"<text>Disturbs an existing mpoint 'P', using a total maximum deviation of "
"'M' and a maximun deviation of 'S' per step.</text--->"
"<text>query train 6 disturb [200.0 , 10.0] </text--->"
") )";
/*
Spec for ~length~
*/
const std::string LengthSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint -> real </text---> "
"<text> length( Mp [, GeoidName ] ) </text--->"
"<text>Computes the travelled length of the movement of object Mp "
"(like an odometer). If the optional parameter is used, the coordinates in "
"Mp are interpreted as geographic coordinates (LON,LAT) instead of metric "
"(X,Y)-coordinates. Valid values for GeoidName are: "
+ Geoid::getGeoIdNames() + ". Unknown GeoidName results in an UNDEF result."
"</text--->"
"<text>query length(train6) </text--->"
") )";
const std::string EqualizeUSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint x real [ x bool] -> mpoint </text---> "
"<text> MP equalizeU[ Dist, Split ] </text--->"
"<text>Tries to identify similar waypoints within moving point MP using "
"distance-based clustering (where Dist is the maximum allowed spatial "
"distance). Then the mpoint's support points are replaced by the clustre's "
"centroids as far as possible. Flag 'Split' signalizes, whether units may "
"be split to allow for a better matching.</text--->"
"<text>query train6 equalizeU[20.0] </text--->"
") )";
const std::string MintHatSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mint -> mint </text---> "
"<text> hat(_) </text--->"
"<text>"
" Summarizes a moving integer into another moving integer"
" consisting of at most 3 units."
" Summarization is done in such a way that the area"
" computed from the length of the time interval of the middle piece"
" and the minimum number reached within that interval is maximal."
"</text--->"
"<text>query hat(noAtCenter)</text--->"
") )";
const std::string restrictSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mint [x int] -> mint </text---> "
"<text> restrict( MI [, Val]) </text--->"
"<text>Removes infinity units at the ends of the moving int 'MI'. "
"If the optional int argument Val is given, the units are only removed if "
"the value store within that units is equal to the given value 'Val'."
"</text--->"
"<text>query restrict(noAtCenter)</text--->"
") )";
const std::string speedupSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint x real -> mpoint </text---> "
"<text> MP speedup [ F ] </text--->"
"<text>Transform 'MP' to a moving point that moves 'F' times as fast "
"as 'MP', but starts at the same instant and moves the same way."
"</text--->"
"<text>query train1 speedup[2.0]</text--->"
") )";
/*
Spec for ~avg\_speed~
*/
const std::string avg_speedSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint [ x string ] -> real </text---> "
"<text> avg_speed ( M [, GeoidName] ) </text--->"
"<text>Query the average speed over ground of the moving point M in unit/s."
"If the optional string parameter is not used, coordinates in M are metric "
"(X,Y)-pairs. Otherwise, GeoidName specifies a geoid to use for orthodrome-"
"based speed calculation (valid GeoidNames are: " + Geoid::getGeoIdNames() +
") and coordinates in M must be valid geographic coordinates (LON,LAT)."
"For an invalid GeoidName or invalid geographic coordinates in M, UNDEF is "
"returned.</text--->"
"<text>query avg_speed(train1)</text--->"
") )";
const std::string submoveSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint x real-> mpoint </text---> "
"<text> MP submove [ F ] </text--->"
"<text>Restricts a moving point 'MP' to a random interval with relative "
"size according to the given factor 0.0<'F'<1.0.</text--->"
"<text>query submove(train1)</text--->"
") )";
const std::string TemporalSpecMp2Onemp =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint x starttime x endtime -> x</text--->"
"<text>mp2onemp ( mp, i1, i2 )</text--->"
"<text>WARNING! The implementation does not match this description:\nl"
"Return a static moving point with a location from mp, starting at i1, "
"and ending at t2.</text--->"
"<text> query mp2onemp (train1 ,minimum(deftime(train1)),"
"maximum(deftime(train1)))</text--->"
") )";
const std::string TemporalSpecP2Mp =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint x starttime x endtime -> x</text--->"
"<text>p2mp ( _,_,_,_ )</text--->"
"<text>Create an moving point from a point and the time interval.</text--->"
"<text>query p2mp ( point(2 3) ,theInstant(2003,11,20,6)"
"theInstant(2003,11,20,7),100)</text--->"
") )";
OperatorInfo DelayOperatorInfo( "delay",
"mpoint x mpoint [x geoid] -> mreal",
"delay(actual, schedule movement [,geoid])",
"At every time instance the result will reflect how many seconds is the "
"actual movement delayed from the scheduled movement. If 'geoid' is used "
"geographic (LON.LAT) coordinates are expected, otherwise euclidean "
"coordinates.",
"");
OperatorInfo DistanceTraversedOperatorInfo( "distancetraversed",
"mpoint [x geoid] -> mreal",
"distancetraversed(schedule [, geoid])",
"Given a mpoint that moves continuously in space the operator will return "
"a moving real indicating the total distance (above ground) traversed so far "
"by the moving point. If 'geoid' is used, geographic (LON.LAT) coordinates "
"are used, euclidean coordinates otherwise.",
"");
OperatorInfo TurnsOperatorInfo( "turns",
"mpoint x real x real [ x duration ] [ x bool] [ x geoid ] -> stream(tuple("
"TimeOld instant, TimeNew instant, PosOld point, PosNew point, HeadingOld "
"real, HeadingNew real, HeadingDiff real))",
"turns( MP, MinDiff, MaxDiff [, MaxDur ] [, UseHeading] [, Geoid] )",
"Given a mpoint MP the operator will return a stream of tuples describing "
"all the object's turns where the heading changes by at least MinDiff and "
"at most MaxDiff' degrees (both parameters' absolute values are used)."
"The optional parameter MaxDur' specifies a maximum duration of definition "
"gaps of the object, that will be ignored (negative durations or missing "
"parameter are handled as 'don't care about temporal distance at all'). "
"Static periods (where the object does not move) are considered like "
"undefined periods. Positive 'HeadingDiff' indicates a counterclockwise "
"rotation, negative 'HeadingDiff' indicates clockwise rotation. "
"'HeadingDiff' is always in range ]-180.0,180.0]. If an optional Geoid is "
"passed, MP is expected to use geographic (LON.LAT) coordinates, otherwise "
"euclidean coordinates (X,Y) are assumed. If optional boolean parameter "
"UseHeading is TRUE (default is FALSE) the semantic of result attributes "
"HeadingOld and HeadingNew is 'heading' (navigational angles), otherwise "
"'direction' (mathematical angles))",
"");
OperatorInfo GridCellEventsOperatorInfo( "gridcellevents",
"{upoint,mpoint} x real x real x real x real x int -> stream(tuple(Cell int, "
"TimeEntered: instant, TimeLeft: instant, CellPrevious: int, CellNext: int))",
"gridcellevents( o, x0, y0, wx, wy, nx )",
"Given an object 'o' and a regular spatial grid specified by the remaining "
"parameters (see operators 'cellnumber' and 'gridintersects'), report all "
"visits of 'o' to grid cells. For each stay at a cell, the cell number 'Cell'"
", the instants when 'o' enters and leaves the cell ('TimeEntered', "
"'TimeLeft') and the numbers of the two cell visited immediately before "
"entering ('CellPrevious') and after leaving ('CellNext') the cell are "
"reported. If the cell is entered from/left to a location outside the grid, "
"the according cellnumber is set to UNDEF. Regular cell numbers are positive "
"integers (excluding '0').",
"");
/*
16.4.3 Operators
*/
Operator temporalisempty( "isempty",
TemporalSpecIsEmpty,
12,
temporalisemptymap,
TemporalSimpleSelect,
TemporalTypeMapBool );
Operator temporalequal( "=",
TemporalSpecEQ,
8,
temporalequalmap,
TemporalDualSelect,
TemporalTemporalTypeMapBool );
Operator temporalequal2( "equal",
TemporalSpecEQ2,
4,
temporalequalmap2,
TemporalDualSelect2,
TemporalTemporalTypeMapBool2 );
Operator temporalnotequal( "#",
TemporalSpecNE,
8,
temporalnotequalmap,
TemporalDualSelect,
TemporalTemporalTypeMapBool );
Operator temporalnotequal2( "nonequal",
TemporalSpecNE2,
4,
temporalnotequalmap2,
TemporalDualSelect2,
TemporalTemporalTypeMapBool2 );
Operator temporalless( "<",
TemporalSpecLT,
InstantLess,
Operator::SimpleSelect,
InstantInstantTypeMapBool );
Operator temporallessequal( "<=",
TemporalSpecLE,
InstantLessEqual,
Operator::SimpleSelect,
InstantInstantTypeMapBool );
Operator temporalgreater( ">",
TemporalSpecLT,
InstantGreater,
Operator::SimpleSelect,
InstantInstantTypeMapBool );
Operator temporalgreaterequal( ">=",
TemporalSpecLE,
InstantGreaterEqual,
Operator::SimpleSelect,
InstantInstantTypeMapBool );
Operator temporalintersects( "intersects",
TemporalSpecIntersects,
3,
temporalintersectsmap,
RangeDualSelect,
RangeRangeTypeMapBool );
Operator temporalinside( "inside",
TemporalSpecInside,
6,
temporalinsidemap,
RangeDualSelect,
RangeBaseTypeMapBool1 );
Operator temporalbefore( "before",
TemporalSpecBefore,
9,
temporalbeforemap,
RangeDualSelect,
RangeBaseTypeMapBool2 );
Operator temporalintersection( "intersection",
TemporalSpecIntersection,
3,
temporalintersectionmap,
RangeDualSelect,
RangeRangeTypeMapRange );
Operator temporalunion( "union",
TemporalSpecUnion,
3,
temporalunionmap,
RangeDualSelect,
RangeRangeTypeMapRange );
Operator temporalminus( "minus",
TemporalSpecMinus,
3,
temporalminusmap,
RangeDualSelect,
RangeRangeTypeMapRange );
Operator temporalmin( "minimum",
TemporalSpecMinimum,
3,
temporalminmap,
RangeSimpleSelect,
RangeTypeMapBase );
Operator temporalmax( "maximum",
TemporalSpecMaximum,
3,
temporalmaxmap,
RangeSimpleSelect,
RangeTypeMapBase );
Operator temporalnocomponents( "no_components",
TemporalSpecNoComponents,
8,
temporalnocomponentsmap,
TemporalSetValueSelect,
TemporalSetValueTypeMapInt );
Operator temporalinst( "inst",
TemporalSpecInst,
5,
temporalinstmap,
IntimeSimpleSelect,
IntimeTypeMapInstant );
/*
More operator specifications...
*/
Operator temporalval( "val",
TemporalSpecVal,
5,
temporalvalmap,
IntimeSimpleSelect,
IntimeTypeMapBase );
Operator temporalatinstant( "atinstant",
TemporalSpecAtInstant,
5,
temporalatinstantmap,
MovingSimpleSelect,
MovingInstantTypeMapIntime );
Operator temporalatperiods( "atperiods",
TemporalSpecAtPeriods,
5,
temporalatperiodsmap,
MovingSimpleSelect,
MovingPeriodsTypeMapMoving );
Operator temporalwhen( "when",
TemporalSpecWhen,
4,
temporalwhenmap,
MovingSimpleSelect,
WhenTM );
Operator temporaldeftime( "deftime",
TemporalSpecDefTime,
5,
temporaldeftimemap,
MovingSimpleSelect,
MovingTypeMapPeriods );
Operator temporaltrajectory( "trajectory",
TemporalSpecTrajectory,
MPointTrajectory,
Operator::SimpleSelect,
MovingTypeMapSpatial);
Operator temporalpresent( "present",
TemporalSpecPresent,
8,
temporalpresentmap,
MovingInstantPeriodsSelect,
MovingInstantPeriodsTypeMapBool);
Operator temporalpasses( "passes",
TemporalSpecPasses,
6,
temporalpassesmap,
MovingBaseSelect,
MovingBaseTypeMapBool);
Operator temporalinitial( "initial",
TemporalSpecInitial,
5,
temporalinitialmap,
MovingSimpleSelect,
MovingTypeMapIntime );
Operator temporalfinal( "final",
TemporalSpecFinal,
5,
temporalfinalmap,
MovingSimpleSelect,
MovingTypeMapIntime );
Operator temporalat( "at",
TemporalSpecAt,
4,
temporalatmap,
MovingBaseSelect,
MovingBaseTypeMapMoving );
Operator temporalbox3d( "box3d",
Box3dSpec,
5,
temporalbox3dmap,
Box3dSelect,
Box3dTypeMap );
Operator temporalsamplempoint("samplempoint",
SampleMPointSpec,
3,
samplempointmap,
SampleMPointSelect,
SampleMPointTypeMap );
Operator temporaldistance( "distance",
TemporalSpecDistance,
MPointDistance,
Operator::SimpleSelect,
MovingBaseTypeMapMReal );
Operator temporaldistanceavg( "distanceAvg",
TemporalSpecDistanceAvg,
2,
DistanceAvgMaps,
DistanceAvgSelect,
DistanceAvgTypeMap);
Operator temporaldistanceavglb( "distanceAvgLB",
TemporalSpecDistanceAvgLB,
4,
DistanceAvgLBMaps,
DistanceAvgLBUBSelect,
DistanceAvgLBUBTypeMap);
Operator temporaldistanceavgub( "distanceAvgUB",
TemporalSpecDistanceAvgUB,
4,
DistanceAvgUBMaps,
DistanceAvgLBUBSelect,
DistanceAvgLBUBTypeMap);
Operator temporalsquareddistance( "squareddistance",
TemporalSpecSquaredDistance,
3,
mpointsquareddistancemap,
SquaredDistanceSelect,
SquaredDistanceTypeMap );
Operator temporalgps( "gps",
GPSSpec,
GPSVM,
Operator::SimpleSelect,
GPSTypeMap );
Operator temporaldisturb( "disturb",
DisturbSpec,
DisturbVM,
Operator::SimpleSelect,
DisturbTypeMap );
Operator temporallength( "length",
LengthSpec,
LengthVM,
Operator::SimpleSelect,
LengthTypeMap );
Operator temporalsimplify( "simplify",
TemporalSpecSimplify,
3,
simplifymap,
SimplifySelect,
MovingTypeMapSimplify );
Operator temporalintegrate( "integrate",
TemporalSpecIntegrate,
2,
integratemap,
IntegrateSelect,
TypeMapIntegrate );
Operator temporallinearize( "linearize",
TemporalSpecLinearize,
2,
linearizemap,
LinearizeSelect,
TypeMapLinearize );
Operator temporallinearize2( "linearize2",
TemporalSpecLinearize2,
2,
linearize2map,
LinearizeSelect,
TypeMapLinearize2 );
Operator temporalapproximate( "approximate",
TemporalSpecApproximate,
6,
approximatemap,
ApproximateSelect,
TypeMapApproximate );
Operator temporalminimum( "minimum",
TemporalSpecMin,
3,
minmap,
MinMaxSelect,
TypeMapMinMax );
Operator temporalmaximum( "maximum",
TemporalSpecMax,
3,
maxmap,
MinMaxSelect,
TypeMapMinMax );
Operator temporalbreakpoints( "breakpoints",
TemporalSpecBreakPoints,
MPointBreakPoints,
Operator::SimpleSelect,
MovingTypeMapBreakPoints );
Operator breaks( "breaks",
breaksSpec,
breaksVM,
Operator::SimpleSelect,
breaksTM);
Operator temporalgk( "gk",
TemporalSpecgk,
2,
gkVM,
gkSelect,
MovingTypeMapgk );
Operator temporalvertices( "vertices",
TemporalSpecVertices,
Vertices,
Operator::SimpleSelect,
MovingTypeMapVertices );
Operator temporalunits( "units",
TemporalSpecUnits,
5,
temporalunitsmap,
MovingSimpleSelect,
MovingTypeMapUnits );
Operator temporalgetunit( "getunit",
TemporalSpecGetUnit,
5,
temporalgetunitmap,
MovingSimpleSelect,
MovingTypeMapGetUnit );
Operator temporalgetposition( "getPosition",
TemporalSpecGetPosition,
7,
temporalgetpositionmap,
TemporalGetPositionSelect,
TemporalGetPositionTypeMap );
Operator temporalbbox( "bbox",
TemporalSpecBBox,
7,
temporalbboxmap,
TemporalBBoxSelect,
TemporalBBoxTypeMap );
Operator temporalmbrange( "mbrange",
TemporalSpecMBRange,
5,
temporalmbrangemap,
TemporalMBRangeSelect,
TemporalMBRangeTypeMap );
Operator temporalbbox2d( "bbox2d",
TemporalSpecBBox2d,
5,
temporalbbox2dmap,
TemporalBBox2dSelect,
TemporalBBox2dTypeMap );
Operator temporalbboxold( "bboxold",
TemporalSpecBBoxOld,
6,
temporalbboxoldmap,
TemporalBBoxSelect,
TemporalBBoxTypeMap );
Operator temporaltranslate( "translate",
MPointSpecTranslate,
MPointTranslate,
Operator::SimpleSelect,
MPointTypeMapTranslate );
Operator temporaltheyear( "theyear",
TemporalSpecTheYear,
TheYear,
Operator::SimpleSelect,
IntSetTypeMapPeriods );
Operator temporalthemonth( "themonth",
TemporalSpecTheMonth,
TheMonth,
Operator::SimpleSelect,
IntSetTypeMapPeriods );
Operator temporaltheday( "theday",
TemporalSpecTheDay,
TheDay,
Operator::SimpleSelect,
IntSetTypeMapPeriods );
Operator temporalthehour( "thehour",
TemporalSpecTheHour,
TheHour,
Operator::SimpleSelect,
IntSetTypeMapPeriods );
Operator temporaltheminute( "theminute",
TemporalSpecTheMinute,
TheMinute,
Operator::SimpleSelect,
IntSetTypeMapPeriods );
Operator temporalthesecond( "thesecond",
TemporalSpecTheSecond,
TheSecond,
Operator::SimpleSelect,
IntSetTypeMapPeriods );
Operator temporaltheperiod( "theperiod",
TemporalSpecThePeriod,
ThePeriod,
Operator::SimpleSelect,
PeriodsPeriodsTypeMapPeriods );
Operator temporalbox2d( "box2d",
TemporalBox2dSpec,
4,
temporalbox2dmap,
TemporalBox2dSelect,
Box2dTypeMap );
Operator mbool2mint( "mbool2mint",
TemporalMBool2MIntSpec,
MBool2MInt,
Operator::SimpleSelect,
TemporalMBool2MInt );
Operator mint2mbool( "mint2mbool",
TemporalMInt2MBoolSpec,
MInt2MBool,
Operator::SimpleSelect,
TemporalMInt2MBool );
Operator mint2mreal( "mint2mreal",
TemporalMInt2MRealSpec,
MInt2MReal,
Operator::SimpleSelect,
TemporalMInt2MReal );
Operator extdeftime( "extdeftime",
TemporalExtDeftimeSpec,
2,
extdeftimemap,
ExtDeftimeSelect,
ExtDeftimeTypeMap );
/*
More operator specifications...
*/
Operator temporaltherange( "theRange",
TemporalTheRangeSpec,
5,
temporaltherangemap,
TemporalTheRangeSelect,
TemporalTheRangeTM );
Operator temporaltranslateappend( "translateappend",
TranslateAppendSpec,
TranslateAppendVM,
Operator::SimpleSelect,
TranslateAppendTM );
Operator temporaltranslateappendS( "translateappendS",
TranslateAppendSSpec,
TranslateAppendSVM,
Operator::SimpleSelect,
TranslateAppendSTM );
Operator temporalreverse("reverse",
ReverseSpec,
ReverseVM,
Operator::SimpleSelect,
ReverseTM );
Operator equalizeU( "equalizeU",
EqualizeUSpec,
MPointEqualize,
Operator::SimpleSelect,
EqualizeUTM );
Operator hat( "hat",
MintHatSpec,
MIntHat,
Operator::SimpleSelect,
MIntHatTypeMap );
Operator restrict( "restrict",
restrictSpec,
2,
restrictVM,
restrictSelect,
restrictTM );
Operator speedup( "speedup",
speedupSpec,
SpeedUpVM,
Operator::SimpleSelect,
SpeedUpTypeMap);
Operator avg_speed( "avg_speed",
avg_speedSpec,
Avg_SpeedVM,
Operator::SimpleSelect,
LengthTypeMap);
Operator submove( "submove",
submoveSpec,
SubMoveVM,
Operator::SimpleSelect,
SubMoveTypeMap);
Operator temporaluval( "uval",
TemporalSpecUVal,
1,
temporaluvalmap,
UIntimeSimpleSelect,
UIntimeTypeMapBase );
Operator mp2onemp( "mp2onemp",
TemporalSpecMp2Onemp,
Mp2OneMpVM,
Operator::SimpleSelect,
Mp2OneMpTypeMap );
Operator p2mp( "p2mp",
TemporalSpecP2Mp,
P2MpVM,
Operator::SimpleSelect,
P2MpTypeMap );
Operator delayoperator(DelayOperatorInfo,
DelayOperatorValueMapping,
DelayOperatorTypeMapping);
Operator distancetraversedoperator(DistanceTraversedOperatorInfo,
DistanceTraversedOperatorValueMapping,
DistanceTraversedOperatorTypeMapping);
Operator turns( TurnsOperatorInfo,
TurnsOperatorValueMapping,
TurnsOperatorTypeMapping );
Operator mappingtimeshift( "timeshift",
MappingTimeShiftSpec,
4,
MappingTimeShiftMap,
MovingSimpleSelect,
MappingTimeShiftTM );
Operator gridcellevents( GridCellEventsOperatorInfo,
GridCellEventsValueMapping,
GridCellEventsSelect,
GridCellEventsTypeMapping );
/*
5.2 Further Operators
5.2.1 createCellGrid2D
~TypeMapping~ and ~Selection Function~
*/
static complexTM getCreateCellGrid2DCTM(){
complexTM tm;
tm.add(tm5<CcInt, CcInt, CcInt, CcInt, CcInt, CellGrid2D>());
tm.add(tm5<CcInt, CcInt, CcInt, CcReal, CcInt, CellGrid2D>());
tm.add(tm5<CcInt, CcInt, CcReal, CcInt, CcInt, CellGrid2D>());
tm.add(tm5<CcInt, CcInt, CcReal, CcReal, CcInt, CellGrid2D>());
tm.add(tm5<CcInt, CcReal, CcInt, CcInt, CcInt, CellGrid2D>());
tm.add(tm5<CcInt, CcReal, CcInt, CcReal, CcInt, CellGrid2D>());
tm.add(tm5<CcInt, CcReal, CcReal, CcInt, CcInt, CellGrid2D>());
tm.add(tm5<CcInt, CcReal, CcReal, CcReal, CcInt, CellGrid2D>());
tm.add(tm5<CcReal, CcInt, CcInt, CcInt, CcInt, CellGrid2D>());
tm.add(tm5<CcReal, CcInt, CcInt, CcReal, CcInt, CellGrid2D>());
tm.add(tm5<CcReal, CcInt, CcReal, CcInt, CcInt, CellGrid2D>());
tm.add(tm5<CcReal, CcInt, CcReal, CcReal, CcInt, CellGrid2D>());
tm.add(tm5<CcReal, CcReal, CcInt, CcInt, CcInt, CellGrid2D>());
tm.add(tm5<CcReal, CcReal, CcInt, CcReal, CcInt, CellGrid2D>());
tm.add(tm5<CcReal, CcReal, CcReal, CcInt, CcInt, CellGrid2D>());
tm.add(tm5<CcReal, CcReal, CcReal, CcReal, CcInt, CellGrid2D>());
//With the constant origin
tm.add(tm3<CcInt, CcInt, CcInt, CellGrid2D>());
tm.add(tm3<CcInt, CcReal, CcInt, CellGrid2D>());
tm.add(tm3<CcReal, CcInt, CcInt, CellGrid2D>());
tm.add(tm3<CcReal, CcReal, CcInt, CellGrid2D>());
return tm;
}
static ListExpr createCellGrid2DTypeMap(ListExpr args){
return getCreateCellGrid2DCTM()(args);
}
static int createCellGrid2DSelect(ListExpr args){
return getCreateCellGrid2DCTM().select(args);
}
/*
~Functor~ and ~Value Mapping Array~
*/
template<class A1,class A2, class A3, class A4, class A5, class R>
class CreateCellGrid2DF{
public:
void operator()(const A1* a1, const A2* a2, const A3* a3,
const A4* a4, const A5* a5, R* res){
res->set(a1->GetValue(), a2->GetValue(), a3->GetValue(),
a4->GetValue(), a5->GetValue());
}
};
template<class A1,class A2, class A3, class R>
class CreateCellGrid2DF2{
public:
void operator()(const A1* a1, const A2* a2, const A3* a3, R* res){
res->set(a1->GetValue(), a2->GetValue(), a3->GetValue());
}
};
ValueMapping createCellGrid2DValueMap[] = {
GenVM5<CcInt, CcInt, CcInt, CcInt, CcInt, CellGrid2D,
CreateCellGrid2DF<CcInt, CcInt, CcInt, CcInt, CcInt, CellGrid2D> >,
GenVM5<CcInt, CcInt, CcInt, CcReal, CcInt, CellGrid2D,
CreateCellGrid2DF<CcInt, CcInt, CcInt, CcReal, CcInt, CellGrid2D> >,
GenVM5<CcInt, CcInt, CcReal, CcInt, CcInt, CellGrid2D,
CreateCellGrid2DF<CcInt, CcInt, CcReal, CcInt, CcInt, CellGrid2D> >,
GenVM5<CcInt, CcInt, CcReal, CcReal, CcInt, CellGrid2D,
CreateCellGrid2DF<CcInt, CcInt, CcReal, CcReal, CcInt, CellGrid2D> >,
GenVM5<CcInt, CcReal, CcInt, CcInt, CcInt, CellGrid2D,
CreateCellGrid2DF<CcInt, CcReal, CcInt, CcInt, CcInt, CellGrid2D> >,
GenVM5<CcInt, CcReal, CcInt, CcReal, CcInt, CellGrid2D,
CreateCellGrid2DF<CcInt, CcReal, CcInt, CcReal, CcInt, CellGrid2D> >,
GenVM5<CcInt, CcReal, CcReal, CcInt, CcInt, CellGrid2D,
CreateCellGrid2DF<CcInt, CcReal, CcReal, CcInt, CcInt, CellGrid2D> >,
GenVM5<CcInt, CcReal, CcReal, CcReal, CcInt, CellGrid2D,
CreateCellGrid2DF<CcInt, CcReal, CcReal, CcReal, CcInt, CellGrid2D> >,
GenVM5<CcReal, CcInt, CcInt, CcInt, CcInt, CellGrid2D,
CreateCellGrid2DF<CcReal, CcInt, CcInt, CcInt, CcInt, CellGrid2D> >,
GenVM5<CcReal, CcInt, CcInt, CcReal, CcInt, CellGrid2D,
CreateCellGrid2DF<CcReal, CcInt, CcInt, CcReal, CcInt, CellGrid2D> >,
GenVM5<CcReal, CcInt, CcReal, CcInt, CcInt, CellGrid2D,
CreateCellGrid2DF<CcReal, CcInt, CcReal, CcInt, CcInt, CellGrid2D> >,
GenVM5<CcReal, CcInt, CcReal, CcReal, CcInt, CellGrid2D,
CreateCellGrid2DF<CcReal, CcInt, CcReal, CcReal, CcInt, CellGrid2D> >,
GenVM5<CcReal, CcReal, CcInt, CcInt, CcInt, CellGrid2D,
CreateCellGrid2DF<CcReal, CcReal, CcInt, CcInt, CcInt, CellGrid2D> >,
GenVM5<CcReal, CcReal, CcInt, CcReal, CcInt, CellGrid2D,
CreateCellGrid2DF<CcReal, CcReal, CcInt, CcReal, CcInt, CellGrid2D> >,
GenVM5<CcReal, CcReal, CcReal, CcInt, CcInt, CellGrid2D,
CreateCellGrid2DF<CcReal, CcReal, CcReal, CcInt, CcInt, CellGrid2D> >,
GenVM5<CcReal, CcReal, CcReal, CcReal, CcInt, CellGrid2D,
CreateCellGrid2DF<CcReal, CcReal, CcReal, CcReal, CcInt, CellGrid2D> >,
GenVM3<CcInt, CcInt, CcInt, CellGrid2D,
CreateCellGrid2DF2<CcInt, CcInt, CcInt, CellGrid2D> >,
GenVM3<CcInt, CcReal, CcInt, CellGrid2D,
CreateCellGrid2DF2<CcInt, CcReal, CcInt, CellGrid2D> >,
GenVM3<CcReal, CcInt, CcInt, CellGrid2D,
CreateCellGrid2DF2<CcReal, CcInt, CcInt, CellGrid2D> >,
GenVM3<CcReal, CcReal, CcInt, CellGrid2D,
CreateCellGrid2DF2<CcReal, CcReal, CcInt, CellGrid2D> >
};
/*
~Operator Instance~
*/
Operator createCellGrid2D(
"createCellGrid2D",
getCreateCellGrid2DCTM().getSpecification(
"createCellGrid2D(x0, y0, xw, yw, no_cells_x) ",
"Creates a cell grid from the arguments, (x0, y0) "
" defines a corner point of the grid, xw, yw are "
" the width for each dimension and no_cells_x is"
" the number of cells in x direction. "
"If (x0, y0) is not given, then the origin is set "
"as (0.0, 0.0) by default. ",
"query createCellgrid2D(1.0, 1.0, 3.0, 3.0, 5)"),
getCreateCellGrid2DCTM().getVMCount(),
createCellGrid2DValueMap,
createCellGrid2DSelect,
createCellGrid2DTypeMap);
/*
5.2.1 Operator ~createCellGrid3D~
~TypeMapping~ and ~Selection Function~
*/
static complexTM getCreateCellGrid3DCTM(){
complexTM tm;
tm.add(tm9<CcInt, CcInt, CcInt, CcInt, CcInt, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcInt, CcInt, CcInt, CcInt, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcInt, CcInt, CcInt, CcReal, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcInt, CcInt, CcInt, CcReal, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcInt, CcInt, CcReal, CcInt, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcInt, CcInt, CcReal, CcInt, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcInt, CcInt, CcReal, CcReal, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcInt, CcInt, CcReal, CcReal, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcInt, CcReal, CcInt, CcInt, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcInt, CcReal, CcInt, CcInt, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcInt, CcReal, CcInt, CcReal, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcInt, CcReal, CcInt, CcReal, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcInt, CcReal, CcReal, CcInt, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcInt, CcReal, CcReal, CcInt, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcInt, CcReal, CcReal, CcReal, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcInt, CcReal, CcReal, CcReal, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcReal, CcInt, CcInt, CcInt, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcReal, CcInt, CcInt, CcInt, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcReal, CcInt, CcInt, CcReal, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcReal, CcInt, CcInt, CcReal, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcReal, CcInt, CcReal, CcInt, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcReal, CcInt, CcReal, CcInt, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcReal, CcInt, CcReal, CcReal, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcReal, CcInt, CcReal, CcReal, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcReal, CcReal, CcInt, CcInt, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcReal, CcReal, CcInt, CcInt, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcReal, CcReal, CcInt, CcReal, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcReal, CcReal, CcInt, CcReal, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcReal, CcReal, CcReal, CcInt, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcReal, CcReal, CcReal, CcInt, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcReal, CcReal, CcReal, CcReal, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcInt, CcReal, CcReal, CcReal, CcReal, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcInt, CcInt, CcInt, CcInt, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcInt, CcInt, CcInt, CcInt, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcInt, CcInt, CcInt, CcReal, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcInt, CcInt, CcInt, CcReal, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcInt, CcInt, CcReal, CcInt, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcInt, CcInt, CcReal, CcInt, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcInt, CcInt, CcReal, CcReal, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcInt, CcInt, CcReal, CcReal, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcInt, CcReal, CcInt, CcInt, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcInt, CcReal, CcInt, CcInt, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcInt, CcReal, CcInt, CcReal, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcInt, CcReal, CcInt, CcReal, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcInt, CcReal, CcReal, CcInt, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcInt, CcReal, CcReal, CcInt, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcInt, CcReal, CcReal, CcReal, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcInt, CcReal, CcReal, CcReal, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcReal, CcInt, CcInt, CcInt, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcReal, CcInt, CcInt, CcInt, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcReal, CcInt, CcInt, CcReal, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcReal, CcInt, CcInt, CcReal, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcReal, CcInt, CcReal, CcInt, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcReal, CcInt, CcReal, CcInt, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcReal, CcInt, CcReal, CcReal, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcReal, CcInt, CcReal, CcReal, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcReal, CcReal, CcInt, CcInt, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcReal, CcReal, CcInt, CcInt, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcReal, CcReal, CcInt, CcReal, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcReal, CcReal, CcInt, CcReal, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcReal, CcReal, CcReal, CcInt, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcReal, CcReal, CcReal, CcInt, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcReal, CcReal, CcReal, CcReal, CcInt,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm9<CcReal, CcReal, CcReal, CcReal, CcReal, CcReal,
CcInt, CcInt, CellGrid<3> >());
tm.add(tm5<CcInt, CcInt, CcInt, CcInt, CcInt, CellGrid<3> >());
tm.add(tm5<CcInt, CcInt, CcReal, CcInt, CcInt, CellGrid<3> >());
tm.add(tm5<CcInt, CcReal, CcInt, CcInt, CcInt, CellGrid<3> >());
tm.add(tm5<CcInt, CcReal, CcReal, CcInt, CcInt, CellGrid<3> >());
tm.add(tm5<CcReal, CcInt, CcInt, CcInt, CcInt, CellGrid<3> >());
tm.add(tm5<CcReal, CcInt, CcReal, CcInt, CcInt, CellGrid<3> >());
tm.add(tm5<CcReal, CcReal, CcInt, CcInt, CcInt, CellGrid<3> >());
tm.add(tm5<CcReal, CcReal, CcReal, CcInt, CcInt, CellGrid<3> >());
return tm;
}
static ListExpr createCellGrid3DTypeMap(ListExpr args){
return getCreateCellGrid3DCTM()(args);
}
static int createCellGrid3DSelect(ListExpr args){
return getCreateCellGrid3DCTM().select(args);
}
/*
~Functor~ and ~Value Mapping Array~
*/
template<class A1,class A2, class A3, class A4,
class A5, class A6, class A7, class A8, class R>
class CreateCellGrid3DF{
public:
void operator()(const A1* a1, const A2* a2, const A3* a3,
const A4* a4, const A5* a5, const A6* a6,
const A7* a7, const A8* a8, R* res){
double origin[3] = { (double)a1->GetValue(),
(double)a2->GetValue(), (double)a3->GetValue()};
double cwidth[3] = { (double)a4->GetValue(),
(double)a5->GetValue(), (double)a6->GetValue()};
int32_t cn[2] = { (int32_t)a7->GetValue(), (int32_t)a8->GetValue()};
res->set(origin, cwidth, cn);
/*
res->set(a1->GetValue(), a2->GetValue(), a3->GetValue(),
a4->GetValue(), a5->GetValue(), a6->GetValue(),
a7->GetValue(), a8->GetValue());
*/
}
};
template<class A1,class A2, class A3, class A4, class A5, class R>
class CreateCellGrid3DF2{
public:
void operator()(const A1* a1, const A2* a2, const A3* a3,
const A4* a4, const A5* a5, R* res){
double origin[3] = { 0.0, 0.0, 0.0};
double cwidth[3] = { (double)a1->GetValue(),
(double)a2->GetValue(), (double)a3->GetValue()};
int32_t cn[2] = { (int32_t)a4->GetValue(), (int32_t)a5->GetValue()};
res->set(origin, cwidth, cn);
}
};
ValueMapping createCellGrid3DValueMap[] = {
GenVM9<CcInt, CcInt, CcInt, CcInt, CcInt, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcInt, CcInt, CcInt,
CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcInt, CcInt, CcInt, CcInt, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcInt, CcInt, CcInt,
CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcInt, CcInt, CcInt, CcReal, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcInt, CcInt, CcInt,
CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcInt, CcInt, CcInt, CcReal, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcInt, CcInt, CcInt,
CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcInt, CcInt, CcReal, CcInt, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcInt, CcInt, CcReal,
CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcInt, CcInt, CcReal, CcInt, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcInt, CcInt, CcReal,
CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcInt, CcInt, CcReal, CcReal, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcInt, CcInt, CcReal,
CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcInt, CcInt, CcReal, CcReal, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcInt, CcInt, CcReal,
CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcInt, CcReal, CcInt, CcInt, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcInt, CcReal, CcInt,
CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcInt, CcReal, CcInt, CcInt, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcInt, CcReal, CcInt,
CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcInt, CcReal, CcInt, CcReal, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcInt, CcReal, CcInt,
CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcInt, CcReal, CcInt, CcReal, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcInt, CcReal, CcInt,
CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcInt, CcReal, CcReal, CcInt, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcInt, CcReal, CcReal,
CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcInt, CcReal, CcReal, CcInt, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcInt, CcReal, CcReal,
CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcInt, CcReal, CcReal, CcReal, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcInt, CcReal, CcReal,
CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcInt, CcReal, CcReal, CcReal, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcInt, CcReal, CcReal,
CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcReal, CcInt, CcInt, CcInt, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcReal, CcInt, CcInt,
CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcReal, CcInt, CcInt, CcInt, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcReal, CcInt, CcInt,
CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcReal, CcInt, CcInt, CcReal, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcReal, CcInt, CcInt,
CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcReal, CcInt, CcInt, CcReal, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcReal, CcInt, CcInt,
CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcReal, CcInt, CcReal, CcInt, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcReal, CcInt, CcReal,
CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcReal, CcInt, CcReal, CcInt, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcReal, CcInt, CcReal,
CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcReal, CcInt, CcReal, CcReal, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcReal, CcInt, CcReal,
CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcReal, CcInt, CcReal, CcReal, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcReal, CcInt, CcReal,
CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcReal, CcReal, CcInt, CcInt, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcReal, CcReal, CcInt,
CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcReal, CcReal, CcInt, CcInt, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcReal, CcReal, CcInt,
CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcReal, CcReal, CcInt, CcReal, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcReal, CcReal, CcInt,
CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcReal, CcReal, CcInt, CcReal, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcReal, CcReal, CcInt,
CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcReal, CcReal, CcReal, CcInt, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcReal, CcReal, CcReal,
CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcReal, CcReal, CcReal, CcInt, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcReal, CcReal, CcReal,
CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcReal, CcReal, CcReal, CcReal, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcReal, CcReal, CcReal,
CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcInt, CcReal, CcReal, CcReal, CcReal, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcInt, CcReal, CcReal, CcReal,
CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcInt, CcInt, CcInt, CcInt, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcInt, CcInt, CcInt,
CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcInt, CcInt, CcInt, CcInt, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcInt, CcInt, CcInt,
CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcInt, CcInt, CcInt, CcReal, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcInt, CcInt, CcInt,
CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcInt, CcInt, CcInt, CcReal, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcInt, CcInt, CcInt,
CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcInt, CcInt, CcReal, CcInt, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcInt, CcInt, CcReal,
CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcInt, CcInt, CcReal, CcInt, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcInt, CcInt, CcReal,
CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcInt, CcInt, CcReal, CcReal, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcInt, CcInt, CcReal,
CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcInt, CcInt, CcReal, CcReal, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcInt, CcInt, CcReal,
CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcInt, CcReal, CcInt, CcInt, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcInt, CcReal, CcInt,
CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcInt, CcReal, CcInt, CcInt, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcInt, CcReal, CcInt,
CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcInt, CcReal, CcInt, CcReal, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcInt, CcReal, CcInt,
CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcInt, CcReal, CcInt, CcReal, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcInt, CcReal, CcInt,
CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcInt, CcReal, CcReal, CcInt, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcInt, CcReal, CcReal,
CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcInt, CcReal, CcReal, CcInt, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcInt, CcReal, CcReal,
CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcInt, CcReal, CcReal, CcReal, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcInt, CcReal, CcReal,
CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcInt, CcReal, CcReal, CcReal, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcInt, CcReal, CcReal,
CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcReal, CcInt, CcInt, CcInt, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcReal, CcInt, CcInt,
CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcReal, CcInt, CcInt, CcInt, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcReal, CcInt, CcInt,
CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcReal, CcInt, CcInt, CcReal, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcReal, CcInt, CcInt,
CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcReal, CcInt, CcInt, CcReal, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcReal, CcInt, CcInt,
CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcReal, CcInt, CcReal, CcInt, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcReal, CcInt, CcReal,
CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcReal, CcInt, CcReal, CcInt, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcReal, CcInt, CcReal,
CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcReal, CcInt, CcReal, CcReal, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcReal, CcInt, CcReal,
CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcReal, CcInt, CcReal, CcReal, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcReal, CcInt, CcReal,
CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcReal, CcReal, CcInt, CcInt, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcReal, CcReal, CcInt,
CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcReal, CcReal, CcInt, CcInt, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcReal, CcReal, CcInt,
CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcReal, CcReal, CcInt, CcReal, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcReal, CcReal, CcInt,
CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcReal, CcReal, CcInt, CcReal, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcReal, CcReal, CcInt,
CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcReal, CcReal, CcReal, CcInt, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcReal, CcReal, CcReal,
CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcReal, CcReal, CcReal, CcInt, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcReal, CcReal, CcReal,
CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcReal, CcReal, CcReal, CcReal, CcInt, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcReal, CcReal, CcReal,
CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM9<CcReal, CcReal, CcReal, CcReal, CcReal, CcReal, CcInt, CcInt,
CellGrid<3>, CreateCellGrid3DF<CcReal, CcReal, CcReal, CcReal,
CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM5<CcInt, CcInt, CcInt, CcInt, CcInt, CellGrid<3>,
CreateCellGrid3DF2<CcInt, CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM5<CcInt, CcInt, CcReal, CcInt, CcInt, CellGrid<3>,
CreateCellGrid3DF2<CcInt, CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM5<CcInt, CcReal, CcInt, CcInt, CcInt, CellGrid<3>,
CreateCellGrid3DF2<CcInt, CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM5<CcInt, CcReal, CcReal, CcInt, CcInt, CellGrid<3>,
CreateCellGrid3DF2<CcInt, CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM5<CcReal, CcInt, CcInt, CcInt, CcInt, CellGrid<3>,
CreateCellGrid3DF2<CcReal, CcInt, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM5<CcReal, CcInt, CcReal, CcInt, CcInt, CellGrid<3>,
CreateCellGrid3DF2<CcReal, CcInt, CcReal, CcInt, CcInt, CellGrid<3> > >,
GenVM5<CcReal, CcReal, CcInt, CcInt, CcInt, CellGrid<3>,
CreateCellGrid3DF2<CcReal, CcReal, CcInt, CcInt, CcInt, CellGrid<3> > >,
GenVM5<CcReal, CcReal, CcReal, CcInt, CcInt, CellGrid<3>,
CreateCellGrid3DF2<CcReal, CcReal, CcReal, CcInt, CcInt, CellGrid<3> > >
};
/*
~Operator Instance~
*/
Operator createCellGrid3D(
"createCellGrid3D",
getCreateCellGrid3DCTM().getSpecification(
"createCellGrid2D(x0, y0, z0, xw, yw, z0, "
"no_cells_x, no_cells_y ) ",
"Creates a 3D cell grid from the arguments, (x0, y0, z0) "
" defines a corner point of the grid, xw, yw, zw are "
" the width for each dimension, "
" no_cells_x and no_cells_y is"
" the number of cells in x and y direction. "
"If the origin is not set, it is (0.0, 0.0, 0.0) by default. ",
"query createCellgrid2D(1.0, 1.0, 1.0, 3.0, 3.0, 3.0, 5, 5)"),
getCreateCellGrid3DCTM().getVMCount(),
createCellGrid3DValueMap,
createCellGrid3DSelect,
createCellGrid3DTypeMap);
/*
5.2.2 Operator ~getRefinementPartition~
*/
/*
5.2.2.1 Type Mapping for Operator ~getRefinementPartition~
----
{mT1|uT1} x {uT2|mT2} -> stream(tuple((Tstart instant)
(Tend instant)
(Tlc bool)
(Trc bool)
(Unit1 uT1)
(Unit2 uT2)
(UnitNo1 int)
(UnitNo2 int))), where
T1, T2 in {point, real, int, bool, string}
----
Type ~MRegion~ cannot be supported due to its representation using ~URegionEmb~
internally, but ~URegion~ externally.
*/
ListExpr GetRefinementPartitionTypeMapping(ListExpr args){
int noargs = nl->ListLength(args);
std::string errmsg = "Expected {uT1|mT1} x {uT2|mT2}, where T in "
"{point, int, real, bool, string}";
if(noargs!=2){
return listutils::typeError(errmsg);
}
std::set<std::string> supportedArgTypes;
supportedArgTypes.insert(MPoint::BasicType());
supportedArgTypes.insert(MReal::BasicType());
supportedArgTypes.insert(MInt::BasicType());
supportedArgTypes.insert(MBool::BasicType());
supportedArgTypes.insert(MString::BasicType());
supportedArgTypes.insert(UPoint::BasicType());
supportedArgTypes.insert(UReal::BasicType());
supportedArgTypes.insert(UInt::BasicType());
supportedArgTypes.insert(UBool::BasicType());
supportedArgTypes.insert(UString::BasicType());
// MRegion not supported due to problems with handling URegionEmb/URegion
ListExpr first = nl->First(args);
ListExpr second= nl->Second(args);
if( !listutils::isASymbolIn(first,supportedArgTypes) ||
!listutils::isASymbolIn(second,supportedArgTypes)) {
return listutils::typeError(errmsg);
}
std::map<std::string,std::string> tm;
typedef std::pair<std::string,std::string> sp;
tm.insert(sp(MPoint::BasicType(),UPoint::BasicType()));
tm.insert(sp(MReal::BasicType(),UReal::BasicType()));
tm.insert(sp(MInt::BasicType(),UInt::BasicType()));
tm.insert(sp(MBool::BasicType(),UBool::BasicType()));
tm.insert(sp(MString::BasicType(),UString::BasicType()));
tm.insert(sp(UPoint::BasicType(),UPoint::BasicType()));
tm.insert(sp(UReal::BasicType(),UReal::BasicType()));
tm.insert(sp(UInt::BasicType(),UInt::BasicType()));
tm.insert(sp(UBool::BasicType(),UBool::BasicType()));
tm.insert(sp(UString::BasicType(),UString::BasicType()));
// MRegion not supported due to problems with handling URegionEmb/URegion
std::string t1; nl->WriteToString(t1, first);
std::string t2; nl->WriteToString(t2, second);
std::map<std::string,std::string>::iterator r1_i = tm.find(t1);
std::map<std::string,std::string>::iterator r2_i = tm.find(t2);
if((r1_i == tm.end()) || (r2_i == tm.end())){
return listutils::typeError(errmsg);
}
NList resTupleType =NList(NList("Tstart"),
NList(Instant::BasicType())).enclose();
resTupleType.append(NList(NList("Tend"),NList(Instant::BasicType())));
resTupleType.append(NList(NList("Tlc"),NList(CcBool::BasicType())));
resTupleType.append(NList(NList("Trc"),NList(CcBool::BasicType())));
resTupleType.append(NList(NList("Unit1"),NList(r1_i->second)));
resTupleType.append(NList(NList("Unit2"),NList(r2_i->second)));
resTupleType.append(NList(NList("UnitNo1"),NList(CcInt::BasicType())));
resTupleType.append(NList(NList("UnitNo2"),NList(CcInt::BasicType())));
NList resType =
NList(NList(Symbol::STREAM()),NList(NList(Tuple::BasicType()),resTupleType));
return resType.listExpr();
}
/*
5.2.2.2 Value Mapping for Operator ~getRefinementPartition~
*/
template<class M1, class U1, class M2, class U2>
class RefinementPartitionLI {
public:
RefinementPartitionLI(M1* _m1, M2* _m2,
ListExpr _restype,
const bool _copy1, const bool _copy2)
:m1(_m1), m2(_m2), r(0),
restupletype(0), hasmore(false), m1_copy(0), m2_copy(0)
{
if(_copy1){
m1_copy = _m1;
}
if(_copy2){
m2_copy = _m2;
}
restupletype = new TupleType(nl->Second(_restype));
r = new RefinementStream<M1,M2,U1,U2>(m1,m2);
hasmore = r->hasNext();
}
~RefinementPartitionLI(){
if(restupletype){
restupletype->DeleteIfAllowed();
restupletype = 0;
}
if(r){
delete r;
r = 0;
}
if(m1_copy){
m1_copy->DeleteIfAllowed();
m1_copy = 0;
}
if(m2_copy){
m2_copy->DeleteIfAllowed();
m2_copy = 0;
}
}
bool hasMore(){
return hasmore;
} const
void next(Tuple* &t){
// get next pairing
Interval<Instant> iv;
int pos1;
int pos2;
if(r->getNext(iv, pos1, pos2)){
// get unit position data
CcInt* unit_no1 = new CcInt((pos1>=0), pos1);
CcInt* unit_no2 = new CcInt((pos2>=0), pos2);
// get interval data
Instant* tstart = new DateTime(instanttype);
Instant* tend = new DateTime(instanttype);
CcBool* tlc = new CcBool(true, true);
CcBool* trc = new CcBool(true, true);
*tstart = iv.start;
*tend = iv.end;
tlc->Set(true, iv.lc);
trc->Set(true, iv.rc);
// get unit data
U1 u1(true);
U2 u2(true);
U1* unit1 = new U1(true);
U2* unit2 = new U2(true);
if(pos1 >= 0){
m1->Get(pos1, u1);
u1.AtInterval(iv, *unit1);
} else {
unit1->SetDefined(false);
}
if(pos2 >= 0){
m2->Get(pos2, u2);
u2.AtInterval(iv, *unit2);
} else {
unit2->SetDefined(false);
}
// create the tuple
Tuple* restuple = new Tuple(restupletype);
restuple->PutAttribute(0,tstart);
restuple->PutAttribute(1,tend);
restuple->PutAttribute(2,tlc);
restuple->PutAttribute(3,trc);
restuple->PutAttribute(4,unit1);
restuple->PutAttribute(5,unit2);
restuple->PutAttribute(6,unit_no1);
restuple->PutAttribute(7,unit_no2);
// actualize hasmore flag and return restuple
hasmore = r->hasNext();
t = restuple;
} else { // no more results -> clear hasmore and return nullpointer
hasmore = false;
t = 0;
}
}
private:
const M1* m1;
const M2* m2;
RefinementStream<M1,M2,U1,U2>* r;
TupleType* restupletype;
bool hasmore;
M1* m1_copy;
M2* m2_copy;
};
template<class M1, class U1, class M2, class U2, bool IsUnit1, bool IsUnit2>
int GetRefinementPartitionVM( Word* args, Word& result, int message,
Word& local, Supplier s ){
RefinementPartitionLI<M1,U1,M2,U2>* li;
switch( message )
{
case OPEN:{
if(local.addr){
delete static_cast<RefinementPartitionLI<M1,U1,M2,U2>*>(local.addr);
local.setAddr(0);
}
M1* mo1;
if(IsUnit1){
mo1 = new M1(1);
U1* unit1 = static_cast<U1*>(args[0].addr);
if(unit1->IsDefined()){
mo1->Add(*unit1);
}
} else {
mo1 = static_cast<M1*>(args[0].addr);
}
M2* mo2;
if(IsUnit2){
mo2 = new M2(1);
U2* unit2 = static_cast<U2*>(args[1].addr);
if(unit2->IsDefined()){
mo2->Add(*unit2);
}
} else {
mo2 = static_cast<M2*>(args[1].addr);
}
li = new
RefinementPartitionLI<M1,U1,M2,U2>(mo1,
mo2,
GetTupleResultType(s),
IsUnit1,IsUnit2);
local.setAddr(li);
return 0;
}
case REQUEST:{
if(!local.addr){
return CANCEL;
}
li = static_cast<RefinementPartitionLI<M1,U1,M2,U2>*>(local.addr);
Tuple* t = 0;
if(li->hasMore()){
li->next(t);
if(t){
result.setAddr(t);
return YIELD;
}
}
return CANCEL;
}
case CLOSE:{
if(local.addr){
delete static_cast<RefinementPartitionLI<M1,U1,M2,U2>*>(local.addr);
local.setAddr(0);
}
return 0;
}
default:{
std::cerr << __PRETTY_FUNCTION__ << "Unknown message = " << message << "."
<< endl;
return -1;
}
} // end switch
std::cerr << __PRETTY_FUNCTION__ << "Unknown message = " << message << "."
<< endl;
return -1;
}
/*
5.2.2.3 Value Mapping Array for Operator ~getRefinementPartition~
*/
ValueMapping GetRefinementPartitionValueMapping[] = {
GetRefinementPartitionVM<MPoint,UPoint,MPoint,UPoint,false,false>, // 0
GetRefinementPartitionVM<MPoint,UPoint,MReal,UReal,false,false>,
GetRefinementPartitionVM<MPoint,UPoint,MInt,UInt,false,false>,
GetRefinementPartitionVM<MPoint,UPoint,MBool,UBool,false,false>,
GetRefinementPartitionVM<MPoint,UPoint,MString,UString,false,false>,
GetRefinementPartitionVM<MPoint,UPoint,MPoint,UPoint,false,true>,
GetRefinementPartitionVM<MPoint,UPoint,MReal,UReal,false,true>,
GetRefinementPartitionVM<MPoint,UPoint,MInt,UInt,false,true>,
GetRefinementPartitionVM<MPoint,UPoint,MBool,UBool,false,true>,
GetRefinementPartitionVM<MPoint,UPoint,MString,UString,false,true>, // 9
GetRefinementPartitionVM<MReal,UReal,MPoint,UPoint,false,false>, //10
GetRefinementPartitionVM<MReal,UReal,MReal,UReal,false,false>,
GetRefinementPartitionVM<MReal,UReal,MInt,UInt,false,false>,
GetRefinementPartitionVM<MReal,UReal,MBool,UBool,false,false>,
GetRefinementPartitionVM<MReal,UReal,MString,UString,false,false>,
GetRefinementPartitionVM<MReal,UReal,MPoint,UPoint,false,true>,
GetRefinementPartitionVM<MReal,UReal,MReal,UReal,false,true>,
GetRefinementPartitionVM<MReal,UReal,MInt,UInt,false,true>,
GetRefinementPartitionVM<MReal,UReal,MBool,UBool,false,true>,
GetRefinementPartitionVM<MReal,UReal,MString,UString,false,true>, //19
GetRefinementPartitionVM<MInt,UInt,MPoint,UPoint,false,false>, //20
GetRefinementPartitionVM<MInt,UInt,MReal,UReal,false,false>,
GetRefinementPartitionVM<MInt,UInt,MInt,UInt,false,false>,
GetRefinementPartitionVM<MInt,UInt,MBool,UBool,false,false>,
GetRefinementPartitionVM<MInt,UInt,MString,UString,false,false>,
GetRefinementPartitionVM<MInt,UInt,MPoint,UPoint,false,true>,
GetRefinementPartitionVM<MInt,UInt,MReal,UReal,false,true>,
GetRefinementPartitionVM<MInt,UInt,MInt,UInt,false,true>,
GetRefinementPartitionVM<MInt,UInt,MBool,UBool,false,true>,
GetRefinementPartitionVM<MInt,UInt,MString,UString,false,true>, //29
GetRefinementPartitionVM<MBool,UBool,MPoint,UPoint,false,false>, //30
GetRefinementPartitionVM<MBool,UBool,MReal,UReal,false,false>,
GetRefinementPartitionVM<MBool,UBool,MInt,UInt,false,false>,
GetRefinementPartitionVM<MBool,UBool,MBool,UBool,false,false>,
GetRefinementPartitionVM<MBool,UBool,MString,UString,false,false>, //34
GetRefinementPartitionVM<MBool,UBool,MPoint,UPoint,false,true>, //35
GetRefinementPartitionVM<MBool,UBool,MReal,UReal,false,true>,
GetRefinementPartitionVM<MBool,UBool,MInt,UInt,false,true>,
GetRefinementPartitionVM<MBool,UBool,MBool,UBool,false,true>,
GetRefinementPartitionVM<MBool,UBool,MString,UString,false,true>, //39
GetRefinementPartitionVM<MString,UString,MPoint,UPoint,false,false>, //40
GetRefinementPartitionVM<MString,UString,MReal,UReal,false,false>,
GetRefinementPartitionVM<MString,UString,MInt,UInt,false,false>,
GetRefinementPartitionVM<MString,UString,MBool,UBool,false,false>,
GetRefinementPartitionVM<MString,UString,MString,UString,false,false>, //44
GetRefinementPartitionVM<MString,UString,MPoint,UPoint,false,true>, //45
GetRefinementPartitionVM<MString,UString,MReal,UReal,false,true>,
GetRefinementPartitionVM<MString,UString,MInt,UInt,false,true>,
GetRefinementPartitionVM<MString,UString,MBool,UBool,false,true>,
GetRefinementPartitionVM<MString,UString,MString,UString,false,true>, //49
GetRefinementPartitionVM<MPoint,UPoint,MPoint,UPoint,true,false>, // 50
GetRefinementPartitionVM<MPoint,UPoint,MReal,UReal,true,false>,
GetRefinementPartitionVM<MPoint,UPoint,MInt,UInt,true,false>,
GetRefinementPartitionVM<MPoint,UPoint,MBool,UBool,true,false>,
GetRefinementPartitionVM<MPoint,UPoint,MString,UString,true,false>,
GetRefinementPartitionVM<MPoint,UPoint,MPoint,UPoint,true,true>,
GetRefinementPartitionVM<MPoint,UPoint,MReal,UReal,true,true>,
GetRefinementPartitionVM<MPoint,UPoint,MInt,UInt,true,true>,
GetRefinementPartitionVM<MPoint,UPoint,MBool,UBool,true,true>,
GetRefinementPartitionVM<MPoint,UPoint,MString,UString,true,true>, // 59
GetRefinementPartitionVM<MReal,UReal,MPoint,UPoint,true,false>, //60
GetRefinementPartitionVM<MReal,UReal,MReal,UReal,true,false>,
GetRefinementPartitionVM<MReal,UReal,MInt,UInt,true,false>,
GetRefinementPartitionVM<MReal,UReal,MBool,UBool,true,false>,
GetRefinementPartitionVM<MReal,UReal,MString,UString,true,false>,
GetRefinementPartitionVM<MReal,UReal,MPoint,UPoint,true,true>,
GetRefinementPartitionVM<MReal,UReal,MReal,UReal,true,true>,
GetRefinementPartitionVM<MReal,UReal,MInt,UInt,true,true>,
GetRefinementPartitionVM<MReal,UReal,MBool,UBool,true,true>,
GetRefinementPartitionVM<MReal,UReal,MString,UString,true,true>, //69
GetRefinementPartitionVM<MInt,UInt,MPoint,UPoint,true,false>, //70
GetRefinementPartitionVM<MInt,UInt,MReal,UReal,true,false>,
GetRefinementPartitionVM<MInt,UInt,MInt,UInt,true,false>,
GetRefinementPartitionVM<MInt,UInt,MBool,UBool,true,false>,
GetRefinementPartitionVM<MInt,UInt,MString,UString,true,false>,
GetRefinementPartitionVM<MInt,UInt,MPoint,UPoint,true,true>,
GetRefinementPartitionVM<MInt,UInt,MReal,UReal,true,true>,
GetRefinementPartitionVM<MInt,UInt,MInt,UInt,true,true>,
GetRefinementPartitionVM<MInt,UInt,MBool,UBool,true,true>,
GetRefinementPartitionVM<MInt,UInt,MString,UString,true,true>, //79
GetRefinementPartitionVM<MBool,UBool,MPoint,UPoint,true,false>, //80
GetRefinementPartitionVM<MBool,UBool,MReal,UReal,true,false>,
GetRefinementPartitionVM<MBool,UBool,MInt,UInt,true,false>,
GetRefinementPartitionVM<MBool,UBool,MBool,UBool,true,false>,
GetRefinementPartitionVM<MBool,UBool,MString,UString,true,false>,
GetRefinementPartitionVM<MBool,UBool,MPoint,UPoint,true,true>,
GetRefinementPartitionVM<MBool,UBool,MReal,UReal,true,true>,
GetRefinementPartitionVM<MBool,UBool,MInt,UInt,true,true>,
GetRefinementPartitionVM<MBool,UBool,MBool,UBool,true,true>,
GetRefinementPartitionVM<MBool,UBool,MString,UString,true,true>, //89
GetRefinementPartitionVM<MString,UString,MPoint,UPoint,true,false>, //90
GetRefinementPartitionVM<MString,UString,MReal,UReal,true,false>,
GetRefinementPartitionVM<MString,UString,MInt,UInt,true,false>,
GetRefinementPartitionVM<MString,UString,MBool,UBool,true,false>,
GetRefinementPartitionVM<MString,UString,MString,UString,true,false>,
GetRefinementPartitionVM<MString,UString,MPoint,UPoint,true,true>,
GetRefinementPartitionVM<MString,UString,MReal,UReal,true,true>,
GetRefinementPartitionVM<MString,UString,MInt,UInt,true,true>,
GetRefinementPartitionVM<MString,UString,MBool,UBool,true,true>,
GetRefinementPartitionVM<MString,UString,MString,UString,true,true> //99
};
/*
5.2.2.4 Selection Function for Operator ~getRefinementPartition~
*/
int GetRefinementPartitionSelect( ListExpr args ) {
int res = 0;
// first arg type
if(listutils::isSymbol(nl->First(args),
MPoint::BasicType())) { res+=0; }
else if(listutils::isSymbol(nl->First(args),
MReal::BasicType())) { res+=10; }
else if(listutils::isSymbol(nl->First(args),
MInt::BasicType())) { res+=20; }
else if(listutils::isSymbol(nl->First(args),
MBool::BasicType())) { res+=30; }
else if(listutils::isSymbol(nl->First(args),
MString::BasicType())) { res+=40; }
else if(listutils::isSymbol(nl->First(args),
UPoint::BasicType())) { res+=50; }
else if(listutils::isSymbol(nl->First(args),
UReal::BasicType())) { res+=60; }
else if(listutils::isSymbol(nl->First(args),
UInt::BasicType())) { res+=70; }
else if(listutils::isSymbol(nl->First(args),
UBool::BasicType())) { res+=80; }
else if(listutils::isSymbol(nl->First(args),
UString::BasicType())) { res+=90; }
else {res+= -9999999; }
// second arg type
if(listutils::isSymbol(nl->Second(args),MPoint::BasicType())) { res+=0; }
else if(listutils::isSymbol(nl->Second(args),
MReal::BasicType())) { res+=1; }
else if(listutils::isSymbol(nl->Second(args),
MInt::BasicType())) { res+=2; }
else if(listutils::isSymbol(nl->Second(args),
MBool::BasicType())) { res+=3; }
else if(listutils::isSymbol(nl->Second(args),
MString::BasicType())) { res+=4; }
else if(listutils::isSymbol(nl->Second(args),
UPoint::BasicType())) { res+=5; }
else if(listutils::isSymbol(nl->Second(args),
UReal::BasicType())) { res+=6; }
else if(listutils::isSymbol(nl->Second(args),
UInt::BasicType())) { res+=7; }
else if(listutils::isSymbol(nl->Second(args),
UBool::BasicType())) { res+=8; }
else if(listutils::isSymbol(nl->Second(args),
UString::BasicType())) { res+=9; }
else {res+= -9999999; }
return (((res>=0)&&(res<=99))?res:-1);
}
/*
5.2.2.5 Specification for Operator ~getRefinementPartition~
*/
OperatorInfo GetRefinementPartitionOperatorInfo(
"getRefinementPartion",
"{mT1|uT1} x {mT2|uT2} -> stream(tuple((Tstart instant)(Tend instant)(Tlc bool)"
"(Trc bool)(Unit1 uT1)(Unit2 uT2)(UnitNo1 int)(UnitNo2 int))); T1, T2 in "
"{point, real, int, bool, string}",
"getRefinementPartion( M1, M2 )",
"Creates a stream representing the temporal refinement partion of the two "
"arguments as a stream of tuples. Each result tuple contains a temporal "
"interval (represented by starting instant Tstart, ending instant Tend, and "
"closedness parameters Tlc (Tstart included), Trc (Tend includes)), "
"restrictions of both arguments, M1 and M2, to this interval, and the position "
"indexes of the according original units within M1 (UnitNo1), M2 (UnitNo2). "
"If for a given interval one of the arguments is not defined, the according "
"result unit is set to UNDEFINED. If one argument is UNDEFINED, the result "
"contains the original units of the other, defined, argument. If M1 and M2 are "
"both undefined, or both are empty (do not contain any unit) the result stream "
"is empty.",
"query getRefinementPartion(train1, train5) count"
""
);
/*
5.2.2.6 Operator definition for ~getRefinementPartition~
*/
Operator getrefinementpartition(
GetRefinementPartitionOperatorInfo,
GetRefinementPartitionValueMapping,
GetRefinementPartitionSelect,
GetRefinementPartitionTypeMapping
);
/*
5.2.3 Operator ~removeNoise~
*/
/*
5.2.3.1 Type Mapping for Operator ~removeNoise~
*/
ListExpr removeNoiseTM(ListExpr args){
if (!nl->HasLength(args, 3) && !nl->HasLength(args, 4)) {
return listutils::typeError("3 or 4 arguments expected");
}
if (!MPoint::checkType(nl->First(args))) {
return listutils::typeError("First argument must be an mpoint");
}
if (!CcReal::checkType(nl->Second(args))) {
return listutils::typeError("Second argument must be a real");
}
if (!CcReal::checkType(nl->Third(args))) {
return listutils::typeError("Third argument must be a real");
}
if (nl->HasLength(args, 4)) {
if (!Geoid::checkType(nl->Fourth(args))) {
return listutils::typeError("Fourth argument must be a geoid");
}
}
return nl->SymbolAtom(MPoint::BasicType());
}
/*
5.2.3.2 Value Mapping
*/
template<bool hasGeoid>
int removeNoiseVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
MPoint* res = (MPoint*)result.addr;
MPoint* src = (MPoint*)args[0].addr;
CcReal* maxspeed = (CcReal*)args[1].addr;
CcReal* maxdist = (CcReal*)args[2].addr;
Geoid *geoid = 0;
if (qp->GetNoSons(s) == 4) {
geoid = (Geoid*)args[3].addr;
}
if (!src->IsDefined() || !maxspeed->IsDefined() || !maxdist->IsDefined()) {
res->SetDefined(false);
}
else {
src->removeNoise(maxspeed->GetValue(), maxdist->GetValue(), geoid, *res);
}
return 0;
}
/*
5.2.2.3 Value Mapping Array for Operator ~removeNoise~
*/
ValueMapping removeNoiseVMs[] = {removeNoiseVM<false>, removeNoiseVM<true>};
/*
5.2.2.4 Selection Function for Operator ~removeNoise~
*/
int removeNoiseSelect(ListExpr args) {
if (nl->HasLength(args, 3)) return 0;
if (nl->HasLength(args, 4)) return 1;
return -1;
}
/*
5.2.2.5 Specification for Operator ~removeNoise~
*/
OperatorInfo removeNoiseOperatorInfo(
"removeNoise",
"mpoint x real x real [x geoid] -> mpoint",
"Movingpoint removeNoise[Maxspeed, Maxlength]",
"One outlier point in the raw data results in two long nonsense units in the "
"moving point. This operator detects them (according to the parameters) and "
"replaces them by one (usually short) unit. For an mpoint given in WGS84 "
"coordinates, the maximum speed and length are given in meters per second and"
" meters, respectively.",
"query no_components(train7) = no_components(train7 removeNoise[10.0, 20.0])"
"FALSE"
);
/*
5.2.2.6 Operator definition for ~removeNoise~
*/
Operator removeNoise(
removeNoiseOperatorInfo,
removeNoiseVMs,
removeNoiseSelect,
removeNoiseTM
);
/*
5.2.3 Operator ~forceToDuration~
*/
/*
5.2.3.1 Type Mapping for Operator ~forceToDuration~
*/
ListExpr forceToDurationTM(ListExpr args) {
if (!nl->HasLength(args, 3) && !nl->HasLength(args, 4)) {
return listutils::typeError("3 or 4 arguments expected");
}
if (!MPoint::checkType(nl->First(args)) &&
!CMPoint::checkType(nl->First(args))) {
return listutils::typeError("1st argument must be an mpoint or a cmpoint");
}
if (!Duration::checkType(nl->Second(args))) {
return listutils::typeError("Second argument must be a duration");
}
if (!CcBool::checkType(nl->Third(args))) {
return listutils::typeError("Third argument must be a bool");
}
if (nl->HasLength(args, 4)) {
if (!Geoid::checkType(nl->Fourth(args))) {
return listutils::typeError("Fourth argument must be a geoid");
}
}
return nl->First(args);
}
/*
5.2.3.2 Value Mapping
*/
template<class M, class U>
int forceToDurationVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
M* res = (M*)result.addr;
M* src = (M*)args[0].addr;
datetime::DateTime* duration = (datetime::DateTime*)args[1].addr;
CcBool* startAtBeginOfTime = (CcBool*)args[2].addr;
Geoid *geoid = 0;
if (qp->GetNoSons(s) == 4) {
geoid = (Geoid*)args[3].addr;
}
ForceToDuration<M, U>(*src, *duration, startAtBeginOfTime->GetValue(), *res,
geoid);
return 0;
}
/*
5.2.4.3 Value Mapping array and Selection Function
*/
ValueMapping forceToDurationVMs[] = {
forceToDurationVM<MPoint, UPoint>,
forceToDurationVM<CMPoint, CUPoint>
};
int forceToDurationSelect(ListExpr args) {
if (MPoint::checkType(nl->First(args))) {
return 0;
}
if (CMPoint::checkType(nl->First(args))) {
return 1;
}
return -1;
}
/*
5.2.2.5 Specification for Operator ~removeNoise~
*/
OperatorInfo forceToDurationOperatorInfo(
"forceToDuration",
"(c)mpoint x duration x bool [x geoid] -> (c)mpoint",
"forceToDuration[mp, dur, startAtBeginOfTime]",
"Extends or prunes the source (c)mpoint to a certain duration. The boolean "
"flag determines whether the beginning of the resulting mpoint is set to the "
"beginning of time or remains unchanged.",
"query no_components(forceToDuration(train7, create_duration(0,60000), TRUE))"
"1"
);
/*
5.2.2.6 Operator definition for ~forceToDuration~
*/
Operator forcetoduration(
"forceToDuration",
forceToDurationOperatorInfo.str(),
2,
forceToDurationVMs,
forceToDurationSelect,
forceToDurationTM
);
/*
5.2.3 Operator atRect
5.2.3.1 Type Maspping
Signature is: mpoint x rect -> mpoint
*/
ListExpr atRectTM(ListExpr args){
std::string err ="mpoint x rect expected";
if(!nl->HasLength(args,2)){
return listutils::typeError(err + " (wrong number of arguments)");
}
if(!MPoint::checkType(nl->First(args)) ||
!Rectangle<2>::checkType(nl->Second(args))){
return listutils::typeError(err);
}
return nl->SymbolAtom(MPoint::BasicType());
}
/*
5.2.3.2 Value Mapping
*/
int atRectVM( Word* args, Word& result, int message, Word&
local, Supplier s ){
MPoint* mp = (MPoint*) args[0].addr;
Rectangle<2>* rect = (Rectangle<2>*) args[1].addr;
result = qp->ResultStorage(s);
MPoint* res = (MPoint*) result.addr;
mp->AtRect(*rect,*res);
return 0;
}
/*
5.2.3.3 Specification
*/
const std::string atRectSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mpoint x rect -> mpoint </text---> "
"<text> mp atRect r </text--->"
"<text>Restricts the moving point mp to the part inside r "
"</text--->"
"<text>query train7 atRect bbox(thecenter)</text--->"
") )";
/*
5.2.3.4 Operator instance
*/
Operator atRect( "atRect",
atRectSpec,
atRectVM,
Operator::SimpleSelect,
atRectTM);
/*
5.2.4 Operator moveTo
This operator changes the start instant of a moving object
to the given object.
5.2.4.1 Type Mapping
Signature: mT x instant -> mT with T in { point, int, real }
*/
ListExpr moveToTM(ListExpr args){
std::string err = "mt x instant with T in {point, int, real, bool} expected";
if(!nl->HasLength(args,2)){
return listutils::typeError(err + " (wrong number of arguments)");
}
if(!Instant::checkType(nl->Second(args))){
return listutils::typeError(err +
" (second argument is not an instant)");
}
ListExpr first = nl->First(args);
if( MPoint::checkType(first) ||
MInt::checkType(first) ||
MReal::checkType(first) ||
MBool::checkType(first) ){ // extend this list
return first;
}
return listutils::typeError(err + " (unsupported first argument)");
}
/*
5.2.4.2 Value Mappings
*/
template<class MT>
int moveToVM1( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
MT* res = (MT*) result.addr;
MT* arg1 = (MT*) args[0].addr;
DateTime* instant = (DateTime*) args[1].addr;
arg1->moveTo(*instant, *res);
return 0;
}
/*
5.2.4.3 Value Mapping array and Selection function
*/
ValueMapping moveToVM[] = {
moveToVM1<MPoint>,
moveToVM1<MInt>,
moveToVM1<MReal>,
moveToVM1<MBool>
};
int moveToSelect(ListExpr args){
ListExpr f = nl->First(args);
if(MPoint::checkType(f)) {
return 0;
}
if(MInt::checkType(f)) {
return 1;
}
if(MReal::checkType(f)) {
return 2;
}
if(MBool::checkType(f)) {
return 3;
}
return -1;
}
/*
5.2.3.4 Specification
*/
const std::string moveToSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>mT x instant -> mT with T in {point, int, real, bool)"
"</text---> "
"<text> mT moveTo [instant] </text--->"
"<text>Changes the start instant of an moving object "
"</text--->"
"<text>query train7 moveTo[ now() ]</text--->"
") )";
/*
5.2.3.5 Operator Instance
*/
Operator moveTo(
"moveTo",
moveToSpec,
4,
moveToVM,
moveToSelect,
moveToTM);
/*
5.2.4 Operator fillGaps
This operator removes gaps within a periods value.
If the optional parameter ~d~ of type duration is given,
only such gaps having a duration smaller than or equal
to ~d~ are removed.
5.2.4.1 Type Mapping
*/
ListExpr fillGapsTM(ListExpr args){
int len = nl->ListLength(args);
std::string err = "{periods, mpoint} [x duration] expected";
if( (len!=1) && (len!=2)){
return listutils::typeError(err + " (wrong number of arguments)");
}
if(!Periods::checkType(nl->First(args))
&& !MPoint::checkType(nl->First(args))){
return listutils::typeError(err
+ " (first argument not of type periods or mpoint)");
}
if( (len==2) && !Duration::checkType(nl->Second(args))){
return listutils::typeError(err
+ " ( second parameter is not a duration)");
}
return nl->First(args);
}
/*
5.2.4.2 Value Mapping
*/
int fillGapsVM_per( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
Periods* res = (Periods*) result.addr;
Periods* p = (Periods*) args[0].addr;
res->Clear();
if(!p->IsDefined()){
res->SetDefined(false);
return 0;
}
res->SetDefined(true);
if(p->IsEmpty()){ // no content, no gap
return 0;
}
if(qp->GetNoSons(s)==1){ // without duration
Interval<Instant> iv1;
p->Get(0,iv1);
Interval<Instant> iv2;
p->Get(p->GetNoComponents()-1, iv2);
Interval<Instant> iv(iv1.start, iv2.end, iv1.lc, iv2.rc);
res->StartBulkLoad();
res->Add(iv);
res->EndBulkLoad(false);
return 0;
}
// the second parameter is given
DateTime* dur = (DateTime*) args[1].addr;
if(!dur->IsDefined()){
res->SetDefined(false);
return 0;
}
res->StartBulkLoad();
int size = p->GetNoComponents();
for(int i=0;i<size;i++){
Interval<Instant> iv1;
p->Get(i,iv1);
res->MergeAdd(iv1);
if(i<size-1){ // compute gap
Interval<Instant> iv2;
p->Get(i+1,iv2);
if((iv2.start-iv1.end) <= (*dur)){
Interval<Instant> iv(iv1.end, iv2.start, !iv1.rc, !iv2.lc);
res->MergeAdd(iv);
}
}
}
res->EndBulkLoad(false);
return 0;
}
int fillGapsVM_MP( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
MPoint* res = (MPoint*) result.addr;
MPoint* mp = (MPoint*) args[0].addr;
DateTime* d = qp->GetNoSons(s)==2?(DateTime*) args[1].addr:0;
if(!mp->IsDefined() || (d && !d->IsDefined())){
res->SetDefined(false);
return 0;
}
res->Clear();
int m = mp->GetNoComponents();
if(m==0){ // no elements -> no gap
return 0;
}
UPoint u1(false);
res->StartBulkLoad();
mp->Get(0,u1);
res->MergeAdd(u1);
UPoint u2(false);
for(int i=1;i<m; i++){
mp->Get(i,u2);
bool connect=true;
DateTime dist = u2.timeInterval.start - u1.timeInterval.end;
if(d){
if(dist > *d){
connect = false;
}
}
if(connect){
if(dist.IsZero()){
if(!u1.timeInterval.rc && !u2.timeInterval.lc){
// instant gap
u2.timeInterval.lc = true;
}
} else { // additional unit required
Interval<Instant> iv (u1.timeInterval.end , u2.timeInterval.start,
!u1.timeInterval.rc , !u2.timeInterval.lc);
UPoint gap (iv, u1.p1, u2.p0);
res->MergeAdd(gap);
}
}
res->MergeAdd(u2);
u1 = u2;
}
res->EndBulkLoad();
return 0;
}
ValueMapping fillGapsVM[] = {
fillGapsVM_per,
fillGapsVM_MP
};
int fillGapsSelect(ListExpr args){
return Periods::checkType(nl->First(args))?0:1;
}
/*
5.2.4.3 Specification
*/
const std::string fillGapsSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text> T [x duration] -> T, T in {periods,mpoint}"
"</text---> "
"<text> fillGaps(_ [,_] ) </text--->"
"<text>Fills gaps within a periods or mpoint value. If the optional "
" argument d is given, only gaps shorter or having the same"
" duration as d are removed."
"</text--->"
"<text>query fillGaps(deftime(train7))</text--->"
") )";
/*
5.2.4.4 Operator Instance
*/
Operator fillGaps(
"fillGaps",
fillGapsSpec,
2,
fillGapsVM,
fillGapsSelect,
fillGapsTM);
/*
5.3.5 Operator removeShort
This operator removes intervals shorther an a given duration from
a periods value.
5.3.5.1 Type Mapping
Signature: periods x duration -> periods
*/
ListExpr removeShortTM(ListExpr args){
std::string err = "periods x duration expected";
if(!nl->HasLength(args,2)){
return listutils::typeError(err + " (wrong number of arguments");
}
if(!Periods::checkType(nl->First(args)) ||
!Duration::checkType(nl->Second(args))){
return listutils::typeError(err);
}
return nl->SymbolAtom(Periods::BasicType());
}
/*
5.3.5.2 Value Mapping
*/
int removeShortVM( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
Periods* res = (Periods*) result.addr;
Periods* p = (Periods*) args[0].addr;
DateTime* dur = (DateTime*) args[1].addr;
res->Clear();
if(!p->IsDefined() || !dur->IsDefined()){
res->SetDefined(false);
return 0;
}
res->SetDefined(true);
res->StartBulkLoad();
Interval<Instant> iv;
int size = p->GetNoComponents();
for(int i=0;i<size;i++){
p->Get(i,iv);
DateTime d(datetime::durationtype);
d = iv.end - iv.start;
if( (d > (*dur)) ||
(d == (*dur) && iv.lc && iv.rc)){
res->Add(iv);
}
}
res->EndBulkLoad(false);
return 0;
}
/*
5.3.5.3 Specification
*/
const std::string removeShortSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text> periods x duration -> periods"
"</text---> "
"<text> removeShort( p ,d ) </text--->"
"<text>Removes intervals shorter than d from p. "
"</text--->"
"<text>query removeShort(deftime(train7),"
"[const duration value (1 0)]) </text--->"
") )";
/*
5.2.5.4 Operator instance
*/
Operator removeShort(
"removeShort",
removeShortSpec,
removeShortVM,
Operator::SimpleSelect,
removeShortTM);
/*
5.2.6 Operator getIntervals
This operator splits a periods value into single interval periods values
5.2.6.1 Type Mapping
Signature : periods -> stream(periods)
*/
ListExpr getIntervalsTM(ListExpr args){
std::string err = "periods expected";
if(!nl->HasLength(args,1)){
return listutils::typeError(err);
}
if(!Range<DateTime>::checkType(nl->First(args))){
return listutils::typeError(err);
}
return nl->TwoElemList( listutils::basicSymbol<Stream<SecInterval> >(),
listutils::basicSymbol<SecInterval> () );
}
/*
5.2.6.2 Value Mapping
The template parameter controls whether the resulting stream returns
intervals (single = true) or intervals wrapped into a periods
value (single = false).
*/
template<bool single>
int getIntervalsVM(Word* args, Word& result, int message,
Word& local, Supplier s) {
size_t* li = (size_t*) local.addr;
Range<DateTime>* p = (Range<DateTime>*)args[0].addr;
size_t v;
switch(message) {
case OPEN:
if (li) {
delete li;
local.addr = 0;
}
if (p->IsDefined()) {
local.addr = new size_t(0);
}
return 0;
case REQUEST:
if (!li) {
return CANCEL;
}
v = *li;
if (v >= (size_t)p->GetNoComponents()) {
return CANCEL;
}
else {
Interval<DateTime> iv;
p->Get(*li, iv);
(*li)++;
if (single) {
result.addr = new SecInterval(iv);
}
else {
Range<DateTime>* r = new Range<DateTime>(1);
r->Add(iv);
result.addr = r;
}
return YIELD;
}
case CLOSE:
if (li) {
delete li;
local.addr = 0;
}
return 0;
}
return -1;
}
/*
5.2.6.3 Specification
*/
const std::string getIntervalsSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text> periods -> stream(interval)"
"</text---> "
"<text> getIntervals(_) </text--->"
"<text>Puts the intervals of a periods value into a stream "
"</text--->"
"<text>query getIntervals(deftime(train7)) count"
" </text--->"
") )";
/*
5.2.6.4 Operator instance
*/
Operator getIntervals(
"getIntervals",
getIntervalsSpec,
getIntervalsVM<true>,
Operator::SimpleSelect,
getIntervalsTM);
/*
5.2.7 Operator ~components~
----
periods -> stream(interval)
----
*/
/*
5.2.7.1 Type Mapping for operator ~components~
*/
ListExpr componentsTM(ListExpr args) {
std::string err = "one argument of type periods expected";
if (!nl->HasLength(args, 1)){
return listutils::typeError(err);
}
if (Periods::checkType(nl->First(args))){
return nl->TwoElemList(
nl->SymbolAtom(Stream<Attribute>::BasicType()),
nl->SymbolAtom(Range<DateTime>::BasicType()));
}
if(MPoint::checkType(nl->First(args))){
return nl->TwoElemList(
nl->SymbolAtom(Stream<Attribute>::BasicType()),
nl->SymbolAtom(MPoint::BasicType()));
}
return listutils::typeError(err);
}
/*
5.2.7.2 Value Mapping for operator ~components~
*/
class ComponentsLocal{
public:
ComponentsLocal(MPoint* _mp): mp(_mp), pos(0) {}
MPoint* next(){
if(pos>=mp->GetNoComponents()){
return 0;
}
MPoint* res = new MPoint(3);
res->StartBulkLoad();
UPoint up(false);
mp->Get(pos,up);
res->Add(up);
pos++;
while(pos < mp->GetNoComponents()){
UPoint up2(false);
mp->Get(pos,up2);
if(up.Adjacent(&up2)){
res->Add(up2);
up = up2;
pos++;
} else {
res->EndBulkLoad(false);
return res;
}
}
res->EndBulkLoad(false);
return res;
}
private:
MPoint* mp;
int pos;
};
int componentsVM_mp(Word* args, Word& result, int message,
Word& local, Supplier s) {
ComponentsLocal* li = (ComponentsLocal*) local.addr;
switch(message){
case OPEN:
if(li) {
delete li;
}
local.addr = new ComponentsLocal( (MPoint*) args[0].addr);
return 0;
case REQUEST:
result.addr= li?li->next():0;
return result.addr?YIELD:CANCEL;
case CLOSE:
if(li){
delete li;
local.addr = 0;
}
return 0;
}
return -1;
}
ValueMapping componentsVM[] = {
getIntervalsVM<false>,
componentsVM_mp
};
/*
5.2.7.3 Selection function
*/
int componentsSelect(ListExpr args){
if (Periods::checkType(nl->First(args))){
return 0;
}
if(MPoint::checkType(nl->First(args))){
return 1;
}
return -1;
}
/*
5.2.7.3 Specification
*/
const std::string componentsSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text> periods -> stream(periods) ; mpoint -> stream(mpoint)"
"</text---> "
"<text> components(_) </text--->"
"<text>Splits the argument into connected components"
"</text--->"
"<text>query components(deftime(train7)) count"
" </text--->"
") )";
/*
5.2.6.4 Operator instance
*/
Operator components(
"components",
componentsSpec,
2,
componentsVM,
componentsSelect,
componentsTM);
/*
5.2.7 Operator trajectory3
5.2.7.1 Type Mapping
*/
ListExpr trajectory3TM(ListExpr args){
if(!nl->HasLength(args,1)){
return listutils::typeError("one argument expected");
}
std::string err = "Mpoint expected";
if(!MPoint::checkType(nl->First(args))){
return listutils::typeError(err);
}
return listutils::basicSymbol<DLine>();
}
/*
5.2.7.2 Value Mapping
*/
int trajectory3VM( Word* args, Word& result, int message, Word&
local, Supplier s ){
MPoint* arg = (MPoint*) args[0].addr;
result= qp->ResultStorage(s);
DLine* res = (DLine*) result.addr;
if(!arg->IsDefined()){
res->SetDefined(false);
return 0;
}
res->clear();
UPoint unit;
for(int i=0;i<arg->GetNoComponents();i++){
arg->Get(i,unit);
SimpleSegment s(unit.p0.GetX(), unit.p0.GetY(),
unit.p1.GetX(), unit.p1.GetY());
res->append(s);
}
return 0;
}
/*
5.2.7.3 Specification
*/
const std::string trajectory3Spec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text> mpoint -> dline"
"</text---> "
"<text> trajectory3(_) </text--->"
"<text>Computes the trajectory of a moving point as a dline "
"</text--->"
"<text>query trajectory3(train7) "
" </text--->"
") )";
/*
5.2.6.4 Operator instance
*/
Operator trajectory3(
"trajectory3",
trajectory3Spec,
trajectory3VM,
Operator::SimpleSelect,
trajectory3TM);
/*
5.2.7 Operator createPeriods
5.2.7.1 Type Mapping
*/
ListExpr createPeriodsTM(ListExpr args){
std::string err = "instant x {instant, duration} x bool x bool expected";
if(!nl->HasLength(args,4)){
return listutils::typeError(err);
}
if(!Instant::checkType(nl->First(args))){
return listutils::typeError(err);
}
if(!Instant::checkType(nl->Second(args)) &&
!Duration::checkType(nl->Second(args))){
return listutils::typeError(err);
}
if(!CcBool::checkType(nl->Third(args))){
return listutils::typeError(err);
}
if(!CcBool::checkType(nl->Fourth(args))){
return listutils::typeError(err);
}
return listutils::basicSymbol<Periods>();
}
/*
5.2.7.2 Value Mappings
*/
int createPeriodsVMinstant( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
Periods* res = (Periods*) result.addr;
Instant* i1 = (Instant*) args[0].addr;
Instant* i2 = (Instant*) args[1].addr;
CcBool* lc = (CcBool*) args[2].addr;
CcBool* rc = (CcBool*) args[3].addr;
if(!i1->IsDefined() || !i2->IsDefined() ||
!lc->IsDefined() || !rc->IsDefined()){
res->SetDefined(false);
return 0;
}
res->Clear();
res->SetDefined(true);
DateTime dur = (*i2) - (*i1);
if(dur.LessThanZero() ||
(dur.IsZero() && !( lc->GetBoolval() && rc->GetBoolval()))){
// invalid interval
res->SetDefined(false);
return 0;
}
Interval<Instant> iv(*i1, ((*i1)+dur), lc->GetBoolval(), rc->GetBoolval());
res->Add(iv);
return 0;
}
int createPeriodsVMduration( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
Periods* res = (Periods*) result.addr;
Instant* i1 = (Instant*) args[0].addr;
DateTime* dur2 = (DateTime*) args[1].addr;
CcBool* lc = (CcBool*) args[2].addr;
CcBool* rc = (CcBool*) args[3].addr;
if(!i1->IsDefined() || !dur2->IsDefined() ||
!lc->IsDefined() || !rc->IsDefined()){
res->SetDefined(false);
return 0;
}
res->Clear();
res->SetDefined(true);
DateTime dur = *dur2;
if(dur.LessThanZero() ||
(dur.IsZero() && !( lc->GetBoolval() && rc->GetBoolval()))){
// invalid interval
res->SetDefined(false);
return 0;
}
Interval<Instant> iv(*i1, (*i1)+dur, lc->GetBoolval(), rc->GetBoolval());
res->Add(iv);
return 0;
}
/*
ValueMappingarray and Selection function
*/
ValueMapping createPeriodsVM[] = {
createPeriodsVMinstant,
createPeriodsVMduration
};
int createPeriodsSelect(ListExpr args){
return Instant::checkType(nl->Second(args))?0:1;
}
/*
Specification
*/
const std::string createPeriodsSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text> instant x {instant,duration} x bool x bool -> periods"
"</text---> "
"<text> createPeriods(_,_,_,_) </text--->"
"<text>Computes a periods value containing a single interval "
"</text--->"
"<text>query createPeriods( [const instant value \"2013-04-18\"],"
" [const duration value (1 0), TRUE, FALSE "
" </text--->"
") )";
/*
Operator instance
*/
Operator createPeriodsOp(
"createPeriods",
createPeriodsSpec,
2,
createPeriodsVM,
createPeriodsSelect,
createPeriodsTM
);
namespace ct{
/*
Operator contains
this operator checks whether a periods value contains a certain instant.
*/
ListExpr containsTM(ListExpr args){
std::string err = "periods x instant expected";
if(!nl->HasLength(args,2)){
return listutils::typeError(err);
}
if(!Periods::checkType(nl->First(args)) ||
!Instant::checkType(nl->Second(args))){
return listutils::typeError(err);
}
return listutils::basicSymbol<CcBool>();
}
/*
value mapping
*/
int containsVM( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
Periods* p = (Periods*) args[0].addr;
Instant* i = (Instant*) args[1].addr;
CcBool* res = (CcBool*) result.addr;
if(!p->IsDefined() || !i->IsDefined()){
res->SetDefined(false);
} else {
res->Set(true, p->Contains(*i));
}
return 0;
}
OperatorSpec containsSpec(
"periods x instant -> bool",
"_ contains _",
"Checks whether a periods value contains a certain instant",
" query theyear(2014) contains [const instant value \"2014-02-14\"]");
Operator containsOP
(
"contains", //name
containsSpec.getStr(), //specification
containsVM, //value mapping
Operator::SimpleSelect, //trivial selection function
containsTM //type mapping
);
/*
16 Operator ~replace~
This Operator replaces part of a moving point by
another moving point.
16.1 Type Mapping
*/
ListExpr replaceTM(ListExpr args){
std::string err = "mpoint x {mpoint, upoint} expected";
if(!nl->HasLength(args,2)){
return listutils::typeError(err + " (invalid number of args)");
}
if(!MPoint::checkType(nl->First(args))){
return listutils::typeError(err + " (first argument is not an mpoint)");
}
if( !MPoint::checkType(nl->Second(args))
&& !UPoint::checkType(nl->Second(args))){
return listutils::typeError(err + " (invalid second arg type)");
}
return nl->First(args);
}
/*
16.2 Value Mapping template
*/
template<class A1, class A2>
int replaceVMT( Word* args, Word& result, int message, Word&
local, Supplier s ){
A1* arg1 = (A1*) args[0].addr;
A2* arg2 = (A2*) args[1].addr;
result = qp->ResultStorage(s);
A1* res = (A1*) result.addr;
res->Clear();
if(!arg1->IsDefined() || !arg2->IsDefined()){
res->SetDefined(false);
return 0;
}
res->SetDefined(true);
res->StartBulkLoad();
typedef typename A1::unittype U1;
RefinementStream<A1,A2, U1, U1> refine(arg1,arg2);
Interval<Instant> iv;
int pos1;
int pos2;
U1 unit(false);
U1 unit_restricted(false);
while( refine.getNext(iv,pos1,pos2)){
if(pos2>=0){
arg2->Get(pos2,unit);
} else {
arg1->Get(pos1,unit);
}
unit.AtInterval(iv, unit_restricted);
res->MergeAdd(unit_restricted);
}
res->EndBulkLoad();
return 0;
}
/*
16.3 Value Mapping Array and Selection
*/
ValueMapping replaceVM[] = {
replaceVMT<MPoint,MPoint>,
replaceVMT<MPoint,UPoint>
};
int replaceSelect(ListExpr args){
return MPoint::checkType(nl->Second(args))?0:1;
}
OperatorSpec replaceSpec(
"mpoint x {mpoint, upoint} -> mpoint",
"replace(_,_)",
"Replaces parts of y moving points by definitions "
"within another moving point.",
"query replace(train1 , train7)"
);
Operator replaceOp(
"replace",
replaceSpec.getStr(),
2,
replaceVM,
replaceSelect,
replaceTM
);
/*
17 Operator ~remove~
This operator removes certain imtervals from a moving object.
*/
ListExpr removeTM(ListExpr args){
if(!nl->HasLength(args,2)){
return listutils::typeError("two arguments expected");
}
if(!Periods::checkType(nl->Second(args))){
return listutils::typeError("second argument must be of type period.");
}
ListExpr a = nl->First(args);
if( !MString::checkType(a)
&& !MReal::checkType(a)
&& !MPoint::checkType(a)
&& !MInt::checkType(a)
&& !MBool::checkType(a)
&& !Periods::checkType(a)){
return listutils::typeError("first argument is usupported");
}
return a;
}
template<class M>
int removeVMT( Word* args, Word& result, int message, Word&
local, Supplier s ){
M* moving = (M*) args[0].addr;
Periods* p = (Periods*) args[1].addr;
result = qp->ResultStorage(s);
M* res = (M*) result.addr;
res->Clear();
if(!moving->IsDefined() || !p->IsDefined()){
res->SetDefined(false);
return 0;
}
res->SetDefined(true);
res->StartBulkLoad();
typedef typename M::unittype U;
RefinementStream<M,Periods, U, Periods::unittype> refine(moving,p);
Interval<Instant> iv;
int pos1;
int pos2;
U unit(false);
U unit_restricted(false);
while( refine.getNext(iv,pos1,pos2)){
if(pos1>=0 && pos2<0){
moving->Get(pos1,unit);
unit.AtInterval(iv, unit_restricted);
res->MergeAdd(unit_restricted);
}
}
res->EndBulkLoad();
return 0;
}
ValueMapping removeVM[] = {
removeVMT<MString>,
removeVMT<MReal>,
removeVMT<MPoint>,
removeVMT<MInt>,
removeVMT<MBool>,
removeVMT<Periods>
};
int removeSelect(ListExpr args){
ListExpr a = nl->First(args);
if(MString::checkType(a)) return 0;
if(MReal::checkType(a)) return 1;
if(MPoint::checkType(a)) return 2;
if(MInt::checkType(a)) return 3;
if(MBool::checkType(a)) return 4;
if(Periods::checkType(a)) return 5;
return -1;
}
OperatorSpec removeSpec(
"X x periods -> X, X in {mpoint, mint, mreal, mstring, mbool, periods}",
"_ removePeriods[_]",
"Removes intervals given by the second argument from the first one. ",
"query train1 removePeriods[deftime(tran6)]"
);
Operator removeOp(
"removePeriods",
removeSpec.getStr(),
6,
removeVM,
removeSelect,
removeTM
);
/*
Operator ~getGKZone~
returns teh gauss krueger zone for a given real or point.
*/
ListExpr getGKZoneTM(ListExpr args){
if(!nl->HasLength(args,1)){
return listutils::typeError("exactly one argument required");
}
ListExpr arg1 = nl->First(args);
if(!CcReal::checkType(arg1) && !Point::checkType(arg1)){
return listutils::typeError("real or point expected");
}
return listutils::basicSymbol<CcInt>();
}
inline double getX(Point* p){ return p->GetX(); }
inline double getX(CcReal* p){ return p->GetValue(); }
template<class T>
int getGKZoneVMT( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
CcInt* res = (CcInt*) result.addr;
T* arg = (T*) args[0].addr;
if(!arg->IsDefined()){
res->SetDefined(false);
return 0;
}
double x = getX(arg);
if(x<-180 || x>180){
res->SetDefined(false);
return 0;
}
if(x<0) x = x + 360;
res->Set(true, (int)(x / 3));
return 0;
}
ValueMapping getGKZoneVM[] = {
getGKZoneVMT<CcReal>,
getGKZoneVMT<Point>
};
int getGKZoneSelect(ListExpr args){
return CcReal::checkType(nl->First(args))?0:1;
}
OperatorSpec getGKZoneSpec(
"{real, point} -> int",
"getGKZone(_)",
"retrieves the zone for Gauss Krueger projektion dor a given Longitude.",
"query getGKZone(7.41)"
);
Operator getGKZoneOp(
"getGKZone",
getGKZoneSpec.getStr(),
2,
getGKZoneVM,
getGKZoneSelect,
getGKZoneTM
);
} // end of namespace ct
/*
Operator ~constmpoint~
This operator creates a static point for a given periods.
*/
ListExpr constmpointTM(ListExpr args){
std::string err = "periods x point expected";
if(!nl->HasLength(args,2)){
return listutils::typeError(err+" (wrong number of args)");
}
if(!Periods::checkType(nl->First(args))){
return listutils::typeError(err+" (first arg is not a periods)");
}
if(!Point::checkType(nl->Second(args))){
return listutils::typeError(err+" (second arg is not a point)");
}
return listutils::basicSymbol<MPoint>();
}
int constmpointVM( Word* args, Word& result, int message, Word&
local, Supplier s ){
result = qp->ResultStorage(s);
MPoint* res = (MPoint*) result.addr;
res->Clear();
Periods* periods = (Periods*) args[0].addr;
Point* point = (Point*) args[1].addr;
if(!periods->IsDefined() || !point->IsDefined()){
res->SetDefined(false);
return 0;
}
res->SetDefined(true);
double x = point->GetX();
double y = point->GetY();
for(int i=0;i<periods->GetNoComponents();i++){
Periods::unittype interval;
periods->Get(i,interval);
UPoint unit(interval,x,y,x,y);
res->MergeAdd(unit);
}
return 0;
}
OperatorSpec constmpointSpec(
"periods x point -> mpoint",
"constmpoint(_,_)",
"Creates a static mpoint at a certain position "
"that exists at given intervals",
"query constmpoint(periods1, point1)"
);
Operator constmpointOp(
"constmpoint",
constmpointSpec.getStr(),
constmpointVM,
Operator::SimpleSelect,
constmpointTM
);
/*
Operator ~cbbox~
This operator creates a cupoint from an mpoint or upoint.
*/
ListExpr cbboxTM(ListExpr args) {
std::string err = "(cmpoint x geoid) | (mpoint x geoid) | upoint (x real) "
"expected";
if (!nl->HasLength(args, 2) && !nl->HasLength(args, 1)) {
return listutils::typeError(err + " (wrong number of args)");
}
if (!MPoint::checkType(nl->First(args))
&& !UPoint::checkType(nl->First(args))
&& !CMPoint::checkType(nl->First(args))) {
return listutils::typeError(err +" (first arg is not a (u|m|cm)point)");
}
if (nl->HasLength(args, 2)) {
if ((!CMPoint::checkType(nl->First(args)) ||
!Geoid::checkType(nl->Second(args))) &&
(!MPoint::checkType(nl->First(args)) ||
!Geoid::checkType(nl->Second(args))) &&
(!UPoint::checkType(nl->First(args)) ||
!CcReal::checkType(nl->Second(args)))) {
return listutils::typeError(err);
}
}
return listutils::basicSymbol<CUPoint>();
}
template<class T>
int cbboxVM(Word* args, Word& result, int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
CUPoint* res = (CUPoint*)result.addr;
T* src = (T*)args[0].addr;
if (!src->IsDefined()) {
res->SetDefined(false);
return 0;
}
Geoid *geoid = 0;
double radius = 0.0;
if (qp->GetNoSons(s) == 2) {
if (T::BasicType() != UPoint::BasicType()) { // no upoint => 2nd arg = geoid
geoid = (Geoid*)args[1].addr;
if (!geoid->IsDefined()) {
res->SetDefined(false);
return 0;
}
}
else {
CcReal* ccrad = (CcReal*)args[1].addr;
if (!ccrad->IsDefined()) {
res->SetDefined(false);
return 0;
}
radius = ccrad->GetValue();
}
}
res->ConvertFrom(*src, geoid);
if (T::BasicType() == "upoint") {
res->SetRadius(radius);
}
else if (T::BasicType() == "mpoint") {
res->SetRadius(res->GetRadius());
}
return 0;
}
int cbboxSelect(ListExpr args) {
if (UPoint::checkType(nl->First(args))) {
return 0;
}
if (MPoint::checkType(nl->First(args))) {
return 1;
}
if (CMPoint::checkType(nl->First(args))) {
return 2;
}
return -1;
}
ValueMapping cbboxVMs[] = {
cbboxVM<UPoint>,
cbboxVM<MPoint>,
cbboxVM<CMPoint>
};
OperatorSpec cbboxSpec(
"cmpoint (x geoid) | mpoint (x geoid) | upoint (x real) -> cupoint",
"cbbox(_, _)",
"Creates a cupoint from a cmpoint, an mpoint or a upoint with a real ("
"otherwise the radius is set to 0.0)",
"query cbbox([const upoint value ((1 2 TRUE FALSE) (0.0 0.0 1.0 1.0))])"
);
Operator cbbox(
"cbbox",
cbboxSpec.getStr(),
3,
cbboxVMs,
cbboxSelect,
cbboxTM
);
/*
Operator ~getRadius~
This operator returns the radius of a CUPoint.
*/
ListExpr getRadiusTM(ListExpr args) {
std::string err = "cupoint expected";
if (!nl->HasLength(args, 1)) {
return listutils::typeError(err + " (wrong number of args)");
}
if (!CUPoint::checkType(nl->First(args))) {
return listutils::typeError(err +" (first arg is not a cupoint)");
}
return listutils::basicSymbol<CcReal>();
}
int getRadiusVM(Word* args, Word& result, int message, Word& local, Supplier s){
result = qp->ResultStorage(s);
CcReal* res = (CcReal*)result.addr;
CUPoint* src = (CUPoint*)args[0].addr;
if (!src->IsDefined()) {
res->SetDefined(false);
return 0;
}
res->Set(true, src->GetRadius());
return 0;
}
OperatorSpec getRadiusSpec(
"cupoint -> real",
"getRadius(_)",
"Returns the radius from a CUPoint",
"query getRadius([const cupoint value ((1 2 TRUE FALSE) (0.0 0.0 1.0 1.0) "
"0.3)])"
);
Operator getRadius(
"getRadius",
getRadiusSpec.getStr(),
getRadiusVM,
Operator::SimpleSelect,
getRadiusTM
);
/*
Operator ~getRadii~
This operator returns the radii of a CMPoint as an MReal.
*/
ListExpr getRadiiTM(ListExpr args) {
std::string err = "cmpoint expected";
if (!nl->HasLength(args, 1)) {
return listutils::typeError(err + " (wrong number of args)");
}
if (!CMPoint::checkType(nl->First(args))) {
return listutils::typeError(err +" (arg is not a cmpoint)");
}
return listutils::basicSymbol<MReal>();
}
int getRadiiVM(Word* args, Word& result, int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
MReal* res = (MReal*)result.addr;
CMPoint* src = (CMPoint*)args[0].addr;
if (!src->IsDefined()) {
res->SetDefined(false);
return 0;
}
src->GetRadii(*res);
return 0;
}
OperatorSpec getRadiiSpec(
"cmpoint -> mreal",
"getRadii(_)",
"Returns the sequence of radii from a CMPoint as an MReal",
"query sometimes(getRadii([const cmpoint value (((1 2 TRUE FALSE) "
"(0.0 0.0 1.0 1.0) 0.3))]) > 0.25)"
);
Operator getRadii(
"getRadii",
getRadiiSpec.getStr(),
getRadiiVM,
Operator::SimpleSelect,
getRadiiTM
);
/*
Operator ~getUPoint~
This operator returns the UPoint value of a CUPoint.
*/
ListExpr getUPointTM(ListExpr args) {
std::string err = "cupoint expected";
if (!nl->HasLength(args, 1)) {
return listutils::typeError(err + " (wrong number of args)");
}
if (!CUPoint::checkType(nl->First(args))) {
return listutils::typeError(err +" (first arg is not a cupoint)");
}
return listutils::basicSymbol<UPoint>();
}
int getUPointVM(Word* args, Word& result, int message, Word& local, Supplier s){
result = qp->ResultStorage(s);
UPoint* res = (UPoint*)result.addr;
CUPoint* src = (CUPoint*)args[0].addr;
src->GetUPoint(*res);
return 0;
}
OperatorSpec getUPointSpec(
"cupoint -> upoint",
"getUPoint(_)",
"Returns the UPoint value of a CUPoint",
"query getUPoint([const cupoint value ((1 2 TRUE FALSE) (0.0 0.0 1.0 1.0) "
"0.3)])"
);
Operator getUPoint(
"getUPoint",
getUPointSpec.getStr(),
getUPointVM,
Operator::SimpleSelect,
getUPointTM
);
/*
Operator ~getMPoint~
This operator returns the MPoint value of a CMPoint.
*/
ListExpr getMPointTM(ListExpr args) {
std::string err = "cmpoint expected";
if (!nl->HasLength(args, 1)) {
return listutils::typeError(err + " (wrong number of args)");
}
if (!CMPoint::checkType(nl->First(args))) {
return listutils::typeError(err +" (first arg is not a cmpoint)");
}
return listutils::basicSymbol<MPoint>();
}
int getMPointVM(Word* args, Word& result, int message, Word& local, Supplier s){
result = qp->ResultStorage(s);
MPoint* res = (MPoint*)result.addr;
CMPoint* src = (CMPoint*)args[0].addr;
src->GetMPoint(*res);
return 0;
}
OperatorSpec getMPointSpec(
"cmpoint -> mpoint",
"getMPoint(_)",
"Returns the MPoint value of a CMPoint",
"query getMPoint([const cmpoint value (((1 2 TRUE FALSE) (0.0 0.0 1.0 1.0) "
"0.3))])"
);
Operator getMPoint(
"getMPoint",
getMPointSpec.getStr(),
getMPointVM,
Operator::SimpleSelect,
getMPointTM
);
/*
Operator ~mpoint2cmpoint~
This operator creates a cmpoint from an mpoint and a duration or an mpoint and
a real. In the first case, all units (except the last one) are created with the
specified duration. Otherwise, a new unit is created as soon as the specified
distance threshold is exceeded.
*/
ListExpr mpoint2cmpointTM(ListExpr args) {
std::string err = "mpoint x (duration|real) (x geoid) expected";
if (!nl->HasLength(args, 2) && !nl->HasLength(args, 3)) {
return listutils::typeError(err + " (wrong number of arguments)");
}
if (!MPoint::checkType(nl->First(args))) {
return listutils::typeError(err + " (first arg is not an mpoint)");
}
if (!Duration::checkType(nl->Second(args))
&& !CcReal::checkType(nl->Second(args))) {
return listutils::typeError(err + " (second arg must be duration or real)");
}
if (nl->HasLength(args, 3)) {
if (!Geoid::checkType(nl->Third(args))) {
return listutils::typeError(err + " (third arg must be a geoid)");
}
}
return listutils::basicSymbol<CMPoint>();
}
template<class T>
int mpoint2cmpointVM(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
CMPoint* res = (CMPoint*)result.addr;
MPoint* src = (MPoint*)args[0].addr;
T* param = (T*)args[1].addr;
if (!src->IsDefined()) {
res->SetDefined(false);
return 0;
}
Geoid *geoid = 0;
if (qp->GetNoSons(s) == 3) {
geoid = (Geoid*)args[2].addr;
}
res->ConvertFrom(*src, *param, geoid);
return 0;
}
int mpoint2cmpointSelect(ListExpr args) {
return Duration::checkType(nl->Second(args)) ? 0 : 1;
}
ValueMapping mpoint2cmpointVMs[] = {
mpoint2cmpointVM<DateTime>,
mpoint2cmpointVM<CcReal>
};
OperatorSpec mpoint2cmpointSpec(
"mpoint x (duration|real) (x geoid) -> cmpoint",
"mpoint2cmpoint(_, _)",
"Creates a cmpoint from an mpoint and a duration or an mpoint and a real (and"
" an optional geoid). In the first case, all units (except the last one) are "
"created with the specified duration. Otherwise, a new unit is created as "
"soon as the specified distance threshold is exceeded.",
"query mpoint2cmpoint(train5, [const duration value (0 60000)])"
);
Operator mpoint2cmpoint(
"mpoint2cmpoint",
mpoint2cmpointSpec.getStr(),
2,
mpoint2cmpointVMs,
mpoint2cmpointSelect,
mpoint2cmpointTM
);
/*
Operator ~traversed~
This operator converts a cupoint into a cupointregion.
*/
ListExpr traversedTM(ListExpr args) {
std::string err = "cupoint or cmpoint expected";
if (!nl->HasLength(args, 1)) {
return listutils::typeError(err + " (wrong number of args)");
}
if (CUPoint::checkType(nl->First(args))) {
return nl->SymbolAtom("cupointregion");
}
if (CMPoint::checkType(nl->First(args))) {
return nl->SymbolAtom("cmpointregion");
}
return listutils::typeError(err +" (arg is not a cupoint or cmpoint)");
}
template<class CXPoint>
int traversedVM(Word* args, Word& result, int message, Word& local, Supplier s){
result = qp->ResultStorage(s);
CXPoint* res = (CXPoint*)result.addr;
CXPoint* src = (CXPoint*)args[0].addr;
*res = *src;
return 0;
}
int traversedSelect(ListExpr args) {
return CUPoint::checkType(nl->First(args)) ? 0 : 1;
}
ValueMapping traversedVMs[] = {
traversedVM<CUPoint>,
traversedVM<CMPoint>
};
OperatorSpec traversedSpec(
"cXpoint -> cXpointregion, X in {m,u}",
"traversed(_)",
"This operator converts a cXpoint into a cXpointregion (X in {m,u})",
"query traversed([const cupoint value ((1 2 TRUE FALSE) (0.0 0.0 1.0 1.0) "
"0.3)])"
);
Operator traversed(
"traversed",
traversedSpec.getStr(),
2,
traversedVMs,
traversedSelect,
traversedTM
);
/*
6 Creating the Algebra
*/
class TemporalAlgebra : public Algebra
{
public:
TemporalAlgebra() : Algebra()
{
AddTypeConstructor( &rangeint );
AddTypeConstructor( &rangereal );
AddTypeConstructor( &periods );
AddTypeConstructor( &intimebool );
AddTypeConstructor( &intimeint );
AddTypeConstructor( &intimereal );
AddTypeConstructor( &intimepoint );
AddTypeConstructor( &intimecpoint );
AddTypeConstructor( &unitbool );
AddTypeConstructor( &unitint );
AddTypeConstructor( &unitreal );
AddTypeConstructor( &unitpoint );
AddTypeConstructor( &cupointTC);
AddTypeConstructor( &cupointregionTC);
AddTypeConstructor( &movingbool );
AddTypeConstructor( &movingint );
AddTypeConstructor( &movingreal );
AddTypeConstructor( &movingpoint );
AddTypeConstructor( &cmpointTC);
AddTypeConstructor( &cmpointregionTC);
AddTypeConstructor( &cellgrid2d);
AddTypeConstructor( &cellgrid3d);
rangeint.AssociateKind( Kind::RANGE() );
rangeint.AssociateKind( Kind::DATA() );
rangereal.AssociateKind( Kind::RANGE() );
rangereal.AssociateKind( Kind::DATA() );
periods.AssociateKind( Kind::RANGE() );
periods.AssociateKind( Kind::DATA() );
intimebool.AssociateKind( Kind::TEMPORAL() );
intimebool.AssociateKind( Kind::DATA() );
intimeint.AssociateKind( Kind::TEMPORAL() );
intimeint.AssociateKind( Kind::DATA() );
intimereal.AssociateKind( Kind::TEMPORAL() );
intimereal.AssociateKind( Kind::DATA() );
intimepoint.AssociateKind( Kind::TEMPORAL() );
intimepoint.AssociateKind( Kind::DATA() );
intimecpoint.AssociateKind( Kind::TEMPORAL() );
intimecpoint.AssociateKind( Kind::DATA() );
unitbool.AssociateKind( Kind::TEMPORAL() );
unitbool.AssociateKind( Kind::DATA() );
unitint.AssociateKind( Kind::TEMPORAL() );
unitint.AssociateKind( Kind::DATA() );
unitreal.AssociateKind( Kind::TEMPORAL() );
unitreal.AssociateKind( Kind::DATA() );
unitpoint.AssociateKind( Kind::TEMPORAL() );
unitpoint.AssociateKind( Kind::DATA() );
unitpoint.AssociateKind( "SPATIAL3D" );
cupointTC.AssociateKind( Kind::TEMPORAL() );
cupointTC.AssociateKind( Kind::DATA() );
cupointTC.AssociateKind( "SPATIAL3D" );
cupointregionTC.AssociateKind( Kind::TEMPORAL() );
cupointregionTC.AssociateKind( Kind::DATA() );
cupointregionTC.AssociateKind( "SPATIAL3D" );
movingbool.AssociateKind( Kind::TEMPORAL() );
movingbool.AssociateKind( Kind::DATA() );
movingint.AssociateKind( Kind::TEMPORAL() );
movingint.AssociateKind( Kind::DATA() );
movingreal.AssociateKind( Kind::TEMPORAL() );
movingreal.AssociateKind( Kind::DATA() );
movingpoint.AssociateKind( Kind::TEMPORAL() );
movingpoint.AssociateKind( Kind::DATA() );
cmpointTC.AssociateKind(Kind::TEMPORAL());
cmpointTC.AssociateKind(Kind::DATA());
cmpointregionTC.AssociateKind( Kind::TEMPORAL() );
cmpointregionTC.AssociateKind( Kind::DATA() );
cmpointregionTC.AssociateKind( "SPATIAL3D" );
cellgrid2d.AssociateKind( Kind::DATA() );
cellgrid2d.AssociateKind( Kind::DELIVERABLE() );
cellgrid3d.AssociateKind( Kind::DATA() );
cellgrid3d.AssociateKind( Kind::DELIVERABLE() );
AddOperator( &temporalisempty );
AddOperator( &temporalequal );
AddOperator( &temporalnotequal );
AddOperator( &temporalequal2 );
AddOperator( &temporalnotequal2 );
AddOperator( &temporalless );
AddOperator( &temporallessequal );
AddOperator( &temporalgreater );
AddOperator( &temporalgreaterequal );
AddOperator( &temporalintersects );
AddOperator( &temporalinside );
AddOperator( &temporalbefore );
AddOperator( &temporalintersection );
AddOperator( &temporalunion );
AddOperator( &temporalminus );
AddOperator( &temporalmin );
AddOperator( &temporalmax );
AddOperator( &temporalnocomponents );
AddOperator( &temporalinst );
AddOperator( &temporalval );
AddOperator( &temporalatinstant );
AddOperator( &temporalatperiods );
AddOperator( &temporalwhen );
AddOperator( &temporaldeftime );
AddOperator( &temporaltrajectory );
AddOperator( &temporalpresent );
AddOperator( &temporalpasses );
AddOperator( &temporalinitial );
AddOperator( &temporalfinal );
AddOperator( &temporalunits );
AddOperator( &temporalgetunit );
AddOperator( &temporalgetposition );
AddOperator( &temporalbbox );
AddOperator( &temporalmbrange );
AddOperator( &temporalbbox2d );
AddOperator( &temporalbboxold);
AddOperator( &temporalat );
AddOperator( &temporaldistance );
AddOperator( &temporaldistanceavg );
AddOperator( &temporaldistanceavglb );
AddOperator( &temporaldistanceavgub );
AddOperator( &temporalsimplify );
AddOperator( &temporalintegrate );
AddOperator( &temporallinearize );
AddOperator( &temporallinearize2 );
AddOperator( &temporalapproximate );
AddOperator( &temporalminimum );
AddOperator( &temporalmaximum );
AddOperator( &temporalbreakpoints );
AddOperator( &breaks);
AddOperator( &temporalgk );
AddOperator( &temporalvertices );
AddOperator( &temporaltranslate );
AddOperator( &temporaltheyear );
AddOperator( &temporalthemonth );
AddOperator( &temporaltheday );
AddOperator( &temporalthehour );
AddOperator( &temporaltheminute );
AddOperator( &temporalthesecond );
AddOperator( &temporaltheperiod );
AddOperator( &temporaltherange );
AddOperator(&temporalbox3d);
AddOperator(&temporalbox2d);
AddOperator(&mbool2mint);
AddOperator(&mint2mbool);
AddOperator(&mint2mreal);
AddOperator(&extdeftime);
AddOperator(&temporaltranslateappend);
AddOperator(&temporaltranslateappendS);
AddOperator(&temporalreverse);
AddOperator(&temporalsamplempoint);
AddOperator(&temporalgps);
AddOperator(&temporaldisturb);
AddOperator(&temporallength);
AddOperator(&equalizeU);
AddOperator(&hat);
AddOperator(&restrict);
AddOperator(&speedup);
AddOperator(&avg_speed);
AddOperator(&submove);
AddOperator(&temporaluval);
AddOperator(&mp2onemp);
AddOperator(&p2mp);
AddOperator(&delayoperator);
AddOperator(&distancetraversedoperator);
AddOperator(&turns);
AddOperator(&mappingtimeshift);
AddOperator(&gridcellevents);
AddOperator(&temporalsquareddistance);
AddOperator(&getrefinementpartition);
AddOperator(&removeNoise);
AddOperator(&forcetoduration);
AddOperator(&createCellGrid2D);
AddOperator(&createCellGrid3D);
AddOperator(&atRect);
AddOperator(&moveTo);
AddOperator(&fillGaps);
AddOperator(&removeShort);
AddOperator(&getIntervals);
AddOperator(&components);
AddOperator(&trajectory3);
AddOperator(&createPeriodsOp);
AddOperator(&ct::containsOP);
AddOperator(&ct::replaceOp);
AddOperator(&ct::removeOp);
AddOperator(&ct::getGKZoneOp);
AddOperator(&constmpointOp);
AddOperator(&cbbox);
AddOperator(&getRadius);
AddOperator(&getRadii);
AddOperator(&getUPoint);
AddOperator(&getMPoint);
AddOperator(&mpoint2cmpoint);
AddOperator(&traversed);
#ifdef USE_PROGRESS
temporalunits.EnableProgress();
#endif
}
~TemporalAlgebra() {};
};
} // end of namespace temporalalgebra
/*
7 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*
InitializeTemporalAlgebra( NestedList* nlRef, QueryProcessor* qpRef )
{
nl = nlRef;
qp = qpRef;
return (new temporalalgebra::TemporalAlgebra());
}