Files
secondo/Algebras/Network2/Network2Algebra.cpp
2026-01-23 17:03:45 +08:00

11227 lines
353 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
April-Mai 2011 - Nina Wrede
1.1 Defines, includes, and constants
*/
#include <sstream>
#include <time.h>
#include <map>
#include <iterator>
#include "Algebras/TupleIdentifier/TupleIdentifier.h"
#include "Algebras/Relation-C++/RelationAlgebra.h"
#include "Algebras/BTree/BTreeAlgebra.h"
#include "Algebras/RTree/RTreeAlgebra.h"
#include "Tools/Flob/DbArray.h"
#include "Tools/Flob/Flob.h"
#include "Algebras/Spatial/SpatialAlgebra.h"
#include "Network2Algebra.h"
#include "Algebras/Rectangle/RectangleAlgebra.h"
#include "StandardTypes.h"
#include "Algebra.h"
#include "Messages.h"
#include "Network2Manager.h"
#include "NestedList.h"
#include "NList.h"
#include "QueryProcessor.h"
#include "AlgebraManager.h"
#include "ListUtils.h"
#include "TypeMapUtils.h"
using namespace network2;
using namespace std;
extern NestedList* nl;
extern QueryProcessor* qp;
static map<int,string> *netList;
/*
2 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();
NList xMessage;
xMessage.append ( NList ( "error" ) );
xMessage.append ( NList().textAtom ( in_strMessage ) );
xMessageCenter->Send (nl, xMessage.listExpr() );
}
/*
Computes a spatial BoundingBox of a RouteInterval
*/
Rectangle<2> RouteInterval::BoundingBox ( Network* pNetwork,
const Geoid* geoid /*=0*/ ) const
{
if(geoid){
cerr << __PRETTY_FUNCTION__ << ": Spherical geometry not implemented."
<< endl;
assert( !geoid ); // TODO: implement spherical geometry case
}
if ( AlmostEqual ( m_dStart , m_dEnd ) )
{
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 searchRouteInterval ( GPoint *pGPoint, GLine *&pGLine, size_t low,
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, mid+1, high );
}
else
{
if ( rI.GetRouteId() > pGPoint->GetRouteId() )
{
return searchRouteInterval ( pGPoint, pGLine, low, mid-1 );
}
else
{
if ( fabs ( pGPoint->GetPosition() - rI.GetStartPos() ) < 0.01 ||
fabs ( pGPoint->GetPosition() - rI.GetEndPos() ) < 0.01 )
{
return true;
}
else
{
if ( rI.GetStartPos() > pGPoint->GetPosition() )
{
return searchRouteInterval ( pGPoint, pGLine, low, mid-1 );
}
else
{
if ( rI.GetEndPos() < pGPoint->GetPosition() )
{
return searchRouteInterval ( pGPoint, pGLine, 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 ( 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 ( 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.
*/
void Find ( TupleId n, SectTree *result, bool &found )
{
if ( n < value.secttid )
{
if ( right != 0 ) right->Find ( n, result, found );
else
{
found = false;
result = 0;
}
}
else
{
if ( n > value.secttid )
{
if ( left != 0 ) left->Find ( n, result, found );
else
{
found = false;
result = 0;
}
}
else
{
found = true;
result = this;
}
}
};
void CheckSection ( Network *pNetwork, SectTreeEntry n, GPoints &result )
{
vector<DirectedSection> sectList;
sectList.clear();
SectTree *pSectTree = 0;
if ( n.startbool || n.endbool )
{
if ( n.startbool )
{
pNetwork->GetAdjacentSections ( n.secttid, false, sectList );
size_t j = 0;
bool found = true;
while ( j < sectList.size() && found )
{
DirectedSection actSection = sectList[j];
Find ( actSection.GetSectionTid(), pSectTree, found );
}
if ( !found )
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;
bool found = true;
while ( j < sectList.size() && found )
{
DirectedSection actSection = sectList[j];
Find ( actSection.GetSectionTid(), pSectTree, found );
}
if ( !found ) 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 ( Network* pNetwork, GPoints &result, SectTree &secTr )
{
if ( left != 0 ) left->WriteResult ( pNetwork, result, secTr );
if ( right != 0 ) right ->WriteResult ( pNetwork, result, secTr );
secTr.CheckSection ( pNetwork, value, result );
//TODO: Remove duplicate GPoint from Result, which are caused by junction
//problematic
};
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, Point point, bool startSmaller, double &pos,
double &difference )
{
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 ( ( fabs ( x-xr ) < 0.01 && fabs ( y-yr ) < 0.01 ) ||
( fabs ( x-xl ) < 0.01 && fabs ( y-yl ) < 0.01 ) )
{
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 ) &&
( ( xl < xr &&
( x > xl || fabs ( x-xl ) < 0.01 ) &&
( x < xr || fabs ( x-xr ) < 0.01 ) ) ||
( xl > xr &&
( x < xl || fabs ( x-xl ) <0.01 ) &&
( x > xr || fabs ( x-xr ) < 0.01 ) ) ) &&
((( yl <= yr &&
( y > yl || fabs ( y-yl ) <0.01 ) &&
( y < yr || fabs ( y-yr ) <0.01 ) ) ||
( yl > yr &&
( y < yl || fabs ( y-yl ) <0.01 ) &&
( y > yr || fabs ( y-yr ) <0.01 ) ) ) ))
{
difference = fabs ( k1-k2 );
result = true;
}
else {result = false;}
}
else
{
if ( ( fabs ( xl - xr ) < 0.01 && fabs ( xl -x ) < 0.01 ) &&
( ( ( yl <= yr &&
( yl < y || fabs (yl-y ) < 0.01 ) &&
( y < yr ||fabs ( y-yr ) <0.01 ) ) ||
( yl > yr &&
( yl > y || fabs ( yl-y ) < 0.01) &&
( y > yr ||fabs ( y-yr ) <0.01 ) ) ) ))
{
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 ( fabs ( pos-0.0 ) < 0.01 )
pos = 0.0;
else if ( fabs ( pos-route->Length() ) <0.01 )
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, Point point, bool startSmaller,
double &pos, double &difference )
{
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 ( ( fabs ( x-xl ) < 0.01 && fabs ( y-yl ) < 0.01 ) ||
( fabs ( x-xr ) < 0.01 && fabs ( y-yr ) < 0.01 ) )
{
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 ) &&
( ( xl < xr &&
( x > xl || fabs ( x-xl ) < 0.01 ) &&
( x < xr || fabs ( x-xr ) < 0.01 ) ) ||
( xl > xr &&
( x < xl || fabs ( x-xl ) < 0.01 ) &&
( x > xr || fabs ( x-xr ) < 0.01 ) ) ) &&
( ( ( yl < yr || fabs ( yl-yr ) < 0.01 ) &&
( y > yl || fabs (y-yl ) <0.01 ) &&
( y < yr || fabs ( y-yr ) <0.01 ) ) ||
( yl > yr &&
( y < yl || fabs ( y-yl ) <0.01 ) &&
( y > yr || fabs ( y-yr ) <0.01 ) ) ) )
{
difference = fabs ( k1-k2 );
result = true;
}
else {result = false;}
}
else
{
if ( ( fabs ( xl - xr ) < 0.01 && fabs ( xl -x ) < 0.01 ) &&
( ( ( yl < yr|| fabs ( yl-yr ) <0.01 ) &&
( yl < y || fabs (yl-y ) <0.01 ) &&
( y < yr ||fabs ( y-yr ) <0.01 ) ) ||
( yl > yr &&
( yl > y || fabs ( yl-y ) < 0.01) &&
( y > yr ||fabs ( y-yr ) <0.01 ) ) ) )
{
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 ( fabs ( pos-0.0 ) < 0.01 )
pos = 0.0;
else if ( fabs ( pos-route->Length() ) <0.01 )
pos = route->Length();
return result;
}
}
return result;
}
bool lastchkPoint03 ( SimpleLine *&route, Point point, bool startSmaller,
double &pos, double &difference )
{
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 ( ( fabs ( x-xl ) < 0.01 && fabs ( y-yl ) < 0.01 ) ||
( fabs ( x-xr ) < 0.01 && fabs ( y-yr ) < 0.01 ) )
{
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 || fabs ( x-xl ) < 0.1 ) &&
( x < xr || fabs ( x-xr ) < 0.01 ) ) ||
( xl > xr &&
( x < xl || fabs ( x-xl ) <0.01 ) &&
( x > xr || fabs ( x-xr ) < 0.01) ) ) &&
( ( ( yl < yr || fabs ( yl-yr ) < 0.01 ) &&
( y > yl || fabs (y-yl ) < 0.01 ) &&
( y < yr || fabs ( y-yr ) < 0.01 ) ) ||
( yl > yr &&
( y < yl || fabs ( y-yl ) <0.01 ) &&
( y > yr || fabs ( y-yr ) <0.01 ) ) ) )
{
difference = fabs ( k1-k2 );
result = true;
}
else {result = false;}
}
else
{
if ( ( fabs ( xl - xr ) < 0.01 && fabs ( xl -x ) < 0.01 ) &&
( ( ( yl < yr|| fabs ( yl-yr ) <0.01 ) &&
( yl < y || fabs ( yl-y ) <0.01 ) &&
( y < yr ||fabs ( y-yr ) <0.01 ) ) ||
( yl > yr &&
( yl > y || fabs ( yl-y ) < 0.01 ) &&
( y > yr ||fabs ( y-yr ) <0.01 ) ) ) )
{
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 ( pos < 0.0 || fabs ( pos - 0.0 ) < 0.01 )
pos = 0.0;
else if ( pos > route->Length() || fabs ( pos - route->Length() ) < 0.01 )
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, Point point, bool startSmaller,
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 ( ( fabs ( x-xr ) < 0.01 && fabs ( y-yr ) < 0.01 ) ||
( fabs ( x-xl ) < 0.01 && fabs ( y-yl ) < 0.01 ) )
{
result = true;
}
else
{
if ( xl != xr && xl != x )
{
k1 = ( y - yl ) / ( x - xl );
k2 = ( yr - yl ) / ( xr - xl );
if ( ( fabs ( k1-k2 ) < 0.004 ) &&
( ( xl < xr &&
( x > xl || fabs ( x-xl ) < 0.01 ) &&
( x < xr || fabs ( x-xr ) < 0.01 ) ) ||
( xl > xr &&
( x < xl || fabs ( x-xl ) < 0.01 ) &&
( x > xr || fabs ( x-xr ) < 0.01 ) ) ) &&
( ( ( yl < yr || fabs ( yl-yr ) < 0.01 ) &&
( y > yl || fabs ( y-yl ) < 0.01 ) &&
( y < yr || fabs ( y-yr ) < 0.01 ) ) ||
( yl > yr &&
( y < yl || fabs ( y-yl ) < 0.01 ) &&
( y > yr || fabs ( y-yr ) < 0.01 ) ) ) )
{
result = true;
}
else {result = false;}
}
else
{
if ( ( fabs ( xl - xr ) < 0.01 && fabs ( xl -x ) < 0.01 ) &&
( ( ( yl < yr|| fabs ( yl-yr ) < 0.01 ) &&
( yl < y || fabs ( yl-y ) <0.01 ) &&
( y < yr ||fabs ( y-yr ) <0.01 ) ) ||
( yl > yr &&
( yl > y || fabs ( yl-y ) < 0.01) &&
( y > yr ||fabs ( y-yr ) <0.01 ) ) ) )
{
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 ( fabs ( pos-0.0 ) < 0.01 )
pos = 0.0;
else if ( fabs ( pos-route->Length() ) <0.01 )
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 ( GLine *pGLine, size_t low, size_t high,
RouteInterval pRi )
{
assert ( pGLine->IsSorted() );
RouteInterval rI;
if ( low <= high )
{
size_t mid = ( high + low ) / 2;
int imid = mid;
if ( ( mid < 0 ) || ( imid >= 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;
}
}
}
}
}
}
else
{
return false;
}
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 ( GPoint *gp, Network *pNetwork ) :
aliasGP ( 0 )
{
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 ( fabs ( pCurrJunction.GetRouteMeas() - gp->GetPosition() ) < 0.01
)
{
found = true;
GPoint test ( true, gp->GetNetworkId(),
pCurrJunction.GetOtherRouteId(),
pCurrJunction.GetOtherRouteMeas(),
None );
aliasGP.Append ( test );
}
i++;
}
while ( found && i < xJunctions.size() )
{
pCurrJunction = xJunctions[i];
if ( fabs ( pCurrJunction.GetRouteMeas() - gp->GetPosition() ) <0.01 )
{
GPoint test ( true, gp->GetNetworkId(),
pCurrJunction.GetOtherRouteId(),
pCurrJunction.GetOtherRouteMeas(),
None );
aliasGP.Append ( test );
}
else
{
found = false;
}
i++;
}
for ( unsigned int 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;
if ( lastPos >= aliasGP.Size() || lastPos < 0 )
{
pAktGPoint.SetDefined ( false );
}
else
{
aliasGP.Get ( lastPos, pAktGPoint );
lastPos++;
}
return pAktGPoint;
}
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 ( 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 ( int ri,double pos1, double pos2, RIStack* next = 0 )
{
m_iRouteId = ri;
m_dStart = pos1;
m_dEnd = pos2;
m_next = next;
};
~RIStack() {};
void Push ( int rid, double pos1, double pos2, RIStack *&first )
{
RIStack *actElem = new RIStack ( rid, pos1, pos2, this );
first = actElem;
};
void StackToGLine ( GLine *gline )
{
int actRId = m_iRouteId;
double actStartPos = m_dStart;
double actEndPos = m_dEnd;
RIStack *actElem = this->m_next;
while ( actElem != 0 )
{
if ( actRId == actElem->m_iRouteId &&
AlmostEqual ( actEndPos,actElem->m_dStart ) )
{
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;
};
/*
Class PQEntry used for priority Queue in Dijkstras Algorithm for shortest path
computing between two gpoint.
*/
class PQEntry
{
public:
PQEntry() {}
PQEntry ( TupleId aktID, double distance, bool upDown,
TupleId beforeID )
{
sectID = aktID;
distFromStart = distance;
upDownFlag = upDown;
beforeSectID = beforeID;
meas1 =0;
meas2 =0;
rid = 0;
costFromStart = 0.0;
}
PQEntry(TupleId in_aktID, double in_distance, bool in_upDown,
TupleId in_beforeID, double in_meas1, double in_meas2,
int in_rid, double in_costs=0.0 ):
sectID(in_aktID),
distFromStart(in_distance),
upDownFlag(in_upDown),
beforeSectID(in_beforeID),
meas1(in_meas1),
meas2(in_meas2),
rid(in_rid),
costFromStart(in_costs)
{
}
PQEntry ( PQEntry &e )
{
sectID = e.sectID;
distFromStart = e.distFromStart;
upDownFlag = e.upDownFlag;
beforeSectID = e.beforeSectID;
meas1 = e.meas1;
meas2 = e.meas2;
rid = e.rid;
costFromStart = e.costFromStart;
}
PQEntry ( const PQEntry &e )
{
sectID = e.sectID;
distFromStart = e.distFromStart;
upDownFlag = e.upDownFlag;
beforeSectID = e.beforeSectID;
meas1 = e.meas1;
meas2 = e.meas2;
rid = e.rid;
costFromStart = e.costFromStart;
}
~PQEntry() {}
TupleId sectID;
double distFromStart;
bool upDownFlag;
TupleId beforeSectID;
double meas1;
double meas2;
int rid;
double costFromStart;
};
/*
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 ( TupleId sectIdent, TupleId beforeSectIdent, bool upDown,
int arrayIndex,
SectIDTree *l = 0,SectIDTree *r = 0 )
{
sectID = sectIdent;
beforeSectId = beforeSectIdent;
upDownFlag = upDown;
index = arrayIndex;
left = l;
right = r;
};
~SectIDTree() {};
SectIDTree* Find ( 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;
}
}
};
void Remove()
{
if ( left != 0 ) left->Remove();
if ( right != 0 ) right->Remove();
delete this;
};
bool Insert ( TupleId sectIdent, TupleId beforeSectIdent, bool upDownFlag,
int arrayIndex,SectIDTree *&pointer )
{
pointer = Find ( sectIdent );
if ( pointer->sectID != sectIdent )
{
if ( pointer->sectID > sectIdent )
{
pointer->left = new SectIDTree ( sectIdent, beforeSectIdent, upDownFlag,
arrayIndex );
pointer = pointer->left;
return true;
}
else
{
if ( pointer->sectID < sectIdent )
{
pointer->right = new SectIDTree ( sectIdent, beforeSectIdent,
upDownFlag, arrayIndex );
pointer = pointer->right;
return true;
}
else
{
//should never be reached
return false;
}
}
}
else
{
return false;
}
};
void SetIndex ( TupleId sectIdent, int arrayIndex )
{
Find ( sectIdent )->index = arrayIndex;
};
void SetIndex ( int arrayIndex )
{
index = arrayIndex;
};
int GetIndex ( TupleId sectIdent )
{
return Find ( sectIdent )->index;
};
void SetBeforeSectId ( TupleId sectIdent, TupleId before )
{
Find ( sectIdent )->beforeSectId = before;
};
void SetBeforeSectId ( TupleId before )
{
beforeSectId = before;
};
TupleId sectID;
TupleId beforeSectId;
bool upDownFlag;
int index;
SectIDTree *left, *right;
};
/*
struct Priority Queue for Dijkstras Algorithm of shortest path computing between
two gpoint.
*/
struct PrioQueue
{
PrioQueue() {};
PrioQueue ( 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 ( int checkX, const PQEntry nElem, SectIDTree *pSection,
SectIDTree *sectTree, bool calcCost=false )
{
int act = checkX;
PQEntry test;
bool found = false;
while ( checkX >= 0 && !found )
{
if ( ( act % 2 ) == 0 ) checkX = ( act-2 ) / 2;
else checkX = ( act -1 ) / 2;
if ( checkX >= 0 )
{
prioQ.Get ( checkX, test );
if(calcCost){
if ( test.costFromStart > nElem.costFromStart )
{
PQEntry help = test;
prioQ.Put ( checkX, nElem );
pSection->SetIndex ( checkX );
prioQ.Put ( act, help );
SectIDTree *thelp = sectTree->Find ( help.sectID );
thelp->SetIndex ( act );
act = checkX;
}
else
{
found = true;
}
}
else {
if ( test.distFromStart > nElem.distFromStart )
{
PQEntry help = test;
prioQ.Put ( checkX, nElem );
pSection->SetIndex ( checkX );
prioQ.Put ( act, help );
SectIDTree *thelp = sectTree->Find ( help.sectID );
thelp->SetIndex ( act );
act = checkX;
}
else
{
found = true;
}
}
}
else
{
found = true;
}
}
};
void Insert ( PQEntry nElem, SectIDTree *sectTree, bool calcCost=false )
{
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(calcCost)
{
if ( nElem.costFromStart < old.costFromStart )
{
prioQ.Put ( pSection->index, nElem );
pSection->SetBeforeSectId ( nElem.beforeSectID );
CorrectPosition( pSection->index, nElem, pSection, sectTree,true);
}
}
else
{
if ( nElem.distFromStart < old.distFromStart )
{
prioQ.Put ( pSection->index, nElem );
pSection->SetBeforeSectId ( nElem.beforeSectID );
CorrectPosition(pSection->index, nElem, pSection, sectTree,false);
}
}
}
}
else
{
prioQ.Put ( firstFree, nElem );
sectTree->Insert ( nElem.sectID, nElem.beforeSectID, nElem.upDownFlag,
firstFree, pSection );
CorrectPosition ( firstFree, nElem, pSection ,sectTree,calcCost );
firstFree++;
}
}
PQEntry* GetAndDeleteMin ( SectIDTree *sectTree, bool calcCost=false)
{
if ( firstFree > 0 )
{
PQEntry result, last, test1, test2;
prioQ.Get ( 0,result );
PQEntry *retValue = new PQEntry ( result.sectID,
result.distFromStart,
result.upDownFlag,
result.beforeSectID,
result.meas1,
result.meas2,
result.rid,
result.costFromStart);
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(calcCost)
{
if ( test1.costFromStart < last.costFromStart ||
test2.costFromStart < last.costFromStart )
{
if ( test1.costFromStart <= test2.costFromStart )
{
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 ( 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(calcCost){
if ( test1.costFromStart < last.costFromStart )
{
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;
}
}
else
{
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()
{
if ( firstFree == 0 ) return true;
else return false;
}
void Destroy()
{
prioQ.Destroy();
}
DbArray<PQEntry> prioQ;
int firstFree;
};
/*
3 Class Definitions
3.1 class ~Network~
3.1.1 Network relations
*/
string Network::routesTypeInfo =
"(rel (tuple ((Id int) (Length real) (Curve sline) "
"(Dual bool) (StartsSmaller bool))))";
string Network::routesInternalTypeInfo =
"(rel (tuple ((Id int) (Length real) (Curve sline) "
"(Dual bool) (StartsSmaller bool) (Startposid int))))";
string Network::routesBTreeTypeInfo =
"(btree (tuple ((Id int) (Length real) (Curve sline) "
"(Dual bool) (StartsSmaller bool) (Startposid int) )) int)";
string Network::routesRTreeTypeInfo =
"(rtree (tuple((Id int)(Length real)(Curve sline)(Dual bool)"
"(StartsSmaller bool) (Startposid int) )) 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) "
"(Pnoup int) (Pnodown int) (Slotup int) (Slotdown int) "
"(Cost real) (Time real))))";
string Network::sectionsBTreeTypeInfo =
"(btree (tuple ((Rid int) (Meas1 real) (Meas2 real) (Dual bool)"
"(Curve sline)(CurveStartsSmaller bool) (Rrc tid) (Sid int) "
"(Pnoup int) (Pnodown int) (Slotup int) (Slotdown int) "
"(Cost real) (Time real) )) int)";
string Network::distancestorageTypeInfo =
"(rel (tuple((J1 tid)(J2 tid)(Dist real)(Sp gline))))";
/*
2.1.2 Constructors and destructors class ~Network~
*/
Network::Network() :
m_iId ( 0 ),
m_bDefined ( false ),
m_pRoutes ( 0 ),
m_pJunctions ( 0 ),
m_pSections ( 0 ),
m_pBTreeRoutes ( 0 ),
m_pBTreeRoutesByStartposId( 0 ),
m_pRTreeRoutes ( 0 ),
m_pBTreeJunctionsByRoute1 ( 0 ),
m_pBTreeJunctionsByRoute2 ( 0 ),
m_xAdjacencyList ( 0 ),
m_xSubAdjacencyList ( 0 ),
m_pBTreeSectionsByRoute ( 0 ),
m_pBTreeSections (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)
{
// Read network id
in_xValueRecord.Read ( &m_iId, sizeof ( int ), inout_iOffset );
inout_iOffset += sizeof ( int );
// Open routes
ListExpr xType;
nl->ReadFromString ( routesInternalTypeInfo, 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 btree for routesByStartposId
nl->ReadFromString ( routesBTreeTypeInfo, xType );
xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
m_pBTreeRoutesByStartposId = BTree::Open ( in_xValueRecord,
inout_iOffset,
xNumericType );
if ( !m_pBTreeRoutesByStartposId )
{
m_pRoutes->Delete();
m_pJunctions->Delete();
m_pSections->Delete();
delete m_pBTreeRoutes;
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;
delete m_pBTreeRoutesByStartposId;
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_pBTreeRoutesByStartposId;
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_pBTreeRoutesByStartposId;
delete m_pRTreeRoutes;
delete m_pBTreeJunctionsByRoute1;
return;
}
// m_xAdjacencyList.OpenFromRecord(in_xValueRecord, inout_iOffset);
// m_xSubAdjacencyList.OpenFromRecord(in_xValueRecord,inout_iOffset);
size_t bufsize = sizeof(FlobId) + sizeof(SmiSize) + 2*sizeof(int);
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);
// Open btree for sections by Routes
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_pBTreeRoutesByStartposId;
delete m_pRTreeRoutes;
delete m_pBTreeJunctionsByRoute1;
delete m_pBTreeJunctionsByRoute2;
return;
}
// Open btree for sections
nl->ReadFromString ( sectionsBTreeTypeInfo, xType );
xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
m_pBTreeSections = BTree::Open ( in_xValueRecord,
inout_iOffset,
xNumericType );
if ( !m_pBTreeSections )
{
m_pRoutes->Delete();
m_pJunctions->Delete();
m_pSections->Delete();
delete m_pBTreeRoutes;
delete m_pBTreeRoutesByStartposId;
delete m_pRTreeRoutes;
delete m_pBTreeJunctionsByRoute1;
delete m_pBTreeJunctionsByRoute2;
delete m_pBTreeSectionsByRoute;
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_bDefined ( false ),
m_pRoutes ( 0 ),
m_pJunctions ( 0 ),
m_pSections ( 0 ),
m_pBTreeRoutes ( 0 ),
m_pBTreeRoutesByStartposId ( 0 ),
m_pRTreeRoutes ( 0 ),
m_pBTreeJunctionsByRoute1 ( 0 ),
m_pBTreeJunctionsByRoute2 ( 0 ),
m_xAdjacencyList ( 0 ),
m_xSubAdjacencyList ( 0 ),
m_pBTreeSectionsByRoute ( 0 ),
m_pBTreeSections (0)
/*alldistance(0)*/
{
// Check the list
if ( ! ( nl->ListLength ( in_xValue ) == 3 ) )
{
string strErrorMessage = "Network(): List length must be 3.";
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 xRouteList = nl->Second ( in_xValue );
ListExpr xJunctionList = nl->Third ( 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 );
// 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,
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_pBTreeRoutesByStartposId;
delete m_pRTreeRoutes;
delete m_pBTreeJunctionsByRoute1;
delete m_pBTreeJunctionsByRoute2;
delete m_pBTreeSectionsByRoute;
delete m_pBTreeSections;
// delete alldistance;
}
/*
2.1.3 Methods of class ~network~
Method ~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_pBTreeRoutesByStartposId != 0 );
m_pBTreeRoutesByStartposId->DeleteFile();
delete m_pBTreeRoutesByStartposId; m_pBTreeRoutesByStartposId = 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();
assert ( m_pBTreeSectionsByRoute != 0 );
m_pBTreeSectionsByRoute->DeleteFile();
delete m_pBTreeSectionsByRoute;
m_pBTreeSectionsByRoute = 0;
assert ( m_pBTreeSections != 0 );
m_pBTreeSections->DeleteFile();
delete m_pBTreeSections;
m_pBTreeSections = 0;
/*
assert(alldistance != 0);
delete alldistance;
*/
}
/*
Method ~Load~
Create a network from two external relations
*/
void Network::Load ( int in_iId,
const Relation* in_pRoutes,
const Relation* in_pJunctions )
{
m_iId = in_iId;
FillRoutes ( in_pRoutes );
FillJunctions ( in_pJunctions );
FillSections();
FillAdjacencyLists();
//FillDistanceStorage();//store distance
m_bDefined = true;
}
/*
Method ~OptimizeNetwork~
optimizes the order of the ~routes~, after that all ~sections~ are generated new
and all structures based on these ~sections~ are adjusted
*/
bool Network::OptimizeNetwork(){
//sort routes
OptimizationRoutes();
//DEBUG
//cout << "output of all routes"<< endl;
//for (int i =1; i<=m_pRoutes->GetNoTuples();i++)
//{
//Tuple *n = m_pRoutes->GetTuple(i,false);
//cout <<"("<< ((CcInt*)n->GetAttribute(ROUTE_ID))->GetIntval() << ","
// << ((CcInt*)n->GetAttribute(ROUTE_STARTPOS_ID))->GetIntval()
// << ")"<<endl;
//n->DeleteIfAllowed();
//}
//update the BTree for routes by startPos_id
delete m_pBTreeRoutesByStartposId;
m_pBTreeRoutesByStartposId=0;
ostringstream xThisRoutesPtrStream2;
xThisRoutesPtrStream2 << ( long ) m_pRoutes;
string strQuery = "(createbtree (" + routesInternalTypeInfo +
" (ptr " + xThisRoutesPtrStream2.str() + "))" + " Startposid)";
Word xResult;
int QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
assert ( QueryExecuted ); // no query with side effects, please!
m_pBTreeRoutesByStartposId = ( BTree* ) xResult.addr;
//Fillsections new
delete m_pBTreeSections;
delete m_pBTreeSectionsByRoute;
int anz = m_pSections->GetNoTuples();
for(int z=1;z <= anz ;z++){
m_pSections->DeleteTuple(m_pSections->GetTuple(z,false));
}
m_pSections->Clear();
delete m_pSections;
m_pSections = 0;
FillSections();
//Update the Adjacencylist
//DEBUG cout << "update AdjacencList mit "<< m_xAdjacencyList.Size()<< endl;
m_xAdjacencyList.clean();
m_xAdjacencyList = 0;
FillAdjacencyLists();
return true;
}
/*
Mehtod ~OptimizationRoutes~
determined for all ~routes~ their lexicographic start point, stores them in an
array and calls the sort method ~QuicksortRoutes~
*/
bool Network::OptimizationRoutes(){
Tuple *route;
GPoint *gp;
Point *p = new Point();
int anzElemente = m_pRoutes->GetNoTuples();
int testarray[anzElemente][2];
bool opt= false;
for (int i =1; i<=m_pRoutes->GetNoTuples();i++)
{
route = m_pRoutes->GetTuple(i,false);
int id = ((CcInt*) route->GetAttribute(ROUTE_ID))->GetIntval();
//bool smaller=
// ((CcBool*) route->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
// dermine points
gp = new GPoint(true, GetId(),id, 0.0);
gp->ToPoint(p);
if (p->IsDefined()) opt = true; else return false;
testarray[i-1][0] = id;
testarray[i-1][1] = p->GetX();
}
if(opt)
{
//DEBUG for testing
//cout << "vor dem Sortieren" << endl;
//for (int k =0; k< anzElemente; k++)
//{
//cout << testarray[k][0] <<"," <<testarray[k][1]<< endl;
//}
QuicksortRoutes(testarray,0,anzElemente-1);
//DEBUG for testing
//cout << "nach dem Sortieren" << endl;
//for (int k =0; k< anzElemente; k++)
//{
//cout << testarray[k][0] <<"," <<testarray[k][1]<< endl;
//}
// update startposId in m_pRoutes
for (int k =0; k< anzElemente; k++)
{
route = m_pRoutes->GetTuple(testarray[k][0],false);
vector<int> xIndices;
vector<Attribute*> xAttrs;
xIndices.push_back ( ROUTE_STARTPOS_ID );
xAttrs.push_back ( new CcInt ( true, k+1 ) );
m_pRoutes->UpdateTuple(route, xIndices, xAttrs);
}
}
p->DeleteIfAllowed();
gp->DeleteIfAllowed();
route->DeleteIfAllowed();
return true;
}
/*
Method ~QuicksortRoutes~
calculates the pivot-element-index with the method
~QuicksortRoutesPartition~. After that ~QuicksortRoutes~ is recursively called
for the upper and lower part of the array
*/
void Network::QuicksortRoutes(int arr[][2], int low, int high)
{
int pivotIndex;
if(low < high)
{ //split the array and calculate the pivot-element
pivotIndex = QuicksortRoutesPartition(arr, low, high);
//sort the bottom part
QuicksortRoutes(arr, low, pivotIndex-1);
//sort the top part
QuicksortRoutes(arr, pivotIndex+1,high);
}
}
/*
Method ~QuicksortRoutesPartition~
split the given array and sorts the array so that all elements before the
pivot-element are smaller and all elements that are above the pivot element
are larger.
*/
int Network::QuicksortRoutesPartition(int arr[][2], int low, int high)
{
//DEBUG cout << "QuicksortPartiton: mit lowindex: " << low
// << " und highindex: " << high << endl;
int high_vac[2]={0},low_vac[2]={0},pivot[2]={0};
pivot[0] = arr[low][0];
pivot[1] = arr[low][1];
// while the lowindex is less than the highIndex
while(high > low)
{ //DEBUG cout << "while high: "<< high
// << " ist groesser als low: " << low << endl;
high_vac[0] = arr[high][0];
high_vac[1] = arr[high][1];
//DEBUG cout << "highWert " << high_vac[1] << endl;
//while the value of the high-element is greater than
//or equal the pivot-element
while(pivot[1] <= high_vac[1])
{ //DEBUG cout << "while pivot : "<< pivot[1]
// << " ist kleiner als hight_vac: " << high_vac[1]<< endl;
// if hightindex less then or equal with
// the lowindex BREAK the while-loop
if(high <= low) break;
high--;
high_vac[0] = arr[high][0];
high_vac[1] = arr[high][1];
}
arr[low][0] = high_vac[0];
arr[low][1] = high_vac[1];
low_vac[0] = arr[low][0];
low_vac[1] = arr[low][1];
//while the value of the pivot-element is greater than the low-element
while(pivot[1] > low_vac[1])
{ //cout << "while pivot : "<< pivot[1]
// << " ist groesser als low_vac: " << low_vac[1]<< endl;
// if hightindex less then or equal with
// the lowindex BREAK the while-loop
if(high<=low) break;
low++;
low_vac[0] = arr[low][0];
low_vac[1] = arr[low][1];
}
arr[high][0] = low_vac[0];
arr[high][1] = low_vac[1];
}
arr[low][0] = pivot[0];
arr[low][1] = pivot[1];
//return the lowindex value
return low;
}
/*
Method ~FillRoutes~
Fill routes relation of network
*/
void Network::FillRoutes ( const Relation *routes )
{
//Create new table for the routes
ListExpr xTypeInfo;
nl->ReadFromString ( routesInternalTypeInfo, xTypeInfo );
ListExpr xNumType = SecondoSystem::GetCatalog()->NumericType ( xTypeInfo );
Relation *pIntRoutes = new Relation ( xNumType, true );
// Iterator for the input-table with routes
GenericRelationIterator* pRoutesIter = routes->MakeScan();
Tuple* pCurrentRoute;
int routeCounter =1;
while ( ( pCurrentRoute = pRoutesIter->GetNextTuple() ) != 0 )
{
// Create tuple for internal table and copy all attributes from input
Tuple* pNewRoute = new Tuple ( nl->Second ( xNumType ) );
for ( int i = 0; i < pCurrentRoute->GetNoAttributes(); i++ )
{
pNewRoute->CopyAttribute ( i, pCurrentRoute, i );
}
// Fill other fields of the table
pNewRoute->PutAttribute(ROUTE_STARTPOS_ID,new CcInt(true,routeCounter));
// Append new route
pIntRoutes->AppendTuple ( pNewRoute );
//clean up
pCurrentRoute->DeleteIfAllowed();
pNewRoute->DeleteIfAllowed();
// increment routeCounter for next route
routeCounter++;
}
delete pRoutesIter;
ostringstream xRoutesPtrStream;
xRoutesPtrStream << ( long ) pIntRoutes;
string strQuery = "(consume (sort (feed (" + routesInternalTypeInfo +
" (ptr " + xRoutesPtrStream.str() + ")))))";
Word xResult;
int QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
assert ( QueryExecuted );
m_pRoutes = ( Relation * ) xResult.addr;
delete pIntRoutes;
// Create B-Tree for the routes
ostringstream xThisRoutesPtrStream;
xThisRoutesPtrStream << ( long ) m_pRoutes;
strQuery = "(createbtree (" + routesInternalTypeInfo +
" (ptr " + xThisRoutesPtrStream.str() + "))" + " Id)";
QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
assert ( QueryExecuted ); // no query with side effects, please!
m_pBTreeRoutes = ( BTree* ) xResult.addr;
// Create B-Tree for the routes by startPos_id
ostringstream xThisRoutesPtrStream2;
xThisRoutesPtrStream2 << ( long ) m_pRoutes;
strQuery = "(createbtree (" + routesInternalTypeInfo +
" (ptr " + xThisRoutesPtrStream2.str() + "))" + " Startposid)";
QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
assert ( QueryExecuted ); // no query with side effects, please!
m_pBTreeRoutesByStartposId = ( BTree* ) xResult.addr;
//Create R-Tree for the routes
ostringstream xNetRoutes;
xNetRoutes << ( long ) m_pRoutes;
strQuery = "(bulkloadrtree(sortby(addid(feed (" + routesInternalTypeInfo +
" (ptr " + xThisRoutesPtrStream.str() + "))))((Curve asc))) Curve)";
QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
assert ( QueryExecuted );
m_pRTreeRoutes = ( R_Tree<2,TupleId>* ) xResult.addr;
}
/*
Method ~FillJunctions~
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 );
CcReal* pMeas = ( CcReal* ) pNewJunction->GetAttribute (
JUNCTION_ROUTE1_MEAS );
Point* pPoint = new Point ( false );
pLine->AtPosition ( pMeas->GetRealval(), true, *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 ) );
pNewJunction->PutAttribute ( JUNCTION_SECTION_ADOWN_RC,
new TupleIdentifier ( false ) );
pNewJunction->PutAttribute ( JUNCTION_SECTION_BUP_RC,
new TupleIdentifier ( false ) );
pNewJunction->PutAttribute ( JUNCTION_SECTION_BDOWN_RC,
new TupleIdentifier ( false ) );
/////////////////////////////////////////////////////////////////////
//
// Append new junction
//
pIntJunctions->AppendTuple ( pNewJunction );
pCurrentJunction->DeleteIfAllowed();
pNewJunction->DeleteIfAllowed();
}
delete pJunctionsIter;
/////////////////////////////////////////////////////////////////////
//
// Sort the table which is now containing all junctions
//
ostringstream xJunctionsStream;
xJunctionsStream << ( long ) pIntJunctions;
string strQuery = "(consume (sortby (feed (" + junctionsInternalTypeInfo +
" (ptr " + xJunctionsStream.str() +
"))) ((R1id asc)(Meas1 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
//
ostringstream xThisJunctionsPtrStream;
xThisJunctionsPtrStream << ( long ) m_pJunctions;
strQuery = "(createbtree (" + junctionsInternalTypeInfo +
" (ptr " + xThisJunctionsPtrStream.str() + "))" + " R1id)";
QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
assert ( QueryExecuted ); // no query with side effects, please!
m_pBTreeJunctionsByRoute1 = ( BTree* ) xResult.addr;
ostringstream xThisJunctionsPtrStream2;
xThisJunctionsPtrStream2 << ( long ) m_pJunctions;
strQuery = "(createbtree (" + junctionsInternalTypeInfo +
" (ptr " + xThisJunctionsPtrStream2.str() + "))" + " R2id)";
QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
assert ( QueryExecuted ); // no query with side effects, please!
m_pBTreeJunctionsByRoute2 = ( BTree* ) xResult.addr;
}
/*
Method ~FillSections~
Fill section relation of network
*/
void Network::FillSections()
{
// The method will iterate over routes by StartposIndex
BTreeIterator* pRoutesIt = m_pBTreeRoutesByStartposId->SelectAll();
// 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;
TupleId iSectionTid = 0;
while ( pRoutesIt->Next() )
{
pRoute = m_pRoutes->GetTuple(pRoutesIt->GetId(),false);
//DEBUG cout << "Rid "
// <<((CcInt*)pRoute->GetAttribute(ROUTE_ID))->GetIntval()<<endl;
// Current position on route - starting at the beginning of the route
double dCurrentPosOnRoute = 0;
SimpleLine* pRouteCurve = ( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE
);
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
//
vector<JunctionSortEntry> xJunctions;
GetJunctionsOnRoute ( xRouteId,
xJunctions );
/////////////////////////////////////////////////////////////////////
//
// Now that we found all relevant junctions we can iterate over them.
//
JunctionSortEntry xCurrentEntry;
xCurrentEntry.m_pJunction = 0;
xCurrentEntry.m_bFirstRoute = false;
for ( size_t i = 0; i < xJunctions.size(); i++ )
{
// Get next junction
xCurrentEntry = xJunctions[i];
// Find values for the new section
double dStartPos = dCurrentPosOnRoute;
double dEndPos = xCurrentEntry.GetRouteMeas();
// If the first junction is at the very start of the route, no
// section will be added
if ( xCurrentEntry.GetRouteMeas() == 0 )
{
vector<int> xIndices;
vector<Attribute*> xAttrs;
if ( xCurrentEntry.m_bFirstRoute )
{
xIndices.push_back ( JUNCTION_SECTION_ADOWN_RC );
xAttrs.push_back ( new TupleIdentifier ( true, 0 ) );
}
else
{
xIndices.push_back ( JUNCTION_SECTION_BDOWN_RC );
xAttrs.push_back ( new TupleIdentifier ( true, 0 ) );
}
m_pJunctions->UpdateTuple ( xCurrentEntry.m_pJunction,
xIndices,
xAttrs );
continue;
}
/////////////////////////////////////////////////////////////////////
//
// Create a new section
//
// Section will only be created if the length is > 0. Otherwise the
// one before remains valid.
if ( dEndPos - dStartPos > 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 );
// Find out, if the orientation of the subline differs from the position
// of the line. If so, the direction has to be changed.
bool bLineStartsSmaller;
Point pStartPoint ( false );
pRouteCurve->AtPosition ( dStartPos, bStartSmaller, pStartPoint );
Point pEndPoint ( false );
pRouteCurve->AtPosition ( dEndPos, bStartSmaller, pEndPoint );
if ( pStartPoint.GetX() < pEndPoint.GetX() ||
(
pStartPoint.GetX() == pEndPoint.GetX() &&
pStartPoint.GetY() < pEndPoint.GetY()
)
)
{
// Normal orientation
bLineStartsSmaller = true;
}
else
{
// Opposite orientation
bLineStartsSmaller = false;
}
// 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, bLineStartsSmaller ) );
pNewSection->PutAttribute ( SECTION_SID,
new CcInt ( true, m_pSections->GetNoTuples()
+1 ) );
//new Attributes inserted
pNewSection->PutAttribute (SECTION_PNO_UP, new CcInt(true,0));
pNewSection->PutAttribute (SECTION_PNO_DOWN, new CcInt(true,0));
pNewSection->PutAttribute (SECTION_SLOT_UP, new CcInt(true,0));
pNewSection->PutAttribute (SECTION_SLOT_DOWN, new CcInt(true,0));
pNewSection->PutAttribute (SECTION_COST, new CcReal(true,1.0));
pNewSection->PutAttribute (SECTION_DURATION, new CcReal(true,1.0));
m_pSections->AppendTuple ( pNewSection );
iSectionTid++;
pNewSection->DeleteIfAllowed();
// Update position for next loop
dCurrentPosOnRoute = dEndPos;
}
/////////////////////////////////////////////////////////////////////
//
// Store ID of new section in junction behind that section.
//
vector<int> xIndices;
vector<Attribute*> xAttrs;
if ( xCurrentEntry.m_bFirstRoute )
{
xIndices.push_back ( JUNCTION_SECTION_ADOWN_RC );
xAttrs.push_back ( new TupleIdentifier ( true, iSectionTid ) );
}
else
{
xIndices.push_back ( JUNCTION_SECTION_BDOWN_RC );
xAttrs.push_back ( new TupleIdentifier ( true, iSectionTid ) );
}
m_pJunctions->UpdateTuple ( xCurrentEntry.m_pJunction,
xIndices,
xAttrs );
if ( pRouteCurve->Length() - xCurrentEntry.GetRouteMeas() < 0.01 )
{
vector<int> xIndices;
vector<Attribute*> xAttrs;
if ( xCurrentEntry.m_bFirstRoute )
{
xIndices.push_back ( JUNCTION_SECTION_AUP_RC );
xAttrs.push_back ( new TupleIdentifier ( true, 0 ) );
}
else
{
xIndices.push_back ( JUNCTION_SECTION_BUP_RC );
xAttrs.push_back ( new TupleIdentifier ( true, 0 ) );
}
m_pJunctions->UpdateTuple ( xCurrentEntry.m_pJunction,
xIndices,
xAttrs );
}
} // End junctions-loop
/////////////////////////////////////////////////////////////////////
//
// The last section of the route is still missing, if the last
// junction is not at the end of the route.
//
if ( pRouteCurve->Length() - dCurrentPosOnRoute > 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 );
// Find out, if the orientation of the subline differs from the position
// of the sline. If so, the direction has to be changed.
bool bLineStartsSmaller;
Point pStartPoint ( false );
pRouteCurve->AtPosition ( dStartPos, bStartSmaller, pStartPoint );
Point pEndPoint ( false );
pRouteCurve->AtPosition ( dEndPos, bStartSmaller, pEndPoint );
if ( pStartPoint.GetX() < pEndPoint.GetX() ||
(
pStartPoint.GetX() == pEndPoint.GetX() &&
pStartPoint.GetY() < pEndPoint.GetY()
)
)
{
// Normal orientation
bLineStartsSmaller = true;
}
else
{
// Opposite orientation
bLineStartsSmaller = false;
}
// 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, bLineStartsSmaller ) );
pNewSection->PutAttribute ( SECTION_SID,
new CcInt ( true, m_pSections->GetNoTuples()
+1 ) );
//new Attributes inserted
pNewSection->PutAttribute (SECTION_PNO_UP, new CcInt(true,0));
pNewSection->PutAttribute (SECTION_PNO_DOWN, new CcInt(true,0));
pNewSection->PutAttribute (SECTION_SLOT_UP, new CcInt(true,0));
pNewSection->PutAttribute (SECTION_SLOT_DOWN, new CcInt(true,0));
pNewSection->PutAttribute (SECTION_COST, new CcReal(true,1.0));
pNewSection->PutAttribute (SECTION_DURATION, new CcReal(true,1.0));
m_pSections->AppendTuple ( pNewSection );
iSectionTid++;
pNewSection->DeleteIfAllowed();
// Store ID of new section in Junction
if ( xCurrentEntry.m_pJunction != 0 )
{
vector<int> xIndicesLast;
vector<Attribute*> xAttrsLast;
if ( xCurrentEntry.m_bFirstRoute )
{
xIndicesLast.push_back ( JUNCTION_SECTION_AUP_RC );
xAttrsLast.push_back ( new TupleIdentifier ( true,
iSectionTid ) );
}
else
{
xIndicesLast.push_back ( JUNCTION_SECTION_BUP_RC );
xAttrsLast.push_back ( new TupleIdentifier ( true,
iSectionTid ) );
}
m_pJunctions->UpdateTuple ( xCurrentEntry.m_pJunction,
xIndicesLast,
xAttrsLast );
}
} // end if
////////////////////////////////////////////////////////////////////
//
// Fill Up-Pointers of all sections but the last
//
vector<JunctionSortEntry> yJunctions;
GetJunctionsOnRoute ( xRouteId,
yJunctions );
if ( yJunctions.size() > 2 )
{
for ( int i = yJunctions.size()-2; i >= 0; i-- )
{
// Get next junction
JunctionSortEntry xEntry = yJunctions[i];
JunctionSortEntry xEntryBehind = yJunctions[i + 1];
vector<int> xIndices;
if ( xEntry.m_bFirstRoute )
{
xIndices.push_back ( JUNCTION_SECTION_AUP_RC );
}
else
{
xIndices.push_back ( JUNCTION_SECTION_BUP_RC );
}
vector<Attribute*> xAttrs;
if ( xEntryBehind.GetRouteMeas() - xEntry.GetRouteMeas() < 0.01 )
{
// Two junctions at the same place. In this case they do have
// the same up-pointers
if ( xEntryBehind.m_bFirstRoute )
{
TupleId iTid = xEntryBehind.GetUpSectionId();
xAttrs.push_back ( new TupleIdentifier ( true, iTid ) );
}
else
{
TupleId iTid = xEntryBehind.GetUpSectionId();
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.
if ( xEntryBehind.m_bFirstRoute )
{
TupleId iTid = xEntryBehind.GetDownSectionId();
xAttrs.push_back ( new TupleIdentifier ( true, iTid ) );
}
else
{
TupleId iTid = xEntryBehind.GetDownSectionId();
xAttrs.push_back ( new TupleIdentifier ( true, iTid ) );
}
}
m_pJunctions->UpdateTuple ( xEntry.m_pJunction,
xIndices,
xAttrs );
}
}
else
{
if ( yJunctions.size() == 2 )
{
JunctionSortEntry xEntry = yJunctions[0];
JunctionSortEntry xEntryBehind = yJunctions[1];
vector<int> xIndices;
if ( xEntry.m_bFirstRoute )
{
xIndices.push_back ( JUNCTION_SECTION_AUP_RC );
}
else
{
xIndices.push_back ( JUNCTION_SECTION_BUP_RC );
}
vector<Attribute*> xAttrs;
if ( fabs ( xEntry.GetRouteMeas() - xEntryBehind.GetRouteMeas() ) < 0.01
)
{
if ( xEntryBehind.m_bFirstRoute )
{
TupleId iTid = xEntryBehind.GetUpSectionId();
xAttrs.push_back ( new TupleIdentifier ( true, iTid ) );
}
else
{
TupleId iTid = xEntryBehind.GetUpSectionId();
xAttrs.push_back ( new TupleIdentifier ( true, iTid ) );
}
m_pJunctions->UpdateTuple ( xEntry.m_pJunction,
xIndices,
xAttrs );
}
else
{
if ( xEntryBehind.m_bFirstRoute )
{
TupleId iTid = xEntryBehind.GetDownSectionId();
xAttrs.push_back ( new TupleIdentifier ( true, iTid ) );
}
else
{
TupleId iTid = xEntryBehind.GetDownSectionId();
xAttrs.push_back ( new TupleIdentifier ( true, iTid ) );
}
m_pJunctions->UpdateTuple ( xEntry.m_pJunction,
xIndices,
xAttrs );
}
}
}
pRoute->DeleteIfAllowed();
// delete Tuples from xJunctions
for ( unsigned int i=0;i<xJunctions.size();i++ )
{
if ( xJunctions[i].m_pJunction )
{
xJunctions[i].m_pJunction->DeleteIfAllowed();
}
}
xJunctions.clear();
// delete Tuples from yJunctions
for ( unsigned int i=0;i<yJunctions.size();i++ )
{
if ( yJunctions[i].m_pJunction )
{
yJunctions[i].m_pJunction->DeleteIfAllowed();
}
}
yJunctions.clear();
} // End while Routes
delete pRoutesIt;
// Create B-Tree for the sections by Routes
Word xResult;
ostringstream xThisSectionsPtrStream;
xThisSectionsPtrStream << ( long ) m_pSections;
string strQuery = "(createbtree (" + sectionsInternalTypeInfo +
" (ptr " + xThisSectionsPtrStream.str() + "))" + " Rid)";
int QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
assert ( QueryExecuted ); // no query with side effects, please!
m_pBTreeSectionsByRoute = ( BTree* ) xResult.addr;
//Create B-Tree for the sections
Word xResultNewBtree;
ostringstream xStream2;
xStream2 << (long) m_pSections;
string query = "(createbtree (" + sectionsInternalTypeInfo +
" (ptr " + xStream2.str() + "))" + " Sid)";
int QueryEx = QueryProcessor::ExecuteQuery ( query, xResultNewBtree );
assert ( QueryEx ); // no query with side effects, please!
m_pBTreeSections = ( BTree* ) xResultNewBtree.addr;
}
/*
Method ~FillAdjacencyLists~
Fill adjacency list of network
*/
void Network::FillAdjacencyLists()
{
////////////////////////////////////////////////////////////////////
//In a first step all pairs of adjacent sections will be collected
GenericRelationIterator* pJunctionsIt = m_pJunctions->MakeScan();
Tuple* pCurrentJunction;
vector<DirectedSectionPair> xList;
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
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 list.
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);
pCurrentJunction->DeleteIfAllowed();
}
delete pJunctionsIt;
////////////////////////////////////////////////////////////////////
// Now - as the second step the adjacency lists are filled.
// Sort the list by the first directed section
sort ( xList.begin(), xList.end() );
//m_pSections contains a sorted List of all sections
//xList contains all neightbours of one section, if a section has no
//neighbours, there is no Entry in xList for this section
//search all neighbours of a section
DirectedSectionPair xLastPair; //stored the last Entry
TupleId actTid = 1; //actual TupleId of the section to be processed
int counterN = 0; //counts the neighbours of one section
bool flag = true; //toggelt after a pageEntry for section without neighbours
DirectedSection actDS = DirectedSection (actTid, flag);
DirectedSection lastDS = DirectedSection(m_pSections->GetNoTuples(),false);
PageRecord actPage = PageRecord(0);
int actPageNum = 1;
int actSlotNum = 1;
m_xAdjacencyList.clean();
//*****************************************************************
// First step to fill the adjacencylist is to identify the number of
// neighbours to calculate the necessery space for a section.
for ( size_t i = 0; i < xList.size(); i++ ){
// Get next entry
DirectedSectionPair xPair = xList[i];
//Special treatment for the first Entry
if(i==0){
//set last Element
xLastPair = xPair;
//collect all Sections without neighbours,
//there are listed befor the first Entry
while(xPair.m_iFirstSectionTid != actDS.GetSectionTid()
|| xPair.m_bFirstUpDown != actDS.GetUpDownFlag()){
// if there is a section without neighbours put it in pageRecord
if(xPair.m_iFirstSectionTid != actDS.GetSectionTid()
|| xPair.m_bFirstUpDown != actDS.GetUpDownFlag()){
//get sid, meas1, meas2 and rid
Tuple *pSect =
m_pSections->GetTuple (actDS.GetSectionTid(),false );
double actMeas1 =
((CcReal*)pSect->GetAttribute(SECTION_MEAS1))->GetRealval();
double actMeas2 =
((CcReal*)pSect->GetAttribute(SECTION_MEAS2))->GetRealval();
int actRid =
(( CcInt* )pSect->GetAttribute(SECTION_RID))->GetIntval();
double actCost =
(( CcReal* )pSect->GetAttribute(SECTION_COST))->GetRealval();
double actDuration =
((CcReal*)pSect->GetAttribute(SECTION_DURATION))->GetRealval();
int actSid =
((CcInt* )pSect->GetAttribute(SECTION_SID))->GetIntval();
// stored Section-Information in page
bool success = actPage.SetSectionContent(
actDS.GetSectionTid(),actSid, actDS.GetUpDownFlag(),
actMeas1,actMeas2,actRid,actCost, actDuration, 0,
actSlotNum);
if(!success){
// page was full, store the pagerecord in adjacencylist
m_xAdjacencyList.Append(actPage);
// reset actSlotNum to 1 and increment actPageNum
actSlotNum = 1;
actPageNum++;
//create a new Page and stored section information there
actPage = PageRecord(0);
actPage.SetSectionContent(
actDS.GetSectionTid(),actSid, actDS.GetUpDownFlag(),
actMeas1,actMeas2, actRid, actCost, actDuration , 0,
actSlotNum);
}
//stored PageNum and SlotNum in Section
vector<int> xIndices;
vector<Attribute*> xAttrs;
if(actDS.GetUpDownFlag()){
xIndices.push_back (SECTION_PNO_UP);
xIndices.push_back (SECTION_SLOT_UP);
}else{
xIndices.push_back (SECTION_PNO_DOWN);
xIndices.push_back (SECTION_SLOT_DOWN);
}
xAttrs.push_back ( new CcInt(true,actPageNum) );
xAttrs.push_back ( new CcInt(true,actSlotNum) );
m_pSections->UpdateTuple(pSect, xIndices, xAttrs);
pSect->DeleteIfAllowed();
//increment actSlotNum
actSlotNum++;
}
//set next actDirectedSection to be processed
if(flag){
flag = false;
} else {
flag= true;
actTid++;
}
actDS = DirectedSection(actTid,flag);
}
}
// 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){
counterN++; //last entry, the counter must increment
}
//all neighbours of a section are found,
//so put the section on the pageRecord
//get sid, meas1, meas2 and rid
Tuple *pSect =
m_pSections->GetTuple (xLastPair.m_iFirstSectionTid,false );
double actMeas1 =
((CcReal*) pSect->GetAttribute (SECTION_MEAS1))->GetRealval();;
double actMeas2 =
((CcReal*) pSect->GetAttribute (SECTION_MEAS2))->GetRealval();
int actRid =
(( CcInt* )pSect->GetAttribute(SECTION_RID))->GetIntval();
double actCost =
(( CcReal* )pSect->GetAttribute(SECTION_COST))->GetRealval();
double actDuration =
(( CcReal* )pSect->GetAttribute(SECTION_DURATION))->GetRealval();
int actSid =
((CcInt*)pSect->GetAttribute(SECTION_SID))->GetIntval();
// stored Section-Information in page
bool success = actPage.SetSectionContent(
xLastPair.m_iFirstSectionTid,actSid, xLastPair.m_bFirstUpDown,
actMeas1,actMeas2,actRid,actCost, actDuration, counterN,
actSlotNum);
if(!success){
// page was full, store the pagerecord in adjacencylist
m_xAdjacencyList.Append(actPage);
// reset actSlotNum to 1 and increment actPageNum
actSlotNum = 1;
actPageNum++;
//create a new Page and stored the section information there
actPage = PageRecord(0);
actPage.SetSectionContent(
xLastPair.m_iFirstSectionTid,actSid,
xLastPair.m_bFirstUpDown,actMeas1, actMeas2, actRid,
actCost, actDuration , counterN, actSlotNum);
}
//stored PageNum and SlotNum in Section
vector<int> xIndices;
vector<Attribute*> xAttrs;
if(xLastPair.m_bFirstUpDown){
xIndices.push_back (SECTION_PNO_UP);
xIndices.push_back (SECTION_SLOT_UP);
}else{
xIndices.push_back (SECTION_PNO_DOWN);
xIndices.push_back (SECTION_SLOT_DOWN);
}
xAttrs.push_back ( new CcInt(true,actPageNum) );
xAttrs.push_back ( new CcInt(true,actSlotNum) );
m_pSections->UpdateTuple(pSect, xIndices, xAttrs);
pSect->DeleteIfAllowed();
//increment actSlotNum
actSlotNum++;
//check, if sections are between the last and the actual Entry
//exist, which have no neighbours
while(xPair.m_iFirstSectionTid != actDS.GetSectionTid()
|| xPair.m_bFirstUpDown != actDS.GetUpDownFlag()){
//set next actDirectedSection to be processed
if(flag){
flag = false;
} else {
flag= true;
actTid++;
}
actDS = DirectedSection(actTid,flag);
//if there is a section without neighbours put it in pageRecord
if(xPair.m_iFirstSectionTid != actDS.GetSectionTid()
|| xPair.m_bFirstUpDown != actDS.GetUpDownFlag()){
//get sid, meas1, meas2 and rid
Tuple *pSect =
m_pSections->GetTuple (actDS.GetSectionTid(),false );
double actMeas1 =
((CcReal*)pSect->GetAttribute(SECTION_MEAS1))->GetRealval();
double actMeas2 =
((CcReal*)pSect->GetAttribute(SECTION_MEAS2))->GetRealval();
int actRid =
(( CcInt* )pSect->GetAttribute(SECTION_RID))->GetIntval();
double actCost =
((CcReal* )pSect->GetAttribute(SECTION_COST))->GetRealval();
double actDuration =
((CcReal*)pSect->GetAttribute(SECTION_DURATION))->GetRealval();
int actSid =
((CcInt*)pSect->GetAttribute(SECTION_SID))->GetIntval();
// stored Section-Information in page
bool success = actPage.SetSectionContent(
actDS.GetSectionTid(),actSid, actDS.GetUpDownFlag(),
actMeas1, actMeas2,actRid, actCost,actDuration , 0,
actSlotNum);
if(!success){
// page was full, store the pagerecord in adjacencylist
m_xAdjacencyList.Append(actPage);
// reset actSlotNum to 1 and increment actPageNum
actSlotNum = 1;
actPageNum++;
//create a new Page and stored section information there
actPage = PageRecord(0);
actPage.SetSectionContent(
actDS.GetSectionTid(),actSid, actDS.GetUpDownFlag(),
actMeas1, actMeas2,actRid, actCost, actDuration , 0,
actSlotNum);
}
//stored PageNum and SlotNum in Section
vector<int> xIndices;
vector<Attribute*> xAttrs;
if(actDS.GetUpDownFlag()){
xIndices.push_back (SECTION_PNO_UP);
xIndices.push_back (SECTION_SLOT_UP);
}else{
xIndices.push_back (SECTION_PNO_DOWN);
xIndices.push_back (SECTION_SLOT_DOWN);
}
xAttrs.push_back ( new CcInt(true,actPageNum) );
xAttrs.push_back ( new CcInt(true,actSlotNum) );
m_pSections->UpdateTuple(pSect, xIndices, xAttrs);
pSect->DeleteIfAllowed();
//increment actSlotNum
actSlotNum++;
}
}
// reset the counter of neighbours after the Entry in the pageRecord
counterN =0;
}
// Check if entry allready exists in list. As the list is sorted it
// has to be the entry before.
if ( i == 0 ||
xLastPair.m_iFirstSectionTid != xPair.m_iFirstSectionTid ||
xLastPair.m_bFirstUpDown != xPair.m_bFirstUpDown ||
xLastPair.m_iSecondSectionTid != xPair.m_iSecondSectionTid ||
xLastPair.m_bSecondUpDown != xPair.m_bSecondUpDown )
{
counterN++; // the counter of neighbours must increment
}
//check, if sections after the last Entry exist, that have no neighbours
if (i == xList.size() -1){
while(lastDS.GetSectionTid() != actDS.GetSectionTid()
|| lastDS.GetUpDownFlag() != actDS.GetUpDownFlag()){
//set next actDirectedSection to be processed
if(flag){
flag = false;
} else {
flag= true;
actTid++;
}
actDS = DirectedSection(actTid,flag);
// if there is a section without neighbours put it in pageRecord
if(lastDS.GetSectionTid() != actDS.GetSectionTid()
|| lastDS.GetUpDownFlag() != actDS.GetUpDownFlag()){
//get sid, meas1,meas2and rid
Tuple *pSect =
m_pSections->GetTuple (actDS.GetSectionTid(),false );
double actMeas1 =
((CcReal*)pSect->GetAttribute(SECTION_MEAS1))->GetRealval();
double actMeas2 =
((CcReal*)pSect->GetAttribute(SECTION_MEAS2))->GetRealval();
int actRid =
(( CcInt* )pSect->GetAttribute(SECTION_RID))->GetIntval();
double actCost =
(( CcReal*)pSect->GetAttribute(SECTION_COST))->GetRealval();
double actDuration =
((CcReal*)pSect->GetAttribute(SECTION_DURATION))->GetRealval();
int actSid =
((CcInt*)pSect->GetAttribute(SECTION_SID))->GetIntval();
// stored Section-Information in page
bool success = actPage.SetSectionContent(
actDS.GetSectionTid(),actSid, actDS.GetUpDownFlag(),
actMeas1, actMeas2, actRid, actCost, actDuration , 0,
actSlotNum);
if(!success){
// page was full, store the pagerecord in adjacencylist
m_xAdjacencyList.Append(actPage);
// reset actSlotNum to 1 and increment actPageNum
actSlotNum = 1;
actPageNum++;
//create a new Page and stored section information there
actPage = PageRecord(0);
actPage.SetSectionContent(
actDS.GetSectionTid(),actSid, actDS.GetUpDownFlag(),
actMeas1, actMeas2, actRid, actCost, actDuration ,0,
actSlotNum);
}
//stored PageNum and SlotNum in Section
vector<int> xIndices;
vector<Attribute*> xAttrs;
if(actDS.GetUpDownFlag()){
xIndices.push_back (SECTION_PNO_UP);
xIndices.push_back (SECTION_SLOT_UP);
}else{
xIndices.push_back (SECTION_PNO_DOWN);
xIndices.push_back (SECTION_SLOT_DOWN);
}
xAttrs.push_back ( new CcInt(true,actPageNum) );
xAttrs.push_back ( new CcInt(true,actSlotNum) );
m_pSections->UpdateTuple(pSect, xIndices, xAttrs);
pSect->DeleteIfAllowed();
//increment actSlotNum
actSlotNum++;
}
}
}
// set last Entry
xLastPair = xPair;
}
if(xList.size()!= 0){
// store last Page in the AdjacencyList
m_xAdjacencyList.Append(PageRecord(actPage));
}
m_xAdjacencyList.TrimToSize();
//
//*****************************************************************
// Second step to fill the adjacencylist is to set all pagenumbers and
// Slotindex for the neighbours of a section. Because that information
// is collected in the first Step.
actPageNum =0; // reset old used variable for actual PageNumber
actSlotNum =0; // reset old used variable for actual SlotNumber
actPage = PageRecord(0); // reset old used variable for actual Page
DirectedSectionPair actPair;// actual read sectionPair from xList
DirectedSectionPair lastPair;
int nCounter=0;// counts the proceeded neighbours start even by 0
int actNPage,actNSlot; // actual PageNR and SlotNR of a Neighboursection
TupleId nSTid; // sectionid and UpDownFlag of a neighbour
bool nUpD;
size_t actIndex = 0; // actual Index of the xList
while(actIndex < xList.size()){
//get actual element
actPair = xList[actIndex];
// get actual Tuple from section relation
Tuple *pSect = m_pSections->GetTuple (actPair.m_iFirstSectionTid,false);
// get page and slotnumber of this DirectionPair
if (actPair.m_bFirstUpDown){
actPageNum =((CcInt*)pSect->GetAttribute(SECTION_PNO_UP))->GetIntval();
actSlotNum =((CcInt*)pSect->GetAttribute(SECTION_SLOT_UP))->GetIntval();
}else{
actPageNum=((CcInt*)pSect->GetAttribute(SECTION_PNO_DOWN))->GetIntval();
actSlotNum=((CcInt*)pSect->GetAttribute(SECTION_SLOT_DOWN))->GetIntval();
}
// get page, where the actual section is stored
m_xAdjacencyList.Get(actPageNum-1, actPage);
nCounter =0;
// at first element strored this as last element
if(actIndex == 0){
lastPair = actPair;
}
while(actIndex==0 ||
(actPair.m_iFirstSectionTid== lastPair.m_iFirstSectionTid
&& actPair.m_bFirstUpDown==lastPair.m_bFirstUpDown)){
if(actIndex !=0 &&
!(lastPair.m_iSecondSectionTid == xList[actIndex].m_iSecondSectionTid
&& lastPair.m_bSecondUpDown ==xList[actIndex].m_bSecondUpDown)){
// read nSid and nUpD form xList
nSTid = lastPair.m_iSecondSectionTid;
nUpD = lastPair.m_bSecondUpDown;
// for each Entry stored Information
Tuple *pNSect = m_pSections->GetTuple (nSTid,false );
if (nUpD){
actNPage =
(( CcInt* )pNSect->GetAttribute(SECTION_PNO_UP))->GetIntval();
actNSlot =
(( CcInt* )pNSect->GetAttribute(SECTION_SLOT_UP))->GetIntval();
}else{
actNPage =
(( CcInt* )pNSect->GetAttribute(SECTION_PNO_DOWN))->GetIntval();
actNSlot =
(( CcInt* )pNSect->GetAttribute(SECTION_SLOT_DOWN))->GetIntval();
}
pNSect->DeleteIfAllowed();
// Update the Information on the page
actPage.SetSectionNeighbour(actSlotNum,nCounter,actNPage,actNSlot);
nCounter++;
}
lastPair = xList[actIndex];
actIndex++;
}
// Delete section Tupel if allowed
pSect->DeleteIfAllowed();
//page stored back in the adjacencyList
// get page, where the actual section is stored
m_xAdjacencyList.Put(actPageNum-1, actPage);
//Reset all used values
actPageNum=0;
actSlotNum=0;
actPage=PageRecord(0);
}
// test output
//of the content from xList, m_xAdjacencyList, m_xSubAdjacencyList
// and all neighbourSection which are issued from GetAdjacentSections()
/* cout << "Output of xList:" <<endl;
DirectedSectionPair actDSP;
for(size_t i=0; i< xList.size();i++){
cout << "[(" << xList[i].m_iFirstSectionTid << ","
<< xList[i].m_bFirstUpDown << ")"
<< "(" << xList[i].m_iSecondSectionTid << ","
<< xList[i].m_bSecondUpDown << ")]" <<endl;
}
//print all information which are stored in the PageRecord
PrintAdjacentSectionInfo();
cout << "output all neighbours with GetAdjacentSections:" << endl;
vector<DirectedSection> actVDS;
for (int i=1; i<= m_pSections->GetNoTuples();i++){
actVDS.clear();
cout << "Sec:(" << i <<",0): [";
GetAdjacentSections(i,false,actVDS);
for(size_t k=0; k<actVDS.size();k++){
cout <<"("<< actVDS[k].GetSectionTid() << ","
<< actVDS[k].GetUpDownFlag() <<")";
}
cout << "]" << endl;
actVDS.clear();
cout << "Sec:(" << i <<",1): [";
GetAdjacentSections(i,true,actVDS);
for(size_t k=0; k<actVDS.size();k++){
cout <<"("<< actVDS[k].GetSectionTid() << ","
<< actVDS[k].GetUpDownFlag() <<")";
}
cout << "]" << endl;
}
//statistic output of the numbers of neighbours
CountNeighbours(xList); */
}
/*
Method ~FillAdjacencyPair~
Build vector of directed section pairs.
*/
void Network::FillAdjacencyPair ( TupleId in_pFirstSection,
bool in_bFirstUp,
TupleId in_pSecondSection,
bool in_bSecondUp,
ConnectivityCode in_xCc,
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 ) );
}
}
/*
Method ~PrintAdjacentSectionInfo~
prints informations of ~sections~ which are stored in a ~PageRecord~.
first output: all ~sections~ with there sectionId and cost-value
second output: all ~routes~ iterated over the startposId
third output: all neighbours-information of the ~sections~
Sec (SectionTupelId,UpDownFlag):[(NeighborSectionTId, UpDownFlag, Meas1, Meas2,
RId, Cost, Time)(..)]
*/
bool Network::PrintAdjacentSectionInfo(){
cout << "output of all Sections: (Section_SId,Section_Cost)"<< endl;
for (int i =1; i<=m_pSections->GetNoTuples();i++){
Tuple *n = m_pSections->GetTuple(i,false);
cout <<"("<< ((CcInt*)n->GetAttribute(SECTION_SID))->GetIntval() << ","
<< ((CcReal*)n->GetAttribute(SECTION_COST))->GetRealval()<< ")"<<endl;
n->DeleteIfAllowed();
}
cout << "ROUTES over startposid: (Routes_Id, Routes_StartposId)" << endl;
BTreeIterator* pRoutesIt = m_pBTreeRoutesByStartposId->SelectAll();
Tuple* pRoute;
while ( pRoutesIt->Next() )
{
pRoute = m_pRoutes->GetTuple(pRoutesIt->GetId(),false);
cout <<"("<< ((CcInt*)pRoute->GetAttribute(ROUTE_ID))->GetIntval() << ","
<< ((CcInt*)pRoute->GetAttribute(ROUTE_STARTPOS_ID))->GetIntval()<< ")"
<<endl;
pRoute->DeleteIfAllowed();
}
delete pRoutesIt;
cout << "output all neighbours with GetAdjacentSectionsInfo" << endl;
cout << "Sec:(SectionTupelId,UpDownFlag):[(NeighborSectionTId,"
<< " UpDownFlag, Meas1, Meas2, RId, Cost, Time)(..)]" << endl;
vector<DirectedSectionInfo> actVDSI;
BTreeIterator* pSectionIt;
pSectionIt = m_pBTreeSections->SelectAll();
while ( pSectionIt->Next() )
{
actVDSI.clear();
TupleId sTid = pSectionIt->GetId();
cout << "Sec:(" << sTid <<",0): [";
GetAdjacentSectionsInfo(sTid,false,actVDSI);
for(size_t k=0; k<actVDSI.size();k++){
cout <<"("<< actVDSI[k].GetSectionTid()<< ","<< actVDSI[k].GetUpDownFlag()
<<","<< actVDSI[k].GetMeas1() << "," << actVDSI[k].GetMeas2() << ","
<< actVDSI[k].GetRid()<<","<< actVDSI[k].GetCost() <<","
<< actVDSI[k].GetDuration()<< ")";
}
cout << "]" << endl;
actVDSI.clear();
cout << "Sec:(" << sTid <<",1): [";
GetAdjacentSectionsInfo(sTid,true,actVDSI);
for(size_t k=0; k<actVDSI.size();k++){
cout <<"("<< actVDSI[k].GetSectionTid()<< ","<< actVDSI[k].GetUpDownFlag()
<<","<< actVDSI[k].GetMeas1() << "," << actVDSI[k].GetMeas2() << ","
<< actVDSI[k].GetRid()<<","<< actVDSI[k].GetCost() <<","
<< actVDSI[k].GetDuration() <<")";
}
cout << "]" << endl;
}
delete pSectionIt;
return true;
}
/*
Method ~CountNeighbours~
calculate the numbers of neighbours of all ~sections~. Only used for internal
debug informations.
*/
void Network::CountNeighbours(vector<DirectedSectionPair> in_xList){
cout << "count all neighbours of all sections:" << endl;
//Counter for neighbours, if more then nine, the counter a10 is increased
int a0=0,a1=0,a2=0,a3=0,a4=0,a5=0,a6=0,a7=0,a8=0,a9=0,a10=0;
int actCounter=0;
DirectedSectionPair xLastPair;
//determin the number of neighbours of the sections
actCounter=0;
//pass through all pairs
for (size_t i=0; i<in_xList.size(); i++){
//get next
DirectedSectionPair xPair = in_xList[i];
//at the first element,remember it as the last pair
if(i==0){
xLastPair = xPair;
actCounter++;
}
if ( i == in_xList.size() -1 ||
(i != 0 &&
( xLastPair.m_iFirstSectionTid != xPair.m_iFirstSectionTid ||
xLastPair.m_bFirstUpDown != xPair.m_bFirstUpDown
)
)
){
switch(actCounter){
case 1: a1++;break;
case 2: a2++;break;
case 3: a3++;break;
case 4: a4++;break;
case 5: a5++;break;
case 6: a6++;break;
case 7: a7++;break;
case 8: a8++;break;
case 9: a9++;break;
default: a10++;
}
actCounter = 0;
}
if ( i == 0 ||
xLastPair.m_iFirstSectionTid != xPair.m_iFirstSectionTid ||
xLastPair.m_bFirstUpDown != xPair.m_bFirstUpDown ||
xLastPair.m_iSecondSectionTid != xPair.m_iSecondSectionTid ||
xLastPair.m_bSecondUpDown != xPair.m_bSecondUpDown ){
actCounter++;
}
xLastPair = xPair;
}
//determine sections without neighbours
a0 = (m_pSections->GetNoTuples() *2) -(a1+a2+a3+a4+a5+a6+a7+a8+a9+a10);
// output of the results
cout << "sections without neighbours: " << a0 << endl;
cout << "sections with one neighbour: " << a1 << endl;
cout << "sections with two neighbours: " << a2 << endl;
cout << "sections with three neighbours: " << a3 << endl;
cout << "sections with four neighbours: " << a4<< endl;
cout << "sections with five neighbours: " << a5 << endl;
cout << "sections with six neighbours: " << a6 << endl;
cout << "sections with seven neighbours: " << a7 << endl;
cout << "sections with eight neighbours: " << a8 << endl;
cout << "sections with nine neighbours: " << a9 << endl;
cout << "sections with more than nine neighbours : " << a10 << endl;
}
/*
Method ~InShortestPath~
*/
bool Network::InShortestPath ( GPoint*start,GPoint *to, GLine *result )
{
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() &&
fabs ( ( ( CcReal* ) t->GetAttribute ( JUNCTION_ROUTE1_MEAS )
)->GetRealval()-
end->GetPosition() ) < 0.1 )
junctionpoint = true;
if ( ( ( CcInt* ) t->GetAttribute ( JUNCTION_ROUTE2_ID ) )->GetIntval() ==
end->GetRouteId() &&
fabs ( ( ( CcReal* ) t->GetAttribute ( JUNCTION_ROUTE2_MEAS )
)->GetRealval()-
end->GetPosition() ) < 0.1 )
junctionpoint = true;
}
vector<TupleId> secjunid;
if ( junctionpoint ) //it is a junction point
{
vector<DirectedSection> sectionlist;
if ( fabs ( end->GetPosition()-
( ( CcReal* ) endSection->GetAttribute ( SECTION_MEAS1 )
)->GetRealval() ) < 0.1 )
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 ) ;
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 );
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 );
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 );
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 );
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.
RIStack *riStack = new RIStack ( 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, riStack );
else
riStack->Push ( actRouteId, sectMeas2, sectMeas1, riStack );
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,
riStack );
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,
riStack );
end = true;
}
}
i++;
}
adjSectionList.clear();
}
}
}
// Cleanup and return result
riStack->StackToGLine ( result );
riStack->RemoveStack();
delete actPQEntry;
}
}
visitedSect->Remove();
prioQ->Destroy();
delete prioQ;
}
startSection->DeleteIfAllowed();
endSection->DeleteIfAllowed();
result->SetSorted ( false );
result->SetDefined ( true );
result->TrimToSize();
end->DeleteIfAllowed();
return true;
};
/*
Method ~FindSP~
*/
void Network::FindSP ( TupleId j1,TupleId j2,double& length,GLine* res )
{
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();
}
/*
Method ~FillDistanceStorage~
*/
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 ( fabs ( p1->GetX()-p2->GetX() ) < 0.1 &&
fabs ( p1->GetY()-p2->GetY() ) < 0.1 ) //different 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();
}
}
}
/*
Method ~UpdateSectionCost~
update the cost of a given ~section~
returns ~true~, if the update was successful, otherwise ~false~
*/
bool Network::UpdateSectionCost(int sectId,double newCost){
BTreeIterator* pSectIter;
CcInt* ciSectId = new CcInt(true,sectId);
pSectIter = m_pBTreeSections->ExactMatch (ciSectId);
delete ciSectId;
if(pSectIter->Next()){
//get act Tuple
Tuple *actSect = 0;
actSect = m_pSections->GetTuple(pSectIter->GetId(), false);
//save cost in the section relation
vector<int> xIndices;
vector<Attribute*> xAttrs;
xIndices.push_back ( SECTION_COST );
xAttrs.push_back ( new CcReal ( true, newCost ) );
m_pSections->UpdateTuple(actSect, xIndices, xAttrs);
//save cost in the PageRecord of the section
// read pages und Slots
int pageUp =
((CcInt* )actSect->GetAttribute(SECTION_PNO_UP))->GetIntval();
int slotUp =
((CcInt* )actSect->GetAttribute(SECTION_SLOT_UP))->GetIntval();
int pageDown =
((CcInt* )actSect->GetAttribute(SECTION_PNO_DOWN))->GetIntval();
int slotDown =
((CcInt* )actSect->GetAttribute(SECTION_SLOT_DOWN))->GetIntval();
//get the page and save cost for both entries
PageRecord actPage =PageRecord(0);
m_xAdjacencyList.Get(pageUp-1, actPage);
actPage.SetSectionCost(slotUp, newCost);
if(pageDown == pageUp){
actPage.SetSectionCost(slotDown, newCost);
m_xAdjacencyList.Put(pageUp-1, actPage);
}else{
m_xAdjacencyList.Put(pageUp-1, actPage);
m_xAdjacencyList.Get(pageDown-1, actPage);
actPage.SetSectionCost(slotDown, newCost);
m_xAdjacencyList.Put(pageDown-1, actPage);
}
//clean up
actSect->DeleteIfAllowed();
delete pSectIter;
return true;
}
else {
//errormessage
sendMessage ( "the section with the given SectId must exist." );
cout << "the section " <<sectId <<" doesn't exist." <<endl;
//clean up
delete pSectIter;
return false;
}
}
/*
Method ~UpdateMoreSectionCost~
update the cost of some ~sections~ which are in the given relation.
returns ~true~, if the update was successful, otherwise ~false~
*/
bool Network::UpdateMoreSectionCost(const Relation* in_pCosts){
//DEBUG PrintAdjacentSectionInfo();
// check input
if(in_pCosts->GetNoTuples() >0){
//for each tuple of the Relation
for(int i=1; i<=in_pCosts->GetNoTuples();i++){
//Get sid and cost
Tuple *actTuple = 0;
actTuple = in_pCosts->GetTuple(i, false);
int sid = ((CcInt*)actTuple->GetAttribute(0))->GetIntval();
double cost = ((CcReal*)actTuple->GetAttribute(1))->GetRealval();
//call the function UpdateSectionCost(sid,cost)
UpdateSectionCost(sid,cost);
// clean up
actTuple->DeleteIfAllowed();
}
//DEBUG PrintAdjacentSectionInfo();
return true;
}else{
sendMessage ( "the relation is empty." );
cout << "the relation is empty." <<endl;
return false;
}
}
/*
Method ~UpdateSectionDuration~
update the duration of a given ~section~
returns ~true~, if the update was successful, otherwise ~false~
*/
bool Network::UpdateSectionDuration(int sectId,double newDuration){
BTreeIterator* pSectIter;
CcInt* ciSectId = new CcInt(true,sectId);
pSectIter = m_pBTreeSections->ExactMatch (ciSectId);
delete ciSectId;
if(pSectIter->Next()){
//get act Tuple
Tuple *actSect = 0;
actSect = m_pSections->GetTuple(pSectIter->GetId(), false);
//save duration in the section relation
vector<int> xIndices;
vector<Attribute*> xAttrs;
xIndices.push_back ( SECTION_DURATION );
xAttrs.push_back ( new CcReal ( true, newDuration ) );
m_pSections->UpdateTuple(actSect, xIndices, xAttrs);
//save duration in the PageRecord of the section
// read pages und Slots
int pageUp =
((CcInt* )actSect->GetAttribute(SECTION_PNO_UP))->GetIntval();
int slotUp =
((CcInt* )actSect->GetAttribute(SECTION_SLOT_UP))->GetIntval();
int pageDown =
((CcInt* )actSect->GetAttribute(SECTION_PNO_DOWN))->GetIntval();
int slotDown =
((CcInt* )actSect->GetAttribute(SECTION_SLOT_DOWN))->GetIntval();
//get the page and save duration for both entries
PageRecord actPage;
m_xAdjacencyList.Get(pageUp-1, actPage);
actPage.SetSectionDuration(slotUp, newDuration);
if(pageDown == pageUp){
actPage.SetSectionDuration(slotDown, newDuration);
m_xAdjacencyList.Put(pageUp-1, actPage);
}else{
m_xAdjacencyList.Put(pageUp-1, actPage);
m_xAdjacencyList.Get(pageDown-1, actPage);
actPage.SetSectionDuration(slotDown, newDuration);
m_xAdjacencyList.Put(pageDown-1, actPage);
}
//clean up
actSect->DeleteIfAllowed();
delete pSectIter;
return true;
}
else {
//errormessage
sendMessage ( "the section with the given SectId must exist." );
cout << "the section " <<sectId <<" doesn't exist." <<endl;
//clean up
delete pSectIter;
return false;
}
}
/*
Method ~UpdateMoreSectionDuration~
update the cost of some ~sections~ which are in the given relation.
returns ~true~, if the update was successful, otherwise ~false~
*/
bool Network::UpdateMoreSectionDuration(const Relation* in_pDurations){
//DEBUG PrintAdjacentSectionInfo();
// check input
if(in_pDurations->GetNoTuples() >0){
//for each tuple of the Relation
for(int i=1; i<=in_pDurations->GetNoTuples();i++){
//Get sid and duration
Tuple *actTuple = 0;
actTuple = in_pDurations->GetTuple(i, false);
int sid = ((CcInt*)actTuple->GetAttribute(0))->GetIntval();
double duration =((CcReal*)actTuple->GetAttribute(1))->GetRealval();
//call the function UpdateSectionDuration(sid,duration)
UpdateSectionDuration(sid,duration);
// clean up
actTuple->DeleteIfAllowed();
}
//DEBUG PrintAdjacentSectionInfo();
return true;
}else{
sendMessage ( "the relation is empty." );
cout << "the relation is emplty." <<endl;
return false;
}
}
/*
Method ~chkStartEndA~
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;
}
};
/*
Method ~ShorterConnection~
*/
bool Network::ShorterConnection ( Tuple *route, double &start,
double &end, double &dpos, double &dpos2,
int &rid, int &ridt, Point p1, Point p2 )
{
if ( AlmostEqual ( p1.Distance ( p2 ), fabs ( end-start ) ) ) return false;
double difference;
GPoint *gp = new GPoint ( true, GetId(), route->GetTupleId(), end - 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 );
if ( ( chkPoint ( pCurve, p1, true, dpos, difference ) ) &&
( chkPoint ( pCurve, p2, true, dpos2, difference ) ) )
{
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 );
if ( ( chkPoint ( pCurve, p1, true, dpos, difference ) ) &&
( chkPoint ( pCurve, p2, true, dpos2, difference ) ) )
{
pAdjSect2.clear();
chkStartEndA ( dpos, dpos2 );
pRoute->DeleteIfAllowed();
if ( fabs ( dpos2-dpos ) < fabs ( end - start ) ) return true;
else return false;
}
pRoute->DeleteIfAllowed();
}
j++;
}
return false;
}
}
/*
Method ~ShorterConnection2~
*/
bool Network::ShorterConnection2 ( Tuple *route, double &start,
double &end, double &dpos, double &dpos2,
int &rid, int &ridt, Point p1, Point p2 )
{
if ( AlmostEqual ( p1.Distance ( p2 ), fabs ( end-start ) ) ) return false;
double difference = 0.0;
if ( start < end && end > 0.01 ) difference = end - 0.01;
else
if ( start < end && end <= 0.01 ) difference = 0.01;
else
if ( start > end ) difference = end + 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 );
if ( ( chkPoint ( pCurve, p1, true, dpos, difference ) ) &&
( chkPoint ( pCurve, p2, true, dpos2, difference ) ) )
{
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 );
if ( ( chkPoint ( pCurve, p1, true, dpos, difference ) ) &&
( chkPoint ( pCurve, p2, true, dpos2, difference ) ) )
{
pAdjSect2.clear();
pRoute->DeleteIfAllowed();
if ( fabs ( dpos2-dpos ) < fabs ( end - start ) ) return true;
else return false;
}
pRoute->DeleteIfAllowed();
}
j++;
}
return false;
}
}
/*
Method ~Find~
Searches the route interval between the two given point values.
*/
RouteInterval* Network::Find ( Point p1, Point p2 )
{
GPoint *gpp1 = GetNetworkPosOfPoint ( p1 );
GPoint *gpp2 = GetNetworkPosOfPoint ( p2 );
assert ( gpp1->IsDefined() && gpp2->IsDefined() );
int rid, ridt;
double start, end, dpos, dpos2, difference;
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 );
if ( chkPoint ( pCurve, p2, true, dpos, difference ) )
{
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 );
if ( chkPoint ( pCurve, p1, true, dpos, difference ) )
{
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 );
if ( ( chkPoint ( pCurve, p1, true, dpos, difference ) ) &&
( chkPoint ( pCurve, p2, true, dpos2, difference ) ) )
{
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 );
if ( ( chkPoint ( pCurve, p1, true, dpos, difference ) ) &&
( chkPoint ( pCurve, p2, true, dpos2, difference ) ) )
{
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;
}
/*
Method ~FindInterval~
Returns the route interval for the connection from p1 to p2
*/
RouteInterval* Network::FindInterval ( Point p1, Point p2 )
{
GPoint *gpp1 = GetNetworkPosOfPoint ( p1 );
GPoint *gpp2 = GetNetworkPosOfPoint ( p2 );
assert ( gpp1->IsDefined() && gpp2->IsDefined() );
int rid, ridt;
double start, end, dpos, dpos2, difference;
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 );
if ( chkPoint ( pCurve, p2, true, dpos, difference ) )
{
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 );
if ( chkPoint ( pCurve, p1, true, dpos, difference ) )
{
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 );
if ( ( chkPoint ( pCurve, p1, true, dpos, difference ) ) &&
( chkPoint ( pCurve, p2, true, dpos2, difference ) ) )
{
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 );
if ( ( chkPoint ( pCurve, p1, true, dpos, difference ) ) &&
( chkPoint ( pCurve, p2, true, dpos2, difference ) ) )
{
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;
}
/*
Get-Methodes of network parameters.
~GetId~, ~GetRoutes~, ~GetJunctions~, ~GetJunctionsOnRoute~, ~GetSection~,
~GetTupleIdSectionOnRoute~, ~GetTupleIdSectionOnRoute~, ~GetSectionOnRoute~,
~GetRoute~, ~GetSectionsOfRouteInterval~, ~GetSectionsOfRoutInterval~,
~GetPointOnRoute~, ~GetSectionsInternal~, ~GetSections~,
~GetAdjacentSectionsInfo~, ~GetAdjacentSections~, ~GetRouteCurve~, ~GetDual~,
~GetTupleIdSectionOnRouteJun~, ~GetNetworkPosOfPoint~,
~GetJunctionMeasForRoutes~, ~GetLineValueOfRouteInterval~
*/
int Network::GetId()
{
return m_iId;
}
Relation *Network::GetRoutes()
{
return m_pRoutes;
/* ostringstream strRoutesPtr;
strRoutesPtr << ( long ) m_pRoutes;
string querystring = "(consume (feed (" + routesTypeInfo +
" (ptr " + strRoutesPtr.str() + "))))";
Word resultWord;
int QueryExecuted = QueryProcessor::ExecuteQuery ( querystring, resultWord );
assert ( QueryExecuted ); // no ASSERT with side effects, please
return ( Relation * ) resultWord.addr;*/
}
Relation *Network::GetJunctions()
{
ostringstream strJunctionsPtr;
strJunctionsPtr << ( long ) m_pJunctions;
string querystring = "(consume (feed (" + junctionsInternalTypeInfo +
" (ptr " + strJunctionsPtr.str() + "))))";
Word resultWord;
int QueryExecuted = QueryProcessor::ExecuteQuery ( querystring, resultWord );
assert ( QueryExecuted ); // no ASSERT with side effects, please
return ( Relation * ) resultWord.addr;
}
void Network::GetJunctionsOnRoute ( CcInt* in_pRouteId,
vector<JunctionSortEntry> &inout_xJunctions
)
{
BTreeIterator* pJunctionsIt;
pJunctionsIt = m_pBTreeJunctionsByRoute1->ExactMatch ( in_pRouteId );
while ( pJunctionsIt->Next() )
{
// Get next junction
Tuple* pCurrentJunction = m_pJunctions->GetTuple ( pJunctionsIt->GetId(),
false );
inout_xJunctions.push_back ( JunctionSortEntry ( true, pCurrentJunction ) );
}
delete pJunctionsIt;
// Now we look up the second b-tree
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;
// The junctions will be sorted by their mesure on the relevant route.
sort ( inout_xJunctions.begin(),
inout_xJunctions.end() );
}
Tuple* Network::GetSection ( TupleId n )
{
return m_pSections->GetTuple ( n, false );
}
TupleId Network::GetTupleIdSectionOnRoute ( GPoint* in_xGPoint )
{
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 ( fabs ( in_xGPoint->GetPosition() - start ) <= 0.01 )
{
delete pSectionIter;
actSect->DeleteIfAllowed();
return result;
}
else
{
if ( fabs ( in_xGPoint->GetPosition() - end ) <= 0.01 )
{
Tuple *pRoute = GetRoute ( ( ( TupleIdentifier* )
actSect->GetAttribute ( SECTION_RRC )
)->GetTid() );
if ( fabs ( ( ( CcReal* )
pRoute->GetAttribute ( ROUTE_LENGTH ) )->GetRealval()
- end ) <= 0.01 )
{
pRoute->DeleteIfAllowed();
delete pSectionIter;
actSect->DeleteIfAllowed();
return result;
}
else
{
pRoute->DeleteIfAllowed();
}
}
}
}
actSect->DeleteIfAllowed();
}
}
delete pSectionIter;
return 0;
}
Tuple* Network::GetSectionOnRoute ( GPoint* in_xGPoint )
{
return GetSection ( GetTupleIdSectionOnRoute ( in_xGPoint ) );
/*
New implementation using sectionsBTree
CcInt *ciRouteId = new CcInt(true, in_xGPoint->GetRouteId());
BTreeIterator* pSectionIter =
m_pBTreeSectionsByRoute->ExactMatch(ciRouteId);
ciRouteId->DeleteIfAllowed();
Tuple *actSect = 0;
while (pSectionIter->Next()){
actSect =
m_pSections->GetTuple(pSectionIter->GetId());
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;
return actSect;
}
else {
if (fabs(in_xGPoint->GetPosition() - start) <= 0.01) {
delete pSectionIter;
return actSect;
}
else {
if (fabs(in_xGPoint->GetPosition() - end) <= 0.01) {
Tuple *pRoute = GetRoute(((TupleIdentifier*)
actSect->GetAttribute(SECTION_RRC))->GetTid());
if (fabs(((CcReal*)
pRoute->GetAttribute(ROUTE_LENGTH))->GetRealval()
- end) <= 0.01){
pRoute->DeleteIfAllowed();
delete pSectionIter;
return actSect;
} else {
pRoute->DeleteIfAllowed();
}
}
}
}
actSect->DeleteIfAllowed();
}
}
delete pSectionIter;
return 0;
vector<JunctionSortEntry> xJunctions;
CcInt xRouteId(true, in_xGPoint->GetRouteId());
GetJunctionsOnRoute(&xRouteId,
xJunctions);
// Now that we found all relevant junctions we can iterate over them.
int iSectionId = 0;
double juncpos;
for(size_t i = 0; i < xJunctions.size(); i++)
{
// Get next junction
JunctionSortEntry xCurrentEntry = xJunctions[i];
iSectionId = xCurrentEntry.GetDownSectionId();
juncpos = xCurrentEntry.GetRouteMeas();
if(juncpos > in_xGPoint->GetPosition())
{
break;
}
if (juncpos != 0 && fabs(juncpos - in_xGPoint->GetPosition()) < 0.01){
break;
}
iSectionId = xCurrentEntry.GetUpSectionId();
}
for(size_t i = 0; i < xJunctions.size(); i++)
{
// Get next junction
JunctionSortEntry xCurrentEntry = xJunctions[i];
xCurrentEntry.m_pJunction->DeleteIfAllowed();
}
if(iSectionId == 0) return 0;
else return m_pSections->GetTuple(iSectionId);
*/
}
Tuple* Network::GetRoute ( int in_RouteId )
{
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 ( TupleId in_routeTID )
{
return m_pRoutes->GetTuple ( in_routeTID, false );
}
void Network::GetSectionsOfRouteInterval ( const RouteInterval *ri,
DbArray<SectTreeEntry> *io_SectionIds )
{
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 ( ( 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->Append ( *sect );
delete sect;
if ( riend <= end )
{
actSect->DeleteIfAllowed();
break;
}
}
actSect->DeleteIfAllowed();
}
io_SectionIds->TrimToSize();
delete pSectionIter;
};
void Network::GetSectionsOfRoutInterval ( const RouteInterval *ri,
vector<TupleId> &res )
{
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 ( fabs ( ristart - riend ) <= 0.01 &&
( fabs ( ristart - start ) <= 0.01 || fabs ( ristart - end ) <= 0.01
) )
{
res.push_back ( actSectTID );
actSect->DeleteIfAllowed();
break;
}
else
{
if ( ( ( ristart <= start && end <= riend ) ||
( start <= ristart && end > ristart ) ||
( start < riend && riend <= end ) ) &&
( ! ( fabs ( ristart - end ) <= 0.01 || fabs ( start - riend ) <=
0.01 ) ) )
res.push_back ( actSectTID );
}
actSect->DeleteIfAllowed();
}
delete pSectionIter;
}
void Network::GetPointOnRoute ( const GPoint* in_pGPoint, Point*& res )
{
/*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 );
assert ( pLine != 0 );
pLine->AtPosition ( in_pGPoint->GetPosition(),true, *res );
pRoute->DeleteIfAllowed();
delete pRoutesIter;
/*return res;*/
}
Relation* Network::GetSectionsInternal()
{
return m_pSections;
}
Relation* Network::GetSections()
{
ostringstream strSectionsPtr;
strSectionsPtr << ( long ) m_pSections;
string querystring = "(consume (feed (" + sectionsInternalTypeInfo +
" (ptr " + strSectionsPtr.str() + "))))";
Word resultWord;
int QueryExecuted = QueryProcessor::ExecuteQuery ( querystring, resultWord );
assert ( QueryExecuted ); // No ASSERT with side effect, please!
return ( Relation * ) resultWord.addr;
}
void Network::GetAdjacentSectionsInfo ( TupleId in_iSectionTId,
bool in_bUpDown,
vector<DirectedSectionInfo> &inout_xSections )
{
inout_xSections.clear();
Tuple *pSect = GetSection ( in_iSectionTId );
if ( pSect != 0 )
{
// get Sid, SectionPage and SectionSlot
int iSectionPage, iSectionSlot;
if (in_bUpDown){
iSectionPage=((CcInt*)pSect->GetAttribute(SECTION_PNO_UP))->GetIntval();
iSectionSlot=((CcInt*)pSect->GetAttribute(SECTION_SLOT_UP))->GetIntval();
}else{
iSectionPage=((CcInt*)pSect->GetAttribute(SECTION_PNO_DOWN))->GetIntval();
iSectionSlot=((CcInt*)pSect->GetAttribute(SECTION_SLOT_DOWN))->GetIntval();
}
pSect->DeleteIfAllowed();
if(iSectionPage != 0 && iSectionSlot !=0){
//getSectionPage
PageRecord xPage;
m_xAdjacencyList.Get ( iSectionPage-1, xPage );
//get Number of Neighbours
int iNeighbours=0;
xPage.GetSectionNoNeighbours(iSectionSlot, iNeighbours);
//Cache for Pages and Slots defined
int **iPagesSlots;
iPagesSlots = new int* [iNeighbours];
for (int i=0; i<iNeighbours;i++){
iPagesSlots[i] = new int[2];
}
for(int i =0; i<iNeighbours ;i++){
xPage.GetSectionNeighbourPage(iSectionSlot,i,iPagesSlots[i][0]);
xPage.GetSectionNeighbourSlot(iSectionSlot,i,iPagesSlots[i][1]);
}
// store all needet attributes of the Neighbour in DirectedSectionInfo
int actPageNum = iSectionPage;
bool bUpDownFlag;
int iSectionId, irid;
double dcost, dduration;
TupleId sectionTid;
double dmeas1, dmeas2;
for(int i=0; i< iNeighbours; i++){
if(actPageNum != iPagesSlots[i][0]){
// get new Page
actPageNum = iPagesSlots[i][0];
m_xAdjacencyList.Get ( actPageNum-1, xPage );
}
xPage.GetSectionId(iPagesSlots[i][1],iSectionId);
xPage.GetSectionUpdown(iPagesSlots[i][1],bUpDownFlag);
xPage.GetSectionMeas1(iPagesSlots[i][1],dmeas1);
xPage.GetSectionMeas2(iPagesSlots[i][1],dmeas2);
xPage.GetSectionRid(iPagesSlots[i][1],irid);
xPage.GetSectionCost(iPagesSlots[i][1],dcost);
xPage.GetSectionDuration(iPagesSlots[i][1],dduration);
xPage.GetSectionTid(iPagesSlots[i][1],sectionTid);
inout_xSections.push_back (
DirectedSectionInfo(sectionTid,bUpDownFlag,dmeas1,dmeas2,irid,
dcost,dduration));
}
//Delete Array
for (int i=0; i<iNeighbours;i++){
delete [] iPagesSlots[i];
}
delete [] iPagesSlots;
}
}
}
void Network::GetAdjacentSections ( TupleId in_iSectionTId,
bool in_bUpDown,
vector<DirectedSection> &inout_xSections )
{
inout_xSections.clear();
Tuple *pSect = GetSection ( in_iSectionTId );
if ( pSect != 0 )
{
// get Sid, SectionPage and SectionSlot
int iSectionPage, iSectionSlot;
if (in_bUpDown){
iSectionPage =((CcInt*)pSect->GetAttribute(SECTION_PNO_UP))->GetIntval();
iSectionSlot =((CcInt*)pSect->GetAttribute(SECTION_SLOT_UP))->GetIntval();
}else{
iSectionPage =((CcInt*)pSect->GetAttribute(SECTION_PNO_DOWN))->GetIntval();
iSectionSlot=((CcInt*)pSect->GetAttribute(SECTION_SLOT_DOWN))->GetIntval();
}
pSect->DeleteIfAllowed();
if(iSectionPage != 0 && iSectionSlot !=0){
//getSectionPage
PageRecord xPage;
m_xAdjacencyList.Get ( iSectionPage-1, xPage );
//get Number of Neighbours
int iNeighbours=0;
xPage.GetSectionNoNeighbours(iSectionSlot, iNeighbours);
//Cache for Pages and Slots defined
int **iPagesSlots;
iPagesSlots = new int* [iNeighbours];
for (int i=0; i<iNeighbours;i++){
iPagesSlots[i] = new int[2];
}
for(int i =0; i<iNeighbours ;i++){
xPage.GetSectionNeighbourPage(iSectionSlot,i,iPagesSlots[i][0]);
xPage.GetSectionNeighbourSlot(iSectionSlot,i,iPagesSlots[i][1]);
}
// store the Sid and UpDownFlag of the Neighbour in DirectedSection
int actPageNum = iSectionPage;
bool bUpDownFlag;
int iSectionId;
TupleId sectionTid;
for(int i=0; i< iNeighbours; i++){
if(actPageNum != iPagesSlots[i][0]){
// get new Page
actPageNum = iPagesSlots[i][0];
m_xAdjacencyList.Get ( actPageNum-1, xPage );
}
xPage.GetSectionId(iPagesSlots[i][1],iSectionId);
xPage.GetSectionUpdown(iPagesSlots[i][1],bUpDownFlag);
xPage.GetSectionTid(iPagesSlots[i][1],sectionTid);
inout_xSections.push_back (DirectedSection(sectionTid,bUpDownFlag));
}
//Delete Array
for (int i=0; i<iNeighbours;i++){
delete [] iPagesSlots[i];
}
delete [] iPagesSlots;
}
}
}
SimpleLine Network::GetRouteCurve ( int in_iRouteId )
{
Tuple *pRoute = GetRoute ( in_iRouteId );
SimpleLine sl = * ( ( SimpleLine* ) pRoute->GetAttribute ( ROUTE_CURVE ) );
pRoute->DeleteIfAllowed();
return sl;
}
bool Network::GetDual ( int in_iRouteId )
{
Tuple *pRoute = GetRoute ( in_iRouteId );
bool dual = ( ( CcBool* ) pRoute->GetAttribute ( ROUTE_DUAL ) )->GetBoolval();
pRoute->DeleteIfAllowed();
return dual;
}
void Network::GetTupleIdSectionOnRouteJun(GPoint* in_xGPoint,
vector<TupleId>& res)
{
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 ( fabs ( in_xGPoint->GetPosition() - start ) <= 0.01 )
{
// delete pSectionIter;
// actSect->DeleteIfAllowed();
// return result;
res.push_back(result);
}
else
{
if ( fabs ( in_xGPoint->GetPosition() - end ) <= 0.01 )
{
Tuple *pRoute = GetRoute(((TupleIdentifier* )
actSect->GetAttribute ( SECTION_RRC ))->GetTid() );
if ( fabs ( ( ( CcReal* )
pRoute->GetAttribute ( ROUTE_LENGTH ) )->GetRealval()
- end ) <= 0.01 )
{
// pRoute->DeleteIfAllowed();
// delete pSectionIter;
// actSect->DeleteIfAllowed();
res.push_back(result);
// return result;
}
pRoute->DeleteIfAllowed();
}
}
}
// actSect->DeleteIfAllowed();
}
actSect->DeleteIfAllowed();
}
delete pSectionIter;
}
GPoint* Network::GetNetworkPosOfPoint ( Point p )
{
const Rectangle<2> orig = p.BoundingBox();
double minMax[] = {orig.MinD ( 0 ) - 1.0,
orig.MaxD ( 0 ) + 1.0,
orig.MinD ( 1 ) - 1.0,
orig.MaxD ( 1 ) + 1.0 };
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 );
pCurrRoute->DeleteIfAllowed();
return result;
}
double dpos, difference;
SimpleLine* pRouteCurve = ( SimpleLine* ) pCurrRoute->GetAttribute (
ROUTE_CURVE );
if ( chkPoint ( pRouteCurve, p, true, dpos, difference ) )
{
int rid = ( ( CcInt* ) pCurrRoute->GetAttribute ( ROUTE_ID ) )->GetIntval();
GPoint *result = new GPoint ( true, GetId(), rid, dpos, None );
pCurrRoute->DeleteIfAllowed();
return result;
}
else
{
pCurrRoute->DeleteIfAllowed();
while ( m_pRTreeRoutes->Next ( res ) )
{
pCurrRoute = m_pRoutes->GetTuple ( res.info, false );
pRouteCurve = ( SimpleLine* ) pCurrRoute->GetAttribute ( ROUTE_CURVE );
if ( chkPoint ( pRouteCurve, p, true, dpos, difference ) )
{
int rid = ( ( CcInt* ) pCurrRoute->GetAttribute ( ROUTE_ID )
)->GetIntval();
GPoint *result = new GPoint ( true, GetId(),
rid,
dpos, None );
pCurrRoute->DeleteIfAllowed();
return result;
}
pCurrRoute->DeleteIfAllowed();
}
/*
If the point exact hits a route the route should be found here. If the point
value is not exact on the route curve we try to map it in the next step with
bigger tolerance for the hit of the route curve.
*/
if ( m_pRTreeRoutes->First ( bbox, res ) )
pCurrRoute = m_pRoutes->GetTuple ( res.info, false );
pRouteCurve = ( SimpleLine* ) pCurrRoute->GetAttribute ( ROUTE_CURVE );
if ( chkPoint03 ( pRouteCurve, p, true, dpos, difference ) )
{
int rid = ( ( CcInt* ) pCurrRoute->GetAttribute ( ROUTE_ID )
)->GetIntval();
GPoint *result = new GPoint ( true, GetId(),
rid,
dpos, None );
pCurrRoute->DeleteIfAllowed();
return result;
}
else
{
pCurrRoute->DeleteIfAllowed();
while ( m_pRTreeRoutes->Next ( res ) )
{
pCurrRoute = m_pRoutes->GetTuple ( res.info , false);
pRouteCurve = ( SimpleLine* ) pCurrRoute->GetAttribute ( ROUTE_CURVE );
if ( chkPoint03 ( pRouteCurve, p, true, dpos, difference ) )
{
int rid = ( ( CcInt* ) pCurrRoute->GetAttribute ( ROUTE_ID )
)->GetIntval();
GPoint *result = new GPoint ( true, GetId(),
rid,
dpos, None );
pCurrRoute->DeleteIfAllowed();
return result;
}
pCurrRoute->DeleteIfAllowed();
}
}
if ( m_pRTreeRoutes->First ( bbox, res ) )
pCurrRoute = m_pRoutes->GetTuple ( res.info, false );
pRouteCurve = ( SimpleLine* ) pCurrRoute->GetAttribute ( ROUTE_CURVE );
if ( lastchkPoint03 ( pRouteCurve, p, true, dpos, difference ) )
{
int rid = ( ( CcInt* ) pCurrRoute->GetAttribute ( ROUTE_ID )
)->GetIntval();
GPoint *result = new GPoint ( true, GetId(),
rid,
dpos, None );
pCurrRoute->DeleteIfAllowed();
return result;
}
else
{
pCurrRoute->DeleteIfAllowed();
while ( m_pRTreeRoutes->Next ( res ) )
{
pCurrRoute = m_pRoutes->GetTuple ( res.info, false );
pRouteCurve = ( SimpleLine* ) pCurrRoute->GetAttribute ( ROUTE_CURVE );
if ( lastchkPoint03 ( pRouteCurve, p, true, dpos, difference ) )
{
int rid = ( ( CcInt* ) pCurrRoute->GetAttribute ( ROUTE_ID )
)->GetIntval();
GPoint *result = new GPoint ( true, GetId(),
rid,
dpos, None );
pCurrRoute->DeleteIfAllowed();
return result;
}
pCurrRoute->DeleteIfAllowed();
}
} // should not be reached
GPoint *result = new GPoint ( false );
pCurrRoute->DeleteIfAllowed();
return result;
}
}
void Network::GetJunctionMeasForRoutes ( CcInt *pRoute1Id, CcInt *pRoute2Id,
double &rid1meas, double &rid2meas )
{
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();
}
}
void Network::GetLineValueOfRouteInterval ( const RouteInterval *in_ri,
SimpleLine *out_Line )
{
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 );
CcBool* pStSm = ( CcBool* ) pRoute->GetAttribute ( ROUTE_STARTSSMALLER );
bool startSmaller = pStSm->GetBoolval();
pLine->SubLine ( min ( in_ri->GetStartPos(), in_ri->GetEndPos() ),
max ( in_ri->GetStartPos(), in_ri->GetEndPos() ),
startSmaller, *out_Line );
pRoute->DeleteIfAllowed();
delete pRoutesIter;
}
/*
3.1.4 Support functions of type constructor ~network~
~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->ThreeElemList ( nl->IntAtom ( m_iId ),
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 routes
ListExpr xType;
nl->ReadFromString ( routesInternalTypeInfo, 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 btree for routesByStartposId
nl->ReadFromString ( routesBTreeTypeInfo, xType );
xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
if ( !m_pBTreeRoutesByStartposId->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;
}
//SmiFileId fileId = 0;
//m_xAdjacencyList.SaveToRecord(in_xValueRecord, inout_iOffset, fileId);
//m_xSubAdjacencyList.SaveToRecord(in_xValueRecord, inout_iOffset, fileId);
//save m_xAdjacencyLlist
//Flob *tmpAdjList = &m_xAdjacencyList;
/* cout << "before storing:" << endl;
cout << "adjList" << ((Flob)m_xAdjacencyList) << endl;
cout << "adjList" << ((Flob)m_xSubAdjacencyList) << endl;
cout << "----" << endl;*/
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 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;
}
nl->ReadFromString ( sectionsBTreeTypeInfo, xType );
xNumericType =SecondoSystem::GetCatalog()->NumericType ( xType );
if ( !m_pBTreeSections->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 );
}
/*
~NetworkProp~-funtion of the type constructor ~network~
*/
ListExpr Network::NetworkProp()
{
ListExpr examplelist = nl->TextAtom();
nl->AppendText ( examplelist,
"thenetwork(<id>,<routes-relation>, <junctions-relation>)" );
return ( nl->TwoElemList (
nl->TwoElemList ( nl->StringAtom ( "Creation" ),
nl->StringAtom ( "Example Creation" ) ),
nl->TwoElemList ( examplelist,
nl->StringAtom ( "(let n = thenetwork(id, r,j))" ) ) ));
}
/*
~OutNetwork~-funtion of the type constructor ~network~
*/
ListExpr Network::OutNetwork ( ListExpr typeInfo, Word value )
{
Network *n = ( Network* ) value.addr;
return n->Out ( typeInfo );
}
/*
~InNetwork~-funtion of the type constructor ~network~
*/
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 ) );
}
}
/*
~CreateNetwork~-funtion of the type constructor ~network~
*/
Word Network::CreateNetwork ( const ListExpr typeInfo )
{
return SetWord ( new Network() );
}
/*
~CloseNetwork~-funtion of the type constructor ~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 ) );
}
/*
~DeleteNetwork~-funtion of the type constructor ~network~
*/
void Network::DeleteNetwork ( const ListExpr typeInfo, Word& w )
{
Network* n = ( Network* ) w.addr;
//n->Destroy();
delete n;
w.addr = 0;
}
/*
~CheckNetwork~-funtion of the type constructor ~network~
*/
bool Network::CheckNetwork ( ListExpr type, ListExpr& errorInfo )
{
return ( nl->IsEqual ( type, "network" ) );
}
/*
~CastNetwork~-funtion of the type constructor ~network~
*/
void* Network::CastNetwork ( void* addr )
{
return ( 0 );
}
/*
~SaveNetwork~-funtion of the type constructor ~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 );
}
/*
~OpenNetwork~-funtion of the type constructor ~network~
*/
bool Network::OpenNetwork ( SmiRecord& valueRecord,
size_t& offset,
const ListExpr typeInfo,
Word& value )
{
value.addr = Network::Open ( valueRecord, offset, typeInfo );
return value.addr != 0;
}
/*
~SizeOfNetwork~-funtion of the type constructor ~network~
*/
int Network::SizeOfNetwork()
{
return 0;
}
/*
~IsDefined~-funtion of the type constructor ~network~
*/
int Network::IsDefined()
{
return m_bDefined;
}
/*
Secondo TypeConstructor for class ~Network~
*/
TypeConstructor network ( "network", Network::NetworkProp,
Network::OutNetwork, Network::InNetwork,
0, 0,
Network::CreateNetwork, Network::DeleteNetwork,
Network::OpenNetwork, Network::SaveNetwork,
Network::CloseNetwork, Network::CloneNetwork,
Network::CastNetwork, Network::SizeOfNetwork,
Network::CheckNetwork );
/*
3.2 class ~GLine~
3.2.1 Constructors
The simple constructor. Should not be used.
*/
GLine::GLine():Attribute()
{}
GLine::GLine ( int in_iSize ) :
Attribute(true),
m_xRouteIntervals ( in_iSize )
{
SetDefined(true);
m_bSorted = false;
m_dLength = 0.0;
}
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;
}
/*
2.2.2 Methods of class ~GLine~
*/
void GLine::SetNetworkId ( int in_iNetworkId )
{
m_iNetworkId = in_iNetworkId;
SetDefined(true);
}
void GLine::AddRouteInterval ( RouteInterval ri )
{
m_xRouteIntervals.Append ( ri );
m_dLength = m_dLength + fabs ( ri.GetEndPos() - ri.GetStartPos() );
}
void GLine::AddRouteInterval ( int in_iRouteId,
double in_dStart,
double in_dEnd )
{
RouteInterval *ri = new RouteInterval ( in_iRouteId,
in_dStart,
in_dEnd );
AddRouteInterval ( *ri );
delete ri;
}
bool GLine::IsSorted()
{
return m_bSorted;
}
void GLine::SetSorted ( 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 ) != 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();
// 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 );
int iRouteId = pCurrentInterval.GetRouteId();
double dStart = pCurrentInterval.GetStartPos();
double dEnd = pCurrentInterval.GetEndPos();
// Build list
xNext = nl->ThreeElemList ( nl->IntAtom ( iRouteId ),
nl->RealAtom ( dStart ),
nl->RealAtom ( dEnd ) );
// 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 );
}
}
if ( pGline->m_xRouteIntervals.Size() == 0 )
{
xRouteIntervals = nl->TheEmptyList();
}
return nl->TwoElemList ( xNetworkId,
xRouteIntervals );
}
Word GLine::Create ( const ListExpr typeInfo )
{
return SetWord ( new GLine ( 0 ) );
}
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() );
}
GLine* GLine::Clone() const
{
GLine *xOther = new GLine ( Size() );
xOther->SetDefined ( IsDefined() );
xOther->SetSorted ( m_bSorted );
xOther->SetNetworkId ( m_iNetworkId );
/*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& GLine::Print ( ostream& os ) const
{
os << "GLine: NetworkId: " << m_iNetworkId << endl;
for ( int i = 0; i < m_xRouteIntervals.Size() ; i++ )
{
RouteInterval ri;
Get ( i, ri );
os << "RouteInterval: " << i << " rid: " << ri.GetRouteId();
os << " from: " << ri.GetStartPos() << " to: " << ri.GetEndPos();
os << endl;
}
os << " end gline";
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 )
{
m_xRouteIntervals.copyFrom(l.m_xRouteIntervals);
m_bSorted = l.m_bSorted;
SetDefined(l.IsDefined());
m_iNetworkId = l.m_iNetworkId;
TrimToSize();
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()
{
if ( IsDefined() ) return &m_xRouteIntervals;
else return 0;
};
void GLine::CopyFrom ( const Attribute* right )
{
*this = * ( ( const GLine* ) right );
//Clear();
/*
GLine *src = (GLine*) right;
SetDefined(src->IsDefined());
SetSorted(src->IsSorted());
const RouteInterval* ri;
for (int i = 0; i < src->Size(); i++) {
src->Get(i,ri);
int rid = ri.GetRouteId();
double start = ri.GetStartPos();
double end = ri.GetEndPos();
AddRouteInterval(rid, start, end);
}
*/
}
double GLine::GetLength()
{
return m_dLength;
}
int GLine::GetNetworkId()
{
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()
{
return m_xRouteIntervals.Size();
};
ListExpr GLine::Property()
{
return ( nl->TwoElemList (
nl->FourElemList ( nl->StringAtom ( "Signature" ),
nl->StringAtom ( "Example Type List" ),
nl->StringAtom ( "List Rep" ),
nl->StringAtom ( "Example List" ) ),
nl->FourElemList (
nl->StringAtom ( "-> DATA" ),
nl->StringAtom ( "gline" ),
nl->StringAtom ( "(<nid> ((<rid> <startpos><endpos>)...))"),
nl->StringAtom ( "(1 ((1 1.5 2.5)(2 1.5 2.0)))" ) ) ) );
}
bool GLine::Check ( ListExpr type, ListExpr& errorInfo )
{
return ( nl->IsEqual ( type, "gline" ) );
}
/*
Netdistance method computes the network distance between two glines. Uses
network distance method of ~GPoint~.
*/
double GLine::Netdistance ( GLine* pgl2 )
{
//GLine* pgl1 = (GLine*) this;
double minDist = numeric_limits<double>::max();
double aktDist = numeric_limits<double>::max();
if ( GetNetworkId() != pgl2->GetNetworkId() )
{
cmsg.inFunError ( "Both glines must belong to the network." );
return minDist;
}
GPoints *bGPgl1 = GetBGP();
GPoints *bGPgl2 = pgl2->GetBGP();
GPoint gp1, gp2;
for ( int i = 0; i < bGPgl1->Size(); i++ )
{
bGPgl1->Get ( i,gp1 );
if ( gp1.Inside ( pgl2 ) )
{
bGPgl1->DeleteIfAllowed();
bGPgl2->DeleteIfAllowed();
return 0.0;
}
for ( int j = 0; j < bGPgl2->Size(); j++ )
{
bGPgl2->Get ( j, gp2 );
if ( gp2.Inside ( this ) )
{
bGPgl1->DeleteIfAllowed();
bGPgl2->DeleteIfAllowed();
return 0.0;
}
aktDist = gp1.Netdistance ( &gp2 );
if ( aktDist < minDist ) minDist = aktDist;
if ( minDist <= 0.0 )
{
bGPgl1->DeleteIfAllowed();
bGPgl2->DeleteIfAllowed();
return 0.0;
}
}
}
bGPgl1->DeleteIfAllowed();
bGPgl2->DeleteIfAllowed();
return minDist;
}
/*
Distance method computes the Euclidean Distance between two glines. Uses
distance method of ~GPoint~.
*/
double GLine::Distance ( GLine* pgl2 )
{
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();
}
void GLine::Uniongl ( GLine *pgl2, GLine *res )
{
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 )
{
res->Clear();
if ( IsDefined() && NoOfComponents() > 0 )
{
//Network* pNetwork = NetworkManager::GetNetwork(GetNetworkId());
Network* pNetwork = NetworkManager::GetNetworkNew ( GetNetworkId(), netList
);
RouteInterval rI;
Line *l = new Line ( 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 = new Line ( 0 );
pSubline->toLine ( *partLine );
pSubline->DeleteIfAllowed();
x = SetOp ( *l, *partLine, avlseg::union_op );
partLine->DeleteIfAllowed();
l->DeleteIfAllowed();
l = x;
}
}
NetworkManager::CloseNetwork ( pNetwork );
( *res ) = *x;
x->DeleteIfAllowed();
res->SetDefined ( true );
}
else
{
if ( IsDefined() && NoOfComponents() == 0 )
{
res->SetDefined ( true );
}
else
{
res->SetDefined ( false );
}
}
res->TrimToSize();
}
bool GLine::Intersects ( GLine *pgl )
{
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() ) ) )
{
return true;
}
}
}
}
}
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;
}
}
else
{
for ( int i = 0; i < pgl->NoOfComponents(); i++ )
{
pgl->Get ( i, pRi2 );
if ( searchUnit ( this, 0, NoOfComponents()-1, pRi2 ) ) return true;
}
}
}
return false;
}
/*
Secondo Type Constructor for class ~GLine~
*/
TypeConstructor gline (
"gline", //name
GLine::Property, //property function
GLine::Out, GLine::In, //Out and In functions
0, 0, //SaveToList and
//RestoreFromList functions
GLine::Create, GLine::Delete, //object creation and deletion
OpenAttribute<GLine>, SaveAttribute<GLine>, //open and save functions
GLine::Close, GLine::CloneGLine, //object close, and clone
GLine::Cast, //cast function
GLine::SizeOf, //sizeof function
GLine::Check ); //kind checking function
/*
3.3 class ~GPoint~
3.3.1 Constructors
See ~network.h~ class definition of ~GPoint~
3.3.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 );
}
}
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 ( "undef" );
}
Word GPoint::CreateGPoint ( const ListExpr typeInfo )
{
return SetWord ( new GPoint ( false ) );
}
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 );
}
ListExpr GPoint::GPointProperty()
{
return ( nl->TwoElemList (
nl->FourElemList ( nl->StringAtom ( "Signature" ),
nl->StringAtom ( "Example Type List" ),
nl->StringAtom ( "List Rep" ),
nl->StringAtom ( "Example List" ) ),
nl->FourElemList ( nl->StringAtom ( "-> DATA" ),
nl->StringAtom ( "gpoint" ),
nl->StringAtom ( "(<network_id> <route_id> "
"<position> <side>)" ),
nl->StringAtom ( "(1 1 0.0 0)" ) ) ) );
}
bool GPoint::CheckGPoint ( ListExpr type, ListExpr& errorInfo )
{
return ( nl->IsEqual ( type, "gpoint" ) );
}
/*
Netdistance function computes the network distance between two ~GPoint~s.
Using Dijkstras-Algorithm for shortest path computing
*/
double GPoint::Netdistance ( GPoint* pToGPoint )
{
GLine* pGLine = new GLine ( 0 );
double res;
if ( ShortestPath ( pToGPoint, pGLine ) )
{
res = pGLine->GetLength();
pGLine->DeleteIfAllowed();
return res;
}
else
{
pGLine->DeleteIfAllowed();
return 0;
}
}
double GPoint::NewNetdistance ( GPoint* pToGPoint,GLine* gline )
{
GPoint* gp1 = new GPoint ( true,GetNetworkId(),GetRouteId(),GetPosition() );
GPoint* gp2 = new GPoint ( true,pToGPoint->GetNetworkId(),
pToGPoint->GetRouteId(),pToGPoint->GetPosition() );
double res;
if ( gp1->ShortestPath ( gp2, gline ) )
{
res = gline->GetLength();
gp1->DeleteIfAllowed();
gp2->DeleteIfAllowed();
return res;
}
else
{
gp1->DeleteIfAllowed();
gp2->DeleteIfAllowed();
return 0;
}
}
/*
Distance function computes the Euclidean Distance between two ~GPoint~s.
*/
double GPoint::Distance ( GPoint* pToGPoint )
{
map<int,string>::iterator it = netList->begin();
if ( IsDefined() && pToGPoint->IsDefined() &&
GetNetworkId() == pToGPoint->GetNetworkId() )
{
//Network* pNetwork=NetworkManager::GetNetwork(GetNetworkId());
Network* pNetwork = NetworkManager::GetNetworkNew ( GetNetworkId(),
netList );
Point *from = new Point ( false );
pNetwork->GetPointOnRoute ( this, from );
Point *to = new Point ( false );
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 ( GLine *gl )
{
if ( ! ( gl->IsDefined() ) || !IsDefined() ||
gl->NoOfComponents() < 1 ) return false;
if ( GetNetworkId() != gl->GetNetworkId() ) return false;
RouteInterval pCurrRInter;
if ( gl->IsSorted() )
return ( searchRouteInterval ( this, gl, 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 ( fabs ( pCurrRInter.GetStartPos() - GetPosition() ) < 0.1 )
return true;
if ( fabs ( pCurrRInter.GetEndPos() - GetPosition() ) < 0.1 )
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::ShortestPath ( GPoint *to, GLine *result )
{
GPoint* start =
new GPoint ( true,GetNetworkId(),GetRouteId(),GetPosition(), GetSide() );
GPoint* end = new GPoint ( true,to->GetNetworkId(),to->GetRouteId(),
to->GetPosition(),to->GetSide() );//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 );
start->DeleteIfAllowed();
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 );
start->DeleteIfAllowed();
end->DeleteIfAllowed();
return false;
}
result->SetNetworkId ( start->GetNetworkId() );
// Load the network
//Network* pNetwork = NetworkManager::GetNetwork(start->GetNetworkId());
Network* pNetwork = NetworkManager::GetNetworkNew ( start->GetNetworkId(),
netList );
if ( pNetwork == 0 )
{
sendMessage ( "Network not found." );
result->SetDefined ( false );
start->DeleteIfAllowed();
end->DeleteIfAllowed();
return false;
}
// Get sections where the path should start or end
TupleId startSectTID = pNetwork->GetTupleIdSectionOnRoute ( start );
Tuple* startSection = pNetwork->GetSection ( startSectTID );
if ( startSection == 0 )
{
sendMessage ( "Starting GPoint not found in network." );
NetworkManager::CloseNetwork ( pNetwork );
result->SetDefined ( false );
start->DeleteIfAllowed();
end->DeleteIfAllowed();
return false;
}
TupleId lastSectTID = pNetwork->GetTupleIdSectionOnRoute ( end );
Tuple* endSection = pNetwork->GetSection ( lastSectTID );
if ( endSection == 0 )
{
sendMessage ( "End GPoint not found in network." );
startSection->DeleteIfAllowed();
NetworkManager::CloseNetwork ( pNetwork );
result->SetDefined ( false );
start->DeleteIfAllowed();
end->DeleteIfAllowed();
return false;
}
////////////////////////////////////////////////////
/* bool junctionpoint = false;
Point* endp = new Point();
pNetwork->GetPointOnRoute(end,endp); //end point
Point* startp = new Point();
pNetwork->GetPointOnRoute(start,startp);
if(fabs(endp->GetX() - startp->GetX()) < 0.1 &&
fabs(endp->GetY() - startp->GetY()) < 0.1){
endp->DeleteIfAllowed();
startp->DeleteIfAllowed();
start->DeleteIfAllowed();
end->DeleteIfAllowed();
startSection->DeleteIfAllowed();
endSection->DeleteIfAllowed();
NetworkManager::CloseNetwork(pNetwork);
return false;
}
vector<JunctionSortEntry> juns;
CcInt* routeid = new CcInt(true,end->GetRouteId());
pNetwork->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() &&
fabs(((CcReal*)t->GetAttribute(JUNCTION_ROUTE1_MEAS))->GetRealval()-
end->GetPosition()) < 0.1)
junctionpoint = true;
if(((CcInt*)t->GetAttribute(JUNCTION_ROUTE2_ID))->GetIntval() ==
end->GetRouteId() &&
fabs(((CcReal*)t->GetAttribute(JUNCTION_ROUTE2_MEAS))->GetRealval()-
end->GetPosition()) < 0.1)
junctionpoint = true;
}
vector<TupleId> secjunid;
if(junctionpoint){//it is a junction point
vector<DirectedSection> sectionlist;
if(fabs(end->GetPosition()-
((CcReal*)endSection->GetAttribute(SECTION_MEAS1))->GetRealval())< 0.1)
pNetwork->GetAdjacentSections(endSection->GetTupleId(),false,sectionlist);
else
pNetwork->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.
*/
if ( startSectTID == lastSectTID ||
GetRouteId() == to->GetRouteId() )
{
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<DirectedSectionInfo> adjSectionList;
adjSectionList.clear();
if ( start->GetSide() == 0 )
{
dist = start->GetPosition() - sectMeas1;
pNetwork->GetAdjacentSectionsInfo ( 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++ )
{
DirectedSectionInfo actNextSect = adjSectionList[i];
if ( actNextSect.GetSectionTid() != startSectTID )
{
PQEntry *actEntry = new PQEntry ( actNextSect.GetSectionTid(), dist,
actNextSect.GetUpDownFlag(),
startSectTID,
actNextSect.GetMeas1(),
actNextSect.GetMeas2(),
actNextSect.GetRid());
prioQ->Insert ( *actEntry, visitedSect ) ;
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;
pNetwork->GetAdjacentSectionsInfo ( startSectTID, true, adjSectionList);
for ( size_t i = 0; i < adjSectionList.size(); i++ )
{
DirectedSectionInfo actNextSect = adjSectionList[i];
if ( actNextSect.GetSectionTid() != startSectTID )
{
PQEntry *actEntry = new PQEntry ( actNextSect.GetSectionTid(), dist,
actNextSect.GetUpDownFlag(),
startSectTID,
actNextSect.GetMeas1(),
actNextSect.GetMeas2(),
actNextSect.GetRid() );
prioQ->Insert ( *actEntry, visitedSect );
delete actEntry;
}
}
adjSectionList.clear();
}
else
{
dist = start->GetPosition() - sectMeas1;
pNetwork->GetAdjacentSectionsInfo ( startSectTID, false, adjSectionList);
bool first = true;
for ( size_t i = 0; i < adjSectionList.size(); i++ )
{
DirectedSectionInfo 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,
actNextSect.GetMeas1(),
actNextSect.GetMeas2(),
actNextSect.GetRid() );
prioQ->Insert ( *actEntry, visitedSect );
delete actEntry;
}
}
adjSectionList.clear();
dist = sectMeas2 -start->GetPosition();
pNetwork->GetAdjacentSectionsInfo ( startSectTID, true, adjSectionList);
for ( size_t i = 0; i < adjSectionList.size(); i++ )
{
DirectedSectionInfo 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,
actNextSect.GetMeas1(),
actNextSect.GetMeas2(),
actNextSect.GetRid() );
prioQ->Insert ( *actEntry, visitedSect );
delete actEntry;
}
}
adjSectionList.clear();
}
}
/*
Use priorityQueue to find shortestPath.
*/
PQEntry *actPQEntry;
bool found = false;
vector<PQEntry> candidate;
while ( !prioQ->IsEmpty() && !found )
{
actPQEntry = prioQ->GetAndDeleteMin ( visitedSect );
sectMeas1 = actPQEntry->meas1;
sectMeas2 = actPQEntry->meas2;
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 = pNetwork->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();
pNetwork->GetAdjacentSectionsInfo ( actPQEntry->sectID,
actPQEntry->upDownFlag,
adjSectionList );
for ( size_t i = 0; i <adjSectionList.size();i++ )
{
DirectedSectionInfo actNextSect = adjSectionList[i];
if ( actNextSect.GetSectionTid() != actPQEntry->sectID )
{
PQEntry *actEntry = new PQEntry ( actNextSect.GetSectionTid(),
dist,
actNextSect.GetUpDownFlag(),
actPQEntry->sectID,
actNextSect.GetMeas1(),
actNextSect.GetMeas2(),
actNextSect.GetRid() );
prioQ->Insert ( *actEntry, visitedSect );
delete actEntry;
}
}
delete actPQEntry;
actPQEntry=0;
}
else
{
/*
Shortest Path found.
Compute last route interval and resulting gline.
*/
//actually not really found
/*candidate.push_back(*actPQEntry);
while(!prioQ->IsEmpty()){
PQEntry* temp = prioQ->GetAndDeleteMin(visitedSect);
Tuple *act = pNetwork->GetSection(temp->sectID);
//double m1 =
// ((CcReal*) act->GetAttribute(SECTION_MEAS1))->GetRealval();
//double m2 =
// ((CcReal*) act->GetAttribute(SECTION_MEAS2))->GetRealval();
act->DeleteIfAllowed();
if(temp->distFromStart >=
(actPQEntry->distFromStart+fabs(sectMeas2-sectMeas1))){
temp->DeleteIfAllowed();
break;
}
if(junctionpoint){ //end point is a junction point
for(unsigned int i = 0;i < secjunid.size();i++){
if(secjunid[i] == temp->sectID){
Tuple* sect = pNetwork->GetSection(temp->sectID);
double m1 =
((CcReal*)sect->GetAttribute(SECTION_MEAS1))->GetRealval();
double m2 =
((CcReal*)sect->GetAttribute(SECTION_MEAS2))->GetRealval();
if(temp->distFromStart+m2-m1 >
actPQEntry->distFromStart+fabs(sectMeas2-sectMeas1)){
sect->DeleteIfAllowed();
continue;
}
lastSectTID = temp->sectID;
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(temp->sectID == lastSectTID){
candidate.push_back(*temp);
}else{
adjSectionList.clear();
pNetwork->GetAdjacentSections(temp->sectID,
temp->upDownFlag,
adjSectionList);
Tuple *tempsec = pNetwork->GetSection(temp->sectID);
double meas1 =
((CcReal*) tempsec->GetAttribute(SECTION_MEAS1))->GetRealval();
double meas2 =
((CcReal*) tempsec->GetAttribute(SECTION_MEAS2))->GetRealval();
dist = temp->distFromStart + fabs(meas2 - meas1);
for (size_t i = 0; i <adjSectionList.size();i++){
DirectedSection actNextSect = adjSectionList[i];
if (actNextSect.GetSectionTid() != temp->sectID) {
PQEntry *actEntry = new PQEntry(actNextSect.GetSectionTid(),
dist,
actNextSect.GetUpDownFlag(),
temp->sectID);
prioQ->Insert(*actEntry, visitedSect);
delete actEntry;
}
}
tempsec->DeleteIfAllowed();
}
temp->DeleteIfAllowed();
}
//double length;
delete actPQEntry;
actSection->DeleteIfAllowed();
double tempdist = numeric_limits<double>::max();
actPQEntry = &candidate[0];
for(unsigned int i = 0; i < candidate.size();i++){
Tuple *sec = pNetwork->GetSection(candidate[i].sectID);
double m1 =
((CcReal*)sec->GetAttribute(SECTION_MEAS1))->GetRealval();
double m2 =
((CcReal*)sec->GetAttribute(SECTION_MEAS2))->GetRealval();
if(candidate[i].upDownFlag == true){//UP
double dist = candidate[i].distFromStart + m2-m1;
if(dist < tempdist){
actPQEntry = &candidate[i];
tempdist = dist;
}
}else{//DOWN
double dist = candidate[i].distFromStart + m2-m1;
if(dist < tempdist){
actPQEntry = &candidate[i];
tempdist = dist;
}
}
sec->DeleteIfAllowed();
}
actSection = pNetwork->GetSection(actPQEntry->sectID);
sectMeas1 =
((CcReal*) actSection->GetAttribute(SECTION_MEAS1))->GetRealval();
sectMeas2 =
((CcReal*) actSection->GetAttribute(SECTION_MEAS2))->GetRealval();*/
///////////////////////////////////////////////
found = true;
double startRI, endRI;
int actRouteId =actPQEntry->rid;
if ( actPQEntry->upDownFlag == true )
{
startRI = sectMeas1;
endRI = end->GetPosition();
}
else
{
startRI = sectMeas2;
endRI = end->GetPosition();
}
/*
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.
*/
RIStack *riStack = new RIStack ( 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
Tuple *actSection = pNetwork->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, riStack );
else
riStack->Push ( actRouteId, sectMeas2, sectMeas1, riStack );
lastSectId = pElem->sectID;
pElem = visitedSect->Find ( pElem->beforeSectId );
}
else
{
end = true;
pNetwork->GetAdjacentSectionsInfo (startSectTID, true,adjSectionList
);
size_t i = 0;
bool stsectfound = false;
while ( i < adjSectionList.size() && !stsectfound )
{
DirectedSectionInfo adjSection = adjSectionList[i];
if ( adjSection.GetSectionTid() == lastSectId )
{
if ( fabs ( start->GetPosition()-sectMeas2 ) > 0.1 )
{
stsectfound = true;
riStack->Push ( actRouteId, start->GetPosition(), sectMeas2,
riStack );
end = true;
}
}
i++;
}
adjSectionList.clear();
if ( !stsectfound )
{
pNetwork->GetAdjacentSectionsInfo ( startSectTID, false,
adjSectionList );
i = 0;
while ( i < adjSectionList.size() && !stsectfound )
{
DirectedSectionInfo adjSection = adjSectionList[i];
if ( adjSection.GetSectionTid() == lastSectId )
{
if ( fabs ( start->GetPosition()-sectMeas1 ) > 0.1 )
{
stsectfound = true;
riStack->Push ( actRouteId, start->GetPosition(), sectMeas1,
riStack );
end = true;
}
}
i++;
}
adjSectionList.clear();
}
}
if ( actSection )
{
actSection->DeleteIfAllowed();
actSection = 0;
}
}
// Cleanup and return result
riStack->StackToGLine ( result );
riStack->RemoveStack();
}
if ( actPQEntry )
{
delete actPQEntry;
actPQEntry = 0;
}
}
if ( visitedSect != 0 ) visitedSect->Remove();
prioQ->Destroy();
delete prioQ;
}
startSection->DeleteIfAllowed();
endSection->DeleteIfAllowed();
NetworkManager::CloseNetwork ( pNetwork );
result->SetSorted ( false );
result->SetDefined ( true );
result->TrimToSize();
start->DeleteIfAllowed();
end->DeleteIfAllowed();
return true;
};
/*
Method ~ShortestPathAStarPlus~
Computes the shortest path between start- and endpoint in the network. Using
AStar-algorithm. The path is returned as gline value.
*/
bool GPoint::ShortestPathAStarPlus(GPoint *pToGPoint,GLine *result,Word func){
bool withfunc = false;
Word funcResult;
ArgVectorPointer funargs;
if (func.addr != 0)
{
withfunc = true;
funargs = qp->Argument(func.addr);
}
//reset the result
result->Clear();
//******************************************************************
// Check the Inputs whether they exist and are defined
//1. generate the startpoint of the search, corresponds with the
// pToGPoint, because we want to have the right sequence at the end
GPoint *end = new GPoint(true, pToGPoint->GetNetworkId(),
pToGPoint->GetRouteId(), pToGPoint->GetPosition(),pToGPoint->GetSide());
//2. generate the endpoint of the search,
// corresponts with the startpoint of the path
GPoint *start =
new GPoint(true, GetNetworkId(), GetRouteId(), GetPosition(), GetSide());
//3. check whether both Points are not 0
if ( start == 0 || end == 0 || !start->IsDefined() ||
!end->IsDefined() )
{
sendMessage ( "Both gpoints must exist and be defined." );
result->SetDefined ( false );
start->DeleteIfAllowed();
end->DeleteIfAllowed();
return false;
}
//4. check whether both Points belong to the same network
if ( start->GetNetworkId() != end->GetNetworkId() )
{
sendMessage ( "Both gpoints belong to different networks." );
result->SetDefined ( false );
start->DeleteIfAllowed();
end->DeleteIfAllowed();
return false;
}
//*************************************************
// Get sections where the path should start or end
//1. get the netwwork and check whether its not null
Network* pNetwork =
NetworkManager::GetNetworkNew ( start->GetNetworkId(),netList );
if ( pNetwork == 0 )
{
sendMessage ( "Network not found." );
result->SetDefined ( false );
start->DeleteIfAllowed();
end->DeleteIfAllowed();
return false;
}
//2. set networkId to the result-gline
TupleId netId = start->GetNetworkId();
result->SetNetworkId ( start->GetNetworkId() );
//3. determin the startsection and check whether its not null
TupleId startSectTID = pNetwork->GetTupleIdSectionOnRoute(start);
Tuple* startSection = pNetwork->GetSection(startSectTID);
if ( startSection == 0 )
{
sendMessage ( "Starting GPoint not found in network." );
NetworkManager::CloseNetwork ( pNetwork );
result->SetDefined ( false );
start->DeleteIfAllowed();
end->DeleteIfAllowed();
return false;
}
//4. determin the endsection and check whether its not null
TupleId endSectTID = pNetwork->GetTupleIdSectionOnRoute(end);
Tuple* endSection = pNetwork->GetSection(endSectTID);
if ( endSection == 0 )
{
sendMessage ( "End GPoint not found in network." );
startSection->DeleteIfAllowed();
NetworkManager::CloseNetwork ( pNetwork );
result->SetDefined ( false );
start->DeleteIfAllowed();
end->DeleteIfAllowed();
return false;
}
//******************************************************************
// CAlCULATE THE SHORTEST PATH WITH A*
//1. check whether both Points on the same Route
// if true, then the path can be directly calculated
if ( startSectTID == endSectTID ||
start->GetRouteId() == end->GetRouteId())
{
result->AddRouteInterval ( start->GetRouteId(), start->GetPosition(),
end->GetPosition());
}
// else calculate the shortespath with the A* algorithem
else{
//1. Generate the openlist,which save all known Points on the searchpath
// with the costs and a pointer to its predecessor used a PrioQueue
PrioQueue *openList = new PrioQueue(0);
//2. Generate the ClosedList, which save alle Points with the sid
// to which the shortest path is known
SectIDTree *closeList = 0;
//3. other variables, they are needed
double dist = 0.0; //distance
double totalcost =0.0; //totalcost of the section
double heuristic = 0.0; //heuristical part of the totalcost
vector<DirectedSectionInfo> adjSectionList;
adjSectionList.clear();
//4. Initialized the OpenList
//Determin the Side of the section, where the point is located
//DEBUG cout << start->GetSide()<<endl;
if(start->GetSide() == 0) // Down-Side of the section
{
//4a. Calculate the distance
double sectMeas1 =
((CcReal*)startSection->GetAttribute(SECTION_MEAS1))->GetRealval();
dist = start->GetPosition() - sectMeas1;
//4b. get the adjacent sections
pNetwork->GetAdjacentSectionsInfo(startSectTID,false,adjSectionList);
//4c. get startsection and put it in the closelist
SectIDTree *startTree = new SectIDTree ( startSectTID,
( TupleId ) numeric_limits<long>::max(),
false, numeric_limits<int>::max() );
closeList = startTree;
//4d. put all adjacent sections in the openlist
for ( size_t i = 0; i < adjSectionList.size(); i++ )
{
DirectedSectionInfo actNextSect = adjSectionList[i];
if (actNextSect.GetSectionTid() != startSectTID)
{
//calculate the totalcost
GPoint *sectEP =
new GPoint(true,netId,
actNextSect.GetRid(),actNextSect.GetMeas1());
heuristic = sectEP->Distance(end);
if(withfunc)
{ //funcargs[0]=cost,funcargs[1]=duration,funcargs[2]=laenge
(*funargs)[0] =new CcReal(true,actNextSect.GetCost());
(*funargs)[1] =new CcReal(true,actNextSect.GetDuration());
(*funargs)[2] =new CcReal(true,actNextSect.GetLength());
qp->Request(func.addr, funcResult);
double fr= ((CcReal*)(funcResult.addr))->GetRealval();
totalcost = fr + heuristic;
//DEBUG cout << "ERGEBNIS:" <<totalcost<<endl;
}
else
{
totalcost = actNextSect.GetCost() + heuristic;
}
//DEBUG
//cout << "section: "<< actNextSect.GetSectionTid()<<"."
// << actNextSect.GetUpDownFlag() << " heuristic: "
// << heuristic<< "+ kosten: "<< actNextSect.GetCost()
// <<"=totalcost: "<< totalcost <<endl;
sectEP->DeleteIfAllowed();
PQEntry *actEntry = new PQEntry(
actNextSect.GetSectionTid(),
dist,
actNextSect.GetUpDownFlag(),
startSectTID,
actNextSect.GetMeas1(),
actNextSect.GetMeas2(),
actNextSect.GetRid(),
totalcost);
openList->Insert (*actEntry, closeList,true);
delete actEntry;
}
}
adjSectionList.clear();
}//END IF (DownSide)
else if(start->GetSide() == 1) //Up-Side of the section
{
//4a. Calculate the distance
double sectMeas2 =
((CcReal*)startSection->GetAttribute(SECTION_MEAS2))->GetRealval();
dist = sectMeas2 - start->GetPosition();
//4b. get the adjacent sections
pNetwork->GetAdjacentSectionsInfo(startSectTID,true,adjSectionList);
//4c. get startsection and put it in the closelist
SectIDTree *startTree = new SectIDTree ( startSectTID,
(TupleId) numeric_limits<long>::max(),
true, numeric_limits<int>::max() );
closeList = startTree;
//4d. put all adjacent sections in the openlist
for ( size_t i = 0; i < adjSectionList.size(); i++ )
{
DirectedSectionInfo actNextSect = adjSectionList[i];
if ( actNextSect.GetSectionTid() != startSectTID )
{
//calculate the totalcost
GPoint *sectEP =
new GPoint(true,netId, actNextSect.GetRid(),
actNextSect.GetMeas2());
heuristic = sectEP->Distance(end);
if(withfunc)
{ //funcargs[0]=cost,funcargs[1]=duration,funcargs[2]=laenge
(*funargs)[0] =new CcReal(true,actNextSect.GetCost());
(*funargs)[1] =new CcReal(true,actNextSect.GetDuration());
(*funargs)[2] =new CcReal(true,actNextSect.GetLength());
qp->Request(func.addr, funcResult);
double fr= ((CcReal*)(funcResult.addr))->GetRealval();
totalcost = fr + heuristic;
//DEBUG cout << "ERGEBNIS:" <<totalcost<<endl;
}
else
{
totalcost = actNextSect.GetCost() + heuristic;
}
sectEP->DeleteIfAllowed();
//DEBUG
//cout << "section: "<< actNextSect.GetSectionTid()<<"."
// << actNextSect.GetUpDownFlag() << " heuristic: "
// << heuristic << "+ kosten: " << actNextSect.GetCost()
// <<"=totalcost: "<< totalcost <<endl;
PQEntry *actEntry = new PQEntry (
actNextSect.GetSectionTid(),
dist,
actNextSect.GetUpDownFlag(),
startSectTID,
actNextSect.GetMeas1(),
actNextSect.GetMeas2(),
actNextSect.GetRid(),
totalcost);
openList->Insert ( *actEntry, closeList, true );
delete actEntry;
}
}
adjSectionList.clear();
}//END ELSE IF (UpSide)
else // NONE, not defined both ways must be calculate
{
bool first = true;
//Entries for the DownSide
//4a. Calculate the totalcost
double sectMeas1 =
((CcReal*)startSection->GetAttribute(SECTION_MEAS1))->GetRealval();
dist = start->GetPosition() - sectMeas1;
//4b. get the adjacent sections
pNetwork->GetAdjacentSectionsInfo(startSectTID,false,adjSectionList);
//4c. put all adjacent sections in the openlist
for ( size_t i = 0; i < adjSectionList.size(); i++ )
{
DirectedSectionInfo actNextSect = adjSectionList[i];
if ( actNextSect.GetSectionTid() != startSectTID )
{
if ( first )
{ //4d. get startsection and put it in the closelist
first = false;
SectIDTree *startTree = new SectIDTree ( startSectTID,
( TupleId ) numeric_limits<long>::max(),
false, numeric_limits<int>::max() );
closeList = startTree;
}
//calculate the totalcost
GPoint *sectEP =
new GPoint(true,netId, actNextSect.GetRid(),
actNextSect.GetMeas1());
heuristic = sectEP->Distance(end);
if(withfunc)
{ //funcargs[0]=cost,funcargs[1]=duration,funcargs[2]=laenge
(*funargs)[0] =new CcReal(true,actNextSect.GetCost());
(*funargs)[1] =new CcReal(true,actNextSect.GetDuration());
(*funargs)[2] = new CcReal(true,actNextSect.GetLength());
qp->Request(func.addr, funcResult);
double fr= ((CcReal*)(funcResult.addr))->GetRealval();
totalcost = fr + heuristic;
//DEBUG cout << "ERGEBNIS:" <<totalcost<<endl;
}
else
{
totalcost = actNextSect.GetCost() + heuristic;
}
sectEP->DeleteIfAllowed();
//DEBUG
//cout << "section: "<< actNextSect.GetSectionTid()<<"."
// << actNextSect.GetUpDownFlag() << " heuristic: "
// << heuristic << "+ kosten: " << actNextSect.GetCost()
// <<"=totalcost: "<< totalcost <<endl;
PQEntry *actEntry = new PQEntry (
actNextSect.GetSectionTid(),
dist,
actNextSect.GetUpDownFlag(),
startSectTID,
actNextSect.GetMeas1(),
actNextSect.GetMeas2(),
actNextSect.GetRid(),
totalcost );
openList->Insert ( *actEntry, closeList, true );
delete actEntry;
}
}
adjSectionList.clear();
//Entries for the UpSide
//4a. Calculate the distance
double sectMeas2 =
((CcReal*)startSection->GetAttribute(SECTION_MEAS2))->GetRealval();
dist = sectMeas2 - start->GetPosition();
//4b. get the adjacent sections
pNetwork->GetAdjacentSectionsInfo(startSectTID,true,adjSectionList);
//4c. put all adjacent sections in the openlist
for ( size_t i = 0; i < adjSectionList.size(); i++ )
{
DirectedSectionInfo actNextSect = adjSectionList[i];
if ( actNextSect.GetSectionTid() != startSectTID )
{
if ( first )
{
//4d. get startsection and put it in the closelist
first = false;
SectIDTree *startTree = new SectIDTree ( startSectTID,
( TupleId ) numeric_limits<long>::max(),
true, numeric_limits<int>::max() );
closeList = startTree;
}
//calculate the totalcost
GPoint *sectEP =
new GPoint(true,netId, actNextSect.GetRid(),
actNextSect.GetMeas2());
heuristic = sectEP->Distance(end);
if(withfunc)
{ //funcargs[0]=cost,funcargs[1]=duration,funcargs[2]=laenge
(*funargs)[0] =new CcReal(true,actNextSect.GetCost());
(*funargs)[1] =new CcReal(true,actNextSect.GetDuration());
(*funargs)[2] =new CcReal(true,actNextSect.GetLength());
qp->Request(func.addr, funcResult);
double fr= ((CcReal*)(funcResult.addr))->GetRealval();
totalcost = fr + heuristic;
//DEBUG cout << "ERGEBNIS:" <<totalcost<<endl;
}
else
{
totalcost = actNextSect.GetCost() + heuristic;
}
sectEP->DeleteIfAllowed();
//DEBUG
//cout << "section: "<< actNextSect.GetSectionTid()<<"."
// << actNextSect.GetUpDownFlag() << " heuristic: "
// << heuristic << "+ kosten: " << actNextSect.GetCost()
// <<"=totalcost: "<< totalcost <<endl;
PQEntry *actEntry = new PQEntry (
actNextSect.GetSectionTid(),
dist,
actNextSect.GetUpDownFlag(),
startSectTID,
actNextSect.GetMeas1(),
actNextSect.GetMeas2(),
actNextSect.GetRid(),
totalcost );
openList->Insert ( *actEntry, closeList, true );
delete actEntry;
}
}
adjSectionList.clear();
}//END ELSE (BothSide)
//5. Use openList to find shortestPath.
PQEntry *actPQEntry;
bool found = false;
vector<PQEntry> candidate;
while ( !openList->IsEmpty() && !found )
{
//5a get the minimum of the openList
actPQEntry = openList->GetAndDeleteMin ( closeList, true );
//5b calculate the totalcost of this element
double sectMeas1 = actPQEntry->meas1;
double sectMeas2 = actPQEntry->meas2;
dist = actPQEntry->distFromStart + fabs ( sectMeas2 - sectMeas1 );
if ( actPQEntry->sectID != endSectTID )
{
// Search further in the network unitl reached last section.
// Get adjacent sections and insert into priority Queue.
adjSectionList.clear();
//5c get adjacent section of the actual element
pNetwork->GetAdjacentSectionsInfo ( actPQEntry->sectID,
actPQEntry->upDownFlag,
adjSectionList );
for ( size_t i = 0; i <adjSectionList.size();i++ )
{
DirectedSectionInfo actNextSect = adjSectionList[i];
if ( actNextSect.GetSectionTid() != actPQEntry->sectID )
{
//calculate the totalcost
GPoint *sectEP;
if(actPQEntry->upDownFlag)
sectEP = new GPoint(true,netId,
actNextSect.GetRid(), actNextSect.GetMeas2());
else
sectEP = new GPoint(true,netId,
actNextSect.GetRid(), actNextSect.GetMeas1());
heuristic = sectEP->Distance(end);
if(withfunc)
{//fcargs[0]=cost,fcargs[1]=duration,fcargs[2]=laenge
(*funargs)[0]=
new CcReal(true,actNextSect.GetCost());
(*funargs)[1]=
new CcReal(true,actNextSect.GetDuration());
(*funargs)[2] =
new CcReal(true,actNextSect.GetLength());
qp->Request(func.addr, funcResult);
double fr=
((CcReal*)(funcResult.addr))->GetRealval();
totalcost = fr + heuristic;
//DEBUG cout << "ERGEBNIS:" <<totalcost<<endl;
}
else
{
totalcost = actNextSect.GetCost() + heuristic;
}
sectEP->DeleteIfAllowed();
//DEBUG
//cout << "section: "<< actNextSect.GetSectionTid()
// <<"."<< actNextSect.GetUpDownFlag()
// << " heuristic: "<< heuristic<<"+ vorkosten "
// << actPQEntry->costFromStart << "+ kosten: "
// << actNextSect.GetCost() <<"=totalcost: "
// << totalcost <<endl;
PQEntry *actEntry = new PQEntry (
actNextSect.GetSectionTid(),
dist,
actNextSect.GetUpDownFlag(),
actPQEntry->sectID,
actNextSect.GetMeas1(),
actNextSect.GetMeas2(),
actNextSect.GetRid(),
totalcost );
openList->Insert ( *actEntry, closeList, true );
delete actEntry;
}
}
delete actPQEntry;
actPQEntry=0;
}//END IF the end is not reached
else //shortespath has been found
{ //Compute last route interval and resulting gline.
found = true;
double startRI, endRI;
int actRouteId =actPQEntry->rid;
if ( actPQEntry->upDownFlag == true )
{
startRI = sectMeas1;
endRI = end->GetPosition();
}
else
{
startRI = sectMeas2;
endRI = end->GetPosition();
}
//6. Get the sections used for shortest path and write them in
// right order (from start to end gpoint) in the resulting
// gline. Because Astar gives the sections from end to start
// we first have to put the result sections on a stack to turn
// in right order.
RIStack *riStack = new RIStack ( actRouteId, startRI, endRI );
TupleId endSectId = actPQEntry->sectID;
SectIDTree *pElem = closeList->Find ( actPQEntry->beforeSectID);
bool end = false;
bool upDown;
if ( startRI > endRI
|| fabs ( startRI-endRI ) < 0.1 ) upDown = false;
else upDown = true;
while ( !end )
{
//GetSection
Tuple *actSection = pNetwork->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,riStack);
else
riStack->Push(actRouteId,sectMeas2,sectMeas1,riStack);
endSectId = pElem->sectID;
pElem = closeList->Find ( pElem->beforeSectId );
}
else
{
end = true;
pNetwork->GetAdjacentSectionsInfo(
startSectTID,true, adjSectionList);
size_t i = 0;
bool stsectfound = false;
while ( i < adjSectionList.size() && !stsectfound )
{
DirectedSectionInfo adjSection = adjSectionList[i];
if ( adjSection.GetSectionTid() == endSectId )
{
if (fabs(start->GetPosition()-sectMeas2 ) > 0.1)
{
stsectfound = true;
riStack->Push(
actRouteId,start->GetPosition(),
sectMeas2,riStack );
end = true;
}
}
i++;
}
adjSectionList.clear();
if ( !stsectfound )
{
pNetwork->
GetAdjacentSectionsInfo(
startSectTID,false,adjSectionList);
i = 0;
while ( i < adjSectionList.size() && !stsectfound )
{
DirectedSectionInfo adjSection = adjSectionList[i];
if ( adjSection.GetSectionTid() == endSectId )
{
if (fabs(start->GetPosition()-sectMeas1) > 0.1)
{
stsectfound = true;
riStack->Push (
actRouteId, start->GetPosition(),
sectMeas1,riStack );
end = true;
}
}
i++;
}
adjSectionList.clear();
}
}
if ( actSection )
{
actSection->DeleteIfAllowed();
actSection = 0;
}
}
// Cleanup and return result
riStack->StackToGLine ( result );
riStack->RemoveStack();
}
if ( actPQEntry )
{
delete actPQEntry;
actPQEntry = 0;
}
}// END ELSE shortesPath has been found
//clean up
if ( closeList != 0 ) closeList->Remove();
openList->Destroy();
delete openList;
}//END ELSE Calculate the shortes path with A*
//clean up
endSection->DeleteIfAllowed();
startSection->DeleteIfAllowed();
NetworkManager::CloseNetwork ( pNetwork );
result->SetSorted ( false );
result->SetDefined ( true );
result->TrimToSize();
start->DeleteIfAllowed();
end->DeleteIfAllowed();
return true;
}
/*
Returns the x,y point represented by gpoint.
*/
void GPoint::ToPoint ( Point *&res )
{
//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 ( false );
//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 ( Network*& pNetwork ) const
{
Point *res = new Point ( false );
if ( pNetwork != 0 ) pNetwork->GetPointOnRoute ( this, res );
return res;
};
/*
Returns the bounding GPoints of the given GLine.
*/
GPoints* GLine::GetBGP ()
{
GPoints *result = new GPoints ( 0 );
if ( !IsDefined() || NoOfComponents() == 0 ) return result;
else
{
SectTree *sectionTree = 0;
RouteInterval ri;
DbArray<SectTreeEntry> *actSections = new DbArray<SectTreeEntry> ( 0 );
//Network *pNetwork = NetworkManager::GetNetwork(GetNetworkId());
Network* pNetwork = NetworkManager::GetNetworkNew ( GetNetworkId(), netList
);
bool first = true;
SectTreeEntry nEntry;
for ( int i = 0; i < Size(); i++ )
{
Get ( i,ri );
pNetwork->GetSectionsOfRouteInterval ( &ri, actSections );
for ( int j = 0; j < actSections->Size(); j++ )
{
actSections->Get ( j, nEntry );
if ( first )
{
first = false;
sectionTree = new SectTree ( &nEntry );
}
else
{
sectionTree->Insert ( &nEntry );
}
}
actSections->clean();
}
delete actSections;
sectionTree->WriteResult ( pNetwork, *result, *sectionTree );
sectionTree->Remove();
NetworkManager::CloseNetwork ( pNetwork );
result->TrimToSize();
return result;
}
};
/*
Secondo Type Constructor for class ~GPoint~
*/
TypeConstructor gpoint (
"gpoint", //name
GPoint::GPointProperty, //property function
GPoint::OutGPoint, GPoint::InGPoint, //Out and In functions
0, 0, //SaveToList and
//RestoreFromList functions
GPoint::CreateGPoint, GPoint::DeleteGPoint, //object creation/deletion
OpenAttribute<GPoint>,SaveAttribute<GPoint>,//open and save functions
GPoint::CloseGPoint, GPoint::CloneGPoint, //object close, and clone
GPoint::CastGPoint, //cast function
GPoint::SizeOfGPoint, //sizeof function
GPoint::CheckGPoint ); //kind checking function
/*
3.4 Class GPoints implemented by Jianqiu Xu
*/
string edistjoinpointlist = "(rel(tuple((pid int)(p point))))";
enum edistjoinpointlistrelation {POINTSID = 0,POINTSOBJECT};
/*
3.4.1 Constructors
*/
GPoints::GPoints():Attribute()
{}
GPoints::GPoints ( int in_iSize ) :Attribute(true),m_xGPoints ( in_iSize )
{}
GPoints::GPoints ( GPoints* in_xOther ) :
Attribute(in_xOther->IsDefined()),
m_xGPoints ( 0 )
{
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();
}
/*
3.4.2 Methods of class ~GPoints~
*/
bool GPoints::IsEmpty() const
{
return m_xGPoints.Size() == 0;
}
ostream& GPoints::Print ( ostream& os ) const
{
for ( int i = 0;i < m_xGPoints.Size();i++ )
{
GPoint pGP;
m_xGPoints.Get ( i,pGP );
os<<"GPoint:"<<i<<" rid "<<pGP.GetRouteId();
os<<" Position "<<pGP.GetPosition();
os<<" Side "<< ( int ) pGP.GetSide() <<endl;
}
return os;
}
GPoints& GPoints::operator= ( const GPoints& gps )
{
m_xGPoints.copyFrom(gps.m_xGPoints);
TrimToSize();
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;
}
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 ( int i, GPoint& pgp ) const
{
assert ( i >= 0 && i < m_xGPoints.Size() );
m_xGPoints.Get ( i,pgp );
}
ListExpr GPoints:: Property()
{
return ( nl->TwoElemList (
nl->FourElemList ( nl->StringAtom ( "Signature" ),
nl->StringAtom ( "Example Type List" ),
nl->StringAtom ( "List Rep" ),
nl->StringAtom ( "Example List" ) ),
nl->FourElemList ( nl->StringAtom ( "-> DATA" ),
nl->StringAtom ( "gpoints" ),
nl->StringAtom (
"(<gpoint1><gpoint2>...<gpointN>))" ),
nl->StringAtom ( "((1 2.0 0)(2 3.0 0))" ) ) )
);
}
ListExpr GPoints::Out ( ListExpr in_xTypeInfo,
Word in_xValue )
{
GPoints *pGPS = ( GPoints* ) in_xValue.addr;
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;
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 ) );
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();
return SetWord ( Address ( 0 ) );
}
}
correct = true;
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 ( 0 ) );
}
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 ( new GPoints ( * ( ( GPoints* ) w.addr ) ) );
}
void* GPoints::Cast ( void* addr )
{
return new ( addr ) GPoints();
}
bool GPoints::Check ( ListExpr type, ListExpr& errorInfo )
{
return ( nl->IsEqual ( type, "gpoints" ) );
}
int GPoints::Compare ( const Attribute* ) const
{
return false;
}
bool GPoints::Adjacent ( const Attribute* ) const
{
return false;
}
GPoints* GPoints::Clone() const
{
GPoints* res = new GPoints ( *this );
return res;
}
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 );
}
TypeConstructor gpoints ( "gpoints",
GPoints::Property,
GPoints::Out, GPoints::In,
0, 0,
GPoints::Create, GPoints::Delete,
GPoints::OpenGPoints, GPoints::SaveGPoints,
GPoints::Close, GPoints::CloneGPoints,
GPoints::Cast, GPoints::SizeOf,
GPoints::Check );
/*
4 Secondo Operators
4.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" &&
nl->SymbolValue ( param2 ) == "gpoint" ) ||
( nl->SymbolValue ( param1 ) == "gline" &&
nl->SymbolValue ( param2 ) == "gline" ) ) ) )
{
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 != numeric_limits<double>::max() ) 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 != numeric_limits<double>::max() ) 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" &&
nl->SymbolValue ( arg2 ) == "gpoint" )
return 0;
if ( nl->SymbolValue ( arg1 ) == "gline" &&
nl->SymbolValue ( arg2 ) == "gline" )
return 1;
return -1; // This point should never be reached
};
const string OpNetNetdistanceSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>A x A x network-> real with A = gpoint or gline" "</text--->"
"<text>netdistance(GPOINT1,GPOINT2, NETWORK)</text--->"
"<text>Calculates the network distance of two gpoints resp. glines.</text--->"
"<text>query netdistance(gp1,gp2, B_NETWORK)</text--->"
") )";
Operator networknetdistance (
"netdistance", // name
OpNetNetdistanceSpec, // specification
2,
OpNetNetdistancemap, // value mapping
OpNetNetdistanceselect, // selection function
OpNetNetdistanceTypeMap // type mapping
);
/*
4.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" ) )
{
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
const string OpGPoint2RectSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>gpoint -> rect" "</text--->"
"<text>gpoint2rect(GPOINT)</text--->"
"<text>Returns a rectangle representing the gpoint.</text--->"
"<text> gpoint2rect (gpoint) </text--->"
") )";
Operator networkgpoint2rect (
"gpoint2rect", // name
OpGPoint2RectSpec, // specification
OpGPoint2RectValueMapping, // value mapping
Operator::SimpleSelect, // selection function
OpGPoint2RectTypeMap // type mapping
);
/*
4.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" || !nl->IsAtom ( gline ) ||
nl->AtomType ( gline ) != SymbolType || nl->SymbolValue ( gline ) !=
"gline" )
{
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 ) );
return 0;
}
const string OpInsideSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>gpoint x gline -> bool" "</text--->"
"<text> _ inside _</text--->"
"<text>Returns true if gpoint is inside gline false elsewhere.</text--->"
"<text>GPOINT inside GLINE</text--->"
") )";
Operator networkinside (
"inside", // name
OpInsideSpec, // specification
OpInsideValueMap, // value mapping
Operator::SimpleSelect, // selection function
OpInsideTypeMap // type mapping
);
/*
4.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" )
{
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;
}
const string OpLengthSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>gline -> real" "</text--->"
"<text>length(_)</text--->"
"<text>Calculates the length of the gline.</text--->"
"<text>query length(gline)</text--->"
") )";
Operator networklength (
"length", // name
OpLengthSpec, // specification
OpLengthValueMap, // value mapping
Operator::SimpleSelect, // selection function
OpLengthTypeMap // type mapping
);
/*
4.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" );
}
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
const string OpLine2GLineSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>network x line -> gline" "</text--->"
"<text>sline2gline(_,_)</text--->"
"<text>Translates a line to a gline value.</text--->"
"<text>line2gline(B_NETWORK, sline)</text--->"
") )";
Operator sline2gline (
"line2gline", // name
OpLine2GLineSpec, // specification
OpLine2GLineValueMapping, // value mapping
Operator::SimpleSelect, // selection function
OpLine2GLineTypeMap // type mapping
);
/*
4.6 Operator ~=~
Returns true if two ~GPoint~s respectively ~GLine~s are identical false
elsewhere.
*/
ListExpr OpNetEqualTypeMap ( ListExpr args )
{
if ( nl->ListLength ( args ) != 2 )
{
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
}
ListExpr first = nl->First ( args );
ListExpr second = nl->Second ( args );
if ( ( nl->IsAtom ( first ) && nl->AtomType ( first ) == SymbolType &&
nl->IsAtom ( second ) && nl->AtomType ( second ) == SymbolType ) &&
( ( nl->SymbolValue ( first ) == "gpoint" &&
nl->SymbolValue ( second ) == "gpoint" ) ||
( nl->SymbolValue ( first ) == "gline" &&
nl->SymbolValue ( second ) == "gline" ) ) )
{
return nl->SymbolAtom ( CcBool::BasicType() );
}
return nl->SymbolAtom ( Symbol::TYPEERROR() );
}
int OpNetEqual_gpgp ( Word* args, Word& result, int message,
Word& local, Supplier in_pSupplier )
{
GPoint* p1 = ( GPoint* ) args[0].addr;
GPoint* p2 = ( GPoint* ) args[1].addr;
result = qp->ResultStorage ( in_pSupplier );
CcBool* pResult = ( CcBool* ) result.addr;
if ( ! ( p1->IsDefined() ) || !p2->IsDefined() )
{
cmsg.inFunError ( "Both gpoints must be defined!" );
pResult->Set ( false, false );
return 0;
};
pResult-> Set ( true, *p1 == *p2 );
return 1;
}
int OpNetEqual_glgl ( Word* args, Word& result, int message,
Word& local, Supplier in_pSupplier )
{
GLine* l1 = ( GLine* ) args[0].addr;
GLine* l2 = ( GLine* ) args[1].addr;
result = qp->ResultStorage ( in_pSupplier );
CcBool* pResult = ( CcBool* ) result.addr;
if ( ! ( l1->IsDefined() ) || !l2->IsDefined() )
{
cmsg.inFunError ( "Both glines must be defined!" );
pResult->Set ( false, false );
return 0;
};
pResult-> Set ( true, *l1 == *l2 );
return 1;
}
ValueMapping OpNetEqualmap[] =
{
OpNetEqual_gpgp,
OpNetEqual_glgl
};
int OpNetEqualselect ( ListExpr args )
{
ListExpr arg1 = nl->First ( args );
ListExpr arg2 = nl->Second ( args );
if ( nl->SymbolValue ( arg1 ) == "gpoint" &&
nl->SymbolValue ( arg2 ) == "gpoint" )
return 0;
if ( nl->SymbolValue ( arg1 ) == "gline" &&
nl->SymbolValue ( arg2 ) == "gline" )
return 1;
return -1; // This point should never be reached
};
const string OpNetEqualSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>A x A -> bool for GPoint and GLine" "</text--->"
"<text> _ = _</text--->"
"<text>Returns if two gpoints are equal.</text--->"
"<text>query gpoint1 = gpoint2</text--->"
") )";
Operator netgpequal (
"=", // name
OpNetEqualSpec, // specification
2,
OpNetEqualmap, // value mapping
OpNetEqualselect, // selection function
OpNetEqualTypeMap // type mapping
);
/*
4.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" && nl->IsAtom ( arg2 ) &&
nl->AtomType ( arg2 ) == SymbolType &&
nl->SymbolValue ( arg2 ) == "gline" )
{
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;
}
const string OpNetIntersectsSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>gline x gline -> bool" "</text--->"
"<text>intersects(gline, gline)</text--->"
"<text>Returns true if the both glines intersects false elsewhere.</text--->"
"<text>intersects(gline, gline)</text--->"
") )";
Operator networkintersects (
"intersects", // name
OpNetIntersectsSpec, // specification
OpNetIntersectsValueMapping, // value mapping
Operator::SimpleSelect, // selection function
OpNetIntersectsTypeMap // type mapping
);
/*
4.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;
}
const string OpNetworkJunctionsSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>network -> rel" "</text--->"
"<text>junctions(_)</text--->"
"<text>Return the junctions of a network.</text--->"
"<text>query junctions(network)</text--->"
") )";
Operator networkjunctions (
"junctions", // name
OpNetworkJunctionsSpec, // specification
OpNetworkJunctionsValueMapping, // value mapping
Operator::SimpleSelect, // trivial selection function
OpNetworkJunctionsTypeMap // type mapping
);
/*
4.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::routesInternalTypeInfo, 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;
}
const string OpNetworkRoutesSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>network -> rel" "</text--->"
"<text>routes(_)</text--->"
"<text>Return the routes of a network.</text--->"
"<text>query routes(network)</text--->"
") )";
Operator networkroutes (
"routes", // name
OpNetworkRoutesSpec, // specification
OpNetworkRoutesValueMapping, // value mapping
Operator::SimpleSelect, // trivial selection function
OpNetworkRoutesTypeMap // type mapping
);
/*
4.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;
}
const string OpNetworkSectionsSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>network -> rel" "</text--->"
"<text>sections(_)</text--->"
"<text>Return the sections of a network.</text--->"
"<text>query sections(network)</text--->"
") )";
Operator networksections (
"sections", // name
OpNetworkSectionsSpec, // specification
OpNetworkSectionsValueMapping, // value mapping
Operator::SimpleSelect, // trivial selection function
OpNetworkSectionsTypeMap // type mapping
);
/*
4.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 ) != 3 )
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
ListExpr xIdDesc = nl->First ( in_xArgs );
ListExpr xRoutesRelDesc = nl->Second ( in_xArgs );
ListExpr xJunctionsRelDesc = nl->Third ( in_xArgs );
if ( !nl->IsEqual ( xIdDesc, CcInt::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, "" ) );
Relation* pRoutes = ( Relation* ) args[1].addr;
Relation* pJunctions = ( Relation* ) args[2].addr;
pNetwork->Load ( iId,
pRoutes,
pJunctions );
result = SetWord ( pNetwork );
return 0;
}
const string OpNetworkTheNetworkSpec =
"((\"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\") "
"(<text>int x rel x rel -> network" "</text--->"
"<text>thenetwork(_, _, _)</text--->"
"<text>Creates network with id or next free id.</text--->"
"<text>let n = thenetwork(int, routes, junctions)</text--->"
"))";
Operator networkthenetwork (
"thenetwork", // name
OpNetworkTheNetworkSpec, // specification
OpNetworkTheNetworkValueMapping, // value mapping
Operator::SimpleSelect, // trivial selection function
OpNetworkTheNetworkTypeMap // type mapping
);
/*
4.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" )
{
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;
}
const string OpNoComponentsSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>gline -> int" "</text--->"
"<text>no_components(_)</text--->"
"<text>Returns the number of route intervals.</text--->"
"<text>query no_components(gline)</text--->"
") )";
Operator networknocomponents (
"no_components", // name
OpNoComponentsSpec, // specification
OpNoComponentsValueMapping, // value mapping
Operator::SimpleSelect, // selection function
OpNoComponentsTypeMap // type mapping
);
/*
4.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" );
}
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
const string OpPoint2GPointSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>network x point -> gpoint" "</text--->"
"<text>point2gpoint(networkobject, point)</text--->"
"<text>Translates a point to a gpoint.</text--->"
"<text>point2gpoint(b_network, point)</text--->"
") )";
Operator point2gpoint (
"point2gpoint", // name
OpPoint2GPointSpec, // specification
OpPoint2GPointValueMapping, // value mapping
Operator::SimpleSelect, // selection function
OpPoint2GPointTypeMap // type mapping
);
/*
4.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" )
{
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
const string OpGPoint2PointSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>gpoint -> point" "</text--->"
"<text>gpoint2point(gpoint)</text--->"
"<text>Translates a gpoint to a point.</text--->"
"<text>gpoint2point(gpoint)</text--->"
") )";
Operator gpoint2point (
"gpoint2point", // name
OpGPoint2PointSpec, // specification
OpGPoint2PointValueMapping, // value mapping
Operator::SimpleSelect, // selection function
OpGPoint2PointTypeMap // type mapping
);
/*
4.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" ) )
{
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" ) );
}
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 )
{
delete ( GPointList* ) local.addr;
local = SetWord ( Address ( 0 ) );
}
return 0;
}
return 0; // ignore unknown message
} //end ValueMapping
const string OpPolyGPointSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>gpoint x network -> stream(gpoint)" "</text--->"
"<text>gpoint polygpoint</text--->"
"<text>Returns the gpoint and gpoints with the same network position"
" if the gpoint is a junction.</text--->"
"<text> polygpoints (gpoint, network) </text--->"
") )";
Operator polygpoints (
"polygpoints", // name
OpPolyGPointSpec, // specification
OpPolyGPointValueMapping, // value mapping
Operator::SimpleSelect, // selection function
OpPolyGPointTypeMap // type mapping
);
/*
4.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" ) )
{
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 );
switch ( message )
{
case OPEN:
local = SetWord ( new RectangleList ( ( GLine* ) args[0].addr ) );
return 0;
case REQUEST:
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
const string OpRouteIntervalsSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>gline -> stream(rect)" "</text--->"
"<text>routeintervals(GLINE)</text--->"
"<text>Returns a stream of rectangles representing the route intervals of the"
" gline.</text--->"
"<text> routeintervals (gline) </text--->"
") )";
Operator networkrouteintervals (
"routeintervals", // name
OpRouteIntervalsSpec, // specification
OpRouteIntervalsValueMapping, // value mapping
Operator::SimpleSelect, // selection function
OpRouteIntervalsTypeMap // type mapping
);
/*
4.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 in_xArgs )
{
if ( nl->ListLength ( in_xArgs ) != 2 )
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
ListExpr xGPoint1Desc = nl->First ( in_xArgs );
ListExpr xGPoint2Desc = nl->Second ( in_xArgs );
// ListExpr xGPoint3Desc = nl->Third(in_xArgs);
if ( ( !nl->IsAtom ( xGPoint1Desc ) ) ||
nl->AtomType ( xGPoint1Desc ) != SymbolType ||
nl->SymbolValue ( xGPoint1Desc ) != "gpoint" )
{
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
}
if ( ( !nl->IsAtom ( xGPoint2Desc ) ) ||
nl->AtomType ( xGPoint2Desc ) != SymbolType ||
nl->SymbolValue ( xGPoint2Desc ) != "gpoint" )
{
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
}
//if((!nl->IsAtom(xGPoint3Desc))|| (!nl->IsEqual(xGPoint3Desc,"network"))) {
// return (nl->SymbolAtom(Symbol::TYPEERROR()));
//}
return nl->SymbolAtom ( "gline" );
}
int OpShortestPathValueMapping ( Word* args,
Word& result,
int message,
Word& local,
Supplier in_xSupplier )
{
GPoint *pFromGPoint = ( GPoint* ) args[0].addr;
GPoint *pToGPoint = ( GPoint* ) args[1].addr;
GLine* pGLine = ( GLine* ) qp->ResultStorage ( in_xSupplier ).addr;
result = SetWord ( pGLine );
pGLine->SetSorted ( false );
pGLine->SetDefined ( pFromGPoint->ShortestPath ( pToGPoint, pGLine ) );
return 0;
}
const string OpShortestPathSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>gpoint x gpoint -> gline" "</text--->"
"<text>shortest_path( _ , _)</text--->"
"<text>Calculates the shortest path between two gpoints.</text--->"
"<text>query shortest_path(x, y)</text--->"
") )";
Operator shortest_path (
"shortest_path", // name
OpShortestPathSpec, // specification
OpShortestPathValueMapping, // value mapping
Operator::SimpleSelect, // trivial selection function
OpShortestPathTypeMap // type mapping
);
/*
4.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" ) )
{
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;
}
const string OpGLine2LineSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>gline -> line" "</text--->"
"<text>gline2line(GLINE)</text--->"
"<text>Returns the line value of the gline.</text--->"
"<text> gline2line(gline) </text--->"
") )";
Operator networkgline2line (
"gline2line", // name
OpGLine2LineSpec, // specification
OpGLine2LineValueMapping, // value mapping
Operator::SimpleSelect, // selection function
OpGLine2LineTypeMap // type mapping
);
/*
4.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" )
{
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;
}
}
const string OpNetIsEmptySpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>gline -> bool" "</text--->"
"<text>isemtpy(_)</text--->"
"<text>Returns true if the gline is empty.</text--->"
"<text>query isempty(gline)</text--->"
") )";
Operator networkisempty (
"isempty", // name
OpNetIsEmptySpec, // specification
OpNetIsEmptyValueMap, // value mapping
Operator::SimpleSelect, // selection function
OpNetIsEmptyTypeMap // type mapping
);
/*
4.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" )
{
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
}
if ( !nl->IsAtom ( gline2 ) || nl->AtomType ( gline2 ) != SymbolType ||
nl->SymbolValue ( gline2 ) != "gline" )
{
return ( nl->SymbolAtom ( Symbol::TYPEERROR() ) );
}
return nl->SymbolAtom ( "gline" );
}
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;
}
const string OpNetUnionSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>gline x gline -> gline" "</text--->"
"<text>_ union _ </text--->"
"<text>Returns the sorted gline resulting of the union of both "
"gline.</text--->"
"<text>query gline1 union gline2</text--->"
") )";
Operator networkunion (
"union", // name
OpNetUnionSpec, // specification
OpNetUnionValueMap, // value mapping
Operator::SimpleSelect, // selection function
OpNetUnionTypeMap // type mapping
);
/*
4.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" &&
nl->SymbolValue ( param2 ) == "gpoint" ) ||
( nl->SymbolValue ( param1 ) == "gline" &&
nl->SymbolValue ( param2 ) == "gline" ) ) ) )
{
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
};
int OpNetDistanceselect ( ListExpr args )
{
ListExpr arg1 = nl->First ( args );
ListExpr arg2 = nl->Second ( args );
if ( nl->SymbolValue ( arg1 ) == "gpoint" &&
nl->SymbolValue ( arg2 ) == "gpoint" )
return 0;
if ( nl->SymbolValue ( arg1 ) == "gline" &&
nl->SymbolValue ( arg2 ) == "gline" )
return 1;
return -1; // This point should never be reached
};
const string OpNetDistanceSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>A x A -> real with A = gpoint or gline" "</text--->"
"<text>distance(GPOINT1,GPOINT2)</text--->"
"<text>Calculates the Euclidean Distance of gpoints resp. glines.</text--->"
"<text>query distance(gp1,gp2)</text--->"
") )";
Operator networkdistance (
"distance", // name
OpNetDistanceSpec, // specification
2,
OpNetDistancemap, // value mapping
OpNetDistanceselect, // selection function
OpNetDistanceTypeMap // type mapping
);
/*
4.22 Operator ~update\_sectioncost~
Updates the costs of one or more sections.
The oprator expects two or three arguments. The first argument should be a
network. Is the number of arguments two. The second agument should be a relation
like (rel (tuple ((sid int) (cost real)))). If the number of arguments is three,
then the second argument should be an sectionid (int) and the third argument
should be the cost of the section (real).
*/
ListExpr OpUpdateSectionCostTypeMap ( ListExpr in_xArgs ){
NList param(in_xArgs);
//check the number of arguments
if(param.length() <2 || param.length() >3)
{
return listutils::typeError(
"update_sectioncost expects either 2 or 3 arguments.");
}
ListExpr xNetworkDesc = nl->First(in_xArgs);
//check the type of the first arguments
if ( ( !nl->IsAtom ( xNetworkDesc ) ) ||
!nl->IsEqual ( xNetworkDesc, "network" ) )
{
return listutils::typeError("1.argument should be a network");
}
if (param.length() == 2)
{ //read the arguments
ListExpr xRelDesc = nl->Second(in_xArgs);
if ( !IsRelDescription ( xRelDesc ) )
{
return listutils::typeError( "2.agument should be a relation" );
}
ListExpr xType;
string costsTypeInfo = "(rel (tuple ((sid int) (cost real))))";
nl->ReadFromString ( costsTypeInfo, xType );
if ( !CompareSchemas ( xRelDesc, xType ) )
{
return listutils::typeError("the pattern of the relation ist wrong");
}
}
if ( param.length() == 3 )
{ //read the arguments
ListExpr xIdDesc = nl->Second(in_xArgs);
ListExpr xCostDesc = nl->Third(in_xArgs);
if (!nl->IsEqual(xIdDesc, CcInt::BasicType()))
{
return listutils::typeError("2.argument should be an int.");
}
if(!nl->IsEqual (xCostDesc, CcReal::BasicType()))
{
return listutils::typeError("3.argument should be an real.");
}
}
return nl->SymbolAtom ( CcBool::BasicType() );
}
int OpUpdateSectionCost_One ( Word* args, Word& result, int message,
Word& local, Supplier in_pSupplier )
{
Network* pNetwork = ( Network* ) args[0].addr;
int secId = (( CcInt* ) args[1].addr)->GetIntval();
double newCost = (( CcReal* ) args[2].addr)->GetRealval();
result = qp->ResultStorage ( in_pSupplier );
CcBool* pResult = ( CcBool* ) result.addr;
if ( pNetwork == 0 || !pNetwork->IsDefined() )
{
string strMessage = "Network is not defined.";
cerr << strMessage << endl;
sendMessage ( strMessage );
pResult->Set ( false, false );
return 0;
}
qp->SetModified(qp->GetSon(in_pSupplier,0));
pResult->Set ( true, pNetwork->UpdateSectionCost(secId,newCost));
return 0;
}
int OpUpdateSectionCost_More ( Word* args, Word& result, int message,
Word& local, Supplier in_pSupplier )
{
Network* pNetwork = ( Network* ) args[0].addr;
Relation* pCosts = ( Relation* ) args[1].addr;
result = qp->ResultStorage ( in_pSupplier );
CcBool* pResult = ( CcBool* ) result.addr;
if ( pNetwork == 0 || !pNetwork->IsDefined() )
{
string strMessage = "Network is not defined.";
cerr << strMessage << endl;
sendMessage ( strMessage );
pResult->Set ( false, false );
return 0;
}
qp->SetModified(qp->GetSon(in_pSupplier,0));
pResult->Set ( true, pNetwork->UpdateMoreSectionCost(pCosts));
return 0;
}
ValueMapping OpUpdateSectionCostMap[]=
{ OpUpdateSectionCost_One,
OpUpdateSectionCost_More
};
int OpUpdateSectionCostSelect(ListExpr in_xArgs){
NList param(in_xArgs);
//check the number of arguments
if ( param.length() == 3 ){
return 0;
}
if(param.length() == 2){
return 1;
}
return -1;
}
const string OpUpdateSectionCostSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text> network x A [x real] -> bool with A as int or as rel </text--->"
"<text> update_sectioncost(_,_,_) </text--->"
"<text>Returns true, when the Update was successful.</text--->"
"<text>query update_sectioncost(B_NETWORK,1,5.0)</text--->"
") )";
Operator update_sectioncost (
"update_sectioncost", // name
OpUpdateSectionCostSpec, // specification
2,
OpUpdateSectionCostMap, // value mapping
OpUpdateSectionCostSelect, // selection function
OpUpdateSectionCostTypeMap // type mapping
);
/*
4.23 Operator ~update\_sectionduration~
Updates the duration of one or more sections.
The oprator expects two or three arguments. The first argument should be a
network. Is the number of arguments two. The second agument should be a relation
like (rel (tuple ((sid int) (duration real)))). If the number of arguments is
three, then the second argument should be an sectionid (int) and the third
argument should be the duration of the section (real).
*/
ListExpr OpUpdateSectionDurationTypeMap ( ListExpr in_xArgs ){
NList param(in_xArgs);
//check the number of arguments
if(param.length() <2 || param.length() >3){
return listutils::typeError(
"update_sectionduration expects either 2 or 3 arguments.");
}
ListExpr xNetworkDesc = nl->First(in_xArgs);
//check the type of the first arguments
if ( ( !nl->IsAtom ( xNetworkDesc ) ) ||
!nl->IsEqual ( xNetworkDesc, "network" ) )
{
return listutils::typeError("1.argument should be a network");
}
if (param.length() == 2)
{ //read the arguments
ListExpr xRelDesc = nl->Second(in_xArgs);
if ( !IsRelDescription ( xRelDesc ) )
{
return listutils::typeError( "2.agument should be a relation" );
}
ListExpr xType;
string durationsTypeInfo = "(rel (tuple ((sid int) (duration real))))";
nl->ReadFromString ( durationsTypeInfo, xType );
if ( !CompareSchemas ( xRelDesc, xType ) )
{
return listutils::typeError("the pattern of the relation ist wrong");
}
}
if ( param.length() == 3 )
{ //read the arguments
ListExpr xIdDesc = nl->Second(in_xArgs);
ListExpr xDurationDesc = nl->Third(in_xArgs);
if (!nl->IsEqual(xIdDesc, CcInt::BasicType()))
{
return listutils::typeError("2.argument should be an int.");
}
if(!nl->IsEqual (xDurationDesc, CcReal::BasicType()))
{
return listutils::typeError("3.argument should be an real.");
}
}
return nl->SymbolAtom ( CcBool::BasicType() );
}
int OpUpdateSectionDuration_One ( Word* args, Word& result, int message,
Word& local, Supplier in_pSupplier )
{
Network* pNetwork = ( Network* ) args[0].addr;
int secId = (( CcInt* ) args[1].addr)->GetIntval();
double newDuration = (( CcReal* ) args[2].addr)->GetRealval();
result = qp->ResultStorage ( in_pSupplier );
CcBool* pResult = ( CcBool* ) result.addr;
if ( pNetwork == 0 || !pNetwork->IsDefined() )
{
string strMessage = "Network is not defined.";
cerr << strMessage << endl;
sendMessage ( strMessage );
pResult->Set ( false, false );
return 0;
}
qp->SetModified(qp->GetSon(in_pSupplier,0));
pResult->Set ( true, pNetwork->UpdateSectionDuration(secId,newDuration));
return 0;
}
int OpUpdateSectionDuration_More ( Word* args, Word& result, int message,
Word& local, Supplier in_pSupplier )
{
Network* pNetwork = ( Network* ) args[0].addr;
Relation* pDurations = ( Relation* ) args[1].addr;
result = qp->ResultStorage ( in_pSupplier );
CcBool* pResult = ( CcBool* ) result.addr;
if ( pNetwork == 0 || !pNetwork->IsDefined() )
{
string strMessage = "Network is not defined.";
cerr << strMessage << endl;
sendMessage ( strMessage );
pResult->Set ( false, false );
return 0;
}
qp->SetModified(qp->GetSon(in_pSupplier,0));
pResult->Set ( true, pNetwork->UpdateMoreSectionDuration(pDurations));
return 0;
}
ValueMapping OpUpdateSectionDurationMap[]=
{ OpUpdateSectionDuration_One,
OpUpdateSectionDuration_More
};
int OpUpdateSectionDurationSelect(ListExpr in_xArgs){
NList param(in_xArgs);
//check the number of arguments
if ( param.length() == 3 ){
return 0;
}
if(param.length() == 2){
return 1;
}
return -1;
}
const string OpUpdateSectionDurationSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text> network x A [x real] -> bool with A as int or as rel </text--->"
"<text> update_sectionduration(_,_,_) </text--->"
"<text>Returns true, when the Update was successful.</text--->"
"<text>query update_sectionduration(B_NETWORK,1,5.0)</text--->"
") )";
Operator update_sectionduration (
"update_sectionduration", // name
OpUpdateSectionDurationSpec, // specification
2,
OpUpdateSectionDurationMap, // value mapping
OpUpdateSectionDurationSelect, // selection function
OpUpdateSectionDurationTypeMap // type mapping
);
/*
4.24 Operator ~shortespath\_astarplus~
Returns the shortest path in the ~Network~ between two ~GPoint~. Using
AStar-Algorithm to compute the shortest path.
The operator expects either 2 or 3 arguments. The first and the second argument
should be a gpoint. If the number of arguments ist three, then the third
argument should be a function with three parameters.
*/
ListExpr OpShortestPathAStarPlusTypeMap ( ListExpr in_xArgs )
{
//check the number of arguments
if(nl->ListLength ( in_xArgs ) <2 || nl->ListLength ( in_xArgs ) >3){
return listutils::typeError(
"shortestpath_astarplus expects either 2 or 3 arguments.");
}
ListExpr xGPoint1Desc = nl->First (in_xArgs);
ListExpr xGPoint2Desc = nl->Second (in_xArgs);
if ( ( !nl->IsAtom ( xGPoint1Desc ) ) ||
nl->AtomType ( xGPoint1Desc ) != SymbolType ||
nl->SymbolValue ( xGPoint1Desc ) != "gpoint" )
{
return listutils::typeError("the first parameter should be a gpoint.");
}
if ( ( !nl->IsAtom ( xGPoint2Desc ) ) ||
nl->AtomType ( xGPoint2Desc ) != SymbolType ||
nl->SymbolValue ( xGPoint2Desc ) != "gpoint" )
{
return listutils::typeError("the second parameter should be a gpoint.");
}
if(nl->ListLength ( in_xArgs ) == 3)
{
ListExpr map = nl->Third(in_xArgs);
if ( nl->IsAtom( map ) || !( nl->IsEqual(nl->First(map),
Symbol::MAP()) ) )
{
return listutils::typeError(
"the third parameter should be a function.");
}
else
{
if ( nl->ListLength(map) != 5)
{
return NList::typeError(
"the third parameter should be a function with three parameter.");
}
if(!( nl->IsEqual(nl->Second(map), CcReal::BasicType()))
|| !( nl->IsEqual(nl->Third(map), CcReal::BasicType()))
|| !( nl->IsEqual(nl->Fourth(map), CcReal::BasicType())) ){
return listutils::typeError(
"one or more parameters has the wrong type, it should be a real.");
}
}
}
return nl->SymbolAtom ( "gline" );
}
int OpShortestPathAStarPlusValueMapping ( Word* args,
Word& result,
int message,
Word& local,
Supplier in_xSupplier )
{
GPoint *pFromGPoint = ( GPoint* ) args[0].addr;
GPoint *pToGPoint = ( GPoint* ) args[1].addr;
Word func = args[2].addr;
GLine* pGLine = ( GLine* ) qp->ResultStorage ( in_xSupplier ).addr;
result = SetWord ( pGLine );
pGLine->SetSorted ( false );
pGLine->SetDefined (
pFromGPoint->ShortestPathAStarPlus ( pToGPoint, pGLine, func ) );
return 0;
}
const string OpShortestPathAStarPlusSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>gpoint x gpoint [x A] -> gline with A as (map real real real real)"
"</text--->"
"<text>shortestpath_astarplus( _ , _ ,_)</t1ext--->"
"<text>Calculates the shortest path between two "
"gpoints with the astar-algorithm.</text--->"
"<text>query shortestpath_astarplus([const gpoint value(1 2 0.0 0)],"
"[const gpoint value(1 10 5.0 1)]);</text--->"
") )";
Operator shortestpath_astarplus (
"shortestpath_astarplus", // name
OpShortestPathAStarPlusSpec, // specification
OpShortestPathAStarPlusValueMapping, // value mapping
Operator::SimpleSelect, // trivial selection function
OpShortestPathAStarPlusTypeMap // type mapping
);
/*
4.25 Operator ~optimize\_network~
Optimizes the given ~network~ by all routes contained sorted by lexicographic
starting point and all sections are rearranged.
*/
ListExpr OpOptimizeNetworkTypeMap ( ListExpr in_xArgs )
{
//check the number of arguments
if(nl->ListLength ( in_xArgs ) !=1){
return listutils::typeError(
"optimize_network expects only one argument.");
}
ListExpr xNetworkDesc = nl->First(in_xArgs);
//check the type of the first arguments
if ( ( !nl->IsAtom ( xNetworkDesc ) ) ||
!nl->IsEqual ( xNetworkDesc, "network" ) )
{
return listutils::typeError("1.argument should be a network");
}
return nl->SymbolAtom ( CcBool::BasicType() );
}
int OpOptimizeNetworkValueMapping ( Word* args,
Word& result,
int message,
Word& local,
Supplier in_xSupplier )
{
Network* pNetwork = ( Network* ) args[0].addr;
result = qp->ResultStorage ( in_xSupplier );
CcBool* pResult = ( CcBool* ) result.addr;
if ( pNetwork == 0 || !pNetwork->IsDefined() )
{
string strMessage = "Network is not defined.";
cerr << strMessage << endl;
sendMessage ( strMessage );
pResult->Set ( false, false );
return 0;
}
qp->SetModified(qp->GetSon(in_xSupplier,0));
pResult->Set ( true, pNetwork->OptimizeNetwork());
return 0;
}
const string OpOptimizeNetworkSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>network -> bool)" "</text--->"
"<text>optimizenet( _ )</t1ext--->"
"<text>Optimized the storage of the sections.</text--->"
"<text>query optimize_network(B_NETWORK)]);</text--->"
") )";
Operator optimizenet (
"optimizenet", // name
OpOptimizeNetworkSpec, // specification
OpOptimizeNetworkValueMapping, // value mapping
Operator::SimpleSelect, // trivial selection function
OpOptimizeNetworkTypeMap // type mapping
);
/*
4.26 Operator ~print\_adjacencylist~
Prints infromations of routes, sections and their neighbours of the
given ~network~.
*/
ListExpr OpPrintAdjacencyListTypeMap ( ListExpr in_xArgs )
{
//check the number of arguments
if(nl->ListLength ( in_xArgs ) !=1){
return listutils::typeError(
"optimize_network expects only one argument.");
}
ListExpr xNetworkDesc = nl->First(in_xArgs);
//check the type of the first arguments
if ( ( !nl->IsAtom ( xNetworkDesc ) ) ||
!nl->IsEqual ( xNetworkDesc, "network" ) )
{
return listutils::typeError("1.argument should be a network");
}
return nl->SymbolAtom ( CcBool::BasicType() );
}
int OpPrintAdjacencyListValueMapping ( Word* args,
Word& result,
int message,
Word& local,
Supplier in_xSupplier )
{
Network* pNetwork = ( Network* ) args[0].addr;
result = qp->ResultStorage ( in_xSupplier );
CcBool* pResult = ( CcBool* ) result.addr;
if ( pNetwork == 0 || !pNetwork->IsDefined() )
{
string strMessage = "Network is not defined.";
cerr << strMessage << endl;
sendMessage ( strMessage );
pResult->Set ( false, false );
return 0;
}
pResult->Set ( true, pNetwork->PrintAdjacentSectionInfo());
return 0;
}
const string OpPrintAdjacencyListSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>network -> bool)" "</text--->"
"<text>print_adjacencylist( _ )</t1ext--->"
"<text>print the informations about the adjacent sections.</text--->"
"<text>query print_adjacencylist(B_NETWORK)]);</text--->"
") )";
Operator print_adjacencylist (
"print_adjacencylist", // name
OpPrintAdjacencyListSpec, // specification
OpPrintAdjacencyListValueMapping, // value mapping
Operator::SimpleSelect, // trivial selection function
OpPrintAdjacencyListTypeMap // type mapping
);
/*
5 Creating the ~NetworkAlgebra~
*/
class NetworkAlgebra : public Algebra
{
public:
NetworkAlgebra() : Algebra()
{
AddTypeConstructor ( &network );
AddTypeConstructor ( &gpoint );
AddTypeConstructor ( &gline );
AddTypeConstructor ( &gpoints );
gpoint.AssociateKind ( Kind::DATA() );
gline.AssociateKind ( Kind::DATA() );
network.AssociateKind ( Kind::NETWORK() );
gpoints.AssociateKind ( Kind::DATA() );
AddOperator ( &networkthenetwork );
AddOperator ( &networkroutes );
AddOperator ( &networkjunctions );
AddOperator ( &networksections );
AddOperator ( &shortest_path );
AddOperator ( &networklength );
AddOperator ( &networknetdistance );
AddOperator ( &point2gpoint );
AddOperator ( &gpoint2point );
AddOperator ( &netgpequal );
AddOperator ( &sline2gline );
AddOperator ( &networkinside );
AddOperator ( &networknocomponents );
AddOperator ( &polygpoints );
AddOperator ( &networkrouteintervals );
AddOperator ( &networkintersects );
AddOperator ( &networkgpoint2rect );
AddOperator ( &networkgline2line );
AddOperator ( &networkisempty );
AddOperator ( &networkunion );
AddOperator ( &networkdistance );
AddOperator ( &update_sectioncost);
AddOperator ( &update_sectionduration);
AddOperator ( &shortestpath_astarplus);
AddOperator ( &optimizenet);
AddOperator ( &print_adjacencylist);
}
~NetworkAlgebra() {delete netList;};
};
/*
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*
InitializeNetwork2Algebra ( NestedList* nlRef,
QueryProcessor* qpRef )
{
nl = nlRef;
qp = qpRef;
netList = new map<int,string>();
return ( new NetworkAlgebra() );
}