Files
secondo/Algebras/Periodic/PMPoints.cpp

1223 lines
31 KiB
C++
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
1.1 ~PMPoints~
*/
#include <iostream>
#include <string>
#include "PeriodicTypes.h"
#include "PeriodicSupport.h"
#include "Algebras/Spatial/SpatialAlgebra.h"
#include "StandardTypes.h"
#include "NestedList.h"
#include "DateTime.h"
extern NestedList* nl;
using namespace std;
using namespace datetime;
namespace periodic{
/*
3.9 ~PMPoints~
~Constructor~
This Constructor creates an undefined value of type PMPoints.
The argument is ignored.
*/
PMPoints::PMPoints(int dummy):
Attribute(false),
linearMoves(0),
thePoints(0),
compositeMoves(0),
compositeSubMoves(0),
periodicMoves(0),
canDelete(false),
interval(0),
startTime(instanttype),
bbox(0)
{ __TRACE__
}
/*
~Destructor~
[3] O(1)
*/
PMPoints::~PMPoints(){
__TRACE__
if(canDelete){
linearMoves.Destroy();
thePoints.Destroy();
compositeMoves.Destroy();
compositeSubMoves.Destroy();
periodicMoves.Destroy();
}
}
/*
~Destroy~
[3] O(1)
*/
void PMPoints::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 PMPoints::Equalize(const PMPoints* P2){
__TRACE__
// equalize the arrays
Attribute::operator=(*P2);
linearMoves.copyFrom(P2->linearMoves);
thePoints.copyFrom(P2->thePoints);
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));
}
/*
~NumOfFLOBs~
This function returns the number of contained FLOBs in this
class. Because five DBarrays are managed here, the return value
is 5.
[3] O(1)
*/
int PMPoints::NumOfFLOBs() const{
__TRACE__
return 5;
}
/*
~GetFLOB~
This function returns the FLOB with index i.
[3] O(1)
*/
Flob* PMPoints::GetFLOB(const int i){
__TRACE__
assert(i>=0 && i<NumOfFLOBs());
if(i==0) return &linearMoves;
if(i==1) return &thePoints;
if(i==2) return &compositeMoves;
if(i==3) return &compositeSubMoves;
if(i==4) return &periodicMoves;
return 0;
}
/*
~Compare~
This function is not implemented at this moment.
[3] O(-1)
*/
int PMPoints::Compare(const Attribute*)const{
__TRACE__
cout << " Warning! PMPoints::Compare not implemented" << endl;
return 0;
}
/*
~Adjacent~
We can't defined a adjacent relation beween two periodic moving
pointsets. For this reason, the return value is allways __false__.
[3] O(1)
*/
bool PMPoints::Adjacent(const Attribute* )const{
__TRACE__
return false;
}
/*
~Clone~
The ~Clone~ function returns a copy of this.
[3] O(L)
*/
PMPoints* PMPoints::Clone() const{
__TRACE__
PMPoints* copy = new PMPoints(0);
copy->Equalize(this);
return copy;
}
/*
~Sizeof~
This function returns the size of the PMPoints-class
[3] O(1)
*/
size_t PMPoints::Sizeof()const{
__TRACE__
return sizeof(PMPoints);
}
/*
~IsEmpty~
Checks whether this pmpoints value has no content at all times.
*/
bool PMPoints::IsEmpty() const{
return linearMoves.Size()==0;
}
/*
~HashValue~
Returns the HashValue for this Point.
[3] O(1)
*/
size_t PMPoints::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 PMPoints instances takes its value from the given argument.
[3] O(L)
*/
void PMPoints::CopyFrom(const Attribute* arg){
__TRACE__
Equalize((PMPoints*)arg);
}
/*
~ToListExpr~
This function returns the ListExpr representing this points.
The list will also contains the type if the flas is set.
This means, this list
is a complete list in format (type value)
[3] O(L)
*/
ListExpr PMPoints::ToListExpr(const bool typeincluded)const{
__TRACE__
ListExpr value;
if(!IsDefined())
value = ::nl->BoolAtom(false);
else{
ListExpr timelist = startTime.ToListExpr(false);
ListExpr SubMoveList = GetSubMoveList(submove);
value = ::nl->TwoElemList(timelist,SubMoveList);
}
ListExpr res;
if(typeincluded)
res = ::nl->TwoElemList( ::nl->SymbolAtom("pmpoints"),value );
else
res = value;
return res;
}
ListExpr PMPoints::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 PMPoints::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 << __POS__ << " Error in creating ListExpr" << endl;
SubMoveList = ::nl->TheEmptyList();
}
return SubMoveList;
}
/*
~GetLinearMove~
This functions returns the nested list representation of the
linear move at the specified index.
[3] O(1)
*/
ListExpr PMPoints::GetLinearMoveList(const int index)const{
__TRACE__
LinearPointsMove LM;
linearMoves.Get(index,LM);
ListExpr res = LM.ToListExpr(thePoints);
return res;
}
/*
~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 PMPoints::GetSpatialPeriodicMoveList(const int index)const{
__TRACE__
SpatialPeriodicMove PM;
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 PMPoints::GetSpatialCompositeMoveList(const int index)const{
__TRACE__
SpatialCompositeMove CM;
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. points from the
given nested list. If the nested list don't contains a
valid points value, the return value will be false and this points
is set to be undefined. Otherwise the points has the value
described in the nested list. The list consists 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 PMPoints::ReadFrom(const ListExpr value, const ListExpr typeInfo){
__TRACE__
/* The list is scanned twice. In the first scan we
compute only the needed size of the contained arrays. The reason is,
that we want to avoid frequently ~Resize~ on the arrays to ensure the
given time complexity.
*/
// for Debugging only
//::nl->WriteListExpr(value);
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__ << ": resizing arrays failed" << endl;
cerr << "*************************************" << 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;
}
SetDefined(false);
return false;
}
// now we have to append the included submove
ListExpr SML = ::nl->Second(value);
if(::nl->ListLength(SML)!=2){ // (submovetype value)
if(DEBUG_MODE){
cerr << __POS__ << ": wrong list length for submove" << endl;
}
SetDefined(false);
return false;
}
ListExpr SMT = ::nl->First(SML);
int LMIndex = 0;
int PtsIndex = 0;
int CMIndex = 0;
int SMIndex = 0;
int PMIndex = 0;
bool res = false;
if(::nl->IsEqual(SMT,"linear")){
submove.arrayNumber = LINEAR;
submove.arrayIndex = 0;
if(!AddLinearMove(::nl->Second(SML),LMIndex,PtsIndex,
CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
cerr << __POS__ << " Error in reading linear move" << endl;
}
SetDefined(false);
res = false;
}else {
SetDefined(true);
LinearPointsMove LM;
linearMoves.Get(0,LM);
interval.Equalize(&(LM.interval));
bbox.Equalize(&(LM.bbox));
res = true;
}
} else if(::nl->IsEqual(SMT,"composite")){
submove.arrayNumber=COMPOSITE;
submove.arrayIndex = 0;
if(!AddSpatialCompositeMove(::nl->Second(SML),LMIndex,PtsIndex,
CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
cerr << __POS__ << "error in reading composite move" << endl;
}
SetDefined(false);
res = false;
} else {
SetDefined(true);
SpatialCompositeMove CM;
compositeMoves.Get(0,CM);
interval.Equalize(&(CM.interval));
bbox.Equalize(&(CM.bbox));
res = true;
}
} else if(::nl->IsEqual(SMT,"period")){
submove.arrayNumber = PERIOD;
submove.arrayIndex = 0;
if(!AddPeriodMove(::nl->Second(SML),LMIndex,PtsIndex,
CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
cerr << __POS__ << " error in reading periodic move" << endl;
}
SetDefined(false);
res = false;
} else {
SetDefined(true);
SpatialPeriodicMove PM;
periodicMoves.Get(0,PM);
interval.Equalize(&(PM.interval));
bbox.Equalize(&(PM.bbox));
res = true;
}
} else {
if(DEBUG_MODE){
cerr << __POS__ << "unknown subtype" << endl;
::nl->WriteListExpr(SMT);
}
res = false;
}
CorrectDurationSums();
return res;
}
/*
~ResizeArrays~
This function resizes the arrays to the needed values.
[3] O(L), where L is the number of contained linear moves
*/
bool PMPoints::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 PtsSize = 0;
int CMSize = 0;
int SMSize = 0;
int PMSize = 0;
if(!AddSubMovesSize(::nl->Second(value),LMSize,PtsSize,CMSize,SMSize,PMSize))
return false;
// set the arrays to the needed size
if(LMSize>0) linearMoves.resize(LMSize);
if(PtsSize>0) thePoints.resize(PtsSize);
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. points represented in the value list.
[3] O(L), where L is the number of contained linear moves
*/
bool PMPoints::AddSubMovesSize(const ListExpr value,int &LMSize, int &PtsSize,
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);
if(::nl->AtomType(type)!=SymbolType){
return false;
}
// in a linear move we have to increment the size of LM
// and to add the number of contained Points
if(::nl->IsEqual(type,"linear")){
LMSize = LMSize +1;
ListExpr val = ::nl->Second(value);
if(::nl->AtomType(val)!=NoAtom)
return false;
if(nl->ListLength(val)==2) {
if(::nl->AtomType(::nl->Second(val))==BoolType){ // undefined
return true;
} else{
return false;
}
}
if(::nl->ListLength(val)!=3)
return false;
if(::nl->AtomType(::nl->Second(val))!=NoAtom ||
::nl->AtomType(::nl->Third(val))!=NoAtom )
return false;
int L1 = ::nl->ListLength(::nl->Second(val));
if(L1 != ::nl->ListLength(::nl->Third(val)))
return false;
PtsSize += L1; // add the Points of this Linear Move
return true;
}
if(::nl->IsEqual(type,"composite")){
CMSize = CMSize+1; // the composite move itself
ListExpr rest = ::nl->Second(value);
SMSize = SMSize+::nl->ListLength(rest); // the contained submoves
while(!::nl->IsEmpty(rest)){
if(!AddSubMovesSize(::nl->First(rest),LMSize,PtsSize,
CMSize,SMSize,PMSize))
return false;
rest = ::nl->Rest(rest);
}
return true;
}
if(::nl->IsEqual(type,"period")){
PMSize = PMSize+1;
int len = ::nl->ListLength(value);
ListExpr PMove;
if(len==2)
PMove = ::nl->Second(value);
else if(len==4)
PMove = ::nl->Fourth(value);
else // invalid listlength
return false;
return AddSubMovesSize(::nl->Second(PMove),LMSize,PtsSize,
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 PMPoints::AddLinearMove(const ListExpr value,
int &LMIndex, int &PtsIndex,
int &CMIndex, int &SMIndex,
int &PMIndex){
__TRACE__
LinearPointsMove LM = LinearPointsMove(0);
if(!LM.ReadFrom(value,thePoints,PtsIndex))
return false;
linearMoves.Put(LMIndex,LM);
LMIndex++;
return true;
}
/*
~AddSpatialCompositeMove~
This Functions appends the composite move given as a 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 PMPoints::AddSpatialCompositeMove(const ListExpr value,int &LMIndex,
int &PtsIndex,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=SpatialCompositeMove(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,PtsIndex,CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
cerr << __POS__ << " can't add a linear move " << endl;
}
return false;
}
LinearPointsMove 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
CM.bbox.Union(&(LM.bbox));
// 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,PtsIndex,CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
cerr << __POS__ << "can't add period move " << endl;
}
return false;
}
SpatialPeriodicMove PM;
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 od 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 PMPoints::AddPeriodMove(const ListExpr value,int &LMIndex, int &PtsIndex,
int &CMIndex, int &SMIndex, int &PMIndex){
__TRACE__
int len = ::nl->ListLength(value);
if((len!=2) && (len!=4)){ // (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;
if(len==2)
SML = ::nl->Second(value);
else
SML = ::nl->Fourth(value);
if(::nl->ListLength(SML)!=2){
if(DEBUG_MODE){
cerr << __POS__ << ": wrong length for submove" << endl;
}
return false;
}
SpatialPeriodicMove PM=SpatialPeriodicMove(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,PtsIndex,
CMIndex,SMIndex,PMIndex)){
if(DEBUG_MODE){
cerr << __POS__ << ": can't add linear submove" << endl;
}
return false;
}
PM.submove.arrayNumber = LINEAR;
PM.submove.arrayIndex = LMPos;
LinearPointsMove LM;
linearMoves.Get(LMPos,LM);
PM.bbox.Equalize(&(LM.bbox));
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,PtsIndex,
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;
compositeMoves.Get(CMPos,CM);
PM.bbox.Equalize(&(CM.bbox));
RelInterval SMI = CM.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;
}
// 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;
}
/*
~BreakPoints~
This function computes all locations where a point of this pointset has
halted.
*/
Points* PMPoints::Breakpoints()const{
DateTime DT(durationtype);
return Breakpoints(&DT,false);
}
void PMPoints::Breakpoints(Points& res) const{
DateTime DT(durationtype);
Breakpoints(&DT,false,res);
}
/*
~BreakPoints~
This function computes all locations where a point of this pointsset was
staying longer than duration. If the duration is less than zero or the
duration is zero and inclusive is true, the result will be an undefined
points value.
*/
Points* PMPoints::Breakpoints(const DateTime* duration,
const bool inclusive) const{
Points* res = new Points(1);
Breakpoints(duration,inclusive,*res);
return res;
}
void PMPoints::Breakpoints(const DateTime* duration,
const bool inclusive,
Points& res) const{
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);
LinearPointsMove LM;
TwoPoints TP;
res.StartBulkLoad();
int size = linearMoves.Size();
for(int i=0;i<size;i++){
linearMoves.Get(i,LM);
DateTime* L = LM.interval.GetLength();
int cmp = L->CompareTo(duration);
delete L;
L = NULL;
if(cmp>0 || (cmp==0 && inclusive)){
unsigned int a = LM.GetStartIndex();
unsigned int b = LM.GetEndIndex();
for(unsigned int j = a; j<=b; j++){
thePoints.Get(j,TP);
if(TP.IsStatic()){
Point P(true,TP.GetStartX(),TP.GetStartY());
res += P;
}
}
}
}
res.EndBulkLoad();
}
/*
~At~
This function computes the state of this pmpoints at time __instant__.
If this pmpoints is not defined at this instant, the result will be
an undefined points object.
*/
void PMPoints::At(const DateTime* instant, Points& res)const{
__TRACE__
DateTime* duration = new DateTime(instanttype);
duration->Equalize(instant);
duration->Minus(&startTime); // now it is really a duration
if(interval.Contains(duration)){
const SubMove* sm;
sm = &submove;
SpatialCompositeMove CM;
SpatialPeriodicMove PM;
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 cur = CM.minIndex;
int max = CM.maxIndex;
bool found=false;
while( (cur<=max) && ! found){
CSubMove csm;
compositeSubMoves.Get(cur,csm); // get the submove
SubMove sm1;
sm1.arrayIndex = csm.arrayIndex;
sm1.arrayNumber = csm.arrayNumber;
sm = &sm1;
if(sm->arrayNumber==LINEAR){
LinearPointsMove LM;
linearMoves.Get(sm->arrayIndex,LM);
RI = LM.interval;
} else if(sm->arrayNumber==PERIOD){
periodicMoves.Get(sm->arrayIndex,PM);
RI = PM.interval;
} else { //another submoves are not allowed
assert(false);
}
if(RI.Contains(duration)) // be happy
found=true;
else{ // search again
DateTime* L = RI.GetLength();
duration->Minus(L);
delete L;
L = NULL;
cur++;
}
}
assert(found); //otherwise we have an error in computation
} 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
sm = &PM.submove;
RelInterval RI;
if(sm->arrayNumber==LINEAR){
LinearPointsMove LM;
linearMoves.Get(sm->arrayIndex,LM);
RI = LM.interval;
} else if(sm->arrayNumber==COMPOSITE){
compositeMoves.Get(sm->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);
}
}
LinearPointsMove LM;
linearMoves.Get(sm->arrayIndex,LM);
if(LM.IsDefinedAt(duration))
LM.At(duration,thePoints,res);
else
res.SetDefined(false);
} else { // the duration does not contains the argument instant
res.SetDefined(false);
}
delete duration;
duration = NULL;
}
PMPoints::PMPoints(){}
PMPoints::PMPoints(const PMPoints& source):
Attribute(source.IsDefined()),
linearMoves(source.linearMoves.Size()),
thePoints(source.thePoints.Size()),
compositeMoves(source.compositeMoves.Size()),
compositeSubMoves(source.compositeMoves.Size()),
periodicMoves(source.periodicMoves.Size()),
canDelete(false),
interval(source.interval),
startTime(instanttype),
bbox(source.bbox)
{
Equalize(&source);
}
PMPoints& PMPoints::operator=(const PMPoints& source){
Equalize(&source);
return *this;
}
void PMPoints::Initial(Points& res)const{
if(!IsDefined()){
res.SetDefined(false);
return;
}
res.Clear();
res.SetDefined(true);
At(&startTime,res);
}
bool PMPoints::Final(Points& res)const{
if(!IsDefined()){
res.SetDefined(false);
return false;
}
DateTime DT(startTime);
DT.Add(interval.GetLength());
At(&DT,res);
return true;
}
void PMPoints::Translate(const DateTime& duration){
startTime += duration;
}
void PMPoints::Translate(const DateTime* duration, PMPoints& res)const{
res.Equalize(this);
res.startTime += *duration;
}
/*
~CorrectDurationSums~
*/
void PMPoints::CorrectDurationSums(){
if(IsEmpty() || !IsDefined()){ // nothing to do
return;
}
int cmsize = compositeMoves.Size();
RelInterval currentInterval;
DateTime currentLength(durationtype);
DateTime duration(durationtype);
SpatialCompositeMove CM;
// 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;
}
}
}
void PMPoints::GetLength(SubMove sm, DateTime& result){
switch(sm.arrayIndex){
case LINEAR:{
LinearPointsMove lpm;
linearMoves.Get(sm.arrayIndex,lpm);
lpm.interval.GetLength(result);
break;
}
case COMPOSITE: {
SpatialCompositeMove scm;
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: assert(false);
}
}
/*
~Shift Operator~
*/
ostream& operator<< (ostream &os, class PMPoints &P){
__TRACE__
os << " <<<< PMPoints >>>>" << endl;
if(!P.IsDefined()){
os << "undefined" << endl;
return os;
}
os << "starttime: " << P.startTime.ToString() << endl;
os << P.submove << endl;
os << "defined :" << P.IsDefined() << endl;
// the contents of the contained arrays
// the linear moves
os << "linear Moves " << P.linearMoves.Size() << endl;
LinearPointsMove LM1;
TwoPoints TP1;
unsigned int thePointsSize = P.thePoints.Size();
os << "SizeOf thePoints: " << thePointsSize << endl;
for(int i=0;i<P.linearMoves.Size();i++){
P.linearMoves.Get(i,LM1);
LinearPointsMove LM2 = (LM1);
os << LM2 << endl;
os << "Content of this linear Move " << endl;
for(int unsigned j=LM2.startIndex;j<LM2.endIndex;j++){
if(j>=thePointsSize){
os << "Array out of bounds " << __POS__ << endl;
os << "Try to access element number " << j << "in an array ";
os << "of size " << thePointsSize << endl;
}else {
os << j << " ." ;
P.thePoints.Get(j,TP1);
TwoPoints TP2 = (TP1);
os << TP2 << endl;
os << j << " ." ;
P.thePoints.Get(j,TP1);
TP2 = (TP1);
os << TP2 << endl;
os << j << " ." ;
P.thePoints.Get(j,TP1);
TP2 = (TP1);
os << TP2 << endl;
}
}
os << "end content of this linear Move " << endl;
}
// os << " please extend the << operator for pmpoints values " << endl;
os << " <<<< end PMPoints >>> " << endl;
return os;
}
} // end of namespace periodic