/* 1.1 ~PMPoint~ ~includes~ */ #include #include #include #include #include #include #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__ <=0 && iEqualize(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(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(maxIndexTheEmptyList(); } 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=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=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=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 ) 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(minCompareTo(&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; iCompareTo(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;iAdd(length); assert(!length->LessThanZero()); delete length; length = NULL; temporalalgebra::Interval 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* L= new List(); 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;iAppend(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;iGetLength(); LinearPointMove* AllMoves = L->ConvertToArray(); int indexInAllMoves[listlength]; int indexInLinearMoves[listlength]; for(int i=0;i0) 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;ilastnumber){ 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;iGetNodeType(); 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 UnitTopRels(linearMoves.Size()); LinearInt9MMove buffer[3]; for(int i=0;i CMs(compositeMoves.Size()); DbArray PMs(periodicMoves.Size()); SpatialCompositeMove SCM(0); CompositeMove CM; for(int i=0;i UnitTopRels(linearMoves.Size()); vector MyBuffer; for(int i=0;i CMs(compositeMoves.Size()); DbArray PMs(periodicMoves.Size()); SpatialCompositeMove SCM(0); CompositeMove CM; for(int i=0;iEqualize(&interval); SubMove* SM =result.GetSubmove(); SM->Equalize(&submove); result.SetStartTime(startTime); // copy periodic moves DbArray* resPMs = result.GetPeriodicMoves(); resPMs->clean(); int size; if((size=periodicMoves.Size())>0){ PeriodicMove PM; SpatialPeriodicMove SPM; resPMs->resize(size); for(int i=0;iPut(i,PM); } } // copy composite moves DbArray* resCMs = result.GetCompositeMoves(); resCMs->clean(); if((size=compositeMoves.Size())>0){ CompositeMove CM; SpatialCompositeMove SCM(0); resCMs->resize(size); for(int i=0;iPut(i,CM); } } // copy composite submoves DbArray* resSMs = result.GetCompositeSubMoves(); resSMs->clean(); if((size=compositeSubMoves.Size())>0){ CSubMove SM; resSMs->resize(size); for(int i=0;iPut(i,SM); } } // now, we build the linear moves for the // periodic moving real DbArray* resLin = result.GetLinearMoves(); MovingRealUnit Unit; resLin->clean(); if((size=linearMoves.Size())>0){ resLin->resize(size); LinearPointMove LPM; for(int i=0;iPut(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* resPMs = result.GetPeriodicMoves(); resPMs->clean(); int size; if((size=periodicMoves.Size())>0){ PeriodicMove PM; SpatialPeriodicMove SPM; resPMs->resize(size); for(int i=0;iPut(i,PM); } } // copy composite moves DbArray* resCMs = result.GetCompositeMoves(); resCMs->clean(); if((size=compositeMoves.Size())>0){ CompositeMove CM; SpatialCompositeMove SCM(0); resCMs->resize(size); for(int i=0;iPut(i,CM); } } // copy composite submoves DbArray* resSMs = result.GetCompositeSubMoves(); resSMs->clean(); if((size=compositeSubMoves.Size())>0){ CSubMove SM; resSMs->resize(size); for(int i=0;iPut(i,SM); } } // now, we build the linear moves for the // periodic moving real DbArray* resLin = result.GetLinearMoves(); MovingRealUnit Unit; resLin->clean(); if((size=linearMoves.Size())>0){ resLin->resize(size); LinearPointMove LPM; for(int i=0;iPut(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