13418 lines
398 KiB
C++
13418 lines
398 KiB
C++
/*
|
|
This file is part of SECONDO.
|
|
|
|
Copyright (C) 2004, University in Hagen, Department of Computer Science,
|
|
Database Systems for New Applications.
|
|
|
|
SECONDO is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
SECONDO is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with SECONDO; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
//paragraph [1] Title: [{\Large \bf \begin{center}] [\end{center}}]
|
|
//paragraph [10] Footnote: [{\footnote{] [}}]
|
|
|
|
1 Implementation of Algebra Network
|
|
|
|
|
|
March 2004 Victor Almeida
|
|
|
|
Mai-Oktober 2007 Martin Scheppokat
|
|
|
|
February 2008 - Simone Jandt
|
|
|
|
October 2008 - Jianqiu Xu
|
|
|
|
1.1 Defines, includes, and constants
|
|
|
|
*/
|
|
|
|
#include <sstream>
|
|
#include <time.h>
|
|
#include <map>
|
|
#include <iterator>
|
|
#include <algorithm>
|
|
#include <limits>
|
|
#include "../Relation-C++/RelationAlgebra.h"
|
|
#include "../BTree/BTreeAlgebra.h"
|
|
#include "../RTree/RTreeAlgebra.h"
|
|
#include "../Spatial/SpatialAlgebra.h"
|
|
#include "NetworkAlgebra.h"
|
|
#include "../Rectangle/RectangleAlgebra.h"
|
|
#include "NetworkManager.h"
|
|
#include "../TupleIdentifier/TupleIdentifier.h"
|
|
#include "Symbols.h"
|
|
#include "../../Tools/Flob/DbArray.h"
|
|
#include "../../Tools/Flob/Flob.h"
|
|
#include "StandardTypes.h"
|
|
#include "Algebra.h"
|
|
#include "Messages.h"
|
|
#include "ListUtils.h"
|
|
#include "ConstructorTemplates.h"
|
|
#include "TypeMapUtils.h"
|
|
#include "Operator.h"
|
|
#include "Attribute.h"
|
|
|
|
|
|
|
|
extern NestedList* nl;
|
|
extern QueryProcessor* qp;
|
|
|
|
|
|
using namespace std;
|
|
using namespace network;
|
|
|
|
static map<int,string> *netList;
|
|
|
|
|
|
/*
|
|
1 Helping structs, methods and classes
|
|
|
|
Sending a message via the message-center
|
|
|
|
*/
|
|
void sendMessage ( string in_strMessage )
|
|
{
|
|
// Get message-center and initialize message-list
|
|
static MessageCenter* xMessageCenter= MessageCenter::GetInstance();
|
|
ListExpr list = nl->TwoElemList( nl->SymbolAtom("error"),
|
|
nl->TextAtom(in_strMessage));
|
|
xMessageCenter->Send ( nl, list);
|
|
}
|
|
|
|
|
|
/*
|
|
Computes a spatial BoundingBox of a RouteInterval
|
|
|
|
*/
|
|
|
|
Rectangle<2> RouteInterval::BoundingBox (const Network* pNetwork ) const
|
|
{
|
|
if ( AlmostEqualAbsolute ( m_dStart , m_dEnd, pNetwork->GetScalefactor()))
|
|
{
|
|
Point *p = ( GPoint ( true, pNetwork->GetId(), m_iRouteId,
|
|
m_dStart ) ).ToPoint ( pNetwork );
|
|
double minMax[] = {p->GetX(), p->GetX(), p->GetY(), p->GetY() };
|
|
Rectangle<2> bbox = Rectangle<2> ( true,minMax);
|
|
p->DeleteIfAllowed();
|
|
return bbox;
|
|
}
|
|
else
|
|
{
|
|
SimpleLine *line = new SimpleLine ( 0 );
|
|
pNetwork->GetLineValueOfRouteInterval ( this, line );
|
|
if ( !line->IsEmpty() )
|
|
{
|
|
Rectangle<2> res = line->BoundingBox();
|
|
line->DeleteIfAllowed();
|
|
return res;
|
|
}
|
|
else
|
|
{
|
|
line->DeleteIfAllowed();
|
|
Point *p1 = ( GPoint ( true, pNetwork->GetId(), m_iRouteId,
|
|
m_dStart ) ).ToPoint ( pNetwork );
|
|
Point *p2 = ( GPoint ( true, pNetwork->GetId(), m_iRouteId,
|
|
m_dEnd ) ).ToPoint ( pNetwork );
|
|
double minMax[] = { min ( p1->GetX(), p2->GetX() ),
|
|
max ( p1->GetX(), p2->GetX() ),
|
|
min ( p1->GetY(), p2->GetY() ),
|
|
max ( p1->GetY(), p2->GetY() )};
|
|
Rectangle<2> bbox = Rectangle<2> ( true,minMax );
|
|
p1->DeleteIfAllowed();
|
|
p2->DeleteIfAllowed();
|
|
return bbox;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
~searchRouteInterval~
|
|
|
|
Method for binary search after a route interval in a sorted ~GLine~. O(log n).
|
|
Used for example by operator ~inside~.
|
|
|
|
*/
|
|
bool RouteInterval::Contains(const RouteInterval *ri,
|
|
const double tolerance)const
|
|
{
|
|
double tstart = min(GetStartPos(),GetEndPos());
|
|
double tend = max(GetStartPos(),GetEndPos());
|
|
double start = min(ri->GetStartPos(),ri->GetEndPos());
|
|
double end = max(ri->GetStartPos(),ri->GetEndPos());
|
|
if (ri->GetRouteId() == GetRouteId() &&
|
|
((tstart <= start || AlmostEqualAbsolute( tstart , start,tolerance )) &&
|
|
(end <= tend ||AlmostEqualAbsolute(tend, end,tolerance ))))
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
bool RouteInterval::Contains(const GPoint *gp)const
|
|
{
|
|
double tstart = min(GetStartPos(),GetEndPos());
|
|
double tend = max(GetStartPos(),GetEndPos());
|
|
if (GetRouteId() == gp->GetRouteId() &&
|
|
tstart <= gp->GetPosition() && tend >= gp->GetPosition())
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
bool RouteInterval::Intersects(const RouteInterval *ri,
|
|
const double tolerance)const
|
|
{
|
|
double tstart = min(GetStartPos(),GetEndPos());
|
|
double tend = max(GetStartPos(),GetEndPos());
|
|
double start = min(ri->GetStartPos(),ri->GetEndPos());
|
|
double end = max(ri->GetStartPos(),ri->GetEndPos());
|
|
if(ri->Contains(this, tolerance) || Contains(ri, tolerance) ||
|
|
(ri->GetRouteId() == GetRouteId() &&
|
|
((start <= tstart && tstart <= end) || (start <= tend && tend <= end))))
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
bool searchRouteInterval (const RouteInterval *ri, const GLine *pGLine,
|
|
const double tolerance,
|
|
const int low, const int high )
|
|
{
|
|
RouteInterval rigl;
|
|
if ( low <= high )
|
|
{
|
|
int mid = ( high + low ) / 2;
|
|
if ( ( mid < 0 ) || ( mid >= pGLine->NoOfComponents() ) )
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
pGLine->Get ( mid, rigl );
|
|
if ( rigl.GetRouteId() < ri->GetRouteId() )
|
|
{
|
|
return searchRouteInterval ( ri, pGLine, tolerance, mid+1, high );
|
|
}
|
|
else
|
|
{
|
|
if ( rigl.GetRouteId() > ri->GetRouteId() )
|
|
{
|
|
return searchRouteInterval ( ri, pGLine, tolerance ,low, mid-1 );
|
|
}
|
|
else
|
|
{
|
|
if (rigl.Contains(ri, tolerance))
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
if ( rigl.GetStartPos() > ri->GetEndPos())
|
|
{
|
|
return searchRouteInterval ( ri, pGLine, tolerance,low, mid-1 );
|
|
}
|
|
else
|
|
{
|
|
if ( rigl.GetEndPos() < ri->GetStartPos() )
|
|
{
|
|
return searchRouteInterval ( ri, pGLine,tolerance, mid+1, high );
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
/*
|
|
~searchRouteInterval~
|
|
|
|
Method for binary search after a route interval in a sorted ~GLine~. O(log n).
|
|
Used for example by operator ~inside~.
|
|
|
|
*/
|
|
|
|
bool searchRouteInterval ( const GPoint *pGPoint, const GLine *&pGLine,
|
|
const double tolerance,
|
|
const size_t low, const size_t high )
|
|
{
|
|
RouteInterval rI;
|
|
if ( low <= high )
|
|
{
|
|
size_t mid = ( high + low ) / 2;
|
|
int imid = mid;
|
|
if ( ( imid < 0 ) || ( imid >= pGLine->NoOfComponents() ) )
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
pGLine->Get ( mid, rI );
|
|
if ( rI.GetRouteId() < pGPoint->GetRouteId() )
|
|
{
|
|
return searchRouteInterval ( pGPoint, pGLine, tolerance, mid+1, high );
|
|
}
|
|
else
|
|
{
|
|
if ( rI.GetRouteId() > pGPoint->GetRouteId() )
|
|
{
|
|
return searchRouteInterval ( pGPoint, pGLine, tolerance, low, mid-1 );
|
|
}
|
|
else
|
|
{
|
|
if (AlmostEqualAbsolute(pGPoint->GetPosition(),
|
|
rI.GetStartPos(), tolerance ) ||
|
|
AlmostEqualAbsolute ( pGPoint->GetPosition() ,
|
|
rI.GetEndPos(),tolerance ))
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
if ( rI.GetStartPos() > pGPoint->GetPosition() )
|
|
{
|
|
return searchRouteInterval ( pGPoint, pGLine, tolerance, low,
|
|
mid-1 );
|
|
}
|
|
else
|
|
{
|
|
if ( rI.GetEndPos() < pGPoint->GetPosition() )
|
|
{
|
|
return searchRouteInterval ( pGPoint, pGLine, tolerance, mid+1,
|
|
high );
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Helper struct to store sections which have been visited before. Used in
|
|
shortest path implementation of Dijkstras Algorithm.
|
|
|
|
*/
|
|
struct SectTree
|
|
{
|
|
|
|
SectTree() {};
|
|
|
|
SectTree ( const SectTreeEntry *nEntry, SectTree *l = 0, SectTree *r = 0 )
|
|
{
|
|
value = *nEntry;
|
|
left = l;
|
|
right = r;
|
|
};
|
|
|
|
~SectTree() {};
|
|
|
|
|
|
/*
|
|
Inserts a section into the tree. If the section is already in the insert is
|
|
ignored.
|
|
|
|
*/
|
|
void Insert (const SectTreeEntry *nEntry )
|
|
{
|
|
if ( nEntry->secttid < value.secttid )
|
|
{
|
|
if ( right != 0 ) right->Insert ( nEntry );
|
|
else right = new SectTree ( nEntry,0,0 );
|
|
}
|
|
else
|
|
{
|
|
if ( nEntry->secttid > value.secttid )
|
|
{
|
|
if ( left != 0 ) left->Insert ( nEntry );
|
|
else left = new SectTree ( nEntry,0,0 );
|
|
}
|
|
}
|
|
};
|
|
|
|
/*
|
|
Returns a pointer to the node with the given id or 0 if not found.
|
|
|
|
*/
|
|
SectTree* Find (const TupleId n )
|
|
{
|
|
if ( n < value.secttid )
|
|
{
|
|
if ( right != 0 ) return right->Find ( n);
|
|
else return 0;
|
|
}
|
|
else
|
|
{
|
|
if ( n > value.secttid )
|
|
{
|
|
if ( left != 0 ) return left->Find ( n);
|
|
else return 0;
|
|
}
|
|
else return this;
|
|
}
|
|
};
|
|
|
|
void CheckSection (const Network *pNetwork, const SectTreeEntry n,
|
|
GPoints &result )
|
|
{
|
|
|
|
vector<DirectedSection> sectList;
|
|
sectList.clear();
|
|
if ( n.startbool || n.endbool )
|
|
{
|
|
if ( n.startbool )
|
|
{
|
|
pNetwork->GetAdjacentSections ( n.secttid, false, sectList );
|
|
size_t j = 0;
|
|
SectTree* test= 0;
|
|
while ( j < sectList.size() && test == 0 )
|
|
{
|
|
DirectedSection actSection = sectList[j];
|
|
test = Find ( actSection.GetSectionTid());
|
|
j++;
|
|
}
|
|
if ( test != 0 )
|
|
result += GPoint ( true, pNetwork->GetId(), n.rid, n.start, None );
|
|
}
|
|
sectList.clear();
|
|
if ( n.endbool )
|
|
{
|
|
pNetwork->GetAdjacentSections ( n.secttid, true, sectList );
|
|
size_t j = 0;
|
|
SectTree* test = 0;
|
|
while ( j < sectList.size() && test == 0 )
|
|
{
|
|
DirectedSection actSection = sectList[j];
|
|
test = Find ( actSection.GetSectionTid());
|
|
j++;
|
|
}
|
|
if ( test != 0 )
|
|
result+= GPoint ( true, pNetwork->GetId(), n.rid, n.end, None );
|
|
}
|
|
sectList.clear();
|
|
}
|
|
else result += GPoint ( true, pNetwork->GetId(), n.rid, n.end, None );
|
|
}
|
|
|
|
void WriteResult ( const Network* pNetwork, GPoints &result,
|
|
SectTree &secTr ) const
|
|
{
|
|
if ( left != 0 ) left->WriteResult ( pNetwork, result, secTr );
|
|
if ( right != 0 ) right ->WriteResult ( pNetwork, result, secTr );
|
|
secTr.CheckSection ( pNetwork, value, result );
|
|
};
|
|
|
|
void Remove()
|
|
{
|
|
if ( left != 0 ) left->Remove();
|
|
if ( right != 0 ) right->Remove();
|
|
delete this;
|
|
};
|
|
|
|
SectTreeEntry value;
|
|
SectTree *left, *right;
|
|
};
|
|
|
|
/*
|
|
Almost similar to operator ~checkPoint~ but additional returning a difference
|
|
value if the point is not exactly on the ~sline~.
|
|
|
|
Used by operator ~point2gpoint~
|
|
|
|
*/
|
|
|
|
bool chkPoint ( SimpleLine *&route, const Point point,
|
|
const bool startSmaller,const double tolerance,
|
|
double &pos, double &difference )
|
|
{
|
|
bool result = false;
|
|
HalfSegment hs;
|
|
double k1, k2;
|
|
Point left(true,0,0), right(true,0,0);
|
|
for ( int i = 0; i < route->Size()-1; i++ )
|
|
{
|
|
route->Get ( i, hs );
|
|
left = hs.GetLeftPoint();
|
|
right = hs.GetRightPoint();
|
|
Coord xl = left.GetX(),
|
|
yl = left.GetY(),
|
|
xr = right.GetX(),
|
|
yr = right.GetY(),
|
|
x = point.GetX(),
|
|
y = point.GetY();
|
|
if ( ( AlmostEqualAbsolute ( x,xr,tolerance) &&
|
|
AlmostEqualAbsolute ( y,yr,tolerance)) ||
|
|
( AlmostEqualAbsolute ( x,xl,tolerance) &&
|
|
AlmostEqualAbsolute ( y,yl,tolerance)))
|
|
{
|
|
difference = 0.0;
|
|
result = true;
|
|
}
|
|
else
|
|
{
|
|
if ( xl != xr && xl != x )
|
|
{
|
|
k1 = ( y - yl ) / ( x - xl );
|
|
k2 = ( yr - yl ) / ( xr - xl );
|
|
if ( ( fabs ( k1-k2 ) < 0.004*tolerance/0.01 ) &&
|
|
( ( xl < xr &&
|
|
( x > xl || AlmostEqualAbsolute ( x,xl,tolerance )) &&
|
|
( x < xr || AlmostEqualAbsolute ( x,xr,tolerance ) ) ) ||
|
|
( xl > xr &&
|
|
( x < xl || AlmostEqualAbsolute ( x,xl,tolerance )) &&
|
|
( x > xr || AlmostEqualAbsolute ( x,xr,tolerance ) ) ) ) &&
|
|
((( yl <= yr &&
|
|
( y > yl || AlmostEqualAbsolute ( y,yl, tolerance )) &&
|
|
( y < yr || AlmostEqualAbsolute ( y,yr, tolerance ) ) ) ||
|
|
( yl > yr &&
|
|
( y < yl || AlmostEqualAbsolute ( y,yl,tolerance ) ) &&
|
|
( y > yr || AlmostEqualAbsolute ( y,yr,tolerance ) ) ) ) ))
|
|
{
|
|
difference = fabs ( k1-k2 );
|
|
result = true;
|
|
}
|
|
else {result = false;}
|
|
}
|
|
else
|
|
{
|
|
if ( ( AlmostEqualAbsolute ( xl, xr,tolerance ) &&
|
|
AlmostEqualAbsolute ( xl,x,tolerance ) ) &&
|
|
( ( ( yl <= yr &&
|
|
( yl < y || AlmostEqualAbsolute (yl,y,tolerance))&&
|
|
( y < yr ||AlmostEqualAbsolute ( y,yr,tolerance ) ) ) ||
|
|
( yl > yr &&
|
|
( yl > y || AlmostEqualAbsolute ( yl,y,tolerance) ) &&
|
|
( y > yr || AlmostEqualAbsolute ( y,yr,tolerance ) ) ) ) ))
|
|
{
|
|
difference = 0.0;
|
|
result = true;
|
|
}
|
|
else {result = false;}
|
|
}
|
|
}
|
|
if ( result )
|
|
{
|
|
LRS lrs;
|
|
route->Get ( hs.attr.edgeno, lrs );
|
|
route->Get ( lrs.hsPos, hs );
|
|
pos = lrs.lrsPos + point.Distance ( hs.GetDomPoint() );
|
|
if ( startSmaller != route->GetStartSmaller() )
|
|
pos = route->Length() - pos;
|
|
if ( AlmostEqualAbsolute ( pos,0.0,tolerance ))
|
|
pos = 0.0;
|
|
else if ( AlmostEqualAbsolute( pos, route->Length(),tolerance))
|
|
pos = route->Length();
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
Almost similar to operator ~chkPoint~ but allowing a greater difference if the
|
|
point is not exactly on the ~sline~.
|
|
|
|
Used by operator ~point2gpoint~
|
|
|
|
*/
|
|
|
|
bool chkPoint03 ( SimpleLine *route, const Point point,
|
|
const bool startSmaller, const double tolerance,
|
|
double &pos, double &difference )
|
|
{
|
|
bool result = false;
|
|
HalfSegment hs(true,Point(true,0,0),Point(true,1,1));
|
|
double k1, k2;
|
|
Point left(false), right(false);
|
|
for ( int i = 0; i < route->Size()-1; i++ )
|
|
{
|
|
route->Get ( i, hs );
|
|
left = hs.GetLeftPoint();
|
|
right = hs.GetRightPoint();
|
|
Coord xl = left.GetX(),
|
|
yl = left.GetY(),
|
|
xr = right.GetX(),
|
|
yr = right.GetY(),
|
|
x = point.GetX(),
|
|
y = point.GetY();
|
|
if ( ( AlmostEqualAbsolute ( x,xl,tolerance ) &&
|
|
AlmostEqualAbsolute ( y,yl,tolerance )) ||
|
|
( AlmostEqualAbsolute ( x,xr,tolerance ) &&
|
|
AlmostEqualAbsolute ( y,yr,tolerance ) ) )
|
|
{
|
|
difference = 0.0;
|
|
result = true;
|
|
}
|
|
else
|
|
{
|
|
if ( xl != xr && xl != x )
|
|
{
|
|
k1 = ( y - yl ) / ( x - xl );
|
|
k2 = ( yr - yl ) / ( xr - xl );
|
|
if ( ( fabs ( k1-k2 ) < 1.2*tolerance ) &&
|
|
( ( xl < xr &&
|
|
( x > xl || AlmostEqualAbsolute ( x,xl,tolerance ) ) &&
|
|
( x < xr || AlmostEqualAbsolute ( x,xr,tolerance ) ) ) ||
|
|
( xl > xr &&
|
|
( x < xl || AlmostEqualAbsolute ( x,xl,tolerance )) &&
|
|
( x > xr || AlmostEqualAbsolute ( x,xr,tolerance ) ) ) ) &&
|
|
( ( ( yl < yr || AlmostEqualAbsolute ( yl,yr,tolerance )) &&
|
|
( y > yl || AlmostEqualAbsolute (y,yl,tolerance )) &&
|
|
( y < yr || AlmostEqualAbsolute ( y,yr,tolerance )) ) ||
|
|
( yl > yr &&
|
|
( y < yl || AlmostEqualAbsolute ( y,yl,tolerance )) &&
|
|
( y > yr || AlmostEqualAbsolute ( y,yr,tolerance ) ) ) ) )
|
|
{
|
|
difference = fabs ( k1-k2 );
|
|
result = true;
|
|
}
|
|
else {result = false;}
|
|
}
|
|
else
|
|
{
|
|
if ( ( AlmostEqualAbsolute ( xl, xr,tolerance ) &&
|
|
AlmostEqualAbsolute ( xl,x,tolerance )) &&
|
|
( ( ( yl < yr|| AlmostEqualAbsolute ( yl,yr,tolerance )) &&
|
|
( yl < y || AlmostEqualAbsolute (yl,y ,tolerance) ) &&
|
|
( y < yr || AlmostEqualAbsolute ( y,yr,tolerance ) ) ) ||
|
|
( yl > yr &&
|
|
( yl > y || AlmostEqualAbsolute ( yl,y,tolerance )) &&
|
|
( y > yr || AlmostEqualAbsolute ( y,yr,tolerance )) ) ) )
|
|
{
|
|
difference = 0.0;
|
|
result = true;
|
|
}
|
|
else {result = false;}
|
|
}
|
|
}
|
|
if ( result )
|
|
{
|
|
LRS lrs;
|
|
route->Get ( hs.attr.edgeno, lrs );
|
|
route->Get ( lrs.hsPos, hs );
|
|
pos = lrs.lrsPos + point.Distance ( hs.GetDomPoint() );
|
|
if ( startSmaller != route->GetStartSmaller() )
|
|
pos = route->Length() - pos;
|
|
if ( AlmostEqualAbsolute ( pos,0.0,tolerance ))
|
|
pos = 0.0;
|
|
else if ( AlmostEqualAbsolute ( pos,route->Length(),tolerance ))
|
|
pos = route->Length();
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
Almost similar to operator ~chkPoint~ but not checking the difference if the
|
|
point is not exactly on the ~sline~.
|
|
|
|
Used by operator ~point2gpoint~
|
|
|
|
*/
|
|
bool lastchkPoint03 ( SimpleLine *&route, const Point point,
|
|
const bool startSmaller, const double tolerance,
|
|
double &pos, double &difference )
|
|
{
|
|
bool result = false;
|
|
HalfSegment hs;
|
|
double k1, k2;
|
|
Point left(false), right(false);
|
|
for ( int i = 0; i < route->Size()-1; i++ )
|
|
{
|
|
route->Get ( i, hs );
|
|
left = hs.GetLeftPoint();
|
|
right = hs.GetRightPoint();
|
|
Coord xl = left.GetX(),
|
|
yl = left.GetY(),
|
|
xr = right.GetX(),
|
|
yr = right.GetY(),
|
|
x = point.GetX(),
|
|
y = point.GetY();
|
|
if ( ( AlmostEqualAbsolute ( x,xl,tolerance ) &&
|
|
AlmostEqualAbsolute ( y,yl,tolerance )) ||
|
|
( AlmostEqualAbsolute ( x,xr,tolerance ) &&
|
|
AlmostEqualAbsolute ( y,yr,tolerance ) ) )
|
|
{
|
|
difference = 0.0;
|
|
result = true;
|
|
}
|
|
else
|
|
{
|
|
if ( xl != xr && xl != x )
|
|
{
|
|
k1 = ( y - yl ) / ( x - xl );
|
|
k2 = ( yr - yl ) / ( xr - xl );
|
|
if ((( xl < xr &&
|
|
( x > xl || AlmostEqualAbsolute ( x,xl,tolerance ) ) &&
|
|
( x < xr || AlmostEqualAbsolute ( x,xr,tolerance ) ) ) ||
|
|
( xl > xr &&
|
|
( x < xl || AlmostEqualAbsolute ( x,xl,tolerance )) &&
|
|
( x > xr || AlmostEqualAbsolute ( x,xr,tolerance ) ) ) ) &&
|
|
( ( ( yl < yr || AlmostEqualAbsolute ( yl,yr,tolerance )) &&
|
|
( y > yl || AlmostEqualAbsolute (y,yl,tolerance )) &&
|
|
( y < yr || AlmostEqualAbsolute ( y,yr,tolerance )) ) ||
|
|
( yl > yr &&
|
|
( y < yl || AlmostEqualAbsolute ( y,yl,tolerance )) &&
|
|
( y > yr || AlmostEqualAbsolute ( y,yr,tolerance ) ) ) ) )
|
|
{
|
|
difference = fabs ( k1-k2 );
|
|
result = true;
|
|
}
|
|
else {result = false;}
|
|
}
|
|
else
|
|
{
|
|
if ( ( AlmostEqualAbsolute ( xl, xr,tolerance ) &&
|
|
AlmostEqualAbsolute ( xl,x,tolerance )) &&
|
|
( ( ( yl < yr|| AlmostEqualAbsolute ( yl,yr,tolerance )) &&
|
|
( yl < y || AlmostEqualAbsolute (yl,y ,tolerance) ) &&
|
|
( y < yr || AlmostEqualAbsolute ( y,yr,tolerance ) ) ) ||
|
|
( yl > yr &&
|
|
( yl > y || AlmostEqualAbsolute ( yl,y,tolerance )) &&
|
|
( y > yr || AlmostEqualAbsolute ( y,yr,tolerance )) ) ) )
|
|
{
|
|
difference = 0.0;
|
|
result = true;
|
|
}
|
|
else {result = false;}
|
|
}
|
|
}
|
|
if ( result )
|
|
{
|
|
LRS lrs;
|
|
route->Get ( hs.attr.edgeno, lrs );
|
|
route->Get ( lrs.hsPos, hs );
|
|
pos = lrs.lrsPos + point.Distance ( hs.GetDomPoint() );
|
|
if ( !startSmaller)
|
|
pos = route->Length() - pos;
|
|
if ( pos < 0.0 || AlmostEqualAbsolute ( pos, 0.0, tolerance ) )
|
|
pos = 0.0;
|
|
else if ( pos > route->Length() ||
|
|
AlmostEqualAbsolute( pos,route->Length(),tolerance))
|
|
pos = route->Length();
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
Returns true if a ~point~ is part of a ~sline~, false elsewhere. If the point
|
|
is part of the sline his distance from the start is computed also. Used by
|
|
operator ~line2gline~.
|
|
|
|
*/
|
|
bool checkPoint ( SimpleLine *&route, const Point point,
|
|
const bool startSmaller, const double tolerance,
|
|
double &pos )
|
|
{
|
|
bool result = false;
|
|
HalfSegment hs;
|
|
double k1, k2;
|
|
Point left, right;
|
|
for ( int i = 0; i < route->Size()-1; i++ )
|
|
{
|
|
route->Get ( i, hs );
|
|
left = hs.GetLeftPoint();
|
|
right = hs.GetRightPoint();
|
|
Coord xl = left.GetX(),
|
|
yl = left.GetY(),
|
|
xr = right.GetX(),
|
|
yr = right.GetY(),
|
|
x = point.GetX(),
|
|
y = point.GetY();
|
|
if ( ( AlmostEqualAbsolute ( x,xr,tolerance ) &&
|
|
AlmostEqualAbsolute ( y,yr,tolerance )) ||
|
|
( AlmostEqualAbsolute ( x,xl,tolerance ) &&
|
|
AlmostEqualAbsolute ( y,yl,tolerance )) )
|
|
{
|
|
result = true;
|
|
}
|
|
else
|
|
{
|
|
if ( xl != xr && xl != x )
|
|
{
|
|
k1 = ( y - yl ) / ( x - xl );
|
|
k2 = ( yr - yl ) / ( xr - xl );
|
|
if ( ( fabs ( k1-k2 ) < 0.004*tolerance ) &&
|
|
( ( xl < xr &&
|
|
( x > xl || AlmostEqualAbsolute ( x,xl,tolerance )) &&
|
|
( x < xr || AlmostEqualAbsolute ( x,xr,tolerance ) ) ) ||
|
|
( xl > xr &&
|
|
( x < xl || AlmostEqualAbsolute ( x,xl,tolerance )) &&
|
|
( x > xr || AlmostEqualAbsolute ( x,xr,tolerance )) ) ) &&
|
|
( ( ( yl < yr || AlmostEqualAbsolute ( yl,yr,tolerance )) &&
|
|
( y > yl || AlmostEqualAbsolute ( y,yl,tolerance )) &&
|
|
( y < yr || AlmostEqualAbsolute ( y,yr,tolerance )) ) ||
|
|
( yl > yr &&
|
|
( y < yl || AlmostEqualAbsolute ( y,yl,tolerance )) &&
|
|
( y > yr || AlmostEqualAbsolute ( y,yr,tolerance )) ) ) )
|
|
{
|
|
result = true;
|
|
}
|
|
else {result = false;}
|
|
}
|
|
else
|
|
{
|
|
if ( ( AlmostEqualAbsolute ( xl, xr,tolerance ) &&
|
|
AlmostEqualAbsolute ( xl,x, tolerance)) &&
|
|
( ( ( yl < yr|| AlmostEqualAbsolute ( yl,yr, tolerance )) &&
|
|
( yl < y || AlmostEqualAbsolute ( yl,y, tolerance ) ) &&
|
|
( y < yr ||AlmostEqualAbsolute ( y,yr, tolerance ) ) ) ||
|
|
( yl > yr &&
|
|
( yl > y || AlmostEqualAbsolute ( yl,y,tolerance )) &&
|
|
( y > yr || AlmostEqualAbsolute ( y,yr, tolerance ) ) ) ) )
|
|
{
|
|
result = true;
|
|
}
|
|
else {result = false;}
|
|
}
|
|
}
|
|
if ( result )
|
|
{
|
|
LRS lrs;
|
|
route->Get ( hs.attr.edgeno, lrs );
|
|
route->Get ( lrs.hsPos, hs );
|
|
pos = lrs.lrsPos + point.Distance ( hs.GetDomPoint() );
|
|
if ( startSmaller != route->GetStartSmaller() )
|
|
pos = route->Length() - pos;
|
|
if ( AlmostEqualAbsolute( pos,0.0, tolerance ))
|
|
pos = 0.0;
|
|
else if ( AlmostEqualAbsolute ( pos,route->Length(), tolerance ))
|
|
pos = route->Length();
|
|
return result;
|
|
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
|
|
/*
|
|
Precondition: ~GLine~ is sorted.
|
|
|
|
Returns true if there is a ~RouteInterval~ in the sorted ~GLine~ which
|
|
intersects with the given ~RouteInterval~ false elsewhere.
|
|
|
|
Used by operator ~intersects~
|
|
|
|
*/
|
|
|
|
bool searchUnit ( const GLine *pGLine, const int low, const int high,
|
|
const RouteInterval pRi )
|
|
{
|
|
|
|
assert ( pGLine->IsSorted() );
|
|
RouteInterval rI;
|
|
if ( low <= high )
|
|
{
|
|
int mid = ( high + low ) / 2;
|
|
if ( ( mid < 0 ) || ( mid >= pGLine->NoOfComponents() ) )
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
pGLine->Get ( mid, rI );
|
|
|
|
if ( rI.GetRouteId() < pRi.GetRouteId() )
|
|
{
|
|
return searchUnit ( pGLine, mid+1, high, pRi );
|
|
}
|
|
else
|
|
{
|
|
if ( rI.GetRouteId() > pRi.GetRouteId() )
|
|
{
|
|
return searchUnit ( pGLine, low, mid-1, pRi );
|
|
}
|
|
else
|
|
{
|
|
if ( rI.GetStartPos() > pRi.GetEndPos() )
|
|
{
|
|
return searchUnit ( pGLine, low, mid-1, pRi );
|
|
}
|
|
else
|
|
{
|
|
if ( rI.GetEndPos() < pRi.GetStartPos() )
|
|
{
|
|
return searchUnit ( pGLine, mid+1, high, pRi );
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/*
|
|
class ~GPointList~
|
|
|
|
Used by the operator ~polygpoint~. Computes and stores the resulting ~GPoints~
|
|
for the resulting ~stream~ of ~GPoint~.
|
|
|
|
*/
|
|
|
|
class GPointList
|
|
{
|
|
public:
|
|
/*
|
|
The constructor creates a GPointList from a given gpoint.
|
|
|
|
*/
|
|
GPointList ( const GPoint *gp, const Network *pNetwork ) :
|
|
aliasGP ( 1 )
|
|
{
|
|
lastPos = 0;
|
|
aliasGP.clean();
|
|
aliasGP.Append ( *gp );
|
|
vector<JunctionSortEntry> xJunctions;
|
|
xJunctions.clear();
|
|
if ( pNetwork != 0 )
|
|
{
|
|
CcInt iRouteId ( true, gp->GetRouteId() );
|
|
pNetwork->GetJunctionsOnRoute ( &iRouteId, xJunctions );
|
|
bool found = false;
|
|
JunctionSortEntry pCurrJunction;
|
|
size_t i = 0;
|
|
while ( !found && i < xJunctions.size() )
|
|
{
|
|
pCurrJunction = xJunctions[i];
|
|
if (AlmostEqualAbsolute( pCurrJunction.GetRouteMeas(),
|
|
gp->GetPosition(),
|
|
pNetwork->GetScalefactor()*0.01))
|
|
{
|
|
found = true;
|
|
aliasGP.Append ( GPoint( true, gp->GetNetworkId(),
|
|
pCurrJunction.GetOtherRouteId(),
|
|
pCurrJunction.GetOtherRouteMeas(),
|
|
None) );
|
|
}
|
|
i++;
|
|
}
|
|
while ( found && i < xJunctions.size() )
|
|
{
|
|
pCurrJunction = xJunctions[i];
|
|
if ( AlmostEqualAbsolute ( pCurrJunction.GetRouteMeas(),
|
|
gp->GetPosition(),
|
|
pNetwork->GetScalefactor()*0.01))
|
|
{
|
|
aliasGP.Append ( GPoint(true, gp->GetNetworkId(),
|
|
pCurrJunction.GetOtherRouteId(),
|
|
pCurrJunction.GetOtherRouteMeas(),
|
|
None) );
|
|
}
|
|
else
|
|
{
|
|
found = false;
|
|
}
|
|
i++;
|
|
}
|
|
for ( size_t i=0;i<xJunctions.size();i++ )
|
|
{
|
|
xJunctions[i].m_pJunction->DeleteIfAllowed();
|
|
}
|
|
xJunctions.clear();
|
|
}
|
|
}
|
|
|
|
~GPointList() {}
|
|
|
|
/*
|
|
~NextGPoint~
|
|
|
|
This function returns the next GPoint from the GPointList.
|
|
If there is no more GPoint in the List the result will be
|
|
0. This function creates a new GPoint instance via the new
|
|
operator. The caller of this function has to ensure the
|
|
deletion of this object.
|
|
|
|
*/
|
|
const GPoint NextGPoint()
|
|
{
|
|
GPoint pAktGPoint(true);
|
|
if ( lastPos < aliasGP.Size() && lastPos >= 0 )
|
|
{
|
|
aliasGP.Get ( lastPos, pAktGPoint );
|
|
lastPos++;
|
|
return pAktGPoint;
|
|
}
|
|
else
|
|
{
|
|
pAktGPoint.SetDefined(false);
|
|
return pAktGPoint;
|
|
}
|
|
}
|
|
|
|
void Destroy()
|
|
{
|
|
aliasGP.Destroy();
|
|
}
|
|
|
|
private:
|
|
|
|
DbArray<GPoint> aliasGP;
|
|
int lastPos;
|
|
|
|
};
|
|
|
|
/*
|
|
class ~RectangleList~
|
|
|
|
Almost similar to ~GPointList~. But storing rectangles representing route
|
|
intervals of a ~gline~. Used by operator ~routeintervals~ to create a ~stream~
|
|
of ~rectangles~.
|
|
|
|
*/
|
|
|
|
class RectangleList
|
|
{
|
|
|
|
public:
|
|
|
|
/*
|
|
~Constructor~
|
|
|
|
Creates a RectangleList from a given gline.
|
|
|
|
*/
|
|
|
|
RectangleList ( const GLine *gl ) :
|
|
aliasRectangleList ( 0 )
|
|
{
|
|
RouteInterval ri;
|
|
lastPos = 0;
|
|
aliasRectangleList.clean();
|
|
for ( int i = 0 ; i < gl->NoOfComponents(); i++ )
|
|
{
|
|
gl->Get ( i, ri );
|
|
double minMax[] = { ( double ) ri.GetRouteId(),
|
|
( double ) ri.GetRouteId(),
|
|
min ( ri.GetStartPos(),ri.GetEndPos() ),
|
|
max ( ri.GetStartPos(), ri.GetEndPos() )};
|
|
Rectangle<2> elem ( true,minMax);
|
|
aliasRectangleList.Append ( elem );
|
|
}
|
|
}
|
|
|
|
~RectangleList() {}
|
|
|
|
/*
|
|
~NextRectangle~
|
|
|
|
This function returns the next rectangle from the RectangleList.
|
|
If there is no more route interval in the List the result will be
|
|
0. This function creates a new Rectangle instance via the new
|
|
operator. The caller of this function has to ensure the
|
|
deletion of this object.
|
|
|
|
*/
|
|
const Rectangle<2> NextRectangle()
|
|
{
|
|
Rectangle<2> pAktRectangle;
|
|
if ( lastPos >= aliasRectangleList.Size() || lastPos < 0 )
|
|
{
|
|
pAktRectangle.SetDefined ( false );
|
|
}
|
|
else
|
|
{
|
|
aliasRectangleList.Get ( lastPos, pAktRectangle );
|
|
lastPos++;
|
|
}
|
|
return pAktRectangle;
|
|
}
|
|
|
|
private:
|
|
|
|
DbArray<Rectangle<2> > aliasRectangleList;
|
|
int lastPos;
|
|
|
|
};
|
|
|
|
/*
|
|
~struct RIStack~
|
|
|
|
Used to build compressed shortestpath ~gline~ values.
|
|
The ~RouteIntervals~ of the shortest path computation are pushed to a stack to
|
|
first the end section. Last the first section of the path. So they can be
|
|
returned in the sequence they are needed in the path.
|
|
|
|
When the stack is returned to the resulting ~gline~ it is checked if the
|
|
~RouteInterval~s on the stack can be connected to bigger parts. This is always
|
|
possible if the shortest path follows the same route for more than one section.
|
|
|
|
*/
|
|
|
|
struct RIStack
|
|
{
|
|
|
|
RIStack() {};
|
|
|
|
RIStack ( const int ri, const double pos1, const double pos2,
|
|
RIStack* next = 0 )
|
|
{
|
|
m_iRouteId = ri;
|
|
m_dStart = pos1;
|
|
m_dEnd = pos2;
|
|
m_next = next;
|
|
};
|
|
|
|
~RIStack() {};
|
|
|
|
void Push ( const int rid, const double pos1, const double pos2,
|
|
RIStack *&first )
|
|
{
|
|
RIStack *actElem = new RIStack ( rid, pos1, pos2, this );
|
|
first = actElem;
|
|
};
|
|
|
|
void StackToGLine ( GLine *gline, const double tolerance ) const
|
|
{
|
|
int actRId = m_iRouteId;
|
|
double actStartPos = m_dStart;
|
|
double actEndPos = m_dEnd;
|
|
RIStack *actElem = m_next;
|
|
while ( actElem != 0 )
|
|
{
|
|
if ( actRId == actElem->m_iRouteId &&
|
|
AlmostEqualAbsolute ( actEndPos,actElem->m_dStart, tolerance ) )
|
|
{
|
|
|
|
actEndPos = actElem->m_dEnd;
|
|
}
|
|
else
|
|
{
|
|
gline->AddRouteInterval ( actRId, actStartPos, actEndPos );
|
|
actRId = actElem->m_iRouteId;
|
|
actStartPos = actElem->m_dStart;
|
|
actEndPos = actElem->m_dEnd;
|
|
}
|
|
actElem = actElem->m_next;
|
|
}
|
|
gline->AddRouteInterval ( actRId, actStartPos, actEndPos );
|
|
};
|
|
|
|
void RemoveStack()
|
|
{
|
|
if ( m_next != 0 ) m_next->RemoveStack();
|
|
delete this;
|
|
};
|
|
|
|
int m_iRouteId;
|
|
double m_dStart, m_dEnd;
|
|
RIStack *m_next;
|
|
};
|
|
|
|
/*
|
|
Analogous to RIStack but not limited by main memory.
|
|
|
|
*/
|
|
|
|
struct RIStackP
|
|
{
|
|
|
|
RIStackP():ristack(0)
|
|
{
|
|
lastEntry = -1;
|
|
};
|
|
|
|
RIStackP(const int n):ristack(n)
|
|
{
|
|
lastEntry = -1;
|
|
};
|
|
|
|
~RIStackP() {};
|
|
|
|
void Destroy()
|
|
{
|
|
ristack.Destroy();
|
|
}
|
|
|
|
void Push ( const int rid, const double pos1, const double pos2)
|
|
{
|
|
ristack.Put(lastEntry+1,RouteInterval(rid,pos1,pos2));
|
|
lastEntry++;
|
|
};
|
|
|
|
void Push (const RouteInterval ri)
|
|
{
|
|
ristack.Put(lastEntry+1,ri);
|
|
lastEntry++;
|
|
}
|
|
|
|
void StackToGLine ( GLine *gline, const int netid ) const
|
|
{
|
|
gline->Clear();
|
|
gline->SetNetworkId(netid);
|
|
RouteInterval ri1, ri2;
|
|
int i = lastEntry;
|
|
if (i > -1 )
|
|
{
|
|
ristack.Get(i,ri1);
|
|
gline->SetDefined(true);
|
|
}
|
|
else
|
|
gline->SetDefined(false);
|
|
i--;
|
|
while (i >= 0)
|
|
{
|
|
ristack.Get(i,ri2);
|
|
if (ri2.GetRouteId() == ri1.GetRouteId() &&
|
|
AlmostEqual(ri1.GetEndPos(),ri2.GetStartPos()))
|
|
{
|
|
ri1.SetEndPos(ri2.GetEndPos());
|
|
}
|
|
else
|
|
{
|
|
gline->AddRouteInterval(ri1);
|
|
ri1 = ri2;
|
|
}
|
|
i--;
|
|
}
|
|
gline->AddRouteInterval ( ri1);
|
|
};
|
|
|
|
DbArray<RouteInterval> ristack;
|
|
int lastEntry;
|
|
};
|
|
|
|
/*
|
|
Class PQEntry used for priority Queue in Dijkstras Algorithm for shortest path
|
|
computing between two gpoint.
|
|
|
|
*/
|
|
|
|
class PQEntry
|
|
{
|
|
public:
|
|
PQEntry() {}
|
|
|
|
PQEntry ( const TupleId aktID, const double distance, const bool upDown,
|
|
const TupleId beforeID )
|
|
{
|
|
sectID = aktID;
|
|
distFromStart = distance;
|
|
upDownFlag = upDown;
|
|
beforeSectID = beforeID;
|
|
}
|
|
|
|
PQEntry ( const PQEntry &e )
|
|
{
|
|
sectID = e.sectID;
|
|
distFromStart = e.distFromStart;
|
|
upDownFlag = e.upDownFlag;
|
|
beforeSectID = e.beforeSectID;
|
|
}
|
|
|
|
ostream& Print ( ostream& os ) const
|
|
{
|
|
os << "Section TupleId: " << sectID << endl;
|
|
os << "Distance from Start: " << distFromStart << endl;
|
|
os << "upDownFlag: " << upDownFlag << endl;
|
|
os << "Before Section TupleId: " << beforeSectID << endl;
|
|
os << endl;
|
|
return os;
|
|
}
|
|
|
|
ostream& csvout (ostream& os) const
|
|
{
|
|
os << sectID << ";" << upDownFlag << endl;
|
|
return os;
|
|
}
|
|
|
|
~PQEntry() {}
|
|
|
|
TupleId sectID;
|
|
double distFromStart;
|
|
bool upDownFlag;
|
|
TupleId beforeSectID;
|
|
};
|
|
|
|
/*
|
|
Almost similar to PQEntry but supporting priority values needed by
|
|
A-Star-Algorithm.
|
|
|
|
*/
|
|
|
|
class PQEntryA {
|
|
public:
|
|
|
|
PQEntryA(){};
|
|
|
|
PQEntryA(const TupleId aktID, const double weight, const double value,
|
|
const bool upDown, const TupleId beforeID,
|
|
const bool beforeUp )
|
|
{
|
|
sectID = aktID;
|
|
prioval = weight;
|
|
valFromStart = value;
|
|
upDownFlag = upDown;
|
|
beforeSectID = beforeID;
|
|
beforeUpDown = beforeUp;
|
|
};
|
|
|
|
PQEntryA (const PQEntryA &e )
|
|
{
|
|
sectID = e.sectID;
|
|
prioval = e.prioval;
|
|
valFromStart = e.valFromStart;
|
|
upDownFlag = e.upDownFlag;
|
|
beforeSectID = e.beforeSectID;
|
|
beforeUpDown = e.beforeUpDown;
|
|
}
|
|
|
|
int Compare(const PQEntryA& nE) const
|
|
{
|
|
if (sectID < nE.sectID) return -1;
|
|
if (sectID > nE.sectID) return 1;
|
|
if (prioval < nE.prioval) return -1;
|
|
if (prioval > nE.prioval) return 1;
|
|
if (valFromStart < nE.valFromStart) return -1;
|
|
if (valFromStart > nE.valFromStart) return 1;
|
|
return 0;
|
|
}
|
|
|
|
ostream& Print ( ostream& os ) const
|
|
{
|
|
os << "Section TupleId: " << sectID << endl;
|
|
os << "Weight: " << prioval << endl;
|
|
os << "Distance from Start: " << valFromStart << endl;
|
|
os << "upDownFlag: " << upDownFlag << endl;
|
|
os << "Before Section TupleId: " << beforeSectID << endl;
|
|
os << "Before Section UpDownFlag: " << beforeUpDown << endl;
|
|
return os;
|
|
}
|
|
|
|
~PQEntryA() {};
|
|
|
|
TupleId sectID;
|
|
double prioval;
|
|
double valFromStart;
|
|
bool upDownFlag;
|
|
TupleId beforeSectID;
|
|
bool beforeUpDown;
|
|
|
|
};
|
|
|
|
/*
|
|
Section Entries for data structure used in shortest path search.
|
|
|
|
*/
|
|
|
|
struct SectEntry
|
|
{
|
|
SectEntry(){}
|
|
|
|
SectEntry(const SectEntry& nE)
|
|
: sectID(nE.GetSectId()),
|
|
beforeSectId(nE.GetBeforeSectId()),
|
|
upDownFlag(nE.GetUpDownFlag()),
|
|
beforeSectUpDown(nE.GetBeforeSectUpDown()),
|
|
index(nE.GetIndex()),
|
|
distFromStart(nE.GetDistFromStart())
|
|
{}
|
|
|
|
SectEntry(const TupleId sid, const TupleId befSID, const bool updown,
|
|
const bool befUpDown, const int i, const double dist)
|
|
: sectID(sid), beforeSectId(befSID), upDownFlag(updown),
|
|
beforeSectUpDown(befUpDown), index(i),
|
|
distFromStart(dist)
|
|
{}
|
|
|
|
~SectEntry(){}
|
|
|
|
inline TupleId GetSectId() const
|
|
{
|
|
return sectID;
|
|
}
|
|
|
|
inline TupleId GetBeforeSectId() const
|
|
{
|
|
return beforeSectId;
|
|
}
|
|
|
|
inline bool GetUpDownFlag() const
|
|
{
|
|
return upDownFlag;
|
|
}
|
|
|
|
inline int GetIndex() const
|
|
{
|
|
return index;
|
|
}
|
|
|
|
inline double GetDistFromStart() const
|
|
{
|
|
return distFromStart;
|
|
}
|
|
|
|
inline bool GetBeforeSectUpDown() const
|
|
{
|
|
return beforeSectUpDown;
|
|
}
|
|
|
|
int Compare (const SectEntry& se) const
|
|
{
|
|
return Compare(se.GetSectId(),se.GetUpDownFlag());
|
|
}
|
|
|
|
inline int Compare (const TupleId sid, const bool upDown) const
|
|
{
|
|
if (sectID < sid ) return -1;
|
|
if (sectID > sid ) return 1;
|
|
if (upDownFlag < upDown) return -1;
|
|
if (upDownFlag > upDown) return 1;
|
|
return 0;
|
|
}
|
|
|
|
void operator=(const SectEntry& se)
|
|
{
|
|
sectID = se.GetSectId();
|
|
beforeSectId = se.GetBeforeSectId();
|
|
upDownFlag = se.GetUpDownFlag();
|
|
index = se.GetIndex();
|
|
distFromStart = se.GetDistFromStart();
|
|
beforeSectUpDown = se.GetBeforeSectUpDown();
|
|
}
|
|
|
|
ostream& Print(ostream& os) const
|
|
{
|
|
os << "SectEntry: ";
|
|
os << "SectionID: " << sectID;
|
|
os << ", upDownFlag: " << upDownFlag;
|
|
os << ", Before Section Id: " << beforeSectId;
|
|
os << ", Before Section UpDownFlag: " << beforeSectUpDown;
|
|
os << ", index: " << index;
|
|
os << ", distFromStart: " << distFromStart << endl;
|
|
return os;
|
|
}
|
|
|
|
inline void SetSectID(const TupleId tid)
|
|
{
|
|
sectID = tid;
|
|
}
|
|
|
|
inline void SetBeforeSectId(const TupleId tid)
|
|
{
|
|
beforeSectId = tid;
|
|
}
|
|
|
|
inline void SetUpDownFlag(const bool b)
|
|
{
|
|
upDownFlag = b;
|
|
}
|
|
|
|
inline void SetIndex(const int i)
|
|
{
|
|
index = i;
|
|
}
|
|
|
|
inline void SetDistFromStart(const double dist)
|
|
{
|
|
distFromStart = dist;
|
|
}
|
|
|
|
inline void SetBeforeSectUpDown(const bool upDown)
|
|
{
|
|
beforeSectUpDown = upDown;
|
|
}
|
|
|
|
TupleId sectID;
|
|
TupleId beforeSectId;
|
|
bool upDownFlag;
|
|
bool beforeSectUpDown;
|
|
int index;
|
|
double distFromStart;
|
|
};
|
|
|
|
/*
|
|
Helpful datastructure for shortest path search.
|
|
|
|
*/
|
|
|
|
struct SectIDTreeEntry
|
|
{
|
|
SectIDTreeEntry(){}
|
|
|
|
SectIDTreeEntry(const SectEntry ne, const int l = -1, const int r = -1)
|
|
: sE(ne), left(l), right(r)
|
|
{}
|
|
|
|
SectIDTreeEntry(const SectIDTreeEntry& nSE)
|
|
{
|
|
sE = nSE.GetEntry();
|
|
left = nSE.GetLeft();
|
|
right = nSE.GetRight();
|
|
}
|
|
|
|
~SectIDTreeEntry(){}
|
|
|
|
inline SectEntry GetEntry() const
|
|
{
|
|
return sE;
|
|
}
|
|
|
|
inline int GetLeft() const
|
|
{
|
|
return left;
|
|
}
|
|
|
|
inline int GetRight() const
|
|
{
|
|
return right;
|
|
}
|
|
|
|
inline void SetEntry(const SectEntry nse)
|
|
{
|
|
sE = nse;
|
|
}
|
|
|
|
inline void SetLeft(const int l)
|
|
{
|
|
left = l;
|
|
}
|
|
|
|
inline void SetRight(const int r)
|
|
{
|
|
right = r;
|
|
}
|
|
|
|
void operator=(const SectIDTreeEntry siE)
|
|
{
|
|
sE = siE.GetEntry();
|
|
left = siE.GetLeft();
|
|
right = siE.GetRight();
|
|
}
|
|
|
|
inline int Compare(const SectIDTreeEntry& siE) const
|
|
{
|
|
return Compare(siE.GetEntry());
|
|
}
|
|
|
|
inline int Compare(const SectEntry& cse) const
|
|
{
|
|
return GetEntry().Compare(cse);
|
|
}
|
|
|
|
inline int Compare(const int stid, const bool upDown) const
|
|
{
|
|
return GetEntry().Compare(stid,upDown);
|
|
}
|
|
|
|
ostream& Print(ostream& os) const
|
|
{
|
|
os << "SectIDTreeEntry: ";
|
|
sE.Print(os);
|
|
os << ", left: " << left;
|
|
os << ", right: " << right << endl;
|
|
return os;
|
|
}
|
|
|
|
SectEntry sE;
|
|
int left, right;
|
|
};
|
|
|
|
/*
|
|
Not main memory limited data structure supporting shortest path search.
|
|
|
|
*/
|
|
|
|
struct SectIDTreeP
|
|
{
|
|
SectIDTreeP()
|
|
: tree(0)
|
|
{
|
|
fFree = 0;
|
|
}
|
|
|
|
SectIDTreeP(const int n)
|
|
: tree(n)
|
|
{
|
|
fFree = 0;
|
|
}
|
|
|
|
~SectIDTreeP(){};
|
|
|
|
inline void Destroy()
|
|
{
|
|
tree.Destroy();
|
|
}
|
|
|
|
int Find(const SectIDTreeEntry& te) const
|
|
{
|
|
int i = 0;
|
|
if (tree.Size() < 1) return -1;
|
|
while (i < fFree)
|
|
{
|
|
SectIDTreeEntry test = GetTreeEntry(i);
|
|
switch(test.Compare(te))
|
|
{
|
|
case 0:
|
|
{
|
|
return i;
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
if (test.GetLeft() != -1) i = test.GetLeft();
|
|
else return i;
|
|
break;
|
|
}
|
|
case -1:
|
|
{
|
|
if (test.GetRight() != -1) i = test.GetRight();
|
|
else return i;
|
|
break;
|
|
}
|
|
default: // should never been reached
|
|
{
|
|
return -1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return -1; // should never been reached.
|
|
}
|
|
|
|
int Find(const TupleId tid, const bool upDown) const
|
|
{
|
|
int i = 0;
|
|
if (tree.Size() < 1) return -1;
|
|
while (i < fFree)
|
|
{
|
|
SectIDTreeEntry test = GetTreeEntry(i);
|
|
switch(test.Compare(tid,upDown))
|
|
{
|
|
case 0:
|
|
{
|
|
return i;
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
if (test.GetLeft() > -1) i = test.GetLeft();
|
|
else return i;
|
|
break;
|
|
}
|
|
case -1:
|
|
{
|
|
if (test.GetRight() > -1) i = test.GetRight();
|
|
else return i;
|
|
break;
|
|
}
|
|
default: // should never been reached
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
return -1; //Should never been reached
|
|
}
|
|
|
|
ostream& Print(ostream& os) const
|
|
{
|
|
for (int i = 0; i < tree.Size(); i++)
|
|
{
|
|
SectIDTreeEntry te = GetTreeEntry(i);
|
|
te.Print(os);
|
|
}
|
|
return os;
|
|
}
|
|
|
|
bool Insert(const SectIDTreeEntry nse, int& newPos)
|
|
{
|
|
newPos = Find(nse);
|
|
if (newPos < 0)
|
|
{
|
|
newPos = fFree;
|
|
fFree++;
|
|
tree.Put(newPos, nse);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
if (newPos >= 0 && newPos < fFree)
|
|
{
|
|
SectIDTreeEntry test = GetTreeEntry(newPos);
|
|
switch(test.Compare(nse))
|
|
{
|
|
case 1:
|
|
{
|
|
test.SetLeft(fFree);
|
|
tree.Put(newPos,test);
|
|
tree.Put(fFree,nse);
|
|
fFree++;
|
|
return true;
|
|
break;
|
|
}
|
|
case -1:
|
|
{
|
|
test.SetRight(fFree);
|
|
tree.Put(newPos,test);
|
|
tree.Put(fFree,nse);
|
|
fFree++;
|
|
return true;
|
|
break;
|
|
}
|
|
case 0:
|
|
{
|
|
if (nse.GetEntry().GetDistFromStart() <
|
|
test.GetEntry().GetDistFromStart())
|
|
{
|
|
tree.Put(newPos,nse);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
default: // should never been reached
|
|
{
|
|
return false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
return false; //should never been reached
|
|
}
|
|
|
|
void SetIndex (const int pos, const int index)
|
|
{
|
|
assert(pos > -1 && pos < fFree);
|
|
SectIDTreeEntry te = GetTreeEntry(pos);
|
|
SectEntry nE = te.GetEntry();
|
|
nE.SetIndex(index);
|
|
te.SetEntry(nE);
|
|
tree.Put(pos,te);
|
|
}
|
|
|
|
inline int GetIndex (const int pos) const
|
|
{
|
|
assert(pos > -1 && pos < fFree);
|
|
return GetTreeEntry(pos).GetEntry().GetIndex();
|
|
}
|
|
|
|
void SetBeforeSectId(const int pos, const TupleId before)
|
|
{
|
|
assert (pos > -1 && pos < fFree);
|
|
SectIDTreeEntry te = GetTreeEntry(pos);
|
|
SectEntry ne = te.GetEntry();
|
|
ne.SetBeforeSectId(before);
|
|
te.SetEntry(ne);
|
|
tree.Put(pos,te);
|
|
}
|
|
|
|
void SetBeforeUpDownFlag(const int pos, const bool upDown)
|
|
{
|
|
assert (pos > -1 && pos < fFree);
|
|
SectIDTreeEntry te = GetTreeEntry(pos);
|
|
SectEntry ne = te.GetEntry();
|
|
ne.SetBeforeSectUpDown(upDown);
|
|
te.SetEntry(ne);
|
|
tree.Put(pos,te);
|
|
}
|
|
|
|
SectIDTreeEntry GetTreeEntry(const int pos) const
|
|
{
|
|
assert(pos > -1 && pos < fFree);
|
|
SectIDTreeEntry te;
|
|
tree.Get(pos,te);
|
|
return te;
|
|
}
|
|
|
|
bool IsNode(const int pos, const TupleId sectId, const bool upDown) const
|
|
{
|
|
assert (pos > -1 && pos < fFree);
|
|
SectEntry se = GetTreeEntry(pos).GetEntry();
|
|
if (se.Compare(sectId,upDown) == 0)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
void SetDistance(const int pos, const double dist)
|
|
{
|
|
assert (pos > -1 && pos < fFree);
|
|
SectIDTreeEntry te = GetTreeEntry(pos);
|
|
SectEntry ne = te.GetEntry();
|
|
ne.SetDistFromStart(dist);
|
|
te.SetEntry(ne);
|
|
tree.Put(pos,te);
|
|
}
|
|
|
|
void SetFlag(const int pos, const bool upDown)
|
|
{
|
|
assert (pos > -1 && pos < fFree);
|
|
SectIDTreeEntry te = GetTreeEntry(pos);
|
|
SectEntry ne = te.GetEntry();
|
|
ne.SetUpDownFlag(upDown);
|
|
te.SetEntry(ne);
|
|
tree.Put(pos,te);
|
|
}
|
|
|
|
DbArray<SectIDTreeEntry> tree;
|
|
int fFree;
|
|
};
|
|
|
|
/*
|
|
struct sectIDTree stores the PQEntrys by section ID with identification flag
|
|
for the PrioQueue-Array.
|
|
An arrayIndex from max integer means not longer in PrioQ and already visited.
|
|
|
|
*/
|
|
|
|
struct SectIDTree
|
|
{
|
|
SectIDTree() {};
|
|
|
|
SectIDTree ( const TupleId sectIdent, const TupleId beforeSectIdent,
|
|
const bool upDown, const int arrayIndex,
|
|
const double dist = numeric_limits<double>::max(),
|
|
SectIDTree *l = 0, SectIDTree *r = 0 )
|
|
{
|
|
sectID = sectIdent;
|
|
beforeSectId = beforeSectIdent;
|
|
upDownFlag = upDown;
|
|
index = arrayIndex;
|
|
left = l;
|
|
right = r;
|
|
distFromStart = dist;
|
|
|
|
};
|
|
|
|
~SectIDTree() {};
|
|
|
|
SectIDTree* Find (const TupleId sectIdent )
|
|
{
|
|
if ( sectID > sectIdent )
|
|
{
|
|
if ( left != 0 ) return left->Find ( sectIdent );
|
|
else
|
|
{
|
|
return this;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( sectID < sectIdent )
|
|
{
|
|
if ( right != 0 ) return right->Find ( sectIdent );
|
|
else
|
|
{
|
|
return this;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return this;
|
|
}
|
|
}
|
|
};
|
|
|
|
ostream& Print(ostream& os) const
|
|
{
|
|
if (left != 0)
|
|
{
|
|
os << "left son:";
|
|
left->Print(os);
|
|
}
|
|
os << "This: ";
|
|
os << "sectID: " << sectID;
|
|
os << ", before sectId: " << beforeSectId;
|
|
os << ", upDownFlag: " << upDownFlag;
|
|
os << ", DistFromStart: " << distFromStart;
|
|
os << ", Index: " << index << endl;
|
|
if (right != 0)
|
|
{
|
|
os << "right son: ";
|
|
right->Print(os);
|
|
}
|
|
return os;
|
|
}
|
|
|
|
void Remove()
|
|
{
|
|
if ( left != 0 ) left->Remove();
|
|
if ( right != 0 ) right->Remove();
|
|
delete this;
|
|
};
|
|
|
|
bool Insert ( const TupleId sectIdent, const TupleId beforeSectIdent,
|
|
const bool upDownFlag, const int arrayIndex,
|
|
SectIDTree *&pointer,
|
|
const double dist = numeric_limits<double>::max())
|
|
{
|
|
pointer = Find ( sectIdent );
|
|
if ( pointer->sectID > sectIdent )
|
|
{
|
|
pointer->left = new SectIDTree ( sectIdent, beforeSectIdent, upDownFlag,
|
|
arrayIndex, dist );
|
|
pointer = pointer->left;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
if ( pointer->sectID < sectIdent )
|
|
{
|
|
pointer->right = new SectIDTree ( sectIdent, beforeSectIdent,
|
|
upDownFlag, arrayIndex, dist);
|
|
pointer = pointer->right;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
if (dist < pointer->distFromStart)
|
|
{
|
|
pointer->beforeSectId = beforeSectIdent;
|
|
pointer->distFromStart = dist;
|
|
pointer->index = arrayIndex;
|
|
pointer->upDownFlag = upDownFlag;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
void SetIndex ( const TupleId sectIdent, const int arrayIndex )
|
|
{
|
|
(Find( sectIdent ))->index = arrayIndex;
|
|
};
|
|
|
|
void SetIndex ( const int arrayIndex )
|
|
{
|
|
index = arrayIndex;
|
|
};
|
|
|
|
void SetFlag(const bool upDown)
|
|
{
|
|
upDownFlag = upDown;
|
|
};
|
|
|
|
void SetDistance(const double dist)
|
|
{
|
|
distFromStart = dist;
|
|
};
|
|
|
|
int GetIndex ( const int sectIdent )
|
|
{
|
|
return (Find ( sectIdent ))->index;
|
|
};
|
|
|
|
void SetBeforeSectId (const TupleId sectIdent, const TupleId before )
|
|
{
|
|
(Find ( sectIdent ))->beforeSectId = before;
|
|
};
|
|
|
|
void SetBeforeSectId ( const TupleId before )
|
|
{
|
|
beforeSectId = before;
|
|
};
|
|
|
|
TupleId sectID;
|
|
TupleId beforeSectId;
|
|
bool upDownFlag;
|
|
int index;
|
|
double distFromStart;
|
|
SectIDTree *left, *right;
|
|
};
|
|
|
|
|
|
/*
|
|
struct Priority Queue for Dijkstras Algorithm of shortest path computing between
|
|
two gpoint.
|
|
|
|
*/
|
|
|
|
struct PrioQueue
|
|
{
|
|
|
|
PrioQueue():prioQ(0) {firstFree = 0;};
|
|
|
|
PrioQueue ( const int n ) : prioQ ( 0 ) {firstFree = 0;};
|
|
|
|
~PrioQueue() {};
|
|
|
|
/*
|
|
If a point is reached second time and the distance of the second way is
|
|
smaller than on the path he has been found before. Its distance value and its
|
|
position in the priority queue must be corrected.
|
|
|
|
*/
|
|
void CorrectPosition ( const int checkX, const PQEntry nElem,
|
|
SectIDTree* pSection,
|
|
SectIDTree *sectTree )
|
|
{
|
|
int act = checkX;
|
|
int n = checkX;
|
|
PQEntry test;
|
|
bool found = false;
|
|
while ( n >= 0 && !found )
|
|
{
|
|
if ( ( act % 2 ) == 0 ) n = ( act-2 ) / 2;
|
|
else n = ( act -1 ) / 2;
|
|
if ( n >= 0 )
|
|
{
|
|
prioQ.Get ( n, test );
|
|
if ( test.distFromStart > nElem.distFromStart )
|
|
{
|
|
PQEntry help = test;
|
|
prioQ.Put ( n, nElem );
|
|
pSection->SetIndex ( n );
|
|
prioQ.Put ( act, help );
|
|
SectIDTree *thelp = sectTree->Find ( help.sectID );
|
|
thelp->SetIndex ( act );
|
|
act = n;
|
|
}
|
|
else
|
|
{
|
|
found = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
found = true;
|
|
}
|
|
}
|
|
};
|
|
|
|
void Insert ( const PQEntry nElem, SectIDTree *sectTree,
|
|
DbArray<TupleId>* touchedSects)
|
|
{
|
|
SectIDTree *pSection = sectTree->Find ( nElem.sectID );
|
|
PQEntry old;
|
|
if ( pSection->sectID == nElem.sectID )
|
|
{
|
|
if ( pSection->index != numeric_limits<int>::max() )
|
|
{
|
|
prioQ.Get ( pSection->index, old );
|
|
if ( nElem.distFromStart < old.distFromStart )
|
|
{
|
|
prioQ.Put ( pSection->index, nElem );
|
|
pSection->SetBeforeSectId ( nElem.beforeSectID );
|
|
CorrectPosition ( pSection->index, nElem, pSection, sectTree );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
prioQ.Put ( firstFree, nElem );
|
|
sectTree->Insert ( nElem.sectID, nElem.beforeSectID, nElem.upDownFlag,
|
|
firstFree, pSection/*, nElem.distFromStart */);
|
|
CorrectPosition ( firstFree, nElem, pSection ,sectTree );
|
|
if(touchedSects != 0) touchedSects->Append(nElem.sectID);
|
|
firstFree++;
|
|
}
|
|
}
|
|
|
|
PQEntry* GetAndDeleteMin ( SectIDTree *sectTree )
|
|
{
|
|
if ( firstFree > 0 )
|
|
{
|
|
PQEntry result, last, test1, test2;
|
|
prioQ.Get ( 0,result );
|
|
PQEntry *retValue = new PQEntry ( result.sectID,
|
|
result.distFromStart,
|
|
result.upDownFlag,
|
|
result.beforeSectID );
|
|
SectIDTree *tRet = sectTree->Find ( result.sectID );
|
|
tRet->SetIndex ( numeric_limits<int>::max() );
|
|
prioQ.Get ( firstFree-1, last );
|
|
prioQ.Put ( 0, last );
|
|
firstFree--;
|
|
SectIDTree *pSection = sectTree->Find ( last.sectID );
|
|
pSection->SetIndex ( 0 );
|
|
int act = 0;
|
|
int checkX = 0;
|
|
bool found = false;
|
|
while ( checkX < firstFree && !found )
|
|
{
|
|
checkX = 2*act + 1;
|
|
if ( checkX < firstFree-1 )
|
|
{
|
|
prioQ.Get ( checkX, test1 );
|
|
prioQ.Get ( checkX+1, test2 );
|
|
if ( test1.distFromStart < last.distFromStart ||
|
|
test2.distFromStart < last.distFromStart )
|
|
{
|
|
if ( test1.distFromStart <= test2.distFromStart )
|
|
{
|
|
PQEntry help = test1;
|
|
prioQ.Put ( checkX, last );
|
|
pSection->SetIndex ( checkX );
|
|
prioQ.Put ( act, help );
|
|
SectIDTree *thelp = sectTree->Find ( help.sectID );
|
|
thelp->SetIndex ( act );
|
|
act = checkX;
|
|
}
|
|
else
|
|
{
|
|
PQEntry help = test2;
|
|
prioQ.Put ( checkX+1, last );
|
|
pSection->SetIndex ( checkX+1 );
|
|
prioQ.Put ( act, help );
|
|
SectIDTree *thelp = sectTree->Find ( help.sectID );
|
|
thelp->SetIndex ( act );
|
|
act = checkX+1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
found = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( checkX != 0 && checkX == firstFree-1 )
|
|
{
|
|
prioQ.Get ( checkX, test1 );
|
|
if ( test1.distFromStart < last.distFromStart )
|
|
{
|
|
PQEntry help = test1;
|
|
prioQ.Put ( checkX, last );
|
|
pSection->SetIndex ( checkX );
|
|
prioQ.Put ( act, help );
|
|
SectIDTree *thelp = sectTree->Find ( help.sectID );
|
|
thelp->SetIndex ( act );
|
|
act = checkX;
|
|
}
|
|
else
|
|
{
|
|
found = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return retValue;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void Clear()
|
|
{
|
|
prioQ.clean();
|
|
firstFree = 0;
|
|
}
|
|
|
|
bool IsEmpty() const
|
|
{
|
|
if ( firstFree == 0 ) return true;
|
|
else return false;
|
|
}
|
|
|
|
void Destroy()
|
|
{
|
|
prioQ.Destroy();
|
|
}
|
|
|
|
DbArray<PQEntry> prioQ;
|
|
int firstFree;
|
|
|
|
};
|
|
|
|
struct PrioQueueA
|
|
{
|
|
PrioQueueA()
|
|
: prioQ(0)
|
|
{
|
|
firstFree=0;
|
|
}
|
|
|
|
PrioQueueA ( const int n )
|
|
: prioQ ( n )
|
|
{
|
|
firstFree = 0;
|
|
}
|
|
|
|
~PrioQueueA() {};
|
|
|
|
/*
|
|
If a point is reached second time and the prioval of the second way is
|
|
smaller than on the path found before. The prioval, the valFromStart and the
|
|
position in the priority queue must be corrected.
|
|
|
|
*/
|
|
void CorrectPosition ( const int checkX, const PQEntryA& nElem,
|
|
SectIDTreeP *sectTree )
|
|
{
|
|
int act = checkX;
|
|
int n = checkX;
|
|
PQEntryA test;
|
|
bool found = false;
|
|
while ( act > 0 && !found )
|
|
{
|
|
if ( ( act % 2 ) == 0 ) n = ( act-2 ) / 2;
|
|
else n = ( act -1 ) / 2;
|
|
if ( n >= 0 )
|
|
{
|
|
prioQ.Get ( n, test );
|
|
if ( test.prioval > nElem.prioval ||
|
|
(test.prioval == nElem.prioval &&
|
|
test.valFromStart > nElem.valFromStart))
|
|
{
|
|
Swap( n, nElem , act, test, sectTree );
|
|
}
|
|
else
|
|
{
|
|
found = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
found = true;
|
|
}
|
|
}
|
|
};
|
|
|
|
void Append ( const PQEntryA nE, int pNElemPos,
|
|
SectIDTreeP *pNodeTree)
|
|
{
|
|
int actPos = firstFree;
|
|
prioQ.Put(actPos, nE );
|
|
pNodeTree->Insert(SectIDTreeEntry(SectEntry(nE.sectID,
|
|
nE.beforeSectID,
|
|
nE.upDownFlag,
|
|
nE.beforeUpDown,
|
|
actPos,
|
|
nE.valFromStart),
|
|
-1,-1),
|
|
pNElemPos);
|
|
CorrectPosition(actPos, nE, pNodeTree );
|
|
firstFree++;
|
|
}
|
|
|
|
void Insert ( const PQEntryA nElem, SectIDTreeP *sectTree,
|
|
DbArray<TupleId>* touchedSects )
|
|
{
|
|
int pSection = sectTree->Find ( nElem.sectID,nElem.upDownFlag );
|
|
if (pSection < 0)
|
|
{
|
|
Append(nElem, pSection,sectTree);
|
|
if (touchedSects != 0) touchedSects->Append(nElem.sectID);
|
|
}
|
|
else
|
|
{
|
|
if (pSection > -1 && pSection < sectTree->fFree)
|
|
{
|
|
if (!sectTree->IsNode(pSection,nElem.sectID,nElem.upDownFlag))
|
|
{
|
|
Append(nElem, pSection,sectTree);
|
|
if (touchedSects != 0) touchedSects->Append(nElem.sectID);
|
|
}
|
|
else
|
|
{
|
|
int index = sectTree->GetIndex(pSection);
|
|
if (index > -1 && index < firstFree)
|
|
{
|
|
PQEntryA test;
|
|
prioQ.Get(index, test);
|
|
if (test.prioval > nElem.prioval)
|
|
{
|
|
prioQ.Put(index,nElem);
|
|
sectTree->SetBeforeSectId(pSection,nElem.beforeSectID);
|
|
sectTree->SetBeforeUpDownFlag(pSection,nElem.beforeUpDown);
|
|
sectTree->SetDistance(pSection, nElem.valFromStart);
|
|
sectTree->SetFlag(pSection, nElem.upDownFlag);
|
|
CorrectPosition(index, nElem, sectTree);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (nElem.valFromStart <
|
|
sectTree->GetTreeEntry(pSection).GetEntry().GetDistFromStart())
|
|
{
|
|
int actPos = firstFree;
|
|
prioQ.Put(actPos,nElem);
|
|
sectTree->SetIndex(pSection, actPos);
|
|
firstFree++;
|
|
sectTree->SetBeforeSectId(pSection,nElem.beforeSectID);
|
|
sectTree->SetBeforeUpDownFlag(pSection,nElem.beforeUpDown);
|
|
sectTree->SetDistance(pSection, nElem.valFromStart);
|
|
sectTree->SetFlag(pSection, nElem.upDownFlag);
|
|
CorrectPosition (actPos, nElem, sectTree );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Swap (const int index1, const PQEntryA& entry1,
|
|
int& index2, const PQEntryA& entry2,
|
|
SectIDTreeP* pSectIdTree)
|
|
{
|
|
prioQ.Put(index1, entry1);
|
|
pSectIdTree->SetIndex(pSectIdTree->Find(entry1.sectID,entry1.upDownFlag),
|
|
index1);
|
|
prioQ.Put(index2, entry2);
|
|
pSectIdTree->SetIndex(pSectIdTree->Find(entry2.sectID,entry2.upDownFlag),
|
|
index2);
|
|
index2 = index1;
|
|
}
|
|
|
|
PQEntryA* GetAndDeleteMin ( SectIDTreeP *sectTree )
|
|
{
|
|
if ( firstFree <= 0 ) return 0;
|
|
PQEntryA result, last, test1, test2;
|
|
prioQ.Get ( 0,result );
|
|
PQEntryA *retValue = new PQEntryA ( result);
|
|
int tRet = sectTree->Find ( result.sectID, result.upDownFlag );
|
|
prioQ.Get (firstFree-1, last );
|
|
prioQ.Put ( 0, last );
|
|
prioQ.Put(firstFree-1, PQEntryA((TupleId)numeric_limits<long>::max(),
|
|
numeric_limits<double>::max(),
|
|
numeric_limits<double>::max(),
|
|
false,
|
|
(TupleId)numeric_limits<long>::max(),
|
|
false));
|
|
|
|
firstFree--;
|
|
int pSection = sectTree->Find ( last.sectID,last.upDownFlag );
|
|
sectTree->SetIndex (pSection,0);
|
|
sectTree->SetIndex(tRet, -1);
|
|
int act = 0;
|
|
int checkX = 0;
|
|
bool found = false;
|
|
while ( checkX < firstFree && !found )
|
|
{
|
|
checkX = 2*act + 1;
|
|
if ( checkX < firstFree-1 )
|
|
{
|
|
prioQ.Get ( checkX, test1 );
|
|
prioQ.Get ( checkX+1, test2 );
|
|
if ( test1.prioval < last.prioval ||
|
|
test2.prioval < last.prioval )
|
|
{
|
|
if ( test1.prioval <= test2.prioval )
|
|
{
|
|
Swap(checkX, last, act, test1, sectTree );
|
|
}
|
|
else
|
|
{
|
|
Swap( checkX+1, last, act, test2, sectTree);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (test1.prioval == last.prioval &&
|
|
test1.valFromStart < last.valFromStart)
|
|
{
|
|
Swap( checkX, last, act, test1, sectTree);
|
|
}
|
|
else
|
|
{
|
|
if (test2.prioval == last.prioval &&
|
|
test2.valFromStart < last.valFromStart)
|
|
{
|
|
Swap( checkX+1, last, act, test2, sectTree );
|
|
}
|
|
else
|
|
{
|
|
found = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( checkX != 0 && checkX == firstFree-1 )
|
|
{
|
|
prioQ.Get ( checkX, test1 );
|
|
if ( test1.prioval < last.prioval ||
|
|
(test1.prioval == last.prioval &&
|
|
test1.valFromStart < last.valFromStart))
|
|
{
|
|
Swap( checkX, last, act, test1, sectTree );
|
|
}
|
|
else
|
|
{
|
|
found = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
found = true;
|
|
}
|
|
}
|
|
}
|
|
return retValue;
|
|
}
|
|
|
|
void Clear()
|
|
{
|
|
prioQ.clean();
|
|
firstFree = 0;
|
|
}
|
|
|
|
bool IsEmpty() const
|
|
{
|
|
if (firstFree == 0 ) return true;
|
|
else return false;
|
|
}
|
|
|
|
void Destroy()
|
|
{
|
|
prioQ.Destroy();
|
|
}
|
|
|
|
ostream& Print(ostream& os) const
|
|
{
|
|
os << "PriorityQueue Start: " << endl;
|
|
PQEntryA pE;
|
|
if (firstFree > 0)
|
|
{
|
|
for (int i = 0; i < prioQ.Size(); i++)
|
|
{
|
|
prioQ.Get(i,pE);
|
|
pE.Print(os);
|
|
}
|
|
}
|
|
os << "PriorityQueue Ende" << endl;
|
|
return os;
|
|
}
|
|
|
|
DbArray<PQEntryA> prioQ;
|
|
int firstFree;
|
|
|
|
};
|
|
|
|
/*
|
|
Some helpful methods for shortest path computing
|
|
|
|
*/
|
|
|
|
bool IsLastSection(const TupleId source,
|
|
DbArray<GPointsSections>* endSections, int& pos)
|
|
{
|
|
GPointsSections target;
|
|
for (int j = 0; j < endSections->Size(); j++)
|
|
{
|
|
endSections->Get(j,target);
|
|
if (source == target.GetTid())
|
|
{
|
|
pos = j;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool IsFirstSection(const TupleId pElem,
|
|
DbArray<GPointsSections>* startSections,
|
|
int& pos)
|
|
{
|
|
GPointsSections source;
|
|
for (int k = 0; k < startSections->Size(); k++)
|
|
{
|
|
startSections->Get(k,source);
|
|
if (pElem == source.GetTid())
|
|
{
|
|
pos = k;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void InsertAdjacentSections(const TupleId tid, const Side direction,
|
|
const bool init, double dist,
|
|
const Points* endPoints,
|
|
const Network* pNetwork, PrioQueueA* prioQ,
|
|
SectIDTreeP* visitedSect,
|
|
DbArray<TupleId>* touchedSects)
|
|
{
|
|
Tuple* sourceTuple = pNetwork->GetSection(tid);
|
|
if (sourceTuple != 0){
|
|
double sectMeas1 =
|
|
((CcReal*) sourceTuple->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
double sectMeas2 =
|
|
((CcReal*)sourceTuple->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
int actRouteId =
|
|
((CcInt*)sourceTuple->GetAttribute(SECTION_RID))->GetIntval();
|
|
Point* sPoint = 0;
|
|
bool upDown = false;
|
|
if (direction == Down)
|
|
{
|
|
if (init)
|
|
dist = fabs(dist - sectMeas1);
|
|
else
|
|
dist += fabs(sectMeas2 - sectMeas1);
|
|
sPoint = (GPoint( true,
|
|
pNetwork->GetId(),
|
|
actRouteId,
|
|
sectMeas1,
|
|
Down)).ToPoint(pNetwork);
|
|
upDown = false;
|
|
}
|
|
else
|
|
{
|
|
if (init)
|
|
dist = fabs(sectMeas2 - dist);
|
|
else
|
|
dist += fabs(sectMeas2 - sectMeas1);
|
|
sPoint = (GPoint( true,
|
|
pNetwork->GetId(),
|
|
actRouteId,
|
|
sectMeas2,
|
|
Up)).ToPoint(pNetwork);
|
|
upDown = true;
|
|
}
|
|
double weight = dist + endPoints->Distance(*sPoint);
|
|
sPoint->DeleteIfAllowed();
|
|
sPoint = 0;
|
|
sourceTuple->DeleteIfAllowed();
|
|
sourceTuple = 0;
|
|
vector<DirectedSection> adjSectionList;
|
|
adjSectionList.clear();
|
|
pNetwork->GetAdjacentSections ( tid, upDown, adjSectionList );
|
|
for (size_t k = 0; k < adjSectionList.size(); k++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[k];
|
|
prioQ->Insert(PQEntryA ( actNextSect.GetSectionTid(),
|
|
weight,
|
|
dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
tid,
|
|
upDown),
|
|
visitedSect, touchedSects ) ;
|
|
}
|
|
adjSectionList.clear();
|
|
}
|
|
}
|
|
|
|
/*
|
|
2 Class Definitions
|
|
|
|
2.1 class ~Network~
|
|
|
|
2.1.2 Network relations
|
|
|
|
*/
|
|
string Network::routesTypeInfo =
|
|
"(rel (tuple ((Id int) (Length real) (Curve sline) "
|
|
"(Dual bool) (StartsSmaller bool))))";
|
|
string Network::routesBTreeTypeInfo =
|
|
"(btree (tuple ((Id int) (Length real) (Curve sline) "
|
|
"(Dual bool) (StartsSmaller bool))) int)";
|
|
|
|
string Network::routesRTreeTypeInfo =
|
|
"(rtree (tuple((Id int)(Length real)(Curve sline)(Dual bool)"
|
|
"(StartsSmaller bool))) sline FALSE)";
|
|
|
|
string Network::junctionsTypeInfo =
|
|
"(rel (tuple ((R1id int) (Meas1 real) (R2id int) "
|
|
"(Meas2 real) (Cc int))))";
|
|
|
|
/*string Network::junctionsInternalTypeInfo =
|
|
"(rel (tuple ((r1id int) (meas1 real) (r2id int) "
|
|
"(meas2 real) (cc int) (pos point) (r1rc tid) (r2rc tid) "
|
|
"(sauprc tid) (sadownrc tid)(sbuprc tid) (sbdownrc tid))))";*/
|
|
string Network::junctionsInternalTypeInfo =
|
|
"(rel (tuple ((R1id int) (Meas1 real) (R2id int) "
|
|
"(Meas2 real) (Cc int) (Loc point) (R1rc tid) (R2rc tid) "
|
|
"(Sauprc tid) (Sadownrc tid)(Sbuprc tid) (Sbdownrc tid))))";
|
|
|
|
|
|
string Network::junctionsBTreeTypeInfo =
|
|
"(btree (tuple ((R1id int) (Meas1 real) (R2id int) "
|
|
"(Meas2 real) (Cc int) (Loc point) (R1rc tid) (R2rc tid) "
|
|
"(Sauprc tid) (Sadownrc tid)(Sbuprc tid) (Sbdownrc tid))) int)";
|
|
string Network::sectionsInternalTypeInfo =
|
|
"(rel (tuple ((Rid int) (Meas1 real) (Meas2 real) (Dual bool)"
|
|
"(Curve sline)(CurveStartsSmaller bool) (Rrc tid) (Sid int))))";
|
|
string Network::sectionsBTreeTypeInfo =
|
|
"(btree (tuple ((Rid int) (Meas1 real) (Meas2 real) (Dual bool)"
|
|
"(Curve sline)(CurveStartsSmaller bool) (Rrc tid) (Sid int))) int)";
|
|
string Network::distancestorageTypeInfo =
|
|
"(rel (tuple((J1 tid)(J2 tid)(Dist real)(Sp gline))))";
|
|
|
|
/*
|
|
2.1.3 Constructors and destructors class ~Network~
|
|
|
|
*/
|
|
|
|
Network::Network() :
|
|
m_iId ( 0 ),
|
|
m_scalefactor(1.0),
|
|
m_bDefined ( false ),
|
|
m_pRoutes ( 0 ),
|
|
m_pJunctions ( 0 ),
|
|
m_pSections ( 0 ),
|
|
m_pBTreeRoutes ( 0 ),
|
|
m_pRTreeRoutes ( 0 ),
|
|
m_pBTreeJunctionsByRoute1 ( 0 ),
|
|
m_pBTreeJunctionsByRoute2 ( 0 ),
|
|
m_xAdjacencyList ( 0 ),
|
|
m_xSubAdjacencyList ( 0 ),
|
|
m_reverseAdjacencyList(0),
|
|
m_reverseSubAdjancencyList(0),
|
|
m_pBTreeSectionsByRoute ( 0 )
|
|
/*alldistance(0)*/ //only for experimental use with network distances
|
|
{
|
|
}
|
|
|
|
Network::Network ( SmiRecord& in_xValueRecord,
|
|
size_t& inout_iOffset,
|
|
const ListExpr in_xTypeInfo ):
|
|
m_xAdjacencyList(0),
|
|
m_xSubAdjacencyList(0),
|
|
m_reverseAdjacencyList(0),
|
|
m_reverseSubAdjancencyList(0)
|
|
{
|
|
|
|
// Read network id
|
|
in_xValueRecord.Read ( &m_iId, sizeof ( int ), inout_iOffset );
|
|
inout_iOffset += sizeof ( int );
|
|
|
|
in_xValueRecord.Read ( &m_scalefactor, sizeof ( double ), inout_iOffset );
|
|
inout_iOffset += sizeof ( double );
|
|
// Open routes
|
|
ListExpr xType;
|
|
nl->ReadFromString ( routesTypeInfo, xType );
|
|
ListExpr xNumericType = SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
m_pRoutes = Relation::Open ( in_xValueRecord,
|
|
inout_iOffset,
|
|
xNumericType );
|
|
if ( !m_pRoutes )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Open junctions
|
|
nl->ReadFromString ( junctionsInternalTypeInfo, xType );
|
|
xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
m_pJunctions = Relation::Open ( in_xValueRecord,
|
|
inout_iOffset,
|
|
xNumericType );
|
|
if ( !m_pJunctions )
|
|
{
|
|
m_pRoutes->Delete();
|
|
return;
|
|
}
|
|
|
|
// Open sections
|
|
nl->ReadFromString ( sectionsInternalTypeInfo, xType );
|
|
xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
m_pSections = Relation::Open ( in_xValueRecord,
|
|
inout_iOffset,
|
|
xNumericType );
|
|
if ( !m_pSections )
|
|
{
|
|
m_pRoutes->Delete();
|
|
m_pJunctions->Delete();
|
|
return;
|
|
}
|
|
|
|
// Open btree for routes
|
|
nl->ReadFromString ( routesBTreeTypeInfo, xType );
|
|
xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
m_pBTreeRoutes = BTree::Open ( in_xValueRecord,
|
|
inout_iOffset,
|
|
xNumericType );
|
|
|
|
if ( !m_pBTreeRoutes )
|
|
{
|
|
m_pRoutes->Delete();
|
|
m_pJunctions->Delete();
|
|
m_pSections->Delete();
|
|
return;
|
|
}
|
|
//Open rtree for routes
|
|
Word xValue;
|
|
|
|
if ( ! ( m_pRTreeRoutes->Open ( in_xValueRecord,
|
|
inout_iOffset,
|
|
routesRTreeTypeInfo,
|
|
xValue ) ) )
|
|
{
|
|
m_pRoutes->Delete();
|
|
m_pJunctions->Delete();
|
|
m_pSections->Delete();
|
|
delete m_pBTreeRoutes;
|
|
return;
|
|
}
|
|
|
|
m_pRTreeRoutes = ( R_Tree<2,TupleId>* ) xValue.addr;
|
|
|
|
// Open first btree for junctions
|
|
nl->ReadFromString ( junctionsBTreeTypeInfo, xType );
|
|
xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
m_pBTreeJunctionsByRoute1 = BTree::Open ( in_xValueRecord,
|
|
inout_iOffset,
|
|
xNumericType );
|
|
if ( !m_pBTreeJunctionsByRoute1 )
|
|
{
|
|
m_pRoutes->Delete();
|
|
m_pJunctions->Delete();
|
|
m_pSections->Delete();
|
|
delete m_pBTreeRoutes;
|
|
delete m_pRTreeRoutes;
|
|
return;
|
|
}
|
|
|
|
// Open second btree for junctions
|
|
nl->ReadFromString ( junctionsBTreeTypeInfo, xType );
|
|
xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
m_pBTreeJunctionsByRoute2 = BTree::Open ( in_xValueRecord,
|
|
inout_iOffset,
|
|
xNumericType );
|
|
if ( !m_pBTreeJunctionsByRoute2 )
|
|
{
|
|
m_pRoutes->Delete();
|
|
m_pJunctions->Delete();
|
|
m_pSections->Delete();
|
|
delete m_pBTreeRoutes;
|
|
delete m_pRTreeRoutes;
|
|
delete m_pBTreeJunctionsByRoute1;
|
|
return;
|
|
}
|
|
|
|
size_t bufsize = sizeof(FlobId) + sizeof(SmiSize) + 2*sizeof(SmiSize);
|
|
SmiSize offset = 0;
|
|
char* buf = (char*) malloc(bufsize);
|
|
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
|
inout_iOffset += bufsize;
|
|
assert(buf != NULL);
|
|
m_xAdjacencyList.restoreHeader(buf,offset);
|
|
free(buf);
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
|
assert(buf != NULL);
|
|
m_xSubAdjacencyList.restoreHeader(buf,offset);
|
|
inout_iOffset += bufsize;
|
|
free(buf);
|
|
|
|
// The same for reverse adjacency lists.
|
|
bufsize = sizeof(FlobId) + sizeof(SmiSize) + 2*sizeof(SmiSize);
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
|
inout_iOffset += bufsize;
|
|
assert(buf != NULL);
|
|
m_reverseAdjacencyList.restoreHeader(buf,offset);
|
|
free(buf);
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
|
assert(buf != NULL);
|
|
m_reverseSubAdjancencyList.restoreHeader(buf,offset);
|
|
inout_iOffset += bufsize;
|
|
free(buf);
|
|
// Open btree for sections
|
|
nl->ReadFromString ( sectionsBTreeTypeInfo, xType );
|
|
xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
m_pBTreeSectionsByRoute = BTree::Open ( in_xValueRecord,
|
|
inout_iOffset,
|
|
xNumericType );
|
|
if ( !m_pBTreeSectionsByRoute )
|
|
{
|
|
m_pRoutes->Delete();
|
|
m_pJunctions->Delete();
|
|
m_pSections->Delete();
|
|
delete m_pBTreeRoutes;
|
|
delete m_pRTreeRoutes;
|
|
delete m_pBTreeJunctionsByRoute1;
|
|
delete m_pBTreeJunctionsByRoute2;
|
|
return;
|
|
}
|
|
|
|
//Open distance storage
|
|
/*
|
|
nl->ReadFromString(distancestorageTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
alldistance = Relation::Open(in_xValueRecord,inout_iOffset,xNumericType);
|
|
|
|
if(!alldistance){
|
|
m_pRoutes->Delete();
|
|
m_pJunctions->Delete();
|
|
m_pSections->Delete();
|
|
delete m_pBTreeRoutes;
|
|
delete m_pRTreeRoutes;
|
|
delete m_pBTreeJunctionsByRoute1;
|
|
delete m_pBTreeJunctionsByRoute2;
|
|
return;
|
|
}
|
|
*/
|
|
m_bDefined = true;
|
|
}
|
|
|
|
Network::Network ( ListExpr in_xValue,
|
|
int in_iErrorPos,
|
|
ListExpr& inout_xErrorInfo,
|
|
bool& inout_bCorrect ) :
|
|
m_iId ( 0 ),
|
|
m_scalefactor(1.0),
|
|
m_bDefined ( false ),
|
|
m_pRoutes ( 0 ),
|
|
m_pJunctions ( 0 ),
|
|
m_pSections ( 0 ),
|
|
m_pBTreeRoutes ( 0 ),
|
|
m_pRTreeRoutes ( 0 ),
|
|
m_pBTreeJunctionsByRoute1 ( 0 ),
|
|
m_pBTreeJunctionsByRoute2 ( 0 ),
|
|
m_xAdjacencyList ( 0 ),
|
|
m_xSubAdjacencyList ( 0 ),
|
|
m_reverseAdjacencyList(0),
|
|
m_reverseSubAdjancencyList(0),
|
|
m_pBTreeSectionsByRoute ( 0 )
|
|
/*alldistance(0)*/
|
|
{
|
|
|
|
// Check the list
|
|
if ( ! ( nl->ListLength ( in_xValue ) == 4 ) )
|
|
{
|
|
string strErrorMessage = "Network(): List length must be 4.";
|
|
inout_xErrorInfo =
|
|
nl->Append ( inout_xErrorInfo, nl->StringAtom ( strErrorMessage ) );
|
|
inout_bCorrect = false;
|
|
return;
|
|
}
|
|
|
|
// Get type-info for temporary table
|
|
ListExpr xType;
|
|
nl->ReadFromString ( routesTypeInfo, xType );
|
|
ListExpr xRoutesNumType = SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
nl->ReadFromString ( junctionsTypeInfo, xType );
|
|
ListExpr xJunctionsNumType = SecondoSystem::GetCatalog()->NumericType ( xType
|
|
);
|
|
|
|
// Split into the three parts
|
|
ListExpr xIdList = nl->First ( in_xValue );
|
|
ListExpr xScalList = nl->Second(in_xValue);
|
|
ListExpr xRouteList = nl->Third ( in_xValue );
|
|
ListExpr xJunctionList = nl->Fourth ( in_xValue );
|
|
// Sections will be calculated in the load-method
|
|
|
|
// Read Id
|
|
if ( !nl->IsAtom ( xIdList ) ||
|
|
nl->AtomType ( xIdList ) != IntType )
|
|
{
|
|
string strErrorMessage = "Network(): Id is missing.";
|
|
inout_xErrorInfo = nl->Append ( inout_xErrorInfo,
|
|
nl->StringAtom ( strErrorMessage ) );
|
|
inout_bCorrect = false;
|
|
return;
|
|
}
|
|
m_iId = nl->IntValue ( xIdList );
|
|
|
|
// Read Scalefactor
|
|
if ( !nl->IsAtom ( xScalList ) ||
|
|
nl->AtomType ( xScalList ) != RealType )
|
|
{
|
|
string strErrorMessage = "Network(): Scalefactor is missing.";
|
|
inout_xErrorInfo = nl->Append ( inout_xErrorInfo,
|
|
nl->StringAtom ( strErrorMessage ) );
|
|
inout_bCorrect = false;
|
|
return;
|
|
}
|
|
m_scalefactor = nl->RealValue ( xScalList );
|
|
|
|
// Create new temporary relations.
|
|
Relation* pRoutes = new Relation ( xRoutesNumType, false );
|
|
Relation* pJunctions = new Relation ( xJunctionsNumType, false );
|
|
|
|
// Iterate over all routes
|
|
while ( !nl->IsEmpty ( xRouteList ) )
|
|
{
|
|
ListExpr xCurrentRoute = nl->First ( xRouteList );
|
|
xRouteList = nl->Rest ( xRouteList );
|
|
|
|
// Create tuple for internal table
|
|
Tuple* pNewRoute = new Tuple ( nl->Second ( xRoutesNumType ) );
|
|
|
|
// Check this part of the list
|
|
if ( nl->ListLength ( xCurrentRoute ) != 5 ||
|
|
( !nl->IsAtom ( nl->First ( xCurrentRoute ) ) ) ||
|
|
nl->AtomType ( nl->First ( xCurrentRoute ) ) != IntType ||
|
|
( !nl->IsAtom ( nl->Second ( xCurrentRoute ) ) ) ||
|
|
nl->AtomType ( nl->Second ( xCurrentRoute ) ) != RealType ||
|
|
( nl->IsAtom ( nl->Third ( xCurrentRoute ) ) ) ||
|
|
( !nl->IsAtom ( nl->Fourth ( xCurrentRoute ) ) ) ||
|
|
nl->AtomType ( nl->Fourth ( xCurrentRoute ) ) != BoolType ||
|
|
( !nl->IsAtom ( nl->Fifth ( xCurrentRoute ) ) ) ||
|
|
nl->AtomType ( nl->Fifth ( xCurrentRoute ) ) != BoolType )
|
|
{
|
|
delete pRoutes;
|
|
delete pRoutes;
|
|
|
|
string strErrorMessage = "Network(): Error while reading out routes.";
|
|
inout_xErrorInfo = nl->Append ( inout_xErrorInfo,
|
|
nl->StringAtom ( strErrorMessage ) );
|
|
inout_bCorrect = false;
|
|
return;
|
|
}
|
|
|
|
// Read attributes from list
|
|
// Read values from table
|
|
int iRouteId = nl->IntValue ( nl->First ( xCurrentRoute ) );
|
|
double dLength = nl->RealValue ( nl->Second ( xCurrentRoute ) );
|
|
Word xLineWord = InSimpleLine ( nl->TheEmptyList(),
|
|
nl->Third ( xCurrentRoute ),
|
|
in_iErrorPos,
|
|
inout_xErrorInfo,
|
|
inout_bCorrect );
|
|
SimpleLine* pLine = ( SimpleLine* ) ( xLineWord.addr );
|
|
bool bDual= nl->BoolValue ( nl->Fourth ( xCurrentRoute ) );
|
|
bool bStartsSmaller = nl->BoolValue ( nl->Fifth ( xCurrentRoute ) );
|
|
|
|
// Set all necessary attributes
|
|
pNewRoute->PutAttribute ( ROUTE_ID, new CcInt ( true, iRouteId ) );
|
|
pNewRoute->PutAttribute ( ROUTE_LENGTH, new CcReal ( true, dLength ) );
|
|
pNewRoute->PutAttribute ( ROUTE_CURVE, pLine );
|
|
pNewRoute->PutAttribute ( ROUTE_DUAL, new CcBool ( true, bDual ) );
|
|
pNewRoute->PutAttribute ( ROUTE_STARTSSMALLER, new CcBool ( true,
|
|
bStartsSmaller ) );
|
|
|
|
// Append new junction
|
|
pRoutes->AppendTuple ( pNewRoute );
|
|
if ( pNewRoute )
|
|
{
|
|
pNewRoute->DeleteIfAllowed();
|
|
pNewRoute=0;
|
|
}
|
|
}
|
|
|
|
// Iterate over all junctions
|
|
while ( !nl->IsEmpty ( xJunctionList ) )
|
|
{
|
|
ListExpr xCurrentJunction = nl->First ( xJunctionList );
|
|
xJunctionList = nl->Rest ( xJunctionList );
|
|
|
|
// Create tuple for internal table
|
|
Tuple* pNewJunction = new Tuple ( nl->Second ( xJunctionsNumType ) );
|
|
|
|
// Check this part of the list
|
|
if ( nl->ListLength ( xCurrentJunction ) != 6 ||
|
|
( !nl->IsAtom ( nl->First ( xCurrentJunction ) ) ) ||
|
|
nl->AtomType ( nl->First ( xCurrentJunction ) ) != IntType ||
|
|
( !nl->IsAtom ( nl->Second ( xCurrentJunction ) ) ) ||
|
|
nl->AtomType ( nl->Second ( xCurrentJunction ) ) != RealType ||
|
|
( !nl->IsAtom ( nl->Third ( xCurrentJunction ) ) ) ||
|
|
nl->AtomType ( nl->Third ( xCurrentJunction ) ) != IntType ||
|
|
( !nl->IsAtom ( nl->Fourth ( xCurrentJunction ) ) ) ||
|
|
nl->AtomType ( nl->Fourth ( xCurrentJunction ) ) != RealType ||
|
|
( !nl->IsAtom ( nl->Fifth ( xCurrentJunction ) ) ) ||
|
|
nl->AtomType ( nl->Fifth ( xCurrentJunction ) ) != IntType )
|
|
{
|
|
delete pRoutes;
|
|
delete pJunctions;
|
|
|
|
string strErrorMessage = "Network(): Error while reading out junctions.";
|
|
inout_xErrorInfo = nl->Append ( inout_xErrorInfo,
|
|
nl->StringAtom ( strErrorMessage ) );
|
|
inout_bCorrect = false;
|
|
return;
|
|
}
|
|
|
|
// Read attributes from list
|
|
int iRoute1Id = nl->IntValue ( nl->First ( xCurrentJunction ) );
|
|
double dMeas1 = nl->RealValue ( nl->Second ( xCurrentJunction ) );
|
|
int iRoute2Id = nl->IntValue ( nl->Third ( xCurrentJunction ) );
|
|
double dMeas2 = nl->RealValue ( nl->Fourth ( xCurrentJunction ) );
|
|
int iConnectivityCode= nl->IntValue ( nl->Fifth ( xCurrentJunction ) );
|
|
// The location of the junction "Point" is calculated in the load-method
|
|
|
|
// Set all necessary attributes
|
|
pNewJunction->PutAttribute ( JUNCTION_ROUTE1_ID,
|
|
new CcInt ( true, iRoute1Id ) );
|
|
pNewJunction->PutAttribute ( JUNCTION_ROUTE1_MEAS,
|
|
new CcReal ( true, dMeas1 ) );
|
|
pNewJunction->PutAttribute ( JUNCTION_ROUTE2_ID,
|
|
new CcInt ( true, iRoute2Id ) );
|
|
pNewJunction->PutAttribute ( JUNCTION_ROUTE2_MEAS,
|
|
new CcReal ( true, dMeas2 ) );
|
|
pNewJunction->PutAttribute ( JUNCTION_CC,
|
|
new CcInt ( true, iConnectivityCode ) );
|
|
|
|
// Append new junction
|
|
pJunctions->AppendTuple ( pNewJunction );
|
|
if ( pNewJunction )
|
|
{
|
|
pNewJunction->DeleteIfAllowed();
|
|
pNewJunction=0;
|
|
}
|
|
}
|
|
|
|
Load ( m_iId,
|
|
m_scalefactor,
|
|
pRoutes,
|
|
pJunctions );
|
|
|
|
delete pRoutes;
|
|
delete pJunctions;
|
|
|
|
|
|
m_bDefined = true;
|
|
}
|
|
|
|
/*
|
|
Destructor
|
|
|
|
*/
|
|
Network::~Network()
|
|
{
|
|
delete m_pRoutes;
|
|
|
|
delete m_pJunctions;
|
|
|
|
delete m_pSections;
|
|
|
|
delete m_pBTreeRoutes;
|
|
|
|
delete m_pRTreeRoutes;
|
|
|
|
delete m_pBTreeJunctionsByRoute1;
|
|
|
|
delete m_pBTreeJunctionsByRoute2;
|
|
|
|
delete m_pBTreeSectionsByRoute;
|
|
|
|
// delete alldistance;
|
|
}
|
|
|
|
/*
|
|
1.3.1.3 Methods class ~network~
|
|
|
|
Destroy -- Removing a network from the database
|
|
|
|
*/
|
|
void Network::Destroy()
|
|
{
|
|
assert ( m_pRoutes != 0 );
|
|
m_pRoutes->Delete(); m_pRoutes = 0;
|
|
|
|
assert ( m_pJunctions != 0 );
|
|
m_pJunctions->Delete(); m_pJunctions = 0;
|
|
|
|
assert ( m_pSections != 0 );
|
|
m_pSections->Delete(); m_pSections = 0;
|
|
|
|
assert ( m_pBTreeRoutes != 0 );
|
|
m_pBTreeRoutes->DeleteFile();
|
|
delete m_pBTreeRoutes; m_pBTreeRoutes = 0;
|
|
|
|
assert ( m_pRTreeRoutes != 0 );
|
|
//m_pRTreeRoutes->DeleteFile();
|
|
delete m_pRTreeRoutes; m_pRTreeRoutes = 0;
|
|
|
|
m_pBTreeJunctionsByRoute1->DeleteFile();
|
|
delete m_pBTreeJunctionsByRoute1; m_pBTreeJunctionsByRoute1 = 0;
|
|
|
|
m_pBTreeJunctionsByRoute2->DeleteFile();
|
|
delete m_pBTreeJunctionsByRoute2; m_pBTreeJunctionsByRoute2 = 0;
|
|
|
|
// m_xAdjacencyList.Destroy();
|
|
// m_xSubAdjacencyList.Destroy();
|
|
// m_reverseAdjacencyList.Destroy();
|
|
// m_reverseSubAdjancencyList.Destroy();
|
|
assert ( m_pBTreeSectionsByRoute != 0 );
|
|
m_pBTreeSectionsByRoute->DeleteFile();
|
|
delete m_pBTreeSectionsByRoute;
|
|
m_pBTreeSectionsByRoute = 0;
|
|
/*
|
|
assert(alldistance != 0);
|
|
delete alldistance;
|
|
|
|
*/
|
|
}
|
|
|
|
/*
|
|
Load -- Create a network from two external relations
|
|
|
|
*/
|
|
|
|
void Network::Load ( int in_iId, double scale,
|
|
const Relation* in_pRoutes,
|
|
const Relation* in_pJunctions )
|
|
{
|
|
m_iId = in_iId;
|
|
m_scalefactor = scale;
|
|
FillRoutes ( in_pRoutes );
|
|
FillJunctions ( in_pJunctions );
|
|
FillSections();
|
|
FillAdjacencyLists();
|
|
//FillDistanceStorage();//store distance
|
|
m_bDefined = true;
|
|
}
|
|
|
|
/*
|
|
Fill routes relation of network
|
|
|
|
*/
|
|
void Network::FillRoutes ( const Relation *routes )
|
|
{
|
|
ListExpr ptrList = listutils::getPtrList(routes);
|
|
|
|
string strQuery = "(consume (sort (feed (" + routesTypeInfo +
|
|
" (ptr " + nl->ToString(ptrList) + ")))))";
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
|
|
assert ( QueryExecuted );
|
|
m_pRoutes = ( Relation * ) xResult.addr;
|
|
// Create B-Tree for the routes
|
|
ptrList = listutils::getPtrList(m_pRoutes);
|
|
|
|
strQuery = "(createbtree (" + routesTypeInfo +
|
|
" (ptr " + nl->ToString(ptrList) + "))" + " Id)";
|
|
QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
|
|
assert ( QueryExecuted ); // no query with side effects, please!
|
|
m_pBTreeRoutes = ( BTree* ) xResult.addr;
|
|
//Create R-Tree for the routes
|
|
|
|
strQuery = "(bulkloadrtree(sortby(addid(feed (" + routesTypeInfo +
|
|
" (ptr " + nl->ToString(ptrList) + "))))((Curve asc))) Curve)";
|
|
QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
|
|
assert ( QueryExecuted );
|
|
m_pRTreeRoutes = ( R_Tree<2,TupleId>* ) xResult.addr;
|
|
}
|
|
|
|
|
|
/*
|
|
Fill junctions relation of network
|
|
|
|
*/
|
|
void Network::FillJunctions ( const Relation *in_pJunctions )
|
|
{
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Create new table for the junctions
|
|
//
|
|
ListExpr xTypeInfo;
|
|
nl->ReadFromString ( junctionsInternalTypeInfo, xTypeInfo );
|
|
ListExpr xNumType = SecondoSystem::GetCatalog()->NumericType ( xTypeInfo );
|
|
Relation *pIntJunctions = new Relation ( xNumType, true );
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Iterator for the input-table with junctions
|
|
//
|
|
GenericRelationIterator* pJunctionsIter = in_pJunctions->MakeScan();
|
|
Tuple* pCurrentJunction;
|
|
while ( ( pCurrentJunction = pJunctionsIter->GetNextTuple() ) != 0 )
|
|
{
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Create tuple for internal table and copy all attributes from input
|
|
//
|
|
Tuple* pNewJunction = new Tuple ( nl->Second ( xNumType ) );
|
|
for ( int i = 0; i < pCurrentJunction->GetNoAttributes(); i++ )
|
|
{
|
|
pNewJunction->CopyAttribute ( i, pCurrentJunction, i );
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Fill other fields of the table
|
|
//
|
|
|
|
// Store Pointer to the first route in the new relation.
|
|
CcInt* pR1Id = ( CcInt* ) pCurrentJunction->GetAttribute (
|
|
JUNCTION_ROUTE1_ID );
|
|
BTreeIterator* pRoutesIter = m_pBTreeRoutes->ExactMatch ( pR1Id );
|
|
int NextIter = pRoutesIter->Next();
|
|
assert ( NextIter );
|
|
TupleIdentifier *pR1RC = new TupleIdentifier ( true, pRoutesIter->GetId() );
|
|
pNewJunction->PutAttribute ( JUNCTION_ROUTE1_RC, pR1RC );
|
|
|
|
// Calculate and store the exakt location of the junction.
|
|
Tuple* pRoute = m_pRoutes->GetTuple ( pRoutesIter->GetId(), false );
|
|
assert ( pRoute != 0 );
|
|
SimpleLine* pLine = ( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE );
|
|
assert ( pLine != 0 );
|
|
bool startSmaller =
|
|
((CcBool*)pRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
CcReal* pMeas = ( CcReal* ) pNewJunction->GetAttribute (
|
|
JUNCTION_ROUTE1_MEAS );
|
|
Point* pPoint = new Point ( true );
|
|
if(pLine->AtPosition ( pMeas->GetRealval(), startSmaller, *pPoint ))
|
|
pNewJunction->PutAttribute ( JUNCTION_POS, pPoint );
|
|
else {
|
|
if (AlmostEqualAbsolute(pMeas->GetRealval(), pLine->Length(),
|
|
m_scalefactor*0.01))
|
|
pLine->AtPosition(pLine->Length(), startSmaller, *pPoint);
|
|
else
|
|
if (AlmostEqualAbsolute(pMeas->GetRealval(), 0.0, m_scalefactor*0.01))
|
|
pLine->AtPosition(pLine->Length(), startSmaller, *pPoint);
|
|
pNewJunction->PutAttribute(JUNCTION_POS, pPoint);
|
|
}
|
|
|
|
pRoute->DeleteIfAllowed();
|
|
delete pRoutesIter;
|
|
|
|
// Store Pointer to the second route in the new relation.
|
|
CcInt* pR2Id = ( CcInt* ) pCurrentJunction->GetAttribute (
|
|
JUNCTION_ROUTE2_ID );
|
|
pRoutesIter = m_pBTreeRoutes->ExactMatch ( pR2Id );
|
|
NextIter = pRoutesIter->Next();
|
|
assert ( NextIter ); // no query with side effects, please!
|
|
TupleIdentifier *pR2RC = new TupleIdentifier ( true, pRoutesIter->GetId() );
|
|
pNewJunction->PutAttribute ( JUNCTION_ROUTE2_RC, pR2RC );
|
|
delete pRoutesIter;
|
|
|
|
// Pointers to sections are filled in FillSections
|
|
pNewJunction->PutAttribute ( JUNCTION_SECTION_AUP_RC,
|
|
new TupleIdentifier ( false,0 ) );
|
|
pNewJunction->PutAttribute ( JUNCTION_SECTION_ADOWN_RC,
|
|
new TupleIdentifier ( false,0 ) );
|
|
pNewJunction->PutAttribute ( JUNCTION_SECTION_BUP_RC,
|
|
new TupleIdentifier ( false,0 ) );
|
|
pNewJunction->PutAttribute ( JUNCTION_SECTION_BDOWN_RC,
|
|
new TupleIdentifier ( false,0 ) );
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Append new junction
|
|
//
|
|
pIntJunctions->AppendTuple ( pNewJunction );
|
|
|
|
pCurrentJunction->DeleteIfAllowed();
|
|
pNewJunction->DeleteIfAllowed();
|
|
}
|
|
delete pJunctionsIter;
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Sort the table which is now containing all junctions
|
|
//
|
|
ListExpr ptrList = listutils::getPtrList(pIntJunctions);
|
|
|
|
string strQuery = "(consume (sortby (feed (" + junctionsInternalTypeInfo +
|
|
" (ptr " + nl->ToString(ptrList) +
|
|
"))) ((R1id asc)(Meas1 asc)(R2id asc)(Meas2 asc))))";
|
|
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
|
|
assert ( QueryExecuted );
|
|
m_pJunctions = ( Relation * ) xResult.addr;
|
|
|
|
// Delete internal table
|
|
pIntJunctions->Delete();
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Create two b-trees for the junctions sorted by first and second id
|
|
//
|
|
|
|
ptrList = listutils::getPtrList(m_pJunctions);
|
|
|
|
strQuery = "(createbtree (" + junctionsInternalTypeInfo +
|
|
" (ptr " + nl->ToString(ptrList) + "))" + " R1id)";
|
|
QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
|
|
assert ( QueryExecuted );
|
|
m_pBTreeJunctionsByRoute1 = ( BTree* ) xResult.addr;
|
|
|
|
strQuery = "(createbtree (" + junctionsInternalTypeInfo +
|
|
" (ptr " + nl->ToString(ptrList) + "))" + " R2id)";
|
|
QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
|
|
assert ( QueryExecuted );
|
|
m_pBTreeJunctionsByRoute2 = ( BTree* ) xResult.addr;
|
|
}
|
|
|
|
/*
|
|
Fill routes relation of network
|
|
|
|
*/
|
|
void Network::FillSections()
|
|
{
|
|
// The method will iterate over routes
|
|
GenericRelationIterator* pRoutesIt = m_pRoutes->MakeScan();
|
|
|
|
// Create relation for sections
|
|
ListExpr xType;
|
|
nl->ReadFromString ( sectionsInternalTypeInfo, xType );
|
|
ListExpr xNumType = SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
m_pSections = new Relation ( xNumType );
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Iterate over all Routes
|
|
//
|
|
Tuple* pRoute = 0;
|
|
TupleId iSectionTid = 0;
|
|
vector<int> xIndices;
|
|
vector<Attribute*> xAttrs;
|
|
vector<JunctionTidSortEntry> xJunctions;
|
|
Tuple* actTuple = 0;
|
|
while ( ( pRoute = pRoutesIt->GetNextTuple() ) != 0 )
|
|
{
|
|
// Current position on route - starting at the beginning of the route
|
|
double dCurrentPosOnRoute = 0.0;
|
|
SimpleLine* pRouteCurve =
|
|
( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE);
|
|
bool cycle = pRouteCurve->IsCycle();
|
|
TupleId iTupleId = pRoute->GetTupleId();
|
|
CcInt* xRouteId = ( CcInt* ) pRoute->GetAttribute ( ROUTE_ID );
|
|
int iRouteId = xRouteId->GetIntval();
|
|
bool bDual = ((CcBool*) pRoute->GetAttribute(ROUTE_DUAL))->GetBoolval();
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// We need to find all junctions belonging to this route
|
|
//
|
|
xJunctions.clear();
|
|
GetTidJunctionsOnRoute ( xRouteId,
|
|
xJunctions );
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Now that we found all relevant junctions we can iterate over them.
|
|
//
|
|
JunctionTidSortEntry xCurrentEntry = xJunctions[0];
|
|
JunctionTidSortEntry xFirstCycleJunction = xJunctions[0];
|
|
bool curFirst = false;
|
|
TupleId startCycleSectionTid = iSectionTid+1;
|
|
for ( size_t i = 0; i < xJunctions.size(); i++ )
|
|
{
|
|
// Get next junction
|
|
xCurrentEntry = xJunctions[i];
|
|
if(actTuple) actTuple->DeleteIfAllowed();
|
|
actTuple = xCurrentEntry.GetTuple();
|
|
// Find values for the new section
|
|
double dStartPos = dCurrentPosOnRoute;
|
|
curFirst = xCurrentEntry.m_bFirstRoute;
|
|
double dEndPos = xCurrentEntry.GetRouteMeas();
|
|
xIndices.clear();
|
|
xAttrs.clear();
|
|
if (AlmostEqualAbsolute(pRouteCurve->Length(), dEndPos,
|
|
m_scalefactor*0.01))
|
|
{
|
|
if ( curFirst )
|
|
{
|
|
xIndices.push_back ( JUNCTION_SECTION_AUP_RC );
|
|
}
|
|
else
|
|
{
|
|
xIndices.push_back ( JUNCTION_SECTION_BUP_RC );
|
|
}
|
|
if (cycle &&
|
|
xCurrentEntry.GetRouteId() == xCurrentEntry.GetOtherRouteId())
|
|
xAttrs.push_back(new TupleIdentifier(true, startCycleSectionTid));
|
|
else
|
|
xAttrs.push_back ( new TupleIdentifier ( true, 0));
|
|
if (cycle)
|
|
{
|
|
xIndices.push_back(JUNCTION_CC);
|
|
if (xCurrentEntry.GetRouteId() == xCurrentEntry.GetOtherRouteId()){
|
|
xAttrs.push_back(new CcInt(true, 1285));
|
|
} else {
|
|
if (curFirst){
|
|
xAttrs.push_back(new CcInt(true, 4365));
|
|
} else {
|
|
xAttrs.push_back(new CcInt(true, 1860));
|
|
}
|
|
}
|
|
}
|
|
m_pJunctions->UpdateTuple ( actTuple, xIndices, xAttrs );
|
|
xIndices.clear();
|
|
xAttrs.clear();
|
|
if (actTuple) actTuple->DeleteIfAllowed();
|
|
actTuple = xCurrentEntry.GetTuple();
|
|
}
|
|
if ( curFirst)
|
|
{
|
|
xIndices.push_back ( JUNCTION_SECTION_ADOWN_RC );
|
|
}
|
|
else
|
|
{
|
|
xIndices.push_back ( JUNCTION_SECTION_BDOWN_RC );
|
|
}
|
|
if ( AlmostEqualAbsolute(dEndPos, 0.0, m_scalefactor*0.01))
|
|
{
|
|
// If the first junction is at the very start of the route, no
|
|
// section will be added
|
|
xAttrs.push_back ( new TupleIdentifier(true,0));
|
|
}
|
|
else
|
|
{
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Create a new section
|
|
//
|
|
// Section will only be created if the length is > 0. Otherwise the
|
|
// one before remains valid.
|
|
if ( !AlmostEqualAbsolute(dEndPos, dStartPos, m_scalefactor*0.01))
|
|
{
|
|
// A sline for the section
|
|
SimpleLine* pLine = new SimpleLine ( 0 );
|
|
|
|
// Take start from the route
|
|
bool bStartSmaller = ( ( CcBool* ) pRoute->GetAttribute (
|
|
ROUTE_STARTSSMALLER ) )->GetBoolval();
|
|
|
|
pRouteCurve->SubLine ( dStartPos,
|
|
dEndPos,
|
|
bStartSmaller,
|
|
*pLine );
|
|
|
|
// The new section
|
|
Tuple* pNewSection = new Tuple ( nl->Second ( xNumType ) );
|
|
pNewSection->PutAttribute ( SECTION_RID, new CcInt ( true,
|
|
iRouteId ) );
|
|
pNewSection->PutAttribute ( SECTION_DUAL, new CcBool ( true,
|
|
bDual ) );
|
|
pNewSection->PutAttribute ( SECTION_MEAS1, new CcReal ( true,
|
|
dStartPos) );
|
|
pNewSection->PutAttribute ( SECTION_MEAS2, new CcReal ( true,
|
|
dEndPos ));
|
|
pNewSection->PutAttribute ( SECTION_RRC, new TupleIdentifier ( true,
|
|
iTupleId ) );
|
|
pNewSection->PutAttribute ( SECTION_CURVE, pLine );
|
|
pNewSection->PutAttribute ( SECTION_CURVE_STARTS_SMALLER,
|
|
new CcBool ( true,
|
|
pLine->GetStartSmaller()));
|
|
pNewSection->PutAttribute ( SECTION_SID,
|
|
new CcInt ( true,
|
|
m_pSections->GetNoTuples()+1 ));
|
|
m_pSections->AppendTuple ( pNewSection );
|
|
iSectionTid++;
|
|
pNewSection->DeleteIfAllowed();
|
|
// Update position for next loop
|
|
dCurrentPosOnRoute = dEndPos;
|
|
}
|
|
xAttrs.push_back ( new TupleIdentifier ( true, iSectionTid ) );
|
|
}
|
|
if(actTuple) actTuple->DeleteIfAllowed();
|
|
actTuple = xCurrentEntry.GetTuple();
|
|
m_pJunctions->UpdateTuple ( actTuple, xIndices, xAttrs );
|
|
xIndices.clear();
|
|
xAttrs.clear();
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// The last section of the route is still missing, if the last
|
|
// junction is not at the end of the route.
|
|
//
|
|
if ( i == xJunctions.size()-1 &&
|
|
(!AlmostEqualAbsolute(pRouteCurve->Length(),
|
|
dCurrentPosOnRoute, m_scalefactor*0.01) ||
|
|
dCurrentPosOnRoute == 0.0 ))
|
|
{
|
|
// Find values for the new section
|
|
int iRouteId =
|
|
( ( CcInt* ) pRoute->GetAttribute ( ROUTE_ID ))->GetIntval();
|
|
bool bDual =
|
|
( ( CcBool* ) pRoute->GetAttribute ( ROUTE_DUAL ))->GetBoolval();
|
|
double dStartPos = dCurrentPosOnRoute;
|
|
double dEndPos = pRouteCurve->Length();
|
|
TupleId iTupleId = pRoute->GetTupleId();
|
|
|
|
// Calculate line
|
|
SimpleLine* pLine = new SimpleLine ( 0 );
|
|
bool bStartSmaller = ( ( CcBool* ) pRoute->GetAttribute (
|
|
ROUTE_STARTSSMALLER ) )->GetBoolval();
|
|
pRouteCurve->SubLine ( dStartPos,
|
|
dEndPos,
|
|
bStartSmaller,
|
|
*pLine );
|
|
|
|
// Create a new Section
|
|
Tuple* pNewSection = new Tuple ( nl->Second ( xNumType ) );
|
|
pNewSection->PutAttribute ( SECTION_RID, new CcInt ( true, iRouteId ) );
|
|
pNewSection->PutAttribute ( SECTION_DUAL, new CcBool ( true, bDual ) );
|
|
pNewSection->PutAttribute ( SECTION_MEAS1,new CcReal(true, dStartPos ));
|
|
pNewSection->PutAttribute ( SECTION_MEAS2, new CcReal(true,dEndPos ) );
|
|
pNewSection->PutAttribute ( SECTION_RRC,
|
|
new TupleIdentifier ( true, iTupleId ) );
|
|
pNewSection->PutAttribute ( SECTION_CURVE, pLine );
|
|
pNewSection->PutAttribute ( SECTION_CURVE_STARTS_SMALLER,
|
|
new CcBool(true, pLine->GetStartSmaller()));
|
|
pNewSection->PutAttribute ( SECTION_SID,
|
|
new CcInt( true, m_pSections->GetNoTuples() + 1 ) );
|
|
m_pSections->AppendTuple ( pNewSection );
|
|
iSectionTid++;
|
|
pNewSection->DeleteIfAllowed();
|
|
// Store ID of new section in Junction
|
|
if (curFirst)
|
|
{
|
|
xIndices.push_back ( JUNCTION_SECTION_AUP_RC );
|
|
}
|
|
else
|
|
{
|
|
xIndices.push_back ( JUNCTION_SECTION_BUP_RC );
|
|
}
|
|
xAttrs.push_back ( new TupleIdentifier ( true, iSectionTid ) );
|
|
if(actTuple) actTuple->DeleteIfAllowed();
|
|
actTuple = xCurrentEntry.GetTuple();
|
|
m_pJunctions->UpdateTuple ( actTuple,
|
|
xIndices,
|
|
xAttrs );
|
|
xIndices.clear();
|
|
xAttrs.clear();
|
|
} // end if
|
|
} //end junctionsloop
|
|
if (cycle)
|
|
{
|
|
xIndices.clear();
|
|
xAttrs.clear();
|
|
if(actTuple) actTuple->DeleteIfAllowed();
|
|
actTuple = xFirstCycleJunction.GetTuple();
|
|
if (xFirstCycleJunction.GetRouteId() ==
|
|
xFirstCycleJunction.GetOtherRouteId() &&
|
|
xFirstCycleJunction.GetRouteMeas() ==
|
|
xFirstCycleJunction.GetOtherRouteMeas() &&
|
|
xFirstCycleJunction.GetRouteMeas() == 0.0){
|
|
xIndices.push_back(JUNCTION_SECTION_BDOWN_RC);
|
|
xAttrs.push_back(new TupleIdentifier(true, iSectionTid));
|
|
xIndices.push_back(JUNCTION_SECTION_ADOWN_RC);
|
|
xAttrs.push_back(new TupleIdentifier(true, iSectionTid));
|
|
}
|
|
m_pJunctions->UpdateTuple(actTuple, xIndices, xAttrs);
|
|
xIndices.clear();
|
|
xAttrs.clear();
|
|
}
|
|
if(actTuple) actTuple->DeleteIfAllowed();
|
|
actTuple = 0;
|
|
// delete Tuples from xJunctions
|
|
xJunctions.clear();
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Fill Up-Pointers of all sections but the last
|
|
//
|
|
GetTidJunctionsOnRoute ( xRouteId,
|
|
xJunctions );
|
|
|
|
if (xJunctions.size()> 1)
|
|
{
|
|
TupleId iTid = xJunctions[xJunctions.size()-1].GetUpSectionId();
|
|
|
|
if ( xJunctions.size() > 2 )
|
|
{
|
|
bool done = false;
|
|
size_t i = xJunctions.size()-2;
|
|
while(!done)
|
|
{
|
|
// Get next junction
|
|
JunctionTidSortEntry xEntry = xJunctions[i];
|
|
JunctionTidSortEntry xEntryBehind = xJunctions[i + 1];
|
|
if(actTuple) actTuple->DeleteIfAllowed();
|
|
actTuple = xEntry.GetTuple();
|
|
if ( xEntry.m_bFirstRoute )
|
|
{
|
|
xIndices.push_back ( JUNCTION_SECTION_AUP_RC );
|
|
}
|
|
else
|
|
{
|
|
xIndices.push_back ( JUNCTION_SECTION_BUP_RC );
|
|
}
|
|
if ( AlmostEqualAbsolute(xEntryBehind.GetRouteMeas(),
|
|
xEntry.GetRouteMeas(), m_scalefactor*0.01))
|
|
{
|
|
// Two junctions at the same place. In this case they do have
|
|
// the same up-pointers
|
|
xAttrs.push_back ( new TupleIdentifier ( true, iTid ) );
|
|
}
|
|
else
|
|
{
|
|
// Junctions not on the same place. The down-pointer of the second
|
|
// is the up-pointer of the first.
|
|
iTid = xEntryBehind.GetDownSectionId();
|
|
xAttrs.push_back ( new TupleIdentifier ( true, iTid ) );
|
|
}
|
|
m_pJunctions->UpdateTuple ( actTuple,
|
|
xIndices,
|
|
xAttrs );
|
|
xIndices.clear();
|
|
xAttrs.clear();
|
|
if (i == 0) done = true;
|
|
else i--;
|
|
}
|
|
if(actTuple) actTuple->DeleteIfAllowed();
|
|
actTuple = 0;
|
|
}
|
|
else
|
|
{
|
|
if ( xJunctions.size() == 2 )
|
|
{
|
|
JunctionTidSortEntry xEntry = xJunctions[0];
|
|
JunctionTidSortEntry xEntryBehind = xJunctions[1];
|
|
if(actTuple) actTuple->DeleteIfAllowed();
|
|
actTuple = xEntry.GetTuple();
|
|
if ( xEntry.m_bFirstRoute )
|
|
{
|
|
xIndices.push_back ( JUNCTION_SECTION_AUP_RC );
|
|
}
|
|
else
|
|
{
|
|
xIndices.push_back ( JUNCTION_SECTION_BUP_RC );
|
|
}
|
|
if ( AlmostEqualAbsolute( xEntry.GetRouteMeas(),
|
|
xEntryBehind.GetRouteMeas(),
|
|
m_scalefactor*0.01))
|
|
{
|
|
xAttrs.push_back ( new TupleIdentifier ( true, iTid ) );
|
|
}
|
|
else
|
|
{
|
|
iTid = xEntryBehind.GetDownSectionId();
|
|
xAttrs.push_back ( new TupleIdentifier ( true, iTid ) );
|
|
}
|
|
m_pJunctions->UpdateTuple ( actTuple,
|
|
xIndices,
|
|
xAttrs );
|
|
xIndices.clear();
|
|
xAttrs.clear();
|
|
if(actTuple) actTuple->DeleteIfAllowed();
|
|
actTuple = 0;
|
|
}
|
|
}
|
|
}
|
|
// delete Tuples from xJunctions
|
|
xJunctions.clear();
|
|
if (actTuple) actTuple->DeleteIfAllowed();
|
|
actTuple = 0;
|
|
pRoute->DeleteIfAllowed();
|
|
} // End while Routes
|
|
delete pRoutesIt;
|
|
// Create B-Tree for the sections
|
|
ListExpr ptrList = listutils::getPtrList(m_pSections);
|
|
string strQuery = "(createbtree (" + sectionsInternalTypeInfo +
|
|
" (ptr " + nl->ToString(ptrList) + "))" + " Rid)";
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
|
|
assert ( QueryExecuted );
|
|
m_pBTreeSectionsByRoute = ( BTree* ) xResult.addr;
|
|
}
|
|
|
|
/*
|
|
Fill adjacency list of network
|
|
|
|
*/
|
|
void Network::FillAdjacencyLists()
|
|
{
|
|
// Adjust the adjacenzy list to the correct size. From each
|
|
// section four directions are possible - including u-turns
|
|
m_xAdjacencyList.resize ( m_pSections->GetNoTuples() * 2 );
|
|
m_reverseAdjacencyList.resize(m_pSections->GetNoTuples()*2);
|
|
for ( int i = 0; i < m_pSections->GetNoTuples() * 2; i++ )
|
|
{
|
|
m_xAdjacencyList.Put ( i, AdjacencyListEntry ( -1, -1 ) );
|
|
m_reverseAdjacencyList.Put(i, AdjacencyListEntry(-1,-1));
|
|
}
|
|
|
|
GenericRelationIterator* pJunctionsIt = m_pJunctions->MakeScan();
|
|
Tuple* pCurrentJunction;
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// In a first step all pairs of adjacent sections will be collected
|
|
//
|
|
vector<DirectedSectionPair> xList;
|
|
vector<DirectedSectionPair> xReverseList;
|
|
|
|
while ( ( pCurrentJunction = pJunctionsIt->GetNextTuple() ) != 0 )
|
|
{
|
|
//////////////////////////////////
|
|
//
|
|
// Retrieve the connectivity code
|
|
//
|
|
int iCc =
|
|
((CcInt*) pCurrentJunction->GetAttribute ( JUNCTION_CC ))->GetIntval();
|
|
ConnectivityCode xCc ( iCc );
|
|
|
|
//////////////////////////////////
|
|
//
|
|
// Retrieve the four sections - if they exist
|
|
//
|
|
// (This should also be possible without loading the Section itself)
|
|
//
|
|
|
|
TupleId tidpAUp, tidpADown, tidpBUp, tidpBDown;
|
|
|
|
tidpAUp = ( ( TupleIdentifier* )
|
|
pCurrentJunction->GetAttribute ( JUNCTION_SECTION_AUP_RC ))->GetTid();
|
|
tidpADown = ( ( TupleIdentifier* )
|
|
pCurrentJunction->GetAttribute ( JUNCTION_SECTION_ADOWN_RC ))->GetTid();
|
|
tidpBUp = ( ( TupleIdentifier* )
|
|
pCurrentJunction->GetAttribute ( JUNCTION_SECTION_BUP_RC ))->GetTid();
|
|
tidpBDown = ( ( TupleIdentifier* )
|
|
pCurrentJunction->GetAttribute ( JUNCTION_SECTION_BDOWN_RC ))->GetTid();
|
|
|
|
//////////////////////////////////
|
|
//
|
|
// If a section is existing and the transition is possible
|
|
// it will be added to the adjacency list.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Implementationversion
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FillAdjacencyPair ( tidpAUp, false, tidpAUp, true, xCc, AUP_AUP, xList );
|
|
// FillAdjacencyPair ( tidpAUp, false, tidpADown, false, xCc, AUP_ADOWN,
|
|
// xList);
|
|
// FillAdjacencyPair ( tidpAUp, false, tidpBUp, true, xCc, AUP_BUP, xList );
|
|
// FillAdjacencyPair ( tidpAUp, false, tidpBDown, false, xCc, AUP_BDOWN,
|
|
// xList);
|
|
//
|
|
// FillAdjacencyPair ( tidpADown, true, tidpAUp, true, xCc, ADOWN_AUP, xList );
|
|
// FillAdjacencyPair ( tidpADown, true, tidpADown, false, xCc, ADOWN_ADOWN,
|
|
// xList);
|
|
// FillAdjacencyPair ( tidpADown, true, tidpBUp, true, xCc, ADOWN_BUP, xList );
|
|
// FillAdjacencyPair ( tidpADown, true, tidpBDown, false, xCc, ADOWN_BDOWN,
|
|
// xList);
|
|
//
|
|
// FillAdjacencyPair ( tidpBUp, false, tidpAUp, true, xCc, BUP_AUP, xList );
|
|
// FillAdjacencyPair ( tidpBUp, false, tidpADown, false, xCc, BUP_ADOWN,
|
|
// xList);
|
|
// FillAdjacencyPair ( tidpBUp, false, tidpBUp, true, xCc, BUP_BUP, xList );
|
|
// FillAdjacencyPair ( tidpBUp, false, tidpBDown, false, xCc, BUP_BDOWN,
|
|
// xList);
|
|
//
|
|
// FillAdjacencyPair ( tidpBDown, true, tidpAUp, true, xCc, BDOWN_AUP, xList );
|
|
// FillAdjacencyPair ( tidpBDown, true, tidpADown, false, xCc,BDOWN_ADOWN,
|
|
// xList);
|
|
// FillAdjacencyPair ( tidpBDown, true, tidpBUp, true, xCc, BDOWN_BUP, xList );
|
|
// FillAdjacencyPair ( tidpBDown, true, tidpBDown, false, xCc, BDOWN_BDOWN,
|
|
// xList);
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Paperversion
|
|
///////////////////
|
|
FillAdjacencyPair ( tidpAUp, false, tidpAUp, true, xCc, ADOWN_AUP, xList );
|
|
FillAdjacencyPair ( tidpAUp, false, tidpADown, false, xCc, ADOWN_ADOWN,
|
|
xList);
|
|
FillAdjacencyPair ( tidpAUp, false, tidpBUp, true, xCc, ADOWN_BUP, xList );
|
|
FillAdjacencyPair ( tidpAUp, false, tidpBDown, false, xCc, ADOWN_BDOWN,
|
|
xList);
|
|
|
|
FillAdjacencyPair ( tidpADown, true, tidpAUp, true, xCc, AUP_AUP, xList );
|
|
FillAdjacencyPair ( tidpADown, true, tidpADown, false, xCc, AUP_ADOWN,
|
|
xList);
|
|
FillAdjacencyPair ( tidpADown, true, tidpBUp, true, xCc, AUP_BUP, xList );
|
|
FillAdjacencyPair ( tidpADown, true, tidpBDown, false, xCc, AUP_BDOWN,
|
|
xList);
|
|
|
|
FillAdjacencyPair ( tidpBUp, false, tidpAUp, true, xCc, BDOWN_AUP, xList );
|
|
FillAdjacencyPair ( tidpBUp, false, tidpADown, false, xCc, BDOWN_ADOWN,
|
|
xList);
|
|
FillAdjacencyPair ( tidpBUp, false, tidpBUp, true, xCc, BDOWN_BUP, xList );
|
|
FillAdjacencyPair ( tidpBUp, false, tidpBDown, false, xCc, BDOWN_BDOWN,
|
|
xList);
|
|
|
|
FillAdjacencyPair ( tidpBDown, true, tidpAUp, true, xCc, BUP_AUP, xList );
|
|
FillAdjacencyPair ( tidpBDown, true, tidpADown, false, xCc,BUP_ADOWN,
|
|
xList);
|
|
FillAdjacencyPair ( tidpBDown, true, tidpBUp, true, xCc, BUP_BUP, xList );
|
|
FillAdjacencyPair ( tidpBDown, true, tidpBDown, false, xCc, BUP_BDOWN,
|
|
xList);
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// And the reverse adjacency list.
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Implementationversion
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// FillReverseAdjacencyPair ( tidpAUp, false, tidpAUp, true, xCc, AUP_AUP,
|
|
// xReverseList );
|
|
// FillReverseAdjacencyPair ( tidpAUp, false, tidpADown, false, xCc, AUP_ADOWN,
|
|
// xReverseList);
|
|
// FillReverseAdjacencyPair ( tidpAUp, false, tidpBUp, true, xCc, AUP_BUP,
|
|
// xReverseList );
|
|
// FillReverseAdjacencyPair ( tidpAUp, false, tidpBDown, false, xCc, AUP_BDOWN,
|
|
// xReverseList);
|
|
//
|
|
// FillReverseAdjacencyPair ( tidpADown, true, tidpAUp, true, xCc, ADOWN_AUP,
|
|
// xReverseList );
|
|
// FillReverseAdjacencyPair ( tidpADown, true, tidpADown, false, xCc,
|
|
// ADOWN_ADOWN, xReverseList);
|
|
// FillReverseAdjacencyPair ( tidpADown, true, tidpBUp, true, xCc, ADOWN_BUP,
|
|
// xReverseList );
|
|
// FillReverseAdjacencyPair ( tidpADown, true, tidpBDown, false, xCc,
|
|
// ADOWN_BDOWN, xReverseList);
|
|
//
|
|
// FillReverseAdjacencyPair ( tidpBUp, false, tidpAUp, true, xCc, BUP_AUP,
|
|
// xReverseList );
|
|
// FillReverseAdjacencyPair ( tidpBUp, false, tidpADown, false, xCc, BUP_ADOWN,
|
|
// xReverseList);
|
|
// FillReverseAdjacencyPair ( tidpBUp, false, tidpBUp, true, xCc, BUP_BUP,
|
|
// xReverseList );
|
|
// FillReverseAdjacencyPair ( tidpBUp, false, tidpBDown, false, xCc, BUP_BDOWN,
|
|
// xReverseList);
|
|
//
|
|
// FillReverseAdjacencyPair ( tidpBDown, true, tidpAUp, true, xCc, BDOWN_AUP,
|
|
// xReverseList );
|
|
// FillReverseAdjacencyPair ( tidpBDown, true, tidpADown, false, xCc,
|
|
// BDOWN_ADOWN, xReverseList);
|
|
// FillReverseAdjacencyPair ( tidpBDown, true, tidpBUp, true, xCc, BDOWN_BUP,
|
|
// xReverseList );
|
|
// FillReverseAdjacencyPair ( tidpBDown, true, tidpBDown, false, xCc,
|
|
// BDOWN_BDOWN, xReverseList);
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Paperversion
|
|
////////////////////////////////
|
|
FillReverseAdjacencyPair ( tidpAUp, false, tidpAUp, true, xCc, ADOWN_AUP,
|
|
xReverseList );
|
|
FillReverseAdjacencyPair ( tidpAUp, false, tidpADown, false, xCc, ADOWN_ADOWN,
|
|
xReverseList);
|
|
FillReverseAdjacencyPair ( tidpAUp, false, tidpBUp, true, xCc, ADOWN_BUP,
|
|
xReverseList );
|
|
FillReverseAdjacencyPair ( tidpAUp, false, tidpBDown, false, xCc, ADOWN_BDOWN,
|
|
xReverseList);
|
|
|
|
FillReverseAdjacencyPair ( tidpADown, true, tidpAUp, true, xCc, AUP_AUP,
|
|
xReverseList );
|
|
FillReverseAdjacencyPair ( tidpADown, true, tidpADown, false, xCc,
|
|
AUP_ADOWN, xReverseList);
|
|
FillReverseAdjacencyPair ( tidpADown, true, tidpBUp, true, xCc, AUP_BUP,
|
|
xReverseList );
|
|
FillReverseAdjacencyPair ( tidpADown, true, tidpBDown, false, xCc,
|
|
AUP_BDOWN, xReverseList);
|
|
|
|
FillReverseAdjacencyPair ( tidpBUp, false, tidpAUp, true, xCc, BDOWN_AUP,
|
|
xReverseList );
|
|
FillReverseAdjacencyPair ( tidpBUp, false, tidpADown, false, xCc, BDOWN_ADOWN,
|
|
xReverseList);
|
|
FillReverseAdjacencyPair ( tidpBUp, false, tidpBUp, true, xCc, BDOWN_BUP,
|
|
xReverseList );
|
|
FillReverseAdjacencyPair ( tidpBUp, false, tidpBDown, false, xCc, BDOWN_BDOWN,
|
|
xReverseList);
|
|
|
|
FillReverseAdjacencyPair ( tidpBDown, true, tidpAUp, true, xCc, BUP_AUP,
|
|
xReverseList );
|
|
FillReverseAdjacencyPair ( tidpBDown, true, tidpADown, false, xCc,
|
|
BUP_ADOWN, xReverseList);
|
|
FillReverseAdjacencyPair ( tidpBDown, true, tidpBUp, true, xCc, BUP_BUP,
|
|
xReverseList );
|
|
FillReverseAdjacencyPair ( tidpBDown, true, tidpBDown, false, xCc,
|
|
BUP_BDOWN, xReverseList);
|
|
|
|
|
|
pCurrentJunction->DeleteIfAllowed();
|
|
}
|
|
delete pJunctionsIt;
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Now - as the second step the adjacency lists are filled.
|
|
//
|
|
// Sort the lists by the first directed section
|
|
|
|
stable_sort ( xList.begin(), xList.end() );
|
|
|
|
DirectedSectionPair xLastPair;
|
|
int iLow = 0;
|
|
int iHigh = 0;
|
|
int iIndex = 0;
|
|
for ( size_t i = 0; i < xList.size(); i++ )
|
|
{
|
|
// Get next
|
|
DirectedSectionPair xPair = xList[i];
|
|
if ( i == 0 )
|
|
{
|
|
// Append new entry to sub-list
|
|
m_xSubAdjacencyList.Append (
|
|
DirectedSection ( xPair.m_iSecondSectionTid,
|
|
xPair.m_bSecondUpDown ) );
|
|
xLastPair = xPair;
|
|
}
|
|
else
|
|
{
|
|
// Check if entry allready exists in list. As the list is sorted it
|
|
// has to be the entry before.
|
|
if ( xLastPair.m_iFirstSectionTid != xPair.m_iFirstSectionTid ||
|
|
xLastPair.m_bFirstUpDown != xPair.m_bFirstUpDown ||
|
|
xLastPair.m_iSecondSectionTid != xPair.m_iSecondSectionTid ||
|
|
xLastPair.m_bSecondUpDown != xPair.m_bSecondUpDown )
|
|
{
|
|
// Append new entry to sub-list
|
|
m_xSubAdjacencyList.Append(DirectedSection ( xPair.m_iSecondSectionTid,
|
|
xPair.m_bSecondUpDown ) );
|
|
}
|
|
}
|
|
|
|
// Entry in adjacency list if all sections adjacent to one section have
|
|
// been found. This is the case every time the first section changes. Never
|
|
// at the first entry and always at the last.
|
|
if ( i == xList.size() -1 ||
|
|
(
|
|
i != 0 &&
|
|
(
|
|
xLastPair.m_iFirstSectionTid != xPair.m_iFirstSectionTid ||
|
|
xLastPair.m_bFirstUpDown != xPair.m_bFirstUpDown
|
|
)
|
|
)
|
|
)
|
|
{
|
|
if (i == xList.size() -1 ) iHigh = m_xSubAdjacencyList.Size()-1;
|
|
else iHigh = m_xSubAdjacencyList.Size()-2;
|
|
Tuple* sectTup =
|
|
(Tuple*) m_pSections->GetTuple(xLastPair.m_iFirstSectionTid,false);
|
|
int sid = ((CcInt*)sectTup->GetAttribute(SECTION_SID))->GetIntval();
|
|
sectTup->DeleteIfAllowed();
|
|
iIndex = 2 * ( sid-1 );
|
|
iIndex += xLastPair.m_bFirstUpDown ? 1 : 0;
|
|
m_xAdjacencyList.Put ( iIndex, AdjacencyListEntry ( iLow, iHigh ) );
|
|
iLow = iHigh + 1;
|
|
}
|
|
xLastPair = xPair;
|
|
}
|
|
m_xAdjacencyList.TrimToSize();
|
|
m_xSubAdjacencyList.TrimToSize();
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Now - as the third step the reverse adjacency lists are filled.
|
|
//
|
|
// Sort the lists by the first directed section
|
|
stable_sort ( xReverseList.begin(), xReverseList.end() );
|
|
|
|
DirectedSectionPair xLastReversePair;
|
|
iLow = 0;
|
|
iHigh = 0;
|
|
iIndex = 0;
|
|
for ( size_t i = 0; i < xReverseList.size(); i++ )
|
|
{
|
|
// Get next
|
|
DirectedSectionPair xReversePair = xReverseList[i];
|
|
if ( i == 0 )
|
|
{
|
|
// Append new entry to sub-list
|
|
m_reverseSubAdjancencyList.Append (
|
|
DirectedSection ( xReversePair.m_iSecondSectionTid,
|
|
xReversePair.m_bSecondUpDown ) );
|
|
xLastReversePair = xReversePair;
|
|
}
|
|
else
|
|
{
|
|
// Check if entry allready exists in list. As the list is sorted it
|
|
// has to be the entry before.
|
|
if(xLastReversePair.m_iFirstSectionTid !=
|
|
xReversePair.m_iFirstSectionTid ||
|
|
xLastReversePair.m_bFirstUpDown != xReversePair.m_bFirstUpDown ||
|
|
xLastReversePair.m_iSecondSectionTid !=
|
|
xReversePair.m_iSecondSectionTid ||
|
|
xLastReversePair.m_bSecondUpDown != xReversePair.m_bSecondUpDown )
|
|
{
|
|
// Append new entry to sub-list
|
|
m_reverseSubAdjancencyList.Append (
|
|
DirectedSection ( xReversePair.m_iSecondSectionTid,
|
|
xReversePair.m_bSecondUpDown ) );
|
|
}
|
|
}
|
|
// Entry in adjacency list if all sections adjacent to one section have
|
|
// been found. This is the case every time the first section changes. Never
|
|
// at the first entry and always at the last.
|
|
if ( i == xReverseList.size() -1 ||
|
|
(
|
|
i != 0 &&
|
|
(
|
|
xLastReversePair.m_iFirstSectionTid !=
|
|
xReversePair.m_iFirstSectionTid
|
|
||
|
|
xLastReversePair.m_bFirstUpDown !=
|
|
xReversePair.m_bFirstUpDown
|
|
)
|
|
)
|
|
)
|
|
{
|
|
if (i == xReverseList.size() -1 )
|
|
iHigh = m_reverseSubAdjancencyList.Size()-1;
|
|
else
|
|
iHigh = m_reverseSubAdjancencyList.Size()-2;
|
|
Tuple* sectTup =
|
|
(Tuple*)m_pSections->GetTuple(xLastReversePair.m_iFirstSectionTid,
|
|
false);
|
|
int sid = ((CcInt*)sectTup->GetAttribute(SECTION_SID))->GetIntval();
|
|
sectTup->DeleteIfAllowed();
|
|
iIndex = 2 * ( sid-1 );
|
|
iIndex += xLastReversePair.m_bFirstUpDown ? 1 : 0;
|
|
m_reverseAdjacencyList.Put ( iIndex, AdjacencyListEntry ( iLow, iHigh ) );
|
|
iLow = iHigh + 1;
|
|
}
|
|
xLastReversePair = xReversePair;
|
|
}
|
|
m_reverseAdjacencyList.TrimToSize();
|
|
m_reverseSubAdjancencyList.TrimToSize();
|
|
}
|
|
|
|
/*
|
|
Build vector of directed section pairs.
|
|
|
|
*/
|
|
|
|
void Network::FillAdjacencyPair ( const TupleId in_pFirstSection,
|
|
const bool in_bFirstUp,
|
|
const TupleId in_pSecondSection,
|
|
const bool in_bSecondUp,
|
|
const ConnectivityCode in_xCc,
|
|
const Transition in_xTransition,
|
|
vector<DirectedSectionPair> &inout_xPairs )
|
|
{
|
|
if ( in_pFirstSection != 0 &&
|
|
in_pSecondSection != 0 &&
|
|
in_xCc.IsPossible ( in_xTransition ) )
|
|
{
|
|
inout_xPairs.push_back ( DirectedSectionPair ( in_pFirstSection,
|
|
in_bFirstUp,
|
|
in_pSecondSection,
|
|
in_bSecondUp ) );
|
|
}
|
|
}
|
|
|
|
void Network::FillReverseAdjacencyPair ( const TupleId in_pFirstSection,
|
|
const bool in_bFirstUp,
|
|
const TupleId in_pSecondSection,
|
|
const bool in_bSecondUp,
|
|
const ConnectivityCode in_xCc,
|
|
const Transition in_xTransition,
|
|
vector<DirectedSectionPair> &inout_xPairs )
|
|
{
|
|
if ( in_pFirstSection != 0 &&
|
|
in_pSecondSection != 0 &&
|
|
in_xCc.IsPossible ( in_xTransition ) )
|
|
{
|
|
inout_xPairs.push_back ( DirectedSectionPair ( in_pSecondSection,
|
|
in_bSecondUp,
|
|
in_pFirstSection,
|
|
in_bFirstUp ) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
c.
|
|
|
|
*/
|
|
bool Network::InShortestPath ( GPoint*start, GPoint *to,
|
|
GLine *result ) const
|
|
{
|
|
GPoint* end = new GPoint ( *to );//copy the gpoint
|
|
result->Clear();
|
|
if ( start == 0 || end == 0 || !start->IsDefined() ||
|
|
!end->IsDefined() )
|
|
{
|
|
sendMessage ( "Both gpoints must exist and be defined." );
|
|
result->SetDefined ( false );
|
|
end->DeleteIfAllowed();
|
|
return false;
|
|
}
|
|
// Check wether both points belong to the same network
|
|
if ( start->GetNetworkId() != end->GetNetworkId() )
|
|
{
|
|
sendMessage ( "Both gpoints belong to different networks." );
|
|
result->SetDefined ( false );
|
|
end->DeleteIfAllowed();
|
|
return false;
|
|
}
|
|
|
|
result->SetNetworkId ( GetId() );
|
|
|
|
// Get sections where the path should start or end
|
|
Tuple* startSection = GetSectionOnRoute ( start );
|
|
if ( startSection == 0 )
|
|
{
|
|
sendMessage ( "Starting GPoint not found in network." );
|
|
result->SetDefined ( false );
|
|
end->DeleteIfAllowed();
|
|
return false;
|
|
}
|
|
Tuple* endSection = GetSectionOnRoute ( end );
|
|
if ( endSection == 0 )
|
|
{
|
|
sendMessage ( "End GPoint not found in network." );
|
|
startSection->DeleteIfAllowed();
|
|
result->SetDefined ( false );
|
|
end->DeleteIfAllowed();
|
|
return false;
|
|
}
|
|
////////////////////////////////////////////////////
|
|
bool junctionpoint = false;
|
|
Point* endp = new Point();
|
|
GetPointOnRoute ( end,endp ); //end point
|
|
vector<JunctionSortEntry> juns;
|
|
CcInt* routeid = new CcInt ( true,end->GetRouteId() );
|
|
GetJunctionsOnRoute ( routeid,juns );
|
|
for ( unsigned int i = 0;i < juns.size();i++ )
|
|
{
|
|
Tuple* t = juns[i].m_pJunction;
|
|
if ( ( ( CcInt* ) t->GetAttribute ( JUNCTION_ROUTE1_ID ) )->GetIntval() ==
|
|
end->GetRouteId() &&
|
|
AlmostEqualAbsolute (
|
|
((CcReal*)t->GetAttribute(JUNCTION_ROUTE1_MEAS))->GetRealval(),
|
|
end->GetPosition(), 0.1*m_scalefactor))
|
|
junctionpoint = true;
|
|
if ( ( ( CcInt* ) t->GetAttribute ( JUNCTION_ROUTE2_ID ) )->GetIntval() ==
|
|
end->GetRouteId() &&
|
|
AlmostEqualAbsolute (
|
|
((CcReal*)t->GetAttribute(JUNCTION_ROUTE2_MEAS))->GetRealval(),
|
|
end->GetPosition(), 0.1*m_scalefactor))
|
|
junctionpoint = true;
|
|
}
|
|
vector<TupleId> secjunid;
|
|
if ( junctionpoint ) //it is a junction point
|
|
{
|
|
vector<DirectedSection> sectionlist;
|
|
if ( AlmostEqualAbsolute( end->GetPosition(),
|
|
((CcReal*)endSection->GetAttribute(SECTION_MEAS1))->GetRealval(),
|
|
0.1*m_scalefactor))
|
|
GetAdjacentSections ( endSection->GetTupleId(),false,sectionlist );
|
|
else
|
|
GetAdjacentSections ( endSection->GetTupleId(),true,sectionlist );
|
|
for ( unsigned int i = 0;i < sectionlist.size();i++ )
|
|
{
|
|
if ( sectionlist[i].GetSectionTid() != endSection->GetTupleId() )
|
|
secjunid.push_back ( sectionlist[i].GetSectionTid() );
|
|
}
|
|
}
|
|
endp->DeleteIfAllowed();
|
|
routeid->DeleteIfAllowed();
|
|
/////////////////////////////////////////////////////
|
|
// Calculate the shortest path using dijkstras algorithm.
|
|
|
|
|
|
|
|
TupleId startSectTID = startSection->GetTupleId();
|
|
TupleId lastSectTID = endSection->GetTupleId();
|
|
|
|
if ( startSectTID == lastSectTID )
|
|
{
|
|
result->AddRouteInterval ( start->GetRouteId(), start->GetPosition(),
|
|
end->GetPosition() );
|
|
}
|
|
else
|
|
{
|
|
|
|
//Initialize PriorityQueue
|
|
|
|
PrioQueue *prioQ = new PrioQueue ( 0 );
|
|
SectIDTree *visitedSect = 0;
|
|
double sectMeas1 =
|
|
((CcReal*)startSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
double sectMeas2 =
|
|
((CcReal*)startSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
double dist = 0.0;
|
|
vector<DirectedSection> adjSectionList;
|
|
adjSectionList.clear();
|
|
if ( start->GetSide() == 0 )
|
|
{
|
|
dist = start->GetPosition() - sectMeas1;
|
|
GetAdjacentSections ( startSectTID, false, adjSectionList );
|
|
SectIDTree *startTree = new SectIDTree ( startSectTID,
|
|
( TupleId ) numeric_limits<long>::max(),
|
|
false,
|
|
numeric_limits<int>::max() );
|
|
visitedSect = startTree;
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
if ( actNextSect.GetSectionTid() != startSectTID )
|
|
{
|
|
PQEntry *actEntry = new PQEntry ( actNextSect.GetSectionTid(), dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectTID );
|
|
prioQ->Insert ( *actEntry, visitedSect, 0 ) ;
|
|
delete actEntry;
|
|
}
|
|
}
|
|
adjSectionList.clear();
|
|
}
|
|
else
|
|
{
|
|
if ( start->GetSide() == 1 )
|
|
{
|
|
dist = sectMeas2 - start->GetPosition();
|
|
SectIDTree *startTree = new SectIDTree ( startSectTID,
|
|
( TupleId ) numeric_limits<long>::max(),
|
|
true,
|
|
numeric_limits<int>::max() );
|
|
visitedSect = startTree;
|
|
GetAdjacentSections ( startSectTID, true, adjSectionList );
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
if ( actNextSect.GetSectionTid() != startSectTID )
|
|
{
|
|
PQEntry *actEntry = new PQEntry ( actNextSect.GetSectionTid(), dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectTID );
|
|
prioQ->Insert ( *actEntry, visitedSect ,0);
|
|
delete actEntry;
|
|
}
|
|
}
|
|
adjSectionList.clear();
|
|
}
|
|
else
|
|
{
|
|
dist = start->GetPosition() - sectMeas1;
|
|
GetAdjacentSections ( startSectTID, false, adjSectionList );
|
|
bool first = true;
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
if ( actNextSect.GetSectionTid() != startSectTID )
|
|
{
|
|
if ( first )
|
|
{
|
|
first = false;
|
|
SectIDTree *startTree = new SectIDTree ( startSectTID,
|
|
( TupleId ) numeric_limits<long>::max(),
|
|
false,
|
|
numeric_limits<int>::max() );
|
|
visitedSect = startTree;
|
|
}
|
|
PQEntry *actEntry = new PQEntry ( actNextSect.GetSectionTid(), dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectTID );
|
|
prioQ->Insert ( *actEntry, visitedSect,0 );
|
|
delete actEntry;
|
|
}
|
|
}
|
|
adjSectionList.clear();
|
|
dist = sectMeas2 -start->GetPosition();
|
|
GetAdjacentSections ( startSectTID, true, adjSectionList );
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
if ( actNextSect.GetSectionTid() != startSectTID )
|
|
{
|
|
if ( first )
|
|
{
|
|
first = false;
|
|
SectIDTree *startTree = new SectIDTree ( startSectTID,
|
|
( TupleId ) numeric_limits<long>::max(),
|
|
true,
|
|
numeric_limits<int>::max() );
|
|
visitedSect = startTree;
|
|
}
|
|
PQEntry *actEntry = new PQEntry ( actNextSect.GetSectionTid(), dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectTID );
|
|
prioQ->Insert ( *actEntry, visitedSect,0 );
|
|
delete actEntry;
|
|
}
|
|
}
|
|
adjSectionList.clear();
|
|
}
|
|
}
|
|
// Use priorityQueue to find shortestPath.
|
|
|
|
PQEntry *actPQEntry;
|
|
bool found = false;
|
|
while ( !prioQ->IsEmpty() && !found )
|
|
{
|
|
actPQEntry = prioQ->GetAndDeleteMin ( visitedSect );
|
|
Tuple *actSection = GetSection ( actPQEntry->sectID );
|
|
sectMeas1 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
sectMeas2 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
dist = actPQEntry->distFromStart + fabs ( sectMeas2 - sectMeas1 );
|
|
|
|
//////////////////////////////////////
|
|
if ( junctionpoint ) //end point is a junction point
|
|
{
|
|
for ( unsigned int i = 0;i < secjunid.size();i++ )
|
|
{
|
|
if ( secjunid[i] == actPQEntry->sectID )
|
|
{
|
|
lastSectTID = actPQEntry->sectID;
|
|
Tuple* sect = GetSection ( lastSectTID );
|
|
double m1 =
|
|
((CcReal*)sect->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
double m2 =
|
|
((CcReal*)sect->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
if ( actPQEntry->upDownFlag )
|
|
{
|
|
GPoint* temp = new GPoint ( true,end->GetNetworkId(),
|
|
end->GetRouteId(),m2,None );
|
|
*end = *temp;
|
|
temp->DeleteIfAllowed();
|
|
}
|
|
else
|
|
{
|
|
GPoint* temp = new GPoint ( true,end->GetNetworkId(),
|
|
end->GetRouteId(),m1,None );
|
|
*end = *temp;
|
|
temp->DeleteIfAllowed();
|
|
}
|
|
sect->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
////////////////////////////////////
|
|
|
|
if ( actPQEntry->sectID != lastSectTID )
|
|
{
|
|
//Search further in the network unitl reached last section.
|
|
//Get adjacent sections and insert into priority Queue.
|
|
|
|
adjSectionList.clear();
|
|
GetAdjacentSections ( actPQEntry->sectID,
|
|
actPQEntry->upDownFlag,
|
|
adjSectionList );
|
|
for ( size_t i = 0; i <adjSectionList.size();i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
if ( actNextSect.GetSectionTid() != actPQEntry->sectID )
|
|
{
|
|
PQEntry *actEntry = new PQEntry ( actNextSect.GetSectionTid(),
|
|
dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
actPQEntry->sectID );
|
|
prioQ->Insert ( *actEntry, visitedSect,0 );
|
|
delete actEntry;
|
|
}
|
|
}
|
|
delete actPQEntry;
|
|
actSection->DeleteIfAllowed();
|
|
}
|
|
else
|
|
{
|
|
|
|
// Shortest Path found.
|
|
// Compute last route interval and resulting gline.
|
|
|
|
found = true;
|
|
double startRI, endRI;
|
|
int actRouteId =
|
|
( ( CcInt* ) actSection->GetAttribute ( SECTION_RID )
|
|
)->GetIntval();
|
|
if ( actPQEntry->upDownFlag == true )
|
|
{
|
|
startRI = sectMeas1;
|
|
endRI = end->GetPosition();
|
|
}
|
|
else
|
|
{
|
|
startRI = sectMeas2;
|
|
endRI = end->GetPosition();
|
|
}
|
|
|
|
actSection->DeleteIfAllowed();
|
|
|
|
//Get the sections used for shortest path and write them in right
|
|
//order (from start to end ) in the resulting gline. Because dijkstra gives
|
|
//the sections from end to start we first have to put the result sections on a
|
|
//stack to turn in right order.
|
|
|
|
RIStackP *riStack = new RIStackP(0);
|
|
riStack->Push(actRouteId, startRI, endRI);
|
|
TupleId lastSectId = actPQEntry->sectID;
|
|
SectIDTree *pElem = visitedSect->Find ( actPQEntry->beforeSectID );
|
|
bool end = false;
|
|
bool upDown;
|
|
// if (startRI >= endRI) upDown = false;
|
|
if ( startRI > endRI || fabs ( startRI-endRI ) < 0.1 ) upDown = false;
|
|
else upDown = true;
|
|
while ( !end )
|
|
{
|
|
//GetSection
|
|
actSection = GetSection ( pElem->sectID );
|
|
actRouteId =
|
|
( ( CcInt* ) actSection->GetAttribute ( SECTION_RID )
|
|
)->GetIntval();
|
|
sectMeas1 =
|
|
( ( CcReal* ) actSection->GetAttribute ( SECTION_MEAS1 )
|
|
)->GetRealval();
|
|
sectMeas2 =
|
|
( ( CcReal* ) actSection->GetAttribute ( SECTION_MEAS2 )
|
|
)->GetRealval();
|
|
upDown = pElem->upDownFlag;
|
|
if ( pElem->sectID != startSectTID )
|
|
{
|
|
if ( upDown )
|
|
riStack->Push ( actRouteId, sectMeas1, sectMeas2);
|
|
else
|
|
riStack->Push ( actRouteId, sectMeas2, sectMeas1);
|
|
lastSectId = pElem->sectID;
|
|
pElem = visitedSect->Find ( pElem->beforeSectId );
|
|
}
|
|
else
|
|
{
|
|
end = true;
|
|
GetAdjacentSections ( startSectTID, true, adjSectionList );
|
|
size_t i = 0;
|
|
bool stsectfound = false;
|
|
while ( i < adjSectionList.size() && !stsectfound )
|
|
{
|
|
DirectedSection adjSection = adjSectionList[i];
|
|
if ( adjSection.GetSectionTid() == lastSectId )
|
|
{
|
|
if ( fabs ( start->GetPosition()-sectMeas2 ) > 0.1 )
|
|
{
|
|
stsectfound = true;
|
|
riStack->Push ( actRouteId, start->GetPosition(), sectMeas2);
|
|
end = true;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
adjSectionList.clear();
|
|
if ( !stsectfound )
|
|
{
|
|
GetAdjacentSections ( startSectTID, false,
|
|
adjSectionList );
|
|
i = 0;
|
|
while ( i < adjSectionList.size() && !stsectfound )
|
|
{
|
|
DirectedSection adjSection = adjSectionList[i];
|
|
if ( adjSection.GetSectionTid() == lastSectId )
|
|
{
|
|
if ( fabs ( start->GetPosition() - sectMeas1 ) > 0.1 )
|
|
{
|
|
stsectfound = true;
|
|
riStack->Push( actRouteId, start->GetPosition(), sectMeas1);
|
|
end = true;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
adjSectionList.clear();
|
|
}
|
|
}
|
|
}
|
|
// Cleanup and return result
|
|
riStack->StackToGLine ( result, GetId());
|
|
riStack->Destroy();
|
|
delete riStack;
|
|
delete actPQEntry;
|
|
}
|
|
}
|
|
visitedSect->Remove();
|
|
prioQ->Destroy();
|
|
delete prioQ;
|
|
}
|
|
startSection->DeleteIfAllowed();
|
|
endSection->DeleteIfAllowed();
|
|
result->SetSorted ( false );
|
|
result->SetDefined ( true );
|
|
result->TrimToSize();
|
|
end->DeleteIfAllowed();
|
|
return true;
|
|
};
|
|
|
|
/*
|
|
.
|
|
|
|
*/
|
|
void Network::FindSP ( TupleId j1, TupleId j2, double& length,
|
|
GLine* res ) const
|
|
{
|
|
res->SetNetworkId ( GetId() );
|
|
for ( int i = 1; i <= alldistance->GetNoTuples();i++ )
|
|
{
|
|
Tuple* tuple = alldistance->GetTuple ( i, false );
|
|
TupleId jun1 = ( ( CcInt* ) tuple->GetAttribute ( 0 ) )->GetIntval();
|
|
TupleId jun2 = ( ( CcInt* ) tuple->GetAttribute ( 1 ) )->GetIntval();
|
|
if ( ( jun1 == j1 && jun2 == j2 ) ||
|
|
( jun1 ==j2 && jun2 == j1 ) )
|
|
{
|
|
length = ( ( CcReal* ) tuple->GetAttribute ( 2 ) )->GetRealval();
|
|
GLine* gline = ( GLine* ) tuple->GetAttribute ( 3 );
|
|
*res = *gline;
|
|
tuple->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
res->TrimToSize();
|
|
}
|
|
|
|
/*
|
|
.
|
|
|
|
*/
|
|
|
|
void Network::FillDistanceStorage()
|
|
{
|
|
ListExpr xType;
|
|
nl->ReadFromString ( distancestorageTypeInfo,xType );
|
|
ListExpr xNumType = SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
alldistance = new Relation ( xNumType );
|
|
//store the distance between each two junction points
|
|
|
|
for ( int i = 1;i <= m_pJunctions->GetNoTuples();i++ )
|
|
{
|
|
for ( int j = i+1; j <= m_pJunctions->GetNoTuples();j++ )
|
|
{
|
|
Tuple* jun1 = m_pJunctions->GetTuple ( i, false );
|
|
Tuple* jun2 = m_pJunctions->GetTuple ( j , false);
|
|
int rid1 = ( ( CcInt* ) jun1->GetAttribute ( JUNCTION_ROUTE1_ID )
|
|
)->GetIntval();
|
|
int rid2 = ( ( CcInt* ) jun2->GetAttribute ( JUNCTION_ROUTE1_ID )
|
|
)->GetIntval();
|
|
float pos1 =
|
|
( ( CcReal* ) jun1->GetAttribute ( JUNCTION_ROUTE1_MEAS )
|
|
)->GetRealval();
|
|
float pos2 =
|
|
( ( CcReal* ) jun2->GetAttribute ( JUNCTION_ROUTE1_MEAS )
|
|
)->GetRealval();
|
|
Side side = None;
|
|
Point* p1 = ( Point* ) jun1->GetAttribute ( JUNCTION_POS );
|
|
Point* p2 = ( Point* ) jun2->GetAttribute ( JUNCTION_POS );
|
|
if ( AlmostEqualAbsolute( p1->GetX(),p2->GetX(),0.1*m_scalefactor) &&
|
|
AlmostEqualAbsolute( p1->GetY(),p2->GetY(),0.1*m_scalefactor))
|
|
//same junction point
|
|
continue;
|
|
GPoint* gp1 = new GPoint ( true,GetId(),rid1,pos1,side );
|
|
GPoint* gp2 = new GPoint ( true,GetId(),rid2,pos2,side );
|
|
Tuple* tuple = new Tuple ( nl->Second ( xNumType ) );
|
|
tuple->PutAttribute ( 0,new TupleIdentifier ( true,i ) );
|
|
tuple->PutAttribute ( 1,new TupleIdentifier ( true,j ) );
|
|
GLine* gline = new GLine ( 0 );
|
|
assert ( InShortestPath ( gp1,gp2,gline ) );
|
|
tuple->PutAttribute ( 2,new CcReal ( true,gline->GetLength() ) );
|
|
GLine* temp = new GLine ( 0 );
|
|
temp->SetNetworkId ( gline->GetNetworkId() );
|
|
RouteInterval ri;
|
|
gline->Get ( 0,ri );
|
|
temp->AddRouteInterval ( ri );//head
|
|
gline->Get ( gline->Size()-1,ri );
|
|
temp->AddRouteInterval ( ri );//tail
|
|
tuple->PutAttribute ( 3,new GLine ( temp ) );
|
|
temp->DeleteIfAllowed();
|
|
gline->DeleteIfAllowed();
|
|
alldistance->AppendTuple ( tuple );
|
|
tuple->DeleteIfAllowed();
|
|
gp1->DeleteIfAllowed();
|
|
gp2->DeleteIfAllowed();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
Returning network parameters.
|
|
|
|
*/
|
|
|
|
int Network::GetId() const
|
|
{
|
|
return m_iId;
|
|
}
|
|
|
|
Relation *Network::GetRoutes() const
|
|
{
|
|
return m_pRoutes;
|
|
}
|
|
|
|
|
|
Relation *Network::GetJunctions() const
|
|
{
|
|
|
|
ListExpr ptrList = listutils::getPtrList(m_pJunctions);
|
|
|
|
string querystring = "(consume (feed (" + junctionsInternalTypeInfo +
|
|
" (ptr " + nl->ToString(ptrList) + "))))";
|
|
|
|
Word resultWord;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery ( querystring, resultWord );
|
|
assert ( QueryExecuted );
|
|
return ( Relation * ) resultWord.addr;
|
|
}
|
|
|
|
|
|
void Network::GetJunctionsOnRoute ( CcInt* in_pRouteId,
|
|
vector<JunctionSortEntry>& inout_xJunctions)
|
|
const
|
|
{
|
|
BTreeIterator* pJunctionsIt;
|
|
pJunctionsIt = m_pBTreeJunctionsByRoute1->ExactMatch ( in_pRouteId );
|
|
inout_xJunctions.clear();
|
|
while(pJunctionsIt->Next())
|
|
{
|
|
Tuple* pCurrentJunction = m_pJunctions->GetTuple ( pJunctionsIt->GetId(),
|
|
false );
|
|
inout_xJunctions.push_back(JunctionSortEntry(true, pCurrentJunction ));
|
|
}
|
|
delete pJunctionsIt;
|
|
pJunctionsIt = m_pBTreeJunctionsByRoute2->ExactMatch ( in_pRouteId );
|
|
while ( pJunctionsIt->Next() )
|
|
{
|
|
Tuple* pCurrentJunction = m_pJunctions->GetTuple ( pJunctionsIt->GetId(),
|
|
false );
|
|
inout_xJunctions.push_back(JunctionSortEntry(false, pCurrentJunction));
|
|
}
|
|
delete pJunctionsIt;
|
|
stable_sort(inout_xJunctions.begin(), inout_xJunctions.end());
|
|
}
|
|
|
|
void Network::GetTidJunctionsOnRoute ( CcInt* in_pRouteId,
|
|
vector<JunctionTidSortEntry>& inout_xJunctions)
|
|
const
|
|
{
|
|
BTreeIterator* pJunctionsIt;
|
|
pJunctionsIt = m_pBTreeJunctionsByRoute1->ExactMatch ( in_pRouteId );
|
|
inout_xJunctions.clear();
|
|
while(pJunctionsIt->Next())
|
|
{
|
|
inout_xJunctions.push_back(JunctionTidSortEntry(true,
|
|
pJunctionsIt->GetId(),
|
|
m_pJunctions));
|
|
}
|
|
delete pJunctionsIt;
|
|
pJunctionsIt = m_pBTreeJunctionsByRoute2->ExactMatch ( in_pRouteId );
|
|
while ( pJunctionsIt->Next() )
|
|
{
|
|
inout_xJunctions.push_back(JunctionTidSortEntry(false,
|
|
pJunctionsIt->GetId(),
|
|
m_pJunctions));
|
|
}
|
|
delete pJunctionsIt;
|
|
stable_sort(inout_xJunctions.begin(), inout_xJunctions.end());
|
|
}
|
|
|
|
Tuple* Network::GetSection ( const TupleId n )const
|
|
{
|
|
return m_pSections->GetTuple ( n, false );
|
|
}
|
|
|
|
|
|
TupleId Network::GetTupleIdSectionOnRoute ( const GPoint* in_xGPoint )const
|
|
{
|
|
CcInt *ciRouteId = new CcInt ( true, in_xGPoint->GetRouteId() );
|
|
BTreeIterator* pSectionIter =
|
|
m_pBTreeSectionsByRoute->ExactMatch ( ciRouteId );
|
|
ciRouteId->DeleteIfAllowed();
|
|
Tuple *actSect = 0;
|
|
TupleId result;
|
|
while ( pSectionIter->Next() )
|
|
{
|
|
result = pSectionIter->GetId();
|
|
actSect =
|
|
m_pSections->GetTuple ( pSectionIter->GetId(), false );
|
|
if ( actSect != 0 )
|
|
{
|
|
double start =
|
|
( ( CcReal* ) actSect->GetAttribute ( SECTION_MEAS1 ) )->GetRealval();
|
|
double end =
|
|
( ( CcReal* ) actSect->GetAttribute ( SECTION_MEAS2 ) )->GetRealval();
|
|
if ( in_xGPoint->GetPosition() >= start&&in_xGPoint->GetPosition() <= end)
|
|
{
|
|
delete pSectionIter;
|
|
actSect->DeleteIfAllowed();
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
if ( AlmostEqualAbsolute( in_xGPoint->GetPosition(), start,
|
|
m_scalefactor*0.01))
|
|
{
|
|
delete pSectionIter;
|
|
actSect->DeleteIfAllowed();
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
if ( AlmostEqualAbsolute( in_xGPoint->GetPosition(), end,
|
|
m_scalefactor*0.01 ))
|
|
{
|
|
Tuple *pRoute =
|
|
GetRoute(((TupleIdentifier*)
|
|
actSect->GetAttribute(SECTION_RRC))->GetTid());
|
|
if (AlmostEqualAbsolute(
|
|
((CcReal*)pRoute->GetAttribute(ROUTE_LENGTH))->GetRealval(),
|
|
end, m_scalefactor*0.01 ))
|
|
{
|
|
pRoute->DeleteIfAllowed();
|
|
delete pSectionIter;
|
|
actSect->DeleteIfAllowed();
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
pRoute->DeleteIfAllowed();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
actSect->DeleteIfAllowed();
|
|
}
|
|
}
|
|
delete pSectionIter;
|
|
return 0;
|
|
}
|
|
|
|
Tuple* Network::GetSectionOnRoute (const GPoint* in_xGPoint )const
|
|
{
|
|
return GetSection ( GetTupleIdSectionOnRoute ( in_xGPoint ) );
|
|
}
|
|
|
|
/*
|
|
Returns the tuple from routes relation for the given route id.
|
|
|
|
*/
|
|
|
|
Tuple* Network::GetRoute ( const int in_RouteId )const
|
|
{
|
|
CcInt* pRouteId = new CcInt ( true, in_RouteId );
|
|
BTreeIterator *pRoutesIter = m_pBTreeRoutes->ExactMatch ( pRouteId );
|
|
pRouteId->DeleteIfAllowed();
|
|
Tuple *pRoute = 0;
|
|
if ( pRoutesIter->Next() )
|
|
pRoute = m_pRoutes->GetTuple ( pRoutesIter->GetId() , false);
|
|
assert ( pRoute != 0 );
|
|
delete pRoutesIter;
|
|
return pRoute;
|
|
|
|
}
|
|
|
|
Tuple* Network::GetRoute (const TupleId in_routeTID )const
|
|
{
|
|
return m_pRoutes->GetTuple ( in_routeTID, false );
|
|
}
|
|
|
|
void Network::GetSectionsOfRouteInterval ( const RouteInterval *ri,
|
|
vector<SectTreeEntry>& io_SectionIds )const
|
|
{
|
|
double ristart = min ( ri->GetStartPos(), ri->GetEndPos() );
|
|
double riend = max ( ri->GetStartPos(), ri->GetEndPos() );
|
|
CcInt* ciRouteId = new CcInt ( true, ri->GetRouteId() );
|
|
BTreeIterator* pSectionIter =
|
|
m_pBTreeSectionsByRoute->ExactMatch ( ciRouteId );
|
|
ciRouteId->DeleteIfAllowed();
|
|
Tuple *actSect;
|
|
TupleId actSectTID;
|
|
while ( pSectionIter->Next() )
|
|
{
|
|
bool bsectstart = true;
|
|
bool bsectend = true;
|
|
actSectTID = pSectionIter->GetId();
|
|
actSect = m_pSections->GetTuple ( actSectTID, false );
|
|
assert ( actSect != 0 );
|
|
double start =
|
|
( ( CcReal* ) actSect->GetAttribute ( SECTION_MEAS1 ) )->GetRealval();
|
|
double end =
|
|
( ( CcReal* ) actSect->GetAttribute ( SECTION_MEAS2 ) )->GetRealval();
|
|
if (( ristart <= start && riend >= end ) ||
|
|
( start <= ristart && end >= ristart ) ||
|
|
( start <= riend && end >= riend ))
|
|
{
|
|
if (start < ristart)
|
|
{
|
|
start = ristart;
|
|
bsectstart = false;
|
|
}
|
|
if (riend < end)
|
|
{
|
|
end = riend;
|
|
bsectend = false;
|
|
}
|
|
SectTreeEntry *sect =
|
|
new SectTreeEntry ( actSect->GetTupleId(), ri->GetRouteId(), start,
|
|
end, bsectstart, bsectend );
|
|
io_SectionIds.push_back(*sect);
|
|
delete sect;
|
|
}
|
|
actSect->DeleteIfAllowed();
|
|
if ( riend <= end ) break;
|
|
}
|
|
delete pSectionIter;
|
|
};
|
|
|
|
void Network::GetSectionsOfRoutInterval ( const RouteInterval *ri,
|
|
vector<TupleId> &res )const
|
|
{
|
|
res.clear();
|
|
double ristart = min ( ri->GetStartPos(), ri->GetEndPos() );
|
|
double riend = max ( ri->GetStartPos(), ri->GetEndPos() );
|
|
CcInt* ciRouteId = new CcInt ( true, ri->GetRouteId() );
|
|
BTreeIterator* pSectionIter =
|
|
m_pBTreeSectionsByRoute->ExactMatch ( ciRouteId );
|
|
ciRouteId->DeleteIfAllowed();
|
|
Tuple *actSect;
|
|
TupleId actSectTID;
|
|
//bool bsectstart = true;
|
|
//bool bsectend = true;
|
|
while ( pSectionIter->Next() )
|
|
{
|
|
actSectTID = pSectionIter->GetId();
|
|
actSect = m_pSections->GetTuple ( actSectTID, false );
|
|
assert ( actSect != 0 );
|
|
double start =
|
|
( ( CcReal* ) actSect->GetAttribute ( SECTION_MEAS1 ) )->GetRealval();
|
|
double end =
|
|
( ( CcReal* ) actSect->GetAttribute ( SECTION_MEAS2 ) )->GetRealval();
|
|
if ( AlmostEqualAbsolute ( ristart, riend, m_scalefactor*0.01 ) &&
|
|
( AlmostEqualAbsolute ( ristart, start, m_scalefactor*0.01 ) ||
|
|
AlmostEqualAbsolute ( ristart, end, m_scalefactor*0.01)))
|
|
{
|
|
res.push_back ( actSectTID );
|
|
actSect->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if ( ( ( ristart <= start && end <= riend ) ||
|
|
( start <= ristart && end > ristart ) ||
|
|
( start < riend && riend <= end ) ) &&
|
|
(!( AlmostEqualAbsolute ( ristart, end, m_scalefactor*0.01 ) ||
|
|
AlmostEqualAbsolute (start, riend, m_scalefactor*0.01 ))))
|
|
res.push_back ( actSectTID );
|
|
}
|
|
actSect->DeleteIfAllowed();
|
|
}
|
|
delete pSectionIter;
|
|
}
|
|
|
|
/*
|
|
Returns the spatial position of the gpoint.
|
|
|
|
*/
|
|
void Network::GetPointOnRoute ( const GPoint* in_pGPoint, Point*& res )const
|
|
{
|
|
/*Point *res = new Point(false);*/
|
|
CcInt* pRouteId = new CcInt ( true, in_pGPoint->GetRouteId() );
|
|
BTreeIterator* pRoutesIter = m_pBTreeRoutes->ExactMatch ( pRouteId );
|
|
pRouteId->DeleteIfAllowed();
|
|
Tuple *pRoute = 0;
|
|
if ( pRoutesIter->Next() )
|
|
pRoute = m_pRoutes->GetTuple ( pRoutesIter->GetId(), false );
|
|
assert ( pRoute != 0 );
|
|
SimpleLine* pLine = ( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE );
|
|
bool startSmaller =
|
|
((CcBool*)pRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
assert ( pLine != 0 );
|
|
double pos = in_pGPoint->GetPosition();
|
|
if (pos < 0.0)
|
|
pos = 0.0;
|
|
else
|
|
if (pos > pLine->Length())
|
|
pos = pLine->Length();
|
|
pLine->AtPosition ( pos, startSmaller, *res );
|
|
pRoute->DeleteIfAllowed();
|
|
delete pRoutesIter;
|
|
/*return res;*/
|
|
}
|
|
|
|
Relation* Network::GetSectionsInternal()const
|
|
{
|
|
return m_pSections;
|
|
}
|
|
|
|
Relation* Network::GetSections()const
|
|
{
|
|
ListExpr ptrList = listutils::getPtrList(m_pSections);
|
|
|
|
string querystring = "(consume (feed (" + sectionsInternalTypeInfo +
|
|
" (ptr " + nl->ToString(ptrList) + "))))";
|
|
|
|
Word resultWord;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery ( querystring, resultWord );
|
|
assert ( QueryExecuted );
|
|
return ( Relation * ) resultWord.addr;
|
|
}
|
|
|
|
/*
|
|
Returns adjacent sections of iniSectionTId.
|
|
|
|
*/
|
|
|
|
void Network::GetAdjacentSections ( const TupleId in_iSectionTId,
|
|
const bool in_bUpDown,
|
|
vector<DirectedSection> &inout_xSections )
|
|
const
|
|
{
|
|
inout_xSections.clear();
|
|
Tuple *pSect = GetSection ( in_iSectionTId );
|
|
if ( pSect != 0 )
|
|
{
|
|
//cout << "found section" << endl;
|
|
int iSectionId =
|
|
( ( CcInt* ) pSect->GetAttribute ( SECTION_SID ) )->GetIntval();
|
|
pSect->DeleteIfAllowed();
|
|
int iIndex = 2 * ( iSectionId-1 ) + ( in_bUpDown ? 1 : 0 );
|
|
AdjacencyListEntry xEntry;
|
|
m_xAdjacencyList.Get ( iIndex, xEntry );
|
|
if ( xEntry.m_iHigh != -1 )
|
|
{
|
|
int iLow = xEntry.m_iLow;
|
|
int iHigh = xEntry.m_iHigh;
|
|
|
|
for ( int i = iLow; i <= iHigh; i++ )
|
|
{
|
|
DirectedSection xSection;
|
|
m_xSubAdjacencyList.Get ( i, xSection );
|
|
|
|
bool bUpDownFlag = xSection.GetUpDownFlag();
|
|
TupleId iSectionTid = xSection.GetSectionTid();
|
|
inout_xSections.push_back ( DirectedSection ( iSectionTid,
|
|
bUpDownFlag ) );
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Network::GetAdjacentSections(const int sectId, const bool upDown,
|
|
DbArray<SectionValue> *resArray)const
|
|
{
|
|
int iIndex = 2 * ( sectId-1 ) + ( upDown ? 1 : 0 );
|
|
AdjacencyListEntry xEntry;
|
|
m_xAdjacencyList.Get ( iIndex, xEntry );
|
|
if ( xEntry.m_iHigh != -1 )
|
|
{
|
|
int iLow = xEntry.m_iLow;
|
|
int iHigh = xEntry.m_iHigh;
|
|
|
|
for ( int i = iLow; i <= iHigh; i++ )
|
|
{
|
|
DirectedSection xSection;
|
|
m_xSubAdjacencyList.Get ( i, xSection );
|
|
|
|
bool bUpDownFlag = xSection.GetUpDownFlag();
|
|
Tuple* sectTuple = GetSection(xSection.GetSectionTid());
|
|
int sectionID =
|
|
((CcInt*)sectTuple->GetAttribute(SECTION_SID))->GetIntval();
|
|
sectTuple->DeleteIfAllowed();
|
|
resArray->Append(SectionValue(sectionID,bUpDownFlag));
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
|
|
Returns reverse adjacent sections of iniSectionTId.
|
|
|
|
*/
|
|
|
|
void Network::GetReverseAdjacentSections ( const TupleId in_iSectionTId,
|
|
const bool in_bUpDown,
|
|
vector<DirectedSection> &inout_xSections )
|
|
const
|
|
{
|
|
inout_xSections.clear();
|
|
Tuple *pSect = GetSection ( in_iSectionTId );
|
|
if ( pSect != 0 )
|
|
{
|
|
int iSectionId =
|
|
( ( CcInt* ) pSect->GetAttribute ( SECTION_SID ) )->GetIntval();
|
|
pSect->DeleteIfAllowed();
|
|
int iIndex = 2 * ( iSectionId-1 ) + ( in_bUpDown ? 1 : 0 );
|
|
AdjacencyListEntry xEntry;
|
|
m_reverseAdjacencyList.Get ( iIndex, xEntry );
|
|
if ( xEntry.m_iHigh != -1 )
|
|
{
|
|
int iLow = xEntry.m_iLow;
|
|
int iHigh = xEntry.m_iHigh;
|
|
|
|
for ( int i = iLow; i <= iHigh; i++ )
|
|
{
|
|
DirectedSection xSection;
|
|
m_reverseSubAdjancencyList.Get ( i, xSection );
|
|
|
|
bool bUpDownFlag = xSection.GetUpDownFlag();
|
|
TupleId iSectionTid = xSection.GetSectionTid();
|
|
inout_xSections.push_back ( DirectedSection ( iSectionTid,
|
|
bUpDownFlag ) );
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Network::GetReverseAdjacentSections(const int sectId,
|
|
const bool upDown,
|
|
DbArray<SectionValue> *resArray)
|
|
const
|
|
{
|
|
int iIndex = 2 * ( sectId-1 ) + ( upDown ? 1 : 0 );
|
|
AdjacencyListEntry xEntry;
|
|
m_reverseAdjacencyList.Get ( iIndex, xEntry );
|
|
if ( xEntry.m_iHigh != -1 )
|
|
{
|
|
int iLow = xEntry.m_iLow;
|
|
int iHigh = xEntry.m_iHigh;
|
|
|
|
for ( int i = iLow; i <= iHigh; i++ )
|
|
{
|
|
DirectedSection xSection;
|
|
m_reverseSubAdjancencyList.Get ( i, xSection );
|
|
|
|
bool bUpDownFlag = xSection.GetUpDownFlag();
|
|
Tuple* sectTuple = GetSection(xSection.GetSectionTid());
|
|
int sectionID =
|
|
((CcInt*)sectTuple->GetAttribute(SECTION_SID))->GetIntval();
|
|
sectTuple->DeleteIfAllowed();
|
|
resArray->Append(SectionValue(sectionID, bUpDownFlag));
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
Returns the route Interval between the two points
|
|
|
|
*/
|
|
|
|
void chkStartEndA ( double &StartPos, double &EndPos )
|
|
{
|
|
double help;
|
|
if ( StartPos > EndPos )
|
|
{
|
|
help = StartPos;
|
|
StartPos = EndPos;
|
|
EndPos = help;
|
|
}
|
|
};
|
|
|
|
bool Network::ShorterConnection ( Tuple *route, double &start,
|
|
double &end, double &dpos, double &dpos2,
|
|
int &rid, int &ridt, Point p1,
|
|
Point p2 )const
|
|
{
|
|
if ( AlmostEqual ( p1.Distance ( p2 ), fabs ( end-start ) ) ) return false;
|
|
GPoint *gp = new GPoint ( true, GetId(), route->GetTupleId(),
|
|
end - m_scalefactor*0.01 );
|
|
TupleId pSection1 = GetTupleIdSectionOnRoute ( gp );
|
|
gp->DeleteIfAllowed();
|
|
vector<DirectedSection> pAdjSect1;
|
|
vector<DirectedSection> pAdjSect2;
|
|
pAdjSect1.clear();
|
|
pAdjSect2.clear();
|
|
GetAdjacentSections ( pSection1,true, pAdjSect1 );
|
|
GetAdjacentSections ( pSection1,false, pAdjSect2 );
|
|
if ( pAdjSect1.size() == 0 || pAdjSect2.size() == 0 )
|
|
{
|
|
pAdjSect1.clear();
|
|
pAdjSect2.clear();
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
size_t j = 0;
|
|
while ( j < pAdjSect1.size() )
|
|
{
|
|
DirectedSection actSection = pAdjSect1[j];
|
|
Tuple *pCurrSect = m_pSections->GetTuple ( actSection.GetSectionTid(),
|
|
false );
|
|
ridt = ( ( CcInt* ) pCurrSect->GetAttribute ( SECTION_RID )
|
|
)->GetIntval();
|
|
pCurrSect->DeleteIfAllowed();
|
|
if ( ridt != rid )
|
|
{
|
|
Tuple *pRoute = GetRoute ( ridt );
|
|
SimpleLine *pCurve =
|
|
( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE );
|
|
bool startSmaller =
|
|
((CcBool*)pRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
/*
|
|
if ( ( chkPoint ( pCurve, p1, true, dpos, difference ) ) &&
|
|
( chkPoint ( pCurve, p2, true, dpos2, difference ) ) )
|
|
{*/
|
|
if (pCurve->AtPoint(p1, startSmaller, m_scalefactor, dpos, 0) &&
|
|
pCurve->AtPoint(p2, startSmaller, m_scalefactor, dpos2, 0))
|
|
{
|
|
pAdjSect1.clear();
|
|
pAdjSect2.clear();
|
|
chkStartEndA ( dpos, dpos2 );
|
|
pRoute->DeleteIfAllowed();
|
|
if ( fabs ( dpos2 - dpos ) < fabs ( end - start ) ) return true;
|
|
else return false;
|
|
}
|
|
pRoute->DeleteIfAllowed();
|
|
}
|
|
j++;
|
|
}
|
|
pAdjSect1.clear();
|
|
j = 0;
|
|
while ( j < pAdjSect2.size() )
|
|
{
|
|
DirectedSection actSection = pAdjSect2[j];
|
|
Tuple *pCurrSect = m_pSections->GetTuple ( actSection.GetSectionTid(),
|
|
false );
|
|
ridt = ( ( CcInt* ) pCurrSect->GetAttribute ( SECTION_RID )
|
|
)->GetIntval();
|
|
pCurrSect->DeleteIfAllowed();
|
|
if ( ridt != rid )
|
|
{
|
|
Tuple *pRoute = GetRoute ( ridt );
|
|
SimpleLine *pCurve =
|
|
( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE );
|
|
bool startSmaller =
|
|
((CcBool*)pRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
/*
|
|
if ( ( chkPoint ( pCurve, p1, true, dpos, difference ) ) &&
|
|
( chkPoint ( pCurve, p2, true, dpos2, difference ) ) )*/
|
|
if (pCurve->AtPoint(p1, startSmaller, m_scalefactor,dpos, 0) &&
|
|
pCurve->AtPoint(p2, startSmaller, m_scalefactor,dpos2, 0))
|
|
{
|
|
pAdjSect2.clear();
|
|
chkStartEndA ( dpos, dpos2 );
|
|
pRoute->DeleteIfAllowed();
|
|
if ( fabs ( dpos2-dpos ) < fabs ( end - start ) ) return true;
|
|
else return false;
|
|
}
|
|
pRoute->DeleteIfAllowed();
|
|
}
|
|
j++;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool Network::ShorterConnection2 ( Tuple *route, double &start,
|
|
double &end, double &dpos, double &dpos2,
|
|
int &rid, int &ridt, Point p1,
|
|
Point p2 )const
|
|
{
|
|
if ( AlmostEqualAbsolute ( p1.Distance ( p2 ), fabs ( end-start),
|
|
m_scalefactor) )
|
|
return false;
|
|
double difference = 0.0;
|
|
if ( start < end && end > m_scalefactor*0.01 )
|
|
difference = end -m_scalefactor*0.01;
|
|
else
|
|
if ( start < end && end <= m_scalefactor*0.01 )
|
|
difference = m_scalefactor*0.01;
|
|
else
|
|
if ( start > end ) difference = end + m_scalefactor*0.01;
|
|
else difference = end; //start == end
|
|
GPoint *gp = new GPoint ( true, GetId(), route->GetTupleId(), difference );
|
|
TupleId pSection1 = GetTupleIdSectionOnRoute ( gp );
|
|
gp->DeleteIfAllowed();
|
|
vector<DirectedSection> pAdjSect1;
|
|
vector<DirectedSection> pAdjSect2;
|
|
pAdjSect1.clear();
|
|
pAdjSect2.clear();
|
|
GetAdjacentSections ( pSection1,true, pAdjSect1 );
|
|
GetAdjacentSections ( pSection1,false, pAdjSect2 );
|
|
if ( pAdjSect1.size() == 0 || pAdjSect2.size() == 0 )
|
|
{
|
|
pAdjSect1.clear();
|
|
pAdjSect2.clear();
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
size_t j = 0;
|
|
while ( j < pAdjSect1.size() )
|
|
{
|
|
DirectedSection actSection = pAdjSect1[j];
|
|
Tuple *pCurrSect = m_pSections->GetTuple ( actSection.GetSectionTid(),
|
|
false );
|
|
ridt = ( ( CcInt* ) pCurrSect->GetAttribute ( SECTION_RID )
|
|
)->GetIntval();
|
|
pCurrSect->DeleteIfAllowed();
|
|
if ( ridt != rid )
|
|
{
|
|
Tuple *pRoute = GetRoute ( ridt );
|
|
SimpleLine *pCurve =
|
|
( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE );
|
|
bool startSmaller =
|
|
((CcBool*)pRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
/*if ( ( chkPoint ( pCurve, p1, true, dpos, difference ) ) &&
|
|
( chkPoint ( pCurve, p2, true, dpos2, difference ) ) )*/
|
|
if (pCurve->AtPoint(p1, startSmaller,m_scalefactor, dpos) &&
|
|
pCurve->AtPoint(p2, startSmaller, m_scalefactor,dpos2))
|
|
{
|
|
pAdjSect1.clear();
|
|
pAdjSect2.clear();
|
|
pRoute->DeleteIfAllowed();
|
|
if ( fabs ( dpos2 - dpos ) < fabs ( end - start ) ) return true;
|
|
else return false;
|
|
}
|
|
pRoute->DeleteIfAllowed();
|
|
}
|
|
j++;
|
|
}
|
|
pAdjSect1.clear();
|
|
j = 0;
|
|
while ( j < pAdjSect2.size() )
|
|
{
|
|
DirectedSection actSection = pAdjSect2[j];
|
|
Tuple *pCurrSect = m_pSections->GetTuple ( actSection.GetSectionTid(),
|
|
false );
|
|
ridt = ( ( CcInt* ) pCurrSect->GetAttribute ( SECTION_RID )
|
|
)->GetIntval();
|
|
pCurrSect->DeleteIfAllowed();
|
|
if ( ridt != rid )
|
|
{
|
|
Tuple *pRoute = GetRoute ( ridt );
|
|
SimpleLine *pCurve =
|
|
( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE );
|
|
bool startSmaller =
|
|
((CcBool*)pRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
/*if ( ( chkPoint ( pCurve, p1, true, dpos, difference ) ) &&
|
|
( chkPoint ( pCurve, p2, true, dpos2, difference ) ) )*/
|
|
if (pCurve->AtPoint(p1, startSmaller,m_scalefactor, dpos) &&
|
|
pCurve->AtPoint(p2, startSmaller, m_scalefactor,dpos2))
|
|
{
|
|
pAdjSect2.clear();
|
|
pRoute->DeleteIfAllowed();
|
|
if ( fabs ( dpos2-dpos ) < fabs ( end - start ) ) return true;
|
|
else return false;
|
|
}
|
|
pRoute->DeleteIfAllowed();
|
|
}
|
|
j++;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/*
|
|
|
|
Returns the route curve for the given route id.
|
|
|
|
*/
|
|
|
|
SimpleLine Network::GetRouteCurve ( const int in_iRouteId )const
|
|
{
|
|
Tuple *pRoute = GetRoute ( in_iRouteId );
|
|
SimpleLine sl = * ( ( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE ) );
|
|
pRoute->DeleteIfAllowed();
|
|
return sl;
|
|
}
|
|
|
|
/*
|
|
GetDual
|
|
|
|
Returns the dual value of the given route id.
|
|
|
|
*/
|
|
|
|
bool Network::GetDual (const int in_iRouteId )const
|
|
{
|
|
Tuple *pRoute = GetRoute ( in_iRouteId );
|
|
bool dual = ( ( CcBool* ) pRoute->GetAttribute ( ROUTE_DUAL ) )->GetBoolval();
|
|
pRoute->DeleteIfAllowed();
|
|
return dual;
|
|
}
|
|
|
|
/*
|
|
Searches the route interval between the two given point values.
|
|
|
|
*/
|
|
|
|
RouteInterval* Network::Find ( const Point p1, const Point p2 )const
|
|
{
|
|
GPoint *gpp1 = GetNetworkPosOfPoint ( p1 );
|
|
GPoint *gpp2 = GetNetworkPosOfPoint ( p2 );
|
|
assert ( gpp1->IsDefined() && gpp2->IsDefined() );
|
|
int rid, ridt;
|
|
double start, end, dpos, dpos2;
|
|
if ( gpp1->GetRouteId() == gpp2->GetRouteId() )
|
|
{
|
|
rid = gpp1->GetRouteId();
|
|
start = gpp1->GetPosition();
|
|
end = gpp2->GetPosition();
|
|
chkStartEndA ( start,end );
|
|
Tuple *pRoute = GetRoute ( rid );
|
|
if ( ShorterConnection ( pRoute, start, end, dpos, dpos2, rid, ridt,
|
|
p1, p2) )
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( ridt, dpos, dpos2 );
|
|
}
|
|
else
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( rid, start, end );
|
|
}
|
|
}
|
|
else // different RouteIds
|
|
{
|
|
Tuple *pRoute = GetRoute ( gpp1->GetRouteId() );
|
|
SimpleLine *pCurve =
|
|
( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE );
|
|
bool startSmaller =
|
|
((CcBool*)pRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
//if ( chkPoint ( pCurve, p2, true, dpos, difference ) )
|
|
if (pCurve->AtPoint(p2, startSmaller, m_scalefactor,dpos))
|
|
{
|
|
rid =
|
|
( ( CcInt* ) pRoute->GetAttribute ( ROUTE_ID ) )->GetIntval();
|
|
start = gpp1->GetPosition();
|
|
end = dpos;
|
|
chkStartEndA ( start, end );
|
|
if ( ShorterConnection ( pRoute, start, end, dpos, dpos2, rid, ridt, p1,
|
|
p2 ) )
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( ridt, dpos, dpos2 );
|
|
}
|
|
else
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( rid, start, end );
|
|
}
|
|
}
|
|
pRoute->DeleteIfAllowed();
|
|
pRoute = GetRoute ( gpp2->GetRouteId() );
|
|
pCurve = ( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE );
|
|
startSmaller =
|
|
((CcBool*)pRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
//if ( chkPoint ( pCurve, p1, true, dpos, difference ) )
|
|
if (pCurve->AtPoint(p1, startSmaller, m_scalefactor,dpos))
|
|
{
|
|
rid =
|
|
( ( CcInt* ) pRoute->GetAttribute ( ROUTE_ID ) )->GetIntval();
|
|
start = gpp2->GetPosition();
|
|
end = dpos;
|
|
chkStartEndA ( start, end );
|
|
if ( ShorterConnection ( pRoute, start, end, dpos, dpos2, rid, ridt, p1,
|
|
p2 ) )
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( ridt, dpos, dpos2 );
|
|
}
|
|
else
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( rid, start, end );
|
|
}
|
|
}
|
|
pRoute->DeleteIfAllowed();
|
|
TupleId pSection = GetTupleIdSectionOnRoute ( gpp1 );
|
|
vector<DirectedSection> pAdjSect1;
|
|
vector<DirectedSection> pAdjSect2;
|
|
pAdjSect1.clear();
|
|
pAdjSect2.clear();
|
|
GetAdjacentSections ( pSection,true, pAdjSect1 );
|
|
GetAdjacentSections ( pSection,false, pAdjSect2 );
|
|
size_t j = 0;
|
|
Tuple *pCurrSect;
|
|
while ( j < pAdjSect1.size() )
|
|
{
|
|
DirectedSection actSection = pAdjSect1[j];
|
|
pCurrSect = m_pSections->GetTuple ( actSection.GetSectionTid(),
|
|
false );
|
|
rid = ( ( CcInt* ) pCurrSect->GetAttribute ( SECTION_RID ) )->GetIntval();
|
|
pCurrSect->DeleteIfAllowed();
|
|
pRoute = GetRoute ( rid );
|
|
pCurve = ( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE );
|
|
startSmaller =
|
|
((CcBool*)pRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
/*if ( ( chkPoint ( pCurve, p1, true, dpos, difference ) ) &&
|
|
( chkPoint ( pCurve, p2, true, dpos2, difference ) ) )*/
|
|
if (pCurve->AtPoint(p1, startSmaller,m_scalefactor, dpos) &&
|
|
pCurve->AtPoint(p2, startSmaller,m_scalefactor, dpos2))
|
|
{
|
|
start = dpos;
|
|
end = dpos2;
|
|
chkStartEndA ( start, end );
|
|
pAdjSect1.clear();
|
|
pAdjSect2.clear();
|
|
if ( ShorterConnection ( pRoute, start, end, dpos, dpos2,
|
|
rid, ridt, p1, p2 ) )
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( ridt, dpos, dpos2 );
|
|
}
|
|
else
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( rid, start, end );
|
|
}
|
|
}
|
|
j++;
|
|
pRoute->DeleteIfAllowed();
|
|
}
|
|
j = 0;
|
|
pAdjSect1.clear();
|
|
while ( j < pAdjSect2.size() )
|
|
{
|
|
DirectedSection actSection = pAdjSect2[j];
|
|
pCurrSect = m_pSections->GetTuple ( actSection.GetSectionTid(),
|
|
false );
|
|
rid = ( ( CcInt* ) pCurrSect->GetAttribute ( SECTION_RID ) )->GetIntval();
|
|
pCurrSect->DeleteIfAllowed();
|
|
pRoute = GetRoute ( rid );
|
|
pCurve = ( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE );
|
|
startSmaller =
|
|
((CcBool*)pRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
/*if ( ( chkPoint ( pCurve, p1, true, dpos, difference ) ) &&
|
|
( chkPoint ( pCurve, p2, true, dpos2, difference ) ) )*/
|
|
if (pCurve->AtPoint(p1, startSmaller,m_scalefactor, dpos) &&
|
|
pCurve->AtPoint(p2, startSmaller,m_scalefactor, dpos2))
|
|
{
|
|
start = dpos;
|
|
end = dpos2;
|
|
chkStartEndA ( start, end );
|
|
pAdjSect2.clear();
|
|
if ( ShorterConnection ( pRoute, start, end, dpos, dpos2,
|
|
rid, ridt, p1, p2 ) )
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( ridt, dpos, dpos2 );
|
|
}
|
|
else
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( rid, start, end );
|
|
}
|
|
}
|
|
j++;
|
|
pRoute->DeleteIfAllowed();
|
|
}//should never be reached
|
|
pAdjSect2.clear();
|
|
}//should never be reached
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
Returns the route interval for the connection from p1 to p2
|
|
|
|
*/
|
|
|
|
RouteInterval* Network::FindInterval ( const Point p1, const Point p2 )const
|
|
{
|
|
GPoint *gpp1 = GetNetworkPosOfPoint ( p1 );
|
|
GPoint *gpp2 = GetNetworkPosOfPoint ( p2 );
|
|
assert ( gpp1->IsDefined() && gpp2->IsDefined() );
|
|
int rid, ridt;
|
|
double start, end, dpos, dpos2;
|
|
if ( gpp1->GetRouteId() == gpp2->GetRouteId() )
|
|
{
|
|
rid = gpp1->GetRouteId();
|
|
start = gpp1->GetPosition();
|
|
end = gpp2->GetPosition();
|
|
Tuple *pRoute = GetRoute ( rid );
|
|
if ( ShorterConnection2 ( pRoute, start, end, dpos, dpos2, rid, ridt,
|
|
p1, p2) )
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( ridt, dpos, dpos2 );
|
|
}
|
|
else
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( rid, start, end );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Tuple *pRoute = GetRoute ( gpp1->GetRouteId() );
|
|
SimpleLine *pCurve =
|
|
( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE );
|
|
bool startSmaller =
|
|
((CcBool*)pRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
//if ( chkPoint ( pCurve, p2, true, dpos, difference ) )
|
|
if (pCurve->AtPoint(p2, startSmaller,m_scalefactor, dpos))
|
|
{
|
|
rid =
|
|
( ( CcInt* ) pRoute->GetAttribute ( ROUTE_ID ) )->GetIntval();
|
|
start = gpp1->GetPosition();
|
|
end = dpos;
|
|
if ( ShorterConnection2 ( pRoute, start, end, dpos, dpos2,
|
|
rid, ridt, p1, p2 ) )
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( ridt, dpos, dpos2 );
|
|
}
|
|
else
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( rid, start, end );
|
|
}
|
|
}
|
|
pRoute->DeleteIfAllowed();
|
|
pRoute = GetRoute ( gpp2->GetRouteId() );
|
|
pCurve = ( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE );
|
|
startSmaller =
|
|
((CcBool*)pRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
//if ( chkPoint ( pCurve, p1, true, dpos, difference ) )
|
|
if (pCurve->AtPoint(p1, startSmaller,m_scalefactor, dpos))
|
|
{
|
|
rid =
|
|
( ( CcInt* ) pRoute->GetAttribute ( ROUTE_ID ) )->GetIntval();
|
|
start = dpos;
|
|
end = gpp2->GetPosition();
|
|
if ( ShorterConnection2 ( pRoute, start, end, dpos, dpos2,
|
|
rid, ridt, p1, p2 ) )
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( ridt, dpos, dpos2 );
|
|
}
|
|
else
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( rid, start, end );
|
|
}
|
|
}
|
|
pRoute->DeleteIfAllowed();
|
|
TupleId pSection = GetTupleIdSectionOnRoute ( gpp1 );
|
|
vector<DirectedSection> pAdjSect1;
|
|
vector<DirectedSection> pAdjSect2;
|
|
pAdjSect1.clear();
|
|
pAdjSect2.clear();
|
|
GetAdjacentSections ( pSection,true, pAdjSect1 );
|
|
GetAdjacentSections ( pSection,false, pAdjSect2 );
|
|
size_t j = 0;
|
|
Tuple *pCurrSect;
|
|
while ( j < pAdjSect1.size() )
|
|
{
|
|
DirectedSection actSection = pAdjSect1[j];
|
|
pCurrSect = m_pSections->GetTuple ( actSection.GetSectionTid(), false );
|
|
rid = ( ( CcInt* ) pCurrSect->GetAttribute ( SECTION_RID ) )->GetIntval();
|
|
pCurrSect->DeleteIfAllowed();
|
|
pRoute = GetRoute ( rid );
|
|
pCurve = ( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE );
|
|
startSmaller =
|
|
((CcBool*)pRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
/*if ( ( chkPoint ( pCurve, p1, true, dpos, difference ) ) &&
|
|
( chkPoint ( pCurve, p2, true, dpos2, difference ) ) )*/
|
|
if (pCurve->AtPoint(p1, startSmaller,m_scalefactor, dpos) &&
|
|
pCurve->AtPoint(p2, startSmaller,m_scalefactor, dpos2))
|
|
{
|
|
start = dpos;
|
|
end = dpos2;
|
|
pAdjSect1.clear();
|
|
pAdjSect2.clear();
|
|
if ( ShorterConnection2 ( pRoute, start, end, dpos, dpos2,
|
|
rid, ridt, p1, p2 ) )
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( ridt, dpos, dpos2 );
|
|
}
|
|
else
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( rid, start, end );
|
|
}
|
|
}
|
|
j++;
|
|
pRoute->DeleteIfAllowed();
|
|
}
|
|
j = 0;
|
|
pAdjSect1.clear();
|
|
while ( j < pAdjSect2.size() )
|
|
{
|
|
DirectedSection actSection = pAdjSect2[j];
|
|
pCurrSect = m_pSections->GetTuple ( actSection.GetSectionTid(), false );
|
|
rid = ( ( CcInt* ) pCurrSect->GetAttribute ( SECTION_RID ) )->GetIntval();
|
|
pCurrSect->DeleteIfAllowed();
|
|
pRoute = GetRoute ( rid );
|
|
pCurve = ( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE );
|
|
startSmaller =
|
|
((CcBool*)pRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
/*if ( ( chkPoint ( pCurve, p1, true, dpos, difference ) ) &&
|
|
( chkPoint ( pCurve, p2, true, dpos2, difference ) ) )*/
|
|
if (pCurve->AtPoint(p1, startSmaller, m_scalefactor,dpos) &&
|
|
pCurve->AtPoint(p2, startSmaller, m_scalefactor,dpos2))
|
|
{
|
|
start = dpos;
|
|
end = dpos2;
|
|
pAdjSect2.clear();
|
|
if ( ShorterConnection2 ( pRoute, start, end, dpos, dpos2,
|
|
rid, ridt, p1, p2 ) )
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( ridt, dpos, dpos2 );
|
|
}
|
|
else
|
|
{
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
pRoute->DeleteIfAllowed();
|
|
return new RouteInterval ( rid, start, end );
|
|
}
|
|
}
|
|
j++;
|
|
pRoute->DeleteIfAllowed();
|
|
}//should never be reached
|
|
pAdjSect2.clear();
|
|
}//should never be reached
|
|
gpp1->DeleteIfAllowed();
|
|
gpp2->DeleteIfAllowed();
|
|
return 0;
|
|
}
|
|
|
|
|
|
void Network::GetTupleIdSectionOnRouteJun(const GPoint* in_xGPoint,
|
|
vector<TupleId>& res)const
|
|
{
|
|
|
|
CcInt *ciRouteId = new CcInt ( true, in_xGPoint->GetRouteId() );
|
|
BTreeIterator* pSectionIter =
|
|
m_pBTreeSectionsByRoute->ExactMatch ( ciRouteId );
|
|
delete ciRouteId;
|
|
Tuple *actSect = 0;
|
|
TupleId result;
|
|
while ( pSectionIter->Next() )
|
|
{
|
|
result = pSectionIter->GetId();
|
|
actSect = m_pSections->GetTuple ( pSectionIter->GetId(), false );
|
|
if ( actSect != 0 )
|
|
{
|
|
double start =
|
|
((CcReal*)actSect->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
double end =
|
|
((CcReal*)actSect->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
if(in_xGPoint->GetPosition() >= start&&in_xGPoint->GetPosition() <= end)
|
|
{
|
|
// delete pSectionIter;
|
|
// actSect->DeleteIfAllowed();
|
|
// return result;
|
|
res.push_back(result);
|
|
}
|
|
else
|
|
{
|
|
if ( AlmostEqualAbsolute ( in_xGPoint->GetPosition(), start,
|
|
m_scalefactor*0.01 ))
|
|
{
|
|
// delete pSectionIter;
|
|
// actSect->DeleteIfAllowed();
|
|
// return result;
|
|
res.push_back(result);
|
|
}
|
|
else
|
|
{
|
|
if ( AlmostEqualAbsolute ( in_xGPoint->GetPosition(), end,
|
|
m_scalefactor*0.01))
|
|
{
|
|
Tuple *pRoute = GetRoute(((TupleIdentifier* )
|
|
actSect->GetAttribute ( SECTION_RRC ))->GetTid() );
|
|
if ( AlmostEqualAbsolute(
|
|
((CcReal*)pRoute->GetAttribute ( ROUTE_LENGTH ) )->GetRealval(),
|
|
end, m_scalefactor*0.01 ))
|
|
{
|
|
// pRoute->DeleteIfAllowed();
|
|
// delete pSectionIter;
|
|
// actSect->DeleteIfAllowed();
|
|
res.push_back(result);
|
|
// return result;
|
|
}
|
|
pRoute->DeleteIfAllowed();
|
|
}
|
|
}
|
|
}
|
|
// actSect->DeleteIfAllowed();
|
|
}
|
|
actSect->DeleteIfAllowed();
|
|
}
|
|
delete pSectionIter;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
~Out~-function of type constructor ~network~
|
|
|
|
*/
|
|
ListExpr Network::Out ( ListExpr typeInfo )
|
|
{
|
|
//cout << "NetworkOut" << endl;
|
|
///////////////////////
|
|
// Output of all routes
|
|
GenericRelationIterator *pRoutesIter = m_pRoutes->MakeScan();
|
|
Tuple *pCurrentRoute = 0;
|
|
ListExpr xLast = nl->TheEmptyList();
|
|
ListExpr xNext = nl->TheEmptyList();
|
|
ListExpr xRoutes = nl->TheEmptyList();
|
|
bool bFirst = true;
|
|
|
|
while ( ( pCurrentRoute = pRoutesIter->GetNextTuple() ) != 0 )
|
|
{
|
|
// Read values from table
|
|
CcInt* pRouteId = ( CcInt* ) pCurrentRoute->GetAttribute ( ROUTE_ID );
|
|
int iRouteId = pRouteId->GetIntval();
|
|
CcReal* pLength = ( CcReal* ) pCurrentRoute->GetAttribute ( ROUTE_LENGTH );
|
|
double dLength = pLength->GetRealval();
|
|
SimpleLine *pCurve = ( SimpleLine* ) pCurrentRoute->GetAttribute (
|
|
ROUTE_CURVE );
|
|
// The list for the curve contains all segments of the curve.
|
|
ListExpr xCurve = OutSimpleLine ( nl->TheEmptyList(), SetWord ( pCurve ) );
|
|
CcBool* pDual = ( CcBool* ) pCurrentRoute->GetAttribute ( ROUTE_DUAL );
|
|
bool bDual= pDual->GetBoolval();
|
|
CcBool* pStartsSmaller;
|
|
pStartsSmaller = ( CcBool* ) pCurrentRoute->GetAttribute (
|
|
ROUTE_STARTSSMALLER );
|
|
bool bStartsSmaller = pStartsSmaller->GetBoolval();
|
|
|
|
// Build list
|
|
xNext = nl->FiveElemList ( nl->IntAtom ( iRouteId ),
|
|
nl->RealAtom ( dLength ),
|
|
xCurve,
|
|
nl->BoolAtom ( bDual ),
|
|
nl->BoolAtom ( bStartsSmaller ) );
|
|
|
|
// Create new list or append element to existing list
|
|
if ( bFirst )
|
|
{
|
|
xRoutes = nl->OneElemList ( xNext );
|
|
xLast = xRoutes;
|
|
bFirst = false;
|
|
}
|
|
else
|
|
{
|
|
xLast = nl->Append ( xLast, xNext );
|
|
}
|
|
pCurrentRoute->DeleteIfAllowed();
|
|
}
|
|
delete pRoutesIter;
|
|
|
|
///////////////////////
|
|
// Output of all junctions
|
|
GenericRelationIterator *pJunctionsIter = m_pJunctions->MakeScan();
|
|
Tuple *pCurrentJunction;
|
|
ListExpr xJunctions = nl->TheEmptyList();
|
|
bFirst = true;
|
|
|
|
while ( ( pCurrentJunction = pJunctionsIter->GetNextTuple() ) != 0 )
|
|
{
|
|
// Read values from table
|
|
CcInt* pRoute1Id;
|
|
pRoute1Id = ( CcInt* ) pCurrentJunction->GetAttribute ( JUNCTION_ROUTE1_ID
|
|
);
|
|
int iRoute1Id = pRoute1Id->GetIntval();
|
|
CcReal* pMeas1;
|
|
pMeas1 = ( CcReal* ) pCurrentJunction->GetAttribute ( JUNCTION_ROUTE1_MEAS
|
|
);
|
|
double dMeas1 = pMeas1->GetRealval();
|
|
CcInt* pRoute2Id;
|
|
pRoute2Id = ( CcInt* ) pCurrentJunction->GetAttribute ( JUNCTION_ROUTE2_ID
|
|
);
|
|
int iRoute2Id = pRoute2Id->GetIntval();
|
|
CcReal* pMeas2;
|
|
pMeas2 = ( CcReal* ) pCurrentJunction->GetAttribute ( JUNCTION_ROUTE2_MEAS
|
|
);
|
|
double dMeas2 = pMeas2->GetRealval();
|
|
CcInt* pConnectivityCode;
|
|
pConnectivityCode = ( CcInt* ) pCurrentJunction->GetAttribute ( JUNCTION_CC
|
|
);
|
|
int iConnectivityCode= pConnectivityCode->GetIntval();
|
|
Point* pPoint = ( Point* ) pCurrentJunction->GetAttribute ( JUNCTION_POS );
|
|
ListExpr xPoint = OutPoint ( nl->TheEmptyList(), SetWord ( pPoint ) );
|
|
|
|
// Build list
|
|
xNext = nl->SixElemList ( nl->IntAtom ( iRoute1Id ),
|
|
nl->RealAtom ( dMeas1 ),
|
|
nl->IntAtom ( iRoute2Id ),
|
|
nl->RealAtom ( dMeas2 ),
|
|
nl->IntAtom ( iConnectivityCode ),
|
|
xPoint );
|
|
|
|
// Create new list or append element to existing list
|
|
if ( bFirst )
|
|
{
|
|
xJunctions= nl->OneElemList ( xNext );
|
|
xLast = xJunctions;
|
|
bFirst = false;
|
|
}
|
|
else
|
|
{
|
|
xLast = nl->Append ( xLast, xNext );
|
|
}
|
|
pCurrentJunction->DeleteIfAllowed();
|
|
}
|
|
|
|
delete pJunctionsIter;
|
|
|
|
return nl->FourElemList ( nl->IntAtom ( m_iId ),
|
|
nl->RealAtom(m_scalefactor),
|
|
xRoutes,
|
|
xJunctions );
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
~Save~-function of type constructor ~network~
|
|
|
|
*/
|
|
ListExpr Network::Save ( SmiRecord& in_xValueRecord,
|
|
size_t& inout_iOffset,
|
|
const ListExpr in_xTypeInfo )
|
|
{
|
|
// Save id of the network
|
|
int iId = m_iId;
|
|
in_xValueRecord.Write ( &iId,
|
|
sizeof ( int ),
|
|
inout_iOffset );
|
|
inout_iOffset += sizeof ( int );
|
|
|
|
// Save scalefactor of the network
|
|
double iScale = m_scalefactor;
|
|
in_xValueRecord.Write ( &iScale,
|
|
sizeof ( double ),
|
|
inout_iOffset );
|
|
inout_iOffset += sizeof ( double );
|
|
// Save routes
|
|
ListExpr xType;
|
|
nl->ReadFromString ( routesTypeInfo, xType );
|
|
ListExpr xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
if ( !m_pRoutes->Save ( in_xValueRecord,
|
|
inout_iOffset,
|
|
xNumericType ) )
|
|
{
|
|
return false;
|
|
}
|
|
// Save junctions
|
|
nl->ReadFromString ( junctionsInternalTypeInfo, xType );
|
|
xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
if ( !m_pJunctions->Save ( in_xValueRecord,
|
|
inout_iOffset,
|
|
xNumericType ) )
|
|
{
|
|
return false;
|
|
}
|
|
// Save sections
|
|
nl->ReadFromString ( sectionsInternalTypeInfo, xType );
|
|
xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
if ( !m_pSections->Save ( in_xValueRecord,
|
|
inout_iOffset,
|
|
xNumericType ) )
|
|
{
|
|
return false;
|
|
}
|
|
// Save btree for routes
|
|
nl->ReadFromString ( routesBTreeTypeInfo, xType );
|
|
xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
if ( !m_pBTreeRoutes->Save ( in_xValueRecord,
|
|
inout_iOffset,
|
|
xNumericType ) )
|
|
{
|
|
return false;
|
|
}
|
|
// Save rtree for routes
|
|
|
|
if ( !m_pRTreeRoutes->Save ( in_xValueRecord,
|
|
inout_iOffset ) )
|
|
{
|
|
return false;
|
|
}
|
|
// Save first btree for junctions
|
|
nl->ReadFromString ( junctionsBTreeTypeInfo, xType );
|
|
xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
if ( !m_pBTreeJunctionsByRoute1->Save ( in_xValueRecord,
|
|
inout_iOffset,
|
|
xNumericType ) )
|
|
{
|
|
return false;
|
|
}
|
|
// Save second btree for junctions
|
|
nl->ReadFromString ( junctionsBTreeTypeInfo, xType );
|
|
xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
if ( !m_pBTreeJunctionsByRoute2->Save ( in_xValueRecord,
|
|
inout_iOffset,
|
|
xNumericType ) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
SecondoCatalog *ctlg = SecondoSystem::GetCatalog();
|
|
SmiRecordFile *rf = ctlg->GetFlobFile();
|
|
m_xAdjacencyList.saveToFile(rf, m_xAdjacencyList);
|
|
SmiSize offset = 0;
|
|
size_t bufsize = m_xAdjacencyList.headerSize();
|
|
char* buf = (char*) malloc(bufsize);
|
|
m_xAdjacencyList.serializeHeader(buf,offset);
|
|
assert(offset==bufsize);
|
|
in_xValueRecord.Write(buf, bufsize, inout_iOffset);
|
|
inout_iOffset += bufsize;
|
|
free(buf);
|
|
//save m_xSubAdjacencyList
|
|
//Flob *tmpSubAdjList = &m_xSubAdjacencyList;
|
|
// SmiRecordFile *rf1 = ctlg->GetFlobFile();
|
|
m_xSubAdjacencyList.saveToFile(rf, m_xSubAdjacencyList);
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
m_xSubAdjacencyList.serializeHeader(buf,offset);
|
|
assert(offset==bufsize);
|
|
in_xValueRecord.Write(buf,bufsize, inout_iOffset);
|
|
free(buf);
|
|
inout_iOffset += bufsize;
|
|
//save m_reverseAdjacencyList
|
|
m_reverseAdjacencyList.saveToFile(rf, m_reverseAdjacencyList);
|
|
offset = 0;
|
|
bufsize = m_reverseAdjacencyList.headerSize();
|
|
buf = (char*) malloc(bufsize);
|
|
m_reverseAdjacencyList.serializeHeader(buf,offset);
|
|
assert(offset==bufsize);
|
|
in_xValueRecord.Write(buf, bufsize, inout_iOffset);
|
|
inout_iOffset += bufsize;
|
|
free(buf);
|
|
//save m_reverseSubAdjacencyList
|
|
m_reverseSubAdjancencyList.saveToFile(rf, m_reverseSubAdjancencyList);
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
m_reverseSubAdjancencyList.serializeHeader(buf,offset);
|
|
assert(offset==bufsize);
|
|
in_xValueRecord.Write(buf,bufsize, inout_iOffset);
|
|
free(buf);
|
|
inout_iOffset += bufsize;
|
|
|
|
// Save btree for sections
|
|
nl->ReadFromString ( sectionsBTreeTypeInfo, xType );
|
|
xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
|
|
if ( !m_pBTreeSectionsByRoute->Save ( in_xValueRecord,
|
|
inout_iOffset,
|
|
xNumericType ) )
|
|
{
|
|
|
|
//cout << "cannot store BTree_sections" << endl;
|
|
|
|
return false;
|
|
}
|
|
|
|
//save distance storage
|
|
/*
|
|
nl->ReadFromString(distancestorageTypeInfo, xType);
|
|
xNumericType =SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!alldistance->Save(in_xValueRecord,
|
|
inout_iOffset,
|
|
xNumericType))
|
|
{
|
|
return false;
|
|
}
|
|
*/
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
~Open~-function of type constructor ~network~
|
|
|
|
*/
|
|
Network *Network::Open ( SmiRecord& in_xValueRecord,
|
|
size_t& inout_iOffset,
|
|
const ListExpr in_xTypeInfo )
|
|
{
|
|
//cout << "NetworkOpen" << endl;
|
|
// Create network
|
|
return new Network ( in_xValueRecord,
|
|
inout_iOffset,
|
|
in_xTypeInfo );
|
|
}
|
|
|
|
|
|
ListExpr Network::OutNetwork ( ListExpr typeInfo, Word value )
|
|
{
|
|
Network *n = ( Network* ) value.addr;
|
|
return n->Out ( typeInfo );
|
|
}
|
|
|
|
Word Network::InNetwork ( ListExpr in_xTypeInfo,
|
|
ListExpr in_xValue,
|
|
int in_iErrorPos,
|
|
ListExpr& inout_xErrorInfo,
|
|
bool& inout_bCorrect )
|
|
{
|
|
//cout << "inNetwork" << endl;
|
|
Network* pNetwork = new Network ( in_xValue,
|
|
in_iErrorPos,
|
|
inout_xErrorInfo,
|
|
inout_bCorrect );
|
|
|
|
if ( inout_bCorrect )
|
|
{
|
|
return SetWord ( pNetwork );
|
|
}
|
|
else
|
|
{
|
|
delete pNetwork;
|
|
return SetWord ( Address ( 0 ) );
|
|
}
|
|
}
|
|
|
|
Word Network::CreateNetwork ( const ListExpr typeInfo )
|
|
{
|
|
return SetWord ( new Network() );
|
|
}
|
|
|
|
void Network::CloseNetwork ( const ListExpr typeInfo, Word& w )
|
|
{
|
|
delete static_cast<Network*> ( w.addr );
|
|
w.addr = 0;
|
|
|
|
}
|
|
|
|
/*
|
|
~Clone~-function of type constructor ~network~
|
|
|
|
Not implemented yet.
|
|
|
|
*/
|
|
Word Network::CloneNetwork ( const ListExpr typeInfo, const Word& w )
|
|
{
|
|
return SetWord ( Address ( 0 ) );
|
|
}
|
|
|
|
void Network::DeleteNetwork ( const ListExpr typeInfo, Word& w )
|
|
{
|
|
Network* n = ( Network* ) w.addr;
|
|
//n->Destroy();
|
|
delete n;
|
|
w.addr = 0;
|
|
}
|
|
|
|
bool Network::CheckNetwork ( ListExpr type, ListExpr& errorInfo )
|
|
{
|
|
return ( nl->IsEqual ( type, "network" ) );
|
|
}
|
|
|
|
void* Network::CastNetwork ( void* addr )
|
|
{
|
|
return new (addr)Network;
|
|
}
|
|
|
|
bool Network::SaveNetwork ( SmiRecord& valueRecord,
|
|
size_t& offset,
|
|
const ListExpr typeInfo,
|
|
Word& value )
|
|
{
|
|
// cout << "Save Network" << endl;
|
|
Network *n = ( Network* ) value.addr;
|
|
return n->Save ( valueRecord, offset, typeInfo );
|
|
}
|
|
|
|
bool Network::OpenNetwork ( SmiRecord& valueRecord,
|
|
size_t& offset,
|
|
const ListExpr typeInfo,
|
|
Word& value )
|
|
{
|
|
value.addr = Network::Open ( valueRecord, offset, typeInfo );
|
|
return value.addr != 0;
|
|
}
|
|
|
|
int Network::SizeOfNetwork()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int Network::IsDefined() const
|
|
{
|
|
return m_bDefined;
|
|
}
|
|
|
|
GPoint* Network::GetNetworkPosOfPoint(const Point p) const
|
|
{
|
|
const Rectangle<2> orig = p.BoundingBox();
|
|
double minMax[]={ orig.MinD ( 0 ) - 1.0*m_scalefactor,
|
|
orig.MaxD ( 0 ) + 1.0*m_scalefactor,
|
|
orig.MinD ( 1 ) - 1.0*m_scalefactor,
|
|
orig.MaxD ( 1 ) + 1.0*m_scalefactor};
|
|
const Rectangle<2> bbox = Rectangle<2> ( true,minMax);
|
|
R_TreeLeafEntry<2,TupleId> res;
|
|
Tuple *pCurrRoute = 0;
|
|
if ( m_pRTreeRoutes->First ( bbox, res ) )
|
|
{
|
|
pCurrRoute = m_pRoutes->GetTuple ( res.info, false );
|
|
// pCurrRoute->PutAttribute(0, new TupleIdentifier(true, res.info));
|
|
}
|
|
else
|
|
{
|
|
GPoint *result = new GPoint ( false );
|
|
return result;
|
|
}
|
|
double dpos, mindiff, difference;
|
|
mindiff = numeric_limits<double>::max();
|
|
int minrid;
|
|
SimpleLine* pRouteCurve =
|
|
( SimpleLine* ) pCurrRoute->GetAttribute (ROUTE_CURVE );
|
|
bool startSmaller =
|
|
((CcBool*)pCurrRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
int rid = ( ( CcInt* ) pCurrRoute->GetAttribute ( ROUTE_ID ) )->GetIntval();
|
|
/*if ( chkPoint ( pRouteCurve, p, true, dpos, difference ) )*/
|
|
if (pRouteCurve->AtPoint(p ,startSmaller,m_scalefactor*0.01, dpos))
|
|
{
|
|
GPoint *result = new GPoint ( true, GetId(), rid, dpos, None );
|
|
pCurrRoute->DeleteIfAllowed();
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
minrid = rid;
|
|
mindiff = pRouteCurve->Distance(p,0);
|
|
pCurrRoute->DeleteIfAllowed();
|
|
pCurrRoute = 0;
|
|
while ( m_pRTreeRoutes->Next ( res ) )
|
|
{
|
|
pCurrRoute = m_pRoutes->GetTuple ( res.info, false );
|
|
pRouteCurve = ( SimpleLine* ) pCurrRoute->GetAttribute ( ROUTE_CURVE );
|
|
startSmaller =
|
|
((CcBool*)pCurrRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
rid = ( ( CcInt* ) pCurrRoute->GetAttribute ( ROUTE_ID ) )->GetIntval();
|
|
//if ( chkPoint ( pRouteCurve, p, true, dpos, difference ) )
|
|
if (pRouteCurve->AtPoint(p,startSmaller,m_scalefactor*0.01, dpos))
|
|
{
|
|
GPoint *result = new GPoint ( true, GetId(),
|
|
rid,
|
|
dpos, None );
|
|
pCurrRoute->DeleteIfAllowed();
|
|
return result;
|
|
}
|
|
difference = pRouteCurve->Distance(p,0);
|
|
if (difference < mindiff)
|
|
{
|
|
mindiff = difference;
|
|
minrid = rid;
|
|
}
|
|
pCurrRoute->DeleteIfAllowed();
|
|
pCurrRoute = 0;
|
|
}
|
|
/*
|
|
If no exact match route has been found map to the route nearest to the point.
|
|
At the place nearest to the point.
|
|
|
|
*/
|
|
pCurrRoute = GetRoute(minrid);
|
|
pRouteCurve = ( SimpleLine* ) pCurrRoute->GetAttribute ( ROUTE_CURVE );
|
|
startSmaller =
|
|
((CcBool*)pCurrRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
if (lastchkPoint03(pRouteCurve, p ,startSmaller, m_scalefactor*0.01,
|
|
dpos, difference))
|
|
{
|
|
GPoint *result = new GPoint ( true, GetId(),
|
|
minrid,
|
|
dpos, None );
|
|
pCurrRoute->DeleteIfAllowed();
|
|
return result;
|
|
}
|
|
GPoint *result = new GPoint ( false );
|
|
if (pCurrRoute != 0)
|
|
{
|
|
pCurrRoute->DeleteIfAllowed();
|
|
pCurrRoute = 0;
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
|
|
GPoint* Network::GetNetworkPosOfPointOnRoute(const Point p, const int rid) const
|
|
{
|
|
Tuple *pCurrRoute = GetRoute(rid);
|
|
if (pCurrRoute != 0)
|
|
{
|
|
double dpos;
|
|
SimpleLine* pRouteCurve =
|
|
( SimpleLine* ) pCurrRoute->GetAttribute (ROUTE_CURVE );
|
|
bool startSmaller =
|
|
((CcBool*)pCurrRoute->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
|
if (pRouteCurve->AtPoint(p, startSmaller,m_scalefactor*0.01, dpos))
|
|
{
|
|
pCurrRoute->DeleteIfAllowed();
|
|
return new GPoint ( true, GetId(), rid, dpos, None );
|
|
}
|
|
}
|
|
if (pCurrRoute != 0) pCurrRoute->DeleteIfAllowed();
|
|
return new GPoint(false);
|
|
}
|
|
|
|
/*
|
|
~GetJunctionsMeasForRoutes~
|
|
|
|
Returns the position of a junction on both routes building the junction.
|
|
|
|
*/
|
|
|
|
void Network::GetJunctionMeasForRoutes ( CcInt *pRoute1Id, CcInt *pRoute2Id,
|
|
double &rid1meas, double &rid2meas )const
|
|
{
|
|
CcInt *pCurrJuncR2id, *pCurrJuncR1id;
|
|
int iCurrJuncTupleR2id, iCurrJuncR1id, iRoute1Id, iRoute2Id;
|
|
CcReal *pRid1Meas, *pRid2Meas;
|
|
bool r1smallerr2, found;
|
|
BTreeIterator *pJunctionsIt;
|
|
if ( pRoute1Id->GetIntval() <= pRoute2Id->GetIntval() )
|
|
{
|
|
pJunctionsIt = m_pBTreeJunctionsByRoute1->ExactMatch ( pRoute1Id );
|
|
iRoute1Id = pRoute1Id->GetIntval();
|
|
iRoute2Id = pRoute2Id->GetIntval();
|
|
r1smallerr2 = true;
|
|
}
|
|
else
|
|
{
|
|
pJunctionsIt = m_pBTreeJunctionsByRoute1->ExactMatch ( pRoute2Id );
|
|
iRoute1Id = pRoute2Id->GetIntval();
|
|
iRoute2Id = pRoute1Id->GetIntval();
|
|
r1smallerr2 = false;
|
|
}
|
|
found = false;
|
|
while ( !found && pJunctionsIt->Next() )
|
|
{
|
|
Tuple *pCurrJuncTuple = m_pJunctions->GetTuple ( pJunctionsIt->GetId(),
|
|
false );
|
|
pCurrJuncR2id = ( CcInt* ) pCurrJuncTuple->GetAttribute ( JUNCTION_ROUTE2_ID
|
|
);
|
|
iCurrJuncTupleR2id = pCurrJuncR2id->GetIntval();
|
|
pCurrJuncR1id = ( CcInt* ) pCurrJuncTuple->GetAttribute ( JUNCTION_ROUTE1_ID
|
|
);
|
|
iCurrJuncR1id = pCurrJuncR1id->GetIntval();
|
|
if ( iCurrJuncTupleR2id == iRoute2Id && iCurrJuncR1id == iRoute1Id )
|
|
{
|
|
found = true;
|
|
if ( r1smallerr2 )
|
|
{
|
|
pRid1Meas = ( CcReal* ) pCurrJuncTuple->GetAttribute (
|
|
JUNCTION_ROUTE1_MEAS );
|
|
rid1meas = pRid1Meas->GetRealval();
|
|
pRid2Meas = ( CcReal* ) pCurrJuncTuple->GetAttribute (
|
|
JUNCTION_ROUTE2_MEAS );
|
|
rid2meas = pRid2Meas->GetRealval();
|
|
}
|
|
else
|
|
{
|
|
pRid1Meas = ( CcReal* ) pCurrJuncTuple->GetAttribute (
|
|
JUNCTION_ROUTE2_MEAS );
|
|
rid1meas = pRid1Meas->GetRealval();
|
|
pRid2Meas = ( CcReal* ) pCurrJuncTuple->GetAttribute (
|
|
JUNCTION_ROUTE1_MEAS );
|
|
rid2meas = pRid2Meas->GetRealval();
|
|
}
|
|
}
|
|
pCurrJuncTuple->DeleteIfAllowed();
|
|
}
|
|
delete pJunctionsIt;
|
|
if ( !found )
|
|
{
|
|
rid1meas = numeric_limits<double>::max();
|
|
rid2meas = numeric_limits<double>::max();
|
|
}
|
|
}
|
|
|
|
/*
|
|
Return sLine Value from RouteId
|
|
|
|
*/
|
|
|
|
void Network::GetLineValueOfRouteInterval ( const RouteInterval *in_ri,
|
|
SimpleLine *out_Line )const
|
|
{
|
|
CcInt* pRouteId = new CcInt ( true, in_ri->GetRouteId() );
|
|
BTreeIterator *pRoutesIter = m_pBTreeRoutes->ExactMatch ( pRouteId );
|
|
pRouteId->DeleteIfAllowed();
|
|
Tuple *pRoute = 0;
|
|
if ( pRoutesIter->Next() )
|
|
pRoute = m_pRoutes->GetTuple (pRoutesIter->GetId(), false);
|
|
assert ( pRoute != 0 );
|
|
SimpleLine* pLine = ( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE );
|
|
assert ( pLine != 0 );
|
|
bool startSmaller =(( CcBool*)pRoute->GetAttribute(ROUTE_STARTSSMALLER))
|
|
->GetBoolval();
|
|
pLine->SubLine ( min ( in_ri->GetStartPos(), in_ri->GetEndPos() ),
|
|
max ( in_ri->GetStartPos(), in_ri->GetEndPos() ),
|
|
startSmaller, *out_Line );
|
|
pRoute->DeleteIfAllowed();
|
|
delete pRoutesIter;
|
|
}
|
|
|
|
/*
|
|
Secondo TypeConstructor for class ~Network~
|
|
|
|
*/
|
|
|
|
struct networkInfo:ConstructorInfo{
|
|
networkInfo():ConstructorInfo(){
|
|
name = Network::BasicType();
|
|
signature = "-> NETWORK";
|
|
typeExample = Network::BasicType();
|
|
listRep = "(<id> <scale> <routes-relation><junctions-relation>)";
|
|
valueExample = "(1 1.0 (rel()) (rel()))";
|
|
remarks = "Datatype containing all network information.";
|
|
}
|
|
};
|
|
|
|
struct networkFunctions:ConstructorFunctions<Network>{
|
|
networkFunctions(){
|
|
in = Network::InNetwork;
|
|
out = Network::OutNetwork;
|
|
create = Network::CreateNetwork;
|
|
deletion = Network::DeleteNetwork;
|
|
open = Network::OpenNetwork;
|
|
save = Network::SaveNetwork;
|
|
close = Network::CloseNetwork;
|
|
clone = Network::CloneNetwork;
|
|
cast = Network::CastNetwork;
|
|
sizeOf = Network::SizeOfNetwork;
|
|
kindCheck = Network::CheckNetwork;
|
|
}
|
|
};
|
|
|
|
networkInfo neti;
|
|
networkFunctions nf;
|
|
TypeConstructor networkTC(neti,nf);
|
|
|
|
/*
|
|
3 class ~GLine~
|
|
|
|
3.1 Constructors
|
|
|
|
The simple constructor. Should not be used.
|
|
|
|
*/
|
|
GLine::GLine():Attribute()
|
|
{}
|
|
|
|
GLine::GLine(const bool def) : Attribute(def), m_xRouteIntervals(0)
|
|
{
|
|
SetDefined(def);
|
|
m_bSorted = false;
|
|
m_dLength = 0.0;
|
|
}
|
|
|
|
GLine::GLine (const int in_iSize ) :
|
|
Attribute(true),
|
|
m_xRouteIntervals ( in_iSize )
|
|
{
|
|
SetDefined(true);
|
|
m_bSorted = false;
|
|
m_dLength = 0.0;
|
|
}
|
|
|
|
GLine::GLine(const int networkId,
|
|
const bool sort,
|
|
const DbArray<RouteInterval> *rilist):
|
|
Attribute(sort), m_xRouteIntervals(rilist->Size())
|
|
{
|
|
m_iNetworkId = networkId;
|
|
m_bSorted = sort;
|
|
m_xRouteIntervals.copyFrom(*rilist);
|
|
m_dLength = 0.0;
|
|
RouteInterval ri;
|
|
for (int i = 0; i < rilist->Size(); i++)
|
|
{
|
|
rilist->Get(i,ri);
|
|
m_dLength = m_dLength + ri.Length();
|
|
}
|
|
}
|
|
|
|
GLine::GLine ( const GLine* in_xOther ) :
|
|
Attribute(in_xOther->IsDefined()),
|
|
m_xRouteIntervals ( 0 )
|
|
{
|
|
SetDefined(in_xOther->IsDefined());
|
|
m_bSorted = in_xOther->m_bSorted;
|
|
m_iNetworkId = in_xOther->m_iNetworkId;
|
|
m_dLength = 0.0;
|
|
// Iterate over all RouteIntervalls
|
|
for ( int i = 0; i < in_xOther->m_xRouteIntervals.Size(); i++ )
|
|
{
|
|
// Get next Interval
|
|
RouteInterval pCurrentInterval;
|
|
in_xOther->m_xRouteIntervals.Get ( i, pCurrentInterval );
|
|
|
|
int iRouteId = pCurrentInterval.GetRouteId();
|
|
double dStart = pCurrentInterval.GetStartPos();
|
|
double dEnd = pCurrentInterval.GetEndPos();
|
|
AddRouteInterval ( iRouteId,
|
|
dStart,
|
|
dEnd );
|
|
}
|
|
TrimToSize();
|
|
}
|
|
|
|
GLine::GLine ( ListExpr in_xValue,
|
|
int in_iErrorPos,
|
|
ListExpr& inout_xErrorInfo,
|
|
bool& inout_bCorrect ):
|
|
Attribute(true)
|
|
{
|
|
// Check the list
|
|
if ( ! ( nl->ListLength ( in_xValue ) == 2 ) )
|
|
{
|
|
string strErrorMessage = "GLine(): List length must be 2.";
|
|
inout_xErrorInfo = nl->Append ( inout_xErrorInfo,
|
|
nl->StringAtom ( strErrorMessage ) );
|
|
inout_bCorrect = false;
|
|
SetDefined(false);
|
|
m_bSorted = false;
|
|
return;
|
|
}
|
|
|
|
// Split into the two parts
|
|
ListExpr xNetworkIdList = nl->First ( in_xValue );
|
|
ListExpr xRouteIntervalList = nl->Second ( in_xValue );
|
|
|
|
// Check the parts
|
|
if ( !nl->IsAtom ( xNetworkIdList ) ||
|
|
nl->AtomType ( xNetworkIdList ) != IntType )
|
|
{
|
|
string strErrorMessage = "GLine(): Error while reading network-id.";
|
|
inout_xErrorInfo = nl->Append ( inout_xErrorInfo,
|
|
nl->StringAtom ( strErrorMessage ) );
|
|
SetDefined(false);
|
|
m_bSorted = false;
|
|
inout_bCorrect = false;
|
|
return;
|
|
}
|
|
|
|
m_iNetworkId = nl->IntValue ( xNetworkIdList );
|
|
m_dLength = 0.0;
|
|
if ( !nl->IsEmpty ( xRouteIntervalList ) )
|
|
{
|
|
// Iterate over all routes
|
|
|
|
while ( !nl->IsEmpty ( xRouteIntervalList ) )
|
|
{
|
|
ListExpr xCurrentRouteInterval = nl->First ( xRouteIntervalList );
|
|
xRouteIntervalList = nl->Rest ( xRouteIntervalList );
|
|
|
|
if ( nl->ListLength ( xCurrentRouteInterval ) != 3 ||
|
|
( !nl->IsAtom ( nl->First ( xCurrentRouteInterval ) ) ) ||
|
|
nl->AtomType ( nl->First ( xCurrentRouteInterval ) ) != IntType ||
|
|
( !nl->IsAtom ( nl->Second ( xCurrentRouteInterval ) ) ) ||
|
|
nl->AtomType ( nl->Second ( xCurrentRouteInterval ) ) != RealType
|
|
||
|
|
( !nl->IsAtom ( nl->Third ( xCurrentRouteInterval ) ) ) ||
|
|
nl->AtomType ( nl->Third ( xCurrentRouteInterval ) ) != RealType )
|
|
{
|
|
string strErrorMessage = "GLine(): Error while reading route-interval.";
|
|
inout_xErrorInfo = nl->Append ( inout_xErrorInfo,
|
|
nl->StringAtom ( strErrorMessage ) );
|
|
inout_bCorrect = false;
|
|
SetDefined(false);
|
|
m_bSorted = false;
|
|
return;
|
|
}
|
|
|
|
// Read attributes from list
|
|
// Read values from table
|
|
int iRouteId = nl->IntValue ( nl->First ( xCurrentRouteInterval ) );
|
|
double dStart = nl->RealValue ( nl->Second ( xCurrentRouteInterval ) );
|
|
double dEnd = nl->RealValue ( nl->Third ( xCurrentRouteInterval ) );
|
|
|
|
AddRouteInterval ( iRouteId,
|
|
dStart,
|
|
dEnd );
|
|
|
|
}
|
|
inout_bCorrect = true;
|
|
SetDefined(true);
|
|
m_bSorted = false;
|
|
}
|
|
else
|
|
{
|
|
SetDefined(false);
|
|
m_bSorted = false;
|
|
inout_bCorrect = true;
|
|
}
|
|
TrimToSize();
|
|
return;
|
|
}
|
|
|
|
/*
|
|
3.2 Methods of class ~GLine~
|
|
|
|
*/
|
|
void GLine::SetNetworkId (const int in_iNetworkId )
|
|
{
|
|
m_iNetworkId = in_iNetworkId;
|
|
SetDefined(true);
|
|
}
|
|
|
|
void GLine::AddRouteInterval ( const RouteInterval ri )
|
|
{
|
|
m_xRouteIntervals.Append ( ri );
|
|
m_dLength = m_dLength + fabs ( ri.GetEndPos() - ri.GetStartPos() );
|
|
|
|
}
|
|
|
|
void GLine::AddRouteInterval ( const int in_iRouteId,
|
|
const double in_dStart,
|
|
const double in_dEnd )
|
|
{
|
|
RouteInterval *ri = new RouteInterval ( in_iRouteId,
|
|
in_dStart,
|
|
in_dEnd );
|
|
AddRouteInterval ( *ri );
|
|
delete ri;
|
|
}
|
|
|
|
|
|
bool GLine::IsSorted() const
|
|
{
|
|
return m_bSorted;
|
|
}
|
|
|
|
void GLine::SetSorted (const bool in_bSorted )
|
|
{
|
|
m_bSorted = in_bSorted;
|
|
}
|
|
|
|
/*
|
|
Secondo Integration
|
|
|
|
*/
|
|
Word GLine::In ( const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct )
|
|
{
|
|
GLine* pGline = new GLine ( 0 );
|
|
if ( nl->ListLength ( instance ) == 0 )
|
|
{
|
|
correct = true;
|
|
pGline->SetDefined ( false );
|
|
return SetWord ( pGline );
|
|
}
|
|
if (nl->ListLength(instance) == 1 &&
|
|
listutils::isSymbol(instance,"undef"))
|
|
{
|
|
correct = true;
|
|
pGline->SetDefined ( false );
|
|
return SetWord ( pGline );
|
|
}
|
|
if ( nl->ListLength ( instance ) != 2 )
|
|
{
|
|
correct = false;
|
|
pGline->DeleteIfAllowed();
|
|
cmsg.inFunError ( "Expecting (networkid (list of routeintervals))" );
|
|
return SetWord ( Address ( 0 ) );
|
|
}
|
|
ListExpr FirstElem = nl->First ( instance );
|
|
ListExpr SecondElem = nl->Second ( instance );
|
|
if ( !nl->IsAtom ( FirstElem ) || (nl->AtomType(FirstElem) != IntType) )
|
|
{
|
|
correct = false;
|
|
pGline->DeleteIfAllowed();
|
|
cmsg.inFunError ( "Networkadress is not evaluable" );
|
|
return SetWord ( Address ( 0 ) );
|
|
}
|
|
pGline->SetNetworkId ( nl->IntValue ( FirstElem ) );
|
|
if ( nl->IsEmpty ( SecondElem ) )
|
|
{
|
|
correct = false;
|
|
pGline->DeleteIfAllowed();
|
|
return SetWord ( Address ( 0 ) );
|
|
}
|
|
while ( !nl->IsEmpty ( SecondElem ) )
|
|
{
|
|
ListExpr start = nl->First ( SecondElem );
|
|
SecondElem = nl->Rest ( SecondElem );
|
|
if ( nl->ListLength ( start ) != 3 )
|
|
{
|
|
correct = false;
|
|
pGline->DeleteIfAllowed();
|
|
cmsg.inFunError ( "Routeinterval incorrect.Expected list of 3 Elements."
|
|
);
|
|
return SetWord ( Address ( 0 ) );
|
|
}
|
|
ListExpr lrid = nl->First ( start );
|
|
ListExpr lpos1 = nl->Second ( start );
|
|
ListExpr lpos2 = nl->Third ( start );
|
|
if ( !nl->IsAtom ( lrid ) || (nl->AtomType ( lrid ) != IntType) ||
|
|
!nl->IsAtom ( lpos1 ) || (nl->AtomType(lpos1) != RealType) ||
|
|
!nl->IsAtom ( lpos2 ) || (nl->AtomType(lpos2) != RealType) )
|
|
{
|
|
correct = false;
|
|
pGline->DeleteIfAllowed();
|
|
cmsg.inFunError ( "Routeinterval should be list int, real, real." );
|
|
return SetWord ( Address ( 0 ) );
|
|
}
|
|
pGline->AddRouteInterval ( nl->IntValue ( lrid ),
|
|
nl->RealValue ( lpos1 ),
|
|
nl->RealValue ( lpos2 ) );
|
|
}
|
|
correct = true;
|
|
pGline->SetDefined(true);
|
|
pGline->TrimToSize();
|
|
return SetWord ( pGline );
|
|
}
|
|
|
|
ListExpr GLine::Out ( ListExpr in_xTypeInfo,
|
|
Word in_xValue )
|
|
{
|
|
GLine *pGline = ( GLine* ) in_xValue.addr;
|
|
if ( pGline == 0 || !pGline->IsDefined() )
|
|
{
|
|
return nl->SymbolAtom ( "undef" );
|
|
}
|
|
|
|
ListExpr xLast = nl->TheEmptyList();
|
|
ListExpr xNext = nl->TheEmptyList();
|
|
bool bFirst = true;
|
|
ListExpr xNetworkId = nl->IntAtom ( pGline->m_iNetworkId );
|
|
ListExpr xRouteIntervals = nl->TheEmptyList();
|
|
if (pGline->m_xRouteIntervals.Size() > 0)
|
|
{
|
|
|
|
// Iterate over all RouteIntervalls
|
|
for ( int i = 0; i < pGline->m_xRouteIntervals.Size(); i++ )
|
|
{
|
|
// Get next Interval
|
|
RouteInterval pCurrentInterval;
|
|
pGline->m_xRouteIntervals.Get ( i, pCurrentInterval );
|
|
|
|
// Build list
|
|
xNext = nl->ThreeElemList ( nl->IntAtom (pCurrentInterval.GetRouteId()),
|
|
nl->RealAtom (pCurrentInterval.GetStartPos()),
|
|
nl->RealAtom (pCurrentInterval.GetEndPos()));
|
|
|
|
// Create new list or append element to existing list
|
|
if ( bFirst )
|
|
{
|
|
xRouteIntervals = nl->OneElemList ( xNext );
|
|
xLast = xRouteIntervals;
|
|
bFirst = false;
|
|
}
|
|
else
|
|
{
|
|
xLast = nl->Append ( xLast, xNext );
|
|
}
|
|
}
|
|
}
|
|
return nl->TwoElemList ( xNetworkId,
|
|
xRouteIntervals );
|
|
}
|
|
|
|
Word GLine::Create ( const ListExpr typeInfo )
|
|
{
|
|
return SetWord ( new GLine ( true ) );
|
|
}
|
|
|
|
void GLine::Clear()
|
|
{
|
|
m_xRouteIntervals.clean();
|
|
SetSorted ( false );
|
|
m_dLength = 0.0;
|
|
}
|
|
|
|
void GLine::Delete ( const ListExpr typeInfo,
|
|
Word& w )
|
|
{
|
|
GLine *l = ( GLine* ) w.addr;
|
|
//if (l->del.refs == 1) l->m_xRouteIntervals.Destroy();
|
|
l->DeleteIfAllowed();
|
|
w.addr = 0;
|
|
}
|
|
|
|
void GLine::Close ( const ListExpr typeInfo,
|
|
Word& w )
|
|
{
|
|
( ( GLine* ) w.addr )->DeleteIfAllowed();
|
|
w.addr = 0;
|
|
}
|
|
|
|
Word GLine::CloneGLine ( const ListExpr typeInfo,
|
|
const Word& w )
|
|
{
|
|
return SetWord ( ( ( GLine* ) w.addr )->Clone() );
|
|
}
|
|
|
|
void GLine::SetLength(const double l)
|
|
{
|
|
m_dLength = l;
|
|
}
|
|
|
|
GLine* GLine::Clone() const
|
|
{
|
|
GLine *xOther = new GLine ( Size() );
|
|
xOther->SetDefined ( IsDefined() );
|
|
xOther->SetSorted ( m_bSorted );
|
|
xOther->SetNetworkId ( m_iNetworkId );
|
|
xOther->SetLength(m_dLength);
|
|
/*RouteInterval ri;
|
|
for ( int i = 0; i < Size(); i++ )
|
|
{
|
|
Get ( i, ri );
|
|
int rid = ri.GetRouteId();
|
|
double start = ri.GetStartPos();
|
|
double end = ri.GetEndPos();
|
|
xOther->AddRouteInterval ( rid, start, end );
|
|
}*/
|
|
xOther->m_xRouteIntervals.copyFrom(m_xRouteIntervals);
|
|
return xOther;
|
|
}
|
|
|
|
void* GLine::Cast ( void* addr )
|
|
{
|
|
return new ( addr ) GLine;
|
|
}
|
|
|
|
int GLine::Size() const
|
|
{
|
|
return m_xRouteIntervals.Size();
|
|
}
|
|
|
|
int GLine::SizeOf()
|
|
{
|
|
return sizeof ( GLine );
|
|
}
|
|
|
|
size_t GLine::Sizeof() const
|
|
{
|
|
return sizeof ( *this );
|
|
}
|
|
|
|
ostream& RouteInterval::Print(ostream& os) const
|
|
{
|
|
os << "RouteInterval: rid: " << m_iRouteId;
|
|
os << " from: " << m_dStart << " to: " << m_dEnd;
|
|
os << endl;
|
|
return os;
|
|
}
|
|
|
|
ostream& GLine::Print ( ostream& os ) const
|
|
{
|
|
if (IsDefined())
|
|
{
|
|
os << "GLine: NetworkId: " << m_iNetworkId << endl;
|
|
for ( int i = 0; i < m_xRouteIntervals.Size() ; i++ )
|
|
{
|
|
RouteInterval ri;
|
|
Get ( i, ri );
|
|
os << i <<". ";
|
|
ri.Print(os);
|
|
}
|
|
os << " end gline";
|
|
}
|
|
else
|
|
os <<"GLine: undef" << endl;
|
|
return os;
|
|
};
|
|
|
|
bool GLine::Adjacent ( const Attribute* arg ) const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Compare
|
|
|
|
*/
|
|
int GLine::Compare ( const Attribute* arg ) const
|
|
{
|
|
GLine *gl2 = ( GLine* ) arg;
|
|
if ( IsDefined() && !gl2->IsDefined() ) return 1;
|
|
else
|
|
if ( !IsDefined() && gl2->IsDefined() ) return -1;
|
|
else
|
|
if ( !IsDefined() && !gl2->IsDefined() ) return 0;
|
|
else
|
|
if ( m_dLength < gl2->m_dLength ) return -1;
|
|
else
|
|
if ( m_dLength > gl2->m_dLength ) return 1;
|
|
else
|
|
if ( m_xRouteIntervals.Size() < gl2->m_xRouteIntervals.Size() )
|
|
return -1;
|
|
else
|
|
if ( m_xRouteIntervals.Size() > gl2->m_xRouteIntervals.Size() )
|
|
return 1;
|
|
else
|
|
if ( *this == *gl2 ) return 0;
|
|
else
|
|
{
|
|
RouteInterval ri1, ri2;
|
|
int i = 0;
|
|
while ( i < m_xRouteIntervals.Size() )
|
|
{
|
|
Get ( i,ri1 );
|
|
gl2->Get ( i,ri2 );
|
|
if ( ri1.GetRouteId() < ri2.GetRouteId() ) return -1;
|
|
else
|
|
if ( ri1.GetRouteId() > ri2.GetRouteId() ) return 1;
|
|
else
|
|
if ( ri1.GetStartPos() < ri2.GetStartPos() ) return -1;
|
|
else
|
|
if ( ri1.GetStartPos() > ri2.GetStartPos() ) return 1;
|
|
else
|
|
if ( ri1.GetEndPos() < ri2.GetEndPos() ) return -1;
|
|
else
|
|
if ( ri1.GetEndPos() > ri2.GetEndPos() ) return 1;
|
|
i++;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
GLine& GLine::operator= ( const GLine& l )
|
|
{
|
|
SetDefined(l.IsDefined());
|
|
if (l.IsDefined())
|
|
{
|
|
m_xRouteIntervals.copyFrom(l.m_xRouteIntervals);
|
|
m_bSorted = l.m_bSorted;
|
|
m_iNetworkId = l.m_iNetworkId;
|
|
m_dLength=l.m_dLength;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
bool GLine::operator== ( const GLine& l ) const
|
|
{
|
|
if ( !IsDefined() || !l.IsDefined())
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
RouteInterval rIt, rIl;
|
|
if ( m_xRouteIntervals.Size() == l.m_xRouteIntervals.Size() &&
|
|
AlmostEqual ( m_dLength, l.m_dLength ) )
|
|
{
|
|
if ( m_bSorted && l.m_bSorted )
|
|
{
|
|
for ( int i=0; i < m_xRouteIntervals.Size(); i++ )
|
|
{
|
|
Get ( i,rIt );
|
|
l.Get ( i,rIl );
|
|
if ( ! ( rIt.GetRouteId() == rIl.GetRouteId() &&
|
|
rIt.GetStartPos() == rIl.GetStartPos() &&
|
|
rIt.GetEndPos() == rIl.GetEndPos() ) ) return false;
|
|
}
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
for ( int i=0; i < m_xRouteIntervals.Size(); i++ )
|
|
{
|
|
Get ( i,rIt );
|
|
for ( int j = 0; j < m_xRouteIntervals.Size(); j++ )
|
|
{
|
|
l.Get ( i,rIl );
|
|
if ( ! ( rIt.GetRouteId() == rIl.GetRouteId() &&
|
|
rIt.GetStartPos() == rIl.GetStartPos() &&
|
|
rIt.GetEndPos() == rIl.GetEndPos() ) ) return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
else return false;
|
|
}
|
|
}
|
|
|
|
size_t GLine::HashValue() const
|
|
{
|
|
size_t xHash = m_iNetworkId;
|
|
|
|
// Iterate over all RouteIntervalls
|
|
for ( int i = 0; i < m_xRouteIntervals.Size(); ++i )
|
|
{
|
|
// Get next Interval
|
|
RouteInterval pCurrentInterval;
|
|
m_xRouteIntervals.Get ( i, pCurrentInterval );
|
|
|
|
// Add something for each entry
|
|
int iRouteId = pCurrentInterval.GetRouteId();
|
|
double dStart = pCurrentInterval.GetStartPos();
|
|
double dEnd = pCurrentInterval.GetEndPos();
|
|
xHash += iRouteId + ( size_t ) dStart + ( size_t ) dEnd;
|
|
}
|
|
return xHash;
|
|
}
|
|
|
|
int GLine::NumOfFLOBs() const
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
Flob* GLine::GetFLOB ( const int i )
|
|
{
|
|
if ( i == 0 ) return &m_xRouteIntervals;
|
|
return 0;
|
|
}
|
|
|
|
DbArray<RouteInterval>* GLine::GetRouteIntervals() const
|
|
{
|
|
DbArray<RouteInterval> * res = new DbArray<RouteInterval>(0);
|
|
if ( IsDefined() )
|
|
{
|
|
res->copyFrom(m_xRouteIntervals);
|
|
return res;
|
|
}
|
|
else return 0;
|
|
};
|
|
|
|
void GLine::CopyFrom ( const Attribute* right )
|
|
{
|
|
*this = * ( ( const GLine * ) right );
|
|
}
|
|
|
|
double GLine::GetLength() const
|
|
{
|
|
return m_dLength;
|
|
}
|
|
|
|
int GLine::GetNetworkId() const
|
|
{
|
|
return m_iNetworkId;
|
|
};
|
|
|
|
/*
|
|
~Get~ returns the route interval at position i in the route intervals ~DbArray~.
|
|
|
|
*/
|
|
|
|
void GLine::Get ( const int i, RouteInterval &ri ) const
|
|
{
|
|
m_xRouteIntervals.Get ( i, ri );
|
|
};
|
|
|
|
int GLine::NoOfComponents() const
|
|
{
|
|
return m_xRouteIntervals.Size();
|
|
};
|
|
|
|
|
|
bool GLine::Check ( ListExpr type, ListExpr& errorInfo )
|
|
{
|
|
return ( nl->IsEqual ( type, GLine::BasicType() ) );
|
|
}
|
|
|
|
|
|
bool GLine::ShortestPathAStar(const GLine *to, GLine *result,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
result->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if (!IsDefined() || !to->IsDefined())
|
|
{
|
|
result->SetDefined(false);
|
|
return false;
|
|
}
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
bool bres = ShortestPathAStar(to,result,pNetwork, touchedSects);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return bres;
|
|
}
|
|
|
|
bool GLine::ShortestPathAStar (const GLine *pgl2, GLine *result,
|
|
const Network *pNetwork,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
result->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if ( GetNetworkId() != pgl2->GetNetworkId() )
|
|
{
|
|
cmsg.inFunError ( "Both glines must belong to the network." );
|
|
return false;
|
|
}
|
|
if (Intersects(pgl2))
|
|
{
|
|
result->SetDefined(true);
|
|
result->SetNetworkId(pNetwork->GetId());
|
|
return true;
|
|
}
|
|
GPoints *bGPgl1 = new GPoints(true);
|
|
GetBGP(pNetwork, bGPgl1);
|
|
GPoints *bGPgl2 = new GPoints(true);
|
|
pgl2->GetBGP(pNetwork,bGPgl2);
|
|
bool bres = bGPgl1->ShortestPathAStar(bGPgl2,result,pNetwork, touchedSects);
|
|
bGPgl1->DeleteIfAllowed();
|
|
bGPgl2->DeleteIfAllowed();
|
|
return bres;
|
|
}
|
|
|
|
bool GLine::ShortestPathAStar(const GPoint *to, GLine *result,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
result->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if (!IsDefined() || !to->IsDefined())
|
|
{
|
|
result->SetDefined(false);
|
|
return false;
|
|
}
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
bool bres = ShortestPathAStar(to, result, pNetwork, touchedSects);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return bres;
|
|
}
|
|
|
|
bool GLine::ShortestPathAStar(const GPoint *to, GLine *result,
|
|
const Network* pNetwork,
|
|
DbArray<TupleId>* touchedSects) const
|
|
{
|
|
result->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if ( GetNetworkId() != to->GetNetworkId() )
|
|
{
|
|
return false;
|
|
}
|
|
result->SetNetworkId(pNetwork->GetId());
|
|
if (to->Inside(this, pNetwork->GetScalefactor()*0.01))
|
|
{
|
|
result->SetDefined(true);
|
|
return true;
|
|
}
|
|
GPoints *bGPgl1 = new GPoints(true);
|
|
GetBGP(pNetwork, bGPgl1);
|
|
GPoints *bGPgl2 = new GPoints(true);
|
|
bGPgl2->MergeAdd(*to,pNetwork);
|
|
bool bres = bGPgl1->ShortestPathAStar(bGPgl2,result,pNetwork, touchedSects);
|
|
bGPgl1->DeleteIfAllowed();
|
|
bGPgl2->DeleteIfAllowed();
|
|
return bres;
|
|
}
|
|
|
|
bool GLine::ShortestPathAStar(const GPoints *to, GLine *result,
|
|
DbArray<TupleId>* touchedSects) const
|
|
{
|
|
result->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if (!IsDefined() || !to->IsDefined())
|
|
{
|
|
result->SetDefined(false);
|
|
return false;
|
|
}
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
bool bres = ShortestPathAStar(to, result, pNetwork, touchedSects);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return bres;
|
|
}
|
|
|
|
bool GLine::ShortestPathAStar(const GPoints *to, GLine *result,
|
|
const Network* pNetwork,
|
|
DbArray<TupleId>* touchedSects) const
|
|
{
|
|
result->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if ( GetNetworkId() != to->GetNetworkId() )
|
|
{
|
|
return false;
|
|
}
|
|
result->SetNetworkId(pNetwork->GetId());
|
|
if (Includes(to,pNetwork)) return true;
|
|
GPoints *bGPgl1 = new GPoints(true);
|
|
GetBGP(pNetwork, bGPgl1);
|
|
bool bres = bGPgl1->ShortestPathAStar(to,result,pNetwork, touchedSects);
|
|
bGPgl1->DeleteIfAllowed();
|
|
return bres;
|
|
}
|
|
|
|
/*
|
|
NetdistanceNew method computes the network distance between two glines.
|
|
Uses GPoints Netdistance
|
|
|
|
*/
|
|
double GLine::NetdistanceNew (const GLine* pgl2) const
|
|
{
|
|
double res = -1.0;
|
|
if (!IsDefined() || !pgl2->IsDefined() ||
|
|
NoOfComponents() < 1 || pgl2->NoOfComponents() < 1)
|
|
return -1.0;
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
res = NetdistanceNew(pgl2,pNetwork);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return res;
|
|
}
|
|
|
|
double GLine::NetdistanceNew (const GLine* pgl2, const Network* pNetwork)const
|
|
{
|
|
double res = -1.0;
|
|
if (!IsDefined() || !pgl2->IsDefined() ||
|
|
NoOfComponents() < 1 || pgl2->NoOfComponents() < 1 ||
|
|
GetNetworkId() != pgl2->GetNetworkId() )
|
|
return res;
|
|
if (Intersects(pgl2)) return 0.0;
|
|
GPoints *bGPgl1 = new GPoints(true);
|
|
GetBGP(pNetwork,bGPgl1);
|
|
GPoints *bGPgl2 = new GPoints(true);
|
|
pgl2->GetBGP(pNetwork,bGPgl2);
|
|
res = bGPgl1->NetdistanceNew(bGPgl2,pNetwork);
|
|
bGPgl1->DeleteIfAllowed();
|
|
bGPgl2->DeleteIfAllowed();
|
|
return res;
|
|
}
|
|
|
|
double GLine::NetdistanceNew(const GPoint* pgl2)const
|
|
{
|
|
double res = -1.0;
|
|
if (!IsDefined() || !pgl2->IsDefined() ||
|
|
NoOfComponents() < 1)
|
|
return res;
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
res = NetdistanceNew(pgl2,pNetwork);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return res;
|
|
}
|
|
|
|
double GLine::NetdistanceNew(const GPoint* pgl2, const Network* pNetwork) const
|
|
{
|
|
double res = -1.0;
|
|
if (!IsDefined() || !pgl2->IsDefined() ||
|
|
NoOfComponents() < 1 || GetNetworkId() != pgl2->GetNetworkId() )
|
|
return res;
|
|
if (pgl2->Inside(this,pNetwork->GetScalefactor()*0.01)) return 0.0;
|
|
GPoints *bGPgl1 = new GPoints(true);
|
|
GetBGP(pNetwork,bGPgl1);
|
|
GPoints *bGPgl2 = new GPoints(true);
|
|
bGPgl2->MergeAdd(*pgl2,pNetwork);
|
|
res = bGPgl1->NetdistanceNew(bGPgl2,pNetwork);
|
|
bGPgl1->DeleteIfAllowed();
|
|
bGPgl2->DeleteIfAllowed();
|
|
return res;
|
|
}
|
|
|
|
double GLine::NetdistanceNew(const GPoints* pgl2) const
|
|
{
|
|
double res = -1.0;
|
|
if (!IsDefined() || !pgl2->IsDefined() ||
|
|
NoOfComponents() < 1 || pgl2->Size() < 1)
|
|
return res;
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
res = NetdistanceNew(pgl2,pNetwork);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return res;
|
|
}
|
|
|
|
double GLine::NetdistanceNew(const GPoints* pgl2, const Network* pNetwork)const
|
|
{
|
|
double res = -1.0;
|
|
if (!IsDefined() || !pgl2->IsDefined() ||
|
|
NoOfComponents() < 1 || pgl2->Size() < 1 ||
|
|
GetNetworkId() != pgl2->GetNetworkId() )
|
|
return res;
|
|
if (Includes(pgl2, pNetwork)) return 0.0;
|
|
GPoints *bGPgl1 = new GPoints(true);
|
|
GetBGP(pNetwork,bGPgl1);
|
|
res = bGPgl1->NetdistanceNew(pgl2,pNetwork);
|
|
bGPgl1->DeleteIfAllowed();
|
|
return res;
|
|
}
|
|
|
|
double GLine::Netdistance(const GLine* pgl2)const
|
|
{
|
|
double res = -1.0;
|
|
if (!IsDefined()|| !pgl2->IsDefined() ||
|
|
NoOfComponents() < 1 || pgl2->NoOfComponents() < 1)
|
|
return res;
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
res = Netdistance(pgl2,pNetwork);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
Netdistance method computes the network distance between two glines. Uses
|
|
astar network distance method of ~GPoint~.
|
|
|
|
*/
|
|
|
|
double GLine::Netdistance ( const GLine* pgl2, const Network* pNetwork )const
|
|
{
|
|
double res = -1.0;
|
|
if ( GetNetworkId() != pgl2->GetNetworkId() )
|
|
{
|
|
cmsg.inFunError ( "Both glines must belong to the network." );
|
|
return res;
|
|
}
|
|
DbArray<TupleId>* touchedSects = 0;
|
|
GLine *path = new GLine(false);
|
|
if (ShortestPathBF(pgl2,path,pNetwork,touchedSects))
|
|
res = path->GetLength();
|
|
path->DeleteIfAllowed();
|
|
path = 0;
|
|
return res;
|
|
}
|
|
|
|
bool GLine::ShortestPathBF(const GLine *pgl2, GLine *result,
|
|
const Network *pNetwork,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
result->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if (!IsDefined()|| !pgl2->IsDefined() ||
|
|
NoOfComponents() < 1 || pgl2->NoOfComponents() < 1)
|
|
return false;
|
|
if ( GetNetworkId() != pgl2->GetNetworkId() )
|
|
return false;
|
|
result->SetNetworkId(GetNetworkId());
|
|
if (Intersects(pgl2))
|
|
return true;
|
|
GPoints *bGPgl1 = new GPoints(0);
|
|
GetBGP(pNetwork,bGPgl1);
|
|
GPoints *bGPgl2 = new GPoints(0);
|
|
pgl2->GetBGP(pNetwork,bGPgl2);
|
|
GPoint gp1, gp2;
|
|
bool first = true;
|
|
for ( int i = 0; i < bGPgl1->Size(); i++ )
|
|
{
|
|
bGPgl1->Get ( i,gp1 );
|
|
for ( int j = 0; j < bGPgl2->Size(); j++ )
|
|
{
|
|
bGPgl2->Get ( j, gp2 );
|
|
GLine *test = new GLine(false);
|
|
DbArray<TupleId> *testTouchedSects = new DbArray<TupleId> (0);
|
|
if (gp1.ShortestPathAStar(&gp2,test,pNetwork,testTouchedSects))
|
|
{
|
|
if (first)
|
|
*result = *test;
|
|
else
|
|
if (test->GetLength() < result->GetLength())
|
|
*result = *test;
|
|
test->DeleteIfAllowed();
|
|
test = 0;
|
|
if (result->GetLength() <= 0)
|
|
{
|
|
bGPgl1->DeleteIfAllowed();
|
|
bGPgl2->DeleteIfAllowed();
|
|
if (touchedSects != 0) touchedSects->Append(*testTouchedSects);
|
|
testTouchedSects->Destroy();
|
|
delete testTouchedSects;
|
|
return true;
|
|
}
|
|
}
|
|
if (touchedSects != 0) touchedSects->Append(*testTouchedSects);
|
|
testTouchedSects->Destroy();
|
|
delete testTouchedSects;
|
|
}
|
|
}
|
|
bGPgl1->DeleteIfAllowed();
|
|
bGPgl2->DeleteIfAllowed();
|
|
return true;
|
|
}
|
|
|
|
bool GLine::ShortestPathBF(const GLine *pgl2, GLine *result,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
result->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if (!IsDefined()|| !pgl2->IsDefined() ||
|
|
NoOfComponents() < 1 || pgl2->NoOfComponents() < 1)
|
|
return false;
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
bool res = ShortestPathBF(pgl2, result, pNetwork, touchedSects);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
Distance method computes the Euclidean Distance between two glines. Uses
|
|
distance method of ~GPoint~.
|
|
|
|
*/
|
|
|
|
double GLine::Distance ( const GLine* pgl2 )const
|
|
{
|
|
Line *l1 = new Line ( 0 );
|
|
Line *l2 = new Line ( 0 );
|
|
Gline2line ( l1 );
|
|
pgl2->Gline2line ( l2 );
|
|
if ( l1->IsDefined() && l2->IsDefined() )
|
|
{
|
|
double res = l1->Distance ( *l2 );
|
|
l1->DeleteIfAllowed();
|
|
l2->DeleteIfAllowed();
|
|
return res;
|
|
}
|
|
else return numeric_limits<double>::max();
|
|
}
|
|
|
|
/*
|
|
Computes the union of 2 glines.
|
|
|
|
*/
|
|
|
|
void GLine::Uniongl (const GLine *pgl2, GLine *res )const
|
|
{
|
|
RouteInterval pRi1, pRi2;
|
|
if ( !IsDefined() || NoOfComponents() == 0 )
|
|
{
|
|
if ( pgl2->IsDefined() && pgl2->NoOfComponents() > 0 )
|
|
{
|
|
if ( pgl2->IsSorted() )
|
|
{
|
|
for ( int j = 0; j < pgl2->NoOfComponents(); j++ )
|
|
{
|
|
pgl2->Get ( j,pRi2 );
|
|
res->AddRouteInterval ( pRi2.GetRouteId(),
|
|
pRi2.GetStartPos(),
|
|
pRi2.GetEndPos() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pgl2->Get ( 0,pRi2 );
|
|
RITree *ritree = new RITree ( pRi2.GetRouteId(),
|
|
pRi2.GetStartPos(), pRi2.GetEndPos(),0,0
|
|
);
|
|
for ( int j = 1; j < pgl2->NoOfComponents(); j++ )
|
|
{
|
|
pgl2->Get ( j,pRi2 );
|
|
ritree->Insert ( pRi2.GetRouteId(), pRi2.GetStartPos(),
|
|
pRi2.GetEndPos() );
|
|
}
|
|
ritree->TreeToGLine ( res );
|
|
ritree->RemoveTree();
|
|
}
|
|
res->SetDefined ( true );
|
|
res->SetSorted ( true );
|
|
res->SetNetworkId ( pgl2->GetNetworkId() );
|
|
}
|
|
else
|
|
{
|
|
res->SetDefined ( false );
|
|
res->SetSorted ( false );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !pgl2->IsDefined() || pgl2->NoOfComponents() == 0 )
|
|
{
|
|
if ( IsDefined() && NoOfComponents() >0 )
|
|
{
|
|
if ( IsSorted() )
|
|
{
|
|
for ( int i = 0; i < NoOfComponents(); i++ )
|
|
{
|
|
Get ( i,pRi1 );
|
|
res->AddRouteInterval ( pRi1.GetRouteId(),
|
|
pRi1.GetStartPos(),
|
|
pRi1.GetEndPos() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Get ( 0,pRi1 );
|
|
RITree *ritree = new RITree ( pRi1.GetRouteId(),
|
|
pRi1.GetStartPos(), pRi1.GetEndPos(),0,0
|
|
);
|
|
for ( int i = 1; i < NoOfComponents(); i++ )
|
|
{
|
|
Get ( i,pRi1 );
|
|
ritree->Insert ( pRi1.GetRouteId(), pRi1.GetStartPos(),
|
|
pRi1.GetEndPos() );
|
|
}
|
|
ritree->TreeToGLine ( res );
|
|
ritree->RemoveTree();
|
|
}
|
|
res->SetDefined ( true );
|
|
res->SetSorted ( true );
|
|
res->SetNetworkId ( GetNetworkId() );
|
|
}
|
|
else
|
|
{
|
|
res->SetDefined ( false );
|
|
res->SetSorted ( false );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( GetNetworkId() != pgl2->GetNetworkId() )
|
|
{
|
|
res->SetDefined ( false );
|
|
res->SetSorted ( false );
|
|
}
|
|
else
|
|
{
|
|
res->SetNetworkId ( GetNetworkId() );
|
|
if ( IsSorted() && pgl2->IsSorted() )
|
|
{
|
|
int i=0;
|
|
int j=0;
|
|
bool newroute = false;
|
|
int iRouteId;
|
|
double start, end;
|
|
while ( i < NoOfComponents() && j < pgl2->NoOfComponents() )
|
|
{
|
|
Get ( i, pRi1 );
|
|
pgl2->Get ( j, pRi2 );
|
|
if ( pRi1.GetRouteId() < pRi2.GetRouteId() )
|
|
{
|
|
res->AddRouteInterval ( pRi1.GetRouteId(),
|
|
pRi1.GetStartPos(),
|
|
pRi1.GetEndPos() );
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
if ( pRi1.GetRouteId() > pRi2.GetRouteId() )
|
|
{
|
|
res->AddRouteInterval ( pRi2.GetRouteId(), pRi2.GetStartPos(),
|
|
pRi2.GetEndPos() );
|
|
j++;
|
|
}
|
|
else
|
|
{
|
|
if ( pRi1.GetEndPos() < pRi2.GetStartPos() )
|
|
{
|
|
res->AddRouteInterval ( pRi1.GetRouteId(), pRi1.GetStartPos(),
|
|
pRi1.GetEndPos() );
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
if ( pRi2.GetEndPos() < pRi1.GetStartPos() )
|
|
{
|
|
res->AddRouteInterval ( pRi2.GetRouteId(),
|
|
pRi2.GetStartPos(),
|
|
pRi2.GetEndPos() );
|
|
j++;
|
|
}
|
|
else
|
|
{
|
|
iRouteId = pRi1.GetRouteId();
|
|
start = min ( pRi1.GetStartPos(), pRi2.GetStartPos() ),
|
|
end = max ( pRi1.GetEndPos(), pRi2.GetEndPos() );
|
|
i++;
|
|
j++;
|
|
newroute = false;
|
|
while ( i < NoOfComponents() && !newroute )
|
|
{
|
|
Get ( i,pRi1 );
|
|
if ( pRi1.GetRouteId() == iRouteId )
|
|
{
|
|
if ( pRi1.GetStartPos() <= end )
|
|
{
|
|
end = max ( pRi1.GetEndPos(), end );
|
|
i++;
|
|
}
|
|
else newroute = true;
|
|
}
|
|
else newroute = true;
|
|
}
|
|
newroute = false;
|
|
while ( j < pgl2->NoOfComponents() && !newroute )
|
|
{
|
|
pgl2->Get ( j,pRi2 );
|
|
if ( pRi2.GetRouteId() == iRouteId )
|
|
{
|
|
if ( pRi2.GetStartPos() <= end )
|
|
{
|
|
end = max ( pRi2.GetEndPos(), end );
|
|
j++;
|
|
}
|
|
else newroute = true;
|
|
}
|
|
else newroute = true;
|
|
}
|
|
res->AddRouteInterval ( iRouteId, start, end );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
while ( i < NoOfComponents() )
|
|
{
|
|
Get ( i,pRi1 );
|
|
res->AddRouteInterval ( pRi1.GetRouteId(),
|
|
pRi1.GetStartPos(),
|
|
pRi1.GetEndPos() );
|
|
i++;
|
|
}
|
|
while ( j < pgl2->NoOfComponents() )
|
|
{
|
|
pgl2->Get ( j,pRi2 );
|
|
res->AddRouteInterval ( pRi2.GetRouteId(), pRi2.GetStartPos(),
|
|
pRi2.GetEndPos() );
|
|
j++;
|
|
}
|
|
res->SetDefined ( true );
|
|
res->SetSorted ( true );
|
|
}
|
|
else
|
|
{
|
|
RITree *ritree;
|
|
Get ( 0,pRi1 );
|
|
ritree = new RITree ( pRi1.GetRouteId(),
|
|
pRi1.GetStartPos(), pRi1.GetEndPos(),0,0 );
|
|
for ( int i = 1; i < NoOfComponents(); i++ )
|
|
{
|
|
Get ( i,pRi1 );
|
|
ritree->Insert ( pRi1.GetRouteId(), pRi1.GetStartPos(),
|
|
pRi1.GetEndPos() );
|
|
}
|
|
for ( int j = 0; j < pgl2->NoOfComponents(); j++ )
|
|
{
|
|
pgl2->Get ( j,pRi2 );
|
|
ritree->Insert ( pRi2.GetRouteId(), pRi2.GetStartPos(),
|
|
pRi2.GetEndPos() );
|
|
}
|
|
ritree->TreeToGLine ( res );
|
|
ritree->RemoveTree();
|
|
res->SetDefined ( true );
|
|
res->SetSorted ( true );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
res->TrimToSize();
|
|
}
|
|
|
|
|
|
void GLine::Gline2line ( Line* res )const
|
|
{
|
|
res->Clear();
|
|
if ( IsDefined() && NoOfComponents() > 0 )
|
|
{
|
|
//Network* pNetwork = NetworkManager::GetNetwork(GetNetworkId());
|
|
Network* pNetwork =
|
|
NetworkManager::GetNetworkNew ( GetNetworkId(), netList);
|
|
RouteInterval rI;
|
|
Line l(0);
|
|
Line x = l;
|
|
for ( int i=0; i < this->NoOfComponents(); i++ )
|
|
{
|
|
this->Get ( i,rI );
|
|
SimpleLine *pSubline = new SimpleLine ( 0 );
|
|
pNetwork->GetLineValueOfRouteInterval ( &rI, pSubline );
|
|
if ( pSubline->IsDefined() )
|
|
{
|
|
Line partLine(0);
|
|
pSubline->toLine ( partLine );
|
|
pSubline->DeleteIfAllowed();
|
|
l.Union(partLine,x);
|
|
l = x;
|
|
}
|
|
}
|
|
NetworkManager::CloseNetwork ( pNetwork );
|
|
( *res ) = x;
|
|
res->SetDefined ( true );
|
|
}
|
|
else
|
|
{
|
|
if ( IsDefined() && NoOfComponents() == 0 )
|
|
{
|
|
res->SetDefined ( true );
|
|
}
|
|
else
|
|
{
|
|
res->SetDefined ( false );
|
|
}
|
|
}
|
|
res->TrimToSize();
|
|
}
|
|
|
|
bool GLine::Intersects (const RouteInterval* ri, const double tolerance)const
|
|
{
|
|
if (IsSorted())
|
|
{
|
|
return searchUnit(this, 0, NoOfComponents()-1, *ri);
|
|
}
|
|
else
|
|
{
|
|
RouteInterval rigl;
|
|
for (int i = 0; i < NoOfComponents(); i++)
|
|
{
|
|
Get(i,rigl);
|
|
if (ri->Intersects(&rigl, tolerance)) return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool GLine::Intersects ( const GLine *pgl )const
|
|
{
|
|
RouteInterval pRi1, pRi2;
|
|
if ( !IsSorted() )
|
|
{
|
|
for ( int i = 0; i < NoOfComponents(); i++ )
|
|
{
|
|
Get ( i, pRi1 );
|
|
if ( pgl->IsSorted() )
|
|
{
|
|
if ( searchUnit ( pgl, 0, pgl->NoOfComponents()-1, pRi1 ) )
|
|
{
|
|
return true;
|
|
};
|
|
}
|
|
else
|
|
{
|
|
for ( int j = 0 ; j < pgl->NoOfComponents(); j ++ )
|
|
{
|
|
pgl->Get ( j,pRi2 );
|
|
if ( pRi1.GetRouteId() == pRi2.GetRouteId() &&
|
|
((!( pRi1.GetEndPos() < pRi2.GetStartPos() ||
|
|
pRi2.GetStartPos() > pRi1.GetEndPos() )) ||
|
|
(!(pRi2.GetEndPos() < pRi1.GetStartPos() ||
|
|
pRi2.GetStartPos() > pRi1.GetEndPos() ))))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
if ( pgl->IsSorted() )
|
|
{
|
|
int i = 0;
|
|
int j = 0;
|
|
while ( i<NoOfComponents() && j < pgl->NoOfComponents() )
|
|
{
|
|
Get ( i,pRi1 );
|
|
pgl->Get ( j,pRi2 );
|
|
if ( pRi1.GetRouteId() < pRi2.GetRouteId() ) i++;
|
|
else
|
|
if ( pRi1.GetRouteId() > pRi2.GetRouteId() ) j++;
|
|
else
|
|
if ( pRi1.GetStartPos() > pRi2.GetEndPos() ) j++;
|
|
else
|
|
if ( pRi1.GetEndPos() < pRi2.GetStartPos() ) i++;
|
|
else return true;
|
|
}
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
for ( int i = 0; i < pgl->NoOfComponents(); i++ )
|
|
{
|
|
pgl->Get ( i, pRi2 );
|
|
if ( searchUnit ( this, 0, NoOfComponents()-1, pRi2 ) ) return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool GLine::Includes(const GPoints* gps) const
|
|
{
|
|
bool res = false;
|
|
if (!IsDefined() || !gps->IsDefined() ||
|
|
NoOfComponents() < 1 || gps->Size() < 1)
|
|
return res;
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
res = Includes(gps,pNetwork);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return res;
|
|
}
|
|
|
|
bool GLine::Includes(const GPoints* gps, const Network* pNetwork) const
|
|
{
|
|
bool res = false;
|
|
if (!IsDefined() || !gps->IsDefined() ||
|
|
NoOfComponents() < 1 || gps->Size() < 1)
|
|
return res;
|
|
for (int i = 0; i < gps->Size() ; i++)
|
|
{
|
|
GPoint gp;
|
|
gps->Get(i,gp);
|
|
GPointList* aliasGPoints = new GPointList(&gp,pNetwork);
|
|
GPoint test = aliasGPoints->NextGPoint();
|
|
while (test.IsDefined() && !res)
|
|
{
|
|
if (test.Inside(this, pNetwork->GetScalefactor()*0.01)) res = true;
|
|
test = aliasGPoints->NextGPoint();
|
|
}
|
|
aliasGPoints->Destroy();
|
|
delete aliasGPoints;
|
|
if (res) break;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
Secondo Type Constructor for class ~GLine~
|
|
|
|
*/
|
|
|
|
struct glineInfo:ConstructorInfo{
|
|
glineInfo(){
|
|
name = GLine::BasicType();
|
|
signature = "-> DATA";
|
|
typeExample = GLine::BasicType();
|
|
listRep = "(<netId> <list of routeintervals>)";
|
|
valueExample = "(1 ((23 34.8 435.3)(...)))";
|
|
remarks = "Route interval: (<routeid><startpos><endpos>)";
|
|
}
|
|
};
|
|
|
|
struct glineFunctions:ConstructorFunctions<GLine>{
|
|
glineFunctions(){
|
|
in = GLine::In;
|
|
out = GLine::Out;
|
|
create = GLine::Create;
|
|
deletion = GLine::Delete;
|
|
open = OpenAttribute<GLine>;
|
|
save = SaveAttribute<GLine>;
|
|
close = GLine::Close;
|
|
clone = GLine::CloneGLine;
|
|
cast = GLine::Cast;
|
|
sizeOf = GLine::SizeOf;
|
|
kindCheck = GLine::Check;
|
|
}
|
|
};
|
|
|
|
glineInfo gli;
|
|
glineFunctions glf;
|
|
TypeConstructor glineTC(gli,glf);
|
|
|
|
|
|
/*
|
|
4 class ~GPoint~
|
|
|
|
4.1 Constructors
|
|
|
|
See ~network.h~ class definition of ~GPoint~
|
|
|
|
4.2 Methods of class ~GPoint~
|
|
|
|
*/
|
|
Word GPoint::InGPoint ( const ListExpr typeInfo,
|
|
const ListExpr instance,
|
|
const int errorPos,
|
|
ListExpr& errorInfo,
|
|
bool& correct )
|
|
{
|
|
if ( nl->ListLength ( instance ) == 4 )
|
|
{
|
|
if ( nl->IsAtom ( nl->First ( instance ) ) &&
|
|
nl->AtomType ( nl->First ( instance ) ) == IntType &&
|
|
nl->IsAtom ( nl->Second ( instance ) ) &&
|
|
nl->AtomType ( nl->Second ( instance ) ) == IntType &&
|
|
nl->IsAtom ( nl->Third ( instance ) ) &&
|
|
nl->AtomType ( nl->Third ( instance ) ) == RealType &&
|
|
nl->IsAtom ( nl->Fourth ( instance ) ) &&
|
|
nl->AtomType ( nl->Fourth ( instance ) ) == IntType )
|
|
{
|
|
GPoint *gp = new GPoint (
|
|
true,
|
|
nl->IntValue ( nl->First ( instance ) ),
|
|
nl->IntValue ( nl->Second ( instance ) ),
|
|
nl->RealValue ( nl->Third ( instance ) ),
|
|
( Side ) nl->IntValue ( nl->Fourth ( instance ) ) );
|
|
correct = true;
|
|
return SetWord ( gp );
|
|
}
|
|
}
|
|
if (nl->IsEqual(instance, Symbol::UNDEFINED() ))
|
|
{
|
|
correct = true;
|
|
return SetWord ( new GPoint(false));
|
|
}
|
|
|
|
correct = false;
|
|
return SetWord ( Address ( 0 ) );
|
|
}
|
|
|
|
ListExpr GPoint::OutGPoint ( ListExpr typeInfo, Word value )
|
|
{
|
|
GPoint *gp = ( GPoint* ) value.addr;
|
|
|
|
if ( gp->IsDefined() )
|
|
{
|
|
return nl->FourElemList (
|
|
nl->IntAtom ( gp->GetNetworkId() ),
|
|
nl->IntAtom ( gp->GetRouteId() ),
|
|
nl->RealAtom ( gp->GetPosition() ),
|
|
nl->IntAtom ( gp->GetSide() ) );
|
|
}
|
|
return nl->SymbolAtom ( Symbol::UNDEFINED());
|
|
}
|
|
|
|
Word GPoint::CreateGPoint ( const ListExpr typeInfo )
|
|
{
|
|
return SetWord ( new GPoint ( true ) );
|
|
}
|
|
|
|
void GPoint::DeleteGPoint ( const ListExpr typeInfo, Word& w )
|
|
{
|
|
GPoint *gp = ( GPoint* ) w.addr;
|
|
if (gp->DeleteIfAllowed()) w.addr = 0;
|
|
}
|
|
|
|
void GPoint::CloseGPoint ( const ListExpr typeInfo, Word& w )
|
|
{
|
|
GPoint *gp = ( GPoint* ) w.addr;
|
|
if(gp->DeleteIfAllowed()) w.addr = 0;
|
|
}
|
|
|
|
Word GPoint::CloneGPoint ( const ListExpr typeInfo, const Word& w )
|
|
{
|
|
return SetWord ( ( ( GPoint* ) w.addr )->Clone() );
|
|
}
|
|
|
|
void* GPoint::CastGPoint ( void* addr )
|
|
{
|
|
return new ( addr ) GPoint;
|
|
}
|
|
|
|
int GPoint::SizeOfGPoint()
|
|
{
|
|
return sizeof ( GPoint );
|
|
}
|
|
|
|
bool GPoint::CheckGPoint ( ListExpr type, ListExpr& errorInfo )
|
|
{
|
|
return ( nl->IsEqual ( type, GPoint::BasicType() ) );
|
|
}
|
|
|
|
/*
|
|
Netdistance function computes the network distance between two ~GPoint~s.
|
|
Using Dijkstras-Algorithm for shortest path computing
|
|
|
|
*/
|
|
|
|
double GPoint::Netdistance ( const GPoint* pToGPoint)const
|
|
{
|
|
if (!IsDefined() || !pToGPoint->IsDefined())
|
|
return -1.0;
|
|
GLine* pGLine = new GLine ( 0 );
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
double res = -1.0;
|
|
if ( ShortestPath ( pToGPoint, pGLine, pNetwork, 0 ) )
|
|
res = pGLine->GetLength();
|
|
pGLine->DeleteIfAllowed();
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return res;
|
|
}
|
|
|
|
double GPoint::NetdistanceNew(const GPoint* pToGPoint, const Network* pNetwork)
|
|
const
|
|
{
|
|
GLine* pGLine = new GLine ( 0 );
|
|
double res = -1.0;
|
|
if ( ShortestPathAStar ( pToGPoint, pGLine, pNetwork,0 ) )
|
|
res = pGLine->GetLength();
|
|
pGLine->DeleteIfAllowed();
|
|
return res;
|
|
}
|
|
|
|
double GPoint::NetdistanceNew ( const GPoint* pToGPoint )const
|
|
{
|
|
double result = -1.0;
|
|
if (!IsDefined() || !pToGPoint->IsDefined())
|
|
return result;
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
result = NetdistanceNew(pToGPoint,pNetwork);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return result;
|
|
}
|
|
|
|
double GPoint::NewNetdistance ( const GPoint* pToGPoint, GLine* gline ) const
|
|
{
|
|
GPoint* gp1 = new GPoint ( true,GetNetworkId(),GetRouteId(),GetPosition() );
|
|
GPoint* gp2 = new GPoint ( true,pToGPoint->GetNetworkId(),
|
|
pToGPoint->GetRouteId(),pToGPoint->GetPosition() );
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
double res = 0.0;
|
|
if ( gp1->ShortestPath ( gp2, gline, pNetwork, 0 ) )
|
|
res = gline->GetLength();
|
|
gp1->DeleteIfAllowed();
|
|
gp2->DeleteIfAllowed();
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return res;
|
|
}
|
|
|
|
double GPoint::NetdistanceNew (const GLine* toGLine)const
|
|
{
|
|
double res = -1.0;
|
|
if (!IsDefined() || !toGLine->IsDefined() || toGLine->NoOfComponents() < 1 ||
|
|
GetNetworkId() != toGLine->GetNetworkId())
|
|
return res;
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
res = NetdistanceNew(toGLine,pNetwork);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return res;
|
|
}
|
|
|
|
double GPoint::NetdistanceNew (const GLine* toGLine, const Network* pNetwork)
|
|
const
|
|
{
|
|
double res = -1.0;
|
|
if (!IsDefined() || !toGLine->IsDefined() || toGLine->NoOfComponents() < 1 ||
|
|
GetNetworkId() != toGLine->GetNetworkId())
|
|
return res;
|
|
if (Inside(toGLine, pNetwork->GetScalefactor()*0.01)) return 0.0;
|
|
GLine *path = new GLine(0);
|
|
if (ShortestPathAStar(toGLine,path,pNetwork,0))
|
|
res = path->GetLength();
|
|
path->DeleteIfAllowed();
|
|
return res;
|
|
}
|
|
|
|
double GPoint::NetdistanceNew (const GPoints* toGPoints)const
|
|
{
|
|
double res = -1.0;
|
|
if (!IsDefined() || !toGPoints->IsDefined() ||
|
|
toGPoints->Size() < 1 ||
|
|
GetNetworkId() != toGPoints->GetNetworkId())
|
|
return res;
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
res = NetdistanceNew(toGPoints,pNetwork);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return res;
|
|
}
|
|
|
|
double GPoint::NetdistanceNew (const GPoints* toGPoints,
|
|
const Network* pNetwork) const
|
|
{
|
|
double res = -1.0;
|
|
if (!IsDefined() || !toGPoints->IsDefined() ||
|
|
toGPoints->Size() < 1 ||
|
|
GetNetworkId() != toGPoints->GetNetworkId())
|
|
return res;
|
|
GLine *path = new GLine(0);
|
|
if (ShortestPathAStar(toGPoints,path,pNetwork,0))
|
|
res = path->GetLength();
|
|
path->DeleteIfAllowed();
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
Distance function computes the Euclidean Distance between two ~GPoint~s.
|
|
|
|
*/
|
|
|
|
double GPoint::Distance ( const GPoint* pToGPoint ) const
|
|
{
|
|
if ( IsDefined() && pToGPoint->IsDefined() &&
|
|
GetNetworkId() == pToGPoint->GetNetworkId() )
|
|
{
|
|
//Network* pNetwork=NetworkManager::GetNetwork(GetNetworkId());
|
|
Network* pNetwork = NetworkManager::GetNetworkNew ( GetNetworkId(),
|
|
netList );
|
|
Point *from = new Point ( true );
|
|
pNetwork->GetPointOnRoute ( this, from );
|
|
Point *to = new Point ( true );
|
|
pNetwork->GetPointOnRoute ( pToGPoint,to );
|
|
double res = from->Distance ( *to );
|
|
from->DeleteIfAllowed();
|
|
to->DeleteIfAllowed();
|
|
NetworkManager::CloseNetwork ( pNetwork );
|
|
return res;
|
|
}
|
|
else return numeric_limits<double>::max();
|
|
}
|
|
|
|
/*
|
|
Returns true if the gpoint is inside the gline false elsewhere.
|
|
|
|
*/
|
|
bool GPoint::Inside (const GLine *gl, const double tolerance )const
|
|
{
|
|
if ( ! ( gl->IsDefined() ) || !IsDefined() ||
|
|
gl->NoOfComponents() < 1 ) return false;
|
|
if ( GetNetworkId() != gl->GetNetworkId() ) return false;
|
|
RouteInterval pCurrRInter;
|
|
if ( gl->IsSorted() )
|
|
return ( searchRouteInterval ( this, gl, tolerance, 0,
|
|
gl->NoOfComponents()-1 ) );
|
|
else
|
|
{
|
|
int i = 0;
|
|
while ( i < gl->NoOfComponents() )
|
|
{
|
|
gl->Get ( i, pCurrRInter );
|
|
if ( pCurrRInter.GetRouteId() == GetRouteId() )
|
|
{
|
|
if ( pCurrRInter.GetStartPos() <= GetPosition() &&
|
|
GetPosition() <= pCurrRInter.GetEndPos() )
|
|
return true;
|
|
if ( pCurrRInter.GetStartPos() >= GetPosition() &&
|
|
GetPosition() >= pCurrRInter.GetEndPos() )
|
|
return true;
|
|
if ( AlmostEqualAbsolute(pCurrRInter.GetStartPos(), GetPosition(),
|
|
tolerance))
|
|
return true;
|
|
if ( AlmostEqualAbsolute( pCurrRInter.GetEndPos(), GetPosition(),
|
|
tolerance ))
|
|
return true;
|
|
}
|
|
i++;
|
|
}
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool GPoint::operator== ( const GPoint& p ) const
|
|
{
|
|
if ( !IsDefined() || !p.IsDefined() ) return false;
|
|
else
|
|
{
|
|
if ( m_iNetworkId == p.GetNetworkId() &&
|
|
m_xRouteLocation.rid == p.GetRouteId() &&
|
|
m_xRouteLocation.d == p.GetPosition() &&
|
|
( m_xRouteLocation.side == p.GetSide() || m_xRouteLocation.side == 2
|
|
||
|
|
p.GetSide() == 2 ) )
|
|
{
|
|
return true;
|
|
}
|
|
else return false;
|
|
}
|
|
}
|
|
|
|
bool GPoint::operator!= ( const GPoint& p ) const
|
|
{
|
|
return ! ( *this == p );
|
|
}
|
|
|
|
/*
|
|
Computes the shortest path between start and end in the network. Using
|
|
Dijkstras Algorithm. The path is returned as gline value.
|
|
|
|
*/
|
|
|
|
bool GPoint::ShortestPathAStar(const GPoint *to, GLine *result,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
result->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if (!IsDefined() || !to->IsDefined())
|
|
{
|
|
result->SetDefined(false);
|
|
return false;
|
|
}
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
double bres = ShortestPathAStar(to, result, pNetwork, touchedSects);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return bres;
|
|
}
|
|
|
|
bool GPoint::ShortestPathAStar (const GPoint *to, GLine *result,
|
|
const Network *pNetwork,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
result->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if (!IsDefined() || !to->IsDefined())
|
|
return false;
|
|
if (GetNetworkId() != to->GetNetworkId()) return false;
|
|
result->SetNetworkId(GetNetworkId());
|
|
result->SetDefined(true);
|
|
if (Compare(*to) == 0) return true;
|
|
GPoints* start = new GPoints(1);
|
|
start->MergeAdd(*this,pNetwork);
|
|
GPoints* target = new GPoints(1);
|
|
target->MergeAdd(*to,pNetwork);
|
|
bool res = start->ShortestPathAStar(target, result, pNetwork, touchedSects);
|
|
result->SetDefined(res);
|
|
start->DeleteIfAllowed();
|
|
target->DeleteIfAllowed();
|
|
return res;
|
|
}
|
|
|
|
bool GPoint::ShortestPath ( const GPoint *to, GLine *result,
|
|
DbArray<TupleId>* touchedSects) const
|
|
{
|
|
result->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if (!IsDefined() || !to->IsDefined())
|
|
{
|
|
result->SetDefined(false);
|
|
return false;
|
|
}
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
double bres = ShortestPath(to, result, pNetwork, touchedSects);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return bres;
|
|
}
|
|
|
|
bool GPoint::ShortestPath ( const GPoint *to, GLine *result,
|
|
const Network* pNetwork,
|
|
DbArray<TupleId>* touchedSects )const
|
|
{
|
|
result->Clear();
|
|
result->SetDefined(false);
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if ( !IsDefined() || !to->IsDefined() || to == 0)
|
|
{
|
|
sendMessage ( "Both gpoints must exist and be defined." );
|
|
return false;
|
|
}
|
|
// Check wether both points belong to the same network
|
|
if ( GetNetworkId() != to->GetNetworkId() || pNetwork == 0 ||
|
|
pNetwork->GetId() != GetNetworkId())
|
|
{
|
|
sendMessage ( "Both gpoints belong to network." );
|
|
return false;
|
|
}
|
|
// Get sections where the path should start or end
|
|
TupleId startSectTID = pNetwork->GetTupleIdSectionOnRoute ( this );
|
|
if (touchedSects != 0) touchedSects->Append(startSectTID);
|
|
Tuple* startSection = pNetwork->GetSection ( startSectTID );
|
|
if ( startSection == 0 )
|
|
{
|
|
sendMessage ( "Starting GPoint not found in network." );
|
|
return false;
|
|
}
|
|
TupleId lastSectTID = pNetwork->GetTupleIdSectionOnRoute ( to );
|
|
Tuple* endSection = pNetwork->GetSection ( lastSectTID );
|
|
if ( endSection == 0 )
|
|
{
|
|
sendMessage ( "End GPoint not found in network." );
|
|
startSection->DeleteIfAllowed();
|
|
return false;
|
|
}
|
|
if ( startSectTID == lastSectTID ||
|
|
GetRouteId() == to->GetRouteId() )
|
|
{
|
|
result->SetDefined(true);
|
|
result->SetNetworkId(pNetwork->GetId());
|
|
result->AddRouteInterval ( GetRouteId(), GetPosition(), to->GetPosition());
|
|
startSection->DeleteIfAllowed();
|
|
endSection->DeleteIfAllowed();
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
Calculate the shortest path using dijkstras algorithm.
|
|
|
|
Initialize PriorityQueue
|
|
|
|
*/
|
|
PrioQueueA *prioQ = new PrioQueueA ( 0 );
|
|
SectIDTreeP *visitedSect = new SectIDTreeP ( 0);
|
|
int pHelp = -1;
|
|
visitedSect->Insert(SectIDTreeEntry(
|
|
SectEntry(startSectTID,
|
|
(TupleId) numeric_limits<long>::max(),
|
|
false,
|
|
false,
|
|
-1,
|
|
0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
visitedSect->Insert(SectIDTreeEntry(SectEntry(startSectTID,
|
|
(TupleId) numeric_limits<long>::max(),
|
|
true,
|
|
true,
|
|
-1,
|
|
0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
double sectMeas1 =
|
|
((CcReal* )startSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
double sectMeas2 =
|
|
((CcReal*)startSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
double dist = 0.0;
|
|
vector<DirectedSection> adjSectionList;
|
|
adjSectionList.clear();
|
|
if ( GetSide() == 0 || GetSide() ==2)
|
|
{
|
|
dist = GetPosition() - sectMeas1;
|
|
pNetwork->GetAdjacentSections ( startSectTID, false, adjSectionList );
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
if ( actNextSect.GetSectionTid() != startSectTID )
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(), dist, dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectTID, false ),
|
|
visitedSect,
|
|
touchedSects);
|
|
}
|
|
adjSectionList.clear();
|
|
}
|
|
|
|
if ( GetSide() == 1 || GetSide()==2 )
|
|
{
|
|
dist = sectMeas2 - GetPosition();
|
|
pNetwork->GetAdjacentSections ( startSectTID, true, adjSectionList );
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
if ( actNextSect.GetSectionTid() != startSectTID )
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(), dist,dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectTID,true ),
|
|
visitedSect, touchedSects);
|
|
}
|
|
adjSectionList.clear();
|
|
}
|
|
/*
|
|
Use priorityQueue to find shortestPath.
|
|
|
|
*/
|
|
PQEntryA *actPQEntry;
|
|
bool found = false;
|
|
vector<PQEntryA> candidate;
|
|
while ( !prioQ->IsEmpty() && !found )
|
|
{
|
|
actPQEntry = prioQ->GetAndDeleteMin ( visitedSect );
|
|
Tuple *actSection = pNetwork->GetSection ( actPQEntry->sectID );
|
|
sectMeas1 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
sectMeas2 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
dist = actPQEntry->valFromStart + fabs ( sectMeas2 - sectMeas1 );
|
|
if ( actPQEntry->sectID != lastSectTID )
|
|
{
|
|
/*
|
|
Search in the network until reached last section.
|
|
Get adjacent sections and insert into priority Queue.
|
|
|
|
*/
|
|
adjSectionList.clear();
|
|
pNetwork->GetAdjacentSections ( actPQEntry->sectID,
|
|
actPQEntry->upDownFlag,
|
|
adjSectionList );
|
|
for ( size_t i = 0; i <adjSectionList.size();i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
if ( actNextSect.GetSectionTid() != actPQEntry->sectID )
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(),
|
|
dist,dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
actPQEntry->sectID,
|
|
actPQEntry->upDownFlag ),
|
|
visitedSect, touchedSects);
|
|
}
|
|
if (actPQEntry != 0){
|
|
delete actPQEntry;
|
|
actPQEntry=0;
|
|
}
|
|
if (actSection != 0){
|
|
actSection->DeleteIfAllowed();
|
|
actSection = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
Shortest Path found. Compute last route interval and resulting gline.
|
|
|
|
*/
|
|
|
|
found = true;
|
|
double startRI, endRI;
|
|
int actRouteId =
|
|
((CcInt*)actSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
if ( actPQEntry->upDownFlag)
|
|
startRI = sectMeas1;
|
|
else
|
|
startRI = sectMeas2;
|
|
endRI = to->GetPosition();
|
|
double minPathLength = actPQEntry->valFromStart + fabs(endRI-startRI);
|
|
bool btestend = false;
|
|
while (!btestend && !prioQ->IsEmpty())
|
|
{
|
|
PQEntryA* testEntry = prioQ->GetAndDeleteMin(visitedSect);
|
|
if (testEntry->valFromStart < minPathLength)
|
|
{
|
|
Tuple *testSection = pNetwork->GetSection ( testEntry->sectID );
|
|
double testMeas1 =
|
|
((CcReal*)testSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
double testMeas2 =
|
|
((CcReal*)testSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
int testRouteId =
|
|
((CcInt*)testSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
if (testEntry->sectID != lastSectTID)
|
|
{
|
|
adjSectionList.clear();
|
|
pNetwork->GetAdjacentSections ( testEntry->sectID,
|
|
testEntry->upDownFlag,
|
|
adjSectionList );
|
|
dist = testEntry->valFromStart + fabs(testMeas2 - testMeas1);
|
|
for ( size_t i = 0; i <adjSectionList.size();i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
if ( actNextSect.GetSectionTid() != testEntry->sectID )
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(),
|
|
dist, dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
testEntry->sectID,
|
|
testEntry->upDownFlag),
|
|
visitedSect, touchedSects);
|
|
}
|
|
if (testEntry != 0)
|
|
{
|
|
delete testEntry;
|
|
testEntry=0;
|
|
}
|
|
if (testSection != 0)
|
|
{
|
|
testSection->DeleteIfAllowed();
|
|
testSection = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
double endTestRI = to->GetPosition();
|
|
double startTestRI = 0.0;
|
|
if ( testEntry->upDownFlag)
|
|
startTestRI = testMeas1;
|
|
else
|
|
startTestRI = testMeas2;
|
|
double actPathLength =
|
|
testEntry->valFromStart + fabs(endTestRI-startTestRI);
|
|
if (actPathLength < minPathLength)
|
|
{
|
|
minPathLength = actPathLength;
|
|
endRI = endTestRI;
|
|
startRI = startTestRI;
|
|
actRouteId = testRouteId;
|
|
|
|
if (actPQEntry != 0)
|
|
{
|
|
delete actPQEntry;
|
|
}
|
|
actPQEntry = testEntry;
|
|
actSection->DeleteIfAllowed();
|
|
actSection = testSection;
|
|
}
|
|
}
|
|
if (testSection != 0 && actSection != testSection)
|
|
{
|
|
testSection->DeleteIfAllowed();
|
|
testSection = 0;
|
|
}
|
|
}
|
|
else
|
|
btestend = true;
|
|
if (testEntry != 0 && testEntry != actPQEntry)
|
|
{
|
|
delete testEntry;
|
|
testEntry = 0;
|
|
}
|
|
}
|
|
if (actSection != 0)
|
|
{
|
|
actSection->DeleteIfAllowed();
|
|
actSection = 0;
|
|
}
|
|
|
|
/*
|
|
Get the sections used for shortest path and write them in right order (from
|
|
start to end gpoint) in the resulting gline. Because Dijkstra gives the
|
|
sections from end to start we first have to put the result sections on a
|
|
stack to turn in right order.
|
|
|
|
*/
|
|
RIStackP *riStack = new RIStackP (0);
|
|
riStack->Push( actRouteId, startRI, endRI );
|
|
//TupleId lastSectId = actPQEntry->sectID;
|
|
int pElem = visitedSect->Find ( actPQEntry->beforeSectID,
|
|
actPQEntry->beforeUpDown );
|
|
bool end = false;
|
|
bool upDown;
|
|
// if (startRI >= endRI) upDown = false;
|
|
if ( startRI > endRI ||
|
|
AlmostEqualAbsolute( startRI,endRI, pNetwork->GetScalefactor()*0.01))
|
|
upDown = false;
|
|
else upDown = true;
|
|
while ( !end && pElem > -1 && pElem < visitedSect->fFree)
|
|
{
|
|
//GetSection
|
|
TupleId actTupleId =
|
|
visitedSect->GetTreeEntry(pElem).GetEntry().GetSectId();
|
|
if (actSection != 0) actSection->DeleteIfAllowed();
|
|
actSection = pNetwork->GetSection ( actTupleId );
|
|
if (actSection != 0)
|
|
{
|
|
actRouteId =
|
|
((CcInt*)actSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
sectMeas1 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
sectMeas2 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
upDown =
|
|
visitedSect->GetTreeEntry(pElem).GetEntry().GetUpDownFlag();
|
|
if (actTupleId != startSectTID)
|
|
{
|
|
if (upDown)
|
|
riStack->Push(actRouteId, sectMeas1,sectMeas2);
|
|
else
|
|
riStack->Push(actRouteId, sectMeas2,sectMeas1);
|
|
//lastSectId =
|
|
// visitedSect->GetTreeEntry(pElem).GetEntry().GetSectId();
|
|
pElem =
|
|
visitedSect->Find(visitedSect->GetTreeEntry(pElem).GetEntry().
|
|
GetBeforeSectId(),
|
|
visitedSect->GetTreeEntry(pElem).GetEntry().
|
|
GetBeforeSectUpDown());
|
|
}
|
|
else
|
|
{
|
|
end = true;
|
|
if (upDown)
|
|
riStack->Push ( actRouteId, GetPosition(), sectMeas2);
|
|
else
|
|
riStack->Push ( actRouteId, GetPosition(), sectMeas1);
|
|
}
|
|
}
|
|
if ( actSection )
|
|
{
|
|
actSection->DeleteIfAllowed();
|
|
actSection = 0;
|
|
}
|
|
}
|
|
// Cleanup and return result
|
|
riStack->StackToGLine ( result, GetNetworkId() );
|
|
riStack->Destroy();
|
|
delete riStack;
|
|
result->SetSorted ( false );
|
|
}
|
|
if ( actPQEntry )
|
|
{
|
|
delete actPQEntry;
|
|
actPQEntry = 0;
|
|
}
|
|
if ( actSection )
|
|
{
|
|
actSection->DeleteIfAllowed();
|
|
actSection = 0;
|
|
}
|
|
}
|
|
if ( visitedSect != 0 )
|
|
{
|
|
visitedSect->Destroy();
|
|
delete visitedSect;
|
|
}
|
|
prioQ->Destroy();
|
|
delete prioQ;
|
|
startSection->DeleteIfAllowed();
|
|
endSection->DeleteIfAllowed();
|
|
result->SetDefined ( found );
|
|
result->TrimToSize();
|
|
return found;
|
|
};
|
|
|
|
bool GPoint::ShortestPathAStar(const GLine *ziel, GLine *result,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
result->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if (!IsDefined() || !ziel->IsDefined() || ziel->NoOfComponents() < 1)
|
|
return false;
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
bool res = ShortestPathAStar(ziel,result,pNetwork,touchedSects);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return res;
|
|
}
|
|
|
|
bool GPoint::ShortestPathAStar(const GLine* ziel, GLine* result,
|
|
const Network *pNetwork,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
result->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if (!IsDefined() || !ziel->IsDefined() || ziel->NoOfComponents() < 1)
|
|
return false;
|
|
if (GetNetworkId() != ziel->GetNetworkId()) return false;
|
|
result->SetNetworkId(GetNetworkId());
|
|
if (Inside(ziel,pNetwork->GetScalefactor()*0.01))return true;
|
|
GPoints* start = new GPoints(1);
|
|
start->MergeAdd(*this,pNetwork);
|
|
GPoints* target = new GPoints(0);
|
|
ziel->GetBGP(pNetwork,target);
|
|
bool res = start->ShortestPathAStar(target, result, pNetwork, touchedSects);
|
|
result->SetDefined(res);
|
|
start->DeleteIfAllowed();
|
|
target->DeleteIfAllowed();
|
|
return res;
|
|
}
|
|
|
|
bool GPoint::ShortestPathAStar(const GPoints *ziel, GLine *result,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
result->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if (!IsDefined() || !ziel->IsDefined() || ziel->Size() < 1)
|
|
return false;
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
bool res = ShortestPathAStar(ziel,result,pNetwork,touchedSects);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return res;
|
|
}
|
|
|
|
bool GPoint::ShortestPathAStar(const GPoints* ziel, GLine* result,
|
|
const Network *pNetwork,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
result->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if (!IsDefined() || !ziel->IsDefined() || ziel->Size() < 1)
|
|
return false;
|
|
if (GetNetworkId() != ziel->GetNetworkId()) return false;
|
|
result->SetNetworkId(GetNetworkId());
|
|
GPoints* start = new GPoints(0);
|
|
start->MergeAdd(*this,pNetwork);
|
|
bool res = start->ShortestPathAStar(ziel, result, pNetwork, touchedSects);
|
|
result->SetDefined(res);
|
|
start->DeleteIfAllowed();
|
|
return res;
|
|
}
|
|
|
|
|
|
/*
|
|
Returns the shortest path tree from the gpoint to all sections of the
|
|
network. The distances are stored in an DbArray<double>, where the index
|
|
of the Array-Field is two times the section number for up sections and
|
|
two times the section number plus one for down sections.
|
|
|
|
*/
|
|
|
|
|
|
void GPoint::ShortestPathTree(const Network* pNetwork,
|
|
DbArray<ShortestPathTreeEntry> *res) const
|
|
{
|
|
if (IsDefined() && pNetwork != 0 && pNetwork->IsDefined() &&
|
|
GetNetworkId() == pNetwork->GetId() && res != 0)
|
|
{
|
|
TupleId startSectionTID = pNetwork->GetTupleIdSectionOnRoute(this);
|
|
PrioQueueA *prioQ = new PrioQueueA ( 0 );
|
|
SectIDTreeP *visitedSect = new SectIDTreeP ( 0);
|
|
int pHelp = -1;
|
|
int sectPos = -1;
|
|
visitedSect->Insert(SectIDTreeEntry(
|
|
SectEntry(startSectionTID,
|
|
startSectionTID,
|
|
true, true,
|
|
-1,
|
|
0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
visitedSect->Insert(SectIDTreeEntry(
|
|
SectEntry(startSectionTID,
|
|
startSectionTID,
|
|
false, false,
|
|
-1,
|
|
0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
Tuple* startSection = pNetwork->GetSection(startSectionTID);
|
|
double sectMeas1 =
|
|
((CcReal* )startSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
double sectMeas2 =
|
|
((CcReal*)startSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
//int actRouteId =
|
|
// ((CcInt*)startSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
int sectID =
|
|
((CcInt*)startSection->GetAttribute(SECTION_SID))->GetIntval();
|
|
res->Put(2*sectID, ShortestPathTreeEntry(0.0,true));
|
|
res->Put(2*sectID + 1, ShortestPathTreeEntry(0.0,false));
|
|
double dist = GetPosition() - sectMeas1;
|
|
vector<DirectedSection> adjSectionList;
|
|
adjSectionList.clear();
|
|
pNetwork->GetAdjacentSections ( startSectionTID, false,
|
|
adjSectionList );
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(), dist, dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectionTID, false ),
|
|
visitedSect, 0);
|
|
}
|
|
adjSectionList.clear();
|
|
dist = sectMeas2 - GetPosition();
|
|
pNetwork->GetAdjacentSections ( startSectionTID, true,
|
|
adjSectionList );
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(), dist,dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectionTID, true ),
|
|
visitedSect, 0);
|
|
}
|
|
adjSectionList.clear();
|
|
PQEntryA* actPQEntry = 0;
|
|
while (!prioQ->IsEmpty())
|
|
{
|
|
actPQEntry = prioQ->GetAndDeleteMin(visitedSect);
|
|
Tuple *actSection = pNetwork->GetSection ( actPQEntry->sectID );
|
|
sectMeas1 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
sectMeas2 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
//actRouteId =
|
|
// ((CcInt*)actSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
sectID =
|
|
((CcInt*)actSection->GetAttribute(SECTION_SID))->GetIntval();
|
|
sectPos = 2*sectID;
|
|
if (!actPQEntry->upDownFlag) sectPos++;
|
|
res->Put(sectPos, ShortestPathTreeEntry(actPQEntry->valFromStart,
|
|
actPQEntry->upDownFlag));
|
|
dist = actPQEntry->valFromStart + fabs ( sectMeas2 - sectMeas1 );
|
|
pNetwork->GetAdjacentSections ( actPQEntry->sectID,
|
|
actPQEntry->upDownFlag,
|
|
adjSectionList );
|
|
if (adjSectionList.size() != 0)
|
|
{
|
|
for ( size_t i = 0; i <adjSectionList.size();i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(),
|
|
dist,dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
actPQEntry->sectID,
|
|
actPQEntry->upDownFlag),
|
|
visitedSect, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!actPQEntry->upDownFlag)
|
|
sectPos--;
|
|
else
|
|
sectPos++;
|
|
res->Put(sectPos, ShortestPathTreeEntry(actPQEntry->valFromStart +
|
|
fabs(sectMeas2 - sectMeas1),
|
|
!actPQEntry->upDownFlag));
|
|
}
|
|
adjSectionList.clear();
|
|
if (actSection != 0)
|
|
{
|
|
actSection->DeleteIfAllowed();
|
|
actSection = 0;
|
|
}
|
|
if (actPQEntry != 0)
|
|
{
|
|
delete actPQEntry;
|
|
actPQEntry=0;
|
|
}
|
|
}
|
|
prioQ->Destroy();
|
|
delete prioQ;
|
|
visitedSect->Destroy();
|
|
delete visitedSect;
|
|
startSection->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
/*
|
|
Almost analogous to shortest path tree but stops computation if all sections
|
|
of ~toReach~ are inserted.
|
|
|
|
*/
|
|
|
|
void GPoint::ShortestPathTree(const Network* pNetwork,
|
|
DbArray<ShortestPathTreeEntry> *res,
|
|
SortedTree<Entry<SectionValue> > *toReach) const{
|
|
if (IsDefined() && pNetwork != 0 && pNetwork->IsDefined() &&
|
|
GetNetworkId() == pNetwork->GetId() && res != 0) {
|
|
TupleId startSectionTID = pNetwork->GetTupleIdSectionOnRoute(this);
|
|
PrioQueueA *prioQ = new PrioQueueA ( 0 );
|
|
SectIDTreeP *visitedSect = new SectIDTreeP ( 0);
|
|
int pHelp = -1;
|
|
int sectPos = -1;
|
|
visitedSect->Insert(SectIDTreeEntry(
|
|
SectEntry(startSectionTID,
|
|
startSectionTID,
|
|
true, true,
|
|
-1,
|
|
0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
visitedSect->Insert(SectIDTreeEntry(
|
|
SectEntry(startSectionTID,
|
|
startSectionTID,
|
|
false, false,
|
|
-1,
|
|
0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
Tuple* startSection = pNetwork->GetSection(startSectionTID);
|
|
double sectMeas1 =
|
|
((CcReal* )startSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
double sectMeas2 =
|
|
((CcReal*)startSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
//int actRouteId =
|
|
// ((CcInt*)startSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
int sectID =
|
|
((CcInt*)startSection->GetAttribute(SECTION_SID))->GetIntval();
|
|
res->Put(2*sectID, ShortestPathTreeEntry(0.0,true));
|
|
res->Put(2*sectID + 1, ShortestPathTreeEntry(0.0,false));
|
|
toReach->Remove(Entry<SectionValue>(SectionValue(sectID, true)));
|
|
toReach->Remove(Entry<SectionValue>(SectionValue(sectID, false)));
|
|
double dist = GetPosition() - sectMeas1;
|
|
vector<DirectedSection> adjSectionList;
|
|
adjSectionList.clear();
|
|
pNetwork->GetAdjacentSections ( startSectionTID, false, adjSectionList );
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ ) {
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(), dist, dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectionTID, false ),
|
|
visitedSect, 0);
|
|
}
|
|
adjSectionList.clear();
|
|
dist = sectMeas2 - GetPosition();
|
|
pNetwork->GetAdjacentSections ( startSectionTID, true,
|
|
adjSectionList );
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ ) {
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(), dist,dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectionTID, true ),
|
|
visitedSect, 0);
|
|
}
|
|
adjSectionList.clear();
|
|
PQEntryA* actPQEntry = 0;
|
|
while (!prioQ->IsEmpty() && !toReach->isEmpty()) {
|
|
actPQEntry = prioQ->GetAndDeleteMin(visitedSect);
|
|
Tuple *actSection = pNetwork->GetSection ( actPQEntry->sectID );
|
|
sectMeas1 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
sectMeas2 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
//actRouteId =
|
|
// ((CcInt*)actSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
sectID =
|
|
((CcInt*)actSection->GetAttribute(SECTION_SID))->GetIntval();
|
|
sectPos = 2*sectID;
|
|
if (!actPQEntry->upDownFlag) sectPos++;
|
|
res->Put(sectPos, ShortestPathTreeEntry(actPQEntry->valFromStart,
|
|
actPQEntry->upDownFlag));
|
|
toReach->Remove(Entry<SectionValue>(SectionValue(sectID,
|
|
actPQEntry->upDownFlag)));
|
|
dist = actPQEntry->valFromStart + fabs ( sectMeas2 - sectMeas1 );
|
|
pNetwork->GetAdjacentSections ( actPQEntry->sectID,
|
|
actPQEntry->upDownFlag,
|
|
adjSectionList );
|
|
if (adjSectionList.size() != 0) {
|
|
for ( size_t i = 0; i <adjSectionList.size();i++ ) {
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(),
|
|
dist,dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
actPQEntry->sectID,
|
|
actPQEntry->upDownFlag),
|
|
visitedSect, 0);
|
|
}
|
|
} else {
|
|
if (!actPQEntry->upDownFlag) sectPos--;
|
|
else sectPos++;
|
|
res->Put(sectPos, ShortestPathTreeEntry(actPQEntry->valFromStart +
|
|
fabs(sectMeas2 - sectMeas1),
|
|
!actPQEntry->upDownFlag));
|
|
toReach->Remove(Entry<SectionValue>(SectionValue(sectID,
|
|
!actPQEntry->upDownFlag)));
|
|
}
|
|
adjSectionList.clear();
|
|
if (actSection != 0) {
|
|
actSection->DeleteIfAllowed();
|
|
actSection = 0;
|
|
}
|
|
if (actPQEntry != 0) {
|
|
delete actPQEntry;
|
|
actPQEntry=0;
|
|
}
|
|
}
|
|
prioQ->Destroy();
|
|
delete prioQ;
|
|
visitedSect->Destroy();
|
|
delete visitedSect;
|
|
startSection->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
/*
|
|
Almost analogous to shortest path tree but stops computation if all sections
|
|
within the maximum distance maxdist are inserted.
|
|
|
|
*/
|
|
|
|
void GPoint::Out_Circle(const Network* pNetwork, GLine* res,
|
|
const double maxdist) const
|
|
{
|
|
res->Clear();
|
|
RITreeP *ritree = new RITreeP(0);
|
|
if (IsDefined() && pNetwork != 0 && pNetwork->IsDefined() &&
|
|
GetNetworkId() == pNetwork->GetId() && res != 0)
|
|
{
|
|
res->SetDefined(true);
|
|
res->SetNetworkId(GetNetworkId());
|
|
TupleId startSectionTID = pNetwork->GetTupleIdSectionOnRoute(this);
|
|
PrioQueueA *prioQ = new PrioQueueA ( 0 );
|
|
SectIDTreeP *visitedSect = new SectIDTreeP ( 0);
|
|
int pHelp = -1;
|
|
visitedSect->Insert(SectIDTreeEntry(SectEntry(startSectionTID,
|
|
startSectionTID,
|
|
true, true, -1, 0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
visitedSect->Insert(SectIDTreeEntry(SectEntry(startSectionTID,
|
|
startSectionTID,
|
|
false, false, -1, 0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
Tuple* startSection = pNetwork->GetSection(startSectionTID);
|
|
double sectMeas1 =
|
|
((CcReal* )startSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
double sectMeas2 =
|
|
((CcReal*)startSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
int actRouteId =
|
|
((CcInt*)startSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
double dist1 = fabs(GetPosition() - sectMeas1);
|
|
double dist2 = fabs(GetPosition() - sectMeas2);
|
|
double length = fabs(sectMeas2 - sectMeas1);
|
|
bool s1 = true;
|
|
bool s2 = true;
|
|
if (length <= maxdist)
|
|
{
|
|
ritree->Insert(actRouteId, sectMeas1, sectMeas2);
|
|
}
|
|
else
|
|
{
|
|
if (dist1 <= maxdist )
|
|
ritree->Insert(actRouteId, sectMeas1, GetPosition());
|
|
else
|
|
{
|
|
ritree->Insert(actRouteId, GetPosition() - maxdist, GetPosition());
|
|
s1 = false;
|
|
}
|
|
if (dist2 <= maxdist)
|
|
ritree->Insert(actRouteId, GetPosition(), sectMeas2);
|
|
else
|
|
{
|
|
ritree->Insert(actRouteId, GetPosition(), GetPosition() + maxdist );
|
|
s2 = false;
|
|
}
|
|
}
|
|
vector<DirectedSection> adjSectionList;
|
|
adjSectionList.clear();
|
|
if (s1)
|
|
{
|
|
pNetwork->GetAdjacentSections ( startSectionTID, false, adjSectionList );
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(), dist1, dist1,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectionTID, false ),
|
|
visitedSect, 0);
|
|
}
|
|
adjSectionList.clear();
|
|
}
|
|
if (s2)
|
|
{
|
|
pNetwork->GetAdjacentSections ( startSectionTID, true,
|
|
adjSectionList );
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ ) {
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(), dist2, dist2,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectionTID, true ),
|
|
visitedSect, 0);
|
|
}
|
|
adjSectionList.clear();
|
|
}
|
|
PQEntryA* actPQEntry = 0;
|
|
double actDist = 0.0;
|
|
bool reached = false;
|
|
while (!prioQ->IsEmpty() && !reached)
|
|
{
|
|
actPQEntry = prioQ->GetAndDeleteMin(visitedSect);
|
|
if (actPQEntry->valFromStart > maxdist)
|
|
{
|
|
reached = true;
|
|
}
|
|
else
|
|
{
|
|
Tuple *actSection = pNetwork->GetSection ( actPQEntry->sectID );
|
|
sectMeas1 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
sectMeas2 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
actRouteId =
|
|
((CcInt*)actSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
length = fabs(sectMeas2 - sectMeas1);
|
|
actDist = actPQEntry->valFromStart + length;
|
|
if(actDist <= maxdist)
|
|
{
|
|
ritree->Insert(actRouteId, sectMeas1, sectMeas2);
|
|
pNetwork->GetAdjacentSections ( actPQEntry->sectID,
|
|
actPQEntry->upDownFlag,
|
|
adjSectionList );
|
|
if (adjSectionList.size() != 0)
|
|
{
|
|
for ( size_t i = 0; i <adjSectionList.size();i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(),
|
|
actDist,actDist,
|
|
actNextSect.GetUpDownFlag(),
|
|
actPQEntry->sectID,
|
|
actPQEntry->upDownFlag),
|
|
visitedSect, 0);
|
|
}
|
|
adjSectionList.clear();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (actPQEntry->upDownFlag)
|
|
{
|
|
ritree->Insert(actRouteId, sectMeas1,
|
|
sectMeas1 + fabs(maxdist - actPQEntry->valFromStart));
|
|
}
|
|
else
|
|
{
|
|
ritree->Insert(actRouteId,
|
|
sectMeas2 - fabs(maxdist - actPQEntry->valFromStart),
|
|
sectMeas2);
|
|
}
|
|
}
|
|
if (actSection != 0)
|
|
{
|
|
actSection->DeleteIfAllowed();
|
|
actSection = 0;
|
|
}
|
|
}
|
|
if (actPQEntry != 0)
|
|
{
|
|
delete actPQEntry;
|
|
actPQEntry=0;
|
|
}
|
|
}
|
|
prioQ->Destroy();
|
|
delete prioQ;
|
|
visitedSect->Destroy();
|
|
delete visitedSect;
|
|
startSection->DeleteIfAllowed();
|
|
ritree->TreeToGLine(res,0);
|
|
res->SetSorted(true);
|
|
}
|
|
else
|
|
{
|
|
res->SetDefined(false);
|
|
}
|
|
ritree->Destroy();
|
|
delete ritree;
|
|
}
|
|
|
|
|
|
/*
|
|
Returns the reverse shortest path tree of the gpoint from all sections of the
|
|
network. The distances are stored in an DbArray<double>, where the index
|
|
of the Array-Field is two times the section number for up sections and
|
|
two times the section number plus one for down sections.
|
|
|
|
*/
|
|
|
|
void GPoint::ReverseShortestPathTree(const Network* pNetwork,
|
|
DbArray<ShortestPathTreeEntry> *res) const
|
|
{
|
|
if (IsDefined() && pNetwork != 0 && pNetwork->IsDefined() &&
|
|
GetNetworkId() == pNetwork->GetId() && res != 0) {
|
|
TupleId startSectionTID = pNetwork->GetTupleIdSectionOnRoute(this);
|
|
PrioQueueA *prioQ = new PrioQueueA ( 0 );
|
|
SectIDTreeP *visitedSect = new SectIDTreeP ( 0);
|
|
int pHelp = -1;
|
|
int sectPos = -1;
|
|
Tuple* startSection = pNetwork->GetSection(startSectionTID);
|
|
double sectMeas1 =
|
|
((CcReal* )startSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
double sectMeas2 =
|
|
((CcReal*)startSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
//int actRouteId =
|
|
// ((CcInt*)startSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
int sectID =
|
|
((CcInt*)startSection->GetAttribute(SECTION_SID))->GetIntval();
|
|
res->Put(2*sectID, ShortestPathTreeEntry(0.0, true));
|
|
res->Put(2*sectID + 1, ShortestPathTreeEntry(0.0, false));
|
|
double dist = fabs(GetPosition() - sectMeas2);
|
|
visitedSect->Insert(SectIDTreeEntry(
|
|
SectEntry(startSectionTID,
|
|
startSectionTID,
|
|
false, false,
|
|
-1,
|
|
0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
visitedSect->Insert(SectIDTreeEntry(
|
|
SectEntry(startSectionTID,
|
|
startSectionTID,
|
|
true, true,
|
|
-1,
|
|
0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
vector<DirectedSection> adjSectionList;
|
|
adjSectionList.clear();
|
|
pNetwork->GetReverseAdjacentSections (startSectionTID, false,
|
|
adjSectionList );
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ ){
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(), dist, dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectionTID, false ),
|
|
visitedSect, 0);
|
|
}
|
|
adjSectionList.clear();
|
|
dist = fabs(sectMeas1 - GetPosition());
|
|
|
|
pNetwork->GetReverseAdjacentSections ( startSectionTID, true,
|
|
adjSectionList );
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ ) {
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(), dist,dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectionTID, true ),
|
|
visitedSect, 0);
|
|
}
|
|
adjSectionList.clear();
|
|
PQEntryA* actPQEntry = 0;
|
|
while (!prioQ->IsEmpty()) {
|
|
actPQEntry = prioQ->GetAndDeleteMin(visitedSect);
|
|
Tuple *actSection = pNetwork->GetSection ( actPQEntry->sectID );
|
|
sectMeas1 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
sectMeas2 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
//actRouteId =
|
|
// ((CcInt*)actSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
sectID =
|
|
((CcInt*)actSection->GetAttribute(SECTION_SID))->GetIntval();
|
|
sectPos = 2*sectID;
|
|
if (!actPQEntry->upDownFlag)
|
|
sectPos++;
|
|
res->Put(sectPos, ShortestPathTreeEntry(actPQEntry->valFromStart,
|
|
actPQEntry->upDownFlag));
|
|
|
|
dist = actPQEntry->valFromStart + fabs ( sectMeas2 - sectMeas1 );
|
|
pNetwork->GetReverseAdjacentSections ( actPQEntry->sectID,
|
|
actPQEntry->upDownFlag,
|
|
adjSectionList );
|
|
if (adjSectionList.size() != 0) {
|
|
for ( size_t i = 0; i <adjSectionList.size();i++ ) {
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(),
|
|
dist,dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
actPQEntry->sectID,
|
|
actPQEntry->upDownFlag),
|
|
visitedSect, 0);
|
|
}
|
|
} else {
|
|
if (!actPQEntry->upDownFlag) sectPos--;
|
|
else sectPos++;
|
|
res->Put(sectPos,
|
|
ShortestPathTreeEntry(actPQEntry->valFromStart +
|
|
fabs(sectMeas2 - sectMeas1),
|
|
!actPQEntry->upDownFlag));
|
|
|
|
}
|
|
adjSectionList.clear();
|
|
if (actSection != 0) {
|
|
actSection->DeleteIfAllowed();
|
|
actSection = 0;
|
|
}
|
|
if (actPQEntry != 0) {
|
|
delete actPQEntry;
|
|
actPQEntry=0;
|
|
}
|
|
}
|
|
prioQ->Destroy();
|
|
delete prioQ;
|
|
visitedSect->Destroy();
|
|
delete visitedSect;
|
|
startSection->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
/*
|
|
Almost analogous to reverse shortest path tree but stops computation if all
|
|
sections of ~toReach~ are inserted.
|
|
|
|
*/
|
|
|
|
void GPoint::ReverseShortestPathTree(const Network* pNetwork,
|
|
DbArray<ShortestPathTreeEntry> *res,
|
|
SortedTree<Entry<SectionValue> > *toReach) const{
|
|
if (IsDefined() && pNetwork != 0 && pNetwork->IsDefined() &&
|
|
GetNetworkId() == pNetwork->GetId() && res != 0) {
|
|
TupleId startSectionTID = pNetwork->GetTupleIdSectionOnRoute(this);
|
|
PrioQueueA *prioQ = new PrioQueueA ( 0 );
|
|
SectIDTreeP *visitedSect = new SectIDTreeP ( 0);
|
|
int pHelp = -1;
|
|
int sectPos = -1;
|
|
Tuple* startSection = pNetwork->GetSection(startSectionTID);
|
|
double sectMeas1 =
|
|
((CcReal* )startSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
double sectMeas2 =
|
|
((CcReal*)startSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
//int actRouteId =
|
|
// ((CcInt*)startSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
int sectID =
|
|
((CcInt*)startSection->GetAttribute(SECTION_SID))->GetIntval();
|
|
res->Put(2*sectID, ShortestPathTreeEntry(0.0, true));
|
|
res->Put(2*sectID + 1, ShortestPathTreeEntry(0.0, false));
|
|
toReach->Remove(Entry<SectionValue>(SectionValue(sectID, true)));
|
|
toReach->Remove(Entry<SectionValue>(SectionValue(sectID, false)));
|
|
double dist = fabs(GetPosition() - sectMeas2);
|
|
visitedSect->Insert(SectIDTreeEntry(
|
|
SectEntry(startSectionTID,
|
|
startSectionTID,
|
|
false, false,
|
|
-1,
|
|
0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
visitedSect->Insert(SectIDTreeEntry(
|
|
SectEntry(startSectionTID,
|
|
startSectionTID,
|
|
true, true,
|
|
-1,
|
|
0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
vector<DirectedSection> adjSectionList;
|
|
adjSectionList.clear();
|
|
pNetwork->GetReverseAdjacentSections (startSectionTID, false,
|
|
adjSectionList );
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ ){
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(), dist, dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectionTID, false ),
|
|
visitedSect, 0);
|
|
}
|
|
adjSectionList.clear();
|
|
dist = fabs(sectMeas1 - GetPosition());
|
|
|
|
pNetwork->GetReverseAdjacentSections ( startSectionTID, true,
|
|
adjSectionList );
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ ) {
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(), dist,dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectionTID, true ),
|
|
visitedSect, 0);
|
|
}
|
|
adjSectionList.clear();
|
|
PQEntryA* actPQEntry = 0;
|
|
while (!prioQ->IsEmpty() && !toReach->isEmpty()) {
|
|
actPQEntry = prioQ->GetAndDeleteMin(visitedSect);
|
|
Tuple *actSection = pNetwork->GetSection ( actPQEntry->sectID );
|
|
sectMeas1 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
sectMeas2 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
//actRouteId =
|
|
// ((CcInt*)actSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
sectID =
|
|
((CcInt*)actSection->GetAttribute(SECTION_SID))->GetIntval();
|
|
sectPos = 2*sectID;
|
|
if (!actPQEntry->upDownFlag) sectPos++;
|
|
res->Put(sectPos, ShortestPathTreeEntry(actPQEntry->valFromStart,
|
|
actPQEntry->upDownFlag));
|
|
toReach->Remove(Entry<SectionValue>(SectionValue(sectID,
|
|
actPQEntry->upDownFlag)));
|
|
dist = actPQEntry->valFromStart + fabs ( sectMeas2 - sectMeas1 );
|
|
pNetwork->GetReverseAdjacentSections ( actPQEntry->sectID,
|
|
actPQEntry->upDownFlag,
|
|
adjSectionList );
|
|
if (adjSectionList.size() != 0) {
|
|
for ( size_t i = 0; i <adjSectionList.size();i++ ) {
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(),
|
|
dist,dist,
|
|
actNextSect.GetUpDownFlag(),
|
|
actPQEntry->sectID,
|
|
actPQEntry->upDownFlag),
|
|
visitedSect, 0);
|
|
}
|
|
} else {
|
|
if (!actPQEntry->upDownFlag) sectPos--;
|
|
else sectPos++;
|
|
res->Put(sectPos,
|
|
ShortestPathTreeEntry(actPQEntry->valFromStart +
|
|
fabs(sectMeas2 - sectMeas1),
|
|
!actPQEntry->upDownFlag));
|
|
toReach->Remove(Entry<SectionValue>(SectionValue(sectID,
|
|
!actPQEntry->upDownFlag)));
|
|
}
|
|
adjSectionList.clear();
|
|
if (actSection != 0) {
|
|
actSection->DeleteIfAllowed();
|
|
actSection = 0;
|
|
}
|
|
if (actPQEntry != 0) {
|
|
delete actPQEntry;
|
|
actPQEntry=0;
|
|
}
|
|
}
|
|
prioQ->Destroy();
|
|
delete prioQ;
|
|
visitedSect->Destroy();
|
|
delete visitedSect;
|
|
startSection->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
/*
|
|
Almost analogous to reverse shortest path tree but stops computation if all
|
|
sections from which the gpoint can be reached within maxdist are inserted.
|
|
|
|
*/
|
|
|
|
void GPoint::In_Circle(const Network* pNetwork, GLine* res,
|
|
const double maxdist) const
|
|
{
|
|
res->Clear();
|
|
RITreeP *ritree = new RITreeP(0);
|
|
if (IsDefined() && pNetwork != 0 && pNetwork->IsDefined() &&
|
|
GetNetworkId() == pNetwork->GetId() && res != 0)
|
|
{
|
|
res->SetDefined(true);
|
|
res->SetNetworkId(GetNetworkId());
|
|
TupleId startSectionTID = pNetwork->GetTupleIdSectionOnRoute(this);
|
|
PrioQueueA *prioQ = new PrioQueueA ( 0 );
|
|
SectIDTreeP *visitedSect = new SectIDTreeP ( 0);
|
|
int pHelp = -1;
|
|
Tuple* startSection = pNetwork->GetSection(startSectionTID);
|
|
double sectMeas1 =
|
|
((CcReal* )startSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
double sectMeas2 =
|
|
((CcReal*)startSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
int actRouteId =
|
|
((CcInt*)startSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
double dist1 = fabs(GetPosition() - sectMeas1);
|
|
double dist2 = fabs(GetPosition() - sectMeas2);
|
|
double length = fabs(sectMeas2 - sectMeas1);
|
|
bool s1 = true;
|
|
bool s2 = true;
|
|
if (length <= maxdist)
|
|
{
|
|
ritree->Insert(actRouteId, sectMeas1, sectMeas2);
|
|
}
|
|
else
|
|
{
|
|
if (dist1 <= maxdist )
|
|
ritree->Insert(actRouteId, sectMeas1, GetPosition());
|
|
else
|
|
{
|
|
ritree->Insert(actRouteId, GetPosition() - maxdist, GetPosition());
|
|
s1 = false;
|
|
}
|
|
if (dist2 <= maxdist)
|
|
ritree->Insert(actRouteId, GetPosition(), sectMeas2);
|
|
else
|
|
{
|
|
ritree->Insert(actRouteId, GetPosition(), GetPosition() + maxdist );
|
|
s2 = false;
|
|
}
|
|
}
|
|
visitedSect->Insert(SectIDTreeEntry(SectEntry(startSectionTID,
|
|
startSectionTID,
|
|
false, false, -1, 0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
visitedSect->Insert(SectIDTreeEntry(SectEntry(startSectionTID,
|
|
startSectionTID,
|
|
true, true, -1, 0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
vector<DirectedSection> adjSectionList;
|
|
adjSectionList.clear();
|
|
if (s1)
|
|
{
|
|
pNetwork->GetReverseAdjacentSections (startSectionTID, false,
|
|
adjSectionList );
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(), dist2, dist2,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectionTID, false ),
|
|
visitedSect, 0);
|
|
}
|
|
adjSectionList.clear();
|
|
}
|
|
if (s2)
|
|
{
|
|
pNetwork->GetReverseAdjacentSections ( startSectionTID, true,
|
|
adjSectionList );
|
|
for ( size_t i = 0; i < adjSectionList.size(); i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(), dist1, dist1,
|
|
actNextSect.GetUpDownFlag(),
|
|
startSectionTID, true ),
|
|
visitedSect, 0);
|
|
}
|
|
adjSectionList.clear();
|
|
}
|
|
PQEntryA* actPQEntry = 0;
|
|
double actDist = 0.0;
|
|
bool reached = false;
|
|
while (!prioQ->IsEmpty() && !reached)
|
|
{
|
|
actPQEntry = prioQ->GetAndDeleteMin(visitedSect);
|
|
if (actPQEntry->valFromStart > maxdist)
|
|
{
|
|
reached = true;
|
|
}
|
|
else
|
|
{
|
|
Tuple *actSection = pNetwork->GetSection ( actPQEntry->sectID );
|
|
sectMeas1 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
sectMeas2 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
actRouteId =
|
|
((CcInt*)actSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
length = fabs(sectMeas2 - sectMeas1);
|
|
actDist = actPQEntry->valFromStart + length;
|
|
if(actDist <= maxdist)
|
|
{
|
|
ritree->Insert(actRouteId, sectMeas1, sectMeas2);
|
|
pNetwork->GetReverseAdjacentSections ( actPQEntry->sectID,
|
|
actPQEntry->upDownFlag,
|
|
adjSectionList );
|
|
if (adjSectionList.size() != 0)
|
|
{
|
|
for ( size_t i = 0; i <adjSectionList.size();i++ )
|
|
{
|
|
DirectedSection actNextSect = adjSectionList[i];
|
|
prioQ->Insert ( PQEntryA ( actNextSect.GetSectionTid(),
|
|
actDist,actDist,
|
|
actNextSect.GetUpDownFlag(),
|
|
actPQEntry->sectID,
|
|
actPQEntry->upDownFlag),
|
|
visitedSect, 0);
|
|
}
|
|
adjSectionList.clear();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (actPQEntry->upDownFlag)
|
|
{
|
|
ritree->Insert(actRouteId,
|
|
sectMeas2 - fabs(maxdist - actPQEntry->valFromStart),
|
|
sectMeas2);
|
|
}
|
|
else
|
|
{
|
|
ritree->Insert(actRouteId, sectMeas1,
|
|
sectMeas1 + fabs(maxdist - actPQEntry->valFromStart));
|
|
}
|
|
}
|
|
if (actSection != 0)
|
|
{
|
|
actSection->DeleteIfAllowed();
|
|
actSection = 0;
|
|
}
|
|
}
|
|
if (actPQEntry != 0)
|
|
{
|
|
delete actPQEntry;
|
|
actPQEntry=0;
|
|
}
|
|
}
|
|
ritree->TreeToGLine(res,0);
|
|
res->SetSorted(true);
|
|
prioQ->Destroy();
|
|
delete prioQ;
|
|
visitedSect->Destroy();
|
|
delete visitedSect;
|
|
startSection->DeleteIfAllowed();
|
|
}
|
|
else
|
|
{
|
|
res->SetDefined(false);
|
|
}
|
|
ritree->Destroy();
|
|
delete ritree;
|
|
}
|
|
|
|
/*
|
|
Returns the route intervals whithin distance maxdist from ~GPoint~ ignoring
|
|
connectivity in the junctions.
|
|
|
|
*/
|
|
|
|
void GPoint::Circle(const Network* pNetwork, GLine *res,
|
|
const double maxdist) const
|
|
{
|
|
res->Clear();
|
|
if (IsDefined() && pNetwork != 0 && pNetwork->IsDefined() &&
|
|
GetNetworkId() == pNetwork->GetId() && res != 0)
|
|
{
|
|
res->SetNetworkId(GetNetworkId());
|
|
res->SetDefined(true);
|
|
GLine *outcircle = new GLine(0);
|
|
Out_Circle(pNetwork, outcircle, maxdist);
|
|
GLine *incircle = new GLine(0);
|
|
In_Circle(pNetwork, incircle, maxdist);
|
|
incircle->Uniongl(outcircle, res);
|
|
outcircle->DeleteIfAllowed();
|
|
incircle->DeleteIfAllowed();
|
|
res->SetSorted(true);
|
|
}
|
|
else res->SetDefined(false);
|
|
}
|
|
|
|
/*
|
|
Returns the x,y point represented by gpoint.
|
|
|
|
*/
|
|
|
|
void GPoint::ToPoint ( Point *&res )const
|
|
{
|
|
//Network *pNetwork = NetworkManager::GetNetwork(GetNetworkId());
|
|
Network* pNetwork = NetworkManager::GetNetworkNew ( GetNetworkId(), netList );
|
|
if ( pNetwork != 0 )
|
|
{
|
|
pNetwork->GetPointOnRoute ( this, res );
|
|
}
|
|
else
|
|
{
|
|
res->SetDefined ( false );
|
|
}
|
|
NetworkManager::CloseNetwork ( pNetwork );
|
|
};
|
|
|
|
Point* GPoint::ToPoint() const
|
|
{
|
|
Point *res = new Point ( true );
|
|
//Network *pNetwork = NetworkManager::GetNetwork(GetNetworkId());
|
|
Network* pNetwork = NetworkManager::GetNetworkNew ( GetNetworkId(), netList );
|
|
if ( pNetwork != 0 ) pNetwork->GetPointOnRoute ( this, res );
|
|
NetworkManager::CloseNetwork ( pNetwork );
|
|
return res;
|
|
};
|
|
|
|
Point* GPoint::ToPoint ( const Network*& pNetwork ) const
|
|
{
|
|
Point *res = new Point ( true );
|
|
if ( pNetwork != 0 ) pNetwork->GetPointOnRoute ( this, res );
|
|
return res;
|
|
};
|
|
|
|
/*
|
|
Returns the bounding GPoints of the given GLine.
|
|
|
|
*/
|
|
|
|
void GLine::GetBGP(GPoints* result)const
|
|
{
|
|
result->Clear();
|
|
if (!IsDefined() || NoOfComponents()==0)
|
|
{
|
|
result->SetDefined(false);
|
|
}
|
|
else
|
|
{
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
GetBGP(pNetwork, result);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
}
|
|
}
|
|
|
|
void GLine::GetBGP(const Network* pNetwork, GPoints* result)const
|
|
{
|
|
result->Clear();
|
|
if ( !IsDefined() || NoOfComponents() == 0 )
|
|
{
|
|
result->SetDefined(false);
|
|
}
|
|
else
|
|
{
|
|
RouteInterval ri;
|
|
vector<SectTreeEntry> actSections;
|
|
actSections.clear();
|
|
for (int i = 0; i < Size(); i++)
|
|
{
|
|
Get(i, ri);
|
|
pNetwork->GetSectionsOfRouteInterval(&ri, actSections);
|
|
SectTreeEntry nEntry;
|
|
for (size_t a = 0; a < actSections.size() ; a++)
|
|
{
|
|
nEntry = actSections[a];
|
|
vector<DirectedSection> adjSect;
|
|
adjSect.clear();
|
|
if (!nEntry.startbool)
|
|
{
|
|
result->MergeAdd(GPoint(true, GetNetworkId(), nEntry.rid,
|
|
nEntry.start),
|
|
pNetwork);
|
|
}
|
|
else
|
|
{
|
|
pNetwork->GetAdjacentSections(nEntry.secttid, false, adjSect);
|
|
for (size_t b = 0; b < adjSect.size(); b++)
|
|
{
|
|
DirectedSection actDirSection = adjSect[b];
|
|
if (actDirSection.GetSectionTid() != nEntry.secttid)
|
|
{
|
|
Tuple* actSection =
|
|
pNetwork->GetSection(actDirSection.GetSectionTid());
|
|
RouteInterval* pri =
|
|
new RouteInterval(
|
|
((CcInt*)actSection->GetAttribute(SECTION_RID))->GetIntval(),
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS1))->GetRealval() +
|
|
1.0*pNetwork->GetScalefactor(),
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS2))->GetRealval() -
|
|
1.0*pNetwork->GetScalefactor());
|
|
actSection->DeleteIfAllowed();
|
|
actSection = 0;
|
|
if (!Intersects(pri, pNetwork->GetScalefactor()*0.01))
|
|
{
|
|
result->MergeAdd(GPoint(true, GetNetworkId(), nEntry.rid,
|
|
nEntry.start),
|
|
pNetwork);
|
|
adjSect.clear();
|
|
delete pri;
|
|
break;
|
|
}
|
|
delete pri;
|
|
pri = 0;
|
|
}
|
|
}
|
|
adjSect.clear();
|
|
}
|
|
if (!nEntry.endbool)
|
|
{
|
|
result->MergeAdd(GPoint(true, GetNetworkId(), nEntry.rid,
|
|
nEntry.end),
|
|
pNetwork);
|
|
}
|
|
else
|
|
{
|
|
pNetwork->GetAdjacentSections(nEntry.secttid, true, adjSect);
|
|
for (size_t b = 0; b < adjSect.size(); b++)
|
|
{
|
|
DirectedSection actDirSection = adjSect[b];
|
|
if (actDirSection.GetSectionTid() != nEntry.secttid)
|
|
{
|
|
Tuple* actSection =
|
|
pNetwork->GetSection(actDirSection.GetSectionTid());
|
|
RouteInterval* pri1 =
|
|
new RouteInterval(
|
|
((CcInt*)actSection->GetAttribute(SECTION_RID))->GetIntval(),
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS1))->GetRealval() +
|
|
1.0 *pNetwork->GetScalefactor(),
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS2))->GetRealval() -
|
|
1.0*pNetwork->GetScalefactor());
|
|
actSection->DeleteIfAllowed();
|
|
actSection = 0;
|
|
if (!Intersects(pri1, pNetwork->GetScalefactor()*0.01))
|
|
{
|
|
result->MergeAdd(GPoint(true, GetNetworkId(), nEntry.rid,
|
|
nEntry.end),
|
|
pNetwork);
|
|
adjSect.clear();
|
|
delete pri1;
|
|
break;
|
|
}
|
|
delete pri1;
|
|
pri1 = 0;
|
|
}
|
|
}
|
|
adjSect.clear();
|
|
}
|
|
}
|
|
actSections.clear();
|
|
}
|
|
result->SetDefined(true);
|
|
}
|
|
};
|
|
|
|
bool GLine::Contains(const RouteInterval* ri, const double tolerance)const
|
|
{
|
|
if (IsSorted())
|
|
{
|
|
return searchRouteInterval(ri, this,tolerance, 0, NoOfComponents()-1);
|
|
}
|
|
else
|
|
{
|
|
RouteInterval rigl;
|
|
for (int i = 0; i < NoOfComponents(); i++)
|
|
{
|
|
Get(i,rigl);
|
|
if (rigl.Contains(ri, tolerance)) return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
|
|
/*
|
|
Secondo Type Constructor for class ~GPoint~
|
|
|
|
*/
|
|
|
|
struct gpointInfo:ConstructorInfo{
|
|
gpointInfo():ConstructorInfo(){
|
|
name = GPoint::BasicType();
|
|
signature = "-> DATA";
|
|
typeExample = GPoint::BasicType();
|
|
listRep = "(<netId> <routeId> <pos> <side>)";
|
|
valueExample = "(1 2 5.4 1)";
|
|
remarks = "Single position in a network.";
|
|
}
|
|
};
|
|
|
|
struct gpointFunctions: ConstructorFunctions<GPoint>{
|
|
gpointFunctions(){
|
|
in = GPoint::InGPoint;
|
|
out = GPoint::OutGPoint;
|
|
create = GPoint::CreateGPoint;
|
|
deletion = GPoint::DeleteGPoint;
|
|
open = OpenAttribute<GPoint>;
|
|
save = SaveAttribute<GPoint>;
|
|
close = GPoint::CloseGPoint;
|
|
cast = GPoint::CastGPoint;
|
|
clone = GPoint::CloneGPoint;
|
|
sizeOf = GPoint::SizeOfGPoint;
|
|
kindCheck = GPoint::CheckGPoint;
|
|
}
|
|
};
|
|
|
|
gpointInfo gpi;
|
|
gpointFunctions gf;
|
|
TypeConstructor gpointTC(gpi,gf);
|
|
|
|
/*
|
|
5 Class GPoints implemented by Jianqiu Xu
|
|
|
|
*/
|
|
|
|
string edistjoinpointlist = "(rel(tuple((pid int)(p point))))";
|
|
enum edistjoinpointlistrelation {POINTSID = 0,POINTSOBJECT};
|
|
|
|
GPoints::GPoints():Attribute()
|
|
{}
|
|
|
|
GPoints::GPoints(const bool def):Attribute(def),m_xGPoints(0)
|
|
{}
|
|
|
|
GPoints::GPoints ( const int in_iSize ) :Attribute(true),m_xGPoints ( in_iSize )
|
|
{}
|
|
|
|
GPoints::GPoints (const GPoints* in_xOther ) :
|
|
Attribute(in_xOther->IsDefined()),
|
|
m_xGPoints ( in_xOther->Size() )
|
|
{
|
|
GPoint pCurrentInterval;
|
|
for ( int i = 0; i < in_xOther->m_xGPoints.Size(); i++ )
|
|
{
|
|
// Get next Interval
|
|
in_xOther->m_xGPoints.Get ( i, pCurrentInterval );
|
|
m_xGPoints.Append ( pCurrentInterval );
|
|
}
|
|
SetDefined(in_xOther->IsDefined());
|
|
TrimToSize();
|
|
}
|
|
|
|
void GPoints::Clear()
|
|
{
|
|
m_xGPoints.clean();
|
|
SetDefined(true);
|
|
}
|
|
|
|
bool GPoints::IsEmpty() const
|
|
{
|
|
return m_xGPoints.Size() == 0;
|
|
}
|
|
ostream& GPoints::Print ( ostream& os ) const
|
|
{
|
|
if (IsDefined())
|
|
{
|
|
for ( int i = 0;i < m_xGPoints.Size();i++ )
|
|
{
|
|
GPoint pGP;
|
|
m_xGPoints.Get ( i,pGP );
|
|
os<<"GPoint "<< i <<": ";
|
|
pGP.Print(os);
|
|
os << endl;
|
|
}
|
|
}
|
|
else os << "not defined." << endl;
|
|
return os;
|
|
}
|
|
|
|
GPoints& GPoints::operator= ( const GPoints& gps )
|
|
{
|
|
SetDefined(gps.IsDefined());
|
|
m_xGPoints.copyFrom(gps.m_xGPoints);
|
|
return *this;
|
|
}
|
|
|
|
int GPoints::NumOfFLOBs() const
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
Flob* GPoints::GetFLOB ( const int i )
|
|
{
|
|
assert ( i >= 0 && i < NumOfFLOBs() );
|
|
return &m_xGPoints;
|
|
}
|
|
|
|
size_t GPoints::Sizeof() const
|
|
{
|
|
return sizeof ( *this );
|
|
}
|
|
|
|
int GPoints::SizeOf()
|
|
{
|
|
return sizeof ( GPoints );
|
|
}
|
|
int GPoints::Size() const
|
|
{
|
|
return m_xGPoints.Size();
|
|
}
|
|
|
|
GPoints& GPoints::operator+= ( const GPoint& gp )
|
|
{
|
|
m_xGPoints.Append ( gp );
|
|
TrimToSize();
|
|
return *this;
|
|
}
|
|
|
|
void GPoints::MergeAdd(const GPoint gp, const Network* pNetwork)
|
|
{
|
|
if (!Contains(gp,pNetwork)) m_xGPoints.Append(gp);
|
|
}
|
|
|
|
bool GPoints::Contains(const GPoint gp)const
|
|
{
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(gp.GetNetworkId(),netList);
|
|
bool result = Contains(gp,pNetwork);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return result;
|
|
}
|
|
|
|
bool GPoints::Contains(const GPoint gp, const Network* pNetwork) const
|
|
{
|
|
GPointList *gpl = new GPointList(&gp,pNetwork);
|
|
GPoint gptest = gpl->NextGPoint();
|
|
while (gptest.IsDefined())
|
|
{
|
|
GPoint gpold;
|
|
for (int i = 0; i < m_xGPoints.Size(); i++)
|
|
{
|
|
m_xGPoints.Get(i,gpold);
|
|
if (gpold == gptest)
|
|
{
|
|
gpl->Destroy();
|
|
delete gpl;
|
|
return true;
|
|
}
|
|
}
|
|
gptest = gpl->NextGPoint();
|
|
}
|
|
gpl->Destroy();
|
|
delete gpl;
|
|
return false;
|
|
}
|
|
|
|
int GPoints::GetNetworkId() const
|
|
{
|
|
if(!IsDefined() || Size() < 1) return -1;
|
|
GPoint gp;
|
|
Get(0,gp);
|
|
return gp.GetNetworkId();
|
|
}
|
|
|
|
bool GPoints::Inside(const GPoint gp)const
|
|
{
|
|
if (!IsDefined() || Size() < 1) return false;
|
|
GPoint gp1;
|
|
for (int i = 0; i < Size(); i++)
|
|
{
|
|
Get(0,gp1);
|
|
if (gp1 == gp) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void GPoints::GetSectionTupleIds(DbArray<GPointsSections>* gpSections,
|
|
const Network *pNetwork)const
|
|
{
|
|
GPoint gp;
|
|
for (int i = 0 ; i < Size() ; i++)
|
|
{
|
|
Get(i,gp);
|
|
Point *pPoint = gp.ToPoint(pNetwork);
|
|
gpSections->Append(GPointsSections(gp,
|
|
pNetwork->GetTupleIdSectionOnRoute(&gp),
|
|
*pPoint));
|
|
pPoint->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
|
|
bool GPoints::Intersects(const GPoints* bgp)const
|
|
{
|
|
if(!IsDefined() || !bgp->IsDefined() || Size() < 1 || bgp->Size() < 1)
|
|
return false;
|
|
GPoint gp;
|
|
Get(0,gp);
|
|
Network *pNetwork =
|
|
NetworkManager::GetNetworkNew(gp.GetNetworkId(),netList);
|
|
bool result = Intersects(bgp, pNetwork);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return result;
|
|
}
|
|
|
|
bool GPoints::Intersects(const GPoints* bgp, const Network* pNetwork)const
|
|
{
|
|
if(!IsDefined() || !bgp->IsDefined() || Size() < 1 || bgp->Size() < 1)
|
|
return false;
|
|
GPoint gp;
|
|
for (int i = 0; i < Size(); i++)
|
|
{
|
|
Get(i,gp);
|
|
if (bgp->Contains(gp,pNetwork))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool GPoints::ShortestPathAStar(const GPoints* bgp, GLine* res,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
res->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if(!IsDefined() || !bgp->IsDefined() || Size() < 1 || bgp->Size() < 1)
|
|
{
|
|
res->SetDefined(false);
|
|
return false;
|
|
}
|
|
Network *pNetwork =
|
|
NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
bool result = ShortestPathAStar(bgp, res, pNetwork, touchedSects);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return result;
|
|
}
|
|
|
|
|
|
bool GPoints::ShortestPathAStar(const GPoints* bgp, GLine* res,
|
|
const Network* pNetwork,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
res->Clear();
|
|
res->SetDefined(false);
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if(!IsDefined() || !bgp->IsDefined() || Size() < 1 || bgp->Size() < 1 ||
|
|
GetNetworkId() != bgp->GetNetworkId() ||
|
|
GetNetworkId() != pNetwork->GetId())
|
|
{
|
|
return false;
|
|
}
|
|
if (Intersects(bgp,pNetwork))
|
|
{
|
|
res->SetDefined(true);
|
|
res->SetNetworkId(pNetwork->GetId());
|
|
return true;
|
|
}
|
|
DbArray<GPointsSections>* startSections = new DbArray<GPointsSections>(0);
|
|
DbArray<GPointsSections>* endSections = new DbArray<GPointsSections>(0);
|
|
GetSectionTupleIds(startSections,pNetwork);
|
|
bgp->GetSectionTupleIds(endSections,pNetwork);
|
|
if (startSections->Size() < 1 || endSections->Size() < 1)
|
|
{
|
|
startSections->Destroy();
|
|
endSections->Destroy();
|
|
delete startSections;
|
|
delete endSections;
|
|
return false;
|
|
}
|
|
Points* endPoints = new Points(endSections->Size());
|
|
endPoints->StartBulkLoad();
|
|
GPointsSections gps;
|
|
for (int i = 0; i < endSections->Size(); i++)
|
|
{
|
|
endSections->Get(i,gps);
|
|
*endPoints += gps.GetPoint();
|
|
}
|
|
endPoints->EndBulkLoad();
|
|
/*
|
|
Initialize PriorityQueue
|
|
|
|
*/
|
|
GPointsSections source, target;
|
|
PrioQueueA* prioQ = new PrioQueueA(0);
|
|
SectIDTreeP *visitedSect = new SectIDTreeP (0);
|
|
double dist = 0.0;
|
|
int pHelp = -1;
|
|
double sectMeas1 = 0.0;
|
|
double sectMeas2 = 0.0;
|
|
double startRI = 0.0;
|
|
double endRI = 0.0;
|
|
int actRouteId = -1;
|
|
int lastSectPos = -1;
|
|
int firstSectPos = -1;
|
|
Tuple *actSection = 0;
|
|
for (int i = 0; i < startSections->Size(); i++)
|
|
{
|
|
startSections->Get(i,source);
|
|
visitedSect->Insert(SectIDTreeEntry(
|
|
SectEntry(source.GetTid(),
|
|
(TupleId) numeric_limits<long>::max(),
|
|
true, true,
|
|
-1,
|
|
0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
visitedSect->Insert(SectIDTreeEntry(
|
|
SectEntry(source.GetTid(),
|
|
(TupleId) numeric_limits<long>::max(),
|
|
false, false,
|
|
-1,
|
|
0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
if (touchedSects != 0) touchedSects->Append(source.GetTid());
|
|
if (IsLastSection(source.GetTid(), endSections, lastSectPos))
|
|
{
|
|
endSections->Get(lastSectPos,target);
|
|
if (source.GetGP().GetRouteId() == target.GetGP().GetRouteId())
|
|
{
|
|
RouteInterval* ri = new RouteInterval(source.GetGP().GetRouteId(),
|
|
source.GetGP().GetPosition(),
|
|
target.GetGP().GetPosition());
|
|
double length = ri->Length();
|
|
i++;
|
|
while (i < startSections->Size())
|
|
{
|
|
startSections->Get(i,source);
|
|
visitedSect->Insert(SectIDTreeEntry(
|
|
SectEntry(source.GetTid(),
|
|
(TupleId) numeric_limits<long>::max(),
|
|
true,true,
|
|
-1,
|
|
0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
visitedSect->Insert(SectIDTreeEntry(
|
|
SectEntry(source.GetTid(),
|
|
(TupleId) numeric_limits<long>::max(),
|
|
false,false,
|
|
-1,
|
|
0.0),
|
|
-1,-1),
|
|
pHelp);
|
|
if (touchedSects != 0) touchedSects->Append(source.GetTid());
|
|
if (IsLastSection(source.GetTid(), endSections, lastSectPos))
|
|
{
|
|
endSections->Get(lastSectPos,target);
|
|
if (source.GetGP().GetRouteId() == target.GetGP().GetRouteId() &&
|
|
fabs(source.GetGP().GetPosition() -
|
|
target.GetGP().GetPosition())
|
|
< length)
|
|
{
|
|
ri->SetStartPos(source.GetGP().GetPosition());
|
|
ri->SetEndPos(target.GetGP().GetPosition());
|
|
ri->SetRouteId(source.GetGP().GetRouteId());
|
|
length = ri->Length();
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
res->AddRouteInterval(*ri);
|
|
delete ri;
|
|
startSections->Destroy();
|
|
endSections->Destroy();
|
|
delete startSections;
|
|
delete endSections;
|
|
endPoints->Destroy();
|
|
delete endPoints;
|
|
prioQ->Destroy();
|
|
delete prioQ;
|
|
visitedSect->Destroy();
|
|
delete visitedSect;
|
|
res->SetDefined(true);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
if (startSections->Size() > 0) {
|
|
for (int i = 0; i < startSections->Size(); i++)
|
|
{
|
|
startSections->Get(i,source);
|
|
dist = source.GetGP().GetPosition();
|
|
InsertAdjacentSections(source.GetTid(), Up, true, dist, endPoints,
|
|
pNetwork, prioQ, visitedSect, touchedSects);
|
|
dist = source.GetGP().GetPosition();
|
|
InsertAdjacentSections(source.GetTid(), Down, true, dist, endPoints,
|
|
pNetwork, prioQ, visitedSect, touchedSects);
|
|
}
|
|
}
|
|
|
|
/*
|
|
Use priorityQueue to find shortestPath.
|
|
|
|
*/
|
|
|
|
PQEntryA *actPQEntry = 0;
|
|
bool found = false;
|
|
while (!prioQ->IsEmpty() && !found )
|
|
{
|
|
actPQEntry = prioQ->GetAndDeleteMin ( visitedSect );
|
|
actSection = pNetwork->GetSection ( actPQEntry->sectID );
|
|
if (!IsLastSection(actPQEntry->sectID, endSections, lastSectPos))
|
|
{
|
|
dist = actPQEntry->valFromStart;
|
|
if (actPQEntry->upDownFlag)
|
|
InsertAdjacentSections(actPQEntry->sectID, Up, false, dist, endPoints,
|
|
pNetwork, prioQ, visitedSect, touchedSects);
|
|
else
|
|
InsertAdjacentSections(actPQEntry->sectID, Down, false, dist, endPoints,
|
|
pNetwork, prioQ, visitedSect, touchedSects);
|
|
delete actPQEntry;
|
|
actPQEntry = 0;
|
|
actSection->DeleteIfAllowed();
|
|
actSection = 0;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
Shortest Path nearly found.
|
|
|
|
It might exist another endSection in the priority queue
|
|
with the same distance from the start section, where the distance of the
|
|
gpoint is nearer to the end of the last section. Therefore we have to check
|
|
the values of the priorty queue with the same weight. To find the correct
|
|
end Section.
|
|
|
|
Compute last route interval and resulting gline.
|
|
|
|
*/
|
|
found = true;
|
|
endSections->Get(lastSectPos, target);
|
|
endRI = target.GetGP().GetPosition();
|
|
sectMeas1 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
sectMeas2 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
actRouteId =
|
|
((CcInt*)actSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
if (bgp->Contains(GPoint(true,GetNetworkId(),actRouteId,sectMeas1),
|
|
pNetwork) &&
|
|
bgp->Contains(GPoint(true,GetNetworkId(),actRouteId,sectMeas2),
|
|
pNetwork))
|
|
startRI = endRI;
|
|
else
|
|
{
|
|
if ( actPQEntry->upDownFlag)
|
|
startRI = sectMeas1;
|
|
else
|
|
startRI = sectMeas2;
|
|
}
|
|
double minPathLength = actPQEntry->valFromStart + fabs(endRI-startRI);
|
|
bool btestended = false;
|
|
while (!btestended && !prioQ->IsEmpty())
|
|
{
|
|
PQEntryA* pqtest = prioQ->GetAndDeleteMin(visitedSect);
|
|
if (pqtest->prioval < minPathLength)
|
|
{
|
|
int posLastTest = -1;
|
|
Tuple *actTestSection = pNetwork->GetSection(pqtest->sectID);
|
|
int actTestRouteId =
|
|
((CcInt*)actTestSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
if (!IsLastSection(pqtest->sectID, endSections, posLastTest))
|
|
{
|
|
dist = pqtest->valFromStart;
|
|
if (pqtest->upDownFlag)
|
|
InsertAdjacentSections(pqtest->sectID, Up, false, dist, endPoints,
|
|
pNetwork, prioQ, visitedSect,
|
|
touchedSects);
|
|
else
|
|
InsertAdjacentSections(pqtest->sectID, Down, false, dist,
|
|
endPoints, pNetwork, prioQ, visitedSect,
|
|
touchedSects);
|
|
delete pqtest;
|
|
pqtest = 0;
|
|
actTestSection->DeleteIfAllowed();
|
|
actTestSection = 0;
|
|
}
|
|
else
|
|
{
|
|
GPointsSections testgps;
|
|
endSections->Get(posLastTest,testgps);
|
|
double endTestRI = testgps.GetGP().GetPosition();
|
|
double testSectMeas1 =
|
|
((CcReal*)actTestSection->GetAttribute(SECTION_MEAS1))
|
|
->GetRealval();
|
|
double testSectMeas2 =
|
|
((CcReal*)actTestSection->GetAttribute(SECTION_MEAS2))
|
|
->GetRealval();
|
|
double startTestRI = 0.0;
|
|
if (bgp->Contains(GPoint(true,GetNetworkId(),actTestRouteId,
|
|
testSectMeas1), pNetwork) &&
|
|
bgp->Contains(GPoint(true,GetNetworkId(),actTestRouteId,
|
|
testSectMeas2),pNetwork))
|
|
startTestRI = endTestRI;
|
|
else
|
|
{
|
|
if ( pqtest->upDownFlag)
|
|
startTestRI = testSectMeas1;
|
|
else
|
|
startTestRI = testSectMeas2;
|
|
}
|
|
double actPathLength =
|
|
pqtest->valFromStart + fabs(endTestRI - startTestRI);
|
|
if (actPathLength < minPathLength)
|
|
{
|
|
endRI = endTestRI;
|
|
startRI = startTestRI;
|
|
lastSectPos = posLastTest;
|
|
minPathLength = actPathLength;
|
|
actRouteId = actTestRouteId;
|
|
delete actPQEntry;
|
|
actPQEntry = pqtest;
|
|
actSection->DeleteIfAllowed();
|
|
actSection = actTestSection;
|
|
}
|
|
}
|
|
if (actSection != actTestSection && actTestSection != 0)
|
|
{
|
|
actTestSection->DeleteIfAllowed();
|
|
actTestSection = 0;
|
|
}
|
|
}
|
|
else
|
|
btestended = true;
|
|
if (pqtest != 0 && pqtest != actPQEntry)
|
|
{
|
|
delete pqtest;
|
|
pqtest = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
Get the sections used for shortest path and write them in right
|
|
order (from start to end gpoint) in the resulting gline. Because Dijkstra
|
|
gives the sections from end to start, we have to put the result sections
|
|
on a stack to turn them in right order.
|
|
|
|
*/
|
|
if (!found)
|
|
{
|
|
startSections->Destroy();
|
|
endSections->Destroy();
|
|
delete startSections;
|
|
delete endSections;
|
|
endPoints->Destroy();
|
|
delete endPoints;
|
|
prioQ->Destroy();
|
|
delete prioQ;
|
|
visitedSect->Destroy();
|
|
delete visitedSect;
|
|
res->SetDefined(false);
|
|
return false;
|
|
}
|
|
RIStackP *riStack = new RIStackP(0);
|
|
if (startRI != endRI) riStack->Push( actRouteId, startRI, endRI );
|
|
//TupleId lastSectId = actPQEntry->sectID;
|
|
int pElem = visitedSect->Find ( actPQEntry->beforeSectID,
|
|
actPQEntry->beforeUpDown );
|
|
bool end = false;
|
|
while ( !end && pElem > -1 && pElem < visitedSect->fFree)
|
|
{
|
|
SectEntry actSectEntry = visitedSect->GetTreeEntry(pElem).GetEntry();
|
|
//GetSection
|
|
TupleId actTupleId = actSectEntry.GetSectId();
|
|
bool upDown = actSectEntry.GetUpDownFlag();
|
|
if (actSection != 0) actSection->DeleteIfAllowed();
|
|
actSection = pNetwork->GetSection(actTupleId);
|
|
if (actSection != 0)
|
|
{
|
|
actRouteId =
|
|
(( CcInt*)actSection->GetAttribute(SECTION_RID))->GetIntval();
|
|
sectMeas1 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
sectMeas2 =
|
|
((CcReal*)actSection->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
actSection->DeleteIfAllowed();
|
|
actSection = 0;
|
|
if(!IsFirstSection(actTupleId, startSections, firstSectPos))
|
|
{
|
|
if ( actSectEntry.GetUpDownFlag())
|
|
riStack->Push ( actRouteId, sectMeas1, sectMeas2);
|
|
else
|
|
riStack->Push ( actRouteId, sectMeas2, sectMeas1);
|
|
//lastSectId = actTupleId;
|
|
pElem =
|
|
visitedSect->Find(actSectEntry.GetBeforeSectId(),
|
|
actSectEntry.GetBeforeSectUpDown());
|
|
}
|
|
else
|
|
{
|
|
end = true;
|
|
startSections->Get(firstSectPos,source);
|
|
if (!(Contains(GPoint(pNetwork->GetId(), actRouteId, sectMeas1, 2),
|
|
pNetwork) &&
|
|
Contains(GPoint(pNetwork->GetId(), actRouteId, sectMeas2, 2),
|
|
pNetwork)))
|
|
{
|
|
if (upDown)
|
|
riStack->Push ( actRouteId, source.GetGP().GetPosition(),
|
|
sectMeas2);
|
|
else
|
|
riStack->Push ( actRouteId, source.GetGP().GetPosition(),
|
|
sectMeas1);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
actSection->DeleteIfAllowed();
|
|
startSections->Destroy();
|
|
endSections->Destroy();
|
|
delete startSections;
|
|
delete endSections;
|
|
endPoints->Destroy();
|
|
delete endPoints;
|
|
prioQ->Destroy();
|
|
delete prioQ;
|
|
visitedSect->Destroy();
|
|
delete visitedSect;
|
|
res->SetDefined(false);
|
|
return false;
|
|
}
|
|
}
|
|
// Cleanup and return result
|
|
riStack->StackToGLine ( res, GetNetworkId() );
|
|
riStack->Destroy();
|
|
delete riStack;
|
|
if ( actSection )
|
|
{
|
|
actSection->DeleteIfAllowed();
|
|
actSection = 0;
|
|
}
|
|
if ( actPQEntry != 0)
|
|
{
|
|
delete actPQEntry;
|
|
actPQEntry = 0;
|
|
}
|
|
visitedSect->Destroy();
|
|
delete visitedSect;
|
|
prioQ->Destroy();
|
|
delete prioQ;
|
|
startSections->Destroy();
|
|
endSections->Destroy();
|
|
delete startSections;
|
|
delete endSections;
|
|
endPoints->Destroy();
|
|
delete endPoints;
|
|
res->SetSorted ( false );
|
|
res->SetDefined ( found);
|
|
res->TrimToSize();
|
|
return true;
|
|
}
|
|
|
|
bool GPoints::ShortestPathAStar(const GPoint* gp, GLine* res,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
res->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if(!IsDefined() || !gp->IsDefined() || Size() < 1 )
|
|
{
|
|
res->SetDefined(false);
|
|
return false;
|
|
}
|
|
Network *pNetwork =
|
|
NetworkManager::GetNetworkNew(gp->GetNetworkId(),netList);
|
|
bool result = ShortestPathAStar(gp, res, pNetwork, touchedSects);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return result;
|
|
}
|
|
|
|
bool GPoints::ShortestPathAStar(const GPoint* gp, GLine* res,
|
|
const Network* pNetwork,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
res->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if ( GetNetworkId() != gp->GetNetworkId() )
|
|
{
|
|
res->SetDefined(false);
|
|
return false;
|
|
}
|
|
res->SetNetworkId(pNetwork->GetId());
|
|
if (Contains(*gp))
|
|
{
|
|
res->SetDefined(true);
|
|
return true;
|
|
}
|
|
GPoints *bGPgl2 = new GPoints(true);
|
|
bGPgl2->MergeAdd(*gp,pNetwork);
|
|
bool bres = ShortestPathAStar(bGPgl2,res,pNetwork, touchedSects);
|
|
bGPgl2->DeleteIfAllowed();
|
|
return bres;
|
|
}
|
|
|
|
bool GPoints::ShortestPathAStar(const GLine* gl, GLine* res,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
res->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if(!IsDefined() || !gl->IsDefined() || Size() < 1 || gl->NoOfComponents() < 1)
|
|
{
|
|
res->SetDefined(false);
|
|
return false;
|
|
}
|
|
Network *pNetwork =
|
|
NetworkManager::GetNetworkNew(gl->GetNetworkId(),netList);
|
|
bool result = ShortestPathAStar(gl, res, pNetwork, touchedSects);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return result;
|
|
}
|
|
|
|
bool GPoints::ShortestPathAStar(const GLine* gl, GLine* res,
|
|
const Network* pNetwork,
|
|
DbArray<TupleId>* touchedSects)const
|
|
{
|
|
res->Clear();
|
|
if (touchedSects != 0) touchedSects->clean();
|
|
if ( GetNetworkId() != gl->GetNetworkId() )
|
|
{
|
|
cmsg.inFunError ( "Both glines must belong to the network." );
|
|
return false;
|
|
}
|
|
if (gl->Includes(this)) return true;
|
|
GPoints *bGPgl2 = new GPoints(true);
|
|
gl->GetBGP(pNetwork,bGPgl2);
|
|
bool bres = ShortestPathAStar(bGPgl2,res,pNetwork, touchedSects);
|
|
bGPgl2->DeleteIfAllowed();
|
|
return bres;
|
|
}
|
|
|
|
double GPoints::NetdistanceNew(const GPoints* bgp, const Network* pNetwork)const
|
|
{
|
|
double res = -1.0;
|
|
if(!IsDefined() || !bgp->IsDefined() || Size() < 1 || bgp->Size() < 1)
|
|
return res;
|
|
if (Intersects(bgp,pNetwork)) return 0.0;
|
|
GLine* pSP = new GLine(true);
|
|
if (ShortestPathAStar(bgp,pSP,pNetwork,0))
|
|
res = pSP->GetLength();
|
|
pSP->DeleteIfAllowed();
|
|
return res;
|
|
}
|
|
|
|
double GPoints::NetdistanceNew(const GPoints* bgp)const
|
|
{
|
|
double result = -1.0;
|
|
if(!IsDefined()||Size() < 1 || !bgp->IsDefined() || bgp->Size() < 1)
|
|
return result;
|
|
Network *pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
result = NetdistanceNew(bgp,pNetwork);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return result;
|
|
}
|
|
|
|
double GPoints::NetdistanceNew(const GPoint* gp, const Network* pNetwork)const
|
|
{
|
|
double res = -1.0;
|
|
if(!IsDefined() || !gp->IsDefined() || Size() < 1)
|
|
return res;
|
|
GLine* pSP = new GLine(0);
|
|
if (ShortestPathAStar(gp, pSP, pNetwork, 0))
|
|
res = pSP->GetLength();
|
|
pSP->DeleteIfAllowed();
|
|
return res;
|
|
}
|
|
|
|
double GPoints::NetdistanceNew(const GPoint* gp)const
|
|
{
|
|
double res = -1.0;
|
|
if(!IsDefined() || Size() < 1 || !gp->IsDefined())
|
|
return res;
|
|
Network *pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
res = NetdistanceNew(gp,pNetwork);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return res;
|
|
}
|
|
|
|
double GPoints::NetdistanceNew(const GLine* gl, const Network* pNetwork)const
|
|
{
|
|
double res = -1.0;
|
|
if(!IsDefined() || !gl->IsDefined() || Size() < 1 || gl->NoOfComponents()<1)
|
|
return res;
|
|
if (gl->Includes(this,pNetwork)) return 0.0;
|
|
GLine* pSP = new GLine(0);
|
|
if (ShortestPathAStar(gl, pSP, pNetwork, 0))
|
|
res = pSP->GetLength();
|
|
pSP->DeleteIfAllowed();
|
|
return res;
|
|
}
|
|
|
|
double GPoints::NetdistanceNew(const GLine* gl)const
|
|
{
|
|
double res = -1.0;
|
|
if(!IsDefined()||Size() < 1 || !gl->IsDefined() || gl->NoOfComponents() < 1)
|
|
return res;
|
|
Network *pNetwork = NetworkManager::GetNetworkNew(GetNetworkId(),netList);
|
|
res = NetdistanceNew(gl,pNetwork);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return res;
|
|
}
|
|
|
|
GPoints& GPoints::operator-= ( const GPoint& gp )
|
|
{
|
|
GPoints *nGPs = new GPoints ( 0 );
|
|
GPoint actGP;
|
|
for ( int i = 0; i < m_xGPoints.Size(); i++ )
|
|
{
|
|
m_xGPoints.Get ( i, actGP );
|
|
if ( gp != actGP ) nGPs->m_xGPoints.Append ( actGP );
|
|
}
|
|
nGPs->TrimToSize();
|
|
return *nGPs;
|
|
}
|
|
|
|
void GPoints::Get ( const int i, GPoint& pgp ) const
|
|
{
|
|
assert ( i >= 0 && i < m_xGPoints.Size() );
|
|
m_xGPoints.Get ( i,pgp );
|
|
}
|
|
|
|
|
|
ListExpr GPoints::Out ( ListExpr in_xTypeInfo,
|
|
Word in_xValue )
|
|
{
|
|
|
|
GPoints *pGPS = ( GPoints* ) (in_xValue.addr);
|
|
//if (!pGPS->IsDefined()) return nl->SymbolAtom("undef");
|
|
if ( pGPS->IsEmpty())
|
|
{
|
|
return nl->TheEmptyList();
|
|
}
|
|
GPoint pgp;
|
|
pGPS->Get ( 0,pgp );
|
|
ListExpr result =
|
|
nl->OneElemList(GPoint::OutGPoint(nl->TheEmptyList(),
|
|
SetWord((void*)&pgp)));
|
|
ListExpr last = result;
|
|
if (pGPS->Size() > 1)
|
|
{
|
|
for ( int i = 1; i < pGPS->Size();i++ )
|
|
{
|
|
pGPS->Get ( i,pgp );
|
|
last =
|
|
nl->Append(last,GPoint::OutGPoint (nl->TheEmptyList(),
|
|
SetWord((void*)&pgp)));
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
Word GPoints::In ( const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct )
|
|
{
|
|
if ( nl->ListLength ( instance ) == 0 )
|
|
{
|
|
correct = false;
|
|
cmsg.inFunError ( "Empty List" );
|
|
return SetWord ( Address ( 0 ) );
|
|
}
|
|
GPoints* pGPS = new GPoints ( nl->ListLength ( instance ) );
|
|
if (nl->IsEqual(instance,"undef"))
|
|
{
|
|
correct = true;
|
|
pGPS->SetDefined(false);
|
|
return SetWord(Address(pGPS));
|
|
}
|
|
|
|
ListExpr rest = instance;
|
|
while ( !nl->IsEmpty ( rest ) )
|
|
{
|
|
ListExpr first = nl->First ( rest );
|
|
rest = nl->Rest ( rest );
|
|
if (nl->ListLength ( first ) != 4)
|
|
{
|
|
correct = false;
|
|
cmsg.inFunError ( "GPoint incorrect.Expected list of 4 Elements." );
|
|
return SetWord ( Address ( 0 ) );
|
|
}
|
|
GPoint* pgp =
|
|
( GPoint*)GPoint::InGPoint(nl->TheEmptyList(),
|
|
first,
|
|
0,
|
|
errorInfo,
|
|
correct ).addr;
|
|
if ( correct )
|
|
{
|
|
( *pGPS ) += ( *pgp );
|
|
pgp->DeleteIfAllowed();
|
|
}
|
|
else
|
|
{
|
|
pgp->DeleteIfAllowed();
|
|
}
|
|
}
|
|
pGPS->SetDefined ( true );
|
|
pGPS->TrimToSize();
|
|
return SetWord ( pGPS );
|
|
}
|
|
|
|
bool GPoints::OpenGPoints ( SmiRecord& valueRecord,size_t& offset,
|
|
const ListExpr typeInfo, Word& value )
|
|
{
|
|
GPoints* pGPS = ( GPoints* ) Attribute::Open ( valueRecord,offset,typeInfo );
|
|
value = SetWord ( pGPS );
|
|
pGPS->TrimToSize();
|
|
return true;
|
|
}
|
|
bool GPoints::SaveGPoints ( SmiRecord& valueRecord,size_t& offset,
|
|
const ListExpr typeInfo, Word& value )
|
|
{
|
|
GPoints* pGPS = ( GPoints* ) value.addr;
|
|
Attribute::Save ( valueRecord,offset,typeInfo,pGPS );
|
|
return true;
|
|
}
|
|
|
|
Word GPoints::Create ( const ListExpr typeInfo )
|
|
{
|
|
return SetWord ( new GPoints ( true ) );
|
|
}
|
|
|
|
void GPoints::Delete ( const ListExpr typeInfo,
|
|
Word& w )
|
|
{
|
|
GPoints *gp = ( GPoints * ) w.addr;
|
|
// if (l->del.refs == 1) { l->m_xRouteIntervals.Destroy();}
|
|
if ( gp->DeleteIfAllowed() == true )
|
|
w.addr = 0;
|
|
}
|
|
|
|
void GPoints::Close ( const ListExpr typeInfo,
|
|
Word& w )
|
|
{
|
|
if ( ( ( GPoints* ) w.addr )->DeleteIfAllowed() == true )
|
|
w.addr = 0;
|
|
}
|
|
|
|
Word GPoints::CloneGPoints ( const ListExpr typeInfo,
|
|
const Word& w )
|
|
{
|
|
return SetWord ( ( ( GPoints* ) w.addr )->Clone() );
|
|
}
|
|
|
|
GPoints* GPoints::Clone() const
|
|
{
|
|
GPoints *xOther = new GPoints ( Size() );
|
|
xOther->SetDefined ( IsDefined() );
|
|
xOther->m_xGPoints.copyFrom(m_xGPoints);
|
|
return xOther;
|
|
}
|
|
|
|
void* GPoints::Cast ( void* addr )
|
|
{
|
|
return new ( addr ) GPoints;
|
|
}
|
|
|
|
bool GPoints::Check ( ListExpr type, ListExpr& errorInfo )
|
|
{
|
|
return ( nl->IsEqual ( type, GPoints::BasicType() ) );
|
|
}
|
|
|
|
|
|
int GPoints::Compare ( const Attribute* a) const
|
|
{
|
|
GPoints* pGPS = (GPoints*) a;
|
|
if (Size() < pGPS->Size()) return -1;
|
|
if (Size() > pGPS->Size()) return 1;
|
|
GPoint gp1, gp2;
|
|
for (int i = 0; i < Size(); i++)
|
|
{
|
|
Get(i,gp1);
|
|
Get(i,gp2);
|
|
if (gp1.Compare(gp2) != 0) return gp1.Compare(gp2);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool GPoints::Adjacent ( const Attribute* a) const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
size_t GPoints::HashValue() const
|
|
{
|
|
size_t xHash = 0;
|
|
// Iterate over all GPoint objects
|
|
for ( int i = 0; i < m_xGPoints.Size(); ++i )
|
|
{
|
|
// Get next Interval
|
|
GPoint pCurrentInterval;
|
|
m_xGPoints.Get ( i, pCurrentInterval );
|
|
|
|
// Add something for each entry
|
|
int iNetworkId = pCurrentInterval.GetNetworkId();
|
|
int iRouteId = pCurrentInterval.GetRouteId();
|
|
double iPosition = pCurrentInterval.GetPosition();
|
|
int iSide = ( int ) pCurrentInterval.GetSide();
|
|
xHash += iNetworkId + iRouteId + ( size_t ) iPosition + iSide;
|
|
}
|
|
return xHash;
|
|
}
|
|
|
|
void GPoints::CopyFrom ( const Attribute* right )
|
|
{
|
|
*this = * ( ( const GPoints * ) right );
|
|
}
|
|
|
|
struct gpointsInfo:ConstructorInfo{
|
|
gpointsInfo(){
|
|
name = GPoints::BasicType();
|
|
signature = "-> DATA";
|
|
typeExample = GPoints::BasicType();
|
|
listRep = "(<gpoint1> <gpoint2> ...)";
|
|
valueExample = "((1 34 235.65 1)(1 98 234.1 0))";
|
|
remarks = "Set of gpoint values.";
|
|
}
|
|
};
|
|
|
|
struct gpointsFunctions:ConstructorFunctions<GPoints>{
|
|
gpointsFunctions(){
|
|
in = GPoints::In;
|
|
out = GPoints::Out;
|
|
create = GPoints::Create;
|
|
deletion = GPoints::Delete;
|
|
open = GPoints::OpenGPoints;
|
|
save = GPoints::SaveGPoints;
|
|
close = GPoints::Close;
|
|
clone = GPoints::CloneGPoints;
|
|
cast = GPoints::Cast;
|
|
sizeOf = GPoints::SizeOf;
|
|
kindCheck = GPoints::Check;
|
|
}
|
|
};
|
|
|
|
gpointsInfo gpsi;
|
|
gpointsFunctions gpsf;
|
|
TypeConstructor gpointsTC(gpsi,gpsf);
|
|
|
|
|
|
|
|
/*
|
|
6 Secondo Operators
|
|
|
|
6.1 Operator ~netdistance~
|
|
|
|
Returns the network distance between two ~Gpoints~ or two ~GLines~. Using
|
|
Dijkstras Algorithm for computation of the shortest paths.
|
|
|
|
*/
|
|
|
|
ListExpr OpNetNetdistanceTypeMap ( ListExpr args )
|
|
{
|
|
if ( nl->ListLength ( args ) != 2 )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
ListExpr param1 = nl->First ( args );
|
|
ListExpr param2 = nl->Second ( args );
|
|
//ListExpr param3 = nl->Third(args);
|
|
|
|
if ( nl->IsAtom ( param1 ) && nl->AtomType ( param1 ) == SymbolType &&
|
|
nl->IsAtom ( param2 ) && nl->AtomType ( param2 ) == SymbolType &&
|
|
( ( nl->SymbolValue ( param1 ) == GPoint::BasicType() &&
|
|
nl->SymbolValue ( param2 ) == GPoint::BasicType() ) ||
|
|
( nl->SymbolValue ( param1 ) == GLine::BasicType() &&
|
|
nl->SymbolValue ( param2 ) == GLine::BasicType() ) ) )
|
|
{
|
|
return nl->SymbolAtom ( CcReal::BasicType() );
|
|
}
|
|
return nl->SymbolAtom ( Symbol::TYPEERROR() );
|
|
}
|
|
|
|
int OpNetNetdistance_gpgp ( Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier )
|
|
{
|
|
GPoint* pFromGPoint = ( GPoint* ) args[0].addr;
|
|
GPoint* pToGPoint = ( GPoint* ) args[1].addr;
|
|
result = qp->ResultStorage ( in_pSupplier );
|
|
CcReal* pResult = ( CcReal* ) result.addr;
|
|
if ( ! ( pFromGPoint->IsDefined() ) || ! ( pToGPoint->IsDefined() ) )
|
|
{
|
|
cmsg.inFunError ( "Both gpoint must be defined!" );
|
|
return 0;
|
|
};
|
|
double dist = pFromGPoint->Netdistance ( pToGPoint );
|
|
if ( dist > -1.0 ) pResult->Set ( true,dist );
|
|
else pResult->Set ( false, dist );
|
|
return 1;
|
|
};
|
|
|
|
int OpNetNetdistance_glgl ( Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier )
|
|
{
|
|
GLine* pGLine1 = ( GLine* ) args[0].addr;
|
|
GLine* pGLine2 = ( GLine* ) args[1].addr;
|
|
CcReal* pResult = ( CcReal* ) qp->ResultStorage ( in_pSupplier ).addr;
|
|
result = SetWord ( pResult );
|
|
if ( ! ( pGLine1->IsDefined() ) || ! ( pGLine2->IsDefined() ) )
|
|
{
|
|
cmsg.inFunError ( "Both gpoint must be defined!" );
|
|
return 0;
|
|
};
|
|
double dist = pGLine1->Netdistance ( pGLine2 );
|
|
if ( dist > -1.0 ) pResult->Set ( true, dist );
|
|
else pResult->Set ( false, dist );
|
|
return 1;
|
|
};
|
|
|
|
ValueMapping OpNetNetdistancemap[] =
|
|
{
|
|
OpNetNetdistance_gpgp,
|
|
OpNetNetdistance_glgl
|
|
};
|
|
|
|
int OpNetNetdistanceselect ( ListExpr args )
|
|
{
|
|
ListExpr arg1 = nl->First ( args );
|
|
ListExpr arg2 = nl->Second ( args );
|
|
if ( nl->SymbolValue ( arg1 ) == GPoint::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoint::BasicType() )
|
|
return 0;
|
|
if ( nl->SymbolValue ( arg1 ) == GLine::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GLine::BasicType() )
|
|
return 1;
|
|
return -1; // This point should never be reached
|
|
};
|
|
|
|
struct netdistanceInfo : OperatorInfo {
|
|
netdistanceInfo():OperatorInfo(){
|
|
name = "netdistance";
|
|
signature = "gpoint X gpoint -> real";
|
|
appendSignature("gline X gline -> real");
|
|
syntax = "netdistance(_,_)";
|
|
meaning = "Returns network distance from 1st to 2nd.";
|
|
}
|
|
};
|
|
|
|
ListExpr OpNetNetdistanceNewTypeMap ( ListExpr args )
|
|
{
|
|
NList param(args);
|
|
if (param.length() != 2)
|
|
{
|
|
return listutils::typeError("netdistancenew expects 2 arguments.");
|
|
}
|
|
if (!( param.first().isSymbol(GPoint::BasicType())
|
|
|| param.first().isSymbol(GLine::BasicType())
|
|
|| param.first().isSymbol(GPoints::BasicType())))
|
|
{
|
|
return
|
|
listutils::typeError("1.argument should be gpoint, gline or gpoints.");
|
|
}
|
|
if (!(param.second().isSymbol(GPoint::BasicType())
|
|
|| param.second().isSymbol(GLine::BasicType()) ||
|
|
param.second().isSymbol(GPoints::BasicType())))
|
|
{
|
|
return
|
|
listutils::typeError("2.argument should be gpoint, gline or gpoints.");
|
|
}
|
|
return nl->SymbolAtom ( CcReal::BasicType() );
|
|
}
|
|
|
|
template<class Source, class Target>
|
|
int OpNetNetdistanceNew ( Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier )
|
|
{
|
|
Source* pFrom = ( Source* ) args[0].addr;
|
|
Target* pTo = ( Target* ) args[1].addr;
|
|
CcReal* pResult = ( CcReal* ) qp->ResultStorage ( in_pSupplier ).addr;
|
|
result = SetWord ( pResult );
|
|
if ( ! ( pFrom->IsDefined() ) || ! ( pTo->IsDefined() ) )
|
|
{
|
|
cmsg.inFunError ( "Both arguments must be defined!" );
|
|
return 0;
|
|
}
|
|
double dist = pFrom->NetdistanceNew( pTo );
|
|
if ( dist > -1.0 ) pResult->Set ( true, dist );
|
|
else pResult->Set ( false, dist );
|
|
return 1;
|
|
};
|
|
|
|
|
|
ValueMapping OpNetNetdistanceNewmap[] =
|
|
{
|
|
OpNetNetdistanceNew<GPoint, GPoint>,
|
|
OpNetNetdistanceNew<GLine, GLine>,
|
|
OpNetNetdistanceNew<GPoints, GPoints>,
|
|
OpNetNetdistanceNew<GPoint, GLine>,
|
|
OpNetNetdistanceNew<GPoint, GPoints>,
|
|
OpNetNetdistanceNew<GLine, GPoint>,
|
|
OpNetNetdistanceNew<GLine, GPoints>,
|
|
OpNetNetdistanceNew<GPoints, GPoint>,
|
|
OpNetNetdistanceNew<GPoints, GLine>
|
|
};
|
|
|
|
int OpNetNetdistanceNewselect ( ListExpr args )
|
|
{
|
|
ListExpr arg1 = nl->First ( args );
|
|
ListExpr arg2 = nl->Second ( args );
|
|
if ( nl->SymbolValue ( arg1 ) == GPoint::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoint::BasicType() )
|
|
return 0;
|
|
if ( nl->SymbolValue ( arg1 ) == GLine::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GLine::BasicType() )
|
|
return 1;
|
|
if ( nl->SymbolValue ( arg1 ) == GPoints::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoints::BasicType() )
|
|
return 2;
|
|
if ( nl->SymbolValue ( arg1 ) == GPoint::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GLine::BasicType() )
|
|
return 3;
|
|
if ( nl->SymbolValue ( arg1 ) == GPoint::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoints::BasicType() )
|
|
return 4;
|
|
if ( nl->SymbolValue ( arg1 ) == GLine::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoint::BasicType() )
|
|
return 5;
|
|
if ( nl->SymbolValue ( arg1 ) == GLine::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoints::BasicType() )
|
|
return 6;
|
|
if ( nl->SymbolValue ( arg1 ) == GPoints::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoint::BasicType() )
|
|
return 7;
|
|
if ( nl->SymbolValue ( arg1 ) == GPoints::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GLine::BasicType() )
|
|
return 8;
|
|
return -1; // This point should never be reached
|
|
};
|
|
|
|
struct netdistanceNewInfo : OperatorInfo {
|
|
netdistanceNewInfo():OperatorInfo(){
|
|
name = "netdistancenew";
|
|
signature = "gpoint X gpoint -> real";
|
|
appendSignature("gline X gline -> real");
|
|
appendSignature("gpoints X gpoints -> real");
|
|
appendSignature("gpoint x gline -> real");
|
|
appendSignature("gpoint x gpoints-> real");
|
|
appendSignature("gline X gpoint -> real");
|
|
appendSignature("gline X gpoints -> real");
|
|
appendSignature("gpoints X gpoint -> real");
|
|
appendSignature("gpoints X gline -> real");
|
|
syntax = "netdistancenew(_,_)";
|
|
meaning = "Network distance from 1st to 2nd using AStar.";
|
|
}
|
|
};
|
|
|
|
/*
|
|
6.2 Operator ~gpoint2rect~
|
|
|
|
Returns a rectangle degenerated to a point with coordinates rid, rid, pos, pos.
|
|
|
|
*/
|
|
|
|
ListExpr OpGPoint2RectTypeMap ( ListExpr in_xArgs )
|
|
{
|
|
if ( nl->ListLength ( in_xArgs ) != 1 )
|
|
{
|
|
sendMessage ( "Expects a list of length 1." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
ListExpr xsource = nl->First ( in_xArgs );
|
|
|
|
if ( ( !nl->IsAtom ( xsource ) ) ||
|
|
!nl->IsEqual ( xsource, GPoint::BasicType() ) )
|
|
{
|
|
sendMessage ( "Element must be of type gpoint." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
return ( nl->SymbolAtom ( Rectangle<2>::BasicType() ) );
|
|
}
|
|
|
|
int OpGPoint2RectValueMapping ( Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier in_xSupplier )
|
|
{
|
|
result = qp->ResultStorage ( in_xSupplier );
|
|
Rectangle<2>* box = static_cast<Rectangle<2>* > ( result.addr );
|
|
GPoint* arg = static_cast<GPoint*> ( args[0].addr );
|
|
if ( !arg->IsDefined() )
|
|
{
|
|
box->SetDefined ( false );
|
|
}
|
|
else
|
|
{
|
|
( *box ) = arg->NetBoundingBox();
|
|
}
|
|
return 0;
|
|
} //end ValueMapping
|
|
|
|
struct gpoint2rectInfo:OperatorInfo{
|
|
gpoint2rectInfo():OperatorInfo(){
|
|
name = "gpoint2rect";
|
|
signature = "gpoint -> rect";
|
|
syntax ="gpoint2rect(_)";
|
|
meaning = "Returns a rectangle representing the gpoint.";
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
6.3 Operator ~inside~
|
|
|
|
Returns true if ths ~GPoint~ is inside the ~GLine~ false elsewhere.
|
|
|
|
*/
|
|
ListExpr OpInsideTypeMap ( ListExpr args )
|
|
{
|
|
if ( nl->ListLength ( args ) != 2 )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
ListExpr gpoint = nl->First ( args );
|
|
ListExpr gline = nl->Second ( args );
|
|
if ( !nl->IsAtom ( gpoint ) || nl->AtomType ( gpoint ) != SymbolType ||
|
|
nl->SymbolValue ( gpoint ) != GPoint::BasicType() ||
|
|
!nl->IsAtom ( gline ) ||
|
|
nl->AtomType ( gline ) != SymbolType || nl->SymbolValue ( gline ) !=
|
|
GLine::BasicType() )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
return nl->SymbolAtom ( CcBool::BasicType() );
|
|
}
|
|
|
|
int OpInsideValueMap ( Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier )
|
|
{
|
|
GPoint* pGPoint = ( GPoint* ) args[0].addr;
|
|
GLine* pGLine = ( GLine* ) args[1].addr;
|
|
result = qp->ResultStorage ( in_pSupplier );
|
|
CcBool* pResult = ( CcBool* ) result.addr;
|
|
if ( pGPoint->GetNetworkId() != pGLine->GetNetworkId() ||
|
|
!pGLine->IsDefined() || !pGPoint->IsDefined() )
|
|
{
|
|
pResult->Set ( false, false );
|
|
}
|
|
pResult->Set ( true, pGPoint->Inside ( pGLine ,0.0) );
|
|
return 0;
|
|
}
|
|
|
|
struct insideInfo : OperatorInfo{
|
|
insideInfo():OperatorInfo(){
|
|
name = "inside";
|
|
signature = "gpoint X gline -> bool";
|
|
syntax = "_ inside _";
|
|
meaning = "Returns true if the gpoint is on the gline.";
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
6.4 Operator ~length~
|
|
|
|
Returns the length of a ~GLine~.
|
|
|
|
*/
|
|
ListExpr OpLengthTypeMap ( ListExpr args )
|
|
{
|
|
if ( nl->ListLength ( args ) != 1 )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
ListExpr gline = nl->First ( args );
|
|
if ( !nl->IsAtom ( gline ) || nl->AtomType ( gline ) != SymbolType ||
|
|
nl->SymbolValue ( gline ) != GLine::BasicType() )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
return nl->SymbolAtom ( CcReal::BasicType() );
|
|
}
|
|
|
|
int OpLengthValueMap ( Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier )
|
|
{
|
|
GLine* pGline = ( GLine* ) args[0].addr;
|
|
result = qp->ResultStorage ( in_pSupplier );
|
|
CcReal* pResult = ( CcReal* ) result.addr;
|
|
if ( ! ( pGline->IsDefined() ) )
|
|
{
|
|
cmsg.inFunError ( "gline is not defined!" );
|
|
return 0;
|
|
};
|
|
pResult-> Set ( true, pGline->GetLength() );
|
|
return 1;
|
|
}
|
|
|
|
struct lengthInfo: OperatorInfo{
|
|
lengthInfo():OperatorInfo(){
|
|
name = "length";
|
|
signature = "gline -> real";
|
|
syntax = "length(_)";
|
|
meaning = "Returns the length of the gline.";
|
|
}
|
|
};
|
|
|
|
/*
|
|
6.5 Operator ~line2gline~
|
|
|
|
Translates a spatial ~line~ value into a network ~GLine~ value if possible.
|
|
|
|
*/
|
|
|
|
ListExpr OpLine2GLineTypeMap ( ListExpr in_xArgs )
|
|
{
|
|
if ( nl->ListLength ( in_xArgs ) != 2 )
|
|
{
|
|
sendMessage ( "Expects a list of length 2." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
ListExpr xNetworkIdDesc = nl->First ( in_xArgs );
|
|
ListExpr xLineDesc = nl->Second ( in_xArgs );
|
|
|
|
if ( ( !nl->IsAtom ( xNetworkIdDesc ) ) ||
|
|
!nl->IsEqual ( xNetworkIdDesc, "network" ) )
|
|
{
|
|
sendMessage ( "First element must be of type network." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
if ( ( !nl->IsAtom ( xLineDesc ) ) ||
|
|
nl->AtomType ( xLineDesc ) != SymbolType ||
|
|
nl->SymbolValue ( xLineDesc ) != Line::BasicType() )
|
|
{
|
|
sendMessage ( "Second element must be of type sline." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
return nl->SymbolAtom ( GLine::BasicType() );
|
|
}
|
|
|
|
int OpLine2GLineValueMapping ( Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier in_xSupplier )
|
|
{
|
|
//Initialize return value
|
|
GLine* pGLine = ( GLine* ) qp->ResultStorage ( in_xSupplier ).addr;
|
|
result = SetWord ( pGLine );
|
|
// Get and check input values.
|
|
Network* pNetwork = ( Network* ) args[0].addr;
|
|
GLine *res = new GLine ( 0 );
|
|
if ( pNetwork == 0 || !pNetwork->IsDefined() )
|
|
{
|
|
string strMessage = "Network is not defined.";
|
|
cerr << strMessage << endl;
|
|
sendMessage ( strMessage );
|
|
res->SetDefined ( false );
|
|
pGLine->CopyFrom ( res );
|
|
res->DeleteIfAllowed();
|
|
return 0;
|
|
}
|
|
res->SetNetworkId ( pNetwork->GetId() );
|
|
Line* pLine = ( Line* ) args[1].addr;
|
|
if ( pLine == NULL || !pLine->IsDefined() )
|
|
{
|
|
string strMessage = "line does not exist.";
|
|
cerr << strMessage << endl;
|
|
sendMessage ( strMessage );
|
|
res->SetDefined ( false );
|
|
pGLine->CopyFrom ( res );
|
|
res->DeleteIfAllowed();
|
|
return 0;
|
|
}
|
|
if ( pLine->Size() <= 0 )
|
|
{
|
|
string strMessage = "line is empty";
|
|
cerr <<strMessage << endl;
|
|
sendMessage ( strMessage );
|
|
res->SetDefined ( true );
|
|
pGLine->CopyFrom ( res );
|
|
res->DeleteIfAllowed();
|
|
return 0;
|
|
}
|
|
|
|
HalfSegment hs;
|
|
pLine->Get ( 0,hs );
|
|
RouteInterval *ri =
|
|
pNetwork->Find ( hs.GetLeftPoint(), hs.GetRightPoint() );
|
|
if ( ri!= 0 )
|
|
{
|
|
RITree *riTree = new RITree ( ri->GetRouteId(), ri->GetStartPos(),
|
|
ri->GetEndPos() );
|
|
delete ri;
|
|
for ( int i = 1; i < pLine->Size();i++ )
|
|
{
|
|
pLine->Get ( i,hs );
|
|
ri = pNetwork->Find ( hs.GetLeftPoint(), hs.GetRightPoint() );
|
|
if ( ri!=0 )
|
|
{
|
|
riTree->Insert ( ri->GetRouteId(), ri->GetStartPos(), ri->GetEndPos() );
|
|
delete ri;
|
|
}
|
|
}
|
|
riTree->TreeToGLine ( res );
|
|
riTree->RemoveTree();
|
|
res->SetDefined ( true );
|
|
res->SetSorted ( true );
|
|
pGLine->CopyFrom ( res );
|
|
res->DeleteIfAllowed();
|
|
}
|
|
else
|
|
{
|
|
res->SetDefined ( false );
|
|
pGLine->CopyFrom ( res );
|
|
res->DeleteIfAllowed();
|
|
}
|
|
return 0;
|
|
} //end ValueMapping
|
|
|
|
struct line2glineInfo : OperatorInfo{
|
|
line2glineInfo():OperatorInfo(){
|
|
name = "line2gline";
|
|
signature = "network X line -> gline";
|
|
syntax = "line2gline(_,_)";
|
|
meaning = "Translates a line into an gline if possible.";
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
6.6 Operator ~=~
|
|
|
|
Returns true if two ~GPoint~s respectively ~GLine~s are identical false
|
|
elsewhere.
|
|
|
|
*/
|
|
|
|
ListExpr OpNetEqualTypeMap ( ListExpr args )
|
|
{
|
|
NList param(args);
|
|
|
|
if ( param.length() != 2 )
|
|
return listutils::typeError("Two arguments expected.");
|
|
|
|
NList arg1(param.first());
|
|
NList arg2(param.second());
|
|
|
|
if (!(arg1.isSymbol(GPoint::BasicType())
|
|
|| arg1.isSymbol(GLine::BasicType())))
|
|
return listutils::typeError("expected gpoint or gline values");
|
|
|
|
if (arg1 != arg2)
|
|
return listutils::typeError("Arguments must be of same type.");
|
|
else
|
|
return nl->SymbolAtom ( CcBool::BasicType() );
|
|
}
|
|
|
|
template<class Arg>
|
|
int OpNetEqual ( Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier )
|
|
{
|
|
Arg* p1 = ( Arg* ) args[0].addr;
|
|
Arg* p2 = ( Arg* ) args[1].addr;
|
|
result = qp->ResultStorage ( in_pSupplier );
|
|
CcBool* pResult = ( CcBool* ) result.addr;
|
|
if ( ! ( p1->IsDefined() ) || !p2->IsDefined() )
|
|
{
|
|
cmsg.inFunError ( "Both arguments must be defined!" );
|
|
pResult->Set ( false, false );
|
|
return 1;
|
|
};
|
|
pResult-> Set ( true, *p1 == *p2 );
|
|
return 0;
|
|
}
|
|
|
|
ValueMapping OpNetEqualmap[] =
|
|
{
|
|
OpNetEqual<GPoint>,
|
|
OpNetEqual<GLine>,
|
|
};
|
|
|
|
int OpNetEqualselect ( ListExpr args )
|
|
{
|
|
ListExpr arg1 = nl->First ( args );
|
|
ListExpr arg2 = nl->Second ( args );
|
|
if ( nl->SymbolValue ( arg1 ) == GPoint::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoint::BasicType() )
|
|
return 0;
|
|
if ( nl->SymbolValue ( arg1 ) == GLine::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GLine::BasicType() )
|
|
return 1;
|
|
return -1; // This point should never be reached
|
|
};
|
|
|
|
struct equalInfo:OperatorInfo{
|
|
equalInfo():OperatorInfo(){
|
|
name = "=";
|
|
signature = "gpoint X gpoint -> bool";
|
|
appendSignature("gline X gline -> bool");
|
|
syntax = "_ = _";
|
|
meaning = "Returns true if the two objects are equal";
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
6.7 Operator ~intersects~
|
|
|
|
Returns true if two ~Gline~ intersect false elsewhere.
|
|
|
|
*/
|
|
|
|
ListExpr OpNetIntersectsTypeMap ( ListExpr in_xArgs )
|
|
{
|
|
ListExpr arg1, arg2;
|
|
if ( nl->ListLength ( in_xArgs ) == 2 )
|
|
{
|
|
arg1 = nl->First ( in_xArgs );
|
|
arg2 = nl->Second ( in_xArgs );
|
|
if ( nl->IsAtom ( arg1 ) && nl->AtomType ( arg1 ) == SymbolType &&
|
|
nl->SymbolValue ( arg1 ) == GLine::BasicType() &&
|
|
nl->IsAtom ( arg2 ) &&
|
|
nl->AtomType ( arg2 ) == SymbolType &&
|
|
nl->SymbolValue ( arg2 ) == GLine::BasicType() )
|
|
{
|
|
return ( nl->SymbolAtom ( CcBool::BasicType() ) );
|
|
}
|
|
}
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
int OpNetIntersectsValueMapping ( Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier in_xSupplier )
|
|
{
|
|
// Get (empty) return value
|
|
CcBool* pResult = ( CcBool* ) qp->ResultStorage ( in_xSupplier ).addr;
|
|
result = SetWord ( pResult );
|
|
pResult->Set ( false, false );
|
|
// Get input values
|
|
GLine* pGLine1 = ( GLine* ) args[0].addr;
|
|
if ( pGLine1 == NULL || !pGLine1->IsDefined() )
|
|
{
|
|
cerr << "First gline does not exist." << endl;
|
|
pResult->Set ( false, false );
|
|
return 0;
|
|
}
|
|
GLine* pGLine2 = ( GLine* ) args[1].addr;
|
|
if ( pGLine2 == NULL || !pGLine2->IsDefined() )
|
|
{
|
|
cerr << "Second gline does not exist." << endl;
|
|
pResult->Set ( false, false );
|
|
return 0;
|
|
}
|
|
// const RouteInterval *pRi1, *pRi2;
|
|
if ( pGLine1->GetNetworkId() != pGLine2->GetNetworkId() )
|
|
{
|
|
cerr << "glines belong to different networks." << endl;
|
|
pResult->Set ( true, false );
|
|
return 0;
|
|
}
|
|
pResult->Set ( true, pGLine1->Intersects ( pGLine2 ) );
|
|
return 0;
|
|
}
|
|
|
|
struct intersectsInfo:OperatorInfo{
|
|
intersectsInfo():OperatorInfo(){
|
|
name = "intersects";
|
|
signature = "gline X gline -> bool";
|
|
syntax = "intersects(_,_)";
|
|
meaning = "Returns true if the glines intersect.";
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
6.8 Operator ~junctions~
|
|
|
|
Returns the junctions relation of the network.
|
|
|
|
*/
|
|
ListExpr OpNetworkJunctionsTypeMap ( ListExpr args )
|
|
{
|
|
ListExpr arg1;
|
|
if ( nl->ListLength ( args ) == 1 )
|
|
{
|
|
arg1 = nl->First ( args );
|
|
if ( nl->IsAtom ( arg1 ) &&
|
|
nl->AtomType ( arg1 ) == SymbolType &&
|
|
nl->SymbolValue ( arg1 ) == "network" )
|
|
{
|
|
ListExpr xType;
|
|
nl->ReadFromString ( Network::junctionsInternalTypeInfo, xType );
|
|
return xType;
|
|
}
|
|
}
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
int OpNetworkJunctionsValueMapping ( Word* args, Word& result, int message,
|
|
Word& local, Supplier s )
|
|
{
|
|
Network *network = ( Network* ) args[0].addr;
|
|
result = SetWord ( network->GetJunctions() );
|
|
|
|
Relation *resultSt = ( Relation* ) qp->ResultStorage ( s ).addr;
|
|
resultSt->Close();
|
|
qp->ChangeResultStorage ( s, result );
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct junctionsInfo:OperatorInfo{
|
|
junctionsInfo():OperatorInfo(){
|
|
name = "junctions";
|
|
signature = "network -> rel";
|
|
syntax = "junctions(_)";
|
|
meaning = "Returns a relation with the junctions of the network";
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
6.9 Operator ~routes~
|
|
|
|
Returns the routes relation of the network.
|
|
|
|
*/
|
|
ListExpr OpNetworkRoutesTypeMap ( ListExpr args )
|
|
{
|
|
ListExpr arg1;
|
|
if ( nl->ListLength ( args ) == 1 )
|
|
{
|
|
arg1 = nl->First ( args );
|
|
if ( nl->IsAtom ( arg1 ) &&
|
|
nl->AtomType ( arg1 ) == SymbolType &&
|
|
nl->SymbolValue ( arg1 ) == "network" )
|
|
{
|
|
ListExpr xType;
|
|
nl->ReadFromString ( Network::routesTypeInfo, xType );
|
|
return xType;
|
|
}
|
|
}
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
int OpNetworkRoutesValueMapping ( Word* args, Word& result, int message,
|
|
Word& local, Supplier s )
|
|
{
|
|
Network *network = ( Network* ) args[0].addr;
|
|
Relation* pRoute = network->GetRoutes();
|
|
result = SetWord ( pRoute->Clone() );
|
|
Relation *resultSt = ( Relation* ) qp->ResultStorage ( s ).addr;
|
|
resultSt->Close();
|
|
qp->ChangeResultStorage ( s, result );
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct routesInfo:OperatorInfo{
|
|
routesInfo():OperatorInfo(){
|
|
name = "routes";
|
|
signature = "network -> rel";
|
|
syntax = "routes(_)";
|
|
meaning = "Returns a relation with the routes of the network.";
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
6.10 Operator ~sections~
|
|
|
|
Returns the sections relation of the network.
|
|
|
|
*/
|
|
|
|
ListExpr OpNetworkSectionsTypeMap ( ListExpr args )
|
|
{
|
|
ListExpr arg1;
|
|
if ( nl->ListLength ( args ) == 1 )
|
|
{
|
|
arg1 = nl->First ( args );
|
|
if ( nl->IsAtom ( arg1 ) &&
|
|
nl->AtomType ( arg1 ) == SymbolType &&
|
|
nl->SymbolValue ( arg1 ) == "network" )
|
|
{
|
|
ListExpr xType;
|
|
nl->ReadFromString ( Network::sectionsInternalTypeInfo, xType );
|
|
return xType;
|
|
}
|
|
}
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
int OpNetworkSectionsValueMapping ( Word* args, Word& result, int message,
|
|
Word& local, Supplier s )
|
|
{
|
|
Network *network = ( Network* ) args[0].addr;
|
|
result = SetWord ( network->GetSections() );
|
|
|
|
Relation *resultSt = ( Relation* ) qp->ResultStorage ( s ).addr;
|
|
resultSt->Close();
|
|
qp->ChangeResultStorage ( s, result );
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct sectionsInfo:OperatorInfo{
|
|
sectionsInfo():OperatorInfo(){
|
|
name = "sections";
|
|
signature = "network -> rel";
|
|
syntax = "sections(_)";
|
|
meaning = "Returns a relation of the network sections.";
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
6.11 Operator ~thenetwork~
|
|
|
|
Creates a network with the given id, from the given routes and junctions
|
|
relations.
|
|
|
|
*/
|
|
ListExpr OpNetworkTheNetworkTypeMap ( ListExpr in_xArgs )
|
|
{
|
|
if ( nl->ListLength ( in_xArgs ) != 4 )
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
|
|
ListExpr xIdDesc = nl->First ( in_xArgs );
|
|
ListExpr xScaleDesc = nl->Second(in_xArgs);
|
|
ListExpr xRoutesRelDesc = nl->Third ( in_xArgs );
|
|
ListExpr xJunctionsRelDesc = nl->Fourth ( in_xArgs );
|
|
|
|
if ( !nl->IsEqual ( xIdDesc, CcInt::BasicType() ) )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
if ( !nl->IsEqual ( xScaleDesc, CcReal::BasicType() ) )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
if ( !IsRelDescription ( xRoutesRelDesc ) ||
|
|
!IsRelDescription ( xJunctionsRelDesc ) )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
ListExpr xType;
|
|
nl->ReadFromString ( Network::routesTypeInfo, xType );
|
|
if ( !CompareSchemas ( xRoutesRelDesc, xType ) )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
nl->ReadFromString ( Network::junctionsTypeInfo, xType );
|
|
if ( !CompareSchemas ( xJunctionsRelDesc, xType ) )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
return nl->SymbolAtom ( "network" );
|
|
}
|
|
|
|
int OpNetworkTheNetworkValueMapping ( Word* args, Word& result,
|
|
int message, Word& local, Supplier s )
|
|
{
|
|
Network* pNetwork = ( Network* ) qp->ResultStorage ( s ).addr;
|
|
CcInt* pId = ( CcInt* ) args[0].addr;
|
|
int iId = pId->GetIntval();
|
|
map<int,string>::iterator it = netList->find ( iId );
|
|
if ( it != netList->end() )
|
|
{
|
|
cerr << "NetworkId used before" << iId << endl;
|
|
while ( it != netList->end() )
|
|
{
|
|
it = netList->find ( ++iId );
|
|
}
|
|
cerr << "NetworkId changed to: " << iId << endl;
|
|
}
|
|
netList->insert ( pair<int,string> ( iId, "" ) );
|
|
double scalef = ((CcReal*)args[1].addr)->GetRealval();
|
|
Relation* pRoutes = ( Relation* ) args[2].addr;
|
|
Relation* pJunctions = ( Relation* ) args[3].addr;
|
|
pNetwork->Load ( iId,
|
|
scalef,
|
|
pRoutes,
|
|
pJunctions );
|
|
result = SetWord ( pNetwork );
|
|
|
|
return 0;
|
|
}
|
|
|
|
const string TheNetworkSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
|
"(<text>" + CcInt::BasicType() + " X " + CcReal::BasicType() + " X " +
|
|
Relation::BasicType() + " X " + Relation::BasicType() + " -> " +
|
|
Network::BasicType() + "</text--->"
|
|
"<text> thenetwork( <id> , <scaleinformation> , <roadsrel> , "+
|
|
"<crossings> ) </text--->"
|
|
"<text> Creates the network with identifier id, from the informations in "+
|
|
"the roads relation and crossings relation. The scaleinformation is used "+
|
|
"within map matching operations. It tells the system how much it must"+
|
|
"scale the given coordinates to get meter values for distances. Because " +
|
|
"the tolerance value of map matching computations must be given relativ to " +
|
|
"the data format. The input relations are expected to have tuples of type " +
|
|
"(int, real, sline, bool, bool) and (int, real, int, real, int) with "+
|
|
"meaning (rid, length, curve, dual, startssmaller) and (rid1, r1dist, rid2 " +
|
|
", r1dist, connectivity code)</text--->"
|
|
"<text> query thenetwork(1, 1.0, roads, crossings)</text--->))";
|
|
|
|
Operator theNetwork(
|
|
"thenetwork",
|
|
TheNetworkSpec,
|
|
OpNetworkTheNetworkValueMapping,
|
|
Operator::SimpleSelect,
|
|
OpNetworkTheNetworkTypeMap
|
|
);
|
|
|
|
|
|
/*
|
|
6.12 Operator ~no\_components~
|
|
|
|
Returns the number of ~RouteIntervals~ of the ~GLine~.
|
|
|
|
*/
|
|
|
|
ListExpr OpNoComponentsTypeMap ( ListExpr args )
|
|
{
|
|
if ( nl->ListLength ( args ) != 1 )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
ListExpr gline = nl->First ( args );
|
|
if ( !nl->IsAtom ( gline ) || nl->AtomType ( gline ) != SymbolType ||
|
|
nl->SymbolValue ( gline ) != GLine::BasicType() )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
return nl->SymbolAtom ( CcInt::BasicType() );
|
|
}
|
|
|
|
int OpNoComponentsValueMapping ( Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier )
|
|
{
|
|
GLine* pGline = ( GLine* ) args[0].addr;
|
|
result = qp->ResultStorage ( in_pSupplier );
|
|
CcInt* pResult = ( CcInt* ) result.addr;
|
|
if ( ! ( pGline->IsDefined() ) )
|
|
{
|
|
pResult->Set ( false, 0 );
|
|
return 0;
|
|
};
|
|
pResult-> Set ( true, pGline->NoOfComponents() );
|
|
return 1;
|
|
}
|
|
|
|
struct noComponentsInfo:OperatorInfo{
|
|
noComponentsInfo():OperatorInfo(){
|
|
name = "no_components";
|
|
signature = "gline -> int";
|
|
syntax = "no_components(_)";
|
|
meaning = "Returns the number of Route Intervals of the gline.";
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
6.13 Operator ~point2gpoint~
|
|
|
|
Translates a spatial ~Point~ value into a network ~GPoint~ value if possible.
|
|
|
|
*/
|
|
ListExpr OpPoint2GPointTypeMap ( ListExpr in_xArgs )
|
|
{
|
|
if ( nl->ListLength ( in_xArgs ) != 2 )
|
|
{
|
|
sendMessage ( "Expects a list of length 2." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
ListExpr xNetworkIdDesc = nl->First ( in_xArgs );
|
|
ListExpr xMPointDesc = nl->Second ( in_xArgs );
|
|
|
|
if ( ( !nl->IsAtom ( xNetworkIdDesc ) ) ||
|
|
!nl->IsEqual ( xNetworkIdDesc, "network" ) )
|
|
{
|
|
sendMessage ( "First element must be of type network." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
if ( ( !nl->IsAtom ( xMPointDesc ) ) ||
|
|
nl->AtomType ( xMPointDesc ) != SymbolType ||
|
|
nl->SymbolValue ( xMPointDesc ) != Point::BasicType() )
|
|
{
|
|
sendMessage ( "Second element must be of type point." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
return nl->SymbolAtom ( GPoint::BasicType() );
|
|
}
|
|
|
|
int OpPoint2GPointValueMapping ( Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier in_xSupplier )
|
|
{
|
|
GPoint* pGPoint = ( GPoint* ) qp->ResultStorage ( in_xSupplier ).addr;
|
|
result = SetWord ( pGPoint );
|
|
Network* pNetwork = ( Network* ) args[0].addr;
|
|
if ( pNetwork == 0 || !pNetwork->IsDefined() )
|
|
{
|
|
string strMessage = "Network is not defined.";
|
|
cerr << strMessage << endl;
|
|
sendMessage ( strMessage );
|
|
pGPoint->SetDefined ( false );
|
|
return 0;
|
|
}
|
|
|
|
Point* pPoint = ( Point* ) args[1].addr;
|
|
if ( pPoint == NULL || !pPoint->IsDefined() )
|
|
{
|
|
string strMessage = "Point does not exist.";
|
|
cerr << strMessage << endl;
|
|
sendMessage ( strMessage );
|
|
pGPoint->SetDefined ( false );
|
|
return 0;
|
|
}
|
|
GPoint *res = pNetwork->GetNetworkPosOfPoint ( *pPoint );
|
|
pGPoint->CopyFrom ( res );
|
|
res->DeleteIfAllowed();
|
|
/*GPoint *res = pNetwork->GetNetworkPosOfPoint(*pPoint);
|
|
qp->ChangeResultStorage(in_xSupplier, res);*/
|
|
return 0;
|
|
} //end ValueMapping
|
|
|
|
struct point2gpointInfo:OperatorInfo{
|
|
point2gpointInfo():OperatorInfo(){
|
|
name = "point2gpoint";
|
|
signature = "network X point -> gpoint";
|
|
syntax = "point2gpoint(_,_)";
|
|
meaning = "Translates a point into a gpoint value.";
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
6.14 Operator ~gpoint2point~
|
|
|
|
Translates a ~gpoint~ into a spatial ~Point~ value.
|
|
|
|
*/
|
|
|
|
ListExpr OpGPoint2PointTypeMap ( ListExpr in_xArgs )
|
|
{
|
|
if ( nl->ListLength ( in_xArgs ) != 1 )
|
|
{
|
|
sendMessage ( "Expects a list of length 1." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
ListExpr xMPointDesc = nl->First ( in_xArgs );
|
|
|
|
if ( ( !nl->IsAtom ( xMPointDesc ) ) ||
|
|
nl->AtomType ( xMPointDesc ) != SymbolType ||
|
|
nl->SymbolValue ( xMPointDesc ) != GPoint::BasicType() )
|
|
{
|
|
sendMessage ( "Element must be of type gpoint." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
return nl->SymbolAtom ( Point::BasicType() );
|
|
}
|
|
|
|
int OpGPoint2PointValueMapping ( Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier in_xSupplier )
|
|
{
|
|
Point* pPoint = ( Point* ) qp->ResultStorage ( in_xSupplier ).addr;
|
|
result = SetWord ( pPoint );
|
|
GPoint* pGPoint = ( GPoint* ) args[0].addr;
|
|
if ( pGPoint == NULL || !pGPoint->IsDefined() )
|
|
{
|
|
string strMessage = "Point does not exist.";
|
|
cerr << strMessage << endl;
|
|
sendMessage ( strMessage );
|
|
pPoint->SetDefined ( false );
|
|
return 0;
|
|
}
|
|
pGPoint->ToPoint ( pPoint );
|
|
return 0;
|
|
} //end ValueMapping
|
|
|
|
struct gpoint2pointInfo:OperatorInfo{
|
|
gpoint2pointInfo():OperatorInfo(){
|
|
name = "gpoint2point";
|
|
signature = "gpoint -> point";
|
|
syntax = "gpoint2point(_)";
|
|
meaning = "Translates a gpoint into an point value.";
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
6.15 Operator ~polygpoint~
|
|
|
|
Returns a stream of all ~GPoint~ values which are at the same network position
|
|
as the given ~GPoint~. Including the given ~GPoint~.
|
|
|
|
*/
|
|
|
|
ListExpr OpPolyGPointTypeMap ( ListExpr in_xArgs )
|
|
{
|
|
if ( nl->ListLength ( in_xArgs ) != 2 )
|
|
{
|
|
sendMessage ( "Expects a list of length 1." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
ListExpr xsource = nl->First ( in_xArgs );
|
|
ListExpr xnetwork = nl->Second ( in_xArgs );
|
|
|
|
if ( ( !nl->IsAtom ( xsource ) ) ||
|
|
!nl->IsEqual ( xsource, GPoint::BasicType() ) )
|
|
{
|
|
sendMessage ( "First Element must be of type gpoint." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
if ( ( !nl->IsAtom ( xnetwork ) ) ||
|
|
!nl->IsEqual ( xnetwork, "network" ) )
|
|
{
|
|
sendMessage ( "Second Element must be of type network." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
return nl->TwoElemList ( nl->SymbolAtom ( Symbol::STREAM() ),
|
|
nl->SymbolAtom ( GPoint::BasicType() ) );
|
|
}
|
|
|
|
int OpPolyGPointValueMapping ( Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier in_xSupplier )
|
|
{
|
|
GPointList* localinfo;
|
|
GPoint res;
|
|
result = qp->ResultStorage ( in_xSupplier );
|
|
switch ( message )
|
|
{
|
|
case OPEN:
|
|
local = SetWord ( new GPointList ( ( GPoint* ) args[0].addr,
|
|
( Network* ) args[1].addr ) );
|
|
return 0;
|
|
case REQUEST:
|
|
localinfo = ( GPointList* ) local.addr;
|
|
res = localinfo->NextGPoint();
|
|
if ( !res.IsDefined() )
|
|
{
|
|
return CANCEL;
|
|
}
|
|
else
|
|
{
|
|
result = SetWord ( new GPoint ( res ) );
|
|
return YIELD;
|
|
}
|
|
case CLOSE:
|
|
if ( local.addr != 0 )
|
|
{
|
|
localinfo = ( GPointList* ) local.addr;
|
|
localinfo->Destroy();
|
|
delete localinfo;
|
|
localinfo = 0;
|
|
local = SetWord ( Address ( 0 ) );
|
|
}
|
|
return 0;
|
|
}
|
|
return 0; // ignore unknown message
|
|
} //end ValueMapping
|
|
|
|
struct polygpointsInfo:OperatorInfo{
|
|
polygpointsInfo():OperatorInfo(){
|
|
name = "polygpoints";
|
|
signature = "gpoint X network -> stream(gpoint)";
|
|
syntax = "polygpoints(gpoint, network)";
|
|
meaning = "Return gpoints with same position in space.";
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
6.16 Operator ~routeintervals~
|
|
|
|
Returns a stream of rectangles representing the ~RouteIntervals~ of the ~GLine~.
|
|
|
|
*/
|
|
|
|
ListExpr OpRouteIntervalsTypeMap ( ListExpr in_xArgs )
|
|
{
|
|
if ( nl->ListLength ( in_xArgs ) != 1 )
|
|
{
|
|
sendMessage ( "Expects a list of length 1." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
ListExpr xsource = nl->First ( in_xArgs );
|
|
|
|
if ( ( !nl->IsAtom ( xsource ) ) ||
|
|
!nl->IsEqual ( xsource, GLine::BasicType() ) )
|
|
{
|
|
sendMessage ( "First Element must be of type gline." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
return nl->TwoElemList ( nl->SymbolAtom ( Symbol::STREAM() ),
|
|
nl->SymbolAtom ( Rectangle<2>::BasicType() ) );
|
|
}
|
|
|
|
int OpRouteIntervalsValueMapping ( Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier in_xSupplier )
|
|
{
|
|
RectangleList* localinfo;
|
|
Rectangle<2> res;
|
|
result = qp->ResultStorage ( in_xSupplier );
|
|
GLine* source = (GLine*) args[0].addr;
|
|
switch ( message )
|
|
{
|
|
case OPEN:
|
|
if (source->IsDefined())
|
|
local = SetWord ( new RectangleList (source));
|
|
else
|
|
local = SetWord (Address(0));
|
|
return 0;
|
|
case REQUEST:
|
|
if (local.addr == 0) return CANCEL;
|
|
localinfo = ( RectangleList* ) local.addr;
|
|
res = localinfo->NextRectangle();
|
|
if ( !res.IsDefined() ) return CANCEL;
|
|
else
|
|
{
|
|
result = SetWord ( new Rectangle<2> ( res ) );
|
|
return YIELD;
|
|
}
|
|
case CLOSE:
|
|
if ( local.addr != 0 )
|
|
{
|
|
delete ( RectangleList* ) local.addr;
|
|
local = SetWord ( Address ( 0 ) );
|
|
}
|
|
return 0;
|
|
}
|
|
return 0; // ignore unknown message
|
|
} //end ValueMapping
|
|
|
|
struct routeIntervalsInfo:OperatorInfo{
|
|
routeIntervalsInfo():OperatorInfo(){
|
|
name = "routeintervals";
|
|
signature = "gline -> stream(rect)";
|
|
syntax = "routeintervals(_)";
|
|
meaning = "Returns a netbox for each routeinterval of the gline.";
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
6.17 Operator ~shortest\_path~
|
|
|
|
Returns the shortest path in the ~Network~ between two ~GPoint~. Using Dijkstra
|
|
Algorithm to compute the shortest path.
|
|
|
|
*/
|
|
|
|
ListExpr OpShortestPathTypeMap ( ListExpr args )
|
|
{
|
|
NList param(args);
|
|
if (param.length() != 2)
|
|
{
|
|
return listutils::typeError("shortest_path expects 2 arguments.");
|
|
}
|
|
|
|
if ((param.first().isSymbol(GPoint::BasicType())
|
|
&& param.second().isSymbol(GPoint::BasicType())) ||
|
|
(param.first().isSymbol(GLine::BasicType())
|
|
&& param.second().isSymbol(GLine::BasicType())))
|
|
return nl->SymbolAtom(GLine::BasicType());
|
|
else
|
|
return listutils::typeError("Both arguments should be gpoint or gline");
|
|
}
|
|
|
|
int OpShortestPath_gpgp ( Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier in_xSupplier )
|
|
{
|
|
result = qp->ResultStorage(in_xSupplier);
|
|
GLine* pGLine = static_cast<GLine*>(result.addr);
|
|
GPoint *pFromGPoint = ( GPoint* ) args[0].addr;
|
|
GPoint *pToGPoint = ( GPoint* ) args[1].addr;
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(pFromGPoint->GetNetworkId(),
|
|
netList);
|
|
pGLine->SetSorted ( false );
|
|
pGLine->SetDefined ( pFromGPoint->ShortestPath ( pToGPoint, pGLine, pNetwork,
|
|
0 ) );
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return 0;
|
|
}
|
|
|
|
int OpShortestPath_glgl ( Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier in_xSupplier )
|
|
{
|
|
result = qp->ResultStorage(in_xSupplier);
|
|
GLine* pGLine = static_cast<GLine*>(result.addr);
|
|
GLine *pFromGLine = ( GLine* ) args[0].addr;
|
|
GLine *pToGLine = ( GLine* ) args[1].addr;
|
|
Network* pNetwork = NetworkManager::GetNetworkNew(pFromGLine->GetNetworkId(),
|
|
netList);
|
|
pGLine->SetSorted ( false );
|
|
pGLine->SetDefined ( pFromGLine->ShortestPathBF( pToGLine, pGLine, pNetwork,
|
|
0 ) );
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return 0;
|
|
}
|
|
|
|
int OpShortestPathSelect ( ListExpr args )
|
|
{
|
|
ListExpr arg1 = nl->First ( args );
|
|
ListExpr arg2 = nl->Second ( args );
|
|
if ( nl->SymbolValue ( arg1 ) == GPoint::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoint::BasicType() )
|
|
return 0;
|
|
if ( nl->SymbolValue ( arg1 ) == GLine::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GLine::BasicType() )
|
|
return 1;
|
|
return -1; // This point should never be reached
|
|
};
|
|
|
|
ValueMapping OpShortestPathValMap[] =
|
|
{
|
|
OpShortestPath_gpgp,
|
|
OpShortestPath_glgl
|
|
};
|
|
|
|
struct shortestpathInfo:OperatorInfo{
|
|
shortestpathInfo():OperatorInfo(){
|
|
name = "shortest_path";
|
|
signature = "gpoint X gpoint -> gline";
|
|
appendSignature ("gline X gline -> gline");
|
|
syntax = "shortest_path (_,_)";
|
|
meaning = "Dijkstra for gpoint. Bruteforce for gline.";
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
6.17 Operator ~shortest\_pathastar~
|
|
|
|
Returns the shortest path in the ~Network~ between two ~GPoint~. Using
|
|
AStar-Algorithm to compute the shortest path.
|
|
|
|
*/
|
|
|
|
ListExpr OpShortestPathAStarTypeMap ( ListExpr args )
|
|
{
|
|
NList param(args);
|
|
if (param.length() != 2)
|
|
{
|
|
return listutils::typeError("netdistancenew expects 2 arguments.");
|
|
}
|
|
if (!( param.first().isSymbol(GPoint::BasicType())
|
|
|| param.first().isSymbol(GLine::BasicType())
|
|
|| param.first().isSymbol(GPoints::BasicType())))
|
|
{
|
|
return
|
|
listutils::typeError("1.argument should be gpoint, gline or gpoints.");
|
|
}
|
|
if (!(param.second().isSymbol(GPoint::BasicType())
|
|
|| param.second().isSymbol(GLine::BasicType()) ||
|
|
param.second().isSymbol(GPoints::BasicType())))
|
|
{
|
|
return
|
|
listutils::typeError("2.argument should be gpoint, gline or gpoints.");
|
|
}
|
|
return nl->SymbolAtom ( GLine::BasicType() );
|
|
}
|
|
|
|
template<class Source, class Target>
|
|
int OpShortestPathAStar ( Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier in_xSupplier )
|
|
{
|
|
result = qp->ResultStorage(in_xSupplier);
|
|
GLine* pGLine = static_cast<GLine*>(result.addr);
|
|
Source *pFrom = ( Source* ) args[0].addr;
|
|
Target *pTo = ( Target* ) args[1].addr;
|
|
pGLine->SetSorted ( false );
|
|
if (!pFrom->IsDefined() || !pTo->IsDefined())
|
|
{
|
|
pGLine->SetDefined(false);
|
|
return 0;
|
|
}
|
|
Network* pNetwork =
|
|
NetworkManager::GetNetworkNew(pFrom->GetNetworkId(), netList);
|
|
pGLine->SetDefined ( pFrom->ShortestPathAStar( pTo, pGLine,
|
|
pNetwork, 0 ) );
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return 0;
|
|
}
|
|
|
|
int OpShortestPathAStarSelect ( ListExpr args )
|
|
{
|
|
ListExpr arg1 = nl->First ( args );
|
|
ListExpr arg2 = nl->Second ( args );
|
|
if ( nl->SymbolValue ( arg1 ) == GPoint::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoint::BasicType() )
|
|
return 0;
|
|
if ( nl->SymbolValue ( arg1 ) == GLine::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GLine::BasicType() )
|
|
return 1;
|
|
if ( nl->SymbolValue ( arg1 ) == GPoints::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoints::BasicType() )
|
|
return 2;
|
|
if ( nl->SymbolValue ( arg1 ) == GPoint::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GLine::BasicType() )
|
|
return 3;
|
|
if ( nl->SymbolValue ( arg1 ) == GPoint::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoints::BasicType() )
|
|
return 4;
|
|
if ( nl->SymbolValue ( arg1 ) == GLine::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoint::BasicType() )
|
|
return 5;
|
|
if ( nl->SymbolValue ( arg1 ) == GLine::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoints::BasicType() )
|
|
return 6;
|
|
if ( nl->SymbolValue ( arg1 ) == GPoints::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoint::BasicType() )
|
|
return 7;
|
|
if ( nl->SymbolValue ( arg1 ) == GPoints::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GLine::BasicType() )
|
|
return 8;
|
|
return -1; // This point should never be reached
|
|
};
|
|
|
|
ValueMapping OpShortestPathAStarMap[] =
|
|
{
|
|
OpShortestPathAStar<GPoint, GPoint>,
|
|
OpShortestPathAStar<GLine, GLine>,
|
|
OpShortestPathAStar<GPoints, GPoints>,
|
|
OpShortestPathAStar<GPoint, GLine>,
|
|
OpShortestPathAStar<GPoint, GPoints>,
|
|
OpShortestPathAStar<GLine, GPoint>,
|
|
OpShortestPathAStar<GLine, GPoints>,
|
|
OpShortestPathAStar<GPoints, GPoint>,
|
|
OpShortestPathAStar<GPoints, GLine>
|
|
};
|
|
|
|
struct shortestpathAstarInfo:OperatorInfo{
|
|
shortestpathAstarInfo():OperatorInfo(){
|
|
name = "shortest_pathastar";
|
|
signature = "gpoint X gpoint -> gline";
|
|
appendSignature("gline X gline -> gline");
|
|
appendSignature("gpoints X gpoints -> gline");
|
|
appendSignature("gpoint x gline -> gline");
|
|
appendSignature("gpoint x gpoints -> gline");
|
|
appendSignature("gline X gpoint -> gline");
|
|
appendSignature("gline X gpoints -> gline");
|
|
appendSignature("gpoints X gpoint -> gline");
|
|
appendSignature("gpoints X gline -> gline");
|
|
syntax = "shortest_pathastar (_,_)";
|
|
meaning = "Returns shortest path between objects using Astar-Variant.";
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
6.18 Operator ~gline2line~
|
|
|
|
Returns the ~line~ value of the given ~GLine~.
|
|
|
|
*/
|
|
|
|
ListExpr OpGLine2LineTypeMap ( ListExpr in_xArgs )
|
|
{
|
|
if ( nl->ListLength ( in_xArgs ) != 1 )
|
|
{
|
|
sendMessage ( "Expects a list of length 1." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
ListExpr xsource = nl->First ( in_xArgs );
|
|
|
|
if ( ( !nl->IsAtom ( xsource ) ) ||
|
|
!nl->IsEqual ( xsource, GLine::BasicType() ) )
|
|
{
|
|
sendMessage ( "Element must be of type gline." );
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
return nl->SymbolAtom ( Line::BasicType() );
|
|
}
|
|
|
|
int OpGLine2LineValueMapping ( Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier in_xSupplier )
|
|
{
|
|
Line* pLine = ( Line* ) qp->ResultStorage ( in_xSupplier ).addr;
|
|
result = SetWord ( pLine );
|
|
GLine* pGLine = ( GLine* ) args[0].addr;
|
|
if ( pGLine == NULL || !pGLine->IsDefined() )
|
|
{
|
|
sendMessage ( "GLine must be defined!" );
|
|
pLine->SetDefined ( false );
|
|
return 0;
|
|
}
|
|
pGLine->Gline2line ( pLine );
|
|
return 0;
|
|
}
|
|
|
|
struct gline2lineInfo:OperatorInfo{
|
|
gline2lineInfo():OperatorInfo(){
|
|
name = "gline2line";
|
|
signature = "gline -> line";
|
|
syntax = "gline2line(_)";
|
|
meaning = "Translates a gline into an line value.";
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
6.19 Operator ~isempty~
|
|
|
|
Returns if the ~GLine~. is empty.
|
|
|
|
*/
|
|
ListExpr OpNetIsEmptyTypeMap ( ListExpr args )
|
|
{
|
|
if ( nl->ListLength ( args ) != 1 )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
ListExpr gline = nl->First ( args );
|
|
if ( !nl->IsAtom ( gline ) || nl->AtomType ( gline ) != SymbolType ||
|
|
nl->SymbolValue ( gline ) != GLine::BasicType() )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
return nl->SymbolAtom ( CcBool::BasicType() );
|
|
}
|
|
|
|
int OpNetIsEmptyValueMap ( Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier )
|
|
{
|
|
GLine* pGline = ( GLine* ) args[0].addr;
|
|
result = qp->ResultStorage ( in_pSupplier );
|
|
CcBool* pResult = ( CcBool* ) result.addr;
|
|
if ( ( ! ( pGline->IsDefined() ) ) || pGline->NoOfComponents() == 0 )
|
|
{
|
|
pResult->Set ( true, true );
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
pResult->Set ( true,false );
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
struct isEmptyInfo:OperatorInfo{
|
|
isEmptyInfo():OperatorInfo(){
|
|
name = "isempty";
|
|
signature = "gline -> bool";
|
|
syntax = "isempty(_)";
|
|
meaning = "Returns true if gline has no route intervals.";
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
6.20 Operator ~union~
|
|
|
|
Builds the union of the two given glines as sorted gline.
|
|
|
|
*/
|
|
|
|
ListExpr OpNetUnionTypeMap ( ListExpr args )
|
|
{
|
|
if ( nl->ListLength ( args ) != 2 )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
ListExpr gline1 = nl->First ( args );
|
|
ListExpr gline2 = nl->Second ( args );
|
|
|
|
if ( !nl->IsAtom ( gline1 ) || nl->AtomType ( gline1 ) != SymbolType ||
|
|
nl->SymbolValue ( gline1 ) != GLine::BasicType() )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
if ( !nl->IsAtom ( gline2 ) || nl->AtomType ( gline2 ) != SymbolType ||
|
|
nl->SymbolValue ( gline2 ) != GLine::BasicType() )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
return nl->SymbolAtom ( GLine::BasicType() );
|
|
}
|
|
|
|
int OpNetUnionValueMap ( Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier )
|
|
{
|
|
GLine *pGL1 = ( GLine* ) args[0].addr;
|
|
GLine *pGL2 = ( GLine* ) args[1].addr;
|
|
GLine *pGLine = ( GLine* ) qp->ResultStorage ( in_pSupplier ).addr;
|
|
result = SetWord ( pGLine );
|
|
pGL1->Uniongl ( pGL2, pGLine );
|
|
return 0;
|
|
}
|
|
|
|
struct unionInfo:OperatorInfo{
|
|
unionInfo():OperatorInfo(){
|
|
name = "union";
|
|
signature = "gline X gline -> gline";
|
|
syntax = "union (_,_)";
|
|
meaning = "Returns one gline containing both gline.";
|
|
}
|
|
};
|
|
|
|
/*
|
|
6.21 Operator ~distance~
|
|
|
|
Returns the Euclidean Distance between two ~Gpoints~ or two ~GLines~.
|
|
|
|
*/
|
|
|
|
ListExpr OpNetDistanceTypeMap ( ListExpr args )
|
|
{
|
|
if ( nl->ListLength ( args ) != 2 )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
ListExpr param1 = nl->First ( args );
|
|
ListExpr param2 = nl->Second ( args );
|
|
|
|
if ( ( nl->IsAtom ( param1 ) && nl->AtomType ( param1 ) == SymbolType &&
|
|
nl->IsAtom ( param2 ) && nl->AtomType ( param2 ) == SymbolType &&
|
|
( ( nl->SymbolValue ( param1 ) == GPoint::BasicType() &&
|
|
nl->SymbolValue ( param2 ) == GPoint::BasicType() ) ||
|
|
( nl->SymbolValue ( param1 ) == GLine::BasicType() &&
|
|
nl->SymbolValue ( param2 ) == GLine::BasicType() ) ) ) )
|
|
{
|
|
return nl->SymbolAtom ( CcReal::BasicType() );
|
|
}
|
|
return nl->SymbolAtom ( Symbol::TYPEERROR() );
|
|
}
|
|
|
|
int OpNetDistance_gpgp ( Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier )
|
|
{
|
|
GPoint* pFromGPoint = ( GPoint* ) args[0].addr;
|
|
GPoint* pToGPoint = ( GPoint* ) args[1].addr;
|
|
result = qp->ResultStorage ( in_pSupplier );
|
|
CcReal* pResult = ( CcReal* ) result.addr;
|
|
if ( ! ( pFromGPoint->IsDefined() ) || ! ( pToGPoint->IsDefined() ) )
|
|
{
|
|
cmsg.inFunError ( "Both gpoint must be defined!" );
|
|
return 0;
|
|
};
|
|
pResult-> Set ( true, pFromGPoint->Distance ( pToGPoint ) );
|
|
return 0;
|
|
};
|
|
|
|
int OpNetDistance_glgl ( Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier )
|
|
{
|
|
GLine* pGLine1 = ( GLine* ) args[0].addr;
|
|
GLine* pGLine2 = ( GLine* ) args[1].addr;
|
|
result = qp->ResultStorage ( in_pSupplier );
|
|
CcReal* pResult = ( CcReal* ) result.addr;
|
|
if ( ! ( pGLine1->IsDefined() ) || ! ( pGLine2->IsDefined() ) ||
|
|
pGLine1->NoOfComponents() == 0 || pGLine2->NoOfComponents() == 0 )
|
|
{
|
|
cmsg.inFunError ( "Both gline must be defined! And have at least 1 interval"
|
|
);
|
|
return 0;
|
|
};
|
|
pResult-> Set ( true, pGLine1->Distance ( pGLine2 ) );
|
|
return 1;
|
|
};
|
|
|
|
ValueMapping OpNetDistancemap[] =
|
|
{
|
|
OpNetDistance_gpgp,
|
|
OpNetDistance_glgl,
|
|
0
|
|
};
|
|
|
|
int OpNetDistanceselect ( ListExpr args )
|
|
{
|
|
ListExpr arg1 = nl->First ( args );
|
|
ListExpr arg2 = nl->Second ( args );
|
|
if ( nl->SymbolValue ( arg1 ) == GPoint::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoint::BasicType() )
|
|
return 0;
|
|
if ( nl->SymbolValue ( arg1 ) == GLine::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GLine::BasicType() )
|
|
return 1;
|
|
return -1; // This point should never be reached
|
|
};
|
|
|
|
struct distanceInfo:OperatorInfo{
|
|
distanceInfo():OperatorInfo(){
|
|
name = "distance";
|
|
signature = "gpoint X gpoint -> real";
|
|
appendSignature("gline X gline -> real");
|
|
syntax = "distance(_,_)";
|
|
meaning = "Computes the Euclidean Distance between the objects.";
|
|
}
|
|
};
|
|
|
|
/*
|
|
6.20 Operator ~getBGP~
|
|
|
|
Returns the bounding GPoints of a gline.
|
|
|
|
*/
|
|
|
|
ListExpr OpGetBGPTypeMap ( ListExpr args )
|
|
{
|
|
if ( nl->ListLength ( args ) != 1 )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
ListExpr gline1 = nl->First ( args );
|
|
|
|
if ( !nl->IsAtom ( gline1 ) || nl->AtomType ( gline1 ) != SymbolType ||
|
|
nl->SymbolValue ( gline1 ) != GLine::BasicType() )
|
|
{
|
|
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
|
|
}
|
|
|
|
return nl->SymbolAtom ( GPoints::BasicType() );
|
|
}
|
|
|
|
int OpGetBGPValueMap ( Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier )
|
|
{
|
|
result = qp->ResultStorage(in_pSupplier);
|
|
GPoints* pGPoints = static_cast<GPoints*>(result.addr);
|
|
GLine *pGL1 = ( GLine* ) args[0].addr;
|
|
if (!pGL1->IsDefined() || pGL1->NoOfComponents() <= 0)
|
|
{
|
|
pGPoints->SetDefined(false);
|
|
return 0;
|
|
}
|
|
pGL1->GetBGP(pGPoints);
|
|
return 0;
|
|
}
|
|
|
|
struct getBGPInfo:OperatorInfo{
|
|
getBGPInfo():OperatorInfo(){
|
|
name = "getBGP";
|
|
signature = "gline -> gpoints";
|
|
syntax = "getBGP (_)";
|
|
meaning = "Returns the set of bounding gpoint of gline.";
|
|
}
|
|
};
|
|
|
|
/*
|
|
6.22 Operator ~spsearchvisited~
|
|
|
|
Returns the stream of section tuples that have been visited searching the
|
|
shortest path.
|
|
|
|
*/
|
|
ListExpr OpSPSearchVisitedTypeMap ( ListExpr args )
|
|
{
|
|
NList param(args);
|
|
|
|
ListExpr xType;
|
|
nl->ReadFromString ( Network::sectionsInternalTypeInfo, xType );
|
|
ListExpr tupleType = nl->Second(xType);
|
|
|
|
if (param.length() != 3)
|
|
{
|
|
return listutils::typeError("spsearchvisited expects 3 arguments.");
|
|
}
|
|
if (!( param.first().isSymbol(GPoint::BasicType())
|
|
|| param.first().isSymbol(GLine::BasicType())
|
|
|| param.first().isSymbol(GPoints::BasicType())))
|
|
{
|
|
return
|
|
listutils::typeError("1.argument should be gpoint, gline or gpoints.");
|
|
}
|
|
if (!(param.second().isSymbol(GPoint::BasicType())
|
|
|| param.second().isSymbol(GLine::BasicType()) ||
|
|
param.second().isSymbol(GPoints::BasicType())))
|
|
{
|
|
if (param.first().isSymbol(GPoint::BasicType())
|
|
&& param.second().isSymbol("ugpoint"))
|
|
return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
|
|
tupleType);
|
|
else
|
|
return listutils::typeError(
|
|
"2.argument should be (u)gpoint, gline or gpoints.");
|
|
}
|
|
if (!param.third().isSymbol(CcBool::BasicType()))
|
|
{
|
|
return listutils::typeError("3.argument should be bool");
|
|
}
|
|
|
|
return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
|
|
tupleType);
|
|
}
|
|
|
|
struct OpSPSearchVisitedLocalInfo
|
|
{
|
|
OpSPSearchVisitedLocalInfo()
|
|
{
|
|
pNetwork = 0;
|
|
visitedSections = 0;
|
|
pos = 0;
|
|
}
|
|
|
|
Network* pNetwork;
|
|
DbArray<TupleId>* visitedSections;
|
|
int pos;
|
|
};
|
|
|
|
int OpSPSearchVisitedValueMap_gpgp(Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier)
|
|
{
|
|
OpSPSearchVisitedLocalInfo* li = 0;
|
|
|
|
switch(message)
|
|
{
|
|
case OPEN:
|
|
{
|
|
li = new OpSPSearchVisitedLocalInfo();
|
|
li->visitedSections = new DbArray<TupleId>(1);
|
|
GPoint *pFromGPoint = ( GPoint* ) args[0].addr;
|
|
GPoint *pToGPoint = ( GPoint* ) args[1].addr;
|
|
bool dijkstra = ((CcBool*)args[2].addr)->GetBoolval();
|
|
bool success = false;
|
|
GLine* pGLine = new GLine(0);
|
|
li->pNetwork =
|
|
NetworkManager::GetNetworkNew(pFromGPoint->GetNetworkId(),netList);
|
|
if (dijkstra)
|
|
{
|
|
success = pFromGPoint->ShortestPath ( pToGPoint, pGLine, li->pNetwork,
|
|
li->visitedSections);
|
|
}
|
|
else
|
|
{
|
|
success = pFromGPoint->ShortestPathAStar ( pToGPoint, pGLine,
|
|
li->pNetwork,
|
|
li->visitedSections);
|
|
}
|
|
if(!success)
|
|
{
|
|
li->visitedSections->Destroy();
|
|
delete li->visitedSections;
|
|
li->visitedSections = 0;
|
|
NetworkManager::CloseNetwork(li->pNetwork);
|
|
li->pNetwork = 0;
|
|
delete li;
|
|
li = 0;
|
|
}
|
|
pGLine->DeleteIfAllowed();
|
|
local.addr = li;
|
|
return 0;
|
|
break;
|
|
}
|
|
|
|
case REQUEST:
|
|
{
|
|
if (local.addr != 0)
|
|
li = (OpSPSearchVisitedLocalInfo*) local.addr;
|
|
else
|
|
return CANCEL;
|
|
if (li->pos < 0 || li->pos >= li->visitedSections->Size())
|
|
return CANCEL;
|
|
else
|
|
{
|
|
TupleId actTID;
|
|
li->visitedSections->Get(li->pos,actTID);
|
|
Tuple* actTuple = li->pNetwork->GetSection(actTID);
|
|
result.setAddr(actTuple);
|
|
li->pos++;
|
|
return YIELD;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case CLOSE:
|
|
{
|
|
if (local.addr != 0)
|
|
{
|
|
li = (OpSPSearchVisitedLocalInfo*) local.addr;
|
|
NetworkManager::CloseNetwork(li->pNetwork);
|
|
li->pNetwork = 0;
|
|
li->visitedSections->Destroy();
|
|
delete li->visitedSections;
|
|
li->visitedSections = 0;
|
|
delete li;
|
|
li = 0;
|
|
local.addr = 0;
|
|
}
|
|
return 0;
|
|
break;
|
|
}
|
|
}
|
|
return 0; //should never been reached
|
|
}
|
|
|
|
int OpSPSearchVisitedValueMap_glgl(Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier)
|
|
{
|
|
OpSPSearchVisitedLocalInfo* li = 0;
|
|
|
|
switch(message)
|
|
{
|
|
case OPEN:
|
|
{
|
|
li = new OpSPSearchVisitedLocalInfo();
|
|
li->visitedSections = new DbArray<TupleId>(0);
|
|
GLine *pFromGLine = ( GLine* ) args[0].addr;
|
|
GLine *pToGLine = ( GLine* ) args[1].addr;
|
|
bool bruteforce = ((CcBool*)args[2].addr)->GetBoolval();
|
|
bool success = false;
|
|
GLine* pGLine = new GLine(0);
|
|
li->pNetwork =
|
|
NetworkManager::GetNetworkNew(pFromGLine->GetNetworkId(),netList);
|
|
if (bruteforce)
|
|
{
|
|
|
|
success = pFromGLine->ShortestPathBF(pToGLine, pGLine, li->pNetwork,
|
|
li->visitedSections);
|
|
}
|
|
else
|
|
{
|
|
success = pFromGLine->ShortestPathAStar ( pToGLine, pGLine,
|
|
li->pNetwork,
|
|
li->visitedSections);
|
|
}
|
|
if(!success)
|
|
{
|
|
li->visitedSections->Destroy();
|
|
delete li->visitedSections;
|
|
li->visitedSections = 0;
|
|
NetworkManager::CloseNetwork(li->pNetwork);
|
|
li->pNetwork = 0;
|
|
delete li;
|
|
li = 0;
|
|
}
|
|
pGLine->DeleteIfAllowed();
|
|
local.addr = li;
|
|
return 0;
|
|
break;
|
|
}
|
|
|
|
case REQUEST:
|
|
{
|
|
if (local.addr != 0)
|
|
li = (OpSPSearchVisitedLocalInfo*) local.addr;
|
|
else
|
|
return CANCEL;
|
|
if (li->pos < 0 || li->pos >= li->visitedSections->Size())
|
|
return CANCEL;
|
|
else
|
|
{
|
|
TupleId actTID;
|
|
li->visitedSections->Get(li->pos,actTID);
|
|
Tuple* actTuple = li->pNetwork->GetSection(actTID);
|
|
result.setAddr(actTuple);
|
|
li->pos++;
|
|
return YIELD;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case CLOSE:
|
|
{
|
|
if (local.addr != 0)
|
|
{
|
|
li = (OpSPSearchVisitedLocalInfo*) local.addr;
|
|
NetworkManager::CloseNetwork(li->pNetwork);
|
|
li->pNetwork = 0;
|
|
li->visitedSections->Destroy();
|
|
delete li->visitedSections;
|
|
li->visitedSections = 0;
|
|
delete li;
|
|
li = 0;
|
|
local.addr = 0;
|
|
}
|
|
return 0;
|
|
break;
|
|
}
|
|
}
|
|
return 0; //should never been reached
|
|
}
|
|
|
|
|
|
template<class Source, class Target>
|
|
int OpSPSearchVisitedValueMap(Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier)
|
|
{
|
|
OpSPSearchVisitedLocalInfo* li = 0;
|
|
|
|
switch(message)
|
|
{
|
|
case OPEN:
|
|
{
|
|
li = new OpSPSearchVisitedLocalInfo();
|
|
li->visitedSections = new DbArray<TupleId>(0);
|
|
Source *pFrom = ( Source* ) args[0].addr;
|
|
Target *pTo = ( Target* ) args[1].addr;
|
|
bool dijkstra = ((CcBool*)args[2].addr)->GetBoolval();
|
|
bool success = false;
|
|
GLine* pGLine = new GLine(0);
|
|
li->pNetwork =
|
|
NetworkManager::GetNetworkNew(pFrom->GetNetworkId(),netList);
|
|
if (dijkstra)
|
|
{
|
|
success = false;
|
|
}
|
|
else
|
|
{
|
|
success = pFrom->ShortestPathAStar( pTo, pGLine,
|
|
li->pNetwork,
|
|
li->visitedSections);
|
|
}
|
|
if(!success)
|
|
{
|
|
li->visitedSections->Destroy();
|
|
delete li->visitedSections;
|
|
li->visitedSections = 0;
|
|
NetworkManager::CloseNetwork(li->pNetwork);
|
|
li->pNetwork = 0;
|
|
delete li;
|
|
li = 0;
|
|
}
|
|
pGLine->DeleteIfAllowed();
|
|
local.addr = li;
|
|
return 0;
|
|
break;
|
|
}
|
|
|
|
case REQUEST:
|
|
{
|
|
if (local.addr != 0)
|
|
li = (OpSPSearchVisitedLocalInfo*) local.addr;
|
|
else
|
|
return CANCEL;
|
|
if (li->pos < 0 || li->pos >= li->visitedSections->Size())
|
|
return CANCEL;
|
|
else
|
|
{
|
|
TupleId actTID;
|
|
li->visitedSections->Get(li->pos,actTID);
|
|
Tuple* actTuple = li->pNetwork->GetSection(actTID);
|
|
result.setAddr(actTuple);
|
|
li->pos++;
|
|
return YIELD;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case CLOSE:
|
|
{
|
|
if (local.addr != 0)
|
|
{
|
|
li = (OpSPSearchVisitedLocalInfo*) local.addr;
|
|
NetworkManager::CloseNetwork(li->pNetwork);
|
|
li->pNetwork = 0;
|
|
li->visitedSections->Destroy();
|
|
delete li->visitedSections;
|
|
li->visitedSections = 0;
|
|
delete li;
|
|
li = 0;
|
|
local.addr = 0;
|
|
}
|
|
return 0;
|
|
break;
|
|
}
|
|
}
|
|
return 0; //should never been reached
|
|
}
|
|
|
|
ValueMapping OpSpvisitedmap[] =
|
|
{
|
|
OpSPSearchVisitedValueMap_gpgp,
|
|
OpSPSearchVisitedValueMap_glgl,
|
|
OpSPSearchVisitedValueMap<GPoints, GPoints>,
|
|
OpSPSearchVisitedValueMap<GPoint, GLine>,
|
|
OpSPSearchVisitedValueMap<GPoint, GPoints>,
|
|
OpSPSearchVisitedValueMap<GLine, GPoint>,
|
|
OpSPSearchVisitedValueMap<GLine, GPoints>,
|
|
OpSPSearchVisitedValueMap<GPoints, GPoint>,
|
|
OpSPSearchVisitedValueMap<GPoints, GLine>
|
|
};
|
|
|
|
int OpSpvisitedselect ( ListExpr args )
|
|
{
|
|
ListExpr arg1 = nl->First ( args );
|
|
ListExpr arg2 = nl->Second ( args );
|
|
if ( nl->SymbolValue ( arg1 ) == GPoint::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoint::BasicType() )
|
|
return 0;
|
|
if ( nl->SymbolValue ( arg1 ) == GLine::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GLine::BasicType() )
|
|
return 1;
|
|
if (nl->SymbolValue (arg1) == GPoints::BasicType() &&
|
|
nl->SymbolValue (arg2) == GPoints::BasicType())
|
|
return 2;
|
|
if ( nl->SymbolValue ( arg1 ) == GPoint::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GLine::BasicType() )
|
|
return 3;
|
|
if (nl->SymbolValue (arg1) == GPoint::BasicType() &&
|
|
nl->SymbolValue (arg2) == GPoints::BasicType())
|
|
return 4;
|
|
if ( nl->SymbolValue ( arg1 ) == GLine::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoint::BasicType() )
|
|
return 5;
|
|
if (nl->SymbolValue (arg1) == GLine::BasicType() &&
|
|
nl->SymbolValue (arg2) == GPoints::BasicType())
|
|
return 6;
|
|
if ( nl->SymbolValue ( arg1 ) == GPoints::BasicType() &&
|
|
nl->SymbolValue ( arg2 ) == GPoint::BasicType() )
|
|
return 7;
|
|
if (nl->SymbolValue (arg1) == GPoints::BasicType() &&
|
|
nl->SymbolValue (arg2) == GLine::BasicType())
|
|
return 8;
|
|
return -1; // This point should never be reached
|
|
};
|
|
|
|
struct spsearchvisitedInfo:OperatorInfo{
|
|
spsearchvisitedInfo():OperatorInfo(){
|
|
name = "spsearchvisited";
|
|
signature = "gpoint x gpoint x bool->stream(tuple(X)))";
|
|
appendSignature("gline x gline x bool->stream(tuple(X)))");
|
|
appendSignature("gpoints x gpoints x bool->stream(tuple(X)))");
|
|
appendSignature("gpoint x gline x bool->stream(tuple(X)))");
|
|
appendSignature("gpoint x gpoints x bool->stream(tuple(X)))");
|
|
appendSignature("gline x gpoint x bool->stream(tuple(X)))");
|
|
appendSignature("gline x gpoints x bool->stream(tuple(X)))");
|
|
appendSignature("gpoints x gpoint x bool->stream(tuple(X)))");
|
|
appendSignature("gpoints x gline x bool->stream(tuple(X)))");
|
|
syntax = "spsearchvisited(_,_,_)";
|
|
meaning = "Stream of network sections visited by shortestpath";
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
6.23 Operator ~shortestpathtree~
|
|
|
|
Returns the complete ~shortestpathtree~ in the network from the source.
|
|
If third argument is true the complete shortest path tree is computed,
|
|
If third arguemtn is false the computation stops if all parts of the target
|
|
have been reached.
|
|
|
|
*/
|
|
|
|
ListExpr OpShortestpathtreeTypeMap ( ListExpr args )
|
|
{
|
|
NList param(args);
|
|
|
|
if(param.length() != 2 )
|
|
return listutils::typeError("2 arguments expected.");
|
|
|
|
NList source(param.first());
|
|
if (!source.isSymbol(GPoint::BasicType()))
|
|
return listutils::typeError("First argument should be gpoint.");
|
|
|
|
NList network(param.second());
|
|
if (!network.isSymbol("network"))
|
|
return listutils::typeError("Second argument should be a network.");
|
|
|
|
//return nl->SymbolAtom(GLine::BasicType());
|
|
|
|
NList secID("SecID");
|
|
NList intVal(CcInt::BasicType());
|
|
NList intAttr(secID, intVal);
|
|
NList dist("Dist");
|
|
NList realVal(CcReal::BasicType());
|
|
NList distAttr(dist,realVal);
|
|
NList up("Up");
|
|
NList upVal(CcBool::BasicType());
|
|
NList upAttr(up,upVal);
|
|
NList tupleType(intAttr,distAttr,upAttr);
|
|
return NList().tupleStreamOf(tupleType).listExpr();
|
|
}
|
|
|
|
struct ShortestPathTreeInfo
|
|
{
|
|
ShortestPathTreeInfo()
|
|
{
|
|
pos = 2;
|
|
resArray = 0;
|
|
}
|
|
|
|
ShortestPathTreeInfo(Network *pNetwork)
|
|
{
|
|
resArray =
|
|
new DbArray<ShortestPathTreeEntry> (2*pNetwork->GetNoSections() + 1);
|
|
ShortestPathTreeEntry spEntryUp(numeric_limits< double >::max(),true);
|
|
ShortestPathTreeEntry spEntryDown(numeric_limits< double >::max(),
|
|
false);
|
|
for (int i = 0; i < resArray->Size(); i++)
|
|
{
|
|
if (i%2 == 0)
|
|
resArray->Put(i,spEntryUp);
|
|
else
|
|
resArray->Put(i,spEntryDown);
|
|
}
|
|
pos = 2;
|
|
}
|
|
|
|
void Destroy()
|
|
{
|
|
resArray->Destroy();
|
|
}
|
|
|
|
~ShortestPathTreeInfo(){};
|
|
|
|
DbArray<ShortestPathTreeEntry> *resArray;
|
|
int pos;
|
|
TupleType* resTupleTyp;
|
|
};
|
|
|
|
int OpShortestpathtreeValueMap_gp(Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier)
|
|
{
|
|
ShortestPathTreeInfo *localinfo = 0;
|
|
|
|
switch(message)
|
|
{
|
|
|
|
case OPEN:
|
|
{
|
|
GPoint* pSource = (GPoint*) args[0].addr;
|
|
Network* pNetwork = (Network*) args[1].addr;
|
|
if (pSource != 0 && pSource->IsDefined() &&
|
|
pNetwork != 0 && pNetwork->IsDefined())
|
|
{
|
|
localinfo = new ShortestPathTreeInfo(pNetwork);
|
|
pSource->ShortestPathTree(pNetwork,localinfo->resArray);
|
|
ListExpr resultType = GetTupleResultType( in_pSupplier );
|
|
localinfo->resTupleTyp = new TupleType(nl->Second(resultType));
|
|
}
|
|
local = SetWord(localinfo);
|
|
return 0;
|
|
break;
|
|
}
|
|
|
|
case REQUEST:
|
|
{
|
|
localinfo = (ShortestPathTreeInfo*) local.addr;
|
|
if (localinfo != 0 && localinfo->pos < localinfo->resArray->Size())
|
|
{
|
|
|
|
Tuple *res = new Tuple(localinfo->resTupleTyp);
|
|
if ((localinfo->pos % 2) == 0)
|
|
res->PutAttribute(0,new CcInt(true,localinfo->pos / 2));
|
|
else
|
|
res->PutAttribute(0,new CcInt(true,(localinfo->pos - 1)/2));
|
|
ShortestPathTreeEntry spTEntry;
|
|
localinfo->resArray->Get(localinfo->pos,spTEntry);
|
|
res->PutAttribute(1,new CcReal(true, spTEntry.GetDist()));
|
|
res->PutAttribute(2,new CcBool(true, spTEntry.GetUpDown()));
|
|
localinfo->pos++;
|
|
result.setAddr(res);
|
|
return YIELD;
|
|
}
|
|
else
|
|
return CANCEL;
|
|
break;
|
|
}
|
|
|
|
case CLOSE:
|
|
{
|
|
localinfo = (ShortestPathTreeInfo*) local.addr;
|
|
if (localinfo != 0)
|
|
{
|
|
localinfo->Destroy();
|
|
delete localinfo->resArray;
|
|
localinfo->resArray = 0;
|
|
if (localinfo->resTupleTyp != 0)
|
|
{
|
|
localinfo->resTupleTyp->DeleteIfAllowed();
|
|
localinfo->resTupleTyp = 0;
|
|
}
|
|
delete localinfo;
|
|
localinfo = 0;
|
|
local.setAddr(0);
|
|
}
|
|
return 0;
|
|
break;
|
|
}
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
ValueMapping OpShortestpathtreeMap[] =
|
|
{
|
|
OpShortestpathtreeValueMap_gp,
|
|
};
|
|
|
|
int OpShortestpathtreeSelect ( ListExpr args )
|
|
{
|
|
ListExpr arg1 = nl->First ( args );
|
|
if ( nl->SymbolValue ( arg1 ) == GPoint::BasicType() )
|
|
return 0;
|
|
return -1; // This point should never be reached
|
|
};
|
|
|
|
struct shortestpathtreeInfo:OperatorInfo{
|
|
shortestpathtreeInfo():OperatorInfo(){
|
|
name = "shortestpathtree";
|
|
signature = "gpoint X network -> stream(tupel((int)(real)(bool)))";
|
|
syntax = "shortestpathtree(_,_)";
|
|
meaning = "Returns the shortestpathtree from source.";
|
|
}
|
|
};
|
|
|
|
/*
|
|
6.24 Operator ~getAdjacentSections~
|
|
|
|
Returns the adjacent Sections of the given section.
|
|
|
|
*/
|
|
|
|
ListExpr OpGetAdjacentSectionsTypeMap ( ListExpr args )
|
|
{
|
|
NList param(args);
|
|
|
|
if(param.length() != 3 )
|
|
return listutils::typeError("3 arguments expected.");
|
|
|
|
NList network(param.first());
|
|
if (!network.isSymbol("network"))
|
|
return listutils::typeError("First argument should be network.");
|
|
|
|
NList source(param.second());
|
|
if (!source.isSymbol(CcInt::BasicType()))
|
|
return listutils::typeError("Second argument should be int.");
|
|
|
|
NList direction(param.third());
|
|
if (!direction.isSymbol(CcBool::BasicType()))
|
|
return listutils::typeError("Third argument should be bool.");
|
|
|
|
//return nl->SymbolAtom(GLine::BasicType());
|
|
|
|
NList secID("SecID");
|
|
NList intVal(CcInt::BasicType());
|
|
NList intAttr(secID, intVal);
|
|
NList up("Up");
|
|
NList upVal(CcBool::BasicType());
|
|
NList upAttr(up,upVal);
|
|
NList tupleType(intAttr,upAttr);
|
|
return NList().tupleStreamOf(tupleType).listExpr();
|
|
}
|
|
|
|
/*
|
|
Helper Struct for Adjacenc Section Lists.
|
|
|
|
*/
|
|
|
|
struct AdjacentSectionsInfo
|
|
{
|
|
AdjacentSectionsInfo()
|
|
{
|
|
pos = 0;
|
|
resArray = new DbArray<SectionValue>(0);
|
|
}
|
|
|
|
void Destroy()
|
|
{
|
|
resArray->Destroy();
|
|
}
|
|
|
|
~AdjacentSectionsInfo(){};
|
|
|
|
DbArray<SectionValue> *resArray;
|
|
int pos;
|
|
TupleType* resTupleTyp;
|
|
};
|
|
|
|
int OpGetAdjacentSectionsValueMap(Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier)
|
|
{
|
|
AdjacentSectionsInfo *localinfo = 0;
|
|
|
|
switch(message)
|
|
{
|
|
|
|
case OPEN:
|
|
{
|
|
Network* pNetwork = (Network*) args[0].addr;
|
|
int sectId =
|
|
((CcInt*) args[1].addr)->GetIntval();
|
|
bool upDownFlag =
|
|
((CcBool*) args[2].addr)->GetBoolval();
|
|
if (pNetwork != 0 && pNetwork->IsDefined())
|
|
{
|
|
localinfo = new AdjacentSectionsInfo();
|
|
|
|
pNetwork->GetAdjacentSections(sectId, upDownFlag,
|
|
localinfo->resArray);
|
|
|
|
ListExpr resultType = GetTupleResultType( in_pSupplier );
|
|
localinfo->resTupleTyp = new TupleType(nl->Second(resultType));
|
|
}
|
|
local = SetWord(localinfo);
|
|
return 0;
|
|
break;
|
|
}
|
|
|
|
case REQUEST:
|
|
{
|
|
localinfo = (AdjacentSectionsInfo*) local.addr;
|
|
if (localinfo != 0 && localinfo->pos < localinfo->resArray->Size())
|
|
{
|
|
SectionValue adjSectEntry;
|
|
localinfo->resArray->Get(localinfo->pos,adjSectEntry);
|
|
Tuple *res = new Tuple(localinfo->resTupleTyp);
|
|
res->PutAttribute(0,new CcInt(true,adjSectEntry.GetSectionID()));
|
|
res->PutAttribute(1,new CcBool(true,adjSectEntry.GetUpDownFlag()));
|
|
localinfo->pos++;
|
|
result.setAddr(res);
|
|
return YIELD;
|
|
}
|
|
else
|
|
return CANCEL;
|
|
break;
|
|
}
|
|
|
|
case CLOSE:
|
|
{
|
|
localinfo = (AdjacentSectionsInfo*) local.addr;
|
|
if (localinfo != 0)
|
|
{
|
|
localinfo->Destroy();
|
|
delete localinfo->resArray;
|
|
localinfo->resArray = 0;
|
|
if (localinfo->resTupleTyp != 0)
|
|
{
|
|
localinfo->resTupleTyp->DeleteIfAllowed();
|
|
localinfo->resTupleTyp = 0;
|
|
}
|
|
delete localinfo;
|
|
localinfo = 0;
|
|
local.setAddr(0);
|
|
}
|
|
return 0;
|
|
break;
|
|
}
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
struct getAdjacentSectionsInfo:OperatorInfo{
|
|
getAdjacentSectionsInfo():OperatorInfo(){
|
|
name = "getAdjacentSections";
|
|
signature = "network X int X bool -> stream(tupel((int)(bool)))";
|
|
syntax = "getAdjacentSections(_,_,_)";
|
|
meaning = "Returns the adjacent sections in given direction.";
|
|
}
|
|
};
|
|
|
|
/*
|
|
6.25 Operator ~getReverseAdjacentSections~
|
|
|
|
Returns the reverse adjacent Sections of the given section.
|
|
|
|
*/
|
|
|
|
int OpGetReverseAdjacentSectionsValueMap(Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier)
|
|
{
|
|
AdjacentSectionsInfo *localinfo = 0;
|
|
|
|
switch(message)
|
|
{
|
|
|
|
case OPEN:
|
|
{
|
|
Network* pNetwork = (Network*) args[0].addr;
|
|
int sectId =
|
|
((CcInt*) args[1].addr)->GetIntval();
|
|
bool upDownFlag =
|
|
((CcBool*) args[2].addr)->GetBoolval();
|
|
if (pNetwork != 0 && pNetwork->IsDefined())
|
|
{
|
|
localinfo = new AdjacentSectionsInfo();
|
|
|
|
pNetwork->GetReverseAdjacentSections(sectId, upDownFlag,
|
|
localinfo->resArray);
|
|
|
|
ListExpr resultType = GetTupleResultType( in_pSupplier );
|
|
localinfo->resTupleTyp = new TupleType(nl->Second(resultType));
|
|
}
|
|
local = SetWord(localinfo);
|
|
return 0;
|
|
break;
|
|
}
|
|
|
|
case REQUEST:
|
|
{
|
|
localinfo = (AdjacentSectionsInfo*) local.addr;
|
|
if (localinfo != 0 && localinfo->pos < localinfo->resArray->Size())
|
|
{
|
|
SectionValue adjSectEntry;
|
|
localinfo->resArray->Get(localinfo->pos,adjSectEntry);
|
|
Tuple *res = new Tuple(localinfo->resTupleTyp);
|
|
res->PutAttribute(0,new CcInt(true,adjSectEntry.GetSectionID()));
|
|
res->PutAttribute(1,new CcBool(true,adjSectEntry.GetUpDownFlag()));
|
|
localinfo->pos++;
|
|
result.setAddr(res);
|
|
return YIELD;
|
|
}
|
|
else
|
|
return CANCEL;
|
|
break;
|
|
}
|
|
|
|
case CLOSE:
|
|
{
|
|
localinfo = (AdjacentSectionsInfo*) local.addr;
|
|
if (localinfo != 0)
|
|
{
|
|
localinfo->Destroy();
|
|
delete localinfo->resArray;
|
|
localinfo->resArray = 0;
|
|
if (localinfo->resTupleTyp != 0)
|
|
{
|
|
localinfo->resTupleTyp->DeleteIfAllowed();
|
|
localinfo->resTupleTyp = 0;
|
|
}
|
|
delete localinfo;
|
|
localinfo = 0;
|
|
local.setAddr(0);
|
|
}
|
|
return 0;
|
|
break;
|
|
}
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
struct getReverseAdjacentSectionsInfo:OperatorInfo{
|
|
getReverseAdjacentSectionsInfo():OperatorInfo(){
|
|
name = "getReverseAdjacentSections";
|
|
signature = "network X int X bool -> stream(tupel((int)(bool)))";
|
|
syntax = "getReverseAdjacentSections(_,_,_)";
|
|
meaning = "Returns the reverse adjacent sections.";
|
|
}
|
|
};
|
|
|
|
/*
|
|
6.26 Operators ~circle~, ~incircle~, ~outcircle~
|
|
|
|
6.26.1 TypeMapping for all operators
|
|
|
|
*/
|
|
ListExpr circleTypeMap ( ListExpr args )
|
|
{
|
|
NList param(args);
|
|
|
|
if(param.length() != 2 )
|
|
return listutils::typeError("2 arguments expected.");
|
|
|
|
NList gp(param.first());
|
|
if (!gp.isSymbol(GPoint::BasicType()))
|
|
return listutils::typeError("First argument should be gpoint.");
|
|
|
|
NList dist(param.second());
|
|
if (!dist.isSymbol(CcReal::BasicType()))
|
|
return listutils::typeError("Second argument should be real.");
|
|
|
|
return nl->SymbolAtom(GLine::BasicType());
|
|
}
|
|
|
|
/*
|
|
6.26.2 ValueMappings and OperatorInfos for cirlce-Operators
|
|
|
|
6.26.2.1 ~circle~
|
|
|
|
*/
|
|
int circleValueMap(Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier)
|
|
{
|
|
GPoint* gp = (GPoint*) args[0].addr;
|
|
double maxdist = ((CcReal*)args[1].addr)->GetRealval();
|
|
if (!gp->IsDefined()) return 0;
|
|
Network *pNetwork = NetworkManager::GetNetworkNew(gp->GetNetworkId(),netList);
|
|
result = qp->ResultStorage(in_pSupplier);
|
|
GLine* pGLine = static_cast<GLine*>(result.addr);
|
|
gp->Circle(pNetwork, pGLine, maxdist);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return 1;
|
|
}
|
|
|
|
struct circleInfo:OperatorInfo{
|
|
circleInfo():OperatorInfo(){
|
|
name = "circlen";
|
|
signature = "gpoint X real -> gline";
|
|
syntax = "circlen(_,_)";
|
|
meaning = "Network part within dist around gpoint.";
|
|
}
|
|
};
|
|
|
|
/*
|
|
6.26.2.2 ~incircle~
|
|
|
|
*/
|
|
int inCircleValueMap(Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier)
|
|
{
|
|
GPoint* gp = (GPoint*) args[0].addr;
|
|
double maxdist = ((CcReal*)args[1].addr)->GetRealval();
|
|
if (!gp->IsDefined()) return 0;
|
|
Network *pNetwork = NetworkManager::GetNetworkNew(gp->GetNetworkId(),netList);
|
|
result = qp->ResultStorage(in_pSupplier);
|
|
GLine* pGLine = static_cast<GLine*>(result.addr);
|
|
gp->In_Circle(pNetwork, pGLine, maxdist);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return 1;
|
|
}
|
|
|
|
struct inCircleInfo:OperatorInfo{
|
|
inCircleInfo():OperatorInfo(){
|
|
name = "in_circlen";
|
|
signature = "gpoint X real -> gline";
|
|
syntax = "in_circlen(_,_)";
|
|
meaning = "Network part gpoint can be reached within dist.";
|
|
}
|
|
};
|
|
|
|
/*
|
|
6.26.2.3 ~outcircle~
|
|
|
|
*/
|
|
|
|
int outCircleValueMap(Word* args, Word& result, int message,
|
|
Word& local, Supplier in_pSupplier)
|
|
{
|
|
GPoint* gp = (GPoint*) args[0].addr;
|
|
double maxdist = ((CcReal*)args[1].addr)->GetRealval();
|
|
if (!gp->IsDefined()) return 0;
|
|
Network *pNetwork = NetworkManager::GetNetworkNew(gp->GetNetworkId(),netList);
|
|
result = qp->ResultStorage(in_pSupplier);
|
|
GLine* pGLine = static_cast<GLine*>(result.addr);
|
|
gp->Out_Circle(pNetwork, pGLine, maxdist);
|
|
NetworkManager::CloseNetwork(pNetwork);
|
|
return 1;
|
|
}
|
|
|
|
struct outCircleInfo:OperatorInfo{
|
|
outCircleInfo():OperatorInfo(){
|
|
name = "out_circlen";
|
|
signature = "gpoint X real -> gline";
|
|
syntax = "out_circlen(_,_)";
|
|
meaning = "Network part within dist of gpoint.";
|
|
}
|
|
};
|
|
|
|
/*
|
|
5.28 Operator ~bbox~
|
|
|
|
Returns the spatial bounding box of the ~network~
|
|
|
|
*/
|
|
|
|
ListExpr bboxTypeMap(ListExpr in_xArgs)
|
|
{
|
|
NList param(in_xArgs);
|
|
|
|
if (param.length() != 1)
|
|
return listutils::typeError("one argument expected");
|
|
|
|
if (param.first().isSymbol(Network::BasicType()))
|
|
return nl->SymbolAtom( Rectangle<2>::BasicType() );
|
|
else
|
|
return listutils::typeError("network expected");
|
|
}
|
|
|
|
int bboxValueMap( Word* args, Word& result, int message,
|
|
Word& local, Supplier s ){
|
|
result = qp->ResultStorage( s );
|
|
Rectangle<2>* box = static_cast<Rectangle<2>* >(result.addr);
|
|
Network* arg = static_cast<Network*>(args[0].addr);
|
|
if(!arg->IsDefined()){
|
|
box->SetDefined(false);
|
|
} else {
|
|
*box = arg->BoundingBox();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
struct OpBboxInfo:OperatorInfo{
|
|
OpBboxInfo(){
|
|
name = "netbbox";
|
|
signature = "network -> rect2";
|
|
syntax = "netbbox(_)";
|
|
meaning = "Returns the spatial bounding box of the network.";
|
|
}
|
|
};
|
|
|
|
/*
|
|
7 Creating the ~NetworkAlgebra~
|
|
|
|
*/
|
|
|
|
class NetworkAlgebra : public Algebra
|
|
{
|
|
public:
|
|
NetworkAlgebra() : Algebra()
|
|
{
|
|
AddTypeConstructor ( &networkTC );
|
|
AddTypeConstructor ( &gpointTC);
|
|
AddTypeConstructor ( &glineTC );
|
|
AddTypeConstructor ( &gpointsTC );
|
|
|
|
gpointTC.AssociateKind ( Kind::DATA() );
|
|
glineTC.AssociateKind ( Kind::DATA() );
|
|
networkTC.AssociateKind ( Kind::NETWORK() );
|
|
gpointsTC.AssociateKind ( Kind::DATA() );
|
|
|
|
AddOperator ( lengthInfo(), OpLengthValueMap, OpLengthTypeMap);
|
|
AddOperator ( noComponentsInfo(), OpNoComponentsValueMapping,
|
|
OpNoComponentsTypeMap);
|
|
AddOperator ( isEmptyInfo(), OpNetIsEmptyValueMap, OpNetIsEmptyTypeMap);
|
|
AddOperator ( &theNetwork);
|
|
AddOperator ( routesInfo(), OpNetworkRoutesValueMapping,
|
|
OpNetworkRoutesTypeMap);
|
|
AddOperator ( junctionsInfo(), OpNetworkJunctionsValueMapping,
|
|
OpNetworkJunctionsTypeMap);
|
|
AddOperator ( sectionsInfo(), OpNetworkSectionsValueMapping,
|
|
OpNetworkSectionsTypeMap);
|
|
AddOperator ( insideInfo(), OpInsideValueMap, OpInsideTypeMap);
|
|
AddOperator ( netdistanceInfo(), OpNetNetdistancemap,
|
|
OpNetNetdistanceselect, OpNetNetdistanceTypeMap);
|
|
AddOperator ( netdistanceNewInfo(), OpNetNetdistanceNewmap,
|
|
OpNetNetdistanceNewselect, OpNetNetdistanceNewTypeMap);
|
|
AddOperator ( point2gpointInfo(), OpPoint2GPointValueMapping,
|
|
OpPoint2GPointTypeMap);
|
|
AddOperator ( gpoint2pointInfo(), OpGPoint2PointValueMapping,
|
|
OpGPoint2PointTypeMap);
|
|
AddOperator ( equalInfo(), OpNetEqualmap, OpNetEqualselect,
|
|
OpNetEqualTypeMap);
|
|
AddOperator ( line2glineInfo(), OpLine2GLineValueMapping,
|
|
OpLine2GLineTypeMap);
|
|
AddOperator ( polygpointsInfo(), OpPolyGPointValueMapping,
|
|
OpPolyGPointTypeMap);
|
|
AddOperator ( routeIntervalsInfo(), OpRouteIntervalsValueMapping,
|
|
OpRouteIntervalsTypeMap);
|
|
AddOperator ( intersectsInfo(), OpNetIntersectsValueMapping,
|
|
OpNetIntersectsTypeMap);
|
|
AddOperator ( gpoint2rectInfo(), OpGPoint2RectValueMapping,
|
|
OpGPoint2RectTypeMap);
|
|
AddOperator ( gline2lineInfo(), OpGLine2LineValueMapping,
|
|
OpGLine2LineTypeMap);
|
|
AddOperator ( unionInfo(), OpNetUnionValueMap, OpNetUnionTypeMap);
|
|
AddOperator ( distanceInfo(), OpNetDistancemap, OpNetDistanceselect,
|
|
OpNetDistanceTypeMap);
|
|
AddOperator ( shortestpathInfo(), OpShortestPathValMap,
|
|
OpShortestPathSelect, OpShortestPathTypeMap);
|
|
AddOperator ( shortestpathAstarInfo(), OpShortestPathAStarMap,
|
|
OpShortestPathAStarSelect, OpShortestPathAStarTypeMap);
|
|
AddOperator ( getBGPInfo(), OpGetBGPValueMap, OpGetBGPTypeMap);
|
|
AddOperator ( spsearchvisitedInfo(), OpSpvisitedmap, OpSpvisitedselect,
|
|
OpSPSearchVisitedTypeMap);
|
|
AddOperator ( shortestpathtreeInfo(), OpShortestpathtreeMap,
|
|
OpShortestpathtreeSelect, OpShortestpathtreeTypeMap);
|
|
AddOperator ( getAdjacentSectionsInfo(), OpGetAdjacentSectionsValueMap,
|
|
OpGetAdjacentSectionsTypeMap);
|
|
AddOperator ( getReverseAdjacentSectionsInfo(),
|
|
OpGetReverseAdjacentSectionsValueMap,
|
|
OpGetAdjacentSectionsTypeMap);
|
|
AddOperator ( inCircleInfo(), inCircleValueMap, circleTypeMap);
|
|
AddOperator ( outCircleInfo(), outCircleValueMap, circleTypeMap);
|
|
AddOperator ( circleInfo(), circleValueMap, circleTypeMap);
|
|
AddOperator ( OpBboxInfo(), bboxValueMap, bboxTypeMap);
|
|
}
|
|
|
|
~NetworkAlgebra()
|
|
{
|
|
delete netList;
|
|
netList = 0;
|
|
}
|
|
};
|
|
|
|
/*
|
|
Initialization
|
|
|
|
Each algebra module needs an initialization function. The algebra manager
|
|
has a reference to this function if this algebra is included in the list
|
|
of required algebras, thus forcing the linker to include this module.
|
|
|
|
The algebra manager invokes this function to get a reference to the instance
|
|
of the algebra class and to provide references to the global nested list
|
|
container (used to store constructor, type, operator and object information)
|
|
and to the query processor.
|
|
|
|
The function has a C interface to make it possible to load the algebra
|
|
dynamically at runtime.
|
|
|
|
*/
|
|
|
|
extern "C"
|
|
Algebra*
|
|
InitializeNetworkAlgebra ( NestedList* nlRef,
|
|
QueryProcessor* qpRef )
|
|
{
|
|
nl = nlRef;
|
|
qp = qpRef;
|
|
netList = new map<int,string>();
|
|
return ( new NetworkAlgebra() );
|
|
}
|