/* ---- 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 #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 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 *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 > 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(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(x, y)); tileToArea.set(x, y, destAreaNo); areas[destAreaNo].insert(areas[sourceAreaNo].begin(), areas[sourceAreaNo].end()); for (set >::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(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(x, y)); } else { // create new area newArea.insert(NewPair(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 >::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(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 >(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 >::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(j)) << "-> {"; for (set::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 >& 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 *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& nodeSeq, vector& 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 *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 *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 > > motorwayParts; map nodeIdIndexes; map, vector > > nodeSeqs; // both directions map, vector > > segments; NestedRelation *roadsNRel = static_cast(roadsPtr.addr); Relation *nodesRel = static_cast(nodesPtr.addr); BTree *nodesBTree = static_cast(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 *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 nodes(INT_MIN, INT_MIN); if (scurve.IsDefined() && !motorwayName.empty()) { if (scurve.BoundingBox().Intersects(raster->bbox())) { AttributeRelation *arel2 = (AttributeRelation*)(tuple->GetAttribute(1)); DbArray *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 > >::iterator it = motorwayParts.begin(); it != motorwayParts.end(); it++) { nodeIdIndexes[it->first] = new BTree(SmiKey::Integer); cout << it->first << ": " << endl; map nodeCounter; // start +2, end +1 for (set >::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::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::iterator it = nodeIdIndexes.begin(); it != nodeIdIndexes.end(); it++) { if (it->second != 0) { delete it->second; } } for (map, vector > >::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,vector > >::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& 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 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 > area; NewPair tile; for (unsigned int j = 0; j < noTiles; j++) { memcpy(&tile, buffer + pos, sizeof(NewPair)); pos += sizeof(NewPair); 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 >(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 > transitionSets; set 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 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 > 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(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 >::iterator it = ta->areas[i].begin(); it != ta->areas[i].end(); it++) { // NewPair tile(*it); memcpy(buffer + pos, &(*it), sizeof(NewPair)); pos += sizeof(NewPair); } // 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::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(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 hLimits = height->LongestCommonSubsequence( ta->roadCourses[i].heightSeq); NewPair 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 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& 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 newAreas; cout << "check neighbors for " << areas.size() << " origins; height range is " << nextHeightLabel << " (" << nextHeightNum << "), instant " << iv2.start << endl; for (set::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& 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 neighborAreas; getNeighborAreas(origin, dirNum, neighborAreas); int currentSpeed = getSpeedFromLabel(speedILabel.value, false); for (set::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& 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& 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 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 >::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 >::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; } }