Files
secondo/Algebras/Periodic/LinearPointsMove.cpp

514 lines
14 KiB
C++
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
3.15 ~LinearPointsMove~
*/
#include <iostream>
#include <string>
#include "NestedList.h"
#include "StandardTypes.h"
#include "PeriodicSupport.h"
#include "PeriodicTypes.h"
#include "DateTime.h"
#include "Algebras/Spatial/SpatialAlgebra.h"
using namespace std;
using namespace datetime;
extern NestedList* nl;
namespace periodic{
/*
~Constructor~
*/
LinearPointsMove::LinearPointsMove(){}
LinearPointsMove::LinearPointsMove(const LinearPointsMove& source):
interval(0), bbox(0){
Equalize(&source);
}
/*
~Destructor~
*/
LinearPointsMove::~LinearPointsMove(){}
/*
~Assignment Operator~
*/
LinearPointsMove& LinearPointsMove::operator=(const LinearPointsMove& source){
Equalize(&source);
return *this;
}
/*
~IsDefined~
*/
bool LinearPointsMove::IsDefined()const{
return defined;
}
/*
~IsStatic~
*/
bool LinearPointsMove::IsStatic()const{
return isStatic;
}
/*
~Accessing the occupied array range~
*/
unsigned int LinearPointsMove::GetStartIndex()const {
return startIndex;
}
unsigned int LinearPointsMove::GetEndIndex()const {
return endIndex;
}
/*
~Constructor~
This Constructor creates an undefined instance of this class.
[3] O(1)
*/
LinearPointsMove::LinearPointsMove(int dummy):interval(0),bbox(0){
__TRACE__
startIndex=0;
endIndex=0;
isStatic = true;
defined = false;
}
/*
~ToListEpr~
This function returns the nested list corresponding to this
LinearPointsMove. Because this class can't manage the location
of the points, the array containing the points is given as an
argument. If the array not contains enough entries, the result
will be zero.
[3] O(P) where P is the number of contained moving points
*/
ListExpr LinearPointsMove::ToListExpr(const DbArray<TwoPoints> &Points) const{
__TRACE__
if(!defined)
return ::nl->SymbolAtom("undefined");
TwoPoints Entry;
unsigned int s = Points.Size();
if(s<endIndex){
if(DEBUG_MODE){
cerr << "Error in creating the nested list for";
cerr << "a LinearPointsMove " << endl;
cerr << "Endindex (" << endIndex << ") ";
cerr << "is located after the last ArrayElement (";
cerr << Points.Size() << ")" << endl;
}
return 0;
}
if(endIndex<=startIndex){
cerr << __POS__ << "endIndex < startIndex " << endl;
return 0;
}
ListExpr starts, ends;
ListExpr Ps,Pe,LastStart,LastEnd;
Points.Get(startIndex,Entry);
Ps = ::nl->TwoElemList( ::nl->RealAtom(Entry.startX),
::nl->RealAtom(Entry.startY));
Pe = ::nl->TwoElemList( ::nl->RealAtom(Entry.endX),
::nl->RealAtom(Entry.endY));
starts = ::nl->OneElemList(Ps);
ends = ::nl->OneElemList(Pe);
LastStart = starts;
LastEnd = ends;
for(unsigned int i=startIndex+1;i<endIndex;i++){
Points.Get(i,Entry);
Ps = ::nl->TwoElemList( ::nl->RealAtom(Entry.startX),
::nl->RealAtom(Entry.startY));
Pe = ::nl->TwoElemList( ::nl->RealAtom(Entry.endX),
::nl->RealAtom(Entry.endY));
LastStart = ::nl->Append(LastStart,Ps);
LastEnd = ::nl->Append(LastEnd,Pe);
}
ListExpr res = ::nl->TwoElemList(::nl->SymbolAtom("linear"),
::nl->ThreeElemList( interval.ToListExpr(false),
starts,ends));
return res;
}
/*
~ReadFrom~
This function reads the value of this LinearPointsMove from
value. The points are appended to the Points array beginning at
the given index. If value don't represent a valid LinearPointsMove,
the return value will be false. Nevertheless it may be that the Points
array is changed. After calling this function the index value will be
points to the elements after the last inserted one.
If an error is occured this instance will be undefined.
[3] O(P) where P is the number of contained moving points
*/
bool LinearPointsMove::ReadFrom(const ListExpr value, DbArray<TwoPoints> &Pts,
int &Index){
__TRACE__
// value has to be a list
if(::nl->AtomType(value)!=NoAtom){
if(DEBUG_MODE){
cerr << "List for LinearPointsMove is an atom " << endl;
}
defined = false;
return false;
}
// check the ListLength
if(::nl->ListLength(value)!=3){ // (interval starts ends)
if(DEBUG_MODE){
cerr << "Wrong listlength for LinearPointsMove; should be 3, is ";
cerr << ::nl->ListLength(value) << endl;
}
defined = false;
return false;
}
// read the Interval
if(!interval.ReadFrom(::nl->First(value),false)){
if(DEBUG_MODE){
cerr << "LinearPointsMove::ReadFFrom: error in reding interval" << endl;
}
defined = false;
return false;
}
ListExpr starts = ::nl->Second(value);
ListExpr ends = ::nl->Third(value);
int L1 = ::nl->ListLength(starts);
if(L1 != ::nl->ListLength(ends)){
if(DEBUG_MODE){
cerr << "Error in LinearPointsMove::ReadFrom" << endl;
cerr << "Different lengths for start and end points " << endl;
}
return false;
}
if(L1==0){
isStatic = true;
startIndex = 0;
endIndex = 0;
defined = true;
bbox.SetEmpty();
return true;
}
double xs,ys,xe,ye;
TwoPoints TP(0,0,0,0);
ListExpr Start,End;
startIndex = Index;
endIndex = Index+L1;
while(! ::nl->IsEmpty(starts)){
Start = ::nl->First(starts);
End = ::nl->First(ends);
if(::nl->AtomType(Start)!=NoAtom ||
::nl->AtomType(End)!=NoAtom){
if(DEBUG_MODE){
cerr << "Error in LinearPointsMove::ReadFrom" << endl;
cerr << "start or end is not a list" << endl;
}
defined = false;
return false;
}
if(::nl->ListLength(Start)!=2 ||
::nl->ListLength(End)!=2) {
if(DEBUG_MODE){
cerr << "Error in LinearPointsMove::ReadFrom" << endl;
cerr << "Wrong listlength for Start or for End " << endl;
cerr << "Expected 2 for both, received " << ::nl->ListLength(Start);
cerr << "(start) and "<<::nl->ListLength(End) << "(end)" << endl;
}
defined = false;
return false;
}
if(!periodic::GetNumeric(::nl->First(Start),xs) ||
!periodic::GetNumeric(::nl->Second(Start),ys) ||
!periodic::GetNumeric(::nl->First(End),xe) ||
!periodic::GetNumeric(::nl->Second(End),ye)){
if(DEBUG_MODE){
cerr << "Error in LinearPointsMove::ReadFrom" << endl;
cerr << "Cannot find numerical value " << endl;
}
defined = false;
return false;
}
TP = TwoPoints(xs,ys,xe,ye);
bbox.Union(xe,ye);
bbox.Union(xs,ys);
if(xe!=xs || ye!=ys)
isStatic=false;
Pts.Put(Index,TP);
Index++;
starts=::nl->Rest(starts);
ends=::nl->Rest(ends);
}
defined = true;
return true;
}
/*
~At~
This function computes the locations of the contained points
at the given point of time. If the duration is outside of the relative
interval of this LinearPointsMove, NULL is returned.
[3] O(P log(P)) where P is the number of contained moving points.
The reason is the sorting of the points in the result. I'm not
sure whether this time is reached because i don't know the
implementation of the sorting of the points.
*/
void LinearPointsMove::At(const DateTime* duration,
const DbArray<TwoPoints> &Pts,
Points& res) const{
__TRACE__
if(!interval.Contains(duration)){
res.SetDefined(false);
return;
}
res.SetDefined(true);
double w = interval.Where(duration);
res.Resize(Pts.Size());
TwoPoints Element;
Point aPoint;
double x,y;
res.StartBulkLoad();
for(unsigned int i=startIndex;i<endIndex;i++){
Pts.Get(i,Element);
x = Element.startX + w * (Element.endX - Element.startX);
y = Element.startY + w * (Element.endY - Element.startY);
aPoint = Point(x,y);
res += aPoint;
}
res.EndBulkLoad();
}
/*
~IsDefinedAt~
The function ~IsDefinedAt~ checks whether the given duration is
part of the relative interval of this LinearPointsMove. This means,
if the duration is zero, the relative interval has to be leftclosed.
If the given duration is less than zero, false is returned. Otherwise
this function checks wether the duration is less or equlas to the duration
of the relative interval. In the case of equality, the relative interval
has to be rightclosed to get the result true.
[3] O(1)
*/
bool LinearPointsMove::IsDefinedAt(const DateTime* duration)const{
__TRACE__
return interval.Contains(duration);
}
/*
~Intersects~
This function checks whether the bounding box of this
LinearPointsMove has common points with the bounding box which is
given as an arguments.
[3] O(1)
*/
bool LinearPointsMove::ProhablyIntersects(const PBBox* window)const {
__TRACE__
return bbox.Intersects(window);
}
/*
~SetUndefined~
This function sets this LinearPointsMove to be undefined.
[3] O(1)
*/
void LinearPointsMove::SetUndefined(){
__TRACE__
defined = false;
}
/*
~CanBeExtendedBy~
This function checks whether this LinearPointsmove can be appended
by the one of the arguments to yielding a single LinearPointsMove.
[3] unknow because not implemented up to now
*/
bool LinearPointsMove::CanBeExtendedBy(const LinearPointsMove* P2,
DbArray<TwoPoints> &MyPoints,
DbArray<TwoPoints> &PointsOfP2) const{
__TRACE__
if(!interval.CanAppended(&(P2->interval)))
return false;
// First we check for defined
if(!defined && !P2->defined)
return true;
if(defined != P2->defined)
return false;
// now both LinearPointsMove are defined
// check for the same number of contained points
if( (endIndex-startIndex) != (P2->endIndex-P2->startIndex))
return false;
// now we have to check wether each endpoint of this LinearPointsMove
// has a matching start point in P2.
// To do this, we insert all endpoints of this into an array and
// all start points of P2 to another one. After sorting both arrays
// we have to check the equality of this ones.
int size = endIndex-startIndex;
SimplePoint endPoints[size];
SimplePoint startPoints[size];
TwoPoints CurrentPoint;
for(unsigned int i=startIndex;i<endIndex;i++){
MyPoints.Get(i,CurrentPoint);
endPoints[i-startIndex].x=CurrentPoint.endX;
endPoints[i-startIndex].y=CurrentPoint.endY;
endPoints[i-startIndex].intinfo=i;
endPoints[i-startIndex].boolinfo=false;
}
for(unsigned int i=P2->startIndex;i<P2->endIndex;i++){
PointsOfP2.Get(i,CurrentPoint);
startPoints[i-P2->startIndex].x=CurrentPoint.startX;
startPoints[i-P2->startIndex].y=CurrentPoint.startY;
startPoints[i-P2->startIndex].intinfo=i;
startPoints[i-P2->startIndex].boolinfo=false;
}
heapsort(size,endPoints);
heapsort(size,startPoints);
for(int i=0;i<size;i++){
if(endPoints[i] != startPoints[i])
return false;
}
// we check for same speed and direction of the points
bool found = false; // found a matching (extending) upoint
int pos,cpos;
pos=cpos=0;
int endIndex;
TwoPoints TestPoint;
bool morethanone;
for(int i=0;i<size;i++){
endIndex=endPoints[i].intinfo;
//startIndex=startPoints[pos].intinfo;
MyPoints.Get(endIndex,CurrentPoint);
// check all Points of P2 with the same startpoint like the current
// endpoint
if(pos<size-1)
morethanone=startPoints[pos]==startPoints[pos+1];
else
morethanone=false;
cpos = pos;
while(!found && cpos<size){
if(endPoints[i]!=startPoints[cpos]) return false; // nothing found
if(startPoints[cpos].boolinfo) // point allready used
cpos++;
else{
PointsOfP2.Get(cpos,TestPoint);
if(CurrentPoint.IsSpatialExtension(&TestPoint)){
// check for same speed
if(CurrentPoint.Speed(interval)==
TestPoint.Speed(P2->interval)){ //mathc found
startPoints[cpos].boolinfo=true; // mark as used
found = true;
}
}else{
cpos++; // try the next
}
}
}
if(!found) return false;
if(!morethanone) pos++;
}
return true;
}
/*
~ExtendsWith~
This function summarized two LinearPointsMove together to a
single one if possible. The return values indicates the
success of this function. The result shows whether the
LinearPointsMoves can be put together. If the result is
__false__, this LinearPointsMove is not changed.
*/
bool LinearPointsMove::ExtendWith(const LinearPointsMove* P2,
DbArray<TwoPoints> &MyPoints,
DbArray<TwoPoints> &PointsOfP2){
__TRACE__
if(!CanBeExtendedBy(P2,MyPoints,PointsOfP2)) return false;
interval.Append(&(P2->interval));
bbox.Union(&(P2->bbox));
// this is very closed to the CanBeExtededFunction but here we need no
// checks because we know that this units can be putted together.
cout << __POS__ << endl;
cout << "ExtendWith(...) notimplemented " << endl;
return false;
}
/*
~Equalize~
This functions makes this equal to the argument.
[3] O(1)
*/
void LinearPointsMove::Equalize(const LinearPointsMove* P2){
__TRACE__
interval.Equalize(&(P2->interval));
bbox.Equalize(&(P2->bbox));
startIndex=P2->startIndex;
endIndex=P2->endIndex;
isStatic = P2->isStatic;
defined = P2->defined;
}
/*
~Shift Operator~
*/
ostream& operator<< (ostream& os, const LinearPointsMove LM){
__TRACE__
os << "LPsM[" ;
os << LM.startIndex << "," << LM.endIndex << "]";
// add also bbox, interval isstatic and so on if required !
return os;
}
} // end of namespace