Files
secondo/Algebras/Periodic/PMPoint.cpp

2543 lines
67 KiB
C++
Raw Permalink Normal View History

2026-01-23 17:03:45 +08:00
/*
1.1 ~PMPoint~
~includes~
*/
#include <iostream>
#include <string>
#include <iostream>
#include <sstream>
#include <math.h>
#include <vector>
#include "NestedList.h"
#include "PeriodicTypes.h"
#include "PeriodicSupport.h"
#include "Algebras/Spatial/SpatialAlgebra.h"
#include "Algebras/Temporal/TemporalAlgebra.h"
#include "TopRel.h"
#include "StandardTypes.h"
#include "DateTime.h"
#include "List2.h"
#include "RepTree.h"
#include "NodeTypes.h"
#include "Tools/Flob/DbArray.h"
using namespace std;
using namespace datetime;
namespace periodic {
/*
~Constructor~
This constructor does nothing
*/
PMPoint::PMPoint(){}
/*
~Constructor~
This constructor creates an undefined periodic moving point.
The argument of this constructor is ignored. The reason for the
parameter is to make this constructor distinct from the standard
constructor which must be nothing.
[3] O(1)
*/
PMPoint::PMPoint(int dummy):
Attribute(false),
linearMoves(0),
compositeMoves(0),
compositeSubMoves(0),
periodicMoves(0),
canDelete(false),
interval(0),
startTime(instanttype),
bbox(0)
{ __TRACE__
}
/*
~Copy Constructor~
*/
PMPoint::PMPoint(const PMPoint& source):
Attribute(source.IsDefined()),
linearMoves(0), compositeMoves(0), compositeSubMoves(0),
periodicMoves(0), canDelete(false), interval(0),
startTime(instanttype), bbox(0){
Equalize(&source);
}
PMPoint& PMPoint::operator=(const PMPoint& source){
Equalize(&source);
return *this;
}
/*
~Destructor~
[3] O(1)
*/
PMPoint::~PMPoint(){
__TRACE__
if(canDelete){
if(linearMoves.Size()>0) linearMoves.Destroy();
if(compositeMoves.Size()>0) compositeMoves.Destroy();
if(compositeSubMoves.Size()>0) compositeSubMoves.Destroy();
if(periodicMoves.Size()>0) periodicMoves.Destroy();
}
}
/*
~Destroy~
[3] O(1)
*/
void PMPoint::Destroy(){
__TRACE__
canDelete=true;
}
/*
~Equalize~
This functions changes the value of this periodic moving point
to be equals to the given parameter.
[3] O(L), where L is the number of linear moves
*/
void PMPoint::Equalize(const PMPoint* P2){
__TRACE__
// equalize the linear moves
Attribute::operator=(*P2);
linearMoves.copyFrom(P2->linearMoves);
compositeMoves.copyFrom(P2->compositeMoves);
compositeSubMoves.copyFrom(P2->compositeSubMoves);
periodicMoves.copyFrom(P2->periodicMoves);
SetDefined(P2->IsDefined());
interval.Equalize(&(P2->interval));
startTime.Equalize(&(P2->startTime));
bbox.Equalize(&(P2->bbox));
submove.Equalize(&(P2->submove));
}
/*
~Statistical Information~
*/
size_t PMPoint::NumberOfNodes()const{
return linearMoves.Size() +
compositeMoves.Size() +
periodicMoves.Size() +
1;
}
size_t PMPoint::NumberOfCompositeNodes()const{
return compositeMoves.Size();
}
size_t PMPoint::NumberOfPeriodicNodes()const{
return periodicMoves.Size();
}
size_t PMPoint::NumberOfUnits()const{
return linearMoves.Size();
}
size_t PMPoint::NumberOfFlatUnits()const{
if(!IsDefined()){
return 0;
}
size_t res = NumberOfFlatNodes(submove);
return res;
}
/*
~NumberOfFlatNodes~
This function computes the number of units of the flat representation
for the given subtree. The periodic moving point itself has to be defined.
Complexity: O(n) where n is the number of nodes within this tree
*/
size_t PMPoint::NumberOfFlatNodes(const SubMove sm)const{
int type = sm.arrayNumber;
switch(type){
case LINEAR:{
LinearPointMove LM;
linearMoves.Get(sm.arrayIndex,LM);
if(LM.IsDefined()){
return 1;
}else{
return 0;
}
}
case PERIOD:{
SpatialPeriodicMove PM(0);
periodicMoves.Get(sm.arrayIndex,PM);
size_t subsize;
subsize = NumberOfFlatNodes(PM.submove);
return (PM.repeatations)*subsize;
}
case COMPOSITE: {
SpatialCompositeMove CM(0);
size_t res;
res = 0;
CSubMove csm;
compositeMoves.Get(sm.arrayIndex,CM);
for(int i=CM.minIndex; i<=CM.maxIndex;i++){
compositeSubMoves.Get(i,csm);
res += NumberOfFlatNodes(csm);
}
return res;
}
default: cerr << "invalid submove found " << endl <<__POS__ <<endl;
assert(false);
}
}
/*
~IsEmpty~
Checks whether this point contains any positions.
*/
bool PMPoint::IsEmpty()const{
return linearMoves.Size()==0;
}
/*
~NumOfFLOBs~
This function returns the number of contained FLOBs in this
class. Because four DBarrays are managed her, the return value
is 4.
[3] O(1)
*/
int PMPoint::NumOfFLOBs() const{
__TRACE__
return 4;
}
/*
~GetFLOB~
This function returns the FLOB with index i.
[3] O(1)
*/
Flob* PMPoint::GetFLOB(const int i){
__TRACE__
assert(i>=0 && i<NumOfFLOBs());
Flob* res=0;
switch(i){
case 0 : res = &linearMoves; break;
case 1 : res = &compositeMoves;break;
case 2 : res = &compositeSubMoves;break;
case 3 : res = &periodicMoves;break;
}
return res;
}
/*
~Compare~
This function is not implemented at this moment.
[3] O(-1)
*/
int PMPoint::Compare(const Attribute*)const{
__TRACE__
cout << " Warning! PMPoint::Compare not implemented" << endl;
return 0;
}
/*
~Adjacent~
We can't define a adjacent relation beween two periodic moving
points. For this reason the return value is allways __false__.
[3] O(1)
*/
bool PMPoint::Adjacent(const Attribute* ) const{
__TRACE__
return false;
}
/*
~Clone~
The ~Clone~ function returns a copy of this.
[3] O(L)
*/
PMPoint* PMPoint::Clone() const{
__TRACE__
PMPoint* copy = new PMPoint(0);
copy->Equalize(this);
return copy;
}
/*
~Sizeof~
This function returns the size of the PMPoint-class
[3] O(1)
*/
size_t PMPoint::Sizeof() const{
__TRACE__
return sizeof(PMPoint);
}
/*
~HashValue~
Returns the HashValue for this Point.
[3] O(1)
*/
size_t PMPoint::HashValue()const{
__TRACE__
DateTime* L = interval.GetLength();
size_t res = (size_t) (bbox.Size()+(int)L->GetDay());
delete L;
L = NULL;
return res;
}
/*
~CopyFrom~
The PMPoint instance takes its value from the given argument.
The caller has to ensure that __arg__ is of type PMPoint.
[3] O(L)
*/
void PMPoint::CopyFrom(const Attribute* arg){
__TRACE__
Equalize(static_cast<const PMPoint*>(arg));
}
/*
~ToListExpr~
This function returns the ListExpr representing this point.
The flag which is the argument constrols whether only the
value list is returned or whether a list with structure
(type value) will be returned.
[3] O(L)
*/
ListExpr PMPoint::ToListExpr(const bool typeincluded)const{
__TRACE__
ListExpr timelist = startTime.ToListExpr(false);
ListExpr SubMoveList;
if(IsDefined())
SubMoveList = GetSubMoveList(&submove);
else
SubMoveList = ::nl->SymbolAtom("undefined");
if(typeincluded)
return ::nl->TwoElemList(
::nl->SymbolAtom("pmpoint"),
::nl->TwoElemList(
timelist,
SubMoveList));
else
return ::nl->TwoElemList(timelist,SubMoveList);
}
ListExpr PMPoint::ToListExpr(const ListExpr typeInfo)const{
return ToListExpr(false);
}
/*
~GetSubMove~
This functions determines the move from the given argument and
returns its nested list representation.
[3] O($L_{SM}$) , where $L_{SM}$ is the number of linear moves contained in SM
*/
ListExpr PMPoint::GetSubMoveList(const SubMove* SM)const{
__TRACE__
ListExpr SubMoveList;
int SubMoveType = SM->arrayNumber;
int index = SM->arrayIndex;
if(SubMoveType==LINEAR)
SubMoveList = GetLinearMoveList(index);
else if(SubMoveType==COMPOSITE)
SubMoveList = GetSpatialCompositeMoveList(index);
else if(SubMoveType==PERIOD)
SubMoveList = GetSpatialPeriodicMoveList(index);
else{
cerr << "unknown submove type detected" << SubMoveType << endl;
cerr << __POS__ << " Error in creating ListExpr" << endl;
assert(false);
}
return SubMoveList;
}
/*
~GetLinearMove~
This functions returns the nested list representation of the
linear move at the specified index.
[3] O(1)
*/
ListExpr PMPoint::GetLinearMoveList(const int index)const{
__TRACE__
LinearPointMove LM;
linearMoves.Get(index,LM);
return LM.ToListExpr();
}
/*
~GetSpatialPeriodicMove~
This function converts the periodic move at the specified index
to its nested list representation.
[3] O($L_{P}$), where $L_{P}$ is the number of linear moves in the
periodic move at index
*/
ListExpr PMPoint::GetSpatialPeriodicMoveList(const int index)const{
__TRACE__
SpatialPeriodicMove PM(0);
periodicMoves.Get(index,PM);
ListExpr periodtype = ::nl->SymbolAtom("period");
ListExpr RepList = ::nl->IntAtom(PM.repeatations);
ListExpr SML = GetSubMoveList(&(PM.submove));
ListExpr LC = ::nl->BoolAtom(PM.interval.IsLeftClosed());
ListExpr RC = ::nl->BoolAtom(PM.interval.IsRightClosed());
return ::nl->TwoElemList(periodtype,::nl->FourElemList(RepList,LC,RC,SML));
}
/*
~GetSpatialCompositeMoveList~
This function returns the nested list representation of the composite
move at the specified array index.
[3] O(L) , where L is the number of submoves contained in the linear
move at index
*/
ListExpr PMPoint::GetSpatialCompositeMoveList(const int index)const{
__TRACE__
SpatialCompositeMove CM(0);
compositeMoves.Get(index,CM);
ListExpr CType = ::nl->SymbolAtom("composite");
int minIndex = CM.minIndex;
int maxIndex = CM.maxIndex;
ListExpr SubMovesList;
if(maxIndex<minIndex){
cerr << __POS__ << "empty composite move" << endl;
SubMovesList = ::nl->TheEmptyList();
}
else{
// construct the List of submoves
CSubMove SM;
compositeSubMoves.Get(minIndex,SM);
SubMovesList = ::nl->OneElemList(GetSubMoveList(&SM));
ListExpr Last = SubMovesList;
for(int i=minIndex+1;i<=maxIndex;i++){
compositeSubMoves.Get(i,SM);
Last = ::nl->Append(Last,GetSubMoveList(&SM));
}
}
return ::nl->TwoElemList(CType,SubMovesList);
}
/*
~ReadFrom~
This function reads the value of this p.m. point from the
given nested list. If the nested list don't contains a
valid point, the return value will be false and this point
is set to be undefined. Otherwise the point has the value
described in the nested list. The list consist only of the
the value, this means the type description is not included
in this list.
[3] O(L) where L = number of linear moves
*/
bool PMPoint::ReadFrom(const ListExpr value, const ListExpr typeInfo){
__TRACE__
/* The list is scanned twice. In the first scan we
compute only the needed size for each of the contained arrays.
This is done to avoid a frequently resize of the arrays which
would lead to a lot of overhead for copying the contents.
*/
if(::nl->ListLength(value)!=2){
if(DEBUG_MODE){
cerr << __POS__ << ": wrong listlength (";
cerr << (::nl->ListLength(value)) << ")" << endl;
}
SetDefined(false);
return false;
}
if(!ResizeArrays(value)){
if(DEBUG_MODE){
cerr << __POS__ << ": resize array failed" << endl;
}
SetDefined(false);
return false;
}
if(!startTime.ReadFrom(::nl->First(value),false)){
if(DEBUG_MODE){
cerr << __POS__ << "reading of the start time failed" << endl;
cerr << "The list is " << endl;
::nl->WriteListExpr(::nl->First(value));
}
SetDefined(false);
return false;
}
// now we have to append the included submove
ListExpr SML = ::nl->Second(value);
if(::nl->ListLength(SML)!=2){
if(DEBUG_MODE){
cerr << __POS__ << ": wrong list length for submove" << endl;
}
SetDefined(false);
return false;
}
// get the submove type
ListExpr SMT = ::nl->First(SML);
int LMIndex = 0;
int CMIndex = 0;
int SMIndex = 0;
int PMIndex = 0;
if(::nl->IsEqual(SMT,"linear")){
submove.arrayNumber = LINEAR;
submove.arrayIndex = 0;
if(!AddLinearMove(::nl->Second(SML),LMIndex,CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
cerr << __POS__ << " Error in reading linear move" << endl;
}
SetDefined(false);
return false;
}
SetDefined(true);
// read out the interval and the bounding box from the
// created linear move
LinearPointMove LM;
linearMoves.Get(0,LM);
interval.Equalize(&(LM.interval));
bbox.Equalize((LM.BoundingBox()));
CorrectDurationSums();
return true;
}
if(::nl->IsEqual(SMT,"composite")){
submove.arrayNumber=COMPOSITE;
submove.arrayIndex = 0;
if(!AddSpatialCompositeMove(::nl->Second(SML),LMIndex,
CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
cerr << __POS__ << "error in reading composite move" << endl;
}
SetDefined(false);
return false;
}
SetDefined(true);
// get interval and bounding box from this move
SpatialCompositeMove CM(0);
compositeMoves.Get(0,CM);
interval.Equalize(&(CM.interval));
bbox.Equalize(&(CM.bbox));
CorrectDurationSums();
return true;
}
if(::nl->IsEqual(SMT,"period")){
submove.arrayNumber = PERIOD;
submove.arrayIndex = 0;
if(!AddPeriodMove(::nl->Second(SML),LMIndex,CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
cerr << __POS__ << " error in reading periodic move" << endl;
}
SetDefined(false);
return false;
}
SetDefined(true);
// get interval as well as bounding box
SpatialPeriodicMove PM(0);
periodicMoves.Get(0,PM);
interval.Equalize(&(PM.interval));
bbox.Equalize(&(PM.bbox));
CorrectDurationSums();
return true;
}
if(DEBUG_MODE){
cerr << __POS__ << "unknown subtype" << endl;
::nl->WriteListExpr(SMT);
}
return false;
}
PMPoint* PMPoint::Intersection(const PInterval* interval){
__TRACE__
PMPoint* result = new PMPoint(1);
PInterval MyInterval=PInterval(this->startTime,this->interval);
if(!(MyInterval.Intersects(interval))){
return result; // return an empty pmpoint
}
if(interval->Contains(&MyInterval)){
result->Equalize(this);
return result; // return a copy of this
}
int Lcount,Ccount,Scount,Pcount; // sizes for the arrays
Lcount = Ccount = Scount = Pcount = 0; // no move
DateTime* tmpTime = startTime.Clone();
AddSubMovesSizeForIntersection(tmpTime,submove,interval,
Lcount,Ccount,Scount,Pcount);
if(Lcount>0) result->linearMoves.resize(Lcount);
if(Ccount>0) result->compositeMoves.resize(Ccount);
if(Scount>0) result->compositeSubMoves.resize(Scount);
if(Pcount>0) result->compositeSubMoves.resize(Pcount);
// in a first step we count the array-sizes
cout << "PMPOINT::Intersection(temporalalgebra::Interval) not implemented ";
cout << __POS__ << endl;
return 0;
}
/*
~computeSubMovesSizeForIntersection~
This function computes the array sizes needed by the result of the intersection
of the calling periodic moving point instance with the given interval.
*/
void PMPoint::AddSubMovesSizeForIntersection(DateTime* startTime,
const SubMove submove, const PInterval* interval,
int &Lcount,int &Ccount, int &Scount,int &Pcount){
__TRACE__
int number = submove.arrayNumber;
if(number==LINEAR){
LinearPointMove LM;
linearMoves.Get(submove.arrayIndex,LM);
PInterval i = PInterval((*startTime) , LM.interval);
if(i.Intersects(interval))
Lcount++;
startTime->Add(LM.interval.GetLength());
}
if(number==COMPOSITE){
SpatialCompositeMove CM(0);
compositeMoves.Get(submove.arrayIndex,CM);
int start = CM.minIndex;
int end = CM.maxIndex;
int sm=0;
bool stop = false;
for(int s=start;s<=end && !stop;s++){
int oldL = Lcount;
int oldC = Ccount;
int oldP = Pcount;
CSubMove SM;
compositeSubMoves.Get(s,SM);
AddSubMovesSizeForIntersection(startTime,SM,interval,Lcount,
Ccount,Scount,Pcount);
if( (Lcount!=oldL) || (Ccount != oldC) || (Pcount != oldP))
sm++;
else
stop = true;
}
if(sm>1){
Ccount ++;
Scount += sm;
}
}
if(number==PERIOD){
SpatialPeriodicMove PM(0);
periodicMoves.Get(submove.arrayIndex,PM);
//SubMove PSM = PM.submove;
cout << __POS__ << "NOT IMPLEMENTED" << endl;
/* wenn PeriodicMOve-Intervall in geg.
temporalalgebra::Interval enthalten
erhoehe um alle enthaltenen Submoves
wenn Intervall vor SubMOve-Intervall beendet,
mache mit SubMoves weiter
sonst fuege alle vollstaendig enthaltenen Perioden hinzu
weiterhin ein Composite Move (welches Periode und Rest verbindet
bearbeite den Rest */
}
}
/*
~PrintArrayContents~
This function is for debugging purposes. It prints out the
contents of the arrays contained within this
periodic moving point.
*/
void PMPoint::PrintArrayContents(){
int size = periodicMoves.Size();
cout << "PERIDICMOVES" << endl;
SpatialPeriodicMove PM(0);
for(int i=0;i<size;i++){
periodicMoves.Get(i,PM);
cout << PM.ToString() << endl;
}
cout << "CompositeMOVES" << endl;
size = compositeMoves.Size();
SpatialCompositeMove CM(0);
for(int i=0;i<size;i++){
compositeMoves.Get(i,CM);
cout << CM.ToString() << endl;
}
cout << "CompositeSubMoves " << endl;
size = compositeSubMoves.Size();
CSubMove SM;
for(int i=0;i<size;i++){
compositeSubMoves.Get(i,SM);
cout << SM.ToString() << endl;
}
}
/*
~CheckCorrectness~
This function checks whether the representation of this
periodic moving point is correct. This means
* no directly nested composite moves exists
* no directly nested periodic moves exists
* a composite move has at least two submoves
[3] O(n) , where n is the number of moves
*/
bool PMPoint::CheckCorrectness(){
__TRACE__
CSubMove SM;
size_t linearSize = linearMoves.Size();
size_t periodSize = periodicMoves.Size();
size_t compositeSize = compositeMoves.Size();
size_t compositeSubSize = compositeSubMoves.Size();
for(size_t i=0; i<compositeSubSize;i++){
compositeSubMoves.Get(i,SM);
size_t an = SM.arrayNumber;
size_t index = SM.arrayIndex;
switch(an){
case COMPOSITE:
if(DEBUG_MODE){
cerr << __POS__ << "nested compositeMove detected" << endl;
}
return false;
case PERIOD:
if(index>=periodSize){
if(DEBUG_MODE){
cerr << __POS__ << "array index " << index
<< "out of bounds " << periodSize << endl;
}
return false;
}
break;
case LINEAR:
if(index>=linearSize){
if(DEBUG_MODE){
cerr << __POS__ << "array index " << index
<< "out of bounds " << linearSize << endl;
}
return false;
}
break;
default:
if(DEBUG_MODE){
cerr << __POS__ << "unknown submove found " << an << endl;
}
return false;
}
}
// check for direcly nested periodic moves
SpatialPeriodicMove PM(0);
for(int i=0; i<periodicMoves.Size();i++){
periodicMoves.Get(i,PM);
int an = PM.submove.arrayNumber;
size_t index = PM.submove.arrayIndex;
switch(an){
case COMPOSITE:
if(index>=compositeSize){
if(DEBUG_MODE){
cerr << __POS__ << "array index " << index
<< "out of bounds " << compositeSize << endl;
}
PrintArrayContents();
return false;
}
break;
case PERIOD:
cerr << __POS__ << "nested periodic move detected" << endl;
PrintArrayContents();
return false;
case LINEAR:
if(index>=linearSize){
if(DEBUG_MODE){
cerr << __POS__ << "array index " << index
<< "out of bounds " << linearSize << endl;
PrintArrayContents();
}
return false;
}
break;
default:
if(DEBUG_MODE){
cerr << __POS__ << "unknown submove found " << endl;
}
return false;
}
if(PM.repeatations<2){
cerr << __POS__ << "invalid number of repetitions detected" << endl;
PrintArrayContents();
return false;
}
}
// check for composite moves with only one submove
SpatialCompositeMove CM(0);
for(int i=0;i<compositeMoves.Size();i++){
compositeMoves.Get(i,CM);
if(CM.minIndex>=CM.maxIndex){
if(DEBUG_MODE){
cerr << __POS__
<< "composite move with a single submove detected"
<< endl;
}
return false;
}
if(CM.maxIndex>=(int)compositeSubSize){
if(DEBUG_MODE){
cerr << __POS__ << "invalid submove position detcetd" << endl;
}
return false;
}
}
return true;
}
/*
~ResizeArrays~
This function resizes the array to the values needed to include
all move types in the list. Note that a call of this function
changes this point even though the list don't represent a
valid periodic moving point. This function should be used before
a periodic moving point is read from a nested list. The disadvantage
is the twice scanning of the lsit, but a frequently resize of the
array can be avoided.
[3] O(L), where L is the number of contained linear moves
*/
bool PMPoint::ResizeArrays(const ListExpr value){
__TRACE__
// first all entries in the arrays are removed
linearMoves.clean();
compositeMoves.clean();
compositeSubMoves.clean();
periodicMoves.clean();
int LMSize = 0;
int CMSize = 0;
int SMSize = 0;
int PMSize = 0;
if(!AddSubMovesSize(::nl->Second(value),LMSize,CMSize,SMSize,PMSize))
return false;
// set the arrays to the needed size
if(LMSize>0) linearMoves.resize(LMSize);
if(CMSize>0) compositeMoves.resize(CMSize);
if(SMSize>0) compositeSubMoves.resize(SMSize);
if(PMSize>0) periodicMoves.resize(PMSize);
return true;
}
/*
~AddSubMovesSize~
This function computes the needed sizes for the arrays to hold the
value of the p.m. point represented in the value list.
[3] O(L), where L is the number of contained linear moves
*/
bool PMPoint::AddSubMovesSize(const ListExpr value,int &LMSize,int &CMSize,
int &SMSize,int &PMSize){
__TRACE__
// all moves have the length 2
if(::nl->ListLength(value)!=2){
return false;
}
ListExpr type = ::nl->First(value);
// the type has to be one of {linear, composite, period}
if(::nl->AtomType(type)!=SymbolType){
return false;
}
// in a linear move we have only to increment the size of LM
if(::nl->IsEqual(type,"linear")){
LMSize = LMSize +1;
return true;
}
if(::nl->IsEqual(type,"composite")){
CMSize = CMSize+1; // the composite move itself
ListExpr rest = ::nl->Second(value);
while(!::nl->IsEmpty(rest)){
SMSize++; // a new submove
if(!AddSubMovesSize(::nl->First(rest),LMSize,CMSize,SMSize,PMSize))
return false;
rest = ::nl->Rest(rest);
}
return true;
}
if(::nl->IsEqual(type,"period")){
PMSize = PMSize+1;
ListExpr PMove;
int len = ::nl->ListLength(value);
if(len==2){
PMove = ::nl->Second(value);
}
else{ // invalid listlength
return false;
}
return AddSubMovesSize(::nl->Second(PMove),LMSize,CMSize,SMSize,PMSize);
}
// a unknown type description
return false;
}
/*
~AddLinearMove~
This functions appends the linear move given as nested list in __value__
to the LinearMoves -array.
[3] O(1)
*/
bool PMPoint::AddLinearMove(const ListExpr value,int &LMIndex, int &CMIndex,
int &SMIndex, int &PMIndex){
__TRACE__
LinearPointMove LM(0);
if(!LM.ReadFrom(value))
return false;
linearMoves.Put(LMIndex,LM);
LMIndex++;
return true;
}
/*
~AddSpatialCompositeMove~
This Functions appends the composite move given as nested list together with
all contained submoves at the appropriate arrays. The return value indiciates
the success of this call.
[3] O(L), where L is the number of contained linear moves
*/
bool PMPoint::AddSpatialCompositeMove(const ListExpr value,int &LMIndex,
int &CMIndex, int &SMIndex, int &PMIndex){
__TRACE__
// a composite move has to contains at least two submoves
int len = ::nl->ListLength(value);
if(len<2){
if(DEBUG_MODE){
cerr << __POS__ << " less than 2 submoves (" << len << ")" << endl;
}
return false;
}
SpatialCompositeMove CM(1);
int CMPos=CMIndex;
// at this position we have to include this composite move
int SMPos=SMIndex;
// beginning at this position we have to include the submoves
// ensure that no submove used the positions for this composite move
CMIndex++;
CM.bbox.SetUndefined();
CM.minIndex=SMIndex;
CM.maxIndex=SMIndex+len-1;
SMIndex= SMIndex+len;
// Append the contained Submoves
ListExpr rest = value;
ListExpr SML,TL,VL;
bool isFirst = true;
while(!::nl->IsEmpty(rest)){
SML = ::nl->First(rest);
rest = ::nl->Rest(rest);
if(::nl->ListLength(SML)!=2){ // all submoves have the format (type value)
if(DEBUG_MODE){
cerr << __POS__ << " submove has wrong length (";
cerr << ::nl->ListLength(SML) << ")" << endl;
}
return false;
}
TL = ::nl->First(SML);
VL = ::nl->Second(SML);
if(::nl->IsEqual(TL,"linear")){
// process a linear submove
int LMPos = LMIndex;
if(!AddLinearMove(VL,LMIndex,CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
cerr << __POS__ << " can't add a linear move " << endl;
}
return false;
}
LinearPointMove LM;
linearMoves.Get(LMPos,LM);
// Append the interval of LM to CM
if(isFirst){
isFirst=false;
CM.interval.Equalize(&(LM.interval));
}else{
if(!CM.interval.Append(&(LM.interval))){
if(DEBUG_MODE){
cerr << __POS__ << " can't append interval ";
cerr << endl;
cerr << "The original interval is";
cerr << CM.interval.ToString() << endl;
cerr << "The interval to append is";
cerr << LM.interval.ToString() << endl;
}
return false;
}
}
// build the union of the bounding boxes of CM and LM
PBBox tmpbox(LM.BoundingBox());
CM.bbox.Union(&tmpbox);
// put the submove in the array
CSubMove SM;
SM.arrayNumber = LINEAR;
SM.arrayIndex = LMPos;
compositeSubMoves.Put(SMPos,SM);
SMPos++;
} else if(::nl->IsEqual(TL,"period")){
// process a periodic submove
int PMPos = PMIndex;
if(!AddPeriodMove(VL,LMIndex,CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
cerr << __POS__ << "can't add period move " << endl;
}
return false;
}
SpatialPeriodicMove PM(0);
periodicMoves.Get(PMPos,PM);
if(isFirst){
isFirst=false;
CM.interval.Equalize(&(PM.interval));
}else{
if(!CM.interval.Append(&(PM.interval))){
if(DEBUG_MODE){
cerr << __POS__ << " can't append interval" << endl;
}
return false;
}
}
CM.bbox.Union(&(PM.bbox));
CSubMove SM;
SM.arrayNumber = PERIOD;
SM.arrayIndex = PMPos;
compositeSubMoves.Put(SMPos,SM);
SMPos++;
} else{ // not of type linear or period
if(DEBUG_MODE){
cerr << __POS__
<< " submove not of type linear or period"
<< endl;
}
return false;
}
}
// put the compositeMove itself
compositeMoves.Put(CMPos,CM);
return true;
}
/*
~AddPeriodMove~
This functions append the periodic move contained in the nested list
__value__ to this periodic moving point.
[3] O(L), where L is the number of contained linear moves
*/
bool PMPoint::AddPeriodMove(const ListExpr value,int &LMIndex, int &CMIndex,
int &SMIndex, int &PMIndex){
__TRACE__
int len = ::nl->ListLength(value);
if(len!=2 ){ // (repeatations <submove>)
if(DEBUG_MODE)
cerr << __POS__ << ": wrong listlength" << endl;
return false;
}
if(::nl->AtomType(::nl->First(value))!=IntType){
if(DEBUG_MODE){
cerr << __POS__ << ": wrong type for repeatations" << endl;
}
return false;
}
int rep = ::nl->IntValue(::nl->First(value));
// rep must be greater than 1
if(rep<=1){
if(DEBUG_MODE){
cerr << __POS__ << " wrong number of repeatations" << endl;
}
return false;
}
ListExpr SML;
SML = ::nl->Second(value);
if(::nl->ListLength(SML)!=2){
if(DEBUG_MODE){
cerr << __POS__ << ": wrong length for submove" << endl;
}
return false;
}
SpatialPeriodicMove PM(1);
PM.repeatations = rep;
int IncludePos = PMIndex; // store the positiuon
PMIndex++;
ListExpr SMT = ::nl->First(SML); // take the submove type
if(::nl->IsEqual(SMT,"linear")){
int LMPos = LMIndex;
if(!AddLinearMove(::nl->Second(SML),LMIndex,CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
cerr << __POS__ << ": can't add linear submove" << endl;
}
return false;
}
PM.submove.arrayNumber = LINEAR;
PM.submove.arrayIndex = LMPos;
LinearPointMove LM;
linearMoves.Get(LMPos,LM);
PM.bbox.Equalize((LM.BoundingBox()));
RelInterval SMI = LM.interval;
PM.interval.Equalize(&SMI);
PM.interval.Mul(rep);
if(len==4){
ListExpr LC = ::nl->Second(value);
ListExpr RC = ::nl->Third(value);
if((::nl->AtomType(LC)!=BoolType) || (::nl->AtomType(RC)!=BoolType))
return false;
PM.interval.SetLeftClosed(::nl->BoolValue(LC));
PM.interval.SetRightClosed(::nl->BoolValue(RC));
}
periodicMoves.Put(IncludePos,PM);
return true;
}else if(::nl->IsEqual(SMT,"composite")){
int CMPos = CMIndex;
if(!AddSpatialCompositeMove(::nl->Second(SML),LMIndex,
CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
cerr << __POS__ << ": can't add composite submove" << endl;
}
return false;
}
PM.submove.arrayNumber = COMPOSITE;
PM.submove.arrayIndex = CMPos;
SpatialCompositeMove CM(0);
compositeMoves.Get(CMPos,CM);
PM.bbox.Equalize(&(CM.bbox));
RelInterval SMI = CM.interval;
PM.interval.Equalize(&SMI);
PM.interval.Mul(rep);
periodicMoves.Put(IncludePos,PM);
return true;
}
// not of type linear or composite
if(DEBUG_MODE){
cerr << __POS__ << ": invalid submove-type for periodic move" << endl;
cerr << "This list is : " << endl;
::nl->WriteListExpr(SMT);
cerr << endl << "end of list " << endl;
}
return false;
}
/*
~At~
This Function computes the location of this Point at the given instant.
If the periodic moving point is not defined at this point of time, the
result will be an undefined Point instance.
[3] O(L), where L is the number of contained linear moves
*/
void PMPoint::At(const DateTime* instant,Point& res)const{
__TRACE__
if(IsEmpty()){
res.SetDefined(false);
return;
}
res.SetDefined(true);
DateTime* duration = new DateTime(instanttype);
duration->Equalize(instant);
duration->Minus(&startTime); // now it is really a duration
if(!interval.Contains(duration)){
res.SetDefined(false);
} else{
const SubMove* sm = &submove;
SpatialCompositeMove CM(0);
SpatialPeriodicMove PM(0);
RelInterval RI;
// i have to find the linear move which is "active" at instant
while(sm->arrayNumber!=LINEAR){
if(sm->arrayNumber==COMPOSITE){
// in this stage of implementation a linear search is
// executed. i have to make it better in the future
int i = sm->arrayIndex;
compositeMoves.Get(i,CM);
int min = CM.minIndex;
int max = CM.maxIndex;
//bool found=false;
CSubMove csm;
// perform binary search
while(min<max){
int mid = (min+max)/2;
CSubMove csm;
compositeSubMoves.Get(mid,csm);
DateTime prev(csm.duration);
int cmp = duration->CompareTo(&prev);
if(cmp < 0){ // duration is before mid
max = mid-1;
}else if(cmp==0){
RelInterval ri;
GetInterval(csm,ri);
if(ri.IsLeftClosed()){ // begin of the mid interval
duration->SetToZero();
min = mid;
max = mid;
} else{ // end of the mid-1 interval
mid--;
compositeSubMoves.Get(mid,csm);
min = mid;
max = mid;
GetInterval(csm,ri); // set to the end of
// the mid-1 interval
DateTime l;
ri.GetLength(l);
duration->Equalize(&l);
}
} else{ // cmp>0 duration my be in mid or after it
RelInterval ri;
GetInterval(csm,ri);
DateTime len;
ri.GetLength(len);
DateTime sum = prev + len;
int cmp2 = duration->CompareTo(&sum);
if(cmp2<0){ // duration located in this interval
min = mid;
max = mid;
duration->Minus(&prev);
} else if(cmp2==0){
if(ri.IsRightClosed()){
min = mid;
max = mid;
duration->Minus(&prev);
} else{ // start of the following son
mid++;
compositeSubMoves.Get(mid,csm);
min = mid;
max = mid;
duration->SetToZero();
}
} else { // cmp2 > 0
min = mid+1;
}
}
}
compositeSubMoves.Get(min,csm);
//found = true;
SubMove sm1;
sm1.arrayNumber = csm.arrayNumber;
sm1.arrayIndex = csm.arrayIndex;
sm = &sm1;
} else if(sm->arrayNumber==PERIOD){
int index = sm->arrayIndex;
periodicMoves.Get(index,PM);
// this is a very slow implementation
// i have to speed up it in the future
RelInterval RI;
sm = &(PM.submove);
if(PM.submove.arrayNumber==LINEAR){
LinearPointMove LM;
linearMoves.Get(PM.submove.arrayIndex,LM);
RI = LM.interval;
} else if(PM.submove.arrayNumber==COMPOSITE){
compositeMoves.Get(PM.submove.arrayIndex,CM);
RI = CM.interval;
} else { //another submoves are not allowed
assert(false);
}
while(!RI.Contains(duration)){
DateTime* L = RI.GetLength();
duration->Minus(L);
delete L;
L = NULL;
}
} else{
// this case should never occurs
assert(false);
}
}
LinearPointMove LM;
linearMoves.Get(sm->arrayIndex,LM);
if(LM.IsDefinedAt(duration)){
LM.At(duration,res);
}
else{
res.SetDefined(false);
}
}
delete duration;
duration = NULL;
}
/*
~Initial~
This function computes the first location of this moving point.
*/
void PMPoint::Initial(Point& res)const{
__TRACE__
if(IsEmpty()){
res.SetDefined(false);
return;
}
LinearPointMove lm;
linearMoves.Get(0,lm);
res.SetDefined(true);
res.Set(lm.startX,lm.startY);
}
/*
~Final~
The ~Final~ function returns the last defined position of this point.
If the value is empty, an undefined point is returned.
*/
bool PMPoint::Final(Point& res){
__TRACE__
if(IsEmpty()){
res.SetDefined(false);
return false;
}
LinearPointMove lm = GetLastUnit();
res.SetDefined(true);
res.Set(lm.endX,lm.endY);
return true;
}
/*
~Translate~
Moves this PMPoint within time.
*/
void PMPoint::Translate(const DateTime& duration){
startTime += duration;
}
void PMPoint::Translate(const DateTime* duration,PMPoint& res)const{
res.Equalize(this);
res.startTime += *duration;
}
/*
~GetLastUnit~
This function returns the temporal last unit of this periodic moving point.
*/
LinearPointMove PMPoint::GetLastUnit(){
__TRACE__
// In the current version of the implementation we can just returm the
// last unit in the array. If the implementation is changed to reuse
// a subtree, we have to go the tree downwards to find it.
int pos = linearMoves.Size()-1;
LinearPointMove res;
linearMoves.Get(pos,res);
return res;
}
/*
~Breakpoints~
This function computes the coordinates on which halt's the
periodic moving point. The result corresponds to the
positions of static units. A call of this function is
an abbreviation to a call of breakpoints(d,false), where
__d__ is a duration of length zero.
[3] O(L) where L is the number of the contained linear moves.
*/
Points* PMPoint::Breakpoints()const{
Points* res = new Points(1);
Breakpoints(*res);
return res;
}
void PMPoint::Breakpoints(Points& res)const{
__TRACE__
DateTime DT(durationtype);
Breakpoints(&DT,false,res);
}
/*
~BreakPoints~
This function computes the breakpoints for this pmpoint. Only
Breakpoints with a minimum break with lenth __duration__ are included in the
result. If the duration is less than zero, the result will be
undefined. The same result will be occur if the duration is zero
and the inclusive argument is true.
*/
Points* PMPoint::Breakpoints(const DateTime* duration,
const bool inclusive)const{
Points* res = new Points(1);
Breakpoints(duration,inclusive,*res);
return res;
}
void PMPoint::Breakpoints(const DateTime* duration,
const bool inclusive,
Points& res)const{
__TRACE__
res.Clear();
if(!IsDefined() || !duration->IsDefined()){
res.SetDefined(false);
return;
}
if(duration->LessThanZero()){
res.SetDefined(false);
return;
}
if(duration->IsZero() && inclusive){
res.SetDefined(false);
return;
}
res.SetDefined(true);
int size = linearMoves.Size();
res.StartBulkLoad();
LinearPointMove LM;
for(int i=0; i<size; i++){
linearMoves.Get(i,LM);
if(LM.IsDefined() && LM.IsStatic()){
DateTime* L = LM.interval.GetLength();
int cmp = L->CompareTo(duration);
delete L;
if(cmp>0 || (cmp==0 && inclusive)){
Point P(true,LM.startX,LM.startY);
res += P;
}
}
}
res.EndBulkLoad();
}
/*
~Trajectory~
This function computes the trajectory of a single periodic moving point.
[3] O(L), where L is the number of contained linear moves
*/
void PMPoint::Trajectory(Line& res)const{
__TRACE__
LinearPointMove LM;
// each linear moves needs 2 halfsegments
res.Clear();
int size = linearMoves.Size();
if(size>0){
res.Resize(size*2);
}
res.StartBulkLoad();
HalfSegment HS1;
HalfSegment HS2;
int edge=0;
for(int i=0;i<size;i++){
linearMoves.Get(i,LM);
if(LM.IsDefined() && !LM.IsStatic() ){
bool hasHS1=LM.GetHalfSegment(true, HS1);
bool hasHS2=LM.GetHalfSegment(false, HS2);
if(hasHS1 && hasHS2){
HS1.attr.edgeno = edge;
HS2.attr.edgeno = edge;
edge++;
res+=HS1;
res+=HS2;
}
}
}
res.EndBulkLoad();
}
/*
~GetStart~
This function returns the first point in time at which this
PMPoint is defined.
*/
DateTime PMPoint::GetStart()const{
__TRACE__
return startTime;
}
/*
~GetEnd~
This function returns the last point in time at which this
PMPoint is defined.
*/
DateTime PMPoint::GetEnd()const{
__TRACE__
DateTime end;
end.Equalize(&startTime);
end.Add(interval.GetLength());
return end;
}
/*
~GetInterval~
Returns the interval of this periodic moving point.
*/
PInterval PMPoint::GetInterval()const{
__TRACE__
PInterval res=PInterval(startTime,interval);
return res;
}
/*
~Expand~
This function converts a periodic moving point to a linearly moving one.
The used data type comes from the TemporalAlgebra.
*/
temporalalgebra::MPoint PMPoint::Expand()const{
__TRACE__
// In a first step we compute the number of resulting units.
// The reason is, to avoid frequently growing of the result.
temporalalgebra::MPoint res(1);
Expand(res);
return res;
}
void PMPoint::Expand(temporalalgebra::MPoint& res)const{
__TRACE__
// In a first step we compute the number of resulting units.
// The reason is, to avoid frequently growing of the result.
int size = NumberOfExpandedUnits();
res.Clear();
if(size==0){
return;
}
res.Resize(size);
DateTime* CurrentTime = startTime.Clone();
res.StartBulkLoad();
AppendUnits(res, CurrentTime,submove);
res.EndBulkLoad(false);
delete CurrentTime;
}
/*
~AppendUnits~
The function ~AppendUnits~ adds all mpoint-units resulting from S to P.
*/
void PMPoint::AppendUnits(temporalalgebra::MPoint& P, DateTime* Time,
const SubMove S)const{
__TRACE__
if(S.arrayNumber==LINEAR){
// first create the Intervall
LinearPointMove LM;
linearMoves.Get(S.arrayIndex,LM);
DateTime* StartTime = new DateTime((*Time));
DateTime* length = LM.interval.GetLength();
Time->Add(length);
assert(!length->LessThanZero());
delete length;
length = NULL;
temporalalgebra::Interval<DateTime> I((*StartTime),(*Time),
LM.interval.IsLeftClosed(),
LM.interval.IsRightClosed());
temporalalgebra::UPoint up(I,LM.startX, LM.startY, LM.endX, LM.endY);
int size = P.GetNoComponents();
if(size > 0){
temporalalgebra::UPoint last;
P.Get(size-1,last);
if(last.timeInterval.rc && I.lc &&
last.timeInterval.end == I.start){
if(last.timeInterval.start == last.timeInterval.start){
P.Put(size - 1, up);
} else if(I.start != I.end){
up.timeInterval.lc=false;
P.MergeAdd(up);
} else {
;
}
} else {
P.MergeAdd(up);
}
} else {
P.MergeAdd(up);
}
delete StartTime;
StartTime = NULL;
return;
}
if (S.arrayNumber==COMPOSITE){
SpatialCompositeMove CM(0);
compositeMoves.Get(S.arrayIndex,CM);
CSubMove csm;
for(int i=CM.minIndex;i<=CM.maxIndex;i++){
compositeSubMoves.Get(i,csm);
AppendUnits(P,Time,csm);
}
return;
}
if(S.arrayNumber==PERIOD){
SpatialPeriodicMove PM(0);
periodicMoves.Get(S.arrayIndex,PM);
long repeats = PM.repeatations;
for(int i=0;i<repeats;i++)
AppendUnits(P,Time,PM.submove);
return;
}
assert(false);
}
/*
~NumberOfExpandedUnits~
This functions returns the number of needed units of a MPoint of the
TemporalAlgebra to represent this periodic moving point.
*/
int PMPoint::NumberOfExpandedUnits()const{
__TRACE__
if(!IsDefined())
return 0;
if(IsEmpty())
return 0;
return NumberOfExpandedUnits(submove);
}
/*
~NumberOfExpandedUnits~
This function computed the needed size of a MPoint of the TemporalAlgebra
to represent this periodic moving one.
*/
int PMPoint::NumberOfExpandedUnits(const SubMove S)const{
__TRACE__
if(S.arrayNumber==LINEAR)
return 1;
if(S.arrayNumber==COMPOSITE){
SpatialCompositeMove CM(0);
compositeMoves.Get(S.arrayIndex,CM);
int num = 0;
CSubMove sm;
for(int i=CM.minIndex;i<=CM.maxIndex;i++){
compositeSubMoves.Get(i,sm);
num += NumberOfExpandedUnits(sm);
}
return num;
}
if(S.arrayNumber==PERIOD){
SpatialPeriodicMove PM(0);
periodicMoves.Get(S.arrayIndex,PM);
int repeats = PM.repeatations;
return repeats*NumberOfExpandedUnits(PM.submove);
}
assert(false); // this should never be reached
}
/*
ReadFrom
This function reads a Periodic moving point from
a lineary moving one.
*/
void PMPoint::ReadFrom(const temporalalgebra::MPoint& P,
const bool twostep/* = true*/){
/* This function works as follow:
First, we create a list containing all LinearMovingPoints for this
Periodic Moving Points. After that, we find equal units in this list
and assign each different unit with an unique number. From this array
of numbers a repetition tree is build. This tree automatically detect
repetitions in this numberlist. From this tree, the final periodic moving
point is created.
*/
int noUPoints = P.GetNoComponents();
// Unfortunately, we can't use a array directly because we need to
// represent non-defined units directly which is not required in
// the MPoint representation.
List<LinearPointMove>* L= new List<LinearPointMove>();
temporalalgebra::UPoint UP;
bool lc,rc,wlc=false;
DateTime start,end;
double x1,y1,x2,y2;
// standard-init
SetDefined(true);
canDelete = false;
bbox.SetEmpty();
linearMoves.clean();
compositeMoves.clean();
compositeSubMoves.clean();
periodicMoves.clean();
temporalalgebra::UPoint LastMove;
if(noUPoints>0){ // we have any units
for(int i=0;i<noUPoints;i++){
P.Get(i,UP);
// get the values from the unit
lc = UP.timeInterval.lc;
rc = UP.timeInterval.rc;
start = UP.timeInterval.start;
end = UP.timeInterval.end;
x1 = UP.p0.GetX();
y1 = UP.p0.GetY();
x2 = UP.p1.GetX();
y2 = UP.p1.GetY();
DateTime Length = end-start;
LinearPointMove theMove(0);
theMove.defined=true;
theMove.isStatic = (x1==x2) && (y1==y2);
theMove.startX = x1;
theMove.startY = y1;
theMove.endX = x2;
theMove.endY = y2;
theMove.interval.Set(&Length,lc,rc);
theMove.interval.SetDefined(true);
// Add the bounding to to the complete bb
PBBox tmpbox(theMove.BoundingBox());
bbox.Union(&tmpbox);
if(i==0){
startTime = start; // sets the starttime
interval.SetDefined(true);
wlc = UP.timeInterval.lc;
}else {
if( ((LastMove.timeInterval.end != start)) ||
(!LastMove.timeInterval.rc && !lc)){
// a gap found between the last unit and this unit
LinearPointMove GapMove(0);
GapMove.defined=false; // an undefined move
DateTime GapLength = start-LastMove.timeInterval.end;
GapMove.interval.Set(&GapLength,
!LastMove.timeInterval.rc, !lc);
GapMove.interval.SetDefined(true);
L->Append(GapMove);
}
}
if(i==noUPoints-1){ // set new interval;
DateTime Len = end-startTime;
interval.Set(&Len,wlc,UP.timeInterval.rc);
}
L->Append(theMove);
LastMove = UP;
}
}else{ // no units available
// here we have to initialize some components
}
// At this point, we have stored all LinearPointsMoves in a List.
// now we have to build an array of numbers for it. To make this fast,
// we use a hashtable with double maximum size. We use closed hashing
// with a linear collision strategy.
int hashsize = L->GetLength()*2;
int MinIndex[hashsize]; // Hashtable containing the minimum
//index of this move
// in the AllMoves array
int LMIndex[hashsize]; // The same table but holding the indices in the
// resulting linear moves
// initialize the hashtable
for(int i=0;i<hashsize;i++){
MinIndex[i]=-1;
LMIndex[i] =-1;
}
int listlength=L->GetLength();
LinearPointMove* AllMoves = L->ConvertToArray();
int indexInAllMoves[listlength];
int indexInLinearMoves[listlength];
for(int i=0;i<listlength;i++){
indexInAllMoves[i] = -1;
indexInLinearMoves[i] = -1;
}
int differentMoves =0; // number of different linear moves
//int lastusedindex = -1;
if(twostep){
cout << "Warning time component ignored !!!" << endl;
}
// we assign each different value in the array to an unique number
for(int i=0;i<listlength;i++){
LinearPointMove theMove = AllMoves[i];
size_t hashvalue = theMove.HashValue()%hashsize;
// search a free index or the same move
bool done = false;
while(!done){
if(MinIndex[hashvalue]<0){ // empty slot found
// put the index of the move into the hashtable
MinIndex[hashvalue] = i;
LMIndex[hashvalue] = differentMoves;
//lastusedindex=i;
differentMoves++;
done = true;
}
else{
int cmp=twostep?
(AllMoves[MinIndex[hashvalue]]).CompareSpatial(&theMove)
:(AllMoves[MinIndex[hashvalue]]).CompareTo(&theMove);
if(cmp==0) {
//equal element found; we are done
done = true;
}
else{
hashvalue = (hashvalue+1)%hashsize; // collision detected
}
}
}
indexInAllMoves[i]= MinIndex[hashvalue];
indexInLinearMoves[i] = LMIndex[hashvalue];
}
/* At this in, in assigned numbers the complete moving point is stored
as sequel of array indices in the array AllMoves. Now we can build a
repetition tree from this numbers.
*/
RepTree RT(indexInLinearMoves,listlength);
/* Debugging output */
//RT.PrintNL();
if(twostep){
// in the twostep process it is possible that spatial repetations has
// been recognized but the temporal deviation is too much to accept that
// as a periodic move
// so we have to check all recognized periodic nodes for temporal
// deviations in the move
}
linearMoves.clean();
compositeMoves.clean();
compositeSubMoves.clean();
periodicMoves.clean();
if(listlength==0){
SetDefined(false);
canDelete=false;
}else{
SetDefined(true);
canDelete = false;
// set all array to the required sizes
if(differentMoves>0)
linearMoves.resize(differentMoves);
int size = RT.NumberOfNodesWithType(COMPOSITION);
if(size>0)
compositeMoves.resize(size);
size = RT.NumberOfNodesWithType(REPETITION);
if(size>0)
periodicMoves.resize(size);
size = RT.NumberOfCompositeSons();
if(size>0)
compositeSubMoves.resize(size);
// in the first step, we copy the linear moves into the
// appropriate array
int lastnumber = -1;
for(int i=0;i<listlength;i++){
if(indexInLinearMoves[i]>lastnumber){
lastnumber = indexInLinearMoves[i];
linearMoves.Put(lastnumber,AllMoves[indexInAllMoves[i]]);
}
}
// analyse the tree and make the entries in the arrays
int cp,csp,pp;
cp=0,csp=0,pp=0;
FillFromRepTree(cp,csp,pp,RT);
int type = RT.GetNodeType();
this->submove.arrayIndex=0;
if(type==SIMPLE)
this->submove.arrayNumber=LINEAR;
else if(type==COMPOSITE)
this->submove.arrayNumber=COMPOSITE;
else if(type==REPETITION)
this->submove.arrayNumber=PERIOD;
else
assert(false);
SetDefined(true);
} // moves exist
L->Destroy();
delete L;
L = NULL;
CorrectDurationSums();
TrimToSize();
}
/*
~FillFromRepTree~
This function fills the composite Array, the compositeSubMoveArray and the
periodic Move array. The linearPointArray must be initializes before calling
this function. The Parameters describe the first free index positions for
this tree. After alling this function, the arguments are incremented with the
space occupied by this tree.
*/
bool PMPoint::FillFromRepTree(int& cp,int& csp, int& pp, RepTree TR){
int type = TR.GetNodeType();
if(type==SIMPLE){
// simple nodes correspond to linearpointmoves
// for this reason, we have to do nothing in this case.
return true;
}
int oldcp=cp;
int oldcsp=csp;
int oldpp=pp;
if(type==REPETITION){
// first include the son of this repetition
pp++;
RepTree* son = TR.GetSon(0);
if(!FillFromRepTree(cp,csp,pp,*son)) // error
return false;
// create a new SpatialPeriodicMove
SpatialPeriodicMove SPM(0);
int sontype = son->GetNodeType();
if(sontype==SIMPLE){
// we need the son for receiving some information
LinearPointMove LPM(0);
linearMoves.Get(son->Content(),LPM);
SPM.repeatations = TR.RepCount();
SPM.submove.arrayNumber=LINEAR;
SPM.submove.arrayIndex=son->Content();
SPM.interval.Equalize(&LPM.interval);
SPM.interval.Mul(SPM.repeatations);
SPM.bbox = LPM.BoundingBox();
} else if(sontype==COMPOSITE){
SpatialCompositeMove SCM(0);
compositeMoves.Get(oldcp,SCM);
SPM.repeatations = TR.RepCount();
SPM.submove.arrayNumber=COMPOSITE;
SPM.submove.arrayIndex=oldcp;
SPM.interval.Equalize(&SCM.interval);
SPM.interval.Mul(SPM.repeatations);
SPM.bbox = SCM.bbox;
} else{
// we don't allow other types to be a son of a
// repetition
return false;
}
periodicMoves.Put(oldpp,SPM);
return true;
} // type==repetition
if(type==COMPOSITE){
int nos = TR.NumberOfSons();
csp = csp + nos;
cp++;
SpatialCompositeMove SCM(0);
SCM.minIndex=oldcsp;
SCM.maxIndex=csp-1;
int currentrep=oldpp;
// insert all submoves
for(int i=0;i<nos;i++){
RepTree* CurrentSon = TR.GetSon(i);
//insert the son
if(!FillFromRepTree(cp,csp,pp,*CurrentSon))
return false;
// create submove
CSubMove SM;
int sontype = CurrentSon->GetNodeType();
if(sontype==SIMPLE){
SM.arrayNumber=LINEAR;
SM.arrayIndex=CurrentSon->Content();
LinearPointMove LPM(0);
linearMoves.Get(CurrentSon->Content(),LPM);
if(i==0){ // the first submove
SCM.interval.Equalize(&LPM.interval);
SCM.bbox.Equalize(LPM.BoundingBox());
}else{
SCM.interval.Plus(&(LPM.interval));
PBBox tmpbox(LPM.BoundingBox());
SCM.bbox.Union(&tmpbox);
}
}else if(sontype==REPETITION){
SM.arrayNumber=PERIOD;
SM.arrayIndex=currentrep;
currentrep=pp;
SpatialPeriodicMove SPM(0);
periodicMoves.Get(SM.arrayIndex,SPM);
if(i==0){
SCM.interval.Equalize(&SPM.interval);
SCM.bbox.Equalize(&SPM.bbox);
} else{
SCM.interval.Plus(&SPM.interval);
SCM.bbox.Union(&SPM.bbox);
}
} else{
// we don't allow a composite move to be a
// son of another composite move
return false;
}
compositeSubMoves.Put(oldcsp+i,SM);
} // for each submove
compositeMoves.Put(oldcp,SCM); // insert the move
return true;
}
// other type are not present
assert(false);
}
/*
~GetBBox~
The function GetBBox returns the bounding Box of this periodic
moving point.
*/
PBBox PMPoint::GetBbox()const{
__TRACE__
return bbox;
}
/*
~Toprel~
This operator computed the topological relationship between this and
the argument.
*/
PMInt9M* PMPoint::Toprel(const Point& P)const{
__TRACE__
PMInt9M* res = new PMInt9M(0);
Toprel(P,*res);
return res;
}
void PMPoint::Toprel(const Point& P, PMInt9M& res)const{
__TRACE__
// first, we create an array of the same size as the
// size of the linearmoves
int rs = linearMoves.Size();
ArrayRange ranges[rs];
int lastPos=0;
LinearPointMove LPM;
DbArray<LinearInt9MMove> UnitTopRels(linearMoves.Size());
LinearInt9MMove buffer[3];
for(int i=0;i<linearMoves.Size();i++){
linearMoves.Get(i,LPM);
int count = LPM.Toprel(P,buffer);
for(int j=0;j<count;j++){
UnitTopRels.Append(buffer[j]);
}
ranges[i].minIndex=lastPos;
ranges[i].maxIndex=lastPos+count-1;
lastPos=lastPos+count;
}
DbArray<CompositeMove> CMs(compositeMoves.Size());
DbArray<PeriodicMove> PMs(periodicMoves.Size());
SpatialCompositeMove SCM(0);
CompositeMove CM;
for(int i=0;i<compositeMoves.Size();i++){
compositeMoves.Get(i,SCM);
CM = SCM.ToCompositeMove();
CMs.Put(i,CM);
}
SpatialPeriodicMove SPM;
PeriodicMove PM;
for(int i=0;i<periodicMoves.Size();i++){
periodicMoves.Get(i,SPM);
PM = SPM.ToPeriodicMove();
PMs.Put(i,PM);
}
res.CreateFrom(UnitTopRels,ranges,rs,CMs,compositeSubMoves,
PMs,startTime,submove);
res.Minimize();
}
/*
~Toprel~
This operator computed the topological relationship between this and
the argument.
*/
void PMPoint::Toprel(const Points& P, PMInt9M& result)const {
__TRACE__
// first, we create an array of the same size as the
// size of the linearmoves
int rs = linearMoves.Size();
ArrayRange ranges[rs];
int lastPos=0;
LinearPointMove LPM;
DbArray<LinearInt9MMove> UnitTopRels(linearMoves.Size());
vector<LinearInt9MMove> MyBuffer;
for(int i=0;i<linearMoves.Size();i++){
linearMoves.Get(i,LPM);
LPM.Toprel(P,MyBuffer);
int count = MyBuffer.size();
for(int j=0;j<count;j++){
UnitTopRels.Append(MyBuffer[j]);
}
ranges[i].minIndex=lastPos;
ranges[i].maxIndex=lastPos+count-1;
lastPos=lastPos+count;
}
DbArray<CompositeMove> CMs(compositeMoves.Size());
DbArray<PeriodicMove> PMs(periodicMoves.Size());
SpatialCompositeMove SCM(0);
CompositeMove CM;
for(int i=0;i<compositeMoves.Size();i++){
compositeMoves.Get(i,SCM);
CM = SCM.ToCompositeMove();
CMs.Put(i,CM);
}
SpatialPeriodicMove SPM;
PeriodicMove PM;
for(int i=0;i<periodicMoves.Size();i++){
periodicMoves.Get(i,SPM);
PM = SPM.ToPeriodicMove();
PMs.Put(i,PM);
}
result.CreateFrom(UnitTopRels,ranges,rs,CMs,compositeSubMoves,PMs,
startTime,submove);
cout << "Linear Moves before minimizations : "
<< result.NumberOfLinearMoves() << endl;
result.Minimize();
cout << "Linear Moves after minimization : "
<< result.NumberOfLinearMoves() << endl;
}
PMInt9M* PMPoint::Toprel(const Points& P)const {
PMInt9M* res = new PMInt9M(1);
Toprel(P,*res);
return res;
}
/*
~DistanceTo~
This function computes the distance to a fixed position in [R2] as
periodic moving real;
*/
bool PMPoint::DistanceTo(const double x, const double y, PMReal& result)const {
// spcial case: this pmpoint is not defined
if(!IsDefined()){
result.SetDefined(false);
return true;
}
result.SetDefined(true);
// copying the tree structure as well as the interval and the
// submove into the result.
RelInterval* resInterval = result.GetInterval();
resInterval->Equalize(&interval);
SubMove* SM =result.GetSubmove();
SM->Equalize(&submove);
result.SetStartTime(startTime);
// copy periodic moves
DbArray<PeriodicMove>* resPMs = result.GetPeriodicMoves();
resPMs->clean();
int size;
if((size=periodicMoves.Size())>0){
PeriodicMove PM;
SpatialPeriodicMove SPM;
resPMs->resize(size);
for(int i=0;i<size;i++){
periodicMoves.Get(i,SPM);
SPM.ToPeriodicMove(PM);
resPMs->Put(i,PM);
}
}
// copy composite moves
DbArray<CompositeMove>* resCMs = result.GetCompositeMoves();
resCMs->clean();
if((size=compositeMoves.Size())>0){
CompositeMove CM;
SpatialCompositeMove SCM(0);
resCMs->resize(size);
for(int i=0;i<size;i++){
compositeMoves.Get(i,SCM);
SCM.ToCompositeMove(CM);
resCMs->Put(i,CM);
}
}
// copy composite submoves
DbArray<CSubMove>* resSMs = result.GetCompositeSubMoves();
resSMs->clean();
if((size=compositeSubMoves.Size())>0){
CSubMove SM;
resSMs->resize(size);
for(int i=0;i<size;i++){
compositeSubMoves.Get(i,SM);
resSMs->Put(i,SM);
}
}
// now, we build the linear moves for the
// periodic moving real
DbArray<MovingRealUnit>* resLin = result.GetLinearMoves();
MovingRealUnit Unit;
resLin->clean();
if((size=linearMoves.Size())>0){
resLin->resize(size);
LinearPointMove LPM;
for(int i=0;i<size;i++){
linearMoves.Get(i,LPM);
LPM.DistanceTo(x,y,Unit);
resLin->Put(i,Unit);
}
}
return true;
}
/*
~Speed~ and ~Direction~
This function computes the speed of this PMPoint.
*/
void PMPoint::SpeedAndDirection(bool isSpeed, PMReal& result)const {
// special case: this pmpoint is not defined
if(!IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined(true);
// copying the tree structure as well as the interval and the
// submove into the result.
RelInterval* resInterval = result.GetInterval();
resInterval->Equalize(&interval);
SubMove* SM =result.GetSubmove();
SM->Equalize(&submove);
result.SetStartTime(startTime);
// copy periodic moves
DbArray<PeriodicMove>* resPMs = result.GetPeriodicMoves();
resPMs->clean();
int size;
if((size=periodicMoves.Size())>0){
PeriodicMove PM;
SpatialPeriodicMove SPM;
resPMs->resize(size);
for(int i=0;i<size;i++){
periodicMoves.Get(i,SPM);
SPM.ToPeriodicMove(PM);
resPMs->Put(i,PM);
}
}
// copy composite moves
DbArray<CompositeMove>* resCMs = result.GetCompositeMoves();
resCMs->clean();
if((size=compositeMoves.Size())>0){
CompositeMove CM;
SpatialCompositeMove SCM(0);
resCMs->resize(size);
for(int i=0;i<size;i++){
compositeMoves.Get(i,SCM);
SCM.ToCompositeMove(CM);
resCMs->Put(i,CM);
}
}
// copy composite submoves
DbArray<CSubMove>* resSMs = result.GetCompositeSubMoves();
resSMs->clean();
if((size=compositeSubMoves.Size())>0){
CSubMove SM;
resSMs->resize(size);
for(int i=0;i<size;i++){
compositeSubMoves.Get(i,SM);
resSMs->Put(i,SM);
}
}
// now, we build the linear moves for the
// periodic moving real
DbArray<MovingRealUnit>* resLin = result.GetLinearMoves();
MovingRealUnit Unit;
resLin->clean();
if((size=linearMoves.Size())>0){
resLin->resize(size);
LinearPointMove LPM;
for(int i=0;i<size;i++){
linearMoves.Get(i,LPM);
if(isSpeed){
LPM.Speed(Unit);
} else {
LPM.Direction(Unit);
}
resLin->Put(i,Unit);
}
}
result.Minimize();
}
/*
~CorrectDurationSums~
*/
void PMPoint::CorrectDurationSums(){
if(IsEmpty() || !IsDefined()){ // nothing to do
return;
}
int cmsize = compositeMoves.Size();
RelInterval currentInterval;
DateTime currentLength(durationtype);
DateTime duration(durationtype);
SpatialCompositeMove CM(0);
// process all compositeMoves.
for(int i=0;i<cmsize;i++){
compositeMoves.Get(i,CM);
duration.SetToZero();
for(int j=CM.minIndex;j<=CM.maxIndex;j++){
CSubMove csm1;
compositeSubMoves.Get(j,csm1);
CSubMove csm;
csm.Equalize(&csm1);
csm.duration.Equalize(&duration);
compositeSubMoves.Put(j,csm);
GetLength(csm,currentLength);
duration += currentLength;
}
}
}
/*
~GetLength~
Returns the length of the submove specified as the argument.
*/
void PMPoint::GetLength(SubMove sm, DateTime& result){
switch(sm.arrayNumber){
case LINEAR:{
LinearPointMove lpm;
linearMoves.Get(sm.arrayIndex,lpm);
lpm.interval.GetLength(result);
break;
}
case COMPOSITE:{
SpatialCompositeMove scm(0);
compositeMoves.Get(sm.arrayIndex,scm);
scm.interval.GetLength(result);
break;
}
case PERIOD:{
SpatialPeriodicMove spm;
periodicMoves.Get(sm.arrayIndex,spm);
spm.interval.GetLength(result);
break;
}
default:
cerr << "unknown submove " << sm << endl;
assert(false);
}
}
/*
~GetInterval~
Returns the interval covered by the subtree given by the argument.
*/
void PMPoint::GetInterval(SubMove sm, RelInterval& result) const{
switch(sm.arrayNumber){
case LINEAR:{
LinearPointMove lpm;
linearMoves.Get(sm.arrayIndex,lpm);
result.Equalize(&lpm.interval);
break;
}
case COMPOSITE:{
SpatialCompositeMove scm(0);
compositeMoves.Get(sm.arrayIndex,scm);
result.Equalize(&scm.interval);
break;
}
case PERIOD:{
SpatialPeriodicMove spm;
periodicMoves.Get(sm.arrayIndex,spm);
result.Equalize(&spm.interval);
break;
}
default:
cerr << "unknown submove " << sm << endl;
assert(false);
}
}
/*
~Length~
This function computes the length of the route of the pmpoint.
This instance has to be defined.
*/
double PMPoint::Length()const{
assert(IsDefined());
return Length(submove);
}
void PMPoint::Length(CcReal& res)const{
if(!IsDefined()){
res.SetDefined(false);
} else{
res.Set(true,Length());
}
}
double PMPoint::Length(const SubMove& sm) const{
switch(sm.arrayNumber){
case LINEAR : {
LinearPointMove lpm;
linearMoves.Get(sm.arrayIndex,lpm);
return lpm.Length();
} case COMPOSITE:{
SpatialCompositeMove scm(0);
CSubMove csm;
compositeMoves.Get(sm.arrayIndex,scm);
double res = 0.0;
for(int i=scm.minIndex; i<= scm.maxIndex; i++){
compositeSubMoves.Get(i,csm);
res += Length(csm);
}
return res;
} case PERIOD: {
SpatialPeriodicMove spm;
periodicMoves.Get(sm.arrayIndex,spm);
return spm.repeatations * Length(spm.submove);
}
default: assert(false);
}
}
} // end of namespace periodic