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

10206 lines
249 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]
[1] Header file of the Temporal Algebra
January 2004 Victor Almeida
March - April 2004 Zhiming Ding
12.03.2005 Juergen Schmidt:
Adding ~Mapping<Unit, Alpha>::MergeAdd~ for merging two adjacent
units with the same values. This is for simplify the result of
operations. For this adding ~TemporalUnit::EqualValue~ to decide
the equality of values.
16.03.2006 Juergen Schmidt:
Added ~ConstTemporalUnit:EqualValue~
31.05.2006 Christian D[ue]ntgen:
Adding ~Range<Alpha>::RBBox~ for constructing the range consisting
of only one minimal interval, that contains all intervals from a range type
Sept 2006 Christian D[ue]ntgen implemented ~defined~ flag for unit types
[TOC]
Dec 2006 Christian D[ue]ntgen: Moved RefimentPartition from MovingRegionAlgebra
here and replaced the error-prone implementation in TemporalLiftedAlgbra by
this version.
29.09.2009 Mahmoud Sakr: Added the operators: delay, distancetraversed, and
mint2mbool
1 Overview
The type system of the Temporal Algebra can be seen below.
\begin{displaymath}
\begin{array}{lll}
& \to \textrm{BASE} & {\underline{\smash{\mathit{int}}}}, {\underline{\smash{\mathit{real}}}},
{\underline{\smash{\mathit{bool}}}}, {\underline{\smash{\mathit{string}}}} \\
& \to \textrm{SPATIAL} & {\underline{\smash{\mathit{point}}}}, {\underline{\smash{\mathit{points}}}},
{\underline{\smash{\mathit{line}}}}, {\underline{\smash{\mathit{region}}}} \\
& \to \textrm{TIME} & {\underline{\smash{\mathit{instant}}}} \\
\textrm{BASE} \cup \textrm{TIME} & \to \textrm{RANGE} & {\underline{\smash{\mathit{range}}}} \\
\textrm{BASE} \cup \textrm{SPATIAL} & \to \textrm{TEMPORAL} & {\underline{\smash{\mathit{intime}}}},
{\underline{\smash{\mathit{moving}}}}
\end{array}
\end{displaymath}
2 Defines, includes, and constants
*/
#ifndef _TEMPORAL_ALGEBRA_H_
#define _TEMPORAL_ALGEBRA_H_
#include <iostream>
#include <ostream>
#include <sstream>
#include <string>
#include "NestedList.h"
#include "QueryProcessor.h"
#include "Algebra.h"
#include "Attribute.h"
#include "StandardTypes.h"
#include "Algebras/Spatial/SpatialAlgebra.h"
#include "NestedList.h"
#include "../../Tools/Flob/DbArray.h"
#include "Progress.h"
#include "Algebras/Rectangle/CellGrid.h"
#include "Algebras/Rectangle/RectangleAlgebra.h"
#include "DateTime.h"
#include "AlmostEqual.h"
#include "Algebras/Geoid/Geoid.h"
#include "ListUtils.h"
#include "CharTransform.h"
extern NestedList* nl;
extern QueryProcessor* qp;
namespace temporalalgebra {
class SecInterval;
//#define REF_DEBUG(msg) cout << msg << std::endl;
#define REF_DEBUG(msg)
std::string int2string(const int& number);
double roundToNPlaces(const double value, const int noPlaces);
/*
3 C++ Classes (Defintion)
3.1 Instant
This class represents a time instant, or a point in time. It will be
used in the ~instant~ type constructor.
*/
// the following typedef has been moved to file DateTime.h:
// typedef DateTime Instant;
/*
3.2 Interval
The class ~Interval~ implements the closure of an $\alpha$-interval.
To be a generic class, this class uses templates with parameter ~Alpha~.
An interval contains a ~start~, an ~end~ and two flags ~lc~ and ~rc~
indicating if the interval is left-closed and right-closed
(or left-right-closed), respectively.
*/
template <class Alpha>
class Interval
{
public:
/*
3.2.1 Constructors
*/
Interval() {}
/*
The simple constructor. This constructor should not be used.
*/
explicit Interval(bool dummy):
start(datetime::instanttype), end(datetime::instanttype),
lc(true), rc(true){}
Interval( const Interval<Alpha>& interval );
/*
The copy constructor.
*/
Interval( const Alpha& start,
const Alpha& end,
const bool lc,
const bool rc );
/*
The creation of the interval setting all attributes.
3.2.2 Member functions
*/
const Interval<Instant>& getTimeInterval() const {
return *this;
}
void CopyFrom( const Interval<Alpha>& interval );
bool IsValid() const;
/*
Checks if the interval is valid or not. This function should be
used for debugging purposes
only. An interval is valid if the following conditions are true:
1 ~start~ and ~end~ are defined
2 ~start~ $<=$ ~end~
3 if ~start~ $==$ ~end~, then must ~lc~ $=$ ~rc~ $=$ ~true~
*/
Interval<Alpha>& operator=( const Interval<Alpha>& i );
/*
Redefinition of the copy operator ~=~.
*/
bool operator==( const Interval<Alpha>& i ) const;
/*
Returns ~true~ if this interval is equal to the interval ~i~ and
~false~ if they are different.
*/
bool operator!=( const Interval<Alpha>& i ) const;
/*
Returns ~true~ if this interval is different to the interval ~i~
and ~false~ if they are equal.
*/
bool operator<(const Interval<Alpha>& i) const;
bool operator>(const Interval<Alpha>& i) const;
/*
Returns always true, because it is not an attribute data type.
Required e.g., for RefinementStream for Periods values.
*/
bool IsDefined() const{
return true;
}
bool R_Disjoint( const Interval<Alpha>& i ) const;
/*
Returns ~true~ if this interval is r-disjoint with the interval
~i~ and ~false~ otherwise.
*/
bool Disjoint( const Interval<Alpha>& i ) const;
/*
Returns ~true~ if this interval is disjoint with the interval
~i~ and ~false~ otherwise.
*/
bool R_Adjacent( const Interval<Alpha>& i ) const;
/*
Returns ~true~ if this interval is r-adjacent with the interval
~i~ and ~false~ otherwise.
*/
bool Adjacent( const Interval<Alpha>& i ) const;
/*
Returns ~true~ if this interval is adjacent with the interval
~i~ and ~false~ otherwise.
*/
bool Inside( const Interval<Alpha>& i ) const;
/*
Returns ~true~ if this interval is inside the interval
~i~ and ~false~ otherwise.
*/
bool Contains( const Alpha& a,
const bool ignoreCloseness = false ) const;
/*
Returns ~true~ if this interval contains the value ~a~ and ~false~ otherwise.
If ignoreCloseness is set to be true, the return value will also be true, if
a is one of the borders of this interval regardless of the closeness at this
point.
*Precondition:* ~a.IsDefined()~
*/
bool Contains(const Interval<Alpha>& i,
const bool ignoreCloseness = false) const;
bool Intersects( const Interval<Alpha>& i ) const;
/*
Returns ~true~ if this interval intersects with the interval
~i~ and ~false~ otherwise.
*/
bool StartsBefore( const Interval<Alpha>& i ) const;
/*
Returns ~true~ iff this interval starts earlier than interval ~i~
*/
bool EndsAfter( const Interval<Alpha>& i ) const;
/*
Returns ~true~ iff this interval ends after interval ~i~
*/
bool Before( const Interval<Alpha>& i ) const;
/*
Returns ~true~ if this interval is before the interval ~i~
and ~false~ otherwise.
*/
bool Before( const Alpha& a ) const;
bool After( const Alpha& a ) const;
bool After( const Interval<Alpha>& iv ) const;
/*
Returns ~true~ if this interval is before/after the value ~a~
and ~false~ otherwise.
*/
void Intersection( const Interval<Alpha>& i, Interval<Alpha>& result ) const;
// for compatibility with moving types, we need an alias for intersection
void AtInterval( const Interval<Alpha>& i, Interval<Alpha>& result ) const{
Intersection(i,result);
}
void IntersectionWith( const Interval<Alpha>& i);
/*
Return the intersection of this interval and ~i~ into ~result~.
*/
void Union(const Interval<Alpha>& iv, Interval<Alpha> result) const;
/*
Constructs the mininum interval containing both, this interval and iv.
*/
void Union(const Interval<Alpha>& iv);
/*
Changes this interval to be the union of this is iv. gaps between the
intervals are included in the result.
*/
int Minus(const Interval<Alpha>& iv,
Interval<Alpha>& res1,
Interval<Alpha>& res2);
/*
Remove iv from this interval. The result(s) are stored in res1 and res2.
The number of results is returned.
*/
int CompareTo(const Interval<Alpha>& i) const;
/*
Compares this and the argument;
*/
std::ostream& Print(std::ostream& os) const{
os << (lc?"[":"(");
start.Print(os) << ", ";
end.Print(os) << (rc?"]":")");
return os;
}
/*
~SplitAround~
Divides this interval into several pieces around the given __value__.
If the value is not included in the interval, the result will only
consists of the original interval itself. If the __value__ is one of the
borders of the interval, the result will hav two entries. One entry consists
of an interval containing only __value__, the other entry is the remaining
interval. If __value__ is located inside the interval, the result will have
three entries.
*/
std::vector<Interval<Alpha> > splitAround(Alpha value) const{
std::vector<Interval<Alpha> > result;
if( (value<start) || (value > end) ){
result.push_back(*this);
return result;
}
if((value==start) && !lc){
result.push_back(*this);
return result;
}
if(value==start){ // lc == true
Interval<Alpha> i1(start,start,true,true);
result.push_back(i1);
if(end>start){ // there is a remaining interval
Interval<Alpha> i2(start,end,false,rc);
result.push_back(i2);
}
return result;
}
if(value==end && !rc){
result.push_back(*this);
return result;
}
if(value==end){
if(start<end){
Interval<Alpha> i1(start,end,lc,false);
result.push_back(i1);
}
Interval<Alpha> i2(end,end,true,true);
result.push_back(i2);
return result;
}
// value is located inside the interval
Interval<Alpha> i1(start,value,lc,false);
Interval<Alpha> i2(value,value,true,true);
Interval<Alpha> i3(value,end,false,rc);
result.push_back(i1);
result.push_back(i2);
result.push_back(i3);
return result;
}
/*
3.2.3 Attributes
*/
Alpha start;
/*
The starting value of the interval.
*/
Alpha end;
/*
The ending value of the interval.
*/
bool lc;
/*
A flag indicating that the interval is left-closed.
*/
bool rc;
/*
A flag indicating that the interval is right-closed.
*/
};
template<class alpha>
std::ostream& operator<<(std::ostream& o, const Interval<alpha>& u);
/*
3.3 Range
The ~Range~ class implements a set of disjoint, non-adjacent
$\alpha$-~intervals~. For this implementation, it is used a
database array of ordered intervals.
Since intervals may contain only defined start and end values, a Range cannot
contain undefined values.
*/
template <class Alpha>
class Range : public Attribute
{
public:
/*
3.3.1 Constructors and Destructor
*/
Range():Attribute() {}
/*
The simple constructor. This constructor should not be used.
*/
Range( const int n );
/*
The constructor. Initializes space for ~n~ elements.
*/
Range(const Range<Alpha>& src);
~Range();
/*
The destructor.
*/
void Destroy();
/*
This function should be called before the destructor if one wants to destroy the
persistent array of intervals. It marks the persistent array for destroying. The
destructor will perform the real destroying.
3.3.2 Functions for Bulk Load of Range
As said before, the point set is implemented as an ordered persistent
array of intervals.
The time complexity of an insertion operation in an ordered array
is $O(n)$, where ~n~ is the size of the interval set. In some cases, bulk load
of intervals for example, it is good to relax the ordered condition to improve
the performance. We have relaxed this ordered condition only for bulk load of
All other operations assume that the interval set is
ordered.
*/
bool IsOrdered() const;
/*
Returns if the interval set is ordered. There is a flag ~ordered~
(see attributes) in order to avoid a scan in the interval set to answer
this question.
*/
void StartBulkLoad();
/*
Marks the start of a bulk load of intervals relaxing the condition that the
intervals must be ordered. We will assume that the only way to add intervals
to an interval set is inside bulk
loads, i.e., into non-ordered ranges.
*/
bool EndBulkLoad( const bool sort = true, const bool checkvalid = false );
/*
Marks the end of a bulk load and sorts the interval set if the flag ~sort~ is set to true.
Checkvalid indicated, whether the validity (non-overlapping intervals) should
be checked. If the mapping is found to be invalid, it is marked undefined
3.3.3 Member functions
*/
bool IsEmpty() const;
/*
Returns true iff the range is undefined or empty of intervals.
*/
void Get( const int i, Interval<Alpha>& ai ) const;
/*
Returns the interval ~ai~ at the position ~i~ in the range.
*Precondition:* ~IsDefined() == true~
*/
void Add( const Interval<Alpha>& i );
/*
Adds an interval ~i~ to the range. We will assume that the only way of adding intervals
is in bulk loads, i.e., in a non-ordered array.
*Precondition:* ~IsOrdered() == false~
*Precondition:* ~IsDefined() == true~
*/
void Merge( Range<Alpha>& result ) const;
/*
Merges a range into ~result~ concatenating adjacent intervals.
*Precondition:* ~IsDefined() == true~
*/
void MergeAdd(const Interval<Alpha>& i);
/*
Adds an interval at the end of that Range. If the last interval and the i can be
merged, the last interval is extended by the new one.
*/
void Clear();
/*
Remove all intervals in the range.
3.3.4 Functions to be part of relations
*/
inline size_t Sizeof() const;
inline int Compare( const Attribute* arg ) const;
inline bool Adjacent( const Attribute* arg ) const;
inline Range<Alpha>* Clone() const;
inline std::ostream& Print( std::ostream &os ) const;
inline size_t HashValue() const;
inline void CopyFrom( const Attribute* right );
inline int NumOfFLOBs() const;
inline Flob *GetFLOB(const int i);
/*
3.3.5 Operations
3.3.5.1 Operation $=$ (~equal~)
Is true, iff both arguments are undefined or both are defined and contain the same intervals.
*Precondition:* ~X.IsOrdered() $\&\&$ Y.IsOrdered()~
*Semantics:* $X = Y$
*Complexity:* $O(n+m)$, where ~n~ is the size of this range ~X~ and m the size of the range ~Y~.
*/
bool operator==( const Range<Alpha>& r ) const;
/*
3.3.5.2 Operation $\neq$ (~not equal~)
*Precondition:* ~X.IsOrdered() $\&\&$ Y.IsOrdered()~
*Semantics:* $X \neq Y$
*Complexity:* $O(n+m)$, where ~n~ is the size of this range ~X~ and m the size of the range ~Y~.
*/
bool operator!=( const Range<Alpha>& r ) const;
/*
3.3.5.3 Operation ~intersects~
*Precondition:* ~IsDefined() == true~
*Precondition:* ~r.IsDefined() == true~
*Precondition:* ~X.IsOrdered() $\&\&$ Y.IsOrdered()~
*Semantics:* $X \cap Y \neq \emptyset$
*Complexity:* $O(n+m)$, where ~n~ is the size of this range ~X~ and m the size of the range ~Y~.
*/
bool Intersects( const Range<Alpha>& r ) const;
bool Intersects( const Interval<Alpha>& iv ) const;
/*
3.3.5.4 Operation ~inside~
*Precondition:* ~IsDefined() == true~
*Precondition:* ~r.IsDefined() == true~
*Precondition:* ~X.IsOrdered() $\&\&$ Y.IsOrdered()~
*Semantics:* $X \subseteq Y$
*Complexity:* $O(n+m)$, where ~n~ is the size of this range ~X~ and m the size of the range ~Y~.
*/
bool Inside( const Range<Alpha>& r ) const;
bool Inside( const Interval<Alpha>& iv ) const;
/*
3.3.5.4 Operation ~GetIndexOf~
This function returns the index of the interval within this periods value containing
the given Alpha. If the parameter ignoreCloseness is set to be true, the index of
the interval is also returned, iff alpha is a border of the interval regardless
of the closeness of the interval. If no interval exist containing alpha, -1 is returned.
*/
int GetIndexOf(const Alpha& alpha,const bool ignoreCloseness = false) const;
/*
3.3.5.5 Operation ~contains~
*Precondition:* ~IsDefined() == true~
*Precondition:* ~a.IsDefined() == true~
*Precondition:* ~X.IsOrdered() $\&\&$ y.IsDefined()~
*Semantics:* $y \in X$
*Complexity:* $O(log(n))$, where ~n~ is the size of this range ~X~.
*/
bool Contains( const Alpha& a ) const;
bool Contains( const Interval<Alpha>& iv,
const bool ignoreCloseness = false ) const;
/*
3.3.5.6 Operation ~before~ (with ~range~)
*Precondition:* ~IsDefined() == true~
*Precondition:* ~r.IsDefined() == true~
*Precondition:* ~X.IsOrdered() $\&\&$ Y.IsOrdered()~
*Semantics:* $\forall x \in X, \forall y \in Y: x \leq y$
*Complexity:* $O(1)$.
*/
bool Before( const Range<Alpha>& r ) const;
bool Before( const Interval<Alpha>& iv ) const;
/*
3.3.5.7 Operation ~before~ (with ~BASE~ type)
*Precondition:* ~IsDefined() == true~
*Precondition:* ~a.IsDefined() == true~
*Precondition:* ~X.IsOrdered() $\&\&$ y.IsDefined()~
*Semantics:* $\forall x \in X: x \leq y$
*Complexity:* $O(1)$.
*/
bool Before( const Alpha& a ) const;
/*
3.3.5.8 Operation ~after~
This operation works only with ~BASE~ type, because it is an attempt to implement the operation
before on a contrary order, i.e., ~x before Y~.
*Precondition:* ~IsDefined() == true~
*Precondition:* ~a.IsDefined() == true~
*Precondition:* ~Y.IsOrdered() $\&\&$ x.IsDefined()~
*Semantics:* $\forall y \in Y: x \leq y$
*Complexity:* $O(1)$.
*/
bool After( const Alpha& a ) const;
/*
3.3.5.9 Operation ~intersection~
*Precondition:* ~X.IsOrdered() $\&\&$ X.IsOrdered() $\&\&$ Result.IsEmpty()~
*Semantics:* $X \cap Y$
*Complexity:* $O(n+m)$, where ~n~ is the size of this range ~X~ and m the size of the range ~Y~.
*/
void Intersection( const Range<Alpha>& r, Range<Alpha>& result ) const;
void Intersection(const Interval<Alpha>& r, Range<Alpha>& result) const;
/*
3.3.5.10 Operation ~union~
*Precondition:* ~X.IsOrdered() $\&\&$ Y.IsOrdered() $\&\&$ Result.IsEmpty()~
*Semantics:* $X \cup Y$
*Complexity:* $O(n+m)$, where ~n~ is the size of this range ~X~ and m the size of the range ~Y~.
*/
void Union( const Range<Alpha>& r, Range<Alpha>& result ) const;
void Union( const Interval<Alpha>& iv, Range<Alpha>& result ) const;
/*
3.3.5.11 Operation ~minus~
*Precondition:* ~X.IsOrdered() $\&\&$ Y.IsOrdered() $\&\&$ Result.IsEmpty()~
*Semantics:* $X \backslash Y$
*Complexity:* $O(n+m)$, where ~n~ is the size of this range ~X~ and m the size of the range ~Y~.
Note, it's not allowed to use ([*]this) as the result of this operation. This will result in
an empty result. To do so, please use the variant without result parameter.
*/
void Minus( const Range<Alpha>& r, Range<Alpha>& result ) const;
void Minus( const Interval<Alpha>& r, Range<Alpha>& result ) const;
/*
Changes this Range value to contain the current intervals without the given ones.
*/
void Minus(const Range<Alpha>& r);
void Minus( const Interval<Alpha>& r);
/*
3.3.5.12 Operation ~max~
*Precondition:* ~X.IsOrdered()~
*Semantics:* $max(\rho(X))$
*Complexity:* $O(1)$
*/
void Maximum( Alpha& result ) const;
/*
3.3.5.13 Operation ~min~
*Precondition:* ~X.IsOrdered()~
*Semantics:* $min(\rho(X))$
*Complexity:* $O(1)$
*/
void Minimum( Alpha& result ) const;
/*
3.3.5.14 Operation ~no\_components~
*Precondition:* ~IsDefined() == true~
*Precondition:* ~X.IsOrdered()~
*Semantics:* $\| intvls(X) \|$
*Complexity:* $O(1)$
*/
int GetNoComponents() const;
/*
3.3.5.15 Function ~compress~
Creates a compressed version of this range.
*/
Range<Alpha>* compress() const;
/*
3.3.5.16 Operation ~bbox~ for ~range~-types
*Precondition:* ~X.IsOrdered() $\&\&$ Result.IsEmpty()~
*Semantics:* The range with the smallest interval, that contains all intervals within $X$.
*Complexity:* $O(1)$
*/
void RBBox( Range<Alpha>& result ) const;
bool IsValid() const;
/*
This functions tests if a ~range~ is in a valid format. It is used for debugging
purposes only. The ~range~ is valid, iff the range is either undefined, or it
is defined and all the following conditions are true:
1 Each interval is valid
2 Start of each interval $>=$ end of the interval before
3 If start of an interval = end of the interval before, then one needs to
make sure that the interval is not left-closed or the interval before
is not right-closed
*/
inline static const std::string BasicType()
{
if(Alpha::BasicType()==datetime::DateTime::BasicType()){
return "periods";
} else {
return "r"+Alpha::BasicType();
}
}
static const bool checkType(const ListExpr type){
return listutils::isSymbol(type, BasicType());
}
/*
3.3.7 Attributes
*/
private:
bool canDestroy;
/*
A flag indicating if the destructor should destroy also the persistent
array of intervals.
*/
bool ordered;
/*
A flag indicating whether the interval set is ordered or not.
*/
DbArray< Interval<Alpha> > intervals;
/*
The intervals database array.
*/
};
/*
3.4 Intime
This class implements the ~intime~ type constructor, which converts a given type
$\alpha$ into a type that associates instants of time with values of $\alpha$.
A defined Intime object may not contain an undefined instant, but an undefined
value.
3.4.1 Constructors
*/
template <class Alpha>
class Intime: public Attribute
{
public:
Intime() {}
/*
The simple constructor.
*/
Intime(const int i):Attribute(false),instant((int64_t)i),value(false){}
Intime( const Instant& _instant, const Alpha& alpha ):
Attribute(true), instant( _instant ), value(alpha)
{
//value.CopyFrom( &alpha );
SetDefined( instant.IsDefined());
}
/*
The first constructor.
*/
Intime( const Intime<Alpha>& intime ):
Attribute(intime),
instant( intime.instant ), value(intime.value)
{
if( intime.IsDefined() ){
//value.CopyFrom( &intime.value );
this->del.isDefined=true;
} else {
this->del.isDefined = false;
}
}
/*
The second constructor.
3.4.2 Functions to be part of relations
*/
inline int NumOfFLOBs() const {return value.NumOfFLOBs();}
inline Flob *GetFLOB(const int i) {return value.GetFLOB(i);}
size_t Sizeof() const
{
return sizeof( *this );
}
int Compare( const Attribute* arg ) const
{
// return 0; // Original implementation
Intime<Alpha>* other = (Intime<Alpha>*) arg;
if (!IsDefined() && !other->IsDefined())
return 0;
if (!IsDefined())
return -1;
if (!other->IsDefined())
return 1;
int cmp = instant.Compare( &(other->instant) );
if(cmp)
return cmp;
return value.Compare( &(other->value) );
}
bool Adjacent( const Attribute* arg ) const
{
return false;
}
Intime<Alpha>* Clone() const
{
return (new Intime<Alpha>( *this));
}
std::ostream& Print( std::ostream &os ) const
{
os << Intime<Alpha>::BasicType() << ": (";
if ( IsDefined() )
{
instant.Print(os);
os << ", ";
value.Print(os);
}
else
{
os << " undefined";
}
os << " ) ";
return os;
}
size_t HashValue() const
{
if(!IsDefined()){
return 0;
}
return static_cast<size_t>( instant.HashValue()
^ value.HashValue() ) ;
}
void CopyFrom( const Attribute* right )
{
const Intime<Alpha>* i = (const Intime<Alpha>*)right;
this->SetDefined(i->IsDefined());
if( IsDefined() )
{
instant.Equalize(&(i->instant));
value.CopyFrom( &i->value );
}
}
bool operator==(const Intime<Alpha>& other) const
{
return (Compare((Attribute*) (&other) ) == 0);
}
bool operator!=(const Intime<Alpha>& other) const
{
return (Compare((Attribute*) (&other) ) != 0);
}
// type name used in Secondo:
inline static const std::string BasicType()
{
return "i"+Alpha::BasicType();
}
static const bool checkType(const ListExpr type){
return listutils::isSymbol(type, BasicType());
}
void Clear() {}
/*
3.4.3 Attributes:
*/
Instant instant;
/*
The time instant associated.
*/
Alpha value;
/*
The $\alpha$ value.
*/
};
typedef Intime<CcBool> IBool;
typedef Intime<CcInt> IInt;
typedef Intime<CcReal> IReal;
typedef Intime<CcString> IString;
typedef Intime<Point> IPoint;
typedef Intime<CPoint> CIPoint;
/*
3.5 TemporalUnit
This class will generically implements a temporal unit. It is an abstract class
that enforces each kind of temporal unit to have a function that computes a value
inside the temporal unit given a time instant (also inside the temporal unit).
The TemporalUnit does not yet contain a ~defined~ flag!
*/
template <class Alpha>
class TemporalUnit
{
public:
/*
3.5.1 Constructors and Destructor
*/
TemporalUnit() {}
/*
The simple constructor. This constructor should not be used.
*/
TemporalUnit(bool defined): timeInterval(defined) {}
/*
Use this constructor when declaring temporal object variables etc.
*/
TemporalUnit( const Interval<Instant>& interval ):
timeInterval( interval )
{ }
/*
This constructor sets the time interval of the temporal unit.
*/
virtual ~TemporalUnit() {}
/*
The destructor.
3.5.2 Member Functions
*/
bool IsValid() const;
/*
Checks if the Temporal Unit is valid or not. This function should be used for debugging purposes
only. A TemoralUnit is valid if its timeInterval is valid.
*/
virtual TemporalUnit<Alpha>& operator=( const TemporalUnit<Alpha>& i );
/*
Redefinition of the copy operator ~=~.
*/
virtual bool operator==( const TemporalUnit<Alpha>& i ) const;
/*
Returns ~true~ if this temporal unit is equal to the temporal unit ~i~ and ~false~ if they are different.
*/
virtual bool operator!=( const TemporalUnit<Alpha>& i ) const;
/*
Returns ~true~ if this temporal unit is different to the temporal unit ~i~ and ~false~ if they are equal.
*/
bool R_Disjoint( const TemporalUnit<Alpha>& i ) const;
/*
Returns ~true~ if this temporal unit is r-disjoint with the temporal unit ~i~ and ~false~ otherwise.
*/
bool Disjoint( const TemporalUnit<Alpha>& i ) const;
/*
Returns ~true~ if this temporal unit is disjoint with the temporal unit ~i~ and ~false~ otherwise.
*/
bool R_Adjacent( const TemporalUnit<Alpha>& i ) const;
/*
Returns ~true~ if this temporal unit is r-adjacent with the temporal unit ~i~ and ~false~ otherwise.
*/
bool TU_Adjacent( const TemporalUnit<Alpha>& i ) const;
// VTA - It should be Adjacent but it does not compile.
/*
Returns ~true~ if this temporal unit is adjacent with the temporal unit ~i~ and ~false~ otherwise.
*/
bool Inside( const TemporalUnit<Alpha>& i ) const;
/*
Returns ~true~ if this temporal unit is inside the temporal unit ~i~ and ~false~ otherwise.
*/
bool Contains( const Instant& a ) const;
/*
Returns ~true~ if this temporal unit contains the value ~a~ and ~false~ otherwise.
*Precondition:* ~a.IsDefined()~
*/
bool Intersects( const TemporalUnit<Alpha>& i ) const;
/*
Returns ~true~ if this temporal unit intersects with the temporal unit ~i~ and ~false~ otherwise.
*/
bool StartsBefore( const TemporalUnit<Alpha>& i ) const;
/*
Returns ~true~ if this temporal unit starts before the temporal unit ~i~ and ~false~ otherwise.
*/
bool EndsAfter( const TemporalUnit<Alpha>& i ) const;
/*
Returns ~true~ if this temporal unit ends after the temporal unit ~i~ and ~false~ otherwise.
*/
bool Before( const TemporalUnit<Alpha>& i ) const;
/*
Returns ~true~ if this temporal unit is before the temporal unit ~i~ and ~false~ otherwise.
*/
bool Before( const Instant& a ) const;
bool After( const Instant& a ) const;
/*
Returns ~true~ if this temporal unit is before/after the value ~a~ and ~false~ otherwise.
*/
inline bool IsInstantUnit() const {
assert(IsValid());
return( timeInterval.lc
&& timeInterval.rc
&& (timeInterval.start == timeInterval.end) );
}
/*
Returns ~true~ iff this unit's timeInterval is a single instant.
*/
virtual void TemporalFunction( const Instant& t,
Alpha& result,
bool ignoreLimits = false ) const = 0;
/*
The temporal function that receives a time instant ~t~ and returns the value
associated with time ~t~ in the output argument ~result~.
If ~ignoreLimits = true~, the limits given by the ~timeinterval~ will be ignored.
You can use this feature e.g. to calculate values for the ~initial~ and ~final~
instants of left/right open intervals.
Otherwise (~ignoreLimits = false~, resp. unspecified) there will be following
*Precondition:* t must be inside the temporal unit time interval.
*/
virtual bool Passes( const Alpha& val ) const = 0;
/*
Checks if inside the unit the function passes by the value ~val~.
*Precondition:* IsDefined() == true AND val.IsDefined() == true
*/
virtual bool At( const Alpha& val, TemporalUnit<Alpha>& result ) const = 0;
/*
Returns a unit restricted to the parts where the temporal function is equal
to ~val~.
*/
virtual void AtInterval( const Interval<Instant>& i,
TemporalUnit<Alpha>& result ) const
{
timeInterval.Intersection( i, result.timeInterval );
}
/*
Returns a unit restricted to the time interval ~i~.
This can be used to create sub-units for refinement partitions.
*/
virtual bool EqualValue( const TemporalUnit<Alpha>& i ) const
{
return false;
}
/*
Returns ~true~ if the value of this temporal unit is equal to the
value of the temporal unit ~i~ and ~false~ if they are different.
Equality is computed with respect to temporal evolution.
*/
virtual bool Merge( const TemporalUnit<Alpha>& i )
{
return false;
}
/*
Type name used in Secondo
*/
inline static const std::string BasicType()
{
return "u"+Alpha::BasicType();
}
static const bool checkType(const ListExpr type){
return listutils::isSymbol(type, BasicType());
}
/*
Tries to merge the other unit into this unit. Returns ~true~ iff this was
successful (and this unit was modified).
If the units cannot be merged, the result is ~false~ and this unit remains
unchanged.
Merge might work, if the definition time is disjunct or overlapping, but does
not have a temporal gap.
It will fail, if the temporal functions cannot be unified with each other, or
if the unified function is not representable as a single unit.
*/
/*
3.5.3 Attributes
*/
inline const Interval<Instant>& getTimeInterval() const{
return timeInterval;
}
Interval<Instant> timeInterval;
/*
The time interval of the temporal unit.
*/
};
/*
3.6 StandardTemporalUnit
This class inherits from ~Attribute~ and allows temporal units
of standard types to be part of relations. One should note that it is
still an abstract class, because the functions ~CopyFrom~ and ~Clone~
are not implemented.
This class contains a defined flag.
*/
template<class Alpha>
class StandardTemporalUnit :
public Attribute,
public TemporalUnit<Alpha>
{
public:
StandardTemporalUnit() {}
/*
The simple constructor. This constructor should not be used.
*/
StandardTemporalUnit( bool is_defined):Attribute(is_defined),
TemporalUnit<Alpha>(is_defined)
{}
/*
Use this constructor when declaring temporal object variables etc.
*/
StandardTemporalUnit( const Interval<Instant>& interval ):
Attribute(true),
TemporalUnit<Alpha>( interval )
{
del.refs=1;
del.SetDelete();
del.isDefined=true;
}
/*
This constructor sets the time interval of the temporal unit.
*/
virtual ~StandardTemporalUnit() {}
/*
The destructor.
3.5.2 Member Functions
3.6.4.1 Functions to be part of relations
*/
virtual int Compare( const Attribute* arg ) const
{
return 0;
}
virtual bool Adjacent( const Attribute* arg ) const
{
return false;
}
virtual std::ostream& Print( std::ostream &os ) const
{
if( IsDefined() )
{
os << StandardTemporalUnit<Alpha>::BasicType() << ": ( ";
TemporalUnit<Alpha>::timeInterval.Print(os);
os << ", NO SPECIFIC Print()-Method for this StandardTemporalUnit! )";
return os;
}
else
return os << StandardTemporalUnit<Alpha>::BasicType() <<": (undef) ";
}
virtual size_t HashValue() const
{
if(!IsDefined()){
return 0;
}
return static_cast<size_t>( this->timeInterval.start.HashValue()
^ this->timeInterval.end.HashValue() ) ;
}
virtual StandardTemporalUnit<Alpha>* Clone() const = 0;
virtual void CopyFrom( const Attribute* right ) = 0;
virtual size_t Sizeof() const = 0;
inline static const std::string BasicType()
{
return "u"+Alpha::BasicType();
}
static const bool checkType(const ListExpr type){
return listutils::isSymbol(type, BasicType());
}
};
/*
The output operator:
*/
template<class Alpha>
std::ostream& operator<<(std::ostream& o, const StandardTemporalUnit<Alpha>& u)
{
return u.Print(o);
}
/*
3.7 SpatialTemporalUnit
This class inherits from ~SpatialAttribute~ and allows temporal units
of spatial types to be part of relations. This class is a template also on the
dimensionality. One should note that it is still an abstract class, because
the functions ~CopyFrom~ and ~Clone~
are not implemented.
This class contains a defined flag!
*/
template <class Alpha, unsigned dim>
class SpatialTemporalUnit :
public StandardSpatialAttribute<dim>,
public TemporalUnit<Alpha>
{
public:
SpatialTemporalUnit() {}
/*
The simple constructor. This constructor should not be used.
*/
SpatialTemporalUnit( bool is_defined )
:StandardSpatialAttribute<dim>(is_defined){
this->del.isDefined=is_defined;
}
/*
Use this constructor when declaring temporal object variables etc.
*/
SpatialTemporalUnit( const Interval<Instant>& interval ):
StandardSpatialAttribute<dim>(true),
TemporalUnit<Alpha>( interval )
{
this->del.isDefined = true;
}
/*
This constructor sets the time interval of the temporal unit.
*/
virtual ~SpatialTemporalUnit() {}
/*
The destructor.
3.5.2 Member Functions
3.6.4.1 Functions to be part of relations
*/
virtual int Compare( const Attribute* arg ) const
{
return 0;
}
virtual bool Adjacent( const Attribute* arg ) const
{
return false;
}
virtual std::ostream& Print( std::ostream &os ) const
{
if( this->del.isDefined )
{
os << SpatialTemporalUnit<Alpha,dim>::BasicType() << ": " << "( ";
TemporalUnit<Alpha>::timeInterval.Print(os);
os << ", ";
// print specific stuff:
os << " NO SPECIFIC Print()-Method for this SpatioTemporalUnit! ) ";
return os;
}
else
return os << SpatialTemporalUnit<Alpha,dim>::BasicType() <<": (undef) ";
}
virtual size_t HashValue() const
{
if(!this->IsDefined()){
return 0;
}
return static_cast<size_t>( this->timeInterval.start.HashValue()
^ this->timeInterval.end.HashValue() ) ;
}
virtual SpatialTemporalUnit<Alpha, dim>* Clone() const = 0;
virtual void CopyFrom( const Attribute* right ) = 0;
virtual size_t Sizeof() const = 0;
virtual const Rectangle<dim> BoundingBox(const Geoid* geoid = 0) const = 0;
static unsigned GetDim(){ return dim; }
inline static const std::string BasicType()
{
return "u"+Alpha::BasicType();
}
static const bool checkType(const ListExpr type){
return listutils::isSymbol(type, BasicType());
}
bool Intersects(const Rectangle<dim>& rect, const Geoid* geoid=0) const{
assert(false); // not implemented yet
return false;
}
};
/*
The output operator
*/
template<class Alpha, unsigned dim>
std::ostream& operator<<(std::ostream& o,
const SpatialTemporalUnit<Alpha, dim>& u)
{
return u.Print(o);
}
/*
3.6 Class ~RInt~
*/
typedef Range<CcInt> RInt;
/*
3.6 Class ~RReal~
*/
typedef Range<CcReal> RReal;
/*
3.6 Class ~RBool~
*/
typedef Range<CcBool> RBool;
/*
3.6 Class ~RString~
*/
typedef Range<CcString> RString;
/*
3.6 Class ~Periods~
*/
class Periods : public Range<Instant> {
public:
typedef Interval<Instant> unittype;
/*
Constructors
*/
Periods() {}
/*
The constructor. Initializes space for ~n~ elements.
*/
Periods(const int n) : Range<Instant>(n) {};
Periods(const Periods& src) : Range<Instant>(src) {};
/*
The ~contains~ functions
*/
const bool Contains(const SecInterval& si) const;
const bool Contains(const Periods& per) const;
inline bool Contains(const Instant& a) const{
return Range<Instant>::Contains(a);
}
inline bool Contains(const Interval<Instant>& iv,
const bool ignoreCloseness = false ) const {
return Range<Instant>::Contains(iv,ignoreCloseness);
}
};
/*
3.6 ConstTemporalUnit
This class will be used in the ~const~ type constructor. It constructs constant
temporal units, i.e. it has a constant value and the temporal function always
return this value. The explicit purpose of the ~const~ type constructor is to
define temporal units for ~int~, ~string~, and ~bool~, i.e., for types where
their values change only in discrete steps.
This class inherits a defined flag!
*/
template <class Alpha>
class ConstTemporalUnit : public StandardTemporalUnit<Alpha>
{
public:
/*
3.6.1 Constructors, Destructor
*/
ConstTemporalUnit() {}
ConstTemporalUnit(bool is_defined):StandardTemporalUnit<Alpha>(is_defined),
constValue(is_defined)
{ }
ConstTemporalUnit( const Interval<Instant>& _interval, const Alpha& a ):
StandardTemporalUnit<Alpha>( _interval ), constValue(a)
{
this->del.isDefined = true;
}
// the following constructor is for implementation compatibility with
// UnitTypes for continious value range types (like UReal, UPoint)
ConstTemporalUnit( const Interval<Instant>& _interval, const Alpha& a,
const Alpha& b ):
StandardTemporalUnit<Alpha>( _interval ), constValue(a)
{
assert(a == b);
this->del.isDefined = true;
}
ConstTemporalUnit( const ConstTemporalUnit<Alpha>& u ):
StandardTemporalUnit<Alpha>( u.timeInterval ), constValue(u.constValue)
{
this->del.isDefined = u.del.isDefined;
}
/*
3.6.2 Operator redefinitions
*/
virtual ConstTemporalUnit<Alpha>&
operator=( const ConstTemporalUnit<Alpha>& i )
{
this->del.isDefined = i.del.isDefined;
if( !i.IsDefined() ){
return *this;
}
*((TemporalUnit<Alpha>*)this) = *((TemporalUnit<Alpha>*)&i);
constValue.CopyFrom( &i.constValue );
return *this;
}
/*
Redefinition of the copy operator ~=~.
Two ConstTemporalUnits are equal, if both are either undefined, or both are
defined and represent the same temporal function
*/
virtual bool operator==( const ConstTemporalUnit<Alpha>& i ) const
{
if( !this->IsDefined() && !i.IsDefined() ){
return true;
}
return (this->IsDefined()) && (i.IsDefined())
&& *((TemporalUnit<Alpha>*)this) == *((TemporalUnit<Alpha>*)&i)
&& constValue.Compare( &i.constValue ) == 0;
}
/*
Returns ~true~ if this temporal unit is equal to the temporal unit ~i~ and ~false~ if they are different.
*/
virtual bool operator!=( const ConstTemporalUnit<Alpha>& i ) const
{
return !( *this == i );
}
/*
Returns ~true~ if this temporal unit is different to the temporal unit ~i~ and ~false~ if they are equal.
*/
/*
3.6.2 The Temporal Functions
~TemporalFunction~ returns an undefined result if the ConstUnit or the Instant
is undefined, or the Instant is not within the unit's timeInterval.
*/
virtual void TemporalFunction( const Instant& t,
Alpha& result,
bool ignoreLimits = false ) const
{
if ( !this->IsDefined() ||
!t.IsDefined() ||
(!this->timeInterval.Contains( t ) && !ignoreLimits))
{
result.SetDefined( false );
}
else
{
result.CopyFrom( &constValue );
result.SetDefined( true );
}
}
virtual bool Passes( const Alpha& val ) const
{
if( this->IsDefined() && (constValue.Compare( &val ) == 0) )
return true;
return false;
}
virtual bool At( const Alpha& val, TemporalUnit<Alpha>& result ) const
{
if( this->IsDefined() && (constValue.Compare( &val ) == 0) )
{
((ConstTemporalUnit<Alpha>*)&result)->CopyFrom( this );
return true;
}
((ConstTemporalUnit<Alpha>*)&result)->SetDefined( false );
return false;
}
virtual void AtInterval( const Interval<Instant>& i,
TemporalUnit<Alpha>& result ) const
{
if( !this->IsDefined() || !this->timeInterval.Intersects( i ) ){
((ConstTemporalUnit<Alpha>*)&result)->SetDefined( false );
} else {
TemporalUnit<Alpha>::AtInterval( i, result );
((ConstTemporalUnit<Alpha>*)&result)->constValue.CopyFrom( &constValue );
}
}
virtual bool EqualValue( const TemporalUnit<Alpha>& i) const{
return EqualValue( *((const ConstTemporalUnit*)&i));
}
virtual bool EqualValue( const ConstTemporalUnit<Alpha>& i ) const
{
return this->IsDefined() && (constValue.Compare( &i.constValue ) == 0);
}
/*
Returns ~true~ if the value of this temporal unit is defined and equal to the
value of the temporal unit ~i~ and ~false~ if they are different.
*/
virtual bool Merge( const TemporalUnit<Alpha>& i){
return Merge( *((const ConstTemporalUnit<Alpha>*)&i));
}
virtual bool Merge( const ConstTemporalUnit<Alpha>& i ) {
if(!this->IsDefined() && !i.IsDefined()) { // mergeable, but nothing to do
return true;
} else if(!this->IsDefined() || !i.IsDefined()) { // not mergable
return false;
} else if( !this->timeInterval.Adjacent(i.timeInterval)
&& !this->timeInterval.Intersects(i.timeInterval) ){
return false; // have a gap in between --> not mergeable
} else if(!this->EqualValue(i)) { // temporal functions are NOT equal
return false;
}
// merge the units (i.e. their timeIntervals)
ConstTemporalUnit<Alpha> res(false);
if(this->StartsBefore(i)){
res.timeInterval.start = this->timeInterval.start;
res.timeInterval.lc = this->timeInterval.lc;
} else {
res.timeInterval.start = i.timeInterval.start;
res.timeInterval.lc = i.timeInterval.lc;
}
if(this->EndsAfter(i)){
res.timeInterval.end = this->timeInterval.end;
res.timeInterval.rc = this->timeInterval.rc;
} else {
res.timeInterval.end = i.timeInterval.end;
res.timeInterval.rc = i.timeInterval.rc;
}
res.constValue = this->constValue;
if(res.IsDefined() && res.IsValid()){ // invalid result -- do nothing!
*this = res;
return true;
} else {
return false;
}
}
/*
Merges unit ~i~ into this unit if possible and return ~true~. Otherwise do
not modify this unit and return ~false~.
*/
/*
3.6.3 Functions to be part of relations
*/
inline int NumOfFLOBs() const {return constValue.NumOfFLOBs();}
inline Flob *GetFLOB(const int i) {return constValue.GetFLOB(i);}
virtual size_t Sizeof() const
{
return sizeof( *this );
}
virtual int Compare( const Attribute* arg ) const
{
ConstTemporalUnit<Alpha>* ctu = (ConstTemporalUnit<Alpha>*)arg;
// SPM: this pointer added since my windows gcc (v3.4.2) reports:
// 'timeInterval' undeclared (first use this function) which
// seems to be a compiler bug!
if (this->IsDefined() && !ctu->IsDefined())
return 0;
if (!this->IsDefined())
return -1;
if (!ctu->IsDefined())
return 1;
int cmp = this->timeInterval.CompareTo(ctu->timeInterval);
if(cmp){
return cmp;
}
return constValue.Compare(&(ctu->constValue));
}
virtual bool Adjacent( const Attribute* arg ) const
{
return false;
}
virtual std::ostream& Print( std::ostream &os ) const
{
if( this->IsDefined() )
{
os << ConstTemporalUnit<Alpha>::BasicType() << ": ( ";
TemporalUnit<Alpha>::timeInterval.Print(os);
os << ", ";
constValue.Print(os);
os << " ) " << std::endl;
return os;
}
else
return os << ConstTemporalUnit<Alpha>::BasicType()<<": (undef) ";
}
virtual size_t HashValue() const
{
if(!this->IsDefined()){
return 0;
}
return static_cast<size_t>( this->timeInterval.start.HashValue()
^ this->timeInterval.end.HashValue() ) ;
}
virtual ConstTemporalUnit<Alpha>* Clone() const
{
return new ConstTemporalUnit<Alpha>(*this);
}
virtual void CopyFrom( const Attribute* right )
{
const ConstTemporalUnit<Alpha>* i = (const ConstTemporalUnit<Alpha>*)right;
this->SetDefined(i->IsDefined());
this->timeInterval.CopyFrom( i->timeInterval );
constValue.CopyFrom( &(i->constValue) );
}
// type name used in Secondo
inline static const std::string BasicType()
{
return "u"+Alpha::BasicType();
}
static const bool checkType(const ListExpr type){
return listutils::isSymbol(type, BasicType());
}
/*
3.6.4 Attributes
*/
Alpha constValue;
/*
The constant value of the temporal unit.
*/
};
/*
3.7 Class ~UBool~
*/
typedef ConstTemporalUnit<CcBool> UBool;
/*
3.7 Class ~UInt~
*/
typedef ConstTemporalUnit<CcInt> UInt;
/*
3.7 UReal
This class will be used in the ~ureal~ type constructor, i.e., the type constructor
for the temporal unit of real numbers.
Inherits a denined flag.
*/
class UPoint; // forward declaration
class UReal : public StandardTemporalUnit<CcReal>
{
public:
/*
3.7.1 Constructors and Destructor
*/
UReal() {};
UReal(bool is_defined):StandardTemporalUnit<CcReal>(is_defined),
a(0.0), b(0.0), c(0.0), r(false)
{ };
UReal( const Interval<Instant>& _interval,
const double a,
const double b,
const double c,
const bool r ):
StandardTemporalUnit<CcReal>( _interval ),
a( a ), b( b ), c( c ),
r( r )
{
del.refs=1;
del.SetDelete();
del.isDefined=true;
}
// linear approximation between v1 and v2
UReal(const Interval<Instant>& _interval,
const double v1,
const double v2): StandardTemporalUnit<CcReal>(_interval){
Instant diff = _interval.end - _interval.start;
a = 0;
r = false;
c = v1;
if(diff.IsZero()){
b = 0;
return;
}
b = (v2-v1) / diff.ToDouble();
del.refs=1;
del.SetDelete();
del.isDefined = true;
}
// linear approximation between v1 and v2
UReal(const Interval<Instant>& _interval,
const CcReal& ccv1,
const CcReal& ccv2): StandardTemporalUnit<CcReal>(_interval){
if(!ccv1.IsDefined() || !ccv2.IsDefined()){
SetDefined(false);
return;
}
double v1 = ccv1.GetValue();
double v2 = ccv2.GetValue();
Instant diff = _interval.end - _interval.start;
a = 0;
r = false;
c = v1;
if(diff.IsZero()){
b = 0;
return;
}
b = (v2-v1) / diff.ToDouble();
del.refs=1;
del.SetDelete();
del.isDefined = true;
}
void Normalize(){
if(!IsDefined()){
return;
}
if(!r){
return;
}
if(AlmostEqual(a,0) && AlmostEqual(b,0)){
r = false;
c = sqrt(c);
return;
}
if(AlmostEqual(b,0) && AlmostEqual(c,0)){
b = sqrt(a);
a = 0;
r = false;
return;
}
}
UReal getNormalized() const{
UReal n(*this);
n.Normalize();
return n;
}
/*
Symbol for use in typemappings
*/
static const std::string BasicType(){ return "ureal"; }
static const bool checkType(const ListExpr type){
return listutils::isSymbol(type, BasicType());
}
/*
3.6.2 Operator redefinitions
*/
virtual UReal& operator=( const UReal& i )
{
del.isDefined = i.del.isDefined;
if( !i.IsDefined() ){
return *this;
}
*((TemporalUnit<CcReal>*)this) = *((TemporalUnit<CcReal>*)&i);
a = i.a;
b = i.b;
c = i.c;
r = i.r;
return *this;
}
/*
Redefinition of the copy operator ~=~.
*/
virtual bool operator==( const UReal& i ) const
{
if( !this->IsDefined() && !i.IsDefined() ) {
return true;
}
return this->IsDefined() && i.IsDefined()
&& *((TemporalUnit<CcReal>*)this) == *((TemporalUnit<CcReal>*)&i)
&& AlmostEqual( a, i.a )
&& AlmostEqual( b, i.b )
&& AlmostEqual( c, i.c )
&& r == i.r;
}
/*
Returns ~true~ if this temporal unit is equal to the temporal unit ~i~ and ~false~ if they are different.
Two undefined units are always equal.
*/
virtual bool operator!=( const UReal& i ) const
{
return !( *this == i );
}
/*
Returns ~true~ if this temporal unit is different to the temporal unit ~i~ and ~false~ if they are equal.
*/
/*
3.7.2 The Temporal Functions
*/
virtual void TemporalFunction( const Instant& t,
CcReal& result,
bool ignoreLimits = false ) const;
virtual bool Passes( const CcReal& val ) const;
virtual bool At( const CcReal& val, TemporalUnit<CcReal>& result ) const;
virtual void AtInterval( const Interval<Instant>& i,
TemporalUnit<CcReal>& result ) const;
virtual bool EqualValue(const TemporalUnit<CcReal>& i1) const{
return TemporalUnit<CcReal>::EqualValue(i1);
}
virtual bool EqualValue( const UReal& i1 ) const
{
if( !this->IsDefined() && !i1.IsDefined() ) {
return true;
}
if( !this->IsDefined() || !i1.IsDefined() ) {
return false;
}
double offset = (i1.timeInterval.start - timeInterval.start).ToDouble();
UReal t = this->getNormalized();
UReal i = i1.getNormalized();
bool res =
(AlmostEqual( t.a, i.a ) &&
(t.r == i.r) &&
AlmostEqual( 2 * t.a * offset + t.b, i.b ) &&
AlmostEqual( t.a * pow(offset, 2) + t.b * offset + t.c, i.c )
);
return res;
}
/*
Returns ~true~ if the value of this temporal unit is equal to the
value of the temporal unit ~i~ and ~false~ if they are different.
Equality is calculated with respect to temporal evolution.
*/
/*
3.7.3 Functions to be part of relations
*/
virtual size_t Sizeof() const
{
return sizeof( *this );
}
virtual int Compare( const Attribute* arg ) const
{
UReal* mr2 = (UReal*) arg;
if (!IsDefined() && !mr2->IsDefined())
return 0;
if (!IsDefined())
return -1;
if (!mr2->IsDefined())
return 1;
// both ureals are defined...
int cmp = timeInterval.CompareTo(mr2->timeInterval);
if(cmp){
return cmp;
}
// because we can't compare the functions themself, we
// use the lexicographical order of the parameters
if(a<mr2->a) return -1;
if(a>mr2->a) return 1;
if(b<mr2->b) return -1;
if(b>mr2->b) return 1;
if(c<mr2->c) return -1;
if(c>mr2->c) return 1;
if(r && !mr2->r) return -1;
if(!r && mr2->r) return 1;
return 0;
}
virtual bool Adjacent( const Attribute* arg ) const
{
return false;
}
virtual std::ostream& Print( std::ostream &os ) const
{
if( IsDefined() )
{
os << "UReal: " << "( ";
timeInterval.Print(os);
os << ", ";
// print specific stuff:
os << " ( " << a << ", " << b << ", " << c
<< (r ? ", TRUE) " : ", FALSE) ");
os << " ) ";
return os;
}
else
return os << "UReal: (undef) ";
}
virtual size_t HashValue() const
{
if(!IsDefined()){
return 0;
}
return static_cast<size_t>( timeInterval.start.HashValue()
^ timeInterval.end.HashValue() ) ;
}
virtual UReal* Clone() const
{
UReal *res;
if( !this->IsDefined() ){
res = new UReal( false );
} else {
res = new UReal( timeInterval, a, b, c, r);
}
res->del.isDefined = del.isDefined;
return res;
}
virtual void CopyFrom( const Attribute* right )
{
const UReal* i = (const UReal*)right;
del.isDefined = i->del.isDefined;
if(i->IsDefined())
{
timeInterval.CopyFrom(i->timeInterval);
a = i->a;
b = i->b;
c = i->c;
r = i->r;
}
else
{
timeInterval = Interval<Instant>();
a = 0;
b = 0;
c = 0;
r = false;
}
}
/*
3.7.4 Other Methods
*/
virtual void TranslateParab( const double& t);
/*
This operator will translate the apex of the parabolic curve
used within the ureal representation by (t) on the x/time-axes.
*/
double Integrate() const;
/*
*Precondition*: this[->]IsDefined() is true
*/
int PeriodsAtVal( const double& value, Periods& times) const;
/*
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.
*/
double PeriodsAtMin(bool& correct, Periods& times) const;
/*
Sets the Periods value to the times, where this takes the
minimum value. Returns the minimum value.
*WARNING*: May return points, that are not inside this->timeInterval,
if a value is located at an open start/end instant.
*/
double PeriodsAtMax(bool& correct, Periods& times) const;
/*
Sets the Periods value to the times, where this takes the
minimum value. Returns the maximum value.
*WARNING*: May return points, that are not inside this->timeInterval,
if a value is located at an open start/end instant.
*/
int PeriodsAtEqual( const UReal& other, Periods& times) const;
/*
Sets the Periods value to the times, where both UReals take the
same value. Returns the number of results (0-2).
*/
int AtMin( std::vector<UReal>& result ) const;
/*
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 AtMax( std::vector<UReal>& result ) const;
/*
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 resultunit 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 AtValue(CcReal value, std::vector<UReal>& result) const;
/*
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 resultunit 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 IsEqual(const UReal& other, std::vector<UBool>& result) const;
/*
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 Abs(std::vector<UReal>& result) const;
/*
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 Distance(const UReal& other, std::vector<UReal>& result) const;
/*
Creates the distance to an other UReal value.
~result~ may contain 0-3 UReal values.
*Preconditions*: this[->]IsDefined() AND other.IsDefined()
this->r == other.r == false
*Result*: stores the resultunits into vector result and returns
the number of results.
*/
double Max(bool& correct) const;
/*
*Precondition*: this[->]IsDefined() is true
*/
double Min(bool& correct) const;
/*
*Precondition*: this[->]IsDefined() is true
*/
void Linearize(UReal& result) const;
void Linearize(UReal& result1, UReal& result2) const;
/*
Stores a linear approximation of this UReal in result1 and result2.
If the extremum is outside of the corresponding interval, result2 will
be undefined and result 1 contains a linear approximation between the
value at the interval boundaries. Otherwise this unit is split at the
extremum.
*/
void CompUReal(UReal& ur2, int opcode, std::vector<UBool>& res);
/*
Computes for two given ~ureal~ values the resulting ~ubool~ values,
sorted by their time intervals, depending on the compare result for
~opcode~. Possible opcode values are:
opcode == 0 =
opcode == 1 #
opcode == 2 <
opcode == 3 >
opcode == 4 <=
opcode == 5 >=
*/
void Recompute(const UPoint& up1, const UPoint& up2, const Geoid* geoid);
/*
Recomputes the unit real so that it represents the distance according to geoid
instead of geographic coordinates. This is necessary because the precise
spherical distance for line segments is not implemented.
*/
void Split(const datetime::DateTime& duration, std::vector<UReal>& result)
const;
/*
3.7.5 Attributes
*/
double a, b, c;
bool r;
};
/*
The following class describes an event created by an object moving over a
regular grid.
*/
class GridCellSeq {
public:
GridCellSeq(); // standard constructor - creates undefined instance
GridCellSeq(const datetime::DateTime &enter,
const datetime::DateTime &leave,
const int32_t &cellNo); // automatically updates defined
GridCellSeq(const GridCellSeq &other); // copy-constructor
GridCellSeq& operator=(const GridCellSeq &other); // assignment
~GridCellSeq(); // destructor
datetime::DateTime getEnterTime() const; // read attribute
datetime::DateTime getLeaveTime() const; // read attribute
int32_t getCellNo() const; // read attribute
void setCellNo(const int32_t &n); // set attr and update definedness
void setEnterTime(const datetime::DateTime &t); // set attr and
//updates definedness
void setLeaveTime(const datetime::DateTime &t); // set attr and
// updates definedness
void setUndefined(); // sets defined to false
bool IsDefined() const; // returns definedness
void set(const int32_t &c, const datetime::DateTime &s,
const datetime::DateTime &e);
// set all attributes and update definedness
std::ostream& Print( std::ostream &os ) const;
private:
datetime::DateTime my_enterTime; // initial instant of presence in the cell
datetime::DateTime my_leaveTime; // final instant of presence in the cell
int32_t my_cellNo; // the cell concerned.
bool defined; // well-definedness of the data
};
/*
3.8 UPoint
This class will be used in the ~upoint~ type constructor, i.e., the type constructor
for the temporal unit of point values.
*/
class UPoint : public SpatialTemporalUnit<Point, 3>
{
/*
3.8.1 Constructors and Destructor
*/
public:
typedef UPoint unittype;
UPoint() {};
UPoint(bool is_defined):
SpatialTemporalUnit<Point, 3>(is_defined)
{
};
UPoint( const Interval<Instant>& _interval,
const double x0, const double y0,
const double x1, const double y1 ):
SpatialTemporalUnit<Point, 3>( _interval ),
p0( true, x0, y0 ),
p1( true, x1, y1 )
{ }
UPoint( const Interval<Instant>& _interval,
const Point& _p0, const Point& _p1 ):
SpatialTemporalUnit<Point, 3>( _interval ),
p0( _p0 ),
p1( _p1 )
{
SetDefined(p0.IsDefined() && p1.IsDefined());
}
UPoint(const UPoint& source):
SpatialTemporalUnit<Point, 3>(source.IsDefined()) {
*((TemporalUnit<Point>*)this) = *((TemporalUnit<Point>*)&source);
p0 = source.p0;
p1 = source.p1;
del.refs=1;
del.SetDelete();
del.isDefined = source.del.isDefined;
}
/*
3.6.2 Operator redefinitions
*/
virtual UPoint& operator=( const UPoint& i )
{
del.isDefined = i.del.isDefined;
if( !i.IsDefined() ){
return *this;
}
*((TemporalUnit<Point>*)this) = *((TemporalUnit<Point>*)&i);
p0 = i.p0;
p1 = i.p1;
return *this;
}
/*
~GetNoComponents~
Returns the constant number 1. This function allows for
templates using UPoint and MPoint.
*/
int GetNoComponents() const{
return 1;
}
/*
~Get~
*/
void Get( const int i, UPoint& upi ) const{
assert(i==0);
upi = *this;
}
/*
Redefinition of the copy operator ~=~.
*/
virtual bool operator==( const UPoint& i ) const
{
if( !this->IsDefined() && !i.IsDefined() ){
return true;
}
return this->IsDefined() && i.IsDefined()
&& *((TemporalUnit<Point>*)this) == *((TemporalUnit<Point>*)&i)
&& AlmostEqual( p0, i.p0 )
&& AlmostEqual( p1, i.p1 );
}
/*
Returns ~true~ if both units are undefined, or if both are defined and this temporal unit is equal to the temporal unit ~i~ and ~false~ if they are different.
*/
virtual bool operator!=( const UPoint& i ) const
{
return !( *this == i );
}
/*
Returns ~true~ if this temporal unit is different to the temporal unit ~i~ and ~false~ if they are equal.
*/
/*
3.8.2 The Temporal Functions
*/
virtual void TemporalFunction( const Instant& t,
Point& result,
bool ignoreLimits = false ) const;
void TemporalFunction( const Instant& t,
Point& result,
const Geoid* geoid,
bool ignoreLimits = false) const;
virtual bool Passes( const Point& val ) const;
bool Passes( const Point& val, const Geoid* geoid ) const;
bool Passes( const Region& val ) const;
bool Passes( const Rectangle<2>& rect ) const;
virtual bool At( const Point& val, TemporalUnit<Point>& result ) const;
bool At( const Point& val, TemporalUnit<Point>& result,
const Geoid* geoid ) const;
virtual void AtInterval( const Interval<Instant>& i,
TemporalUnit<Point>& result ) const;
void AtInterval( const Interval<Instant>& i,
TemporalUnit<Point>& result,
const Geoid* geoid ) const;
void At(const Rectangle<2>& rect, UPoint& result) const;
/*
Computes the temporal distance to a Point ~p~. Result is a single unit.
Only to be used with euclidean coordinate data!
*/
void Distance( const Point& p, UReal& result ) const;
/*
Computes the temporal distance to a Point ~p~. All result units will be appended
to the ~result~ vector of UReal values. If ~geoid~ in NULL, euclidean geometry is
applied and only a single result unit is appended. Otherwise, spherical geometry
is used ~result~ is appended with a series uf UReal units approximating the
actual moving distance.
UNDEFINED UReal values may be appended!.
*/
void Distance( const Point& p, std::vector<UReal>& result,
const Geoid* geoid = 0, const double epsilon = 0.00001 ) const;
/*
Computes the temporal distance to a Point ~p~ using an iterative method. The
result is passed in output parameter ~result~. The vector may contain UNDEFINED
units.
The function works recursively. It is possible to pass down pre-computed data
using parameters ~tMin~ (instant of nearest approach), ~distMin~ (distance at
nearest approach), ~distStart~ (distance at initial instant of THIS unit),
~distEnd~ (distance at final instant of THIS unit). Doing so avoids repeated
calculation of these values. The default parameters make sure, that the values
will be computed once.
Computation stops, once the absolute distance difference between consecutive
steps drops below ~epsilon~.
*/
void 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;
/*
Computes the spatial projection of THIS UPoint.
*/
void UTrajectory( Line& line ) const;
/*
The scalar velocity as a temporal function
If geoid = 0, metric (X,Y)-coordinates are used within the UPoint.
If geoid points to a valid Geoid object, geografic coordinates (LON,LAT)
are used within the UPoint. Speed is interpreted as speed over ground!
*/
void USpeed( UReal& result, const Geoid* geoid = 0 ) const;
/*
The vectorial velocity --- (X,Y)-components --- as temporal function
*/
void UVelocity( UPoint& result ) const;
void Intersection(const UPoint &other, UPoint &result) const;
/*
~EqualValue~ returns true iff both units describe parts if the same linear
temporal function.
*/
virtual bool EqualValue( const TemporalUnit<Point>& i) const{
return EqualValue(* ((UPoint*) &i));
}
virtual bool EqualValue( const UPoint& i ) const {
if( !IsDefined() && !i.IsDefined() ){
// both undefined
// cout << "\t" << __PRETTY_FUNCTION__ << " SUCCEEDED: both undefined."
// << std::endl;
return true;
} else if( !IsDefined() || !i.IsDefined() ){
// one of *this and i undefined
// cout << "\t" << __PRETTY_FUNCTION__ << " FAILED: one undefined."
// << std::endl;
return false;
} // else: both are defined
Point v(false);
TemporalFunction(i.timeInterval.start, v, true);
if( !v.IsDefined() || !AlmostEqual(i.p0,v) ){
// cout << "\t" << __PRETTY_FUNCTION__ << " FAILED: start1 unmatched."
// << std::endl;
return false;
}
TemporalFunction(i.timeInterval.end, v, true);
if( !v.IsDefined() || !AlmostEqual(i.p1,v) ){
// cout << "\t" << __PRETTY_FUNCTION__ << " FAILED: end1 unmatched."
// << std::endl;
// cout << "\t" << __PRETTY_FUNCTION__ << " i.p1 = " << i.p1 << std::endl;
// cout << "\t" << __PRETTY_FUNCTION__ << " v = " << v << std::endl;
return false;
}
TemporalFunction(timeInterval.start, v, true);
if( !v.IsDefined() || !AlmostEqual(p0,v) ){
// cout << "\t" << __PRETTY_FUNCTION__ << " FAILED: start2 unmatched."
// << std::endl;
return false;
}
TemporalFunction(timeInterval.end, v, true);
if( !v.IsDefined() || !AlmostEqual(p1,v) ){
// cout << "\t" << __PRETTY_FUNCTION__ << " FAILED: end2 unmatched."
// << std::endl;
return false;
}
// cout << "\t" << __PRETTY_FUNCTION__
// << " SUCCEEDED: all points matched." << std::endl;
return true;
}
virtual bool Merge( const TemporalUnit<Point>& i){
return Merge(*((UPoint*) &i));
}
virtual bool Merge( const UPoint& i ) {
// check for gap in definition time
if(!IsDefined() && !i.IsDefined()) { // mergeable, but nothing to do
// cout << __PRETTY_FUNCTION__ << " SUCCEEDED: both undefined." << endl;
return true;
} else if(!IsDefined() || !i.IsDefined()) { // not mergable
// cout << __PRETTY_FUNCTION__ << " FAILED: one undefined." << endl;
return false;
} else if( !this->timeInterval.Adjacent(i.timeInterval)
&& !this->timeInterval.Intersects(i.timeInterval) ){
// cout << __PRETTY_FUNCTION__ << " FAILED: found definition gap."
// << endl;
return false; // have a gap in between --> not mergeable
} else if(!EqualValue(i)) { // temporal functions are NOT equal
// cout << __PRETTY_FUNCTION__ << " FAILED: functions not equal." << endl;
return false;
}
// merge the units (i.e. their timeIntervals)
UPoint res(false);
if(StartsBefore(i)){
res.timeInterval.start = this->timeInterval.start;
res.timeInterval.lc = this->timeInterval.lc;
res.p0 = this->p0;
} else {
res.timeInterval.start = i.timeInterval.start;
res.timeInterval.lc = i.timeInterval.lc;
res.p0 = i.p0;
}
if(EndsAfter(i)){
res.timeInterval.end = this->timeInterval.end;
res.timeInterval.rc = this->timeInterval.rc;
res.p1 = this->p1;
} else {
res.timeInterval.end = i.timeInterval.end;
res.timeInterval.rc = i.timeInterval.rc;
res.p1 = i.p1;
}
if(res.IsDefined() && res.IsValid()){ // invalid result -- do nothing!
// cout << __PRETTY_FUNCTION__ << " SUCCEEDED: created result unit."
// << endl;
*this = res;
return true;
} else {
// cout << __PRETTY_FUNCTION__ << " FAILED: result invalid." << endl;
return false;
}
}
/*
Merges UPoint ~i~ into this unit if possible and return ~true~. Otherwise do
not modify this unit and return ~false~.
*/
void Translate(const double x, const double y,
const datetime::DateTime& duration);
/*
Translates a moving point spatially and temporally.
*/
void GetGridCellSequence(CellGrid2D &g, std::vector<GridCellSeq> &res);
/*
Computes all events created by a UPoint moving across a regular grid.
*/
/*
3.8.3 Functions to be part of relations
*/
inline virtual size_t Sizeof() const
{
return sizeof( *this );
}
inline virtual int Compare( const Attribute* arg ) const
{
UPoint* up2 = (UPoint*) arg;
if (!IsDefined() && !up2->IsDefined())
return 0;
if (!IsDefined())
return -1;
if (!up2->IsDefined())
return 1;
int cmp = timeInterval.CompareTo(up2->timeInterval);
if(cmp){
return cmp;
}
if(p0<up2->p0){
return -1;
}
if(p0>up2->p0){
return 1;
}
if(p1>up2->p1){
return 1;
}
if(p1<up2->p1){
return -1;
}
return 0;
}
inline virtual bool Adjacent( const Attribute* arg ) const
{
UPoint* up = (UPoint*) arg;
if(timeInterval.end == up->timeInterval.start){ // up after this
return AlmostEqual(p1, up->p0) &&
(timeInterval.rc || up->timeInterval.lc);
}
if(up->timeInterval.end == timeInterval.start){
return AlmostEqual(up->p1,p0) &&
(up->timeInterval.rc || timeInterval.lc);
}
return false;
}
inline virtual std::ostream& Print( std::ostream &os ) const
{
if(IsDefined())
{
os << "UPoint: " << "( ";
timeInterval.Print(os);
os << ", ";
p0.Print(os);
os << ", ";
p1.Print(os);
os << " ) ";
return os;
}
else
return os << "UPoint: (undef) ";
}
inline virtual size_t HashValue() const
{
if(!IsDefined()){
return 0;
}
return static_cast<size_t>( timeInterval.start.HashValue()
^ timeInterval.end.HashValue() ) ;
}
inline virtual UPoint* Clone() const
{
UPoint *res;
if(this->IsDefined()){
res = new UPoint( timeInterval, p0, p1 );
res->del.isDefined = del.isDefined;
} else {
res = new UPoint( false );
// res->timeInterval = Interval<Instant>();
res->p0 = Point( false, 0.0, 0.0);
res->p1 = Point( false, 0.0, 0.0);
}
return res;
}
inline virtual void CopyFrom( const Attribute* right )
{
const UPoint* i = static_cast<const UPoint*>(right);
if(i->del.isDefined)
{
timeInterval.CopyFrom( i->timeInterval );
p0 = i->p0;
p1 = i->p1;
}
else
{
// timeInterval = Interval<Instant>();
p0 = Point( false, 0.0, 0.0);
p1 = Point( false, 0.0, 0.0);
}
del.isDefined = i->del.isDefined;
}
virtual const Rectangle<3> BoundingBox(const Geoid* geoid = 0) const
{
if(geoid){
if(!geoid->IsDefined() || !IsDefined()){
return Rectangle<3>(false);
}
Rectangle<2> geobbox(false);
if(AlmostEqual(p0,p1)){
Rectangle<2> geobbox = p0.GeographicBBox(p1, *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: use HalfSegment::BoundingBox(...)
geobbox = HalfSegment(true,p0,p1).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
if(this->IsDefined()){
double minMax[] = {MIN( p0.GetX(), p1.GetX() ),
MAX( p0.GetX(), p1.GetX() ),
MIN( p0.GetY(), p1.GetY() ),
MAX( p0.GetY(), p1.GetY() ),
timeInterval.start.ToDouble(),
timeInterval.end.ToDouble() };
return Rectangle<3>( true,minMax );
} else {
return Rectangle<3>( false );
}
}
static unsigned GetDim(){ return 3; }
virtual const Rectangle<3> BoundingBox(const double scaleTime,
const Geoid* geoid = 0) 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> BoundingBoxSpatial(const Geoid* geoid = 0) 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 );
}
}
/*
Calculates the distance between 2 upoints as a real value.
If ~geoid~ is NULL, euclidean geometry is used, spherical geometry otherwise.
If invalid geographic coordinates are found, the result is UNDEFINED.
*Precondition*: intersecting timeIntervals.
*Result*: the distance of two upoints as a ureal
*/
void Distance( const UPoint& up, UReal& result, const Geoid* geoid = 0) const;
double GetRadius() const {return 0.0;}
void SetRadius(const double r) {}
double DistanceIntegral(const UPoint& up, const bool upperBound,
const Geoid* geoid = 0) const;
/*
Computes the distance between the three dimensional line defined by
that unit and the rectangle.
*/
virtual double Distance(const Rectangle<3>& rect, const Geoid* geoid=0) const;
virtual bool Intersects(const Rectangle<3>& rect, const Geoid* geoid=0) const;
virtual bool IsEmpty() const{
return !IsDefined();
}
/*
Calculates the spatial length of the unit using metric (X,Y) coordinates.
*Precondition*: none
*Result*: the distance of the unit's initial and final value
*/
void Length( CcReal& result ) const;
/*
Calculates the spatial length of the unit using geographic (LON,LAT)-coordinates.
*Precondition*: none
*Result*: the distance of the unit's initial and final value
*/
void Length( const Geoid& g, CcReal& result ) const;
/*
Calculates the intersection of the UPoint and Region r.
*Precondition*: none
*Result*: The ~result~ is a vector of UPoints, sorted ascendingly by their starting instants.
The boolean return value is ~false~, iff either the UPoint or the Region is UNDEFINED.
*/
bool AtRegion(const Region *r, std::vector<UPoint> &result) const;
/*
Calculates the ~direction~ (when ~useHeading~ is ~false~) resp. the heading
(when ~true~) of this UPoint. If ~geoid~ is not NULL, spherical geometry is
applied and the true course is approximated as a series of units according
to preciseness parameter ~epsilon~.
Any results are appended to the ~result~ vector.
Attention: UNDEFINED units my be appended!
*/
void Direction( std::vector<UReal> &result,
const bool useHeading = false,
const Geoid* geoid = 0,
const double epsilon = 0.0000001) const;
static const std::string BasicType(){ return "upoint"; }
static const bool checkType(const ListExpr type){
return listutils::isSymbol(type, BasicType());
}
/*
~IsStatic~
Returns true, iff this unit is defined and not moving during its definition time.
*/
bool IsStatic() const{
return IsDefined() && AlmostEqual(p0,p1);
}
void Clear() {}
void gk(int zone, UPoint& result) const{
if(!IsDefined()){
result.SetDefined(false);
}
static WGSGK gk;
gk.setMeridian(zone);
result = *this;
gk.project(p0,result.p0);
gk.project(p1,result.p1);
if(!result.p0.IsDefined() || !result.p1.IsDefined()){
result.p0.Set(true,0,0);
result.p1.Set(true,0,0);
result.SetDefined(false);
}
}
void SetToConstantUnit(const Point& p, const double r = 0) {
p0 = p;
p1 = p0;
}
/*
3.8.4 Attributes
*/
Point p0, p1;
};
std::ostream& operator<<(std::ostream& o, const UPoint& u);
ListExpr OutUPoint( ListExpr typeInfo, Word value );
Word InUPoint( const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr& errorInfo, bool& correct );
/*
3.9 Mapping
This class will implement the functionalities of the ~mapping~ type constructor.
It contains a database array of temporal units. For that, ~Unit~ must implement
the class ~TemporalUnit~ or ~ConstTemporalUnit~, because functions of these classes will be used.
*/
bool IsMaximumPeriods(const Periods& p);
template <class Unit, class Alpha>
class Mapping : public Attribute
{
public:
typedef Unit unittype;
typedef Alpha alphatype;
/*
3.9.1 Constructors and Destructor
*/
Mapping() {}
/*
The simple constructor. This constructor should not be used.
*/
Mapping( const int n );
/*
The constructor. Initializes space for ~n~ elements.
*/
virtual ~Mapping();
/*
The destructor.
*/
void Destroy();
/*
This function should be called before the destructor if one wants to destroy the
persistent array of moving units. It marks the persistent array for destroying. The
destructor will perform the real destroying.
3.10.2 Functions for Bulk Load of moving units
As said before, the moving unit set is implemented as an ordered persistent array of units.
The time complexity of an insertion operation in an ordered array is $O(n)$, where ~n~
is the size of the unit set. In some cases, bulk load of units for example, it is good
to relax the ordered condition to improve the performance. We have relaxed this ordered
condition only for bulk load of units. All other operations assume that the unit set is
ordered.
*/
bool IsOrdered() const;
/*
Returns true, if the unit set is ordered.
There is a flag ~ordered~ (see attributes) in order
to avoid a scan in the unit set to answer this question.
*/
void StartBulkLoad();
/*
Marks the start of a bulk load of units relaxing the condition that the units must be
ordered. We will assume that the only way to add units to an unit set is inside bulk
loads, i.e., into non-ordered mappings.
*/
virtual bool EndBulkLoad( const bool sort = true,
const bool checkvalid = false );
/*
Marks the end of a bulk load and sorts the unit set if the flag ~sort~ is set to true.
Checkvalid indicated, wheter the validity (temporally non-overlapping untis) should
be checked. In this case, if the Range is invalid, it is set to undefined!
3.10.3 Member functions
*/
bool IsEmpty() const;
/*
Returns true, if the mapping is undefined or empty of units.
*/
void Get( const int i, Unit& upi ) const;
/*
Returns the unit ~upi~ at the position ~i~ in the mapping.
*Precondition*: this[->]IsDefined() == true
*Precondition*: 0 <= this[->]NoComponents() <= i
*/
virtual void Add( const Unit& upi );
/*
Adds an unit ~upi~ to the mapping. We will assume that the only way of adding units
is in bulk loads, i.e., in a non-ordered array.
*Precondition:* this[->]IsDefined() == true
*Precondition:* ~IsOrdered() == false~
*/
virtual void MergeAdd( const Unit& upi );
/*
Adds an unit ~upi~ to the mapping. If the new unit and the last
unit in the Mapping are equalValue it merges the two units.
We will assume that the only way of adding units
is in bulk loads, i.e., in a non-ordered array.
Without defining the function ~equalValue~ for units
~MergeAdd~ works the same way as ~Add~.
*Precondition:* this[->]IsDefined() == true
*Precondition:* ~IsOrdered() == false~
*/
inline void Put(const int i, const Unit& u){
units.Put(i,u);
}
/*
Replaces the unit at position ~i~ within the mapping's DbArray.
*Precondition:* this[->]IsDefined() == true
*/
virtual void Clear();
/*
Remove all units in the mapping and set the defined flag.
*/
bool IsValid() const;
/*
This functions tests if a ~mapping~ is in a valid format. It is used for debugging
purposes only. The ~mapping~ is valid, if the following conditions are true:
Either the mapping is undefined, or the mapping is defined and conditions 1--3 hold:
1 Each unit is valid
2 Start of each unit $>=$ end of the unit before
3 If start of an unit = end of the unit before, then one needs to
make sure that the unit is not left-closed or the unit before
is not right-closed
3.10.4 Functions to be part of relations
*/
inline virtual size_t Sizeof() const;
inline virtual int Compare( const Attribute* arg ) const;
inline bool Adjacent( const Attribute* arg ) const;
inline Attribute* Clone() const;
inline virtual std::ostream& Print( std::ostream &os ) const;
inline size_t HashValue() const;
inline virtual void CopyFrom( const Attribute* right );
inline virtual void Restrict(
const std::vector< std::pair<int, int> >& intervals );
inline int NumOfFLOBs() const;
inline Flob *GetFLOB(const int i);
/*
3.10.5 Operations
3.10.5.1 Operation $=$ (~equal~)
*Precondition:* ~X.IsOrdered() $\&\&$ Y.IsOrdered()~
*Semantics:* $X = Y$
*Complexity:* $O(n+m)$, where ~n~ is the number of units of this mapping ~X~ and m the
number of units of the mapping ~Y~.
*/
bool operator==( const Mapping<Unit, Alpha>& mp ) const;
/*
3.10.5.2 Operation $\neq$ (~not equal~)
*Precondition:* ~X.IsOrdered() $\&\&$ Y.IsOrdered()~
*Semantics:* $X \neq Y$
*Complexity:* $O(n+m)$, where ~n~ is the number of units of this mapping ~X~ and m the
number of units of the mapping ~Y~.
*/
bool operator!=( const Mapping<Unit, Alpha>& mp ) const;
/*
3.10.5.3 Operation ~no\_components~
*Precondition:* ~IsDefined() == true~
*Precondition:* ~X.IsOrdered()~
*Semantics:* $\| intvls(X) \|$
*Complexity:* $O(1)$
*/
int GetNoComponents() const;
/*
3.10.5.3 Operation ~position~
*Precondition:* ~X.IsOrdered()~
*Semantics:*
*Complexity:* $O( \log n )$, where ~n~ is the number of units of this mapping ~X~
*/
int Position( const Instant& t ) const;
/*
3.10.5.3 Operation ~atinstant~
*Precondition:* ~X.IsOrdered()~
*Semantics:*
*Complexity:* $O( \log n )$, where ~n~ is the number of units of this mapping ~X~
*/
void AtInstant( const Instant& t, Intime<Alpha>& result ) const;
/*
3.3.3.3 Operation ~Temporal Function~
same as ~AtInstant~, but returns an Alpha, not an Intime.
*/
void TemporalFunction( const Instant& t,
Alpha& result,
bool ignoreLimits = true) const;
/*
3.10.5.3 Operation ~atperiods~
*Precondition:* ~X.IsOrdered() \&\& Y.IsOrdered()~
*Semantics:*
*Complexity:* $O( m + n )$, where ~n~ is the number of units of this mapping ~X~
and ~m~ is the number of intervals of the periods ~Y~
*/
void AtPeriods( const Periods& periods,
Mapping<Unit, Alpha>& result ) const;
/*
3.10.5.3 Operation ~present~
*Precondition:* ~X.IsOrdered()~
*Semantics:*
*Complexity:* $O( \log n )$, where ~n~ is the number of units of this mapping ~X~
*/
bool Present( const Instant& t ) const;
bool Present( const Periods& periods ) const;
/*
3.10.5.4 Operator compress
Creates a compressed version of this mapping.
*/
Mapping<Unit,Alpha>* compress() const;
/*
3.10.5.3 Operation ~passes~
*Precondition:* ~X.IsDefined() AND X.IsOrdered()~
*Semantics:*
*Complexity:* $O( n )$, where ~n~ is the number of units of this mapping ~X~
*/
template <class Beta>
bool Passes( const Beta& val ) const;
/*
3.10.5.3 Operation ~deftime~
*Precondition:* ~X.IsOrdered()~
*Semantics:*
*Complexity:* $O( n )$, where ~n~ is the number of units of this mapping ~X~
*/
void DefTime( Periods& result ) const;
/*
3.10.5.3 Operation ~at~
*Precondition:* ~X.IsOrdered()~
*Semantics:*
*Complexity:* $O( n )$, where ~n~ is the number of units of this mapping ~X~
*/
void At( const Alpha& val, Mapping<Unit, Alpha>& result ) const;
/*
3.10.5.3 Operation ~initial~
*Precondition:* ~X.IsOrdered()~
*Semantics:*
*Complexity:* $O( 1 )$
*/
void Initial( Intime<Alpha>& result ) const;
/*
3.10.5.3 Operation ~final~
*Precondition:* ~X.IsOrdered()~
*Semantics:*
*Complexity:* $O( 1 )$
*/
void Final( Intime<Alpha>& result ) const;
/*
3.10.5.3 ~Resize~
Changes the unit's array to have space for ~n~ entries.
*/
void Resize(const size_t n);
/*
3.10.5.4 ~TrimToSize~
Changes the unit's array to have space to contain exactly the
number of actually contained elements.
*/
void TrimToSize();
/*
3.10.4.4 ~ExtendDefTime~
The result takes all units from this Mapping. Additionally the deftime
is extended to the union with the interval of the given unit. Missing parts
in the definition time of this Mapping are filled with the value given by the
unit. Note that this implementation works only for instances of
ConstTempralUnit - Mappings.
*/
void ExtendDefTime(Unit u, Mapping<Unit, Alpha>& result);
/*
3.10.5.5 ~GetInterval~
Extracts the time interval of the unit at a certain position.
*/
void GetInterval(const int pos, SecInterval& result) const;
/*
3.10.5.6 ~InitialInstant~
Extracts the initial instant of the object.
*/
void InitialInstant(Instant& result) const;
/*
3.10.5.7 ~FinalInstant~
Extracts the final instant of the object.
*/
void FinalInstant(Instant& result) const;
/*
3.10.5.7 ~GetFullInterval~
Extracts the time interval consisting of the initial and final instant and the
leftclosed/rightclosed flags.
*/
void GetFullInterval(Interval<Instant>& result) const;
/*
3.10.5.7 ~GetDuration~
Extracts the sum of the lengths of all time intervals (avoiding the creation
and the scan of a periods value).
*/
void GetDuration(datetime::DateTime& result) const;
/*
type name used in Secondo
*/
inline static const std::string BasicType()
{
return "m"+Alpha::BasicType();
}
static const bool checkType(const ListExpr type){
return listutils::isSymbol(type, BasicType());
}
/*
~Move in time~
*/
void timeMove(const datetime::DateTime& duration,
Mapping<Unit, Alpha>& result) const;
void moveTo(const datetime::DateTime& instant,
Mapping<Unit,Alpha>& result) const;
/*
3.10.7 Attributes
*/
private:
bool canDestroy;
/*
A flag indicating if the destructor should destroy also the persistent
array of intervals.
*/
bool ordered;
/*
A flag indicating whether the unit set is ordered or not.
*/
protected:
DbArray< Unit > units;
/*
The database array of temporal units.
*/
};
/*
3.10 Class ~MBool~
*/
typedef Mapping< UBool, CcBool > MBool;
class MReal;
/*
3.10 Class ~MInt~
*/
class MInt : public Mapping< UInt, CcInt > {
public:
/*
~Simple Constructor~
*/
MInt(){}
/*
~Constructor~
Initializes the size of the array of units
*/
MInt(const int n):
Mapping<UInt, CcInt>(n){}
/*
~MergeAddFillUp~
Append the unit to this MInt. If a gap in time between the last
Unit and the new units exists, it is filled up using a unit having value
as it's value.
*/
void MergeAddFillUp(const UInt& unit, const int fillValue);
/*
Fills gaps in the definition time eith the given value.
*/
void fillUp(int value, MInt& result) const;
int maximum() const;
int minimum() const;
int Min(bool& correct) const;
int Max(bool& correct) const;
/*
~ReadFrom~
Reads the value of this moving(int) from the value
of the given moving(bool). The temporal structure
is equal to the temporal structure of the moving(bool).
A unit holding the value false is converted to a unit with
value zero. Units with value true are converted into units
representing the value 1 over their interval.
*/
void ReadFrom(const MBool& arg);
/*
~WriteTo(MBool)~
Writes the value of this moving(int) into the value
of the result moving(bool). The temporal structure of
the result is equal to the temporal structure of this
moving(int). A unit holding the value zero is converted
to a unit with value false. Otherwise true.
*/
void WriteTo(MBool& arg);
/*
~WriteTo(MReal)~
Casts this MInt into an MReal.
*/
void WriteTo(MReal& arg);
static const std::string BasicType(){ return "mint"; }
static const bool checkType(const ListExpr type){
return listutils::isSymbol(type, BasicType());
}
void Hat(MInt& mint);
/*
~Restrict~
This operator removes the first (last) unit of this mint if it
starts (ends) with endoftime (beginoftime). If __useValue__
is set to true, the units are only removed if the stored value is equals to
the given value.
*/
virtual void Restrict(const std::vector<std::pair<int, int> >& intervals){
return Mapping<ConstTemporalUnit<CcInt>, CcInt>::Restrict(intervals);
}
void Restrict(MInt& result,
const bool useValue = false,
const int value = 0) const;
void PlusExtend(const MInt* arg2, MInt& result) const;
void SortbyUnitTime();
};
class MPoint;
/*
3.11 Class ~MReal~
*/
class MReal: public Mapping< UReal, CcReal > {
public:
/*
3.11.1 Constructory
*/
MReal() {}
MReal( const int n ):
Mapping< UReal, CcReal >( n )
{
del.refs=1;
del.SetDelete();
del.isDefined = true;
}
/*
3.11.2 Operation ~Simplify~
Simplifies the connected linear approximated parts of this moving real.
*/
void Simplify(const double epsilon, MReal& result) const;
/*
3.11.3 Operation ~Integrate~
Compute the integral of this moving real.
*/
double Integrate();
/*
3.11.4 Operation ~Max~
*/
double Max(bool& correct) const;
/*
3.11.5 Operation ~Min~
*/
double Min(bool& correct) const;
/*
3.11.6 Operation ~Linearize~
This function replaces all units by linear approximations between their
start and end value.
*/
void Linearize(MReal& result) const;
/*
3.11.6 Operation ~Linearize2~
This function replaces all units by linear approximations between their
start and end value and possible the extremum.
*/
void Linearize2(MReal& result) const;
/*
3.11.6 Operation ~AtMin~
Restrict to periods where the temporal value is minimal.
*/
void AtMin( MReal& result ) const;
/*
3.11.7 Operation ~AtMax~
Restrict to periods where the temporal value is maximal.
*/
void AtMax( MReal& result ) const;
/*
3.11.8 Operation ~AtValue~
Restrict to periods where the temporal value is equal to a const value.
Precondition: ccvalue.IsDefined() == true
*/
void AtValue( const CcReal& ccvalue, MReal& result ) const;
/*
3.11.9 Operation ~Recompute~
*/
void Recompute(const MPoint& mp1, const MPoint& mp2, const Geoid* geoid);
static const std::string BasicType(){ return "mreal"; }
static const bool checkType(const ListExpr type){
return listutils::isSymbol(type, BasicType());
}
private:
void Simplify(const int min, const int max,
bool* useleft, bool* useright,
const double epsilon) const;
};
/*
3.12 Class ~MPoint~
*/
class MPoint : public Mapping< UPoint, Point >
{
public:
/*
3.12.1 Constructors and Destructor
*/
MPoint() {}
/*
The simple constructor. This constructor should not be used.
*/
MPoint( const int n ):
Mapping< UPoint, Point >( n )
{
del.refs=1;
del.SetDelete();
del.isDefined = true;
bbox = Rectangle<3>(false);
}
/*
The constructor. Initializes space for ~n~ elements.
*/
MPoint(const MPoint& src): Mapping<UPoint, Point>(1) {
SetDefined(src.IsDefined());
if (IsDefined()) {
StartBulkLoad();
UPoint unit(true);
for (int i = 0; i < src.GetNoComponents(); i++) {
src.Get(i, unit);
Add(unit);
}
EndBulkLoad(false);
bbox = src.BoundingBox();
}
}
/*
3.12.2 Modifications of Inherited Functions
Overwrites the function defined in Mapping, mostly in order to
maintain the object's bounding box. Also, some methods can be improved
using a check on bbox.
*/
void Clear();
void Add( const UPoint& unit );
void MergeAdd(const UPoint& unit);
bool EndBulkLoad( const bool sort = true, const bool checkvalid = false );
void Restrict( const std::vector< std::pair<int, int> >& intervals );
std::ostream& Print( std::ostream &os ) const;
bool operator==( const MPoint& r ) const;
bool Present( const Instant& t ) const;
bool Present( const Periods& t ) const;
void AtInstant( const Instant& t, Intime<Point>& result ) const;
void AtPeriods( const Periods& p, MPoint& result ) const;
void AtRect(const Rectangle<2>& rect, MPoint& result) const;
virtual Attribute* Clone() const
{
assert( IsOrdered() );
MPoint *result;
if( !this->IsDefined() ){
result = new MPoint( 0 );
} else {
result = new MPoint( GetNoComponents() );
if(GetNoComponents()>0){
result->units.resize(GetNoComponents());
}
result->StartBulkLoad();
UPoint unit;
for( int i = 0; i < GetNoComponents(); i++ ){
Get( i, unit );
result->Add( unit );
}
result->EndBulkLoad( false );
}
result->SetDefined(this->IsDefined());
return (Attribute*) result;
}
void CopyFrom( const Attribute* right )
{
const MPoint *r = (const MPoint*)right;
assert( r->IsOrdered() );
Clear();
this->SetDefined(r->IsDefined());
if( !this->IsDefined() ) {
return;
}
StartBulkLoad();
UPoint unit;
for( int i = 0; i < r->GetNoComponents(); i++ ){
r->Get( i, unit );
Add( unit );
}
EndBulkLoad( false );
}
/*
3.10.5.3 Operation ~trajectory~
*Precondition:* ~X.IsOrdered()~
*Semantics:*
*Complexity:* $O( n )$, where ~n~ is the number of units of this ~MPoint~
*/
void Trajectory( Line& line ) const;
// The scalar velocity as a temporal function
// If geoid = 0, metric (X.Y)-coordinates are used within the MPoint.
// If geoid points to a valid Geoid object, geografic coordinates (LON,LAT)
// are used within the MPoint (speed over ground).
void MSpeed( MReal& result, const Geoid* geoid = 0 ) const;
// The vectorial velocity --- (X,Y)-components --- as temporal function
void MVelocity( MPoint& result ) const;
/*
3.10.5.3 Operation ~distance~
If ~geoid~ is NULL, euclidean geometry is used, spherical geometry otherwise.
If invalid geographic coordinates are found, the result is UNDEFINED.
*Precondition:* ~X.IsOrdered()~
*Semantics:*
*Complexity:* $O( n )$, where ~n~ is the number of units of this ~MPoint~
*/
void Distance( const Point& p, MReal& result,
const Geoid* geoid=0 ) const;
// void DistanceAvg(const MPoint& mp, const datetime::DateTime& duration,
// CcReal& result, const Geoid* geoid=0) const;
// double DistanceAvg(const MPoint& mp, const datetime::DateTime& duration,
// const Geoid* geoid = 0) const;
void SquaredDistance( const Point& p, MReal& result,
const Geoid* geoid=0 ) const;
void SquaredDistance( const MPoint& p, MReal& result,
const Geoid* geoid=0 ) const;
/*
3.10.5.4 Operation ~Simplify~
*Precondition*: ~X.IsOrdered()~
*Semantics*: Simplifies the tracjectory this moving point.
*Complexity*: worst case: O(n * n), in average O(n * log (n))
*/
void Simplify(const double epsilon, MPoint& result,
const bool checkBreakPoints,
const datetime::DateTime& duration,
const Geoid* geoid) const;
/*
3.10.5.5 Operation ~BreakPoints~
*Precondition*: ~X.IsOrdered()~
*Semantics*: Computes all points where this mpoints stays longer than the given
time.
*/
void BreakPoints(Points& result, const datetime::DateTime& dur) const;
void BreakPoints(Points& result, const datetime::DateTime& dur,
const CcReal& epsilon,
const Geoid* geoid=0) const;
/*
3.10.5.6 Operatiopn ~Breaks~
This function computes the timeIntervalls for Breaks
*/
void Breaks(Periods& result, const datetime::DateTime& dur,
const CcReal& epsilon,
const Geoid* geoid=0) const;
/*
3.10.5.5 Operation ~Vertices~
This operations stores the ends of the units into a ~points~ value.
*/
void Vertices(Points& result) const;
/*
3.10.5.5 Operation ~gk~
This method performs a gauss krueger projection to that mpoint.
If the coordinates are not in geo range (-180-180, -90-90), the result
will be undefined. The same holds for zone < 0 and zone > 119.
*/
void gk(const int &zone, MPoint& result) const;
/*
3.10.5.6 Operation ~TranslateAppend~
Appends the mpoint argument to this moving point. The point will stay on its
last position for an interval of length dur. If dur is smaller or equals to
zero, the new movement starts directly after the definition time of the
original object. The movement is continued at the last position of this mpoint.
*/
void TranslateAppend(const MPoint& mp, const datetime::DateTime& dur);
/*
3.10.5.7 Reverse
Store the reverse of the movement of this instance of a mpoint into result.
*/
void Reverse(MPoint& result);
/*
3.10.5.7 Direction
Compute the ~direction~ (~useHeading~ is ~false~) resp. ~heading~ (~true~) of a
moving point.
If ~geoid~ is not NULL, spherical geometry is applied. In this case, each unit
may produce several result units, since the true course changes along the
orthodrome. Parameter ~epsilon~ determines how exact the approximation will be.
*/
void Direction( MReal* result,
const bool useHeading = false,
const Geoid* geoid = 0,
const double epsilon = 0.0000001) const;
/*
3.10.5.8 ~Sample~
This operator creates a new mpoint from the original one.
All units will have the length of the duration given as
parameter. The starting time is the same as for the original
mpoint. If gaps longer than the given duration exist,
the next unit will also have the starting time of the unit
directly after the gap.
If __KeepEndPoint__ is set to __true__, the last position will be
part of the resuolt even if at the corresponding time no
sample point exist. If the parameter __exactPath__ is set to
__true__, additional sample points are inserted to be sure that the
path of the object is the same as in the original, i.e. no shortcuts
for corners.
*/
void Sample(const datetime::DateTime& duration, MPoint& result,
const bool KeepEndPoint = false,
const bool exactPath = false )const;
/*
3.10.5.8 ~Append~
The ~Append~ function appends all units of the argument to this
MPoint. If this mpoint or the argument is undefined or if the
argument starts before this mpoint ends, this mpoint will be set
to be undefined. The return value is the defined state of this
mpoint after the operation (indicating the success).
*/
bool Append(const MPoint& p, const bool autoresize = true);
/*
3.10.5.9 ~Disturb~
The ~disturb~ operation changes the position of the moving point
using a random generator.
*/
void Disturb(MPoint& result,
const double maxDerivation,
double maxDerivationPerStep);
/*
3.10.5.10 ~length~
Determines the drive distance of this moving point (odometer).
Coordinates are interpreted as metric (X,Y) coordinates.
Will return a value smaller than zero if this mpoint is not defined
*/
double Length() const;
/*
Determines the drive distance of this moving point (odometer).
Coordinates are interpreted as geographic (LON,LAT) coordinates.
If an invalid geographic coordinate is encountered, ~valid~ is set to false,
otherwise the result is calculated and ~valid~ is set to true.
The same happens, if the Mpoint is undefined. In addition to setting ~valid~ to
false, the return value will be negative.
*/
double Length(const Geoid& g, bool& valid) const;
/*
3.10.5.11 ~BoundingBox~
Returns the MPoint's minimum bounding rectangle. If geoid is NULL, euclidean
geometry is used, otherwise spherical geometry is applied.
*/
// return the stored bbox
Rectangle<3> BoundingBox(const Geoid* geoid = 0) const;
static unsigned GetDim(){ return 3; }
// return the spatial bounding box (2D: X/Y)
const Rectangle<2> BoundingBoxSpatial(const Geoid* geoid = 0) const;
// recompute bbox, if necessary
void RestoreBoundingBox(const bool force = false);
void EqualizeUnitsSpatial(const double epsilon,
MPoint& result,
const bool skipSplit = false) const;
static const std::string BasicType(){ return "mpoint"; }
static const bool checkType(const ListExpr type){
return listutils::isSymbol(type, BasicType());
}
/*
3.10.5.11 ~Delay Operator~
Considering this MPoint instance as the schedule, and a given MPoint as the
actual movement, the goal is to compute the continuous delay between the two
MPoints (i.e. How many seconds is the actual movement delayed from the
schedule).
If ~geoid~ is NULL, euclidean geometry is used, otherwise spherical geometry
using the provided geoid.
If invalid coordinates are found, the result is UNDEFINED.
*/
MReal* DelayOperator(const MPoint *actual, const Geoid* geoid = 0 );
MReal* DistanceTraversed(double*, const Geoid* geoid = 0 ) const;
MReal* DistanceTraversed( const Geoid* geoid = 0 ) const;
/*
3.10.5.11 ~at region~ operators
This operator returns a copy of the mpoint's restriction to a given region
*/
void AtRegion(const Region *reg, MPoint &result) const;
/*
3.10.5.11 ~DistanceStartEnd~ function
Invoked by operator ~hybriddistance~ for a simplified distance computation.
*/
double DistanceStartEnd(const MPoint& p, const int geoDistFun,
const Geoid* geoid = 0) const;
/*
3.10.5.11 ~frechetDistance~ operator (TemporalLiftedAlgebra)
Implements the discrete Frechet distance between two moving points and uses the
auxiliary function getPointSequence.
*/
void getPointSequence(std::vector<Point>& result) const;
double FrechetDistance(const MPoint* mp, const Geoid* geoid = 0) const;
/*
3.10.5.11 ~removeNoise~ operator
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.
*/
void removeNoise(const double maxspeed, const double maxdist,
const Geoid *geoid, MPoint &result) const;
/*
3.10.5.12 Functions ~serialize~ and ~deserialize~
Required for usage in M-tree.
*/
void serialize(size_t &size, char *&bytes) const;
MPoint* deserialize(const char *bytes);
private:
int IntervalRelation(Interval<Instant> &int_a_b,
Interval<Instant> &int_c_d ) const;
double* MergePartitions(double* first, int firstSize,
double* second, int secondSize, int& count );
void Simplify(const int min, const int max,
bool* useleft, bool* useright,
const double epsilon,
const Geoid* geoid) const;
Rectangle<3> bbox;
};
template<class M, class U>
class MappingNoFlob {
public:
MappingNoFlob(const int size);
MappingNoFlob(const M& src);
void SetDefined(const bool def);
bool IsDefined() const;
MappingNoFlob operator=(const M& src);
void Add(const U& unit);
void Get(const int i, U& unit) const;
int GetNoComponents() const;
void ConvertToMapping(M& res) const;
void Reserve(const int size);
void Truncate();
private:
std::vector<U> units;
bool isdefined;
};
template<class M, class U>
std::ostream& operator<<(std::ostream& o, const MappingNoFlob<M, U>& m) {
if (!m.IsDefined()) {
o << "MPointNoFlob, undefined" << endl;
return o;
}
o << "MPointNoFlob, defined, has " << m.GetNoComponents() << " components:"
<< endl;
U unit(true);
for (int i = 0; i < m.GetNoComponents(); i++) {
m.Get(i, unit);
o << unit << endl;
}
o << endl;
return o;
}
template<class M, class U>
MappingNoFlob<M, U>::MappingNoFlob(const int size) {
isdefined = (size > 0);
if (isdefined) {
units.clear();
units.reserve(size);
}
}
template<class M, class U>
MappingNoFlob<M, U>::MappingNoFlob(const M& src) {
*this = src;
}
template<class M, class U>
void MappingNoFlob<M, U>::SetDefined(const bool def) {
isdefined = def;
}
template<class M, class U>
bool MappingNoFlob<M, U>::IsDefined() const {
return isdefined;
}
template<class M, class U>
MappingNoFlob<M, U> MappingNoFlob<M, U>::operator=(const M& src) {
isdefined = src.IsDefined();
if (isdefined) {
units.clear();
units.reserve(src.GetNoComponents());
UPoint unit(true);
for (int i = 0; i < src.GetNoComponents(); i++) {
src.Get(i, unit);
Add(unit);
}
}
return *this;
}
template<class M, class U>
void MappingNoFlob<M, U>::Add(const U& unit) {
units.push_back(unit);
}
template<class M, class U>
void MappingNoFlob<M, U>::Get(const int i, U& unit) const {
assert(i >= 0 && i < GetNoComponents());
unit = units[i];
}
template<class M, class U>
int MappingNoFlob<M, U>::GetNoComponents() const {
return units.size();
}
template<class M, class U>
void MappingNoFlob<M, U>::ConvertToMapping(M& res) const {
res.SetDefined(isdefined);
if (!isdefined) {
return;
}
res.Clear();
res.StartBulkLoad();
for (unsigned int i = 0; i < units.size(); i++) {
res.Add(units[i]);
}
res.EndBulkLoad();
}
template<class M, class U>
void MappingNoFlob<M, U>::Reserve(const int size) {
units.reserve(size);
}
template<class M, class U>
void MappingNoFlob<M, U>::Truncate() {
units.shrink_to_fit();
}
/*
3.10.5 ~ForceToDuration~ function
Force duration of the src mpoint or cmpoint to the given value. This means,
longer instances are pruned and shorter ones are extended (by a constant unit
located at the center of the bounding box). Temporal gaps are also filled by
constant units.
For efficiency reasons, the result is stored in an object without flobs.
*/
template<class M, class U>
void ForceToDuration(const M& src, const datetime::DateTime& duration,
const bool startAtBeginOfTime, MappingNoFlob<M, U>& result,
const Geoid* geoid = 0) {
assert(duration.GetType() == datetime::durationtype);
if (!src.IsDefined()) {
result.SetDefined(false);
return;
}
result.SetDefined(true);
if (src.IsEmpty()) {
return;
}
Instant firstInstant(0.0), beginOfTime(0.0);
src.InitialInstant(firstInstant);
datetime::DateTime diffToBeginOfTime = firstInstant - beginOfTime;
datetime::DateTime durTemp(0, 0, datetime::durationtype);
int i = 0;
U unit(true), unit2(true), unit3(true);
Interval<Instant> iv;
while (i < src.GetNoComponents()) {
src.Get(i, unit);
if (i > 0) {
if (iv.end != unit.timeInterval.start) { // fill temporal gap with const u
unit2.timeInterval = Interval<Instant>(iv.end, unit.timeInterval.start,
!iv.rc, !unit.timeInterval.lc);
unit2.SetToConstantUnit(unit2.p1, 0.0);
durTemp += (unit2.timeInterval.end - unit2.timeInterval.start);
if (durTemp >= duration) { // prune current unit and finish
iv = unit2.timeInterval;
unit2.AtInterval(Interval<Instant>(iv.start,
iv.end - (durTemp - duration), iv.lc, iv.rc), unit3, geoid);
if (startAtBeginOfTime) {
unit3.timeInterval.start -= diffToBeginOfTime;
unit3.timeInterval.end -= diffToBeginOfTime;
}
unit3.SetRadius(0.0);
result.Add(unit3);
result.Truncate();
return;
}
if (startAtBeginOfTime) {
unit2.timeInterval.start -= diffToBeginOfTime;
unit2.timeInterval.end -= diffToBeginOfTime;
}
result.Add(unit2);
}
}
iv = unit.timeInterval;
durTemp += (iv.end - iv.start);
if (durTemp >= duration) { // prune current unit and finish
unit.AtInterval(Interval<Instant>(iv.start, iv.end - (durTemp - duration),
iv.lc, iv.rc), unit2, geoid);
if (startAtBeginOfTime) {
unit2.timeInterval.start -= diffToBeginOfTime;
unit2.timeInterval.end -= diffToBeginOfTime;
}
unit2.SetRadius(unit.GetRadius());
result.Add(unit2);
result.Truncate();
return;
}
else {
if (startAtBeginOfTime) {
unit.timeInterval.start -= diffToBeginOfTime;
unit.timeInterval.end -= diffToBeginOfTime;
}
result.Add(unit);
}
unit2 = unit;
i++;
}
if (durTemp < duration) { // add constant unit at the end
unit.timeInterval = Interval<Instant>(iv.end, iv.end + (duration - durTemp),
!iv.rc, iv.rc);
unit.SetToConstantUnit(unit2.p1, 0.0);
if (startAtBeginOfTime) {
unit.timeInterval.start -= diffToBeginOfTime;
unit.timeInterval.end -= diffToBeginOfTime;
}
result.Add(unit);
}
result.Truncate();
}
template<class M, class U>
void ForceToDuration(const M& src, const datetime::DateTime& duration,
const bool startAtBeginOfTime, M& result,
const Geoid* geoid = 0) {
MappingNoFlob<M, U> res(src.GetNoComponents());
ForceToDuration<M, U>(src, duration, startAtBeginOfTime, res, geoid);
res.ConvertToMapping(result);
}
class CMPoint;
/*
3.8 CUPoint
This class will be used in the ~cupoint~ type constructor, i.e., the type constructor
for the temporal unit of point values together with a radius.
*/
class CUPoint : public UPoint {
/*
3.8.1 Constructors and Destructor
*/
public:
typedef CUPoint unittype;
CUPoint() {};
CUPoint(bool is_defined): UPoint(is_defined) {radius = 0.0;};
CUPoint(const Interval<Instant>& _interval, const double x0, const double y0,
const double x1, const double y1, const double r):
UPoint(_interval, x0, y0, x1, y1), radius(r) {}
CUPoint(const Interval<Instant>& _interval, const Point& _p0,
const Point& _p1, const double _r):
UPoint(_interval, _p0, _p1), radius(_r) {
SetDefined(p0.IsDefined() && p1.IsDefined());
}
CUPoint(const UPoint& _up, const double _r) :
UPoint(_up), radius(_r) {}
CUPoint(const CUPoint& source):
UPoint(source.IsDefined()) {
*((UPoint*)this) = *((UPoint*)&source);
radius = source.radius;
}
/*
3.6.2 Operator redefinitions
*/
virtual CUPoint& operator=(const CUPoint& src) {
UPoint::operator=(src);
radius = src.radius;
return *this;
}
/*
~GetNoComponents~
Returns the constant number 1. This function allows for
templates using UPoint and MPoint.
*/
int GetNoComponents() const {
return 1;
}
/*
~Get~
*/
void Get(const int i, CUPoint& result) const {
assert(i==0);
result = *this;
}
/*
~GetRadius~
*/
double GetRadius() const {
return radius;
}
/*
~SetRadius~
*/
void SetRadius(const double r) {
radius = r;
}
/*
~Set~
*/
void Set(const UPoint& up, const double r) {
UPoint::operator=(up);
radius = r;
}
/*
~GetUPoint~
*/
void GetUPoint(UPoint& result) const {
result = *((UPoint*)this);
}
/*
Redefinition of the copy operator ~=~.
*/
virtual bool operator==(const CUPoint& src) const {
if (!this->IsDefined() && !src.IsDefined()) {
return true;
}
return this->IsDefined() && src.IsDefined()
&& this->timeInterval == src.timeInterval
&& AlmostEqual(p0, src.p0) && AlmostEqual(p1, src.p1)
&& AlmostEqual(radius, src.radius);
}
/*
Returns ~true~ if both units are undefined, or if both are defined and this temporal unit is equal to the temporal unit ~i~ and ~false~ if they are different.
*/
virtual bool operator!=(const CUPoint& src) const {
return !(*this == src);
}
/*
Restricts this cupoint to a certain time interval.
*/
virtual void AtIntervalCU(const Interval<Instant>& i, CUPoint& result) const;
void AtIntervalCU(const Interval<Instant>& i, CUPoint& result,
const Geoid* geoid) const;
/*
Evaluates this cupoint at a certain instant.
*/
virtual void TemporalFunctionCU(const Instant& t, CPoint& result,
bool ignoreLimits = false) const;
/*
Functions required for attribute type
*/
static const std::string BasicType() {
return "c" + UPoint::BasicType();
}
static const bool checkType(const ListExpr type) {
return listutils::isSymbol(type, BasicType());
}
inline virtual size_t Sizeof() const {
return sizeof(*this);
}
inline virtual int Compare(const Attribute* arg) const {
UPoint u1(*this), u2(*((CUPoint*)arg));
int superclassResult = u1.Compare(&u2);
if (superclassResult == 0) {
if (GetRadius() > ((CUPoint*)arg)->GetRadius()) {
return 1;
}
else if (GetRadius() < ((CUPoint*)arg)->GetRadius()) {
return -1;
}
else {
return 0;
}
}
else {
return superclassResult;
}
}
inline virtual bool Adjacent(const Attribute* arg) const {
return ((UPoint*)this)->Adjacent((UPoint*)arg);
}
inline virtual std::ostream& Print(std::ostream &os) const {
if (IsDefined()) {
os << "CUPoint: " << "( ";
timeInterval.Print(os);
os << ", ";
p0.Print(os);
os << ", ";
p1.Print(os);
os << ", " << GetRadius() << " ) ";
return os;
}
else
return os << "CUPoint: (undef) ";
}
inline virtual size_t HashValue() const {
return ((UPoint*)this)->HashValue();
}
inline virtual CUPoint* Clone() const {
CUPoint *res;
if (this->IsDefined()) {
res = new CUPoint(timeInterval, p0, p1, GetRadius());
res->del.isDefined = del.isDefined;
}
else {
res = new CUPoint(false);
// res->timeInterval = Interval<Instant>();
res->p0 = Point(false, 0.0, 0.0);
res->p1 = Point(false, 0.0, 0.0);
res->radius = 0.0;
}
return res;
}
inline virtual void CopyFrom(const Attribute* right) {
// UPoint::CopyFrom(right);
// radius = ((CUPoint*)right)->GetRadius();
*this = *((CUPoint*)right);
}
virtual const Rectangle<3> BoundingBox(const Geoid* geoid = 0) const;
static unsigned GetDim() {
return (UPoint::GetDim());
}
virtual const Rectangle<3> BoundingBox(const double scaleTime,
const Geoid* geoid = 0) const;
const Rectangle<2> BoundingBoxSpatial(const Geoid* geoid = 0) const;
static double GetToleranceFactor();
/*
Transforms a UPoint into a CUPoint.
*/
void ConvertFrom(const UPoint& up, const Geoid* geoid = 0);
/*
Transforms an MPoint into a CUPoint.
*/
void ConvertFrom(const MPoint& mp, const Geoid* geoid = 0);
/*
Transforms a CMPoint into a CUPoint, adopting the CMPoint's maximum radius.
*/
void ConvertFrom(const CMPoint& cmp, const Geoid* geoid = 0);
/*
Computes the distance to another CUPoint ~cup~.
*/
void Split(const datetime::DateTime& duration, std::vector<CUPoint>& result)
const;
using UPoint::Distance;
double DistanceStartEnd(const CUPoint& cup, const Geoid* geoid = 0);
double DistanceIntegral(const CUPoint& cup, const bool upperBound,
const Geoid* geoid = 0) const;
double DistanceAvg(const CUPoint& cup, const datetime::DateTime& duration,
const bool upperBound, const Geoid* geoid = 0) const;
void DistanceAvg(const CUPoint& cup, const datetime::DateTime& duration,
const bool upperBound, CcReal& result, const Geoid* geoid = 0) const;
void SetToConstantUnit(const Point& p, const double r);
private:
double radius;
};
std::ostream& operator<<(std::ostream& o, const CUPoint& u);
/*
3.12 Class ~CMPoint~
An instance of this class is a sequence of ~CUPoint~ values.
*/
class CMPoint : public Mapping<CUPoint, CPoint> {
public:
/*
3.12.1 Constructors and Destructor
The simple constructor. This constructor should not be used.
*/
CMPoint() {}
/*
The constructor. Initializes space for ~n~ elements.
*/
CMPoint(const int n): Mapping<CUPoint, CPoint>(n) {
del.refs=1;
del.SetDelete();
del.isDefined = true;
bbox = Rectangle<3>(false);
}
CMPoint(const CMPoint& src): Mapping<CUPoint, CPoint>(1) {
SetDefined(src.IsDefined());
if (IsDefined()) {
StartBulkLoad();
CUPoint unit(true);
for (int i = 0; i < src.GetNoComponents(); i++) {
src.Get(i, unit);
Add(unit);
}
EndBulkLoad(false);
bbox = src.BoundingBox();
}
}
virtual Attribute* Clone() const {
assert(IsOrdered());
CMPoint *result;
if (!this->IsDefined()) {
result = new CMPoint(0);
}
else {
result = new CMPoint(GetNoComponents());
if (GetNoComponents() > 0) {
result->units.resize(GetNoComponents());
}
result->StartBulkLoad();
CUPoint unit;
for (int i = 0; i < GetNoComponents(); i++) {
Get(i, unit);
result->Add(unit);
}
result->EndBulkLoad(false);
}
result->SetDefined(this->IsDefined());
return (Attribute*)result;
}
void CopyFrom(const Attribute* right) {
const CMPoint *r = (const CMPoint*)right;
assert(r->IsOrdered());
Clear();
this->SetDefined(r->IsDefined());
if (!this->IsDefined()) {
return;
}
StartBulkLoad();
CUPoint unit;
for(int i = 0; i < r->GetNoComponents(); i++) {
r->Get(i, unit);
Add(unit);
}
EndBulkLoad(false);
}
/*
Extracts the ~mpoint~ information from a ~cmpoint~.
*/
void GetMPoint(MPoint& result) const;
/*
Extracts the ~upoint~ information at a given position.
*/
void GetUPoint(const int pos, UPoint& result) const;
/*
Converts an ~mpoint~ into a ~cmpoint~ with a constant cylinder length (duration)
*/
void ConvertFrom(const MPoint& src, const datetime::DateTime dur,
const Geoid *geoid = 0);
/*
Converts an ~mpoint~ into a ~cmpoint~; a new unit starts as soon as the
specified threshold is exceeded.
*/
void ConvertFrom(const MPoint& src, const CcReal& threshold,
const Geoid *geoid = 0);
/*
3.12.2 Modifications of Inherited Functions
Overwrites the function defined in Mapping, mostly in order to
maintain the object's bounding box. Also, some methods can be improved
using a check on bbox.
*/
void Clear();
void Add(const CUPoint& unit);
void MergeAdd(const CUPoint& unit);
bool EndBulkLoad(const bool sort = true, const bool checkvalid = false);
void Restrict(const std::vector<std::pair<int, int> >& intervals);
std::ostream& Print(std::ostream &os) const;
bool operator==(const CMPoint& r) const;
bool Present(const Instant& t) const;
bool Present(const Periods& t) const;
void AtInstant(const Instant& t, Intime<CPoint>& result) const;
void AtPeriods(const Periods& p, CMPoint& result) const;
void AtRect(const Rectangle<2>& rect, CMPoint& result) const;
void AtRegion(const Region *reg, CMPoint &result) const;
/*
3.10.5.3 Operation ~trajectory~
*Precondition:* ~X.IsOrdered()~
*Semantics:*
*Complexity:* $O( n )$, where ~n~ is the number of units of this ~MPoint~
*/
void Trajectory(Line& line) const;
// The scalar velocity as a temporal function
// If geoid = 0, metric (X.Y)-coordinates are used within the MPoint.
// If geoid points to a valid Geoid object, geografic coordinates (LON,LAT)
// are used within the MPoint (speed over ground).
void MSpeed(MReal& result, const Geoid* geoid = 0) const;
// The vectorial velocity --- (X,Y)-components --- as temporal function
void MVelocity(MPoint& result) const;
/*
3.10.5.3 Operation ~distance~
If ~geoid~ is NULL, euclidean geometry is used, spherical geometry otherwise.
If invalid geographic coordinates are found, the result is UNDEFINED.
*Precondition:* ~X.IsOrdered()~
*Semantics:*
*Complexity:* $O( n )$, where ~n~ is the number of units of this ~CMPoint~
*/
// void Distance(const CPoint& p, MReal& result, const Geoid* geoid = 0) const;
// double DistanceAvg(const CMPoint& cmp, const bool upperBound,
// const Geoid* geoid = 0) const;
// void DistanceAvg(const CMPoint& cmp, const bool upperBound,
// CcReal& result, const Geoid* geoid = 0) const;
/*
3.10.5.6 Operatiopn ~Breaks~
This function computes the timeIntervals for Breaks
*/
// void Breaks(Periods& result, const datetime::DateTime& dur,
// const CcReal& epsilon, const Geoid* geoid= 0 ) const;
/*
3.10.5.7 Direction
Compute the ~direction~ (~useHeading~ is ~false~) resp. ~heading~ (~true~) of a
moving point.
If ~geoid~ is not NULL, spherical geometry is applied. In this case, each unit
may produce several result units, since the true course changes along the
orthodrome. Parameter ~epsilon~ determines how exact the approximation will be.
*/
void Direction(MReal* result,
const bool useHeading = false,
const Geoid* geoid = 0,
const double epsilon = 0.0000001) const;
/*
3.10.5.8 ~Append~
The ~Append~ function appends all units of the argument to this
CMPoint. If this cmpoint or the argument is undefined or if the
argument starts before this cmpoint ends, this cmpoint will be set
to undefined. The return value is the defined state of this
cmpoint after the operation (indicating the success).
*/
bool Append(const CMPoint& p, const bool autoresize = true);
/*
3.10.5.10 ~length~
Determines the drive distance of this cmpoint (odometer).
Coordinates are interpreted as metric (X,Y) coordinates.
Will return a value smaller than zero if this cmpoint is not defined
*/
double Length() const;
/*
Determines the drive distance of this cmpoint (odometer).
Coordinates are interpreted as geographic (LON,LAT) coordinates.
If an invalid geographic coordinate is encountered, ~valid~ is set to false,
otherwise the result is calculated and ~valid~ is set to true.
The same happens, if the cmpoint is undefined. In addition to setting ~valid~ to
false, the return value will be negative.
*/
double Length(const Geoid& g, bool& valid) const;
/*
3.10.5.11 ~BoundingBox~
Returns the cmpoint's minimum bounding rectangle. If geoid is NULL, euclidean
geometry is used, otherwise spherical geometry is applied.
*/
Rectangle<3> BoundingBox(const Geoid* geoid = 0) const;
static unsigned GetDim() {return 3;}
const Rectangle<2> BoundingBoxSpatial(const Geoid* geoid = 0) const;
// recompute bbox, if necessary
void RestoreBoundingBox(const bool force, const Geoid* geoid = 0);
void GetRadii(MReal& result) const;
static const std::string BasicType() {return "cmpoint";}
static const bool checkType(const ListExpr type) {
return listutils::isSymbol(type, BasicType());
}
/*
3.10.5.11 ~frechetDistance~ operator (TemporalLiftedAlgebra)
Implements the discrete Frechet distance between two moving points and uses the
auxiliary function getPointSequence.
*/
// void getPointSequence(std::vector<Point>& result) const;
// double FrechetDistance(const MPoint* mp, const Geoid* geoid = 0) const;
private:
Rectangle<3> bbox;
};
/*
4 Implementation of C++ Classes
4.1 Interval
4.1.1 Constructors and Destructor
*/
template <class Alpha>
Interval<Alpha>::Interval( const Interval<Alpha>& interval ):
start(interval.start),
end(interval.end),
lc( interval.lc ),
rc( interval.rc )
{
}
template <class Alpha>
Interval<Alpha>::Interval( const Alpha& start1, const Alpha& end1,
const bool lc1, const bool rc1 ):
start(start1),
end(end1),
lc( lc1 ),
rc( rc1 )
{
// assert(IsValid());
}
template <class Alpha>
void Interval<Alpha>::CopyFrom( const Interval<Alpha>& i )
{
start.CopyFrom( &i.start );
end.CopyFrom( &i.end );
lc = i.lc;
rc = i.rc;
}
template <class Alpha>
bool Interval<Alpha>::IsValid() const
{
if( !start.IsDefined() || !end.IsDefined() ){
return false;
}
int cmp = start.Compare( &end );
if( cmp < 0 ) // start < end
{
return true;
}
else if( cmp == 0 ) // start == end
{
return rc && lc;
}
// start > end
return false;
}
/*
4.1.2 Member functions
*/
template <class Alpha>
Interval<Alpha>& Interval<Alpha>::operator=( const Interval<Alpha>& i )
{
assert( i.IsValid() );
start.CopyFrom( &i.start );
end.CopyFrom( &i.end );
lc = i.lc;
rc = i.rc;
return *this;
}
template <class Alpha>
bool Interval<Alpha>::operator==( const Interval<Alpha>& i ) const
{
assert( IsValid() && i.IsValid() );
return( ( start.Compare( &i.start ) == 0 && lc == i.lc &&
end.Compare( &i.end ) == 0 && rc == i.rc ) ||
( start.Compare( &i.start ) == 0 && lc == i.lc &&
end.Compare( &i.end ) != 0 &&
end.Adjacent( &i.end ) && ( !rc || !i.rc ) ) ||
( end.Compare( &i.end ) == 0 && rc == i.rc &&
start.Compare( &i.start ) != 0 && start.Adjacent( &i.start ) &&
( !lc || !i.lc ) ) ||
( start.Compare( &i.start ) != 0 && start.Adjacent( &i.start )
&& (!lc || !i.lc) &&
end.Compare( &i.end ) != 0 && end.Adjacent( &i.end ) &&
( !rc || !i.rc ) ) );
}
template <class Alpha>
bool Interval<Alpha>::operator!=( const Interval<Alpha>& i ) const
{
return !( *this == i );
}
template <class Alpha>
bool Interval<Alpha>::operator<( const Interval<Alpha>& i ) const
{
return CompareTo(i) <0;
}
template <class Alpha>
bool Interval<Alpha>::operator>( const Interval<Alpha>& i ) const
{
return CompareTo(i) >0;
}
template <class Alpha>
bool Interval<Alpha>::R_Disjoint( const Interval<Alpha>& i ) const
{
bool res= ((end.Compare( &i.start ) < 0) ||
( (end.Compare( &i.start ) == 0) && !( rc && i.lc ) ));
return( res );
}
template <class Alpha>
bool Interval<Alpha>::Disjoint( const Interval<Alpha>& i ) const
{
assert( IsValid() && i.IsValid() );
bool res=( R_Disjoint( i ) || i.R_Disjoint( *this ) );
return( res );
}
template <class Alpha>
bool Interval<Alpha>::R_Adjacent( const Interval<Alpha>& i ) const
{
bool res=( (Disjoint( i ) &&
( end.Compare( &i.start ) == 0 && (rc || i.lc) )) ||
( ( end.Compare( &i.start ) < 0 && rc && i.lc ) &&
end.Adjacent( &i.start ) ) );
return( res );
}
template <class Alpha>
bool Interval<Alpha>::Adjacent( const Interval<Alpha>& i ) const
{
assert( IsValid() && i.IsValid() );
bool res= ( R_Adjacent( i ) || i.R_Adjacent( *this ) );
return( res );
}
template <class Alpha>
bool Interval<Alpha>::Inside( const Interval<Alpha>& i ) const
{
assert( IsValid() && i.IsValid() );
return( ( start.Compare( &i.start ) > 0 ||
( start.Compare( &i.start ) == 0 && ( !lc || i.lc ) ) ) &&
( end.Compare( &i.end ) < 0 ||
( end.Compare( &i.end ) == 0 && ( !rc || i.rc ) ) ) );
}
template <class Alpha>
bool Interval<Alpha>::Contains( const Alpha& a,
const bool ignoreCloseness /* = false */ ) const
{
assert(this->IsValid());
assert(a.IsDefined());
bool lc = this->lc || ignoreCloseness;
bool rc = this->rc || ignoreCloseness;
return ( ( start.Compare( &a ) < 0 ||
( start.Compare( &a ) == 0 && lc ) ) &&
( end.Compare( &a ) > 0 ||
( end.Compare( &a ) == 0 && rc ) ) );
}
template <class Alpha>
bool Interval<Alpha>::Contains( const Interval<Alpha>& i,
const bool ignoreCloseness /* = false */ ) const
{
int cmp1 = start.CompareTo(&(i.start));
int cmp2 = end.CompareTo(&(i.end));
if(cmp1>0) { // i starts before this
return false;
}
if((cmp1==0) && !lc && i.lc && !ignoreCloseness){ // i starts before this
return false;
}
// start is ok
if(cmp2<0){ // this ends before i
return false;
}
if(cmp2==0 && !rc && i.rc && !ignoreCloseness){
return false;
}
return true;
}
template <class Alpha>
bool Interval<Alpha>::Intersects( const Interval<Alpha>& i ) const
{
assert( this->IsValid());
assert( i.IsValid() );
return !( (start.Compare(&i.end) > 0 ) ||
((start.Compare(&i.end) == 0) && ( !lc || !i.rc)) ||
(end.Compare(&i.start) < 0 ) ||
((end.Compare(&i.start) == 0 ) && (!rc || !i.lc))
);
}
template <class Alpha>
bool Interval<Alpha>::StartsBefore( const Interval<Alpha>& i ) const
{
assert( IsValid() && i.IsValid() );
return ( (start < i.start) || ( (start == i.start) && lc && !i.lc ));
}
template <class Alpha>
bool Interval<Alpha>::EndsAfter( const Interval<Alpha>& i ) const
{
assert( IsValid() && i.IsValid() );
return ( end > i.end || ( (end == i.end) && rc && !i.rc ));
}
template <class Alpha>
bool Interval<Alpha>::Before( const Interval<Alpha>& i ) const
{
assert( IsValid() && i.IsValid() );
if( Before( i.start ) )
return true;
return end.Compare( &i.start ) == 0 && i.lc == false;
}
template <class Alpha>
bool Interval<Alpha>::Before( const Alpha& a ) const
{
assert( IsValid() && a.IsDefined() );
return ( end.Compare( &a ) < 0 ||
( end.Compare( &a ) == 0 && rc == false ) );
}
template <class Alpha>
bool Interval<Alpha>::After( const Alpha& a ) const
{
assert( IsValid() && a.IsDefined() );
return ( start.Compare( &a ) > 0 ||
( start.Compare( &a ) == 0 && lc == false ) );
}
template <class Alpha>
bool Interval<Alpha>::After( const Interval<Alpha>& iv ) const
{
assert( IsValid() && iv.IsValid() );
return (iv.end < start) ||
((iv.end == start) && (!iv.rc || !lc));
}
template <class Alpha>
void Interval<Alpha>::Intersection( const Interval<Alpha>& i,
Interval<Alpha>& result ) const
{
assert( IsValid() && i.IsValid() );
assert( Intersects( i ) );
if( Inside( i ) )
{
result = *this;
}
else if( i.Inside( *this ) )
{
result = i;
}
else
{ // Normal intersection
int comp = start.Compare( &i.start );
if( comp < 0 )
{ // this starts smaller
result.start.CopyFrom( &i.start );
result.lc = i.lc;
}
else if( comp == 0 )
{ // equal start
result.start.CopyFrom( &i.start );
result.lc = (lc && i.lc);
}
else
{ // i starts smaller
result.start.CopyFrom( &start );
result.lc = lc;
}
comp = end.Compare( &i.end );
if( comp > 0 )
{ // i ends smaller
result.end.CopyFrom( &i.end );
result.rc = i.rc;
}
else if( comp == 0 )
{ // equal end
result.end.CopyFrom( &i.end );
result.rc = (rc && i.rc);
}
else
{ // this ends smaller
result.end.CopyFrom( &this->end );
result.rc = rc;
}
}
}
template<class Alpha>
void Interval<Alpha>::IntersectionWith( const Interval<Alpha>& i){
assert(this->IsValid());
assert(i.IsValid());
assert(this->Intersects(i));
if(start < i.start){
start = i.start;
lc = i.lc;
}else if(start==i.start){
lc = lc && i.lc;
}
if(i.end < end){
end = i.end;
rc = i.rc;
} else if(end == i.end){
rc = rc && i.rc;
}
}
template<class Alpha>
void Interval<Alpha>::Union(const Interval<Alpha>& iv,
Interval<Alpha> result) const{
// set start
if(start<iv.start){
result.start = start;
result.lc = lc;
} else if(start > iv.start){
result.start = iv.start;
result.lc = iv.lc;
} else { // start == iv.start
result.start = start;
result.lc = lc || iv.lc;
}
// set end
if(end>iv.end){
result.end = end;
result.rc = rc;
} else if(end<iv.end){
result.end = iv.end;
result.rc = iv.rc;
} else {
result.end = end;
result.rc = rc || iv.rc;
}
}
template<class Alpha>
void Interval<Alpha>::Union(const Interval<Alpha>& iv) {
if(iv.start < this->start){
this->start = iv.start;
this->lc = iv.lc;
} else if(iv.start == this->start){
this->lc = this->lc || iv.lc;
}
if(this->end < iv.end){
this->end = iv.end;
this->rc = iv.rc;
} else if(iv.end == this->end){
this->rc = this->rc || iv.rc;
}
}
template<class Alpha>
int Interval<Alpha>::Minus(const Interval<Alpha>& iv,
Interval<Alpha>& res1,
Interval<Alpha>& res2){
if(iv.Before(*this)){
res1 = *this;
return 1;
}
if(iv.After(*this)){
res1=*this;
return 1;
}
int no = 0;
// check for an interval left of iv
if( (start < iv.start) || ((start==iv.start) && lc && !iv.lc)){
no++;
res1 = *this;
if(end > iv.start){
res1.end = iv.start;
res1.rc = !iv.lc;
} else if(end == iv.start){
res1.rc = rc && !iv.lc;
}
}
// check for an remaining interval right of iv
if( (end > iv.end) || ((end==iv.end) && rc && !iv.rc)){
no++;
Interval<Alpha>
res = *this;
if(start < iv.end){
res.start = iv.end;
res.lc = !iv.rc;
} else if(start == iv.end) {
res.lc = lc && !iv.rc;
}
if(no==1){
res1 = res;
} else {
res2 = res;
}
}
return no;
}
template <class Alpha>
int Interval<Alpha>::CompareTo( const Interval<Alpha>& i) const{
int cmp = start.Compare( &(i.start) );
if( cmp != 0 ){
return cmp;
}
if(!lc && i.lc){
return 1;
}
if(lc && !i.lc){
return -1;
}
cmp = end.Compare( &(i.end) );
if( cmp != 0 ){
return cmp;
}
if(rc && !i.rc){
return 1;
}
if(!rc && i.rc){
return -1;
}
return 0;
}
/*
4.2 Range
4.2.1 Constructors and destructor
*/
template <class Alpha>
Range<Alpha>::Range( const int n ):
Attribute(true),
canDestroy( false ),
ordered( true ),
intervals( n )
{
del.refs=1;
del.SetDelete();
del.isDefined=true;
}
template<class Alpha>
Range<Alpha>::Range(const Range<Alpha>& src):
Attribute(src),
canDestroy(false),
ordered(src.ordered),
intervals(src.intervals.Size()){
intervals.copyFrom(src.intervals);
}
template <class Alpha>
void Range<Alpha>::Destroy()
{
canDestroy = true;
}
template <class Alpha>
Range<Alpha>::~Range()
{
if( canDestroy )
intervals.Destroy();
}
/*
4.2.2 Member functions
*/
template <class Alpha>
bool Range<Alpha>::IsOrdered() const
{
return ordered;
}
template <class Alpha>
void Range<Alpha>::StartBulkLoad()
{
assert( IsDefined() );
assert( ordered );
ordered = false;
}
template <class Alpha>
int IntervalCompare( const void *a, const void *b )
{
Interval<Alpha> *inta = new ((void*)a) Interval<Alpha>,
*intb = new ((void*)b) Interval<Alpha>;
if( *inta == *intb )
return 0;
else if( inta->Before( *intb ) )
return -1;
else
return 1;
}
template <class Alpha>
bool Range<Alpha>::EndBulkLoad( const bool sort, const bool checkvalid )
{
assert( IsDefined() );
assert( !ordered );
if( !IsDefined() ){
intervals.clean();
} else if( sort ){
intervals.Sort( IntervalCompare<Alpha> );
}
ordered = true;
intervals.TrimToSize();
if(checkvalid && !IsValid()){
intervals.clean();
SetDefined(false);
return false;
}
return true;
}
template <class Alpha>
bool Range<Alpha>::IsEmpty() const
{
return !IsDefined() || (intervals.Size() == 0);
}
template <class Alpha>
void Range<Alpha>::Get( const int i, Interval<Alpha> &interval ) const
{
assert( IsDefined() );
assert(i>=0);
assert(i<intervals.Size());
intervals.Get( i, &interval );
assert( interval.IsValid() );
}
template <class Alpha>
void Range<Alpha>::Add( const Interval<Alpha>& interval )
{
assert( IsDefined() );
assert( interval.IsValid() );
intervals.Append( interval );
}
template<class Alpha>
void Range<Alpha>::MergeAdd(const Interval<Alpha>& interval){
assert(IsDefined());
assert(interval.IsValid());
if(intervals.Size()==0){
intervals.Append(interval);
} else {
Interval<Alpha> last;
intervals.Get(intervals.Size()-1, last);
if (last.Adjacent(interval)){
last.end = interval.end;
last.rc = interval.rc;
intervals.Put(intervals.Size()-1, last);
}
else if (last.Intersects(interval)) {
last.end = std::max(last.end, interval.end);
last.rc = std::max(last.rc, interval.rc);
intervals.Put(intervals.Size() - 1, last);
}
else {
intervals.Append(interval);
}
}
}
template <class Alpha>
void Range<Alpha>::Clear()
{
ordered = true;
intervals.clean();
}
/*
4.2.3 Functions to be part of relations
*/
template <class Alpha>
inline size_t Range<Alpha>::Sizeof() const
{
return sizeof( *this );
}
template <class Alpha>
inline int Range<Alpha>::Compare( const Attribute* arg ) const
{
// return 0; // Original implementation
Range<Alpha>* other = (Range<Alpha>*) arg;
if (!IsDefined() && !other->IsDefined())
return 0;
if (!IsDefined())
return -1;
if (!other->IsDefined())
return 1;
int cmp = 0;
Interval<Alpha> my_interval, other_interval;
int maxindex = MIN(GetNoComponents(),other->GetNoComponents());
for( int i = 0; i < maxindex; i++ )
{
Get( i, my_interval );
other->Get( i, other_interval );
cmp = my_interval.CompareTo(other_interval);
if ( cmp != 0 )
return cmp;
}
if ( GetNoComponents() < other->GetNoComponents() )
return -1;
if ( GetNoComponents() > other->GetNoComponents() )
return 1;
return 0;
}
template <class Alpha>
inline bool Range<Alpha>::Adjacent( const Attribute* arg ) const
{
return false;
}
template <class Alpha>
inline Range<Alpha>* Range<Alpha>::Clone() const
{
Range *result;
if( !this->IsDefined() ){
result = new Range( 0 );
result->del.isDefined = false;
} else {
assert( IsOrdered() );
result = new Range( GetNoComponents() );
result->del.isDefined = this->del.isDefined;
result->StartBulkLoad();
Interval<Alpha> interval;
for( int i = 0; i < GetNoComponents(); i++ )
{
Get( i, interval );
result->Add( interval );
}
result->EndBulkLoad( false );
}
return result;
}
template <class Alpha>
inline std::ostream& Range<Alpha>::Print( std::ostream &os ) const
{
os << Range<Alpha>::BasicType()<<": ";
if( !IsDefined() ){
os << "UNDEFINED.";
} else {
os << " defined, contains " << GetNoComponents()
<< " intervals: [" << std::endl;
Interval<Alpha> interval;
for( int i = 0; i < GetNoComponents(); i++ )
{
Get( i, interval );
os << "\t"; interval.Print( os ); os << std::endl;
}
os << "]." << std::endl;
}
return os << std::endl;
}
template <class Alpha>
inline size_t Range<Alpha>::HashValue() const
{
if(!IsDefined()){
return 0;
}
Interval<Alpha> min, max;
intervals.Get(0,&min);
intervals.Get(GetNoComponents()-1,&max);
return static_cast<size_t>( min.start.HashValue()
^ max.end.HashValue() ) ;
return 0;
}
template <class Alpha>
inline void Range<Alpha>::CopyFrom( const Attribute* right )
{
Clear();
const Range<Alpha> *r = (const Range<Alpha>*)right;
this->SetDefined(r->IsDefined());
if(r->IsDefined()){
assert( r->IsOrdered() );
StartBulkLoad();
Interval<Alpha> interval;
for( int i = 0; i < r->GetNoComponents(); i++ ){
r->Get( i, interval );
Add( interval );
}
EndBulkLoad( false );
}
}
template <class Alpha>
inline int Range<Alpha>::NumOfFLOBs() const
{
return 1;
}
template <class Alpha>
inline Flob *Range<Alpha>::GetFLOB(const int i)
{
assert( i == 0 );
return &intervals;
}
/*
4.2.4 Operator functions
*/
template <class Alpha>
bool Range<Alpha>::operator==( const Range<Alpha>& r ) const
{
assert( IsValid() && r.IsValid() );
if( !this->IsDefined() && !r.IsDefined() ) {
return true;
}
if( !this->IsDefined() || !r.IsDefined() ) {
return false;
}
if( GetNoComponents() != r.GetNoComponents() )
return false;
bool result = true;
Interval<Alpha> thisInterval, interval;
for( int i = 0; i < GetNoComponents(); i++ )
{
Get( i, thisInterval );
r.Get( i, interval );
if( thisInterval != interval )
{
result = false;
break;
}
}
return result;
}
template <class Alpha>
bool Range<Alpha>::operator!=( const Range<Alpha>& r ) const
{
return !( *this == r );
}
template <class Alpha>
bool Range<Alpha>::Intersects( const Range<Alpha>& r ) const
{
assert( IsDefined() );
assert( IsValid() );
assert( r.IsDefined() );
assert( r.IsValid() );
if( IsEmpty() || r.IsEmpty() )
return false;
bool result = false;
Interval<Alpha> thisInterval, interval;
int i = 0, j = 0;
Get( i, thisInterval );
r.Get( j, interval );
while( 1 )
{
if( thisInterval.Intersects( interval ) )
{
result = true;
break;
}
if( thisInterval.Before( interval ) )
{
if( ++i == GetNoComponents() )
{
result = false;
break;
}
Get( i, thisInterval );
}
if( interval.Before( thisInterval ) )
{
if( ++j == r.GetNoComponents() )
{
result = false;
break;
}
r.Get( j, interval );
}
}
return result;
}
template <class Alpha>
bool Range<Alpha>::Intersects( const Interval<Alpha>& iv ) const
{
if(!IsDefined() || IsEmpty()){
return false;
}
// TODO: Use binary search to accelerate computations
Interval<Alpha> this_iv;
for(int i=0;i<GetNoComponents();i++){
Get(i,this_iv);
if(iv.Intersects(this_iv)){
return true;
}
}
return false;
}
template <class Alpha>
bool Range<Alpha>::Inside( const Range<Alpha>& r ) const
{
assert( IsDefined() );
assert( IsValid() );
assert( r.IsDefined() );
assert( r.IsValid() );
if( IsEmpty() ) return true;
if( r.IsEmpty() ) return false;
bool result = true;
Interval<Alpha> thisInterval, interval;
int i = 0, j = 0;
Get( i, thisInterval );
r.Get( j, interval );
while( 1 )
{
if( interval.Before( thisInterval ) )
{
if( ++j == r.GetNoComponents() )
{
result = false;
break;
}
r.Get( j, interval );
}
else if( thisInterval.Inside( interval ) )
{
if( ++i == GetNoComponents() )
{
break;
}
Get( i, thisInterval );
}
else if( thisInterval.Before( interval ) )
{
result = false;
break;
}
else
{
// Intersects but not inside.
result = false;
break;
}
}
return result;
}
template <class Alpha>
bool Range<Alpha>::Inside( const Interval<Alpha>& iv ) const
{
if(IsEmpty()){
return true;
}
Interval<Alpha> first;
Interval<Alpha> last;
Get(0,first);
Get(GetNoComponents()-1,last);
return iv.Contains(first) && iv.Contains(last);
}
/*
Returns the index of the interval containing a, or -1 if not found
*/
template<class Alpha>
int Range<Alpha>::GetIndexOf(const Alpha& alpha,
const bool ignoreCloseness /* = false */) const{
assert( IsDefined() );
assert( IsValid() );
assert( alpha.IsDefined() );
if( IsEmpty() ){
return -1;
}
Interval<Alpha> midInterval;
int first = 0;
int last = GetNoComponents() - 1;
while (first <= last)
{
int mid = ( first + last ) / 2;
Get( mid, midInterval );
if( midInterval.Contains( alpha, ignoreCloseness ) )
{
return mid;
} else if( midInterval.Before( alpha ) ){
first = mid + 1;
} else if( midInterval.After( alpha ) ) {
last = mid - 1;
} else {
return mid;
}
}
return -1;
}
template <class Alpha>
bool Range<Alpha>::Contains( const Alpha& a ) const
{
return GetIndexOf(a) >=0;
}
template<class Alpha>
bool Range<Alpha>::Contains(const Interval<Alpha>& iv,
const bool ignoreCloseness /* = false */) const {
int index = GetIndexOf(iv.start, ignoreCloseness);
if(index < 0){
return false;
}
Interval<Alpha> miv;
Get(index,miv);
return miv.Contains(iv, ignoreCloseness);
}
template <class Alpha>
bool Range<Alpha>::Before( const Range<Alpha>& r ) const
{
assert( IsDefined() );
assert( IsValid() );
assert( !IsEmpty() );
assert( r.IsDefined() );
assert( r.IsValid() );
assert( !r.IsEmpty() );
Interval<Alpha> thisInterval, interval;
Get( GetNoComponents() - 1, thisInterval );
r.Get( 0, interval );
return thisInterval.Before( interval );
}
template <class Alpha>
bool Range<Alpha>::Before( const Interval<Alpha>& iv ) const
{
if(IsEmpty()){
return false;
}
Interval<Alpha> last;
Get(GetNoComponents()-1,last);
return last.Before(iv);
}
template <class Alpha>
bool Range<Alpha>::Before( const Alpha& a ) const
{
assert( IsDefined() );
assert( IsValid() );
assert( !IsEmpty() );
assert( a.IsDefined() );
Interval<Alpha> thisInterval;
Get( GetNoComponents() - 1, thisInterval );
return thisInterval.Before( a );
}
template <class Alpha>
bool Range<Alpha>::After( const Alpha& a ) const
{
assert( IsDefined() );
assert( IsValid() );
assert( !IsEmpty() );
assert( a.IsDefined() );
Interval<Alpha> thisInterval;
Get( 0, thisInterval );
return thisInterval.After( a );
}
template <class Alpha>
void Range<Alpha>::Intersection( const Range<Alpha>& r,
Range<Alpha>& result ) const
{
assert( IsValid() );
assert( r.IsValid() );
result.Clear();
if( !IsDefined() || !r.IsDefined() ){
result.SetDefined( false );
return;
}
result.SetDefined( true );
if( (GetNoComponents()==0) || (r.GetNoComponents()==0)){
return;
}
Interval<Alpha> thisInterval, interval;
int i = 0, j = 0;
Get( i, thisInterval );
r.Get( j, interval );
result.StartBulkLoad();
while( i < GetNoComponents() && j < r.GetNoComponents() )
{
if( thisInterval.start.Compare( &interval.start ) == 0 &&
thisInterval.end.Compare( &interval.end ) == 0 )
{
Interval<Alpha> newInterval( thisInterval.start, thisInterval.end,
thisInterval.lc && interval.lc,
thisInterval.rc && interval.rc );
if( newInterval.IsValid() )
result.Add( newInterval );
if( ++i < GetNoComponents() )
Get( i, thisInterval );
if( ++j < r.GetNoComponents() )
r.Get( j, interval );
}
else if( thisInterval.Inside( interval ) )
{
Interval<Alpha> newInterval( thisInterval );
if( newInterval.IsValid() )
result.Add( newInterval );
if( ++i < GetNoComponents() )
Get( i, thisInterval );
}
else if( interval.Inside( thisInterval ) )
{
Interval<Alpha> newInterval( interval );
if( newInterval.IsValid() )
result.Add( newInterval );
if( ++j < r.GetNoComponents() )
r.Get( j, interval );
}
else if( thisInterval.Intersects( interval ) )
{
if( thisInterval.start.Compare( &interval.end ) == 0 &&
thisInterval.lc && interval.rc )
{
Interval<Alpha> newInterval( interval.end, interval.end, true, true );
result.Add( newInterval );
if( ++j < r.GetNoComponents() )
r.Get( j, interval );
}
else if( thisInterval.end.Compare( &interval.start ) == 0 &&
thisInterval.rc && interval.lc )
{
Interval<Alpha> newInterval( interval.start,
interval.start, true, true );
result.Add( newInterval );
if( ++i < GetNoComponents() )
Get( i, thisInterval );
}
else if( thisInterval.start.Compare( &interval.start ) < 0 )
{
Interval<Alpha> newInterval( interval.start,
thisInterval.end,
interval.lc, thisInterval.rc );
if( newInterval.IsValid() )
result.Add( newInterval );
if( ++i < GetNoComponents() )
Get( i, thisInterval );
}
else if( thisInterval.start.Compare( &interval.start ) == 0 )
{
assert( !thisInterval.lc || !interval.lc );
if( thisInterval.end.Compare( &interval.end ) > 0 )
{
Interval<Alpha> newInterval( interval.start,
interval.end,
interval.lc && thisInterval.lc,
interval.rc );
if( newInterval.IsValid() )
result.Add( newInterval );
if( ++j < r.GetNoComponents() )
r.Get( j, interval );
}
else
{
assert( thisInterval.end.Compare( &interval.end ) < 0 );
Interval<Alpha> newInterval( thisInterval.start,
thisInterval.end,
interval.lc && thisInterval.lc,
thisInterval.rc );
if( newInterval.IsValid() )
result.Add( newInterval );
if( ++i < GetNoComponents() )
Get( i, thisInterval );
}
}
else
{
Interval<Alpha> newInterval( thisInterval.start,
interval.end,
thisInterval.lc, interval.rc );
if( newInterval.IsValid() )
result.Add( newInterval );
if( ++j < r.GetNoComponents() )
r.Get( j, interval );
}
}
else if( thisInterval.start.Compare( &interval.start ) <= 0 )
{
if( ++i < GetNoComponents() )
Get( i, thisInterval );
}
else
{
if( ++j < r.GetNoComponents() )
r.Get( j, interval );
}
}
result.EndBulkLoad( false );
}
template <class Alpha>
void Range<Alpha>::Intersection( const Interval<Alpha>& iv,
Range<Alpha>& result ) const
{
Interval<Alpha> tiv;
result.Clear();
result.StartBulkLoad();
for(int i=0;i<GetNoComponents(); i++){
Get(i,tiv);
if(tiv.Intersects(iv)){
Interval<Alpha> res;
tiv.Intersection(iv, res);
result.Add(res);
}
}
result.EndBulkLoad();
}
/*
1.1 Auxiliary class ParallelRangeScan
This class makes an parallel Scan over two range values.
The returned intevals are sorted by their starting time and
leftClosed properties. If two intervals start at the same
time, the interval of r1 is the next result.
*/
template<class Alpha>
class ParallelRangeScan{
public:
/*
1.1.1 Constructor
Both Ranges must be defined.
*/
ParallelRangeScan(const Range<Alpha>* _r1, const Range<Alpha>* _r2):
r1(_r1), r2(_r2), pos1(0), pos2(0){
assert(r1->IsDefined());
assert(r2->IsDefined());
}
/*
1.1.2 ~next~
If there is a next interval, it's returned using the parameter. In this case, the
result will be true. If both ranges are exhausted, the parameter is not changed
and the result of this function is false
*/
bool next(Interval<Alpha>& nextInterval){
if( (pos1>=r1->GetNoComponents() ) && (pos2>=r2->GetNoComponents())){
return false;
}
if(pos1>=r1->GetNoComponents()){
r2->Get(pos2, nextInterval);
pos2++;
return true;
}
if(pos2>=r2->GetNoComponents()){
r1->Get(pos1, nextInterval);
pos1++;
return true;
}
// both ranges have more entries
Interval<Alpha> iv1;
Interval<Alpha> iv2;
r1->Get(pos1, iv1);
r2->Get(pos2,iv2);
if(iv2.StartsBefore(iv1)){
nextInterval = iv2;
pos2++;
} else {
nextInterval = iv1;
pos1++;
}
return true;
}
private:
const Range<Alpha>* r1;
const Range<Alpha>* r2;
int pos1;
int pos2;
};
template<class Alpha>
void Range<Alpha>::Union(const Range<Alpha>& r, Range<Alpha>& result) const{
assert(IsValid());
assert(r.IsValid());
result.Clear();
if(!IsDefined() || !r.IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined(true);
if(IsEmpty()){
result.CopyFrom(&r);
return;
}
if(r.IsEmpty()){
result.CopyFrom(this);
return;
}
// both ranges have elements
Interval<Alpha> ivUnion; // current interval union
Interval<Alpha> nextInterval;
ParallelRangeScan<Alpha> scan(this, &r);
// we already know that both intervals have entries, so
// the first call of scan.next must return true
bool ok = scan.next(ivUnion);
assert(ok);
while(scan.next(nextInterval)){
if(nextInterval.Intersects(ivUnion)){
ivUnion.Union(nextInterval);
} else {
result.MergeAdd(ivUnion);
ivUnion = nextInterval;
}
}
result.MergeAdd(ivUnion);
}
template <class Alpha>
void Range<Alpha>::Union( const Interval<Alpha>& iv,
Range<Alpha>& result ) const
{
Interval<Alpha> enlargedInterval(iv);
Interval<Alpha> tiv;
bool done = false;
result.Clear();
for(int i=0;i< this->GetNoComponents();i++){
Get(i,tiv);
if(tiv.Before(iv) ){
result.Add(tiv);
} else if(tiv.After(enlargedInterval)){
if(!done){
result.Add(enlargedInterval);
done = true;
}
result.Add(tiv);
} else {
enlargedInterval.Union(tiv);
}
}
if(!done){
result.Add(enlargedInterval);
}
}
template <class Alpha>
void Range<Alpha>::Minus( const Range<Alpha>& r, Range<Alpha>& result ) const
{
assert( IsValid() );
assert( r.IsValid() );
result.Clear();
if( !IsDefined() || !r.IsDefined() ){
result.SetDefined( false );
return;
}
result.SetDefined( true );
if( IsEmpty() )
return;
result.StartBulkLoad();
Interval<Alpha> thisInterval, interval;
int i = 0, j = 0;
Get( i, thisInterval );
if( !r.IsEmpty() )
{
r.Get( j, interval );
Alpha *start = NULL, *end = NULL;
bool lc = false, rc = false;
while( i < GetNoComponents() && j < r.GetNoComponents() )
{
if( thisInterval.start.Compare( &interval.start ) == 0 &&
thisInterval.end.Compare( &interval.end ) == 0 )
{
if( thisInterval.lc && !interval.lc )
{
Interval<Alpha> newInterval( thisInterval.start,
thisInterval.start, true, true );
result.Add( newInterval );
}
if( thisInterval.rc && !interval.rc )
{
Interval<Alpha> newInterval( thisInterval.end,
thisInterval.end, true, true );
result.Add( newInterval );
}
if( ++i < GetNoComponents() )
Get( i, thisInterval );
if( ++j < r.GetNoComponents() )
r.Get( j, interval );
}
else if( !thisInterval.Intersects( interval ) )
{
if( start != NULL && end != NULL )
{
Interval<Alpha> newInterval( *start, *end, lc, rc );
if( newInterval.IsValid() )
result.Add( newInterval );
delete start; start = NULL;
delete end; end = NULL;
lc = rc = false;
}
else if( thisInterval.start.Compare( &interval.start ) <= 0 )
{
Interval<Alpha> newInterval( thisInterval );
result.Add( newInterval );
}
if( thisInterval.start.Compare( &interval.start ) <= 0 )
{
if( ++i < GetNoComponents() )
Get( i, thisInterval );
}
else
{
if( ++j < r.GetNoComponents() )
r.Get( j, interval );
}
}
else if( thisInterval.Inside( interval ) )
{
if( ++i < GetNoComponents() )
Get( i, thisInterval );
}
else if( interval.Inside( thisInterval ) )
{
if( interval.start.Compare( &thisInterval.start ) == 0 )
{
assert( start == NULL && end == NULL );
if( thisInterval.lc && !interval.lc )
{
Interval<Alpha> newInterval( thisInterval.start,
thisInterval.start, true, true );
result.Add( newInterval );
}
start = interval.end.Clone();
lc = !interval.rc;
end = thisInterval.end.Clone();
rc = thisInterval.rc;
if( ++j < r.GetNoComponents() )
r.Get( j, interval );
}
else if( interval.end.Compare( &thisInterval.end ) == 0 )
{
if( start == NULL && end == NULL )
{
Interval<Alpha> newInterval( thisInterval.start,
interval.start,
thisInterval.lc, !interval.lc );
if( newInterval.IsValid() )
result.Add( newInterval );
}
else
{
Interval<Alpha> newInterval( *start, interval.start,
lc, !interval.lc );
if( newInterval.IsValid() )
result.Add( newInterval );
delete start; start = NULL;
delete end; end = NULL;
lc = false; rc = false;
}
if( thisInterval.rc && !interval.rc )
{
Interval<Alpha> newInterval( thisInterval.end,
thisInterval.end, true, true );
result.Add( newInterval );
}
if( ++i < GetNoComponents() )
Get( i, thisInterval );
if( ++j < r.GetNoComponents() )
r.Get( j, interval );
}
else
{
assert( thisInterval.start.Compare( &interval.start ) < 0 &&
thisInterval.end.Compare( &interval.end ) > 0 );
if( start == NULL && end == NULL )
{
Interval<Alpha> newInterval( thisInterval.start,
interval.start,
thisInterval.lc, !interval.lc );
if( newInterval.IsValid() )
result.Add( newInterval );
}
else
{
assert( end->Compare( &thisInterval.end ) == 0 &&
rc == thisInterval.rc );
Interval<Alpha> newInterval( *start, interval.start,
lc, !interval.lc );
if( newInterval.IsValid() )
result.Add( newInterval );
delete start; start = NULL;
delete end; end = NULL;
lc = rc = false;
}
start = interval.end.Clone();
lc = !interval.rc;
end = thisInterval.end.Clone();
rc = thisInterval.rc;
if( ++j < r.GetNoComponents() )
r.Get( j, interval );
}
}
else
{
assert( thisInterval.Intersects( interval ) );
if( interval.start.Compare( &thisInterval.start ) < 0 )
{
assert( start == NULL && end == NULL );
if( interval.end.Compare( &thisInterval.end ) == 0 )
{
if( thisInterval.rc && !interval.rc )
{
Interval<Alpha> newInterval( thisInterval.end,
thisInterval.end, true, true );
result.Add( newInterval );
}
if( ++i < GetNoComponents() )
Get( i, thisInterval );
if( ++j < r.GetNoComponents() )
r.Get( j, interval );
}
else
{
start = interval.end.Clone();
if( interval.end.Compare( &thisInterval.start ) == 0 )
{
lc = thisInterval.lc && !interval.rc;
}
else
{
lc = !interval.rc;
}
end = thisInterval.end.Clone();
rc = thisInterval.rc;
if( ++j < r.GetNoComponents() )
r.Get( j, interval );
}
}
else if( interval.start.Compare( &thisInterval.start ) == 0 )
{
assert( (start == NULL) & (end == NULL) );
if( thisInterval.lc && !interval.lc )
{
Interval<Alpha> newInterval( thisInterval.start,
thisInterval.start, true, true );
result.Add( newInterval );
}
if( thisInterval.end.Compare( &interval.end ) > 0 )
{
start = interval.end.Clone();
lc = !interval.rc;
end = thisInterval.end.Clone();
rc = thisInterval.rc;
if( ++j < r.GetNoComponents() )
r.Get( j, interval );
}
else
{
assert( thisInterval.end.Compare( &interval.end ) < 0 );
if( ++i < GetNoComponents() )
Get( i, thisInterval );
}
}
else if( interval.end.Compare( &thisInterval.end ) > 0 )
{
if( thisInterval.start.Compare( &interval.start ) == 0 )
{
assert( start == NULL && end == NULL );
std::cerr << "I think that there is an error here!!!" << std::endl;
}
else
{
if( start != NULL && end != NULL )
{
if( interval.start.Compare( start ) > 0 ||
( interval.start.Compare( start ) == 0 &&
interval.lc && !lc ) )
{
delete end;
end = interval.start.Clone();
if( interval.start.Compare( &thisInterval.end ) == 0 )
rc = thisInterval.rc && !interval.lc;
else
rc = !interval.lc;
Interval<Alpha> newInterval( *start, *end, lc, rc );
if( newInterval.IsValid() )
result.Add( newInterval );
}
delete start; start = NULL;
delete end; end = NULL;
lc = rc = false;
}
else
{
Interval<Alpha> newInterval( thisInterval.start,
interval.start,
thisInterval.lc, !interval.lc );
if( newInterval.IsValid() )
result.Add( newInterval );
}
if( ++i < GetNoComponents() )
Get( i, thisInterval );
}
}
else
{
assert( interval.end.Compare( &thisInterval.end ) == 0 );
if( interval.start.Compare( &thisInterval.start ) < 0 )
{
assert( start == NULL && end == NULL );
if( thisInterval.rc && !interval.rc )
{
Interval<Alpha> newInterval( interval.end,
interval.end, true, true );
result.Add( newInterval );
}
}
else
{
assert( interval.start.Compare( &thisInterval.start ) > 0 );
if( start != NULL && end != NULL )
{
delete end;
end = interval.start.Clone();
rc = !interval.lc;
Interval<Alpha> newInterval( *start, *end, lc, rc );
if( newInterval.IsValid() )
result.Add( newInterval );
delete start; start = NULL;
delete end; end = NULL;
lc = rc = false;
}
else
{
Interval<Alpha> newInterval( thisInterval.start,
interval.start,
thisInterval.lc, !interval.lc );
if( newInterval.IsValid() )
result.Add( newInterval );
}
}
if( ++i < GetNoComponents() )
Get( i, thisInterval );
if( ++j < r.GetNoComponents() )
r.Get( j, interval );
}
}
}
if( start != NULL && end != NULL )
{
Interval<Alpha> newInterval( *start, *end, lc, rc );
if( newInterval.IsValid() )
result.Add( newInterval );
delete start;
delete end;
if( j >= r.GetNoComponents() )
{
if( ++i < GetNoComponents() )
Get( i, thisInterval );
}
else if( i >= GetNoComponents() )
{
if( ++j < r.GetNoComponents() )
r.Get( j, interval );
}
}
}
while( i < GetNoComponents() )
{
result.Add( thisInterval );
if( ++i < GetNoComponents() )
Get( i, thisInterval );
}
result.EndBulkLoad( false );
}
template <class Alpha>
void Range<Alpha>::Minus( const Interval<Alpha>& iv,
Range<Alpha>& result ) const
{
Interval<Alpha> tiv;
Interval<Alpha> iv_1;
Interval<Alpha> iv_2;
result.Clear();
for(int i=0;i<GetNoComponents(); i++){
Get(i,tiv);
if(tiv.Before(iv)){
result.Add(tiv);
} else if(tiv.After(iv)){
result.Add(tiv);
} else {
int num = tiv.Minus(iv,iv_1,iv_2);
if(num>0){
result.Add(iv_1);
}
if(num>1){
result.Add(iv_2);
}
}
}
}
template <class Alpha>
void Range<Alpha>::Minus(const Range<Alpha>& r){
// TODO: improve this naive implementation to avoid a lot of work
Range<Alpha> tmp(*this);
tmp.Minus(r, *this);
tmp.Destroy();
}
template <class Alpha>
void Range<Alpha>::Minus(const Interval<Alpha>& i){
// TODO: improve this naive implementation to avoid a lot of work
Range<Alpha> tmp(*this);
tmp.Minus(i, *this);
tmp.Destroy();
}
template <class Alpha>
void Range<Alpha>::Maximum( Alpha& result ) const
{
result.SetDefined( IsDefined() );
if( !IsDefined() ){
return;
}
assert( IsValid() );
if( IsEmpty() ) {
result.SetDefined( false );
} else {
Interval<Alpha> interval;
Get( GetNoComponents()-1, interval );
result.CopyFrom( &interval.end );
}
}
template <class Alpha>
void Range<Alpha>::Minimum( Alpha& result ) const
{
result.SetDefined( IsDefined() );
if( !IsDefined() ){
return;
}
assert( IsValid() );
if( IsEmpty() ) {
result.SetDefined( false );
} else {
Interval<Alpha> interval;
Get( 0, interval );
result.CopyFrom( &interval.start );
}
}
template <class Alpha>
int Range<Alpha>::GetNoComponents() const
{
assert( IsDefined() );
return intervals.Size();
}
template<class Alpha>
Range<Alpha>* Range<Alpha>::compress() const{
Range<Alpha>* result = new Range<Alpha>(true);
if (!IsDefined()) {
result->SetDefined(false);
return result;
}
result->SetDefined(true);
Interval<Alpha> u(true);
for (int i = 0; i < GetNoComponents() ; i++) {
Get(i, u);
result->MergeAdd(u);
}
return result;
}
template <class Alpha>
void Range<Alpha>::RBBox( Range<Alpha>& result ) const
{
result.Clear();
result.SetDefined( IsDefined() );
if( !IsDefined() ){
return;
}
assert( IsValid() );
if( !IsEmpty() )
{
Alpha minIntervalMin;
Alpha maxIntervalMax;
Minimum( minIntervalMin );
Maximum( maxIntervalMax );
Interval<Alpha> interval( minIntervalMin, maxIntervalMax, true, true);
result.Add(interval);
}
}
template <class Alpha>
bool Range<Alpha>::IsValid() const
{
if( !IsDefined() )
return true;
if( canDestroy )
return false;
if( !IsOrdered() )
return false;
if( IsEmpty() )
return true;
bool result = true;
Interval<Alpha> lastInterval, interval;
if( GetNoComponents() == 1 )
{
Get( 0, interval );
return( interval.IsValid() );
}
for( int i = 1; i < GetNoComponents(); i++ )
{
Get( i-1, lastInterval );
if( !lastInterval.IsValid() )
{
result = false;
break;
}
Get( i, interval );
if( !interval.IsValid() )
{
result = false;
break;
}
if( (!lastInterval.Disjoint( interval )) &&
(!lastInterval.Adjacent( interval )) )
{
result = false;
break;
}
}
return result;
}
template <class Alpha>
void Range<Alpha>::Merge( Range<Alpha>& result ) const
{
result.Clear();
result.SetDefined( IsDefined() );
if(!IsDefined()){
return;
}
assert( IsOrdered() );
result.StartBulkLoad();
Interval<Alpha> ii, ji;
int i = 0, j;
bool jcont = true;
while( i < GetNoComponents() )
{
Get( i, ii );
j = i + 1;
jcont = true;
Interval<Alpha> copyii( ii );
while( j < GetNoComponents() && jcont )
{
Get( j, ji );
if( copyii.Adjacent( ji ) )
{
copyii.end = ji.end;
copyii.rc = ji.rc;
j++;
}
else
jcont=false;
}
result.Add( copyii );
i = j;
}
result.EndBulkLoad( false );
}
/*
4.3 TemporalUnit
4.3.1 Constructors and destructor
*/
template <class Alpha>
bool TemporalUnit<Alpha>::IsValid() const
{
return timeInterval.IsValid();
}
template <class Alpha>
TemporalUnit<Alpha>&
TemporalUnit<Alpha>::operator=( const TemporalUnit<Alpha>& i )
{
assert( i.timeInterval.IsValid() );
timeInterval = i.timeInterval;
return *this;
}
template <class Alpha>
bool TemporalUnit<Alpha>::operator==( const TemporalUnit<Alpha>& i ) const
{
assert( timeInterval.IsValid() && i.timeInterval.IsValid() );
return( timeInterval == i.timeInterval);
}
template <class Alpha>
bool TemporalUnit<Alpha>::operator!=( const TemporalUnit<Alpha>& i ) const
{
return !( *this == i );
}
template <class Alpha>
bool TemporalUnit<Alpha>::R_Disjoint( const TemporalUnit<Alpha>& i ) const
{
return( timeInterval.R_Disjoint( i.timeInterval ) );
}
template <class Alpha>
bool TemporalUnit<Alpha>::Disjoint( const TemporalUnit<Alpha>& i ) const
{
assert( IsValid() && i.IsValid() );
return( R_Disjoint( i ) || i.R_Disjoint( *this ) );
}
template <class Alpha>
bool TemporalUnit<Alpha>::R_Adjacent( const TemporalUnit<Alpha>& i ) const
{
return( timeInterval.R_Adjacent(i.timeInterval));
}
template <class Alpha>
bool TemporalUnit<Alpha>::TU_Adjacent( const TemporalUnit<Alpha>& i ) const
{
assert( IsValid() && i.IsValid() );
return( R_Adjacent( i ) || i.R_Adjacent( *this ) );
}
template <class Alpha>
bool TemporalUnit<Alpha>::Inside( const TemporalUnit<Alpha>& i ) const
{
assert( IsValid() && i.IsValid() );
return( timeInterval.Inside(i.timeInterval) );
}
template <class Alpha>
bool TemporalUnit<Alpha>::Contains( const Instant& a ) const
{
assert( IsValid() && a.IsDefined() );
return ( timeInterval.Contains(a) );
}
template <class Alpha>
bool TemporalUnit<Alpha>::Intersects( const TemporalUnit<Alpha>& i ) const
{
assert( IsValid() && i.IsValid() );
return ( timeInterval.Intersects(i.timeInterval) );
}
template <class Alpha>
bool TemporalUnit<Alpha>::StartsBefore( const TemporalUnit<Alpha>& i ) const
{
assert( IsValid() && i.IsValid() );
return ( timeInterval.StartsBefore(i.timeInterval) );
}
template <class Alpha>
bool TemporalUnit<Alpha>::EndsAfter( const TemporalUnit<Alpha>& i ) const
{
assert( IsValid() && i.IsValid() );
return ( timeInterval.EndsAfter(i.timeInterval) );
}
template <class Alpha>
bool TemporalUnit<Alpha>::Before( const TemporalUnit<Alpha>& i ) const
{
assert( IsValid() && i.IsValid() );
return ( timeInterval.Before(i.timeInterval) );
}
template <class Alpha>
bool TemporalUnit<Alpha>::Before( const Instant& a ) const
{
assert( IsValid() && a.IsDefined() );
return ( timeInterval.Before( a ) );
}
template <class Alpha>
bool TemporalUnit<Alpha>::After( const Instant& a ) const
{
assert( IsValid() && a.IsDefined() );
return ( timeInterval.After( a ) );
}
/*
4.4 Mapping
4.4.1 Constructors and destructor
*/
template <class Unit, class Alpha>
Mapping<Unit, Alpha>::Mapping( const int n ):
Attribute(true),
canDestroy( false ),
ordered( true ),
units( n )
{
del.refs=1;
del.SetDelete();
del.isDefined = true;
}
template <class Unit, class Alpha>
void Mapping<Unit, Alpha>::Destroy()
{
canDestroy = true;
}
template <class Unit, class Alpha>
Mapping<Unit, Alpha>::~Mapping()
{
if( canDestroy ) {
units.Destroy();
} else {
//units.destroyIfNonPersistent();
}
}
/*
4.4.2 Member functions
*/
template <class Unit, class Alpha>
bool Mapping<Unit, Alpha>::IsOrdered() const
{
return ordered;
}
template <class Unit, class Alpha>
void Mapping<Unit, Alpha>::StartBulkLoad()
{
assert( IsDefined() );
assert( ordered );
ordered = false;
}
template <class Unit>
int UnitCompare( const void *a, const void *b )
{
Unit *unita = new ((void*)a) Unit,
*unitb = new ((void*)b) Unit;
if( *unita == *unitb )
return 0;
else if( unita->Before( *unitb ) )
return -1;
else
return 1;
}
template <class Unit, class Alpha>
bool Mapping<Unit, Alpha>::EndBulkLoad( const bool sort, const bool checkvalid )
{
assert( !ordered );
if( !IsDefined() ){
units.clean();
} else if( sort ){
units.Sort( UnitCompare<Unit> );
}
ordered = true;
units.TrimToSize();
if( checkvalid && !IsValid() ){
units.clean();
SetDefined( false );
return false;
}
return true;
}
template <class Unit, class Alpha>
bool Mapping<Unit, Alpha>::IsEmpty() const
{
return !IsDefined() || (units.Size() == 0);
}
template <class Unit, class Alpha>
void Mapping<Unit, Alpha>::Get( const int i, Unit &unit ) const
{
assert( IsDefined() );
assert(i>=0);
assert(i<units.Size());
bool ok = units.Get( i, unit );
if(!ok){
cout << "Problem in getting data from " << units << std::endl;
assert(ok);
}
if ( !unit.IsValid() )
{
cout << __FILE__ << "," << __LINE__ << ":" << __PRETTY_FUNCTION__
<< " Get(" << i << ", Unit): Unit is invalid:";
unit.Print(cout); cout << std::endl;
assert( unit.IsValid());
}
}
template <class Unit, class Alpha>
void Mapping<Unit, Alpha>::Add( const Unit& unit )
{
assert( IsDefined() );
if ( !unit.IsDefined() || !unit.IsValid() )
{
cout << __FILE__ << "," << __LINE__ << ":" << __PRETTY_FUNCTION__
<< " Add(Unit): Unit is undefined or invalid:";
unit.Print(cout); cout << std::endl;
assert( false );
}
units.Append( unit );
}
template <class Unit, class Alpha>
void Mapping<Unit, Alpha>::MergeAdd( const Unit& unit )
{
assert( IsDefined() );
Unit lastunit;
int size = units.Size();
if ( !unit.IsDefined() || !unit.IsValid() )
{
cout << __FILE__ << "," << __LINE__ << ":" << __PRETTY_FUNCTION__
<< " MergeAdd(Unit): Unit is undefined or invalid:";
unit.Print(cout); cout << std::endl;
assert( false );
}
if (size > 0) {
units.Get( size - 1, &lastunit );
if (lastunit.EqualValue(unit) &&
(lastunit.timeInterval.end == unit.timeInterval.start) &&
(lastunit.timeInterval.rc || unit.timeInterval.lc)) {
lastunit.timeInterval.end = unit.timeInterval.end;
lastunit.timeInterval.rc = unit.timeInterval.rc;
if ( !lastunit.IsValid() )
{
cout << __FILE__ << "," << __LINE__ << ":" << __PRETTY_FUNCTION__
<< "\nMapping::MergeAdd(): lastunit is invalid:";
lastunit.Print(cout); cout << std::endl;
assert( false );
}
units.Put(size - 1, lastunit);
}
else {
units.Append( unit );
}
}
else {
units.Append( unit );
}
}
template <class Unit, class Alpha>
void Mapping<Unit, Alpha>::Clear()
{
ordered = true;
units.clean();
this->del.isDefined = true;
}
/*
4.4.3 Functions to be part of relations
*/
template <class Unit, class Alpha>
inline size_t Mapping<Unit, Alpha>::Sizeof() const
{
return sizeof( *this );
}
template <class Unit, class Alpha>
inline int Mapping<Unit, Alpha>::Compare( const Attribute *arg ) const
{
Mapping<Unit,Alpha>* map2 = (Mapping<Unit,Alpha>*) arg;
if( !IsDefined() && !map2->IsDefined() )
return 0;
if( !IsDefined() && map2->IsDefined() )
return -1;
if( IsDefined() && !map2->IsDefined() )
return 1;
size_t size1 = units.Size();
size_t size2 = map2->units.Size();
size_t index = 0;
Unit u1;
Unit u2;
int cmp;
while( (index < size1) && (index < size2)){
units.Get(index,&u1);
map2->units.Get(index,&u2);
cmp = u1.Compare(&u2);
if(cmp){ // different units
return cmp;
}
index++;
}
// the common entries all equals
if(size1<size2){
cmp = -1;
} else if(size1>size2){
cmp = 1;
} else{
cmp= 0;
}
return cmp;
}
template <class Unit, class Alpha>
inline bool Mapping<Unit, Alpha>::Adjacent( const Attribute *arg ) const
{
return false;
}
template <class Unit, class Alpha>
inline Attribute* Mapping<Unit, Alpha>::Clone() const
{
Mapping<Unit, Alpha> *result;
if( !IsDefined() ){
result = new Mapping<Unit, Alpha>( 0 );
result->SetDefined( false );
return result;
}
result = new Mapping<Unit, Alpha>( GetNoComponents() );
result->SetDefined( true );
assert( IsOrdered() );
if(GetNoComponents()>0){
result->units.resize(GetNoComponents());
}
result->StartBulkLoad();
Unit unit;
for( int i = 0; i < GetNoComponents(); i++ )
{
Get( i, unit );
result->Add( unit );
}
result->EndBulkLoad( false );
return result;
}
template <class Unit, class Alpha>
inline std::ostream& Mapping<Unit, Alpha>::Print( std::ostream &os ) const
{
if( !IsDefined() )
{
return os << "("<< Mapping<Unit,Alpha>::BasicType() <<": undefined)";
}
os << "("<< Mapping<Unit,Alpha>::BasicType()
<<": defined, contains " << GetNoComponents() << " units: ";
for(int i=0; i<GetNoComponents(); i++)
{
Unit unit;
Get( i , unit );
os << "\n\t";
unit.Print(os);
}
os << "\n)" << std::endl;
return os;
}
template <class Unit, class Alpha>
inline size_t Mapping<Unit, Alpha>::HashValue() const
{
if(!IsDefined()){
return 0;
}
Unit min, max;
units.Get(0,&min);
units.Get(GetNoComponents()-1,max);
return static_cast<size_t>( min.HashValue()
^ max.HashValue() ) ;
return 0;
}
template <class Unit, class Alpha>
inline void Mapping<Unit, Alpha>::CopyFrom( const Attribute* right )
{
const Mapping<Unit, Alpha> *r = (const Mapping<Unit, Alpha>*)right;
Clear();
SetDefined( r->IsDefined() );
if( !r->IsDefined() ){
return;
}
assert( r->IsOrdered() );
StartBulkLoad();
Unit unit;
for( int i = 0; i < r->GetNoComponents(); i++ )
{
r->Get( i, unit );
Add( unit );
}
EndBulkLoad( false );
this->SetDefined(r->IsDefined());
}
template <class Unit, class Alpha>
inline void
Mapping<Unit, Alpha>::Restrict(
const std::vector< std::pair<int, int> >& intervals )
{
if( !IsDefined() ){
Clear();
SetDefined( false );
}
units.Restrict( intervals, units );
}
template <class Unit, class Alpha>
inline int Mapping<Unit, Alpha>::NumOfFLOBs() const
{
return 1;
}
template <class Unit, class Alpha>
inline Flob *Mapping<Unit, Alpha>::GetFLOB(const int i)
{
assert( i == 0 );
return &units;
}
/*
4.4.4 Operator functions
*/
template <class Unit, class Alpha>
bool Mapping<Unit, Alpha>::operator==( const Mapping<Unit, Alpha>& r ) const
{
if( !IsDefined() && !r.IsDefined() )
return true;
if( !IsDefined() || !r.IsDefined() )
return false;
assert( IsOrdered() && r.IsOrdered() );
if( GetNoComponents() != r.GetNoComponents() )
return false;
bool result = true;
Unit thisunit, unit;
for( int i = 0; i < GetNoComponents(); i++ )
{
Get( i, thisunit );
r.Get( i, unit );
if( thisunit != unit )
{
result = false;
break;
}
}
return result;
}
template <class Unit, class Alpha>
bool Mapping<Unit, Alpha>::operator!=( const Mapping<Unit, Alpha>& r ) const
{
return !( *this == r );
}
template <class Unit, class Alpha>
int Mapping<Unit, Alpha>::GetNoComponents() const
{
assert( IsDefined() );
return units.Size();
}
template <class Unit, class Alpha>
bool Mapping<Unit, Alpha>::IsValid() const
{
if( !IsDefined() )
return true;
if( canDestroy )
return false;
if( !IsOrdered() )
return false;
if( IsEmpty() )
return true;
bool result = true;
Unit lastunit, unit;
Get( 0, lastunit );
if ( !lastunit.IsValid() )
{
std::cerr << "Mapping<Unit, Alpha>::IsValid(): "
"unit is invalid: i=0" << std::endl;
return false;
}
if ( GetNoComponents() == 1 ){
return true;
}
for( int i = 1; i < GetNoComponents(); i++ )
{
Get( i, unit );
if( !unit.IsValid() )
{
result = false;
std::cerr << "Mapping<Unit, Alpha>::IsValid(): "
"unit is invalid: i=" << i << std::endl;
return false;
}
if(lastunit.timeInterval.end > unit.timeInterval.start){
std::cerr << "Units are not ordered by time" << std::endl;
std::cerr << "lastUnit.timeInterval = ";
lastunit.timeInterval.Print(std::cerr);
std::cerr << std::endl;
std::cerr << "unit.timeInterval = ";
unit.timeInterval.Print(std::cerr);
std::cerr << std::endl;
return false;
}
if( (!lastunit.timeInterval.Disjoint(unit.timeInterval)) )
{
result = false;
std::cerr << "Mapping<Unit, Alpha>::IsValid(): "
"unit and lastunit not disjoint: i=" << i << std::endl;
std::cerr << "\n\tlastunit = "; lastunit.timeInterval.Print(std::cerr);
std::cerr << "\n\tunit = "; unit.timeInterval.Print(std::cerr);
std::cerr << std::endl;
return false;
}
lastunit = unit;
}
return result;
}
template <class Unit, class Alpha>
int Mapping<Unit, Alpha>::Position( const Instant& t ) const
{
assert( IsDefined() );
assert( IsOrdered() );
assert( t.IsDefined() );
int first = 0, last = units.Size() - 1;
Instant t1 = t;
while (first <= last)
{
int mid = ( first + last ) / 2;
if( (mid < 0) || (mid >= units.Size()) )
return -1;
Unit midUnit;
units.Get( mid, &midUnit );
if( midUnit.timeInterval.Contains(t1) )
return mid;
else //not contained
if( ( t1 > midUnit.timeInterval.end ) ||
( t1 == midUnit.timeInterval.end ) )
first = mid + 1;
else if( ( t1 < midUnit.timeInterval.start ) ||
( t1 == midUnit.timeInterval.start ) )
last = mid - 1;
else
return -1; //should never be reached.
}
return -1;
}
template<class Unit, class Alpha>
Mapping<Unit,Alpha>* Mapping<Unit,Alpha>::compress() const{
Mapping<Unit,Alpha>* result = new Mapping<Unit,Alpha>(GetNoComponents());
if(!IsDefined()){
result->SetDefined(false);
return result;
}
result->SetDefined(true);
Unit u;
for(int i=0;i<GetNoComponents();i++){
Get(i,u);
result->MergeAdd(u);
}
return result;
}
template <class Unit, class Alpha>
void Mapping<Unit, Alpha>::AtInstant( const Instant& t,
Intime<Alpha>& result ) const
{
if( !IsDefined() || !t.IsDefined() ) {
result.SetDefined( false );
return;
}
assert( IsOrdered() );
int pos = Position( t );
if( pos == -1 ) // not contained in any unit
result.SetDefined( false );
else
{
Unit posUnit;
units.Get( pos, &posUnit );
result.SetDefined( true );
posUnit.TemporalFunction( t, result.value );
result.instant.CopyFrom( &t );
}
}
template <class Unit, class Alpha>
void Mapping<Unit, Alpha>::TemporalFunction( const Instant& t,
Alpha& result,
bool ignoreLimits) const
{
if( !IsDefined() || !t.IsDefined() ) {
result.SetDefined( false );
return;
}
assert( IsOrdered() );
int pos = Position( t );
if( pos == -1 ) // not contained in any unit
result.SetDefined( false );
else
{
Unit posUnit;
units.Get( pos, &posUnit );
result.SetDefined( true );
posUnit.TemporalFunction( t, result, ignoreLimits );
}
}
template <class Unit, class Alpha>
void Mapping<Unit, Alpha>::AtPeriods( const Periods& periods,
Mapping<Unit, Alpha>& result ) const
{
result.Clear();
if( !IsDefined() || !periods.IsDefined() ) {
result.SetDefined( false );
return;
}
assert( IsOrdered() );
assert( periods.IsOrdered() );
if( IsEmpty() || periods.IsEmpty() )
return;
if( IsMaximumPeriods(periods) )
{ // p is [begin of time, end of time]. Copy the input into result.
result.CopyFrom(this);
return;
}
result.StartBulkLoad();
Unit unit;
Interval<Instant> interval;
int i = 0, j = 0;
Get( i, unit );
periods.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 == periods.GetNoComponents() )
break;
periods.Get( j, interval );
}
else
{
Unit r(1);
unit.AtInterval( interval, r );
result.Add( r );
if( interval.end == unit.timeInterval.end )
{
if( interval.rc == unit.timeInterval.rc )
{
if( ++i == GetNoComponents() )
break;
Get( i, unit );
if( ++j == periods.GetNoComponents() )
break;
periods.Get( j, interval );
}
else if( interval.rc == true )
{
if( ++i == GetNoComponents() )
break;
Get( i, unit );
}
else
{
assert( unit.timeInterval.rc == true );
if( ++j == periods.GetNoComponents() )
break;
periods.Get( j, interval );
}
}
else if( interval.end > unit.timeInterval.end )
{
if( ++i == GetNoComponents() )
break;
Get( i, unit );
}
else
{
assert( interval.end < unit.timeInterval.end );
if( ++j == periods.GetNoComponents() )
break;
periods.Get( j, interval );
}
}
}
result.EndBulkLoad( false );
// VTA - The merge of the result is not implemented yet.
}
template <class Unit, class Alpha>
bool Mapping<Unit, Alpha>::Present( const Instant& t ) const
{
assert( IsDefined() && t.IsDefined() && IsOrdered() );
int pos = Position(t);
if( pos == -1 ) //not contained in any unit
return false;
return true;
}
template <class Unit, class Alpha>
bool Mapping<Unit, Alpha>::Present( const Periods& t ) const
{
assert( IsDefined() && t.IsOrdered() && IsOrdered() );
Periods defTime( 0 );
DefTime( defTime );
return t.Intersects( defTime );
}
template <class Unit, class Alpha>
void Mapping<Unit, Alpha>::DefTime( Periods& r ) const
{
r.Clear();
r.SetDefined( IsDefined() );
if( !IsDefined() ){
return;
}
assert( IsOrdered() );
Unit unit;
for( int i = 0; i < GetNoComponents(); i++ )
{
Get( i, unit );
r.MergeAdd( unit.timeInterval );
}
}
template <class Unit, class Alpha>
template <class Beta>
bool Mapping<Unit, Alpha>::Passes( const Beta& val ) const
{
assert( IsDefined() );
assert( IsOrdered() );
assert( val.IsDefined() );
Unit unit;
for( int i = 0; i < GetNoComponents(); i++ )
{
Get( i, unit );
if( unit.Passes( val ) )
return true;
}
return false;
}
template <class Unit, class Alpha>
void Mapping<Unit, Alpha>::At( const Alpha& val,
Mapping<Unit, Alpha>& result ) const
{
result.Clear();
if( !IsDefined() || !val.IsDefined() ){
result.SetDefined( false );
return;
}
result.SetDefined( true );
assert( IsOrdered() );
result.StartBulkLoad();
Unit unit;
for( int i = 0; i < GetNoComponents(); i++ )
{
Get( i, unit );
Unit resUnit;
if( unit.At( val, resUnit ) )
result.Add( resUnit );
}
result.EndBulkLoad( false );
// VTA - The merge of the result is not implemented yet.
}
template <class Unit, class Alpha>
void Mapping<Unit, Alpha>::Initial( Intime<Alpha>& result ) const
{
if( !IsDefined() ){
result.SetDefined( false );
return;
}
assert( IsOrdered() );
if( IsEmpty() ){
result.SetDefined( false );
} else
{
Unit unit;
units.Get( 0, &unit );
result.SetDefined( true );
unit.TemporalFunction( unit.timeInterval.start, result.value, true );
result.instant.CopyFrom( &unit.timeInterval.start );
}
}
template <class Unit, class Alpha>
void Mapping<Unit, Alpha>::Final( Intime<Alpha>& result ) const
{
if( !IsDefined() ){
result.SetDefined( false );
return;
}
assert( IsOrdered() );
if( IsEmpty() ){
result.SetDefined( false );
} else
{
Unit unit;
bool ok = units.Get( GetNoComponents()-1, unit );
assert(ok);
result.SetDefined( true );
unit.TemporalFunction( unit.timeInterval.end, result.value, true );
result.instant.CopyFrom( &unit.timeInterval.end );
}
}
template <class Unit, class Alpha>
void Mapping<Unit, Alpha>::Resize(size_t n){
if (n>0)
{
units.resize(n);
} else
{
units.clean();
}
}
template <class Unit, class Alpha>
void Mapping<Unit, Alpha>::TrimToSize(){
units.TrimToSize();
}
template <class Unit, class Alpha>
void Mapping<Unit, Alpha>::ExtendDefTime(Unit u,
Mapping<Unit,Alpha>& result){
// special case undefined unit -> donst make any changes
if(!u.IsDefined()){
result.CopyFrom(this);
return;
}
// make an empty result
result.Clear();
if(!IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined(true);
// resize for two additional units (estimated a good choice)
result.Resize(units.Size()+2);
Instant CI(u.timeInterval.start); // current instant
bool Cc = u.timeInterval.lc; // current closed
Unit unit;
result.canDestroy=false;
int size = units.Size();
// we have to connect units holding the same value, so
// we hold a unit and extend it if it is possible
result.StartBulkLoad();
for(int i=0; i<size;i++){
units.Get(i,&unit);
// check whether a gap exits between the currect position in time
// and this unit
if(CI<unit.timeInterval.start || // time is before
(( CI==unit.timeInterval.start && !Cc && !unit.timeInterval.lc))){
// create a Unit filling the gap
Interval<Instant> interval(CI,unit.timeInterval.start,
!Cc,!unit.timeInterval.lc);
Unit gap(interval,u.constValue);
result.MergeAdd(gap); // append the gap filling unit
}
Unit st(unit);
result.MergeAdd(st);
// change the current instant and closed information
CI = unit.timeInterval.end;
Cc = unit.timeInterval.rc;
}
// fill the gap between the last inserted unit and the end of the given one
// if one exists
if( CI<u.timeInterval.end ||
((CI==u.timeInterval.end && !Cc && u.timeInterval.rc))){
Interval<Instant> interval(CI,u.timeInterval.end,!Cc,u.timeInterval.rc);
Unit gap(interval,u.constValue);
result.MergeAdd(gap);
}
result.EndBulkLoad(false);
}
template<class Unit, class Alpha>
void Mapping<Unit,Alpha>::GetInterval(const int pos, SecInterval& result) const{
assert(pos >= 0 && pos < GetNoComponents());
Unit u(true);
units.Get(pos, u);
result = u.timeInterval;
}
template<class Unit, class Alpha>
void Mapping<Unit, Alpha>::InitialInstant(Instant& result) const {
assert(result.GetType() == datetime::instanttype);
if (!IsDefined() || IsEmpty()) {
result.SetDefined(false);
return;
}
Unit unit(true);
units.Get(0, unit);
result = unit.timeInterval.start;
}
template<class Unit, class Alpha>
void Mapping<Unit, Alpha>::FinalInstant(Instant& result) const {
assert(result.GetType() == datetime::instanttype);
if (!IsDefined() || IsEmpty()) {
result.SetDefined(false);
return;
}
Unit unit(true);
units.Get(GetNoComponents() - 1, unit);
result = unit.timeInterval.end;
}
template<class Unit, class Alpha>
void Mapping<Unit, Alpha>::GetFullInterval(Interval<Instant>& result) const {
if (!IsDefined() || IsEmpty()) {
return;
}
Unit unit(true);
units.Get(0, unit);
result.start = unit.timeInterval.start;
result.lc = unit.timeInterval.lc;
units.Get(GetNoComponents() - 1, unit);
result.end = unit.timeInterval.end;
result.rc = unit.timeInterval.rc;
}
template<class Unit, class Alpha>
void Mapping<Unit, Alpha>::GetDuration(datetime::DateTime& result) const {
result.SetToZero();
if (!IsDefined()) {
result.SetDefined(false);
return;
}
Unit u(true);
for (int i = 0; i < GetNoComponents(); i++) {
Get(i, u);
result += u.timeInterval.end - u.timeInterval.start;
}
}
template<class Unit, class Alpha>
void Mapping<Unit,Alpha>::timeMove(const datetime::DateTime& duration,
Mapping<Unit,Alpha>& result) const{
assert(duration.GetType()==datetime::durationtype);
if(!IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined(true);
result.StartBulkLoad();
Unit unit;
for(int i=0;i<GetNoComponents();i++){
Get(i,unit);
unit.timeInterval.start += duration;
unit.timeInterval.end += duration;
result.Add(unit);
}
result.EndBulkLoad();
}
template<class Unit, class Alpha>
void Mapping<Unit,Alpha>::moveTo(const datetime::DateTime& instant,
Mapping<Unit,Alpha>& result) const{
assert(instant.GetType()==datetime::instanttype);
result.Clear();
if(!IsDefined()){
result.SetDefined(false);
return;
}
if(IsEmpty()){
result.SetDefined(true);
return;
}
Unit unit;
Get(0,unit);
datetime::DateTime dur = instant - unit.timeInterval.start;
timeMove(dur, result);
}
/*
5 Type Constructor template functions
5.1 Type Constructor ~range~
5.1.1 ~Out~-function
*/
template <class Alpha, ListExpr (*OutFun)( ListExpr, Word )>
ListExpr OutRange( ListExpr typeInfo, Word value )
{
Range<Alpha>* range = (Range<Alpha>*)(value.addr);
if( !range->IsDefined() ){
return nl->SymbolAtom( Symbol::UNDEFINED() );
}
if( range->IsEmpty() )
{
return (nl->TheEmptyList());
}
else
{
assert( range->IsOrdered() );
ListExpr l = nl->TheEmptyList(), lastElem=nl->TheEmptyList(), intervalList;
for( int i = 0; i < range->GetNoComponents(); i++ )
{
Interval<Alpha> interval;
range->Get( i, interval );
Alpha *start = (Alpha*)&interval.start,
*end = (Alpha*)&interval.end;
intervalList = nl->FourElemList(
OutFun( nl->TheEmptyList(), SetWord(start) ),
OutFun( nl->TheEmptyList(), SetWord(end) ),
nl->BoolAtom( interval.lc ),
nl->BoolAtom( interval.rc));
if (l == nl->TheEmptyList())
{
l = nl->Cons( intervalList, nl->TheEmptyList());
lastElem = l;
}
else
lastElem = nl->Append(lastElem, intervalList);
}
return l;
}
}
/*
5.1.2 ~In~-function
*/
template <class Alpha, Word (*InFun)( const ListExpr, const ListExpr,
const int, ListExpr&, bool& )>
Word InRange( const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr& errorInfo, bool& correct )
{
Range<Alpha>* range;
if ( listutils::isSymbolUndefined( instance ) )
{
range = new Range<Alpha>( 0 );
range->SetDefined( false );
correct = true;
return SetWord( range );
}
range = new Range<Alpha>( 0 );
range->SetDefined( true );
range->StartBulkLoad();
ListExpr rest = instance;
correct = true;
while( !nl->IsEmpty( rest ) && correct )
{
ListExpr first = nl->First( rest );
rest = nl->Rest( rest );
if( nl->ListLength( first ) == 4 &&
nl->IsAtom( nl->First( first ) ) &&
nl->IsAtom( nl->Second( first ) ) &&
nl->IsAtom( nl->Third( first ) ) &&
nl->AtomType( nl->Third( first ) ) == BoolType &&
nl->IsAtom( nl->Fourth( first ) ) &&
nl->AtomType( nl->Fourth( first ) ) == BoolType )
{
Alpha *start = (Alpha *)InFun( nl->TheEmptyList(),
nl->First( first ),
errorPos, errorInfo, correct ).addr;
if( !correct )
{
delete start;
break;
}
Alpha *end = (Alpha *)InFun( nl->TheEmptyList(),
nl->Second( first ),
errorPos, errorInfo, correct ).addr;
if( !correct )
{
delete start;
delete end;
break;
}
// get closedness parameters
bool lc = nl->BoolValue( nl->Third( first ) );
bool rc = nl->BoolValue( nl->Fourth( first ) );
// check, wether interval is well defined
Interval<Alpha> interval( *start, *end, lc, rc );
correct = interval.IsValid();
delete start;
delete end;
if ( !correct )
break;
range->Add( interval );
}
else
{
correct = false;
break;
}
}
if ( !correct )
{
range->Destroy();
delete range;
return SetWord( Address(0) );
}
range->EndBulkLoad( false ); // Do not sort. We expect sorted input
correct = range->IsValid(); // Check, wether input was well defined
return SetWord( range );
}
/*
5.1.3 ~Open~-function
*/
template <class Alpha>
bool OpenRange( SmiRecord& valueRecord,
size_t& offset,
const ListExpr typeInfo,
Word& value )
{
Range<Alpha> *range = (Range<Alpha>*)Attribute::Open( valueRecord, offset,
typeInfo );
value = SetWord( range );
return true;
}
/*
5.1.4 ~Save~-function
*/
template <class Alpha>
bool SaveRange( SmiRecord& valueRecord,
size_t& offset,
const ListExpr typeInfo,
Word& value )
{
Range<Alpha> *range = (Range<Alpha> *)value.addr;
Attribute::Save( valueRecord, offset, typeInfo, range );
return true;
}
/*
5.1.5 ~Create~-function
*/
template <class Alpha>
Word CreateRange( const ListExpr typeInfo )
{
return (SetWord( new Range<Alpha>( 0 ) ));
}
/*
5.1.6 ~Delete~-function
*/
template <class Alpha>
void DeleteRange( const ListExpr typeInfo, Word& w )
{
((Range<Alpha> *)w.addr)->Destroy();
delete (Range<Alpha> *)w.addr;
w.addr = 0;
}
/*
5.1.7 ~Close~-function
*/
template <class Alpha>
void CloseRange( const ListExpr typeInfo, Word& w )
{
delete (Range<Alpha> *)w.addr;
w.addr = 0;
}
/*
5.1.8 ~Clone~-function
*/
template <class Alpha>
Word CloneRange( const ListExpr typeInfo, const Word& w )
{
Range<Alpha> *r = (Range<Alpha> *)w.addr;
return SetWord( r->Clone() );
}
/*
5.1.9 ~Sizeof~-function
*/
template <class Alpha>
int SizeOfRange()
{
return sizeof(Range<Alpha>);
}
/*
5.1.10 ~Cast~-function
*/
template <class Alpha>
void* CastRange(void* addr)
{
return new (addr) Range<Alpha>;
}
/*
5.2 Type Constructor ~intime~
5.2.1 ~Out~-function
*/
template <class Alpha, ListExpr (*OutFun)( ListExpr, Word )>
ListExpr OutIntime( ListExpr typeInfo, Word value )
{
Intime<Alpha>* intime = (Intime<Alpha>*)(value.addr);
if( intime->IsDefined() )
return nl->TwoElemList(
datetime::OutDateTime( nl->TheEmptyList(),
SetWord(&intime->instant) ),
OutFun( nl->TheEmptyList(), SetWord( &intime->value ) ) );
else
return nl->SymbolAtom( Symbol::UNDEFINED() );
}
/*
5.2.2 ~In~-function
*/
template <class Alpha, Word (*InFun)( const ListExpr,
const ListExpr,
const int, ListExpr&, bool& )>
Word InIntime( const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr& errorInfo, bool& correct )
{
if ( listutils::isSymbolUndefined( instance ) )
{
Intime<Alpha> *intime = new Intime<Alpha>(false);
intime->SetDefined( false );
correct = true;
return SetWord( intime );
}
if( !nl->IsAtom( instance ) &&
nl->ListLength( instance ) == 2 )
{
Instant *instant = (Instant *)datetime::InInstant( nl->TheEmptyList(),
nl->First( instance ),
errorPos,
errorInfo,
correct ).addr;
if(!correct)
{
if(instant){
delete instant;
}
return SetWord( Address(0) );
}
Alpha *value = (Alpha *)InFun( nl->TheEmptyList(),
nl->Second( instance ),
errorPos, errorInfo, correct ).addr;
if( correct )
{
Intime<Alpha> *intime = new Intime<Alpha>( *instant, *value );
delete instant;
delete value;
return SetWord( intime );
}
delete instant;
if(value){
delete value;
}
}
correct = false;
return SetWord( Address(0) );
}
/*
5.2.3 ~Create~-function
*/
template <class Alpha>
Word CreateIntime( const ListExpr typeInfo )
{
return (SetWord( new Intime<Alpha>() ));
}
/*
5.2.4 ~Delete~-function
*/
template <class Alpha>
void DeleteIntime( const ListExpr typeInfo, Word& w )
{
delete (Intime<Alpha> *)w.addr;
w.addr = 0;
}
/*
5.2.5 ~Close~-function
*/
template <class Alpha>
void CloseIntime( const ListExpr typeInfo, Word& w )
{
delete (Intime<Alpha> *)w.addr;
w.addr = 0;
}
/*
5.2.6 ~Clone~-function
*/
template <class Alpha>
Word CloneIntime( const ListExpr typeInfo, const Word& w )
{
Intime<Alpha> *intime = (Intime<Alpha> *)w.addr;
return intime->Clone();
}
/*
5.2.7 ~Sizeof~-function
*/
template <class Alpha>
int SizeOfIntime()
{
return sizeof(Intime<Alpha>);
}
/*
5.2.8 ~Cast~-function
*/
template <class Alpha>
void* CastIntime(void* addr)
{
return new (addr) Intime<Alpha>;
}
/*
5.3 Type Constructor ~constunit~
5.3.1 ~Out~-function
*/
template <class Alpha, ListExpr (*OutFun)( ListExpr, Word )>
ListExpr OutConstTemporalUnit( ListExpr typeInfo, Word value )
{
//1.get the address of the object and have a class object
ConstTemporalUnit<Alpha>* constunit = (ConstTemporalUnit<Alpha>*)(value.addr);
//2.test for undefined value
if ( !constunit->IsDefined() )
return (nl->SymbolAtom(Symbol::UNDEFINED()));
//3.get the time interval NL
ListExpr intervalList = nl->FourElemList(
datetime::OutDateTime( nl->TheEmptyList(),
SetWord(&constunit->timeInterval.start) ),
datetime::OutDateTime( nl->TheEmptyList(),
SetWord(&constunit->timeInterval.end) ),
nl->BoolAtom( constunit->timeInterval.lc ),
nl->BoolAtom( constunit->timeInterval.rc));
//4. return the final result
return nl->TwoElemList( intervalList,
OutFun( nl->TheEmptyList(),
SetWord( &constunit->constValue ) ) );
}
/*
5.3.2 ~In~-function
*/
template <class Alpha, Word (*InFun)( const ListExpr, const ListExpr,
const int, ListExpr&, bool& )>
Word InConstTemporalUnit( const ListExpr typeInfo,
const ListExpr instance,
const int errorPos,
ListExpr& errorInfo,
bool& correct )
{
std::string errmsg;
if( nl->ListLength( instance ) == 2 )
{
//1. deal with the time interval
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 *)datetime::InInstant( nl->TheEmptyList(),
nl->First( first ),
errorPos, errorInfo, correct ).addr;
if( !correct )
{
errmsg = "InConstTemporalUnit(): Error in first instant.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
delete start;
return SetWord( Address(0) );
}
Instant *end =
(Instant *)datetime::InInstant( nl->TheEmptyList(),
nl->Second( first ),
errorPos, errorInfo, correct ).addr;
if( !correct )
{
errmsg = "InConstTemporalUnit(): Error in second instant.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
delete start;
delete end;
return SetWord( Address(0) );
}
// get closedness parameters
bool lc = nl->BoolValue( nl->Third( first ) );
bool rc = nl->BoolValue( nl->Fourth( first ) );
Interval<Instant> tinterval( *start, *end, lc, rc );
delete start;
delete end;
// check, wether interval is well defined
correct = tinterval.IsValid();
if ( !correct )
{
errmsg = "InConstTemporalUnit(): Non valid time interval.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
return SetWord( Address(0) );
}
//2. deal with the alpha value
Alpha *value = (Alpha *)InFun( nl->TheEmptyList(), nl->Second( instance ),
errorPos, errorInfo, correct ).addr;
//3. create the class object
if( correct )
{
ConstTemporalUnit<Alpha> *constunit =
new ConstTemporalUnit<Alpha>( tinterval, *value );
if( constunit->IsValid() )
{
delete value;
return SetWord( constunit );
}
delete constunit;
}
delete value;
}
}
else if ( listutils::isSymbolUndefined( instance ) )
{
ConstTemporalUnit<Alpha> *constunit =
new ConstTemporalUnit<Alpha>();
constunit->SetDefined(false);
constunit->timeInterval=
Interval<datetime::DateTime>(
datetime::DateTime(datetime::instanttype),
datetime::DateTime(datetime::instanttype),true,true);
correct = true;
return (SetWord( constunit ));
}
errmsg = "InConstTemporalUnit(): Error in representation.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
correct = false;
return SetWord( Address(0) );
}
/*
5.3.3 ~Create~-function
*/
template <class Alpha>
Word CreateConstTemporalUnit( const ListExpr typeInfo )
{
return (SetWord( new ConstTemporalUnit<Alpha>(false) ));
}
/*
5.3.4 ~Delete~-function
*/
template <class Alpha>
void DeleteConstTemporalUnit( const ListExpr typeInfo, Word& w )
{
delete (ConstTemporalUnit<Alpha> *)w.addr;
w.addr = 0;
}
/*
5.3.5 ~Close~-function
*/
template <class Alpha>
void CloseConstTemporalUnit( const ListExpr typeInfo, Word& w )
{
delete (ConstTemporalUnit<Alpha> *)w.addr;
w.addr = 0;
}
/*
5.3.6 ~Clone~-function
*/
template <class Alpha>
Word CloneConstTemporalUnit( const ListExpr typeInfo, const Word& w )
{
ConstTemporalUnit<Alpha> *constunit = (ConstTemporalUnit<Alpha> *)w.addr;
return SetWord( new ConstTemporalUnit<Alpha>( *constunit ) );
}
/*
5.3.7 ~Sizeof~-function
*/
template <class Alpha>
int SizeOfConstTemporalUnit()
{
return sizeof(ConstTemporalUnit<Alpha>);
}
/*
5.3.8 ~Cast~-function
*/
template <class Alpha>
void* CastConstTemporalUnit(void* addr)
{
return new (addr) ConstTemporalUnit<Alpha>;
}
/*
5.4 Type Constructor ~moving~
5.4.1 ~Out~-function
*/
template <class Mapping, class Unit,
ListExpr (*OutUnit)( ListExpr, Word )>
ListExpr OutMapping( ListExpr typeInfo, Word value )
{
Mapping* m = (Mapping*)(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++ )
{
Unit unit;
m->Get( i, unit );
unitList = OutUnit( nl->TheEmptyList(), SetWord(&unit) );
if( l == nl->TheEmptyList() )
{
l = nl->Cons( unitList, nl->TheEmptyList() );
lastElem = l;
}
else
lastElem = nl->Append( lastElem, unitList );
}
return l;
}
}
/*
5.6.2 ~In~-function
*/
template <class Mapping, class Unit,
Word (*InUnit)( const ListExpr, const ListExpr,
const int, ListExpr&, bool& )>
Word InMapping( const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr& errorInfo, bool& correct )
{
int numUnits = 0;
if(nl->AtomType(instance)==NoAtom){
numUnits = nl->ListLength(instance);
}
Mapping* m = new Mapping( numUnits );
correct = true;
int unitcounter = 0;
std::string errmsg;
m->StartBulkLoad();
ListExpr rest = instance;
if (nl->AtomType( rest ) != NoAtom)
{ if(listutils::isSymbolUndefined(rest)){
m->EndBulkLoad();
m->SetDefined(false);
return SetWord( Address( m ) );
} else {
correct = false;
m->Destroy();
delete m;
return SetWord( Address( 0 ) );
}
}
else while( !nl->IsEmpty( rest ) )
{
ListExpr first = nl->First( rest );
rest = nl->Rest( rest );
Unit *unit = (Unit*)InUnit( nl->TheEmptyList(), first,
errorPos, errorInfo, correct ).addr;
if ( !correct )
{
errmsg = "InMapping(): Representation of Unit "
+ int2string(unitcounter) + " is wrong.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
m->Destroy();
delete m;
return SetWord( Address(0) );
}
if( /* correct && (...)*/ !unit->IsDefined() || !unit->IsValid() )
{
errmsg = "InMapping(): Unit " + int2string(unitcounter) + " is undef.";
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
correct = false;
delete unit;
m->Destroy();
delete m;
return SetWord( Address(0) );
}
m->Add( *unit );
unitcounter++;
delete unit;
}
if(! m->EndBulkLoad( true,true )){ // overlapping intervals found
m->Destroy();
delete m;
correct = false;
return SetWord(Address(0));
}
return SetWord( m );
}
/*
5.6.3 ~Open~-function
*/
template <class Mapping>
bool OpenMapping( SmiRecord& valueRecord,
const ListExpr typeInfo, Word& value )
{
Mapping *m = new Mapping( 0 );
m->Open( valueRecord, typeInfo );
value = SetWord( m );
return true;
}
/*
5.6.4 ~Save~-function
*/
template <class Mapping>
bool SaveMapping( SmiRecord& valueRecord,
const ListExpr typeInfo, Word& value )
{
Mapping *m = (Mapping *)value.addr;
m->Save( valueRecord, typeInfo );
return true;
}
/*
5.6.5 ~Create~-function
*/
template <class Mapping>
Word CreateMapping( const ListExpr typeInfo )
{
return (SetWord( new Mapping( 0 ) ));
}
/*
5.6.6 ~Delete~-function
*/
template <class Mapping>
void DeleteMapping( const ListExpr typeInfo, Word& w )
{
((Mapping *)w.addr)->Destroy();
delete (Mapping *)w.addr;
w.addr = 0;
}
/*
5.6.7 ~Close~-function
*/
template <class Mapping>
void CloseMapping( const ListExpr typeInfo, Word& w )
{
((Mapping *)w.addr)->DeleteIfAllowed();
w.addr = 0;
}
/*
5.6.8 ~Clone~-function
*/
template <class Mapping>
Word CloneMapping( const ListExpr typeInfo, const Word& w )
{
return SetWord( ((Mapping *)w.addr)->Clone() );
}
/*
5.6.9 ~Sizeof~-function
*/
template <class Mapping>
int SizeOfMapping()
{
return sizeof(Mapping);
}
/*
5.6.10 ~Cast~-function
*/
template <class Mapping>
void* CastMapping(void* addr)
{
return new (addr) Mapping;
}
/*
6 Operators value mapping template functions
6.1 Value mapping functions of operator ~isempty~
*/
template <class Mapping>
int MappingIsEmpty( Word* args, Word& result,
int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
((CcBool*)result.addr)->Set( true, ((Mapping*)args[0].addr)->IsEmpty() );
return 0;
}
template <class Unit>
int UnitIsEmpty( Word* args, Word& result,
int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
((CcBool*)result.addr)->Set( true, !((Unit*)args[0].addr)->IsDefined() );
return 0;
}
/*
6.2 Value mapping functions of operator $=$ (~equal~)
*/
template <class Mapping>
int MappingEqual( Word* args, Word& result,
int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
((CcBool*)result.addr)->Set(
true,
*((Mapping*)args[0].addr) == *((Mapping*)args[1].addr)
);
return 0;
}
/*
6.3 Value mapping functions of operator $\#$ (~not equal~)
*/
template <class Mapping>
int MappingNotEqual( Word* args, Word& result,
int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
((CcBool*)result.addr)->Set(
true,
*((Mapping*)args[0].addr) != *((Mapping*)args[1].addr)
);
return 0;
}
/*
6.4 Value mapping functions of operator ~inst~
*/
template <class Alpha>
int IntimeInst( Word* args, Word& result, int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
Intime<Alpha>* i = (Intime<Alpha>*)args[0].addr;
if( i->IsDefined() )
((Instant*)result.addr)->CopyFrom(
&((Intime<Alpha>*)args[0].addr)->instant );
else
((Instant*)result.addr)->SetDefined( false );
return 0;
}
/*
6.5 Value mapping functions of operator ~val~
*/
template <class Alpha>
int IntimeVal( Word* args, Word& result, int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
Intime<Alpha>* i = (Intime<Alpha>*)args[0].addr;
if( i->IsDefined() )
((Alpha*)result.addr)->CopyFrom( &((Intime<Alpha>*)args[0].addr)->value );
else
((Alpha*)result.addr)->SetDefined( false );
return 0;
}
/*
6.5 Value mapping functions of operator ~uval~
Return a constant unit's value
*/
template <class Alpha,class Beta>
int UIntimeVal( Word* args, Word& result, int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
Alpha* i = (Alpha*)args[0].addr;
if( i->IsDefined())
((Beta*)result.addr)->Set(true,i->constValue.GetValue());
else
((Beta*)result.addr)->SetDefined( false );
return 0;
}
/*
6.6 Value mapping functions of operator ~no\_components~
*/
template <class Mapping, class Alpha>
int MappingNoComponents( Word* args, Word& result,
int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
Mapping* m = ((Mapping*)args[0].addr);
if( m->IsDefined() ){
((CcInt*)result.addr)->Set( true,
((Mapping*)args[0].addr)->GetNoComponents() );
} else {
((CcInt*)result.addr)->Set( false, 0 );
}
return 0;
}
/*
6.7 Value mapping functions of operator ~atinstant~
*/
template <class Mapping, class Alpha>
int MappingAtInstant( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
Intime<Alpha>* pResult = (Intime<Alpha>*)result.addr;
((Mapping*)args[0].addr)->AtInstant( *((Instant*)args[1].addr), *pResult );
return 0;
}
/*
6.8 Value mapping functions of operator ~atperiods~
*/
template <class Mapping>
int MappingAtPeriods( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
((Mapping*)args[0].addr)->AtPeriods( *((Periods*)args[1].addr),
*((Mapping*)result.addr) );
return 0;
}
/*
Value mapping functions of operator ~when~
*/
template <class Mapping>
int MappingWhen( Word* args, Word& result, int message,
Word& local, Supplier s )
{
result = qp->ResultStorage( s );
MBool* mb= static_cast<MBool*>(args[1].addr);
MBool mbTrue(0);
CcBool tru(true, true);
mb->At(tru, mbTrue);
Periods p(0);
mbTrue.DefTime(p);
((Mapping*)args[0].addr)->AtPeriods( p, *((Mapping*)result.addr) );
return 0;
}
/*
6.9 Value mapping functions of operator ~deftime~
*/
template <class Mapping>
int MappingDefTime( Word* args, Word& result,
int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
((Mapping*)args[0].addr)->DefTime( *(Periods*)result.addr );
return 0;
}
/*
6.10 Value mapping functions of operator ~present~
*/
template <class Mapping>
int MappingPresent_i( Word* args, Word& result,
int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
Mapping *m = ((Mapping*)args[0].addr);
Instant* inst = ((Instant*)args[1].addr);
if( !m->IsDefined() || !inst->IsDefined() )
((CcBool *)result.addr)->Set( false, false );
else
((CcBool *)result.addr)->Set( true, m->Present( *inst ) );
return 0;
}
template <class Mapping>
int MappingPresent_p( Word* args, Word& result,
int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
Mapping *m = ((Mapping*)args[0].addr);
Periods* periods = ((Periods*)args[1].addr);
if( !m->IsDefined() || !periods->IsDefined() || periods->IsEmpty() )
((CcBool *)result.addr)->Set( false, false );
else
((CcBool *)result.addr)->Set( true, m->Present( *periods ) );
return 0;
}
/*
6.11 Value mapping functions of operator ~passes~
*/
template <class Mapping, class Alpha, class Beta>
int MappingPasses( Word* args, Word& result,
int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
Mapping *m = ((Mapping*)args[0].addr);
Beta* val = ((Beta*)args[1].addr);
if( !m->IsDefined() || !val->IsDefined() )
((CcBool *)result.addr)->Set( false, false );
else
((CcBool *)result.addr)->Set( true, m->Passes( *val ) );
return 0;
}
/*
6.12 Value mapping functions of operator ~initial~
*/
template <class Mapping, class Unit, class Alpha>
int MappingInitial( Word* args, Word& result,
int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
((Mapping*)args[0].addr)->Initial( *((Intime<Alpha>*)result.addr) );
return 0;
}
/*
6.13 Value mapping functions of operator ~final~
*/
template <class Mapping, class Unit, class Alpha>
int MappingFinal( Word* args, Word& result,
int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
((Mapping*)args[0].addr)->Final( *((Intime<Alpha>*)result.addr) );
return 0;
}
/*
6.14 Value mapping functions of operator ~at~
*/
template <class Mapping, class Unit, class Alpha>
int MappingAt( Word* args, Word& result, int message, Word& local, Supplier s )
{
result = qp->ResultStorage( s );
Mapping *m = ((Mapping*)args[0].addr);
Alpha* val = ((Alpha*)args[1].addr);
Mapping* pResult = ((Mapping*)result.addr);
m->At( *val, *pResult );
return 0;
}
/*
6.15 Value mapping functions of operator ~units~
*/
template <class Mapping, class Unit>
class UnitsLocalInfo
{
public:
int unitIndex; // current item index (unit to be processed next)
int noUnits; // no of all units within the mapping m
double totalSize; // attrExtSize of the mapping m (incl. FLOBs)
double attrSize; // attrSize (without FLOBs)
double attrSizeExt; // average attrSizeExt (withFlob)
bool progressinitialized;
double feedunittime;
bool sonIsObjectNode;
UnitsLocalInfo(Mapping *m, const Supplier &s) :
unitIndex(0), noUnits(-1), totalSize(0.0), attrSize(0.0),
attrSizeExt(0.0), progressinitialized(false), feedunittime(0.0001),
sonIsObjectNode(false) {
Unit u(false);
attrSizeExt = ((double)(u.Sizeof()));
attrSize = attrSizeExt;
if(m->IsDefined()) {
noUnits = m->GetNoComponents();
if(noUnits > 0) { // compute and add FLOB size
for(int f = 0; f < m->NumOfFLOBs(); f++) {
totalSize += m->GetFLOB(f)->getSize();
}
attrSizeExt += ( totalSize / ((double)noUnits) );
}
} else {
unitIndex = -1; // will provoke "CANCEL" on first REQUEST
}
feedunittime = 0.00042 * attrSizeExt;
sonIsObjectNode = qp->IsObjectNode(qp->GetSupplierSon(s,0));
}
~UnitsLocalInfo() {}
};
template <class Mapping, class Unit>
int MappingUnits(Word* args, Word& result, int message, Word& local, Supplier s)
{
Mapping* m = static_cast<Mapping*>(args[0].addr);
UnitsLocalInfo<Mapping, Unit> *localinfo =
static_cast<UnitsLocalInfo<Mapping, Unit> *>(local.addr);
#ifdef USE_PROGRESS
ProgressInfo *pRes = (ProgressInfo*) result.addr;
ProgressInfo p1;
#endif
switch( message )
{
case OPEN:
if(localinfo){
delete localinfo;
}
localinfo = new UnitsLocalInfo<Mapping, Unit>(m, s);
local = SetWord(localinfo);
return 0;
case REQUEST:
if( local.addr == 0 ) {
return CANCEL;
} else if( localinfo->unitIndex < localinfo->noUnits ) {
Unit unit(true);
m->Get( localinfo->unitIndex++, unit );
result = SetWord( unit.Clone());
return YIELD;
} else {
return CANCEL;
}
case CLOSE:
#ifndef USE_PROGRESS
if( local.addr != 0 )
{
delete localinfo;
local = SetWord(Address(0));
}
#endif
return 0;
#ifdef USE_PROGRESS
case REQUESTPROGRESS:
if(local.addr == 0) {
return CANCEL;
}
if( !localinfo->sonIsObjectNode
&& qp->RequestProgress(qp->GetSon(s,0), &p1) ) {
// the son is a computed result node
// just copy everything
pRes->CopyBlocking(p1);
pRes->Time = p1.Time;
} else {
// the son is a database object or constant
pRes->BTime = 0.00001; // no blocking time
pRes->BProgress = 1.0; // non-blocking
pRes->Time = 0.00001; // (almost) zero runtime
}
if(!localinfo->progressinitialized){
pRes->Card = (double) std::max(0,localinfo->noUnits); // cardinality
pRes->Size = localinfo->attrSize; // total size
pRes->SizeExt = localinfo->attrSizeExt; // size w/o FLOBS
pRes->noAttrs = 1; //no of attributes
pRes->attrSize = &(localinfo->attrSize);
pRes->attrSizeExt = &(localinfo->attrSizeExt);
localinfo->progressinitialized = true;
pRes->sizesChanged = true; //sizes have been recomputed
localinfo->progressinitialized = true;
} else {
pRes->Card = (double) std::max(0,localinfo->noUnits); // cardinality
pRes->sizesChanged = false;
}
if( (localinfo->noUnits > 0)
&& (localinfo->unitIndex < localinfo->noUnits) ){
pRes->Progress = ((double)localinfo->unitIndex)
/ ((double)localinfo->noUnits);
pRes->Time += ((double)(localinfo->noUnits - localinfo->unitIndex))
* localinfo->feedunittime;
} else {
pRes->Progress = 1.0;
pRes->Time = 0.00001;
}
return YIELD;
case CLOSEPROGRESS:
if( local.addr != 0 )
{
delete localinfo;
local = SetWord(Address(0));
}
return 0;
#endif
}
/* should not happen */
return -1;
}
template <class Mapping, class Unit>
int MappingGetUnit
(Word* args, Word& result, int message, Word& local, Supplier s)
{
Mapping* m = static_cast<Mapping*>(args[0].addr);
result = qp->ResultStorage( s );
CcInt* index = ((CcInt*)args[1].addr);
Unit* pResult = ((Unit*)result.addr);
if(!m->IsDefined() || m->GetNoComponents()==0 || index->GetIntval() < 0 ||
index->GetIntval() >= m->GetNoComponents())
{
pResult->SetDefined(false);
return 0;
}
m->Get( index->GetIntval(), *pResult );
return 0;
}
template<class Mapping>
int MappingGetPosition(Word* args, Word& result, int message, Word& local,
Supplier s) {
result = qp->ResultStorage(s);
CcInt *res = static_cast<CcInt*>(result.addr);
Mapping *m = static_cast<Mapping*>(args[0].addr);
Instant *inst = static_cast<Instant*>(args[1].addr);
if (!m->IsDefined() || !inst->IsDefined()) {
res->SetDefined(false);
return 0;
}
int pos = m->Position(*inst);
if (pos == -1) {
res->SetDefined(false);
return 0;
}
res->Set(true, m->Position(*inst));
return 0;
}
template <class Mapping, class Unit>
int MappingTimeShift( Word* args, Word& result,
int message, Word& local, Supplier s )
{
Word t;
datetime::DateTime* dd;
Unit unit;
Mapping* mapping, *mpResult;
result = qp->ResultStorage( s );
mapping= (Mapping*)args[0].addr,
mpResult = (Mapping*)result.addr;
mpResult->Clear();
dd = (datetime::DateTime *)args[1].addr;
if( mapping->IsDefined() &&
dd->IsDefined() )
{
mpResult->SetDefined( true );
if(mapping->GetNoComponents() == 0)
return 0;
mapping->Get(0, unit);
mpResult->StartBulkLoad();
for( int i = 0; i < mapping->GetNoComponents(); i++ )
{
mapping->Get( i, unit );
Unit aux( unit );
aux.timeInterval.start.Add(dd);
aux.timeInterval.end.Add(dd);
mpResult->Add(aux);
}
mpResult->EndBulkLoad();
return 0;
}
else
{
mpResult->SetDefined( false );
return 0;
}
}
/*
7.0 Refinement Partition
*/
template<class Mapping1, class Mapping2, class Unit1, class Unit2>
class RefinementPartition {
private:
/*
Private attributes:
* ~iv~: Array (vector) of sub-intervals, which has been calculated from the
unit intervals of the ~Mapping~ instances.
* ~vur~: Maps intervals in ~iv~ to indices of original units in first
~Mapping~ instance. A $-1$ values indicates that interval in ~iv~ is no
sub-interval of any unit interval in first ~Mapping~ instance.
* ~vup~: Same as ~vur~ for second mapping instance.
*/
std::vector< Interval<Instant> > iv;
std::vector<int> vur;
std::vector<int> vup;
/*
~AddUnit()~ is a small helper method to create a new interval from
~start~ and ~end~ instant and ~lc~ and ~rc~ flags and to add these to the
~iv~, ~vur~ and ~vup~ vectors.
*/
void AddUnits(const int urPos,
const int upPos,
const Instant& start,
const Instant& end,
const bool lc,
const bool rc,
const Mapping1& map1,
const Mapping2& map2);
public:
/*
The constructor creates the refinement partition from the two ~Mapping~
instances ~mr~ and ~mp~.
Runtime is $O(\max(n, m))$ with $n$ and $m$ the numbers of units in
~mr~ and ~mp~.
*Preconditions*: mr.IsDefined AND mp.IsDefiened()
*/
RefinementPartition(const Mapping1& mr, const Mapping2& mp);
/*
Since the elements of ~iv~ point to dynamically allocated objects, we need
a destructor.
*/
~RefinementPartition();
/*
Return the number of intervals in the refinement partition.
*/
unsigned int Size(void);
/*
Return the interval and indices in original units of position $pos$ in
the refinement partition in the referenced variables ~civ~, ~ur~ and
~up~. Remember that ~ur~ or ~up~ may be $-1$ if interval is no sub-interval
of unit intervals in the respective ~Mapping~ instance.
Runtime is $O(1)$.
You can use
----
void TemporalUnit<Alpha>::AtInterval(const Interval<Instant> &i,
TemporalUnit<Alpha> &result)
----
to access the broken-down units
*/
void Get(const unsigned int pos,
Interval<Instant>& civ,
int& ur,
int& up);
};
template<class Mapping1, class Mapping2, class Unit1, class Unit2>
unsigned int RefinementPartition<Mapping1, Mapping2, Unit1, Unit2>
::Size(void)
{
return iv.size();
}
template<class Mapping1, class Mapping2, class Unit1, class Unit2>
void RefinementPartition<Mapping1, Mapping2, Unit1, Unit2>
::Get(const unsigned int pos, Interval<Instant>& civ, int& ur,
int& up)
{
assert(pos < iv.size());
civ = iv[pos];
ur = vur[pos];
up = vup[pos];
}
template<class Mapping1, class Mapping2, class Unit1, class Unit2>
void RefinementPartition<Mapping1, Mapping2, Unit1,
Unit2>::AddUnits( const int urPos, const int upPos,
const Instant& start, const Instant& end,
const bool lc, const bool rc,
const Mapping1& map1, const Mapping2& map2)
{
REF_DEBUG(
"RP::AddUnits() ["<<start.ToString()<<" "
<<end.ToString()<<" "<<lc<<" "<<rc<<"] "<<urPos<<" "<<upPos)
assert(urPos!=-1 || upPos!=-1);
assert( start.IsDefined() && end.IsDefined() );
if( (start==end) && !(lc && rc)){ // invalid interval
return;
}
if(start.Adjacent(&end) && !(lc || rc)){ // invalid interval
return;
}
Interval<Instant> civ(start, end, lc, rc);
iv.push_back(civ);
vur.push_back(urPos);
vup.push_back(upPos);
}
template<class Mapping1, class Mapping2, class Unit1, class Unit2>
RefinementPartition<Mapping1, Mapping2, Unit1,
Unit2>::RefinementPartition( const Mapping1& m1, const Mapping2& m2 )
{
assert( m1.IsDefined() );
assert( m2.IsDefined() );
iv.clear();
vur.clear();
vup.clear();
REF_DEBUG("RefinedmentPartition called ");
int no1 = m1.GetNoComponents();
int no2 = m2.GetNoComponents();
if(no1 + no2 == 0){ // both mappings are empty
REF_DEBUG("empty mappings");
return;
}
if(no2==0){ // m2 is empty
REF_DEBUG("m2 is empty");
iv.reserve(no1);
vur.reserve(no1);
vup.reserve(no1);
Unit1 u1;
for(int i=0;i<no1;i++){
m1.Get(i,u1);
AddUnits(i,-1,u1.timeInterval.start, u1.timeInterval.end,
u1.timeInterval.lc, u1.timeInterval.rc,m1, m2);
}
return;
}
if(no1==0){ // m1 is empty
REF_DEBUG("m1 is empty " );
iv.reserve(no2);
vur.reserve(no2);
vup.reserve(no2);
Unit2 u2;
for(int i=0;i<no2;i++){
m2.Get(i,u2);
AddUnits(-1,i,u2.timeInterval.start, u2.timeInterval.end,
u2.timeInterval.lc, u2.timeInterval.rc,m1, m2);
}
return;
}
// both arguments are non-empty
int maxsize = (no1 + no2 + 2) * 2;
iv.reserve(maxsize);
vur.reserve(maxsize);
vup.reserve(maxsize);
Unit1 u1p;
Unit2 u2p;
m1.Get(0,u1p);
m2.Get(0,u2p);
// create editable units from the constant ones
Interval<Instant> t1(u1p.timeInterval);
Interval<Instant> t2(u2p.timeInterval);
int pos1 = 0;
int pos2 = 0;
REF_DEBUG("both arguments are non-empty");
REF_DEBUG("no1 = " << no1 );
REF_DEBUG("no2 = " << no2 );
while( (pos1<no1) && (pos2<no2) ){
REF_DEBUG("pos1 = " << pos1 );
REF_DEBUG("pos2 = " << pos2 );
REF_DEBUG("t1 = " << t1);
REF_DEBUG("t2 = " << t2);
// both arguments have units
if(t1.start < t2.start){
REF_DEBUG("case 1: t1 starts before t2 " );
// t1 starts before t2
if(t1.end < t2.start){ // t1 before t2
REF_DEBUG("case 1.1: t1 ends before t2 starts" );
AddUnits(pos1, -1, t1.start, t1.end, t1.lc, t1.rc,m1,m2);
pos1++;
if(pos1 < no1){
m1.Get(pos1, u1p);
t1 = u1p.timeInterval;
}
} else if(t1.end > t2.start){
REF_DEBUG("case 1.2: t1 ends after t2 starts" );
// overlapping intervals
AddUnits(pos1, -1, t1.start, t2.start, t1.lc, !t2.lc,m1,m2);
t1.start = t2.start;
t1.lc = t2.lc;
} else { // u1.timeInterval.end == u2.timeInterval.start
REF_DEBUG("case 1.3: t1 ends when t2 starts ");
if( !t1.rc || !t2.lc){
REF_DEBUG("case 1.3.1: t1 ends before t2 starts (closeness) " );
// u1 before u2
AddUnits(pos1, -1, t1.start, t1.end, t1.lc, t1.rc,m1,m2);
pos1++;
if(pos1 < no1){
m1.Get(pos1,u1p);
t1 = u1p.timeInterval;
}
} else { // intervals have a common instant
REF_DEBUG("case 1.3.2: t2 ends when t2 starts (common instant)");
AddUnits(pos1, -1, t1.start, t1.end, t1.lc, false,m1,m2);
t1.lc = true;
t1.start = t2.start;
}
}
} else if(t2.start < t1.start){
REF_DEBUG("case 2: t2 starts before t1 starts" );
// symmetric case , u2 starts before u1
if(t2.end < t1.start){ // u2 before u1
REF_DEBUG("case 2.1: t2 ends before t1 ends ");
AddUnits(-1, pos2, t2.start, t2.end, t2.lc, t2.rc,m1,m2);
pos2++;
if(pos2 < no2){
m2.Get(pos2,u2p);
t2 = u2p.timeInterval;
}
} else if(t2.end > t1.start){
REF_DEBUG("case 2.2: t2 ends after t1 starts");
// overlapping intervals
AddUnits(-1, pos2, t2.start, t1.start, t2.lc, !t1.lc,m1,m2);
t2.start = t1.start;
t2.lc = t1.lc;
} else { // u1.timeInterval.end == u2.timeInterval.start
REF_DEBUG("case 2.3: t2 ends when t1 starts" );
if( !t2.rc || !t1.lc){
REF_DEBUG("case 2.3.1: t2 ends before t1 starts (closeness)" );
// u1 before u2
AddUnits(-1, pos2, t2.start, t2.end, t2.lc, t2.rc,m1,m2);
pos2++;
if(pos2 < no2){
m2.Get(pos2,u2p);
t2 = u2p.timeInterval;
}
} else { // intervals have a common instant
REF_DEBUG("case 2.3.2: t2 ends when t1 starts (common instant)");
AddUnits(-1, pos2, t2.start, t2.end, t2.lc, false,m1,m2);
t2.lc = true;
t2.start = t1.start;
}
}
} else { // u1.timeInterval.start == u2.timeInterval.start
REF_DEBUG("case 3: t1 and t2 start at the same instant" );
// both intervals start at the same instant
if(t1.lc != t2.lc){
REF_DEBUG("case 3.1: membership of the instant differs");
if(t1.lc){ // add a single instant interval
AddUnits(pos1, -1, t1.start, t1.start, true,true,m1,m2);
if(t1.start == t1.end){ // u1 exhausted
pos1++;
if(pos1< no1){
m1.Get(pos1,u1p);
t1 = u1p.timeInterval;
}
} else {
t1.lc = false;
}
} else {
// symmetric case
AddUnits(-1, pos2, t2.start, t2.start, true, true,m1,m2);
if(t2.start == t2.end){
pos2++;
if(pos2 < no2){
m2.Get(pos2, u2p);
t2 = u2p.timeInterval;
}
} else {
t2.lc = false;
}
}
} else { // intervals start exact at the same instant
REF_DEBUG("case 3.2: intervalls start exact together");
if(t1.end < t2.end){
REF_DEBUG("case 3.2.1: t1 ends before t2 ends");
AddUnits(pos1, pos2, t1.start, t1.end, t1.lc, t1.rc,m1,m2);
t2.start = t1.end;
t2.lc = !t1.rc;
pos1++;
if(pos1<no1){
m1.Get(pos1,u1p);
t1 = u1p.timeInterval;
}
} else if (t2.end < t1.end){
REF_DEBUG("case 3.2.2: t2 ends before t1 ends" );
AddUnits(pos1, pos2, t2.start, t2.end, t2.lc, t2.rc,m1,m2);
t1.start = t2.end;
t1.lc = !t2.rc;
pos2++;
if(pos2 < no2){
m2.Get(pos2,u2p);
t2 = u2p.timeInterval;
}
} else { // both units end at the same instant
REF_DEBUG("case 3.2.3: both intervals ends at the same instant");
if(t1.rc == t2.rc){ // equal intervals
REF_DEBUG("case 3.2.3.1: intervals are equal" );
AddUnits(pos1, pos2, t1.start, t1.end, t1.lc, t1.rc,m1,m2);
pos1++;
if(pos1 < no1){
m1.Get(pos1,u1p);
t1 = u1p.timeInterval;
}
pos2++;
if(pos2 < no2){
m2.Get(pos2, u2p);
t2 = u2p.timeInterval;
}
} else {
REF_DEBUG("case 3.2.3.2: intervals differ at right closeness");
// process common part
AddUnits(pos1,pos2,t1.start, t1.end, t1.lc, false,m1,m2);
if(t1.rc){
pos2++;
if(pos2<no2){
m2.Get(pos2,u2p);
t2 = u2p.timeInterval;
}
t1.lc = true;
t1.start = t1.end;
} else {
pos1++;
if(pos1 < no1){
m1.Get(pos1,u1p);
t1 = u1p.timeInterval;
}
t2.lc = true;
t2.start = t2.end;
}
}
}
}
}
}
REF_DEBUG("one of the arguments is finished");
// process remainder of m1
while(pos1 < no1){
AddUnits(pos1, -1, t1.start, t1.end, t1.lc, t1.rc,m1,m2);
pos1++;
if(pos1<no1){
m1.Get(pos1,u1p);
t1 = u1p.timeInterval;
}
}
// process remainder of m2
while(pos2 < no2){
AddUnits(-1, pos2, t2.start, t2.end, t2.lc, t2.rc,m1,m2);
pos2++;
if(pos2<no2){
m2.Get(pos2,u2p);
t2 = u2p.timeInterval;
}
}
}
template<class Mapping1, class Mapping2, class Unit1, class Unit2>
RefinementPartition<Mapping1, Mapping2, Unit1,
Unit2>::~RefinementPartition() {
REF_DEBUG("RP::~RP() called" );
}
/*
7.7.7 functions ~DistanceAvg~ for MPoint and CMPoint
*/
template<class M, class U>
struct DistanceComputation{
static void DistanceAvg(const M& mp1, const M& mp2,
const datetime::DateTime& duration,
const bool upperBound, CcReal& result, const Geoid* geoid = 0) {
if (!mp1.IsDefined() || !mp2.IsDefined() || (geoid && !geoid->IsDefined())) {
result.SetDefined(false);
return;
}
result.Set(true, roundToNPlaces(DistanceAvg(mp1, mp2, duration, upperBound,
geoid), 6));
}
static double DistanceAvg(const M& mp1, const M& mp2,
const datetime::DateTime& duration,
const bool upperBound, const Geoid* geoid = 0) {
assert(duration.GetType() == datetime::durationtype);
if (!mp1.IsDefined() || !mp2.IsDefined() || (geoid && !geoid->IsDefined())) {
return -1.0;
}
if (mp1 == mp2) {
return 0.0;
}
if (mp1.IsEmpty() || mp2.IsEmpty()) {
return DBL_MAX;
}
// cout << "original: " << mp1 << endl << mp2 << endl << endl;
MappingNoFlob<M, U> m1(mp1.GetNoComponents()), m2(mp2.GetNoComponents());
ForceToDuration<M, U>(mp1, duration, true, m1, geoid);
ForceToDuration<M, U>(mp2, duration, true, m2, geoid);
if (mp1.Compare(&mp2) == -1) {
std::swap(m1, m2);
}
double durTemp(0.0), sum(0.0);
U u1(true), u2(true), u1cut(true), u2cut(true), up1(true), up2(true);
RefinementPartition<MappingNoFlob<M, U>, MappingNoFlob<M, U>, U, U> rp(m1,m2);
int u1Pos, u2Pos;
Interval<Instant> iv;
std::stack<std::pair<double, unsigned int> > integralSt;
for (unsigned int i = 0; i < rp.Size(); i++) {
rp.Get(i, iv, u1Pos, u2Pos);
m1.Get(u1Pos, u1);
u1.AtInterval(iv, u1cut, geoid);
u1cut.SetRadius(u1.GetRadius());
m2.Get(u2Pos, u2);
u2.AtInterval(iv, u2cut, geoid);
u2cut.SetRadius(u2.GetRadius());
assert(u1cut.IsDefined() && u2cut.IsDefined());
durTemp += (iv.end - iv.start).ToDouble();
std::pair<double, unsigned int> stackElem(u1cut.DistanceIntegral(u2cut,
upperBound, geoid), 0);
while (!integralSt.empty() && integralSt.top().second == stackElem.second) {
stackElem.first += integralSt.top().first;
stackElem.second++;
integralSt.pop();
}
integralSt.push(stackElem);
}
while (!integralSt.empty()) {
sum += integralSt.top().first;
integralSt.pop();
}
// datetime::DateTime dur(datetime::durationtype);
// dur.ReadFrom(durTemp);
// cout << "DistanceAvg, integral SUM is " << sum << ", DURATION is "
// << dur << endl << endl << endl;
return sum / durTemp;
}
};
template<class Unittype>
class CComparator_before{ // create a strict ordering function
public:
bool operator() (const Unittype &i, const Unittype &j) {
return i.StartsBefore(j);
}
};
/*
The following template function consolidates a vector of units:
As a preliminary step, the argument vector will be sorted by starting
instant and leftclosedness. Then, all undefined or invalid units are removed.
It restricts remaining units to the Interval ~intv~ and arranges them in such a
way, that consecutive units do not overlap temporally.
The elements in the result of this function can be consecutively added to any ~Mapping<UnitType,AlphaType>~
The return value is ~false~, iff the units pairwisely overlap in more than a
single instant.
*Precondition*: Units may not intersect despite in single points, where they
must have the same temporal value.
*Precondition*: The class parameter ~UnitType~ must be a class inheriting from ~Attribute~ AND ~TemporalUnit<AlphaType>~.
*Precondition*: The class parameter ~AlphaType~ must be a class inheriting from ~Attribute~.
*/
template<class UnitType, class AlphaType>
bool ConsolidateUnitVector(
const Interval<Instant> &intv,
std::vector<UnitType> &arg,
std::vector<UnitType> &result) {
assert( intv.IsValid() );
result.clear();
// sort tmpresult by starting time (and leftclosedness)
CComparator_before<UnitType> my_comparator_before;
sort(arg.begin(), arg.end(), my_comparator_before);
// do the consolidation
UnitType lastUnit(false), currUnit(false);
for(unsigned int i=0; i<arg.size(); i++) {
// cout << "======================================================" << endl;
// cout << "Iteration " << i << ":" << endl;
// cout << "\tintv = " << intv << endl;
// cout << "\tlastUnit = " << lastUnit << endl;
// cout << "\tcurrUnit = " << arg[i] << endl;
UnitType u_full = arg[i];
if( !u_full.IsDefined() || !u_full.IsValid() ) { // drop invalid units
// cout << "\tcurrUnit is UNDEF or invalid. --> CONTINUE."
// << arg[i] << endl;
continue;
}
if(!intv.Intersects(u_full.timeInterval)){
continue;
}
u_full.AtInterval( intv, currUnit ); // restrict to intv
// cout << "\tRestricting currUnit to intv:" << endl;
// cout << "\tcurrUnit := " << currUnit << endl;
if(!currUnit.IsDefined() || !currUnit.IsValid() ) { // drop invaild result
// cout << "\tcurrUnit is UNDEF or invalid. --> CONTINUE."
// << arg[i] << endl;
continue;
}
if(!lastUnit.IsDefined()) { // nothing to match with, keep currUnit
// cout << "\tlastUnit is UNDEF. --> lastUnit := currUnit." << endl;
lastUnit = currUnit;
continue;
}
if(lastUnit.timeInterval == currUnit.timeInterval) {
// identical timeIntervals
if(lastUnit != currUnit) {
std::cerr << __PRETTY_FUNCTION__
<< "WARNING: same interval, but different values" << std::endl;
result.clear();
return false;
} else { // same units --> drop currUnit
// cout << "\tlastUnit and currUnit have same time Interval. "
// << "--> CONTINUE." << endl;
continue;
}
}
if(lastUnit.timeInterval.Inside(currUnit.timeInterval)){
// lastUnit contained by currUnit
lastUnit = currUnit; // drop lastUnit
// cout << "\tlastUnit inside currUnit. --> lastUnit := currUnit."
// << endl;
continue;
}
if(currUnit.timeInterval.Inside(lastUnit.timeInterval)){
// lastUnit contains currUnit
// cout << "\tlastUnit contains currUnit. --> CONTINUE." << endl;
continue; // drop currUnit
}
if(lastUnit.timeInterval.end == currUnit.timeInterval.start) {
// cout << "\tlastUnit and currUnit have common endpoint..." << endl;
// lastUnit and currUnit share a common boundary point at least
// (but are not identical - that has been handled above)
// handle all the closedness and point/interval combinations
if(lastUnit.timeInterval.rc){
if(currUnit.timeInterval.lc){
// rc - lc: ...a][a...
AlphaType lastVal, currVal;
lastUnit.TemporalFunction(lastUnit.timeInterval.end, lastVal, true);
currUnit.TemporalFunction(currUnit.timeInterval.start,currVal, true);
if( lastVal.CompareAlmost(static_cast<Attribute*>(&currVal)) != 0) {
std::cerr << __PRETTY_FUNCTION__
<< " ERROR: Two units share an endpoint"
<< ", but have different temporal values at that instant: "
<< std::endl << "\tlastUnit = " << lastUnit << ", lastVal = " ;
lastVal.Print(std::cerr);
std::cerr << std::endl << "\tcurrUnit = "
<< currUnit << ", currVal = " ;
lastVal.Print(std::cerr);
std::cerr << std::endl;
result.clear();
return false;
}
if(lastUnit.IsInstantUnit()){
if(currUnit.IsInstantUnit()){
// [aa][aa]: Drop lastUnit, keep currUnit
// should already be dealt with
lastUnit = currUnit;
// cout << "\tCase: [aa][aa]. ---> lastUnit = currUnit." << endl;
continue;
} else {
// [aa] [a---: Drop lastUnit, keep currUnit
lastUnit = currUnit;
// cout << "\tCase: [aa] [a---. ---> lastUnit = currUnit."
// << endl;
continue;
}
} else {
if(currUnit.IsInstantUnit()){
// ---a] [aa]: drop currUnit, keep lastUnit
// cout << "\tCase: ---a] [aa]. ---> CONTINUE." << endl;
continue;
} else {
// ---a] [a---: append rightopen lastUnit. Keep currUnit
// one could also try to merge the units and keep the merged unit
if(!lastUnit.Merge(currUnit)) {
lastUnit.timeInterval.rc = false;
result.push_back(lastUnit);
// cout << "\tCase: ---a] [a---. ---> Cannot merge units. "
// << "Change and append lastUnit to the result. lastUnit "
// << ":= currUnit" << endl;
// cout << "\t\tappending: " << lastUnit << endl;
lastUnit = currUnit;
continue;
} else {
// cout << "\tCase: ---a] [a---. ---> Merged units. lastUnit "
// << ":= " << lastUnit << endl;
continue;
}
}
}
} else {
// rc - lo: ...]]...
if(lastUnit.IsInstantUnit()){
// [aa] ]a---: modify currUnit and keep it
// cout << "\tCase: [aa] ]a---. ---> merge lastUnit with currUnit:"
// << endl;
currUnit.timeInterval.lc = true;
lastUnit = currUnit;
// cout << "\t\tmerged unit: " << lastUnit << endl;
continue;
} else {
// ---a] ]a---: No problem.
result.push_back(lastUnit);
// cout << "\tCase: ---a] ]a---. ---> Append lastUnit:" << endl;
// cout << "\t\tAppended: " << lastUnit << endl;
lastUnit = currUnit;
continue;
}
}
} else { // lastUnit has rightopen interval
if(currUnit.timeInterval.rc){
// ro - lc: ...a[[a...:
if(currUnit.IsInstantUnit()){
// ..a[ [aa]: Merge currUnit into lastUnit. Keep modified lastUnit
AlphaType lastVal, currVal;
lastUnit.TemporalFunction(lastUnit.timeInterval.end, lastVal,true);
currUnit.TemporalFunction(currUnit.timeInterval.start,currVal,true);
if( lastVal.CompareAlmost(static_cast<Attribute*>(&currVal)) == 0 ){
// units can be merged: Merge both into lastUnit, drop currUnit
lastUnit.timeInterval.rc = true;
// cout << "\tCase: ..a[ [aa]. ---> merge lastUnit with currUnit:"
// << endl;
// cout << "\t\tmerged unit: " << lastUnit << endl;
continue;
} else {
// units cannot be merged: Output lastUnit, keep currUnit
result.push_back(lastUnit);
// cout << "\tCase: ..a[ [aa]. ---> cannot merge lastUnit with "
// << "currUnit:" << endl;
// cout << "\t\tAppended: " << lastUnit << endl;
lastUnit = currUnit;
continue;
}
} else {
// ...a[ [a---: No problem: Output lastUnit, keep currUnit.
result.push_back(lastUnit);
// cout << "\tCase: ...a[ [a---" << endl;
// cout << "\t\tAppended: " << lastUnit << endl;
lastUnit = currUnit;
continue;
}
} else {
// ro - lo: ...a[]a...: No problem: Output lastUnit, keep currUnit.
result.push_back(lastUnit);
// cout << "\tCase: ...a[]a..." << endl;
// cout << "\t\tAppended: " << lastUnit << endl;
lastUnit = currUnit;
continue;
}
}
}
if(!currUnit.timeInterval.Intersects(lastUnit.timeInterval)){
// lastUnit and lastUnit do NOT overlap at all
// cout << "\tCase: lastUnit and currUnit do not overlap and have no "
// <<common endpoint." << endl;
// cout << "\t\tAppended: " << lastUnit << endl;
result.push_back(lastUnit);
lastUnit = currUnit;
continue;
} else {
// lastUnit and currUnit overlap, but have not a single common boundary
// point. This shoulöd be a misstake! There is no way to merge the units:
std::cerr << __PRETTY_FUNCTION__
<< " ERROR: Two units overlap, but in more "
<< "than a single point:" << std::endl << "\tlastUnit = " << lastUnit
<< std::endl << "\tcurrUnit = " << currUnit << std::endl;
result.clear();
return false;
}
}
// possibly insert remaining lastUnit:
// cout << "========================================================" << endl;
// cout << "Aftermath:" << endl;
// cout << "\tintv = " << intv << endl;
// cout << "\tlastUnit = " << lastUnit << endl;
if(lastUnit.IsDefined()) {
// cout << "\t\tAppended: " << lastUnit << endl;
result.push_back(lastUnit);
}
// cout << "========================================================" << endl;
// cout << "Finished." << endl;
return true;
}
/*
3 Type definitions moved here from TemporalExtAlgebra.h
The types UString and MString was defined to implement the data types
~ustring~ and ~mapping(string)~ according to the declared defintions in the
signature for moving objects. The types RBool and RString was declared in order
to implement the data types ~range(bool)~ and ~range(string)~. They are
also part of the signature for moving objects.
*/
typedef ConstTemporalUnit<CcString> UString;
typedef Mapping< UString, CcString > MString;
typedef Range<CcBool> RBool;
typedef Range<CcString> RString;
}
#endif // _TEMPORAL_ALGEBRA_H_