1523 lines
51 KiB
C++
1523 lines
51 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}}]
|
|
//[TOC] [\tableofcontents]
|
|
|
|
Started March 2012, Fabio Vald\'{e}s
|
|
|
|
[TOC]
|
|
|
|
\section{Overview}
|
|
This is the implementation of the Symbolic Trajectory Algebra.
|
|
|
|
\section{Defines and Includes}
|
|
|
|
*/
|
|
|
|
#include "RestoreTraj.h"
|
|
#include <unordered_set>
|
|
#include "Algebras/Raster2/Operators/CellIterator.h"
|
|
|
|
using namespace temporalalgebra;
|
|
using namespace std;
|
|
using namespace raster2;
|
|
|
|
namespace stj {
|
|
|
|
const int SPEED_MAX = 1000;
|
|
|
|
const int MaxspeedRaster::getMaxspeedFromRoadInfo(string roadInfo1,
|
|
string roadInfo2) {
|
|
NewPair<string, string> info(roadInfo1, roadInfo2);
|
|
if (info.first == "access" &&
|
|
(info.second == "agricultural" || info.second == "destination" ||
|
|
info.second == "private" || info.second == "yes")) {
|
|
return 30;
|
|
}
|
|
if (info.first == "bicycle" && (info.second == "designated" ||
|
|
info.second == "yes")) {
|
|
return 50;
|
|
}
|
|
if (info.first == "cycleway" && info.second == "lane") {
|
|
return 50;
|
|
}
|
|
if (info.first == "cycleway:left" && info.second == "track") {
|
|
return 50;
|
|
}
|
|
if (info.first == "foot" && (info.second == "designated" ||
|
|
info.second == "official" || info.second == "permissive" ||
|
|
info.second == "yes")) {
|
|
return 15;
|
|
}
|
|
if (info.first == "footway" && info.second == "sidewalk") {
|
|
return 15;
|
|
}
|
|
if (info.first == "highway") {
|
|
if (info.second == "bridleway" || info.second == "cycleway" ||
|
|
info.second == "tertiary" || info.second == "track" ||
|
|
info.second == "residential" || info.second == "service") {
|
|
return 50;
|
|
}
|
|
if (info.second == "footway" || info.second == "path" ||
|
|
info.second == "steps" || info.second == "living_street") {
|
|
return 15;
|
|
}
|
|
if (info.second == "motorway" || info.second == "motorway_link") {
|
|
return 200;
|
|
}
|
|
if (info.second == "primary" || info.second == "secondary") {
|
|
return 130;
|
|
}
|
|
}
|
|
if (info.first == "maxspeed" && (info.second == "10" ||
|
|
info.second == "100" || info.second == "120" || info.second == "130" ||
|
|
info.second == "20" || info.second == "30" || info.second == "40" ||
|
|
info.second == "50" || info.second == "60" || info.second == "70" ||
|
|
info.second == "80")) {
|
|
int result;
|
|
istringstream(info.second) >> result;
|
|
return result + 20;
|
|
}
|
|
if (info.first == "motor_vehicle" && (info.second == "agricultural" ||
|
|
info.second == "forestry" || info.second == "private")) {
|
|
return 50;
|
|
}
|
|
if (info.first == "service" && (info.second == "parking_aisle" ||
|
|
info.second == "driveway" || info.second == "alley")) {
|
|
return 30;
|
|
}
|
|
if (info.first == "sidewalk" && (info.second == "both" ||
|
|
info.second == "left" || info.second == "right")) {
|
|
return 15;
|
|
}
|
|
if (info.first == "vehicle" && (info.second == "agricultural" ||
|
|
info.second == "forestry" || info.second == "private")) {
|
|
return 50;
|
|
}
|
|
return SPEED_MAX;
|
|
}
|
|
|
|
const int MaxspeedRaster::getMaxspeedFromLeaf(TupleId leafinfo) {
|
|
Tuple *ntuple = 0, *tuple = 0, *atuple = 0;
|
|
ntuple = primary->GetTuple(leafinfo, false);
|
|
tuple = nrel->NestedTuple2Tuple(ntuple);
|
|
AttributeRelation *arel = (AttributeRelation*)(tuple->GetAttribute(4));
|
|
DbArray<TupleId> *ids = arel->getTupleIds();
|
|
TupleId id;
|
|
int result = SPEED_MAX, tempResult = SPEED_MAX;
|
|
for (int i = 0; i < ids->Size(); i++) {
|
|
ids->Get(i, id);
|
|
atuple = arel->getRel()->GetTuple(id, false);
|
|
if (atuple != 0) {
|
|
FText *roadInfo1 = ((FText*)(atuple->GetAttribute(0)));
|
|
FText *roadInfo2 = ((FText*)(atuple->GetAttribute(1)));
|
|
if (roadInfo1->IsDefined() && roadInfo2->IsDefined()) {
|
|
tempResult = getMaxspeedFromRoadInfo(roadInfo1->GetValue(),
|
|
roadInfo2->GetValue());
|
|
if (tempResult < result) {
|
|
result = tempResult;
|
|
}
|
|
}
|
|
atuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
ntuple->DeleteIfAllowed();
|
|
return result;
|
|
}
|
|
|
|
const int MaxspeedRaster::getMaxspeed(const RasterIndex<2> pos) {
|
|
Rectangle<2> cell = grid.getCell(pos);
|
|
R_TreeLeafEntry<2, TupleId> leaf;
|
|
int result = SPEED_MAX, tempResult = SPEED_MAX;
|
|
if (rtree->First(cell, leaf)) {
|
|
tempResult = getMaxspeedFromLeaf(leaf.info);
|
|
if (tempResult < result) {
|
|
result = tempResult;
|
|
}
|
|
}
|
|
else {
|
|
return 0; // occurs if no road is found; other values are conceivable here
|
|
}
|
|
while (rtree->Next(leaf)) {
|
|
tempResult = getMaxspeedFromLeaf(leaf.info);
|
|
if (tempResult < result) {
|
|
result = tempResult;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& o, const Tile tile) {
|
|
if (!tile.path.empty()) {
|
|
o << "<";
|
|
}
|
|
for (unsigned int i = 1; i < tile.path.size(); i++) {
|
|
o << "(" << tile.path[i-1].first << ", " << tile.path[i-1].second << "), ";
|
|
}
|
|
if (!tile.path.empty()) {
|
|
o << "(" << tile.path[tile.path.size() - 1].first << ", "
|
|
<< tile.path[tile.path.size() - 1].second << ")> ";
|
|
}
|
|
o << "(" << tile.x << ", " << tile.y << ")";
|
|
return o;
|
|
}
|
|
|
|
/*
|
|
\section{Implementation of class ~Tileareas~}
|
|
|
|
*/
|
|
Tileareas::Tileareas(const Tileareas& _src) :
|
|
raster(_src.raster), minX(_src.minX), maxX(_src.maxX), minY(_src.minY),
|
|
maxY(_src.maxY), noTransitions(_src.noTransitions), areas(_src.areas),
|
|
tileToArea(_src.tileToArea), transitions(_src.transitions),
|
|
areaFile(_src.areaFile), ttaFile(_src.ttaFile), transFile(_src.transFile) {}
|
|
|
|
Tileareas::~Tileareas() {
|
|
if (areaFile.IsOpen()) {
|
|
areaFile.Close();
|
|
}
|
|
if (ttaFile.IsOpen()) {
|
|
ttaFile.Close();
|
|
}
|
|
if (transFile.IsOpen()) {
|
|
transFile.Close();
|
|
}
|
|
}
|
|
|
|
void Tileareas::processTile(const int x, const int y, int& value) {
|
|
int rasterPos[2];
|
|
rasterPos[0] = x;
|
|
rasterPos[1] = y;
|
|
raster2::sint::index_type rasterIndex(rasterPos);
|
|
int newValue = raster->get(rasterIndex);
|
|
if (newValue == INT_MIN) {
|
|
value = newValue;
|
|
return;
|
|
}
|
|
set<NewPair<int, int> > newArea;
|
|
rasterPos[0] = x - 1;
|
|
raster2::sint::index_type leftRasterIndex(rasterPos);
|
|
int leftValue = raster->get(leftRasterIndex);
|
|
if (newValue == leftValue && y > minY && newValue == value) {//unite areas
|
|
int leftAreaNo = tileToArea.get(x - 1, y);
|
|
int lowerAreaNo = tileToArea.get(x, y - 1);
|
|
if (leftAreaNo == lowerAreaNo) { // both tiles already belong to same area
|
|
tileToArea.set(x, y, leftAreaNo);
|
|
areas[leftAreaNo].insert(NewPair<int, int>(x, y));
|
|
}
|
|
else { // move smaller area into larger area
|
|
int sourceAreaNo = (areas[leftAreaNo].size() < areas[lowerAreaNo].size()
|
|
? leftAreaNo : lowerAreaNo);
|
|
int destAreaNo = (sourceAreaNo == leftAreaNo ? lowerAreaNo : leftAreaNo);
|
|
// if (x == -1181 && y == 1549) {
|
|
// cout << sourceAreaNo << " " << destAreaNo << " | "
|
|
// << areas[sourceAreaNo].size() << " " << areas[destAreaNo].size()
|
|
// << " | ";
|
|
// }
|
|
areas[destAreaNo].insert(NewPair<int, int>(x, y));
|
|
tileToArea.set(x, y, destAreaNo);
|
|
areas[destAreaNo].insert(areas[sourceAreaNo].begin(),
|
|
areas[sourceAreaNo].end());
|
|
for (set<NewPair<int, int> >::iterator it = areas[sourceAreaNo].begin();
|
|
it != areas[sourceAreaNo].end(); it++) {
|
|
tileToArea.set(it->first, it->second, destAreaNo);
|
|
}
|
|
areas[sourceAreaNo].clear();
|
|
// if (x == -640 && y == 1815) {
|
|
// cout << areas[sourceAreaNo].size() << " " << areas[destAreaNo].size()
|
|
// << endl;
|
|
// }
|
|
}
|
|
}
|
|
else if (newValue == leftValue) { // extend area of left neighbor
|
|
int leftAreaNo = tileToArea.get(x - 1, y);
|
|
tileToArea.set(x, y, leftAreaNo);
|
|
areas[leftAreaNo].insert(NewPair<int, int>(x, y));
|
|
}
|
|
else if (y > minY && newValue == value) { // extend area of lower neighbor
|
|
int lowerAreaNo = tileToArea.get(x, y - 1);
|
|
tileToArea.set(x, y, lowerAreaNo);
|
|
areas[lowerAreaNo].insert(NewPair<int, int>(x, y));
|
|
}
|
|
else { // create new area
|
|
newArea.insert(NewPair<int, int>(x, y));
|
|
tileToArea.set(x, y, areas.size());
|
|
areas.push_back(newArea);
|
|
}
|
|
value = newValue;
|
|
}
|
|
|
|
void Tileareas::trimAreaVector() {
|
|
if (areas.empty()) {
|
|
return;
|
|
}
|
|
int last = areas.size() - 1;
|
|
for (int i = 0; i < (int)areas.size(); i++) {
|
|
if (areas[i].empty()) {
|
|
while (areas[last].empty() && last > i) {
|
|
areas.pop_back();
|
|
last--;
|
|
}
|
|
for (set<NewPair<int, int> >::iterator it = areas[last].begin();
|
|
it != areas[last].end(); it++) {
|
|
areas[i].insert(areas[i].end(), *it);
|
|
tileToArea.set(it->first, it->second, i);
|
|
}
|
|
last--;
|
|
areas.pop_back();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Tileareas::recordAreaTransitions(const int x, const int y) {
|
|
// cout << "rAT(" << x << ", " << y << ")" << endl;
|
|
int rasterPos[2], rasterNeighbor[2];
|
|
rasterPos[0] = x;
|
|
rasterPos[1] = y;
|
|
raster2::sint::index_type rasterIndex(rasterPos);
|
|
int value = raster->get(rasterIndex);
|
|
if (value == INT_MIN) {
|
|
return;
|
|
}
|
|
int areaNo = tileToArea.get(x, y);
|
|
int neighborAreaNo = -1;
|
|
Tile tile(x, y);
|
|
for (int dir = 0; dir <= 7; dir++) {
|
|
DirectionNum dirNum = static_cast<DirectionNum>(dir);
|
|
Tile neighborTile = tile.moveTo(dirNum);
|
|
if (belongsToRaster(neighborTile.x, neighborTile.y)) {
|
|
rasterNeighbor[0] = neighborTile.x;
|
|
rasterNeighbor[1] = neighborTile.y;
|
|
raster2::sint::index_type rasterIndexNeighbor(rasterNeighbor);
|
|
int neighborValue = raster->get(rasterIndexNeighbor);
|
|
if (value != neighborValue && neighborValue != INT_MIN) {
|
|
neighborAreaNo = tileToArea.get(neighborTile.x, neighborTile.y);
|
|
transitions[areaNo][dir].insert(neighborAreaNo);
|
|
noTransitions++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Tileareas::retrieveAreas(raster2::sint *_raster) {
|
|
raster = _raster;
|
|
raster2::grid2 grid = raster->getGrid();
|
|
Rectangle<2> bbox = raster->bbox();
|
|
raster2::RasterIndex<2> minIndex = grid.getIndex(bbox.MinD(0), bbox.MinD(1));
|
|
raster2::RasterIndex<2> maxIndex = grid.getIndex(bbox.MaxD(0), bbox.MaxD(1));
|
|
minX = minIndex[0];
|
|
maxX = maxIndex[0];
|
|
minY = minIndex[1];
|
|
maxY = maxIndex[1];
|
|
areas.clear();
|
|
tileToArea.initialize(minX, maxX, minY, maxY, -1);
|
|
int tileValue = INT_MIN;
|
|
for (int i = minX; i <= maxX; i++) {
|
|
for (int j = minY; j <= maxY; j++) {
|
|
processTile(i, j, tileValue);
|
|
}
|
|
}
|
|
trimAreaVector();
|
|
transitions.resize(areas.size(), std::vector<std::set<int> >(8));
|
|
cout << areas.size() << " areas successfully retrieved" << endl;
|
|
for (int i = minX; i <= maxX; i++) {
|
|
for (int j = minY; j <= maxY; j++) {
|
|
recordAreaTransitions(i, j);
|
|
}
|
|
}
|
|
cout << transitions.size() << " transitions found" << endl;
|
|
}
|
|
|
|
void Tileareas::print(const bool printRange, const bool printAreas,
|
|
const bool printTileToArea, const bool printTransitions) {
|
|
if (printRange) {
|
|
cout << "Tile range: " << "(" << minX << ", " << minY << ") -- (" << maxX
|
|
<< ", " << maxY << ")" << endl;
|
|
}
|
|
if (printAreas) {
|
|
cout << areas.size() << " areas." << endl;
|
|
for (unsigned int i = 0; i < areas.size(); i++) {
|
|
cout << " area # " << i << ": ";
|
|
for (set<NewPair<int, int> >::iterator it = areas[i].begin();
|
|
it != areas[i].end(); it++) {
|
|
cout << "(" << it->first << ", " << it->second << ") ";
|
|
}
|
|
cout << endl;
|
|
}
|
|
}
|
|
if (printTileToArea) {
|
|
cout << "tileToArea:" << endl;
|
|
for (int i = minX; i <= maxX; i++) {
|
|
for (int j = minY; j <= maxY; j++) {
|
|
cout << "(" << i << ", " << j << ") --> " << tileToArea.get(i, j)
|
|
<< " ";
|
|
}
|
|
}
|
|
cout << endl;
|
|
}
|
|
if (printTransitions) {
|
|
cout << noTransitions << " transitions:" << endl;
|
|
for (unsigned int i = 0; i < transitions.size(); i++) {
|
|
for (int j = 0; j < 8; j++) {
|
|
if (!transitions[i][j].empty()) {
|
|
cout << i << " --"
|
|
<< RestoreTrajLI::dirNumToString(static_cast<DirectionNum>(j))
|
|
<< "-> {";
|
|
for (set<int>::iterator it = transitions[i][j].begin();
|
|
it != transitions[i][j].end(); it++) {
|
|
cout << *it << ", ";
|
|
}
|
|
cout << "} ";
|
|
}
|
|
}
|
|
}
|
|
cout << endl;
|
|
}
|
|
}
|
|
|
|
void Tileareas::getNodeSeqFromNodesBTree(BTree* btree, const int startNode,
|
|
NewPair<vector<int>, vector<int> >& seqs) {
|
|
bool first = seqs.first.empty();
|
|
if (!first && !seqs.second.empty()) {
|
|
return;
|
|
}
|
|
CcInt *cclookup = new CcInt(true, startNode);
|
|
bool nextSectionExists = true;
|
|
int nextId = INT_MIN;
|
|
while (nextSectionExists) {
|
|
BTreeIterator_t<unsigned int> *bit = btree->ExactMatch(cclookup);
|
|
if (bit->Next()) {
|
|
nextId = bit->GetId();
|
|
if (first) {
|
|
seqs.first.push_back(nextId);
|
|
}
|
|
else {
|
|
seqs.second.push_back(nextId);
|
|
}
|
|
}
|
|
else {
|
|
nextSectionExists = false;
|
|
}
|
|
delete bit;
|
|
cclookup->Set(nextId);
|
|
}
|
|
cclookup->DeleteIfAllowed();
|
|
}
|
|
|
|
void Tileareas::getSegmentsFromNodesBTree(BTree *btree, Relation *nodesRel,
|
|
vector<int>& nodeSeq, vector<HalfSegment>& segments) {
|
|
if (nodeSeq.size() <= 1) {
|
|
return;
|
|
}
|
|
bool nextNodeExists = true;
|
|
unsigned int nodeCounter = 0;
|
|
int nextId = nodeSeq[nodeCounter];
|
|
CcInt *cclookup = new CcInt(true, nextId);
|
|
Point startPt(true), endPt(true);
|
|
Tuple *tuple = 0;
|
|
BTreeIterator_t<unsigned int> *bit = btree->ExactMatch(cclookup);
|
|
if (bit->Next()) {
|
|
tuple = nodesRel->GetTuple(bit->GetId(), false);
|
|
startPt.CopyFrom((Point*)(tuple->GetAttribute(3)));
|
|
}
|
|
else {
|
|
nextNodeExists = false;
|
|
}
|
|
delete bit;
|
|
while (nextNodeExists) {
|
|
BTreeIterator_t<unsigned int> *bit = btree->ExactMatch(cclookup);
|
|
if (bit->Next()) {
|
|
Tuple *tuple = nodesRel->GetTuple(bit->GetId(), false);
|
|
endPt.CopyFrom((Point*)(tuple->GetAttribute(3)));
|
|
if (!AlmostEqual(startPt, endPt)) {
|
|
HalfSegment hs(true, startPt, endPt);
|
|
segments.push_back(hs);
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
startPt = endPt;
|
|
}
|
|
else {
|
|
nextNodeExists = false;
|
|
}
|
|
delete bit;
|
|
nodeCounter++;
|
|
if (nodeCounter < nodeSeq.size()) {
|
|
nextId = nodeSeq[nodeCounter];
|
|
}
|
|
else {
|
|
nextNodeExists = false;
|
|
}
|
|
cclookup->Set(nextId);
|
|
}
|
|
cclookup->DeleteIfAllowed();
|
|
}
|
|
|
|
void Tileareas::recordRoadCourses(raster2::sint *_raster) {
|
|
cout << "Start recording road courses" << endl;
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
Word roadsPtr, roadsIndexPtr, nodesPtr, nodesBTreePtr;
|
|
bool isDefined;
|
|
if (!sc->GetObject("RoadsB", roadsPtr, isDefined)) {
|
|
cout << "Object RoadsB does not exist." << endl;
|
|
return;
|
|
}
|
|
if (!isDefined) {
|
|
cout << "Object RoadsB is undefined." << endl;
|
|
return;
|
|
}
|
|
if (!sc->GetObject("Nodes", nodesPtr, isDefined)) {
|
|
cout << "Object Nodes does not exist." << endl;
|
|
return;
|
|
}
|
|
if (!isDefined) {
|
|
cout << "Object Nodes is undefined." << endl;
|
|
return;
|
|
}
|
|
if (!sc->GetObject("Nodes_NodeIdNew_btree", nodesBTreePtr, isDefined)) {
|
|
cout << "Object Nodes_NodeIdNew_btree does not exist." << endl;
|
|
return;
|
|
}
|
|
if (!isDefined) {
|
|
cout << "Object Nodes_NodeIdNew_btree is undefined." << endl;
|
|
return;
|
|
}
|
|
map<string, set<NewPair<int, int> > > motorwayParts;
|
|
map<string, BTree*> nodeIdIndexes;
|
|
map<string, NewPair<vector<int>, vector<int> > > nodeSeqs; // both directions
|
|
map<string, NewPair<vector<HalfSegment>, vector<HalfSegment> > > segments;
|
|
NestedRelation *roadsNRel = static_cast<NestedRelation*>(roadsPtr.addr);
|
|
Relation *nodesRel = static_cast<Relation*>(nodesPtr.addr);
|
|
BTree *nodesBTree = static_cast<BTree*>(nodesBTreePtr.addr);
|
|
Tuple *tuple = 0, *ntuple = 0, *atuple = 0, *atuple1 = 0;
|
|
TupleId tid;
|
|
Relation *roadsRel = roadsNRel->getPrimary();
|
|
GenericRelationIterator *rit = roadsRel->MakeScan();
|
|
HalfSegment hs;
|
|
Geoid geoid(Geoid::WGS1984);
|
|
RoadCourse roadCourse;
|
|
string motorwayName;
|
|
while ((ntuple = rit->GetNextTuple()) != 0) {
|
|
bool isHighway = false;
|
|
tuple = roadsNRel->NestedTuple2Tuple(ntuple);
|
|
AttributeRelation *arel = (AttributeRelation*)(tuple->GetAttribute(4));
|
|
DbArray<TupleId> *wtkTids = arel->getTupleIds();
|
|
int i = 0;
|
|
while (i < wtkTids->Size()) { // check waytagkeys for highway and name
|
|
wtkTids->Get(i, tid);
|
|
atuple = arel->getRel()->GetTuple(tid, false);
|
|
if (atuple != 0) {
|
|
FText *roadInfo1 = ((FText*)(atuple->GetAttribute(0)));
|
|
FText *roadInfo2 = ((FText*)(atuple->GetAttribute(1)));
|
|
if (roadInfo1->IsDefined() && roadInfo2->IsDefined()) {
|
|
if (roadInfo1->GetValue() == "highway") {
|
|
if (roadInfo2->GetValue() == "motorway") {
|
|
isHighway = true;
|
|
}
|
|
}
|
|
else if (roadInfo1->GetValue() == "ref") {
|
|
motorwayName = roadInfo2->GetValue();
|
|
}
|
|
}
|
|
}
|
|
atuple->DeleteIfAllowed();
|
|
i++;
|
|
}
|
|
if (isHighway) { // find and store motorway nodes (start/end node ids)
|
|
Line *curve = (Line*)(tuple->GetAttribute(2));
|
|
SimpleLine scurve(*curve);
|
|
NewPair<int, int> nodes(INT_MIN, INT_MIN);
|
|
if (scurve.IsDefined() && !motorwayName.empty()) {
|
|
if (scurve.BoundingBox().Intersects(raster->bbox())) {
|
|
AttributeRelation *arel2 =
|
|
(AttributeRelation*)(tuple->GetAttribute(1));
|
|
DbArray<TupleId> *nodeTids = arel2->getTupleIds();
|
|
// cout << "section of " << motorwayName << " has "
|
|
// << nodeTids->Size() << " nodes" << endl;
|
|
if (nodeTids->Size() > 1) { // less than 2 nodes: ignore
|
|
for (int i = 0; i < nodeTids->Size(); i++) {
|
|
nodeTids->Get(i, tid);
|
|
atuple1 = arel2->getRel()->GetTuple(tid, false);
|
|
if (atuple1 != 0) {
|
|
CcInt *cccount = ((CcInt*)(atuple1->GetAttribute(3)));
|
|
CcInt *ccnode = ((CcInt*)(atuple1->GetAttribute(2)));
|
|
if (ccnode->IsDefined() && cccount->IsDefined()) {
|
|
int nodeId(ccnode->GetValue()),nodeCount(cccount->GetValue());
|
|
if (nodeCount == 0) {
|
|
nodes.first = nodeId;
|
|
}
|
|
if (nodeCount == nodeTids->Size() - 1) {
|
|
nodes.second = nodeId;
|
|
}
|
|
}
|
|
}
|
|
atuple1->DeleteIfAllowed();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (nodes.first != INT_MIN && nodes.second != INT_MIN) {
|
|
motorwayParts[motorwayName].insert(nodes);
|
|
}
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
for (map<string, set<NewPair<int, int> > >::iterator it =
|
|
motorwayParts.begin(); it != motorwayParts.end(); it++) {
|
|
nodeIdIndexes[it->first] = new BTree(SmiKey::Integer);
|
|
cout << it->first << ": " << endl;
|
|
map<int, int> nodeCounter; // start +2, end +1
|
|
for (set<NewPair<int, int> >::iterator it1 = it->second.begin();
|
|
it1 != it->second.end(); it1++) {
|
|
if (nodeCounter.find(it1->first) != nodeCounter.end()) { // start existing
|
|
nodeCounter[it1->first] += 2;
|
|
}
|
|
else { // start not found before
|
|
nodeCounter[it1->first] = 2;
|
|
}
|
|
if (nodeCounter.find(it1->second) != nodeCounter.end()) { // end existing
|
|
nodeCounter[it1->second] += 1;
|
|
}
|
|
else { // end not found before
|
|
nodeCounter[it1->second] = 1;
|
|
}
|
|
nodeIdIndexes[it->first]->Append(it1->first, it1->second);
|
|
}
|
|
for (map<int, int>::iterator it2 = nodeCounter.begin();
|
|
it2 != nodeCounter.end(); it2++) {
|
|
if (it2->second == 1) {
|
|
// cout << " ...node " << it2->first << " is only end node" << endl;
|
|
}
|
|
if (it2->second == 2) {
|
|
// cout << " ...node " << it2->first << " is only start node" << endl;
|
|
getNodeSeqFromNodesBTree(nodeIdIndexes[it->first], it2->first,
|
|
nodeSeqs[it->first]);
|
|
}
|
|
}
|
|
}
|
|
for (map<string, BTree*>::iterator it = nodeIdIndexes.begin();
|
|
it != nodeIdIndexes.end(); it++) {
|
|
if (it->second != 0) {
|
|
delete it->second;
|
|
}
|
|
}
|
|
for (map<string, NewPair<vector<int>, vector<int> > >::iterator it
|
|
= nodeSeqs.begin(); it != nodeSeqs.end(); it++) {
|
|
getSegmentsFromNodesBTree(nodesBTree, nodesRel, it->second.first,
|
|
segments[it->first].first);
|
|
getSegmentsFromNodesBTree(nodesBTree, nodesRel, it->second.second,
|
|
segments[it->first].second);
|
|
// cout << "Segments created for " << it->first << endl;
|
|
}
|
|
for (map<string, NewPair<vector<HalfSegment>,vector<HalfSegment> > >::iterator
|
|
it = segments.begin(); it != segments.end(); it++) {
|
|
// cout << it->first << ": " << it->second.first.size() << ", "
|
|
// << it->second.second.size() << endl;
|
|
RoadCourse rc1, rc2;
|
|
processRoadCourse(it->second.first, rc1);
|
|
if (!rc1.dirSeq.IsEmpty() || !rc1.heightSeq.IsEmpty()) {
|
|
roadCourses.push_back(rc1);
|
|
}
|
|
processRoadCourse(it->second.second, rc2);
|
|
if (!rc2.dirSeq.IsEmpty() || !rc2.heightSeq.IsEmpty()) {
|
|
roadCourses.push_back(rc2);
|
|
}
|
|
}
|
|
cout << "height & dir written for " << roadCourses.size() << " ways" << endl;
|
|
// for (unsigned int i = 0; i < roadCourses.size(); i++) {
|
|
// cout << "Directions:" << roadCourses[i].dirSeq << endl << "Heights:"
|
|
// << roadCourses[i].heightSeq << endl << endl << endl;
|
|
// }
|
|
if (!createRoadCourseRelation("RoadCourses")) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
bool Tileareas::createRoadCourseRelation(const string& name) {
|
|
TupleType *tt = getTupleType();
|
|
Relation *roadCourseRel = new Relation(tt);
|
|
for (unsigned int i = 0; i < roadCourses.size(); i++) {
|
|
Tuple *tuple = new Tuple(tt);
|
|
CcInt *pos = new CcInt(true, i);
|
|
tuple->PutAttribute(0, pos);
|
|
tuple->PutAttribute(1, &(roadCourses[i].heightSeq));
|
|
tuple->PutAttribute(2, &(roadCourses[i].dirSeq));
|
|
roadCourseRel->AppendTuple(tuple);
|
|
}
|
|
tt->DeleteIfAllowed();
|
|
cout << "relation with " << roadCourseRel->GetNoTuples() << " tuples created"
|
|
<< endl;
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
if (sc->IsObjectName(name)) {
|
|
cout << "relation \"" << name << " already exists" << endl;
|
|
return false;
|
|
}
|
|
string errMsg = "error";
|
|
if (!sc->IsValidIdentifier(name, errMsg, true)) {
|
|
cout << errMsg << endl;
|
|
return false;
|
|
}
|
|
if (sc->IsSystemObject(name)) {
|
|
cout << name << " is a reserved name" << endl;
|
|
return false;
|
|
}
|
|
ListExpr type = nl->TwoElemList(nl->SymbolAtom(Relation::BasicType()),
|
|
getTupleTypeInfo());
|
|
Word relWord;
|
|
relWord.setAddr(roadCourseRel);
|
|
sc->InsertObject(name, "", type, relWord, true);
|
|
return true;
|
|
}
|
|
|
|
TupleType* Tileareas::getTupleType() {
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
ListExpr resultTupleType = getTupleTypeInfo();
|
|
ListExpr numResultTupleType = sc->NumericType(resultTupleType);
|
|
return new TupleType(numResultTupleType);
|
|
}
|
|
|
|
ListExpr Tileareas::getTupleTypeInfo() {
|
|
return nl->TwoElemList(nl->SymbolAtom(Tuple::BasicType()),
|
|
nl->ThreeElemList(nl->TwoElemList(nl->SymbolAtom("No"),
|
|
nl->SymbolAtom(CcInt::BasicType())),
|
|
nl->TwoElemList(nl->SymbolAtom("Height"),
|
|
nl->SymbolAtom(MLabel::BasicType())),
|
|
nl->TwoElemList(nl->SymbolAtom("Direction"),
|
|
nl->SymbolAtom(MLabel::BasicType()))));
|
|
}
|
|
|
|
void Tileareas::processRoadCourse(const vector<HalfSegment>& segments,
|
|
RoadCourse& rc) {
|
|
rc.clear();
|
|
if (segments.empty()) {
|
|
return;
|
|
}
|
|
Geoid geoid(Geoid::WGS1984);
|
|
string dirStr, lastDirStr;
|
|
raster2::RasterIndex<2> from, to;
|
|
int height(INT_MIN), lastHeight(INT_MIN);
|
|
grid2::index_type cell1, cell2, cellBetween;
|
|
Point pt1(true), pt2(true);
|
|
for (unsigned int i = 0; i < segments.size(); i++) {
|
|
pt1 = segments[i].GetDomPoint();
|
|
pt2 = segments[i].GetSecPoint();
|
|
// process direction
|
|
double dir = pt1.Direction(pt2, false, &geoid);
|
|
string dirStr =
|
|
RestoreTrajLI::dirNumToString(RestoreTrajLI::dirDoubleToNum(dir));
|
|
rc.addDir(pt1, dirStr, dirStr != lastDirStr);
|
|
lastDirStr = dirStr;
|
|
// process height(s)
|
|
cell1 = raster->getGrid().getIndex(pt1.GetX(), pt1.GetY());
|
|
cell2 = raster->getGrid().getIndex(pt2.GetX(), pt2.GetY());
|
|
if (cell1 == cell2) {
|
|
height = raster->atlocation(pt1.GetX(), pt1.GetY());
|
|
if (height != INT_MIN) {
|
|
rc.addHeight(cell1, height, height != lastHeight);
|
|
lastHeight = height;
|
|
}
|
|
}
|
|
else {
|
|
CellIterator it(raster->getGrid(), pt1.GetX(), pt1.GetY(), pt2.GetX(),
|
|
pt2.GetY());
|
|
double dx = pt2.GetX() - pt1.GetX();
|
|
double dy = pt2.GetY() - pt1.GetY();
|
|
while (it.hasNext()) {
|
|
pair<double, double> p = it.next();
|
|
double delta = (p.first + p.second) / 2.0;
|
|
height = raster->atlocation(pt1.GetX() + delta*dx,
|
|
pt1.GetY() + delta*dy);
|
|
if (height != INT_MIN) {
|
|
cellBetween = raster->getGrid().getIndex(pt1.GetX() + delta*dx,
|
|
pt1.GetY() + delta*dy);
|
|
rc.addHeight(cellBetween, height, height != lastHeight);
|
|
lastHeight = height;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
void Tileareas::deleteFiles() {
|
|
areaFile.Close();
|
|
areaFile.Drop();
|
|
ttaFile.Close();
|
|
ttaFile.Drop();
|
|
transFile.Close();
|
|
transFile.Drop();
|
|
}
|
|
|
|
ListExpr Tileareas::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("-> SIMPLE"),
|
|
nl->StringAtom(Tileareas::BasicType()),
|
|
nl->StringAtom("No list representation"),
|
|
nl->StringAtom("No example available"))));
|
|
}
|
|
|
|
ListExpr Tileareas::Out(ListExpr typeInfo, Word value) {
|
|
return nl->SymbolAtom("No list representation");
|
|
}
|
|
|
|
Word Tileareas::In(const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct) {
|
|
Word res((void*)0);
|
|
correct = true;
|
|
return res;
|
|
}
|
|
|
|
Word Tileareas::Create(const ListExpr typeInfo) {
|
|
Word w;
|
|
w.addr = (new Tileareas(0));
|
|
return w;
|
|
}
|
|
|
|
void Tileareas::Delete(const ListExpr typeInfo, Word& w) {
|
|
Tileareas *t = (Tileareas*)w.addr;
|
|
// t->deleteFiles();
|
|
delete t;
|
|
w.addr = 0;
|
|
}
|
|
|
|
bool Tileareas::Open(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value) {
|
|
Tileareas *ta = new Tileareas(true);
|
|
unsigned int noAreas, noTiles, pos(0);
|
|
char *buffer = 0;
|
|
int areaNo;
|
|
SmiRecord aRecord, ttaRecord, trRecord;
|
|
SmiRecordId aRecordId, ttaRecordId, trRecordId;
|
|
SmiFileId aFileId, ttaFileId, trFileId;
|
|
// load min, max, fileIds, recordIds
|
|
if (!valueRecord.Read(&(ta->minX), sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
if (!valueRecord.Read(&(ta->maxX), sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
if (!valueRecord.Read(&(ta->minY), sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
if (!valueRecord.Read(&(ta->maxY), sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
if (!valueRecord.Read(&aRecordId, sizeof(SmiRecordId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiRecordId);
|
|
if (!valueRecord.Read(&aFileId, sizeof(SmiFileId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiFileId);
|
|
if (!valueRecord.Read(&ttaRecordId, sizeof(SmiRecordId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiRecordId);
|
|
if (!valueRecord.Read(&ttaFileId, sizeof(SmiFileId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiFileId);
|
|
if (!valueRecord.Read(&trRecordId, sizeof(SmiRecordId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiRecordId);
|
|
if (!valueRecord.Read(&trFileId, sizeof(SmiFileId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiFileId);
|
|
ta->areaFile.Open(aFileId);
|
|
ta->ttaFile.Open(ttaFileId);
|
|
ta->transFile.Open(trFileId);
|
|
// load areas
|
|
ta->areaFile.SelectRecord(aRecordId, aRecord);
|
|
buffer = new char[aRecord.Size()];
|
|
if (aRecord.Read(buffer, aRecord.Size()) == 0) {
|
|
return false;
|
|
}
|
|
memcpy(&noAreas, buffer + pos, sizeof(unsigned int));
|
|
pos += sizeof(unsigned int);
|
|
for (unsigned int i = 0; i < noAreas; i++) {
|
|
memcpy(&noTiles, buffer + pos, sizeof(unsigned int));
|
|
pos += sizeof(unsigned int);
|
|
set<NewPair<int, int> > area;
|
|
NewPair<int, int> tile;
|
|
for (unsigned int j = 0; j < noTiles; j++) {
|
|
memcpy(&tile, buffer + pos, sizeof(NewPair<int, int>));
|
|
pos += sizeof(NewPair<int, int>);
|
|
area.insert(tile);
|
|
}
|
|
ta->areas.push_back(area);
|
|
}
|
|
delete[] buffer;
|
|
pos = 0;
|
|
// load tileToArea
|
|
ta->tileToArea.initialize(ta->minX, ta->maxX, ta->minY, ta->maxY, -1);
|
|
ta->ttaFile.SelectRecord(ttaRecordId, ttaRecord);
|
|
buffer = new char[ttaRecord.Size()];
|
|
if (ttaRecord.Read(buffer, ttaRecord.Size()) == 0) {
|
|
return false;
|
|
}
|
|
for (int i = ta->minX; i <= ta->maxX; i++) {
|
|
for (int j = ta->minY; j <= ta->maxY; j++) {
|
|
memcpy(&areaNo, buffer + pos, sizeof(int));
|
|
pos += sizeof(int);
|
|
ta->tileToArea.set(i, j, areaNo);
|
|
}
|
|
}
|
|
delete[] buffer;
|
|
pos = 0;
|
|
// load transitions
|
|
ta->transitions.resize(ta->areas.size(), std::vector<std::set<int> >(8));
|
|
ta->transFile.SelectRecord(trRecordId, trRecord);
|
|
buffer = new char[trRecord.Size()];
|
|
if (trRecord.Read(buffer, trRecord.Size()) == 0) {
|
|
return false;
|
|
}
|
|
int dir(0);
|
|
unsigned int sourceAreaNo = 0;
|
|
vector<set<int> > transitionSets;
|
|
set<int> newAreas;
|
|
while (pos < trRecord.Size()) {
|
|
memcpy(&areaNo, buffer + pos, sizeof(int));
|
|
pos += sizeof(int);
|
|
if (areaNo == INT_MAX) { // symbol for next direction / next source area
|
|
transitionSets.push_back(newAreas);
|
|
newAreas.clear();
|
|
dir++;
|
|
if (dir == 8) { // proceed to next source area and first direction
|
|
ta->transitions[sourceAreaNo] = transitionSets;
|
|
sourceAreaNo++;
|
|
transitionSets.clear();
|
|
dir = 0;
|
|
}
|
|
}
|
|
else { // extend current set of target areas
|
|
newAreas.insert(areaNo);
|
|
ta->noTransitions++;
|
|
}
|
|
}
|
|
delete[] buffer;
|
|
// cout << *(ta->areas[2].begin()) << " | " << ta->tileToArea.get(-653, 1820)
|
|
// << " | " << *(ta->transitions[2][0].begin()) << " "
|
|
// << *(ta->transitions[2][4].begin()) << endl;
|
|
unsigned int noRoadCourses, noDirCourses, noHeightCourses;
|
|
double xCoord, yCoord;
|
|
int rasterIndexPos[2];
|
|
RoadCourse rc;
|
|
if (!valueRecord.Read(&noRoadCourses, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
for (unsigned int i = 0; i < noRoadCourses; i++) {
|
|
rc.clear();
|
|
if (!valueRecord.Read(&noDirCourses, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
for (unsigned int j = 0; j < noDirCourses; j++) {
|
|
if (!valueRecord.Read(&pos, sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
if (!valueRecord.Read(&xCoord, sizeof(double), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(double);
|
|
if (!valueRecord.Read(&yCoord, sizeof(double), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(double);
|
|
Point pt(true, xCoord, yCoord);
|
|
NewPair<int, Point> dirCourseElement(pos, pt);
|
|
rc.dirCourse.push_back(dirCourseElement);
|
|
}
|
|
if (!valueRecord.Read(&noHeightCourses, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
for (unsigned int j = 0; j < noHeightCourses; j++) {
|
|
if (!valueRecord.Read(&pos, sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
if (!valueRecord.Read(&rasterIndexPos[0], sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
if (!valueRecord.Read(&rasterIndexPos[1], sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
raster2::RasterIndex<2> rIndex(rasterIndexPos);
|
|
NewPair<int, raster2::RasterIndex<2> > heightCourseElement(pos, rIndex);
|
|
rc.heightCourse.push_back(heightCourseElement);
|
|
}
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
ListExpr mlabelType = nl->SymbolAtom(MLabel::BasicType());
|
|
ListExpr mlabelTypeInfo = sc->NumericType(mlabelType);
|
|
MLabel *dirCourse = (MLabel*)(MLabel::Open(valueRecord, offset,
|
|
mlabelTypeInfo));
|
|
MLabel *heightCourse = (MLabel*)(MLabel::Open(valueRecord, offset,
|
|
mlabelTypeInfo));
|
|
MLabel dc(*dirCourse), hc(*heightCourse);
|
|
rc.dirSeq = dc;
|
|
rc.heightSeq = hc;
|
|
ta->roadCourses.push_back(rc);
|
|
}
|
|
value.addr = ta;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~Save~}
|
|
|
|
*/
|
|
|
|
bool Tileareas::Save(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value) {
|
|
Tileareas *ta = static_cast<Tileareas*>(value.addr);
|
|
SmiRecord aRecord, ttaRecord, trRecord;
|
|
SmiRecordId aRecordId, ttaRecordId, trRecordId;
|
|
// cout << *(ta->areas[2].begin()) << " | " << ta->tileToArea.get(-650, 1820)
|
|
// << " | " << *(ta->transitions[2][0].begin()) << " "
|
|
// << *(ta->transitions[2][4].begin()) << endl;
|
|
ta->areaFile.Create();
|
|
ta->ttaFile.Create();
|
|
ta->transFile.Create();
|
|
ta->print(true, false, false, false);
|
|
// store min, max
|
|
if (!valueRecord.Write(&(ta->minX), sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
if (!valueRecord.Write(&(ta->maxX), sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
if (!valueRecord.Write(&(ta->minY), sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
if (!valueRecord.Write(&(ta->maxY), sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
// store areas
|
|
size_t bufferSize = (ta->areas.size() + 1) * sizeof(unsigned int)
|
|
+ (ta->maxX - ta->minX + 1) * (ta->maxY - ta->minY + 1) * 2 * sizeof(int);
|
|
char* buffer = new char[bufferSize];
|
|
size_t pos = 0;
|
|
int maxint = INT_MAX;
|
|
unsigned int noAreas = ta->areas.size();
|
|
cout << "begin storing " << noAreas << " areas" << endl;
|
|
memcpy(buffer + pos, &noAreas, sizeof(unsigned int));
|
|
pos += sizeof(unsigned int);
|
|
for (unsigned int i = 0; i < ta->areas.size(); i++) {
|
|
unsigned int noTiles = ta->areas[i].size();
|
|
memcpy(buffer + pos, &noTiles, sizeof(unsigned int));
|
|
pos += sizeof(unsigned int);
|
|
for (set<NewPair<int, int> >::iterator it = ta->areas[i].begin();
|
|
it != ta->areas[i].end(); it++) {
|
|
// NewPair<int, int> tile(*it);
|
|
memcpy(buffer + pos, &(*it), sizeof(NewPair<int, int>));
|
|
pos += sizeof(NewPair<int, int>);
|
|
}
|
|
// if (i % 5000 == 0 && i > 0) {
|
|
// cout << " area # " << i << " stored..." << endl;
|
|
// }
|
|
}
|
|
ta->areaFile.AppendRecord(aRecordId, aRecord);
|
|
assert(aRecordId != 0);
|
|
size_t bytesWritten = aRecord.Write(buffer, bufferSize);
|
|
aRecord.Finish();
|
|
SmiFileId aFileId = ta->areaFile.GetFileId();
|
|
if (!valueRecord.Write(&aRecordId, sizeof(SmiRecordId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiRecordId);
|
|
if (!valueRecord.Write(&aFileId, sizeof(SmiFileId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiFileId);
|
|
cout << "......... all areas stored (" << bytesWritten << " bytes)" << endl;
|
|
delete[] buffer;
|
|
bufferSize = (ta->maxX - ta->minX+1) * (ta->maxY - ta->minY+1) * sizeof(int);
|
|
buffer = new char[bufferSize];
|
|
pos = 0;
|
|
// store tileToArea
|
|
cout << "begin storing tileToArea: " << ta->maxX - ta->minX + 1 << " columns"
|
|
<< endl;
|
|
for (int i = ta->minX; i <= ta->maxX; i++) {
|
|
for (int j = ta->minY; j <= ta->maxY; j++) {
|
|
int areaNo = ta->tileToArea.get(i, j);
|
|
memcpy(buffer + pos, &areaNo, sizeof(int));
|
|
pos += sizeof(int);
|
|
}
|
|
// if ((i - ta->minX + 1) % 100 == 0) {
|
|
// cout << " " << i - ta->minX + 1 << " columns stored..." << endl;
|
|
// }
|
|
}
|
|
ta->ttaFile.AppendRecord(ttaRecordId, ttaRecord);
|
|
assert(ttaRecordId != 0);
|
|
bytesWritten = ttaRecord.Write(buffer, bufferSize);
|
|
ttaRecord.Finish();
|
|
SmiFileId ttaFileId = ta->ttaFile.GetFileId();
|
|
if (!valueRecord.Write(&ttaRecordId, sizeof(SmiRecordId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiRecordId);
|
|
if (!valueRecord.Write(&ttaFileId, sizeof(SmiFileId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiFileId);
|
|
cout << "......... tileToArea stored (" << bytesWritten << " bytes)" << endl;
|
|
delete[] buffer;
|
|
bufferSize = ta->noTransitions * sizeof(int)
|
|
+ 8 * ta->transitions.size() * sizeof(int);
|
|
buffer = new char[bufferSize];
|
|
pos = 0;
|
|
// store transitions
|
|
cout << "begin storing " << ta->noTransitions << " transitions" << endl;
|
|
for (unsigned int i = 0; i < ta->transitions.size(); i++) {
|
|
for (int j = 0; j < 8; j++) {
|
|
for (set<int>::iterator it = ta->transitions[i][j].begin();
|
|
it != ta->transitions[i][j].end(); it++) {
|
|
memcpy(buffer + pos, &(*it), sizeof(int));
|
|
pos += sizeof(int);
|
|
}
|
|
memcpy(buffer + pos, &maxint, sizeof(int));
|
|
pos += sizeof(int);
|
|
}
|
|
}
|
|
ta->transFile.AppendRecord(trRecordId, trRecord);
|
|
assert(trRecordId != 0);
|
|
bytesWritten = trRecord.Write(buffer, bufferSize);
|
|
trRecord.Finish();
|
|
SmiFileId trFileId = ta->transFile.GetFileId();
|
|
if (!valueRecord.Write(&trRecordId, sizeof(SmiRecordId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiRecordId);
|
|
if (!valueRecord.Write(&trFileId, sizeof(SmiFileId), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(SmiFileId);
|
|
cout << ".........transitions stored (" << bytesWritten << " bytes)" << endl;
|
|
delete[] buffer;
|
|
unsigned int noRoadCourses(ta->roadCourses.size()), noDirCourses,
|
|
noHeightCourses;
|
|
double coord;
|
|
int indexPos;
|
|
if (!valueRecord.Write(&noRoadCourses, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
for (unsigned int i = 0; i < noRoadCourses; i++) {
|
|
noDirCourses = ta->roadCourses[i].dirCourse.size();
|
|
if (!valueRecord.Write(&noDirCourses, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
for (unsigned int j = 0; j < noDirCourses; j++) {
|
|
if (!valueRecord.Write(&ta->roadCourses[i].dirCourse[j].first,
|
|
sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
coord = ta->roadCourses[i].dirCourse[j].second.GetX();
|
|
if (!valueRecord.Write(&coord, sizeof(double), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(double);
|
|
coord = ta->roadCourses[i].dirCourse[j].second.GetY();
|
|
if (!valueRecord.Write(&coord, sizeof(double), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(double);
|
|
}
|
|
|
|
noHeightCourses = ta->roadCourses[i].heightCourse.size();
|
|
if (!valueRecord.Write(&noHeightCourses, sizeof(unsigned int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(unsigned int);
|
|
for (unsigned int j = 0; j < noHeightCourses; j++) {
|
|
if (!valueRecord.Write(&ta->roadCourses[i].heightCourse[j].first,
|
|
sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
indexPos = ta->roadCourses[i].heightCourse[j].second[0];
|
|
if (!valueRecord.Write(&indexPos, sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
indexPos = ta->roadCourses[i].heightCourse[j].second[1];
|
|
if (!valueRecord.Write(&indexPos, sizeof(int), offset)) {
|
|
return false;
|
|
}
|
|
offset += sizeof(int);
|
|
}
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
ListExpr mlabelType = nl->SymbolAtom(MLabel::BasicType());
|
|
ListExpr mlabelTypeInfo = sc->NumericType(mlabelType);
|
|
MLabel::Save(valueRecord, offset, mlabelTypeInfo,
|
|
&(ta->roadCourses[i].dirSeq));
|
|
MLabel::Save(valueRecord, offset, mlabelTypeInfo,
|
|
&(ta->roadCourses[i].heightSeq));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Tileareas::Close(const ListExpr typeInfo, Word& w) {
|
|
Tileareas *t = (Tileareas*)w.addr;
|
|
delete t;
|
|
w.addr = 0;
|
|
}
|
|
|
|
Word Tileareas::Clone(const ListExpr typeInfo, const Word& w) {
|
|
Tileareas *t = (Tileareas*)w.addr;
|
|
Word res;
|
|
res.addr = new Tileareas(*t);
|
|
return res;
|
|
}
|
|
|
|
bool Tileareas::TypeCheck(ListExpr typeList, ListExpr& errorInfo) {
|
|
return nl->IsEqual(typeList, BasicType());
|
|
}
|
|
|
|
int Tileareas::SizeOfObj() {
|
|
return INT_MAX;
|
|
}
|
|
|
|
/*
|
|
\subsection{Type Constructor}
|
|
|
|
*/
|
|
TypeConstructor tileareasTC(
|
|
Tileareas::BasicType(), Tileareas::Property,
|
|
Tileareas::Out, Tileareas::In,
|
|
0, 0,
|
|
Tileareas::Create, Tileareas::Delete,
|
|
Tileareas::Open, Tileareas::Save,
|
|
Tileareas::Close, Tileareas::Clone,
|
|
0,
|
|
Tileareas::SizeOfObj,
|
|
Tileareas::TypeCheck);
|
|
|
|
/*
|
|
\section{Implementation of class ~RestoreTrajLI~}
|
|
|
|
Applied for the operator ~restoreTraj~.
|
|
|
|
*/
|
|
RestoreTrajLI::RestoreTrajLI(Relation *e, BTree *ht, RTree2TID *st,
|
|
raster2::sint *r, Hash *rh, raster2::sint *mr, Tileareas *ta, MLabel *h,
|
|
MLabel *d, MLabel *s)
|
|
: edgesRel(e), heightBtree(ht), segmentsRtree(st), raster(r), rhash(rh),
|
|
maxspeedRaster(mr), tileareas(ta), height(h), direction(d), speed(s) {
|
|
edgesRel = 0;
|
|
heightBtree = 0;
|
|
segmentsRtree = 0;
|
|
// Word roadCoursesPtr;
|
|
// bool isDefined;
|
|
// SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
// if (!sc->GetObject("RoadCourses", roadCoursesPtr, isDefined)) {
|
|
// cout << "Object RoadCourses does not exist." << endl;
|
|
// return;
|
|
// }
|
|
// if (!isDefined) {
|
|
// cout << "Object RoadCourses is undefined." << endl;
|
|
// return;
|
|
// }
|
|
// Relation *roadCourses = static_cast<Relation*>(roadCoursesPtr.addr);
|
|
// cout << roadCourses->GetNoTuples() << " tuples" << endl;
|
|
// RelationIterator *rit = (RelationIterator*)(roadCourses->MakeScan());
|
|
// Tuple *tuple = 0;
|
|
datetime::DateTime fiveMinutes(0, 180000, datetime::durationtype);
|
|
Point pt1(true), pt2(true);
|
|
for (unsigned int i = 0; i < ta->roadCourses.size(); i++) {
|
|
NewPair<int, int> hLimits = height->LongestCommonSubsequence(
|
|
ta->roadCourses[i].heightSeq);
|
|
NewPair<int, int> dLimits = direction->LongestCommonSubsequence(
|
|
ta->roadCourses[i].dirSeq);
|
|
MLabel hPart(true), dPart(true), hPart2(true), dPart2(true);
|
|
if (hLimits.first >= 0 && dLimits.first >= 0) {
|
|
height->GetPart(hLimits.first, hLimits.second, hPart);
|
|
direction->GetPart(dLimits.first, dLimits.second, dPart);
|
|
Periods hPer(true), dPer(true), inter(true);
|
|
hPart.DefTime(hPer);
|
|
dPart.DefTime(dPer);
|
|
hPer.Intersection(dPer, inter);
|
|
if (!inter.IsEmpty()) {
|
|
Interval<Instant> iv1, iv2;
|
|
inter.Get(0, iv1);
|
|
inter.Get(inter.GetNoComponents() - 1, iv2);
|
|
if (iv2.end - iv1.start > fiveMinutes) {
|
|
hPart.AtPeriods(inter, hPart2);
|
|
dPart.AtPeriods(inter, dPart2);
|
|
if (ta->roadCourses[i].restorePoints(dLimits.first, dLimits.second,
|
|
pt1, pt2)) {
|
|
cout << "found HEIGHT part: " << hPart2 << endl;
|
|
cout << "found DIR part: " << dPart2 << endl;
|
|
cout << "between " << pt1 << " and " << pt2 << endl
|
|
<< "----------------------------------" << endl << endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
bool RestoreTrajLI::retrieveSequel(const int startPos, set<int>& areas) {
|
|
if (startPos < 0 || startPos + 1 >= height->GetNoComponents()) {
|
|
return false;
|
|
}
|
|
string nextHeightLabel;
|
|
SecInterval iv1(true), iv2(true);
|
|
height->GetInterval(startPos, iv1);
|
|
height->GetInterval(startPos + 1, iv2);
|
|
if (iv1.end != iv2.start) { // intervals have to be adjacent
|
|
return false;
|
|
}
|
|
height->GetValue(startPos + 1, nextHeightLabel); // next height value
|
|
int nextHeightNum = stoi(nextHeightLabel.substr(0,nextHeightLabel.find("-")));
|
|
set<int> newAreas;
|
|
cout << "check neighbors for " << areas.size() << " origins; height range is "
|
|
<< nextHeightLabel << " (" << nextHeightNum << "), instant " << iv2.start
|
|
<< endl;
|
|
for (set<int>::iterator it = areas.begin(); it != areas.end(); it++) {
|
|
processNeighbors(*it, iv2.start, nextHeightNum, newAreas);
|
|
}
|
|
areas = newAreas;
|
|
return !areas.empty();
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~processNeighbors~}
|
|
|
|
For the tile ~origin~, each of its three neighbors in the direction assumed at
|
|
the instant ~inst~ and adjacent directions are inserted into ~result~, iff their
|
|
altitude and maximum speed match the symbolic trajectories.
|
|
|
|
*/
|
|
void RestoreTrajLI::processNeighbors(const int origin, const Instant& inst,
|
|
const int height, set<int>& result) {
|
|
ILabel dirILabel(true), speedILabel(true);
|
|
Label dirLabel(true);
|
|
direction->AtInstant(inst, dirILabel);
|
|
speed->AtInstant(inst, speedILabel);
|
|
if (!dirILabel.IsDefined() || !speedILabel.IsDefined()) {
|
|
return;
|
|
}
|
|
DirectionNum dirNum = dirLabelToNum(dirILabel.value);
|
|
set<int> neighborAreas;
|
|
getNeighborAreas(origin, dirNum, neighborAreas);
|
|
int currentSpeed = getSpeedFromLabel(speedILabel.value, false);
|
|
for (set<int>::iterator it = neighborAreas.begin(); it != neighborAreas.end();
|
|
it++) {
|
|
if (getHeightFromArea(*it) == height &&
|
|
getMaxspeedFromArea(*it) >= currentSpeed) {
|
|
result.insert(*it);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~getNeighbors~}
|
|
|
|
For the area ~origin~, its neighbors in the direction ~dir~ and the two
|
|
adjacent directions are collected and returned.
|
|
|
|
*/
|
|
void RestoreTrajLI::getNeighborAreas(const int origin, const DirectionNum dir,
|
|
set<int>& result) {
|
|
result.clear();
|
|
result.insert(tileareas->transitions[origin][dir].begin(),
|
|
tileareas->transitions[origin][dir].end());
|
|
int dir2 = (dir + 7) % 8;
|
|
result.insert(tileareas->transitions[origin][dir2].begin(),
|
|
tileareas->transitions[origin][dir2].end());
|
|
int dir3 = (dir + 1) % 8;
|
|
result.insert(tileareas->transitions[origin][dir3].begin(),
|
|
tileareas->transitions[origin][dir3].end());
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~retrieveAreasFromHeight~}
|
|
|
|
First, we determine the speed at the start instant of the unit corresponding to
|
|
~pos~. Then all tiles with a lower or equal maximum speed are inserted into
|
|
~result~.
|
|
|
|
*/
|
|
void RestoreTrajLI::retrieveAreasFromHeight(const int pos, set<int>& result) {
|
|
ULabel heightULabel(true);
|
|
ILabel speedILabel(true);
|
|
height->Get(pos, heightULabel);
|
|
if (!heightULabel.IsDefined()) {
|
|
return;
|
|
}
|
|
string heightStr = heightULabel.constValue.GetValue();
|
|
int heightNum = stoi(heightStr.substr(0, heightStr.find("-")));
|
|
CcInt *key = new CcInt(heightNum, true);
|
|
HashIterator *hit = rhash->ExactMatch(key);
|
|
speed->AtInstant(heightULabel.timeInterval.start, speedILabel);
|
|
if (!speedILabel.IsDefined()) {
|
|
return;
|
|
}
|
|
int currentSpeed = getSpeedFromLabel(speedILabel.value, false);
|
|
int rasterPos[2];
|
|
while (hit->Next()) {
|
|
rasterPos[0] = (int)hit->GetId();
|
|
if (hit->Next()) {
|
|
rasterPos[1] = (int)hit->GetId();
|
|
raster2::sint::index_type rasterIndex(rasterPos);
|
|
if (maxspeedRaster->get(rasterIndex) >= currentSpeed) {
|
|
result.insert(tileareas->tileToArea.get(rasterPos[0], rasterPos[1]));
|
|
}
|
|
}
|
|
}
|
|
key->DeleteIfAllowed();
|
|
}
|
|
|
|
int RestoreTrajLI::getHeightFromArea(const int areaNo) {
|
|
NewPair<int, int> tile = *(tileareas->areas[areaNo].begin());
|
|
int rasterPos[2];
|
|
rasterPos[0] = tile.first;
|
|
rasterPos[1] = tile.second;
|
|
raster2::sint::index_type rasterIndex(rasterPos);
|
|
return raster->get(rasterIndex);
|
|
}
|
|
|
|
int RestoreTrajLI::getMaxspeedFromArea(const int areaNo) {
|
|
int result = INT_MIN;
|
|
int rasterPos[2];
|
|
for (set<NewPair<int, int> >::iterator it = tileareas->areas[areaNo].begin();
|
|
it != tileareas->areas[areaNo].end(); it++) {
|
|
rasterPos[0] = it->first;
|
|
rasterPos[1] = it->second;
|
|
raster2::sint::index_type rasterIndex(rasterPos);
|
|
int tileMaxspeed = maxspeedRaster->get(rasterIndex);
|
|
if (tileMaxspeed > result) {
|
|
result = tileMaxspeed;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void RestoreTrajLI::getBboxFromArea(const int areaNo, Rectangle<2>& result) {
|
|
set<NewPair<int, int> >::iterator it = tileareas->areas[areaNo].begin();
|
|
int rasterPos[2];
|
|
rasterPos[0] = it->first;
|
|
rasterPos[1] = it->second;
|
|
raster2::sint::index_type rasterIndex(rasterPos);
|
|
result = raster->getGrid().getCell(rasterIndex);
|
|
while (it != tileareas->areas[areaNo].end()) {
|
|
rasterPos[0] = it->first;
|
|
rasterPos[1] = it->second;
|
|
raster2::sint::index_type rasterIndex(rasterPos);
|
|
result = result.Union(raster->getGrid().getCell(rasterIndex));
|
|
it++;
|
|
}
|
|
}
|
|
|
|
const DirectionNum RestoreTrajLI::dirLabelToNum(const Label& dirLabel) {
|
|
if (dirLabel == "East") return EAST;
|
|
if (dirLabel == "Northeast") return NORTHEAST;
|
|
if (dirLabel == "North") return NORTH;
|
|
if (dirLabel == "Northwest") return NORTHWEST;
|
|
if (dirLabel == "West") return WEST;
|
|
if (dirLabel == "Southwest") return SOUTHWEST;
|
|
if (dirLabel == "South") return SOUTH;
|
|
if (dirLabel == "Southeast") return SOUTHEAST;
|
|
return DIR_ERROR;
|
|
}
|
|
|
|
const string RestoreTrajLI::dirNumToString(const DirectionNum dirNum) {
|
|
if (dirNum == EAST) return "East";
|
|
if (dirNum == NORTHEAST) return "Northeast";
|
|
if (dirNum == NORTH) return "North";
|
|
if (dirNum == NORTHWEST) return "Northwest";
|
|
if (dirNum == WEST) return "West";
|
|
if (dirNum == SOUTHWEST) return "Southwest";
|
|
if (dirNum == SOUTH) return "South";
|
|
if (dirNum == SOUTHEAST) return "Southeast";
|
|
return "Error";
|
|
}
|
|
|
|
const DirectionNum RestoreTrajLI::dirDoubleToNum(const double dirDouble) {
|
|
if (dirDouble > 360.0 || dirDouble < 0.0) return DIR_ERROR;
|
|
if (dirDouble > 337.5 || dirDouble <= 22.5) return EAST;
|
|
if (dirDouble <= 67.5) return NORTHEAST;
|
|
if (dirDouble <= 112.5) return NORTH;
|
|
if (dirDouble <= 157.5) return NORTHWEST;
|
|
if (dirDouble <= 202.5) return WEST;
|
|
if (dirDouble <= 247.5) return SOUTHWEST;
|
|
if (dirDouble <= 292.5) return SOUTH;
|
|
return SOUTHEAST;
|
|
}
|
|
|
|
const int RestoreTrajLI::getDirectionDistance(const DirectionNum dir1,
|
|
const DirectionNum dir2) {
|
|
return min(abs(dir1 - dir2), abs(8 - abs(dir1 - dir2)));
|
|
}
|
|
|
|
const int RestoreTrajLI::getSpeedFromLabel(const Label& speedLabel,
|
|
const bool getMax) {
|
|
if (speedLabel == "0-6") return (getMax ? 6 : 0);
|
|
if (speedLabel == "6-15") return (getMax ? 15 : 6);
|
|
if (speedLabel == "15-30") return (getMax ? 30 : 15);
|
|
if (speedLabel == "30-50") return (getMax ? 50 : 30);
|
|
if (speedLabel == "50-100") return (getMax ? 100 : 50);
|
|
if (speedLabel == "100-200") return (getMax ? 200 : 100);
|
|
return SPEED_MAX;
|
|
}
|
|
|
|
Rectangle<2>* RestoreTrajLI::nextCandidate() {
|
|
if (resultAreas.empty() || it == resultAreas.end()) {
|
|
return 0;
|
|
}
|
|
Rectangle<2> *areaBox = new Rectangle<2>(true);
|
|
getBboxFromArea(*it, *areaBox);
|
|
it++;
|
|
return areaBox;
|
|
}
|
|
|
|
}
|