26#include <unordered_set>
35#define KDTP_EXCLUDE_INTERNAL_EDGES
38#define KDTP_KEEP_OUTGOING_BOUNDARY_EDGES
40#define KDTP_KEEP_INCOMING_BOUNDARY_EDGES
45#define KDTP_KEEP_BOUNDARY_FROM_NODES
51#ifdef KDTP_WRITE_QGIS_FILTERS
60#ifdef KDTP_DEBUG_LEVEL_2
61#define KDTP_DEBUG_LEVEL_1
64#ifdef KDTP_DEBUG_LEVEL_1
65#define KDTP_DEBUG_LEVEL_0
85template<
class E,
class N,
class V>
105 bool operator()(
const N* firstNode,
const N* secondNode)
const {
106 if (firstNode->getPosition().x() == secondNode->getPosition().x()) {
107 std::string str = firstNode->getID();
108 std::intmax_t firstValue = std::strtoimax(str.c_str(),
nullptr, 10);
109 str = secondNode->getID();
110 std::intmax_t secondValue = std::strtoimax(str.c_str(),
nullptr, 10);
111 return firstValue < secondValue;
113 return firstNode->getPosition().x() < secondNode->getPosition().x();
129 bool operator()(
const N* firstNode,
const N* secondNode)
const {
130 if (firstNode->getPosition().y() == secondNode->getPosition().y()) {
131 std::string str = firstNode->getID();
132 std::intmax_t firstValue = std::strtoimax(str.c_str(),
nullptr, 10);
133 str = secondNode->getID();
134 std::intmax_t secondValue = std::strtoimax(str.c_str(),
nullptr, 10);
135 return firstValue < secondValue;
137 return firstNode->getPosition().y() < secondNode->getPosition().y();
147#ifdef KDTP_FOR_SYNTHETIC_NETWORKS
173 Cell(std::vector<const Cell*>* cells, std::vector<std::vector<const Cell*>>* levelCells, std::vector<const N*>* sortedNodes,
int numberOfLevels,
174 int level,
Axis axis,
size_t fromInclusive,
size_t toExclusive,
Cell* supercell,
double minX,
double maxX,
double minY,
double maxY,
175 std::unordered_set<const N*>* northernConflictNodes, std::unordered_set<const N*>* easternConflictNodes,
176 std::unordered_set<const N*>* southernConflictNodes, std::unordered_set<const N*>* westernConflictNodes,
177 bool isLeftOrLowerCell,
const V*
const vehicle,
const bool havePermissions,
const bool haveRestrictions);
200 Cell(std::vector<const Cell*>* cells, std::vector<std::vector<const Cell*>>* levelCells, std::vector<const N*>* sortedNodes,
201 int numberOfLevels,
int level,
Axis axis,
size_t fromInclusive,
size_t toExclusive, Cell* supercell,
double minX,
double maxX,
202 double minY,
double maxY,
bool isLeftOrLowerCell,
const V*
const vehicle,
const bool havePermissions,
const bool haveRestrictions);
219 std::unordered_set<const E*>*
edgeSet(
const V*
const vehicle)
const;
248 std::pair<typename std::vector<const N*>::const_iterator,
253 std::vector<const N*>*
nodes()
const;
254#ifdef KDTP_KEEP_BOUNDARY_NODES
256 const std::vector<const N*>& getBoundaryNodes()
const {
257 return myBoundaryNodes;
260#ifdef KDTP_KEEP_BOUNDARY_FROM_NODES
266#ifdef KDTP_KEEP_BOUNDARY_TO_NODES
268 const std::vector<const N*>& getBoundaryToNodes()
const {
269 return myBoundaryToNodes;
272#ifdef KDTP_KEEP_BOUNDARY_EDGES
274 const std::unordered_set<const E*>& getBoundaryEdges()
const {
275 return myBoundaryEdges;
278#ifdef KDTP_KEEP_INCOMING_BOUNDARY_EDGES
284#ifdef KDTP_KEEP_OUTGOING_BOUNDARY_EDGES
354#ifdef KDTP_FOR_SYNTHETIC_NETWORKS
359 std::pair<std::unordered_set<const N*>*, std::unordered_set<const N*>*> spatialConflictNodes(
size_t medianIndex)
const;
404#if defined(KDTP_KEEP_BOUNDARY_NODES) || defined(KDTP_WRITE_QGIS_FILTERS)
406 std::vector<const N*> myBoundaryNodes;
408#ifdef KDTP_KEEP_BOUNDARY_FROM_NODES
412#ifdef KDTP_KEEP_BOUNDARY_TO_NODES
414 std::vector<const N*> myBoundaryToNodes;
416#ifdef KDTP_KEEP_INCOMING_BOUNDARY_EDGES
421#ifdef KDTP_KEEP_OUTGOING_BOUNDARY_EDGES
426#ifdef KDTP_KEEP_BOUNDARY_EDGES
428 std::unordered_set<const E*> myBoundaryEdges;
450#ifdef KDTP_FOR_SYNTHETIC_NETWORKS
452 std::unordered_set<const N*>* myNorthernConflictNodes;
454 std::unordered_set<const N*>* myEasternConflictNodes;
456 std::unordered_set<const N*>* mySouthernConflictNodes;
458 std::unordered_set<const N*>* myWesternConflictNodes;
475 const bool havePermissions,
const bool haveRestrictions);
480 std::vector<const Cell*>().swap(
myCells);
481 std::vector<std::vector<const Cell*>>().swap(
myLevelCells);
488 void init(
const V*
const vehicle);
493 void reset(
const V*
const vehicle) {
510 const Cell*
cell(
int number)
const;
572 void cellNumbersAux(
const N* node,
const Cell*
cell,
int level, std::vector<int>* nodeCellNumbers)
const;
597template<
class E,
class N,
class V>
599 const bool havePermissions,
const bool haveRestrictions) :
600 myNumberOfLevels(numberOfLevels),
602 myHavePermissions(havePermissions),
603 myHaveRestrictions(haveRestrictions),
605 if (numberOfLevels <= 0) {
606 throw std::invalid_argument(
"KDTreePartition::KDTreePartition: zero or negative number of levels has been passed!");
610template<
class E,
class N,
class V>
612 size_t edgeCounter = 0;
613 std::unordered_set<const N*> nodeSet;
615 mySortedNodes.resize(myEdges.size() * 2);
616#ifdef KDTP_DEBUG_LEVEL_1
617 std::cout <<
"Extracting nodes from edges..." << std::endl;
619 for (E* edge : myEdges) {
620 if ((myHavePermissions && edge->prohibits(vehicle))
621 || (myHaveRestrictions && edge->restricts(vehicle))) {
624 const N* node = edge->getFromJunction();
625 typename std::unordered_set<const N*>::const_iterator it = nodeSet.find(node);
626 if (it == nodeSet.end()) {
627 nodeSet.insert(node);
628 assert(edgeCounter < mySortedNodes.size());
629 mySortedNodes[edgeCounter++] = node;
631 node = edge->getToJunction();
632 it = nodeSet.find(node);
633 if (it == nodeSet.end()) {
634 nodeSet.insert(node);
635 assert(edgeCounter < mySortedNodes.size());
636 mySortedNodes[edgeCounter++] = node;
639 mySortedNodes.shrink_to_fit();
640#ifdef KDTP_DEBUG_LEVEL_1
641 std::cout <<
"Nodes extracted from edges." << std::endl;
643 mySortedNodes.resize(edgeCounter);
644 myCells.resize(numberOfCells());
645 myLevelCells.resize(myNumberOfLevels);
647#ifdef KDTP_DEBUG_LEVEL_1
648 std::cout <<
"Calling root cell constructor..." << std::endl;
650#ifdef KDTP_FOR_SYNTHETIC_NETWORKS
651 myRoot =
new Cell(&myCells, &myLevelCells, &mySortedNodes, myNumberOfLevels, 0, Axis::Y, 0, mySortedNodes.size(),
nullptr, -1, -1, -1, -1,
652 nullptr,
nullptr,
nullptr,
nullptr,
false, vehicle, havePermissions, haveRestrictions);
654 myRoot =
new Cell(&myCells, &myLevelCells, &mySortedNodes, myNumberOfLevels, 0, Axis::Y, 0, mySortedNodes.size(),
nullptr, -1, -1, -1, -1,
655 false, vehicle, myHavePermissions, myHaveRestrictions);
657#ifdef KDTP_DEBUG_LEVEL_1
658 std::cout <<
"Done." << std::endl;
660 assert(myCells[0] == myRoot);
661 assert(myRoot->getNumber() == 0);
663#ifdef KDTP_DEBUG_LEVEL_0
664 const N* node = mySortedNodes[0];
665 std::vector<int>* numbers = cellNumbers(node);
667 for (i = 0; i < myNumberOfLevels; ++i) {
668 std::cout <<
"Cell numbers of test node: " << (*numbers)[i] << std::endl;
671 for (i = 0; i < myNumberOfLevels; ++i) {
672 const std::vector<const Cell*>& levelCells = getCellsAtLevel(i);
673 size_t size = levelCells.size();
674 std::cout <<
"Level " << i <<
" has " << size <<
" cells." << std::endl;
675 std::cout <<
"The numbers of the cells are: " << std::endl;
677 for (
const Cell* cell : levelCells) {
678 std::cout << cell->getNumber() << (k++ < size ?
", " :
"") << std::endl;
685template<
class E,
class N,
class V>
689 if (cell->getNumber() == number) {
696template<
class E,
class N,
class V>
698 std::vector<int>* nodeCellNumbers =
new std::vector<int>(myNumberOfLevels);
700 for (i = 0; i < myNumberOfLevels; ++i) {
701 (*nodeCellNumbers)[i] = -1;
703 cellNumbersAux(node, myCells[0], 0, nodeCellNumbers);
704#ifdef KDTP_DEBUG_LEVEL_1
705 std::cout <<
"The following entries in nodeCellNumbers should all be set (!=-1): " << std::endl;
706 for (i = 0; i < myNumberOfLevels; ++i) {
707 assert((*nodeCellNumbers)[i] != -1);
708 std::cout <<
"nodeCellNumbers[" << i <<
"]:" << (*nodeCellNumbers)[i] << std::endl;
711 return nodeCellNumbers;
714template<
class E,
class N,
class V>
716#ifdef KDTP_DEBUG_LEVEL_1
717 std::cout <<
"Call ...aux, level: " << level <<
", cell->getAxis(): " << (cell->
getAxis() == Axis::X ?
"X" :
"Y") << std::endl;
719 assert(level < myNumberOfLevels);
720#ifdef KDTP_DEBUG_LEVEL_1
722 double nodeAxisValue = flippedCellAxis == Axis::Y ? node->getPosition().y() : node->getPosition().x();
723 std::cout <<
"Flipped axis of cell (=parent cell axis): " << (flippedCellAxis == Axis::X ?
"X" :
"Y")
724 <<
", cell min axis value in flipped axis: " << (flippedCellAxis == Axis::X ? cell->
getMinX() : cell->
getMinY())
725 <<
", node axis value in flipped axis: " << nodeAxisValue <<
", cell max axis value in flipped axis: "
726 << (flippedCellAxis == Axis::X ? cell->
getMaxX() : cell->
getMaxY()) << std::endl;
730 (*nodeCellNumbers)[level] = cell->
getNumber();
731#ifdef KDTP_DEBUG_LEVEL_1
732 std::cout <<
"Just filled nodeCellNumbers[" << level <<
"]:" << (*nodeCellNumbers)[level] << std::endl;
736 if (leftOrLowerSubcell) {
737 cellNumbersAux(node, leftOrLowerSubcell, level + 1, nodeCellNumbers);
740 if (rightOrUpperSubcell) {
741 cellNumbersAux(node, rightOrUpperSubcell, level + 1, nodeCellNumbers);
744#ifdef KDTP_DEBUG_LEVEL_1
746 std::cout <<
"Not inside cell, do nothing." << std::endl;
751template<
class E,
class N,
class V>
752#ifdef KDTP_FOR_SYNTHETIC_NETWORKS
753KDTreePartition<E, N, V>::Cell::Cell(std::vector<const Cell*>* cells, std::vector<std::vector<const Cell*>>* levelCells, std::vector<const N*>* sortedNodes,
int numberOfLevels,
int level,
754 Axis axis,
size_t fromInclusive,
size_t toExclusive, Cell* supercell,
double minX,
double maxX,
double minY,
double maxY, std::unordered_set<const N*>* northernConflictNodes,
755 std::unordered_set<const N*>* easternConflictNodes, std::unordered_set<const N*>* southernConflictNodes, std::unordered_set<const N*>* westernConflictNodes,
const V*
const vehicle,
756 const bool havePermissions,
const bool haveRestrictions) :
758 myLevelCells(levelCells),
759 mySortedNodes(sortedNodes),
760 myNumberOfLevels(numberOfLevels),
761 myLevel(level), myNumber(cellCounter()++),
763 myFromInclusive(fromInclusive),
764 myToExclusive(toExclusive),
765 mySupercell(supercell),
770 myNorthernConflictNodes(northernConflictNodes),
771 myEasternConflictNodes(easternConflictNodes),
772 mySouthernConflictNodes(southernConflictNodes),
773 myWesternConflictNodes(westernConflictNodes),
774 myIsLeftOrLowerCell(isLeftOrLowerCell),
775 myHavePermissions(havePermissions),
776 myHaveRestrictions(haveRestrictions),
777 myMedianCoordinate(-1.) {
780 Axis axis,
size_t fromInclusive,
size_t toExclusive,
Cell* supercell,
double minX,
double maxX,
double minY,
double maxY,
bool isLeftOrLowerCell,
const V*
const vehicle,
781 const bool havePermissions,
const bool haveRestrictions) :
787 myNumber(cellCounter()++),
789 myFromInclusive(fromInclusive),
790 myToExclusive(toExclusive),
791 mySupercell(supercell),
796 myIsLeftOrLowerCell(isLeftOrLowerCell),
799 myMedianCoordinate(-1.) {
803 throw std::invalid_argument(
"Cell::Cell: myFromInclusive greater than or equal to myToExclusive!");
808 (*myLevelCells)[
myLevel].push_back(
this);
809#ifdef KDTP_DEBUG_LEVEL_1
810 std::cout <<
"Cell number: " <<
myNumber <<
", cell's extent: minX=" <<
myMinX <<
", maxX="
812 std::vector<const N*>* cellNodes =
nodes();
814 for (
const N* node : *cellNodes) {
815 if (++cnt % 10000 == 0) {
816 std::cout <<
"Testing node " << cnt << std::endl;
824 typename std::vector<const N*>::const_iterator iter;
825#ifdef KDTP_WRITE_QGIS_FILTERS
828 std::string qgisFilterString =
"id IN (";
830 for (iter = first; iter != last; iter++) {
832 qgisFilterString += (*iter)->getID() + (k < numberOfNodes ?
", " :
"");
834 qgisFilterString +=
")";
835 std::ostringstream pathAndFileName;
836 pathAndFileName <<
"./filter_nodes_of_cell_" <<
myNumber <<
".qqf";
838 file.open(pathAndFileName.str());
839 std::ostringstream content;
840 content <<
"<Query>" << qgisFilterString <<
"</Query>";
841 file << content.str();
845#ifdef KDTP_DEBUG_LEVEL_1
846 std::cout <<
"Computing the set of of edges inside the cell..." << std::endl;
849#ifdef KDTP_DEBUG_LEVEL_1
850 std::cout <<
"Done. Now collecting boundary edges..." << std::endl;
854 for (iter = first; iter != last; iter++) {
855#if defined(KDTP_KEEP_BOUNDARY_EDGES) || defined(KDTP_KEEP_BOUNDARY_NODES) || defined(KDTP_WRITE_QGIS_FILTERS)
856 std::unordered_set<const E*> nodeEdgeSet;
858#ifdef KDTP_DEBUG_LEVEL_1
859 if ((i++ % 10000) == 0) {
860 std::cout << i <<
" cell nodes processed..." << std::endl;
863#if defined(KDTP_KEEP_BOUNDARY_EDGES) || defined(KDTP_KEEP_BOUNDARY_NODES) || defined(KDTP_WRITE_QGIS_FILTERS)
864 const std::vector<const E*>& incomingEdges = (*iter)->getIncoming();
865 for (
const E* incomingEdge : incomingEdges) {
869#ifdef KDTP_EXCLUDE_INTERNAL_EDGES
870 if (incomingEdge->isInternal()) {
874 nodeEdgeSet.insert(incomingEdge);
876 const std::vector<const E*>& outgoingEdges = (*iter)->getOutgoing();
877 for (
const E* outgoingEdge : outgoingEdges) {
881#ifdef KDTP_EXCLUDE_INTERNAL_EDGES
882 if (outgoingEdge->isInternal()) {
886 nodeEdgeSet.insert(outgoingEdge);
888 bool containsAll =
true;
889 for (
const E* nodeEdge : nodeEdgeSet) {
892#ifndef KDTP_KEEP_BOUNDARY_EDGES
895 myBoundaryEdges.insert(nodeEdge);
899#if defined(KDTP_KEEP_BOUNDARY_NODES) || defined(KDTP_WRITE_QGIS_FILTERS)
901 myBoundaryNodes.push_back(*iter);
905#if defined(KDTP_KEEP_INCOMING_BOUNDARY_EDGES) || defined(KDTP_KEEP_BOUNDARY_TO_NODES)
906 const std::vector<const E*>& incoming = (*iter)->getIncoming();
907 std::unordered_set<const N*> boundaryToNodesSet;
908 for (
const E* nodeEdge : incoming) {
912#ifdef KDTP_EXCLUDE_INTERNAL_EDGES
913 if (nodeEdge->isInternal()) {
917 assert(nodeEdge->getToJunction() == *iter);
919#ifdef KDTP_KEEP_INCOMING_BOUNDARY_EDGES
922#ifdef KDTP_KEEP_BOUNDARY_TO_NODES
923 boundaryToNodesSet.insert(*iter); ;
927#ifdef KDTP_KEEP_BOUNDARY_TO_NODES
928 std::copy(boundaryToNodesSet.begin(), boundaryToNodesSet.end(),
929 std::back_inserter(myBoundaryToNodes));
932#if defined(KDTP_KEEP_OUTGOING_BOUNDARY_EDGES) || defined(KDTP_KEEP_BOUNDARY_FROM_NODES)
933 const std::vector<const E*>& outgoing = (*iter)->getOutgoing();
934 std::unordered_set<const N*> boundaryFromNodesSet;
935 for (
const E* nodeEdge : outgoing) {
939#ifdef KDTP_EXCLUDE_INTERNAL_EDGES
940 if (nodeEdge->isInternal()) {
944 assert(nodeEdge->getFromJunction() == *iter);
946#ifdef KDTP_KEEP_OUTGOING_BOUNDARY_EDGES
949#ifdef KDTP_KEEP_BOUNDARY_FROM_NODES
950 boundaryFromNodesSet.insert(*iter);
954#ifdef KDTP_KEEP_BOUNDARY_FROM_NODES
955 std::copy(boundaryFromNodesSet.begin(), boundaryFromNodesSet.end(),
961#if defined(KDTP_KEEP_BOUNDARY_NODES) || defined(KDTP_WRITE_QGIS_FILTERS)
962 size_t numberOfBoundaryNodes = myBoundaryNodes.size();
963#ifdef KDTP_DEBUG_LEVEL_1
964 std::cout <<
"Number of boundary nodes: " << numberOfBoundaryNodes << std::endl;
967#ifdef KDTP_KEEP_BOUNDARY_FROM_NODES
968#ifdef KDTP_DEBUG_LEVEL_1
970 std::cout <<
"Number of boundary from nodes: " << numberOfBoundaryFromNodes << std::endl;
973#ifdef KDTP_KEEP_BOUNDARY_TO_NODES
974 size_t numberOfBoundaryToNodes = myBoundaryToNodes.size();
975#ifdef KDTP_DEBUG_LEVEL_1
976 std::cout <<
"Number of boundary to nodes: " << numberOfBoundaryToNodes << std::endl;
979#ifdef KDTP_KEEP_BOUNDARY_EDGES
980 size_t numberOfBoundaryEdges = myBoundaryEdges.size();
981#ifdef KDTP_DEBUG_LEVEL_1
982 std::cout <<
"Number of boundary edges: " << numberOfBoundaryEdges << std::endl;
985#ifdef KDTP_KEEP_INCOMING_BOUNDARY_EDGES
986#ifdef KDTP_DEBUG_LEVEL_1
988 std::cout <<
"Number of incoming boundary edges: " << numberOfIncomingBoundaryEdges << std::endl;
991#ifdef KDTP_KEEP_OUTGOING_BOUNDARY_EDGES
992#ifdef KDTP_DEBUG_LEVEL_1
994 std::cout <<
"Number of outgoing boundary edges: " << numberOfOutgoingBoundaryEdges << std::endl;
997#ifdef KDTP_WRITE_QGIS_FILTERS
999 qgisFilterString.clear();
1000 qgisFilterString =
"id IN (";
1002 for (
const N* node : myBoundaryNodes) {
1004 qgisFilterString += node->getID() + (k < numberOfBoundaryNodes ?
", " :
"");
1006#ifndef KDTP_KEEP_BOUNDARY_NODES
1007 myBoundaryNodes.clear();
1009 qgisFilterString +=
")";
1010 pathAndFileName.str(
"");
1011 pathAndFileName.clear();
1012 pathAndFileName <<
"./filter_boundary_nodes_of_cell_" <<
myNumber <<
".qqf";
1014 file.open(pathAndFileName.str());
1017 content <<
"<Query>" << qgisFilterString <<
"</Query>";
1018 file << content.str();
1021#ifdef KDTP_DEBUG_LEVEL_1
1022 std::cout <<
"Done. Now calling the constructor recursively to instantiate the subcells (left or lower one first)..." << std::endl;
1029 double passMinX = -1, passMaxX = -1, passMinY = -1, passMaxY = -1;
1032 passMaxX = (*mySortedNodes)[medianIndex]->getPosition().x();
1039 passMaxY = (*mySortedNodes)[medianIndex]->getPosition().y();
1041#ifdef KDTP_FOR_SYNTHETIC_NETWORKS
1049 std::pair<std::unordered_set<const N*>*, std::unordered_set<const N*>*> conflictNodes = spatialConflictNodes(medianIndex);
1051 std::unordered_set<const N*>* passNorthernConflictNodes;
1052 std::unordered_set<const N*>* passEasternConflictNodes;
1053 std::unordered_set<const N*>* passSouthernConflictNodes;
1054 std::unordered_set<const N*>* passWesternConflictNodes;
1056 passNorthernConflictNodes = myNorthernConflictNodes;
1057 passEasternConflictNodes = conflictNodes.first;
1058 passSouthernConflictNodes = mySouthernConflictNodes;
1059 passWesternConflictNodes = myWesternConflictNodes;
1061 passNorthernConflictNodes = conflictNodes.first;
1062 passEasternConflictNodes = myEasternConflictNodes;
1063 passSouthernConflictNodes = mySouthernConflictNodes;
1064 passWesternConflictNodes = myWesternConflictNodes;
1067 passMinX, passMaxX, passMinY, passMaxY, passNorthernConflictNodes, passEasternConflictNodes, passSouthernConflictNodes, passWesternConflictNodes,
true,
1073#ifdef KDTP_DEBUG_LEVEL_1
1074 std::cout <<
"Left or lower call done. Now calling it for the right or upper subcell..." << std::endl;
1077 passMinX = -1, passMaxX = -1, passMinY = -1, passMaxY = -1;
1079 passMinX = (*mySortedNodes)[medianIndex + 1]->getPosition().x();
1086 passMinY = (*mySortedNodes)[medianIndex + 1]->getPosition().y();
1089#ifdef KDTP_FOR_SYNTHETIC_NETWORKS
1092 passNorthernConflictNodes = myNorthernConflictNodes;
1093 passEasternConflictNodes = myEasternConflictNodes;
1094 passSouthernConflictNodes = mySouthernConflictNodes;
1095 passWesternConflictNodes = conflictNodes.second;
1097 passNorthernConflictNodes = myNorthernConflictNodes;
1098 passEasternConflictNodes = myEasternConflictNodes;
1099 passSouthernConflictNodes = conflictNodes.second;
1100 passWesternConflictNodes = myWesternConflictNodes;
1103 passMinX, passMaxX, passMinY, passMaxY, passNorthernConflictNodes, passEasternConflictNodes, passSouthernConflictNodes, passWesternConflictNodes,
false,
1109#ifdef KDTP_DEBUG_LEVEL_1
1110 std::cout <<
"Right or upper call done. Returning from constructor..." << std::endl;
1119template<
class E,
class N,
class V>
1121#ifdef KDTP_DEBUG_LEVEL_1
1122 double returnValue = -1;
1124 if (myHasNodesSortedWrtToMyAxis && axis == myAxis) {
1125#ifndef KDTP_DEBUG_LEVEL_1
1127 : (*mySortedNodes)[myFromInclusive]->getPosition().x());
1129 returnValue = (myAxis ==
Axis::Y ? (*mySortedNodes)[myFromInclusive]->getPosition().y()
1130 : (*mySortedNodes)[myFromInclusive]->getPosition().x());
1133 double minAxisValue = std::numeric_limits<double>::max();
1134 typename std::vector<const N*>::const_iterator first =
mySortedNodes->begin() + myFromInclusive;
1135 typename std::vector<const N*>::const_iterator last =
mySortedNodes->begin() + myToExclusive;
1136 typename std::vector<const N*>::const_iterator iter;
1138 for (iter = first; iter != last; iter++) {
1139 double nodeAxisValue;
1140 nodeAxisValue = (axis ==
Axis::Y ? (*iter)->getPosition().y() : (*iter)->getPosition().x());
1141 if (nodeAxisValue < minAxisValue) {
1142 minAxisValue = nodeAxisValue;
1145 assert(minAxisValue < std::numeric_limits<double>::max());
1146#ifdef KDTP_DEBUG_LEVEL_1
1147 assert((!myHasNodesSortedWrtToMyAxis || axis != myAxis) || minAxisValue == returnValue);
1149 return minAxisValue;
1152template<
class E,
class N,
class V>
1154 return minAxisValue(myAxis);
1157template<
class E,
class N,
class V>
1159#ifdef KDTP_DEBUG_LEVEL_1
1160 double returnValue = -1;
1162 if (myHasNodesSortedWrtToMyAxis && axis == myAxis) {
1163#ifndef KDTP_DEBUG_LEVEL_1
1165 : (*mySortedNodes)[myToExclusive - 1]->getPosition().x());
1167 returnValue = (myAxis ==
Axis::Y ? (*mySortedNodes)[myToExclusive - 1]->getPosition().y()
1168 : (*mySortedNodes)[myToExclusive - 1]->getPosition().x());
1172 double maxAxisValue = -1;
1173 typename std::vector<const N*>::const_iterator first =
mySortedNodes->begin() + myFromInclusive;
1174 typename std::vector<const N*>::const_iterator last =
mySortedNodes->begin() + myToExclusive;
1175 typename std::vector<const N*>::const_iterator iter;
1177 for (iter = first; iter != last; iter++) {
1178 double nodeAxisValue;
1179 nodeAxisValue = (axis ==
Axis::Y ? (*iter)->getPosition().y() : (*iter)->getPosition().x());
1180 if (nodeAxisValue > maxAxisValue) {
1181 maxAxisValue = nodeAxisValue;
1184 assert(maxAxisValue > 0);
1185#ifdef KDTP_DEBUG_LEVEL_1
1186 assert((!myHasNodesSortedWrtToMyAxis || axis != myAxis) || maxAxisValue == returnValue);
1188 return maxAxisValue;
1191template<
class E,
class N,
class V>
1193 return maxAxisValue(myAxis);
1196template<
class E,
class N,
class V>
1198 typename std::vector<const N*>::iterator first =
mySortedNodes->begin() + myFromInclusive;
1199 typename std::vector<const N*>::iterator last =
mySortedNodes->begin() + myToExclusive;
1205 myHasNodesSortedWrtToMyAxis =
true;
1208 mySupercell->myHasNodesSortedWrtToMyAxis =
false;
1210 size_t length = myToExclusive - myFromInclusive;
1211 size_t medianIndex = myFromInclusive + (length % 2 == 0 ? length / 2 - 1 : (length + 1) / 2 - 1);
1212#ifndef KDTP_FOR_SYNTHETIC_NETWORKS
1223 const N* medianNode = (*mySortedNodes)[medianIndex];
1224 const N* afterMedianNode = (*mySortedNodes)[medianIndex + 1];
1225 double medianNodeCoordinate = myAxis ==
Axis::X ? medianNode->getPosition().x()
1226 : medianNode->getPosition().y();
1227 double afterMedianNodeCoordinate = myAxis ==
Axis::X ? afterMedianNode->getPosition().x()
1228 : afterMedianNode->getPosition().y();
1229 while (medianNodeCoordinate == afterMedianNodeCoordinate && medianIndex < myToExclusive - 3) {
1230#ifdef KDTP_DEBUG_LEVEL_2
1231 std::cout <<
"Found spatially conflicting nodes." << std::endl;
1234 medianNode = (*mySortedNodes)[medianIndex];
1235 afterMedianNode = (*mySortedNodes)[medianIndex + 1];
1236 medianNodeCoordinate = myAxis ==
Axis::X ? medianNode->getPosition().x()
1237 : medianNode->getPosition().y();
1238 afterMedianNodeCoordinate = myAxis ==
Axis::X ? afterMedianNode->getPosition().x()
1239 : afterMedianNode->getPosition().y();
1242 myMedianCoordinate = medianNodeCoordinate;
1246template<
class E,
class N,
class V>
1250 myMinX = minAxisValue(
Axis::X);
1253 myMaxX = maxAxisValue(
Axis::X);
1256 myMinY = minAxisValue(
Axis::Y);
1259 myMaxY = maxAxisValue(
Axis::Y);
1261 myHasCompleteSpatialInfo =
true;
1264template<
class E,
class N,
class V>
1266 std::unordered_set<const E*>* edgeSet =
new std::unordered_set<const E*>();
1267 typename std::vector<const N*>::const_iterator first =
mySortedNodes->begin() + myFromInclusive;
1268 typename std::vector<const N*>::const_iterator last =
mySortedNodes->begin() + myToExclusive;
1269 typename std::vector<const N*>::const_iterator iter;
1270 for (iter = first; iter != last; iter++) {
1272 const std::vector<const E*>& incomingEdges = (*iter)->getIncoming();
1273 for (
const E* incomingEdge : incomingEdges) {
1274 if (isProhibited(incomingEdge, vehicle)) {
1277#ifdef KDTP_EXCLUDE_INTERNAL_EDGES
1278 if (incomingEdge->isInternal()) {
1282 edgeNode = incomingEdge->getFromJunction();
1283 if (contains(edgeNode)) {
1284 edgeSet->insert(incomingEdge);
1287 const std::vector<const E*>& outgoingEdges = (*iter)->getOutgoing();
1288 for (
const E* outgoingEdge : outgoingEdges) {
1289 if (isProhibited(outgoingEdge, vehicle)) {
1292#ifdef KDTP_EXCLUDE_INTERNAL_EDGES
1293 if (outgoingEdge->isInternal()) {
1297 edgeNode = outgoingEdge->getToJunction();
1298 if (contains(edgeNode)) {
1299 edgeSet->insert(outgoingEdge);
1306template<
class E,
class N,
class V>
1308 typename std::vector<const N*>::const_iterator first =
mySortedNodes->begin() + myFromInclusive;
1309 typename std::vector<const N*>::const_iterator last =
mySortedNodes->begin() + myToExclusive;
1310 typename std::vector<const N*>::const_iterator iter;
1311 size_t edgeCounter = 0;
1312 for (iter = first; iter != last; iter++) {
1313 const std::vector<const E*>& incomingEdges = (*iter)->getIncoming();
1314 for (
const E* incomingEdge : incomingEdges) {
1315 if (isProhibited(incomingEdge, vehicle)) {
1318#ifdef KDTP_EXCLUDE_INTERNAL_EDGES
1319 if (incomingEdge->isInternal()) {
1330template<
class E,
class N,
class V>
1332 typename std::vector<const N*>::const_iterator first =
mySortedNodes->begin() + myFromInclusive;
1333 typename std::vector<const N*>::const_iterator last =
mySortedNodes->begin() + myToExclusive;
1334 typename std::vector<const N*>::const_iterator iter;
1335 size_t edgeCounter = 0;
1336 for (iter = first; iter != last; iter++) {
1337 const std::vector<const E*>& outgoingEdges = (*iter)->getOutgoing();
1338 for (
const E* outgoingEdge : outgoingEdges) {
1339 if (isProhibited(outgoingEdge, vehicle)) {
1342#ifdef KDTP_EXCLUDE_INTERNAL_EDGES
1343 if (outgoingEdge->isInternal()) {
1354template<
class E,
class N,
class V>
1355std::pair<typename std::vector<const N*>::const_iterator,
1357 typename std::vector<const N*>::const_iterator first =
mySortedNodes->begin() + myFromInclusive;
1358 typename std::vector<const N*>::const_iterator last =
mySortedNodes->begin() + myToExclusive;
1359 std::pair<typename std::vector<const N*>::const_iterator,
1360 typename std::vector<const N*>::const_iterator> iterators = std::make_pair(first, last);
1364template<
class E,
class N,
class V>
1366 typename std::vector<const N*>::const_iterator first =
mySortedNodes->begin() + myFromInclusive;
1367 typename std::vector<const N*>::const_iterator last =
mySortedNodes->begin() + myToExclusive;
1368 std::vector<const N*>* nodes =
new std::vector<const N*>(first, last);
1372#ifdef KDTP_FOR_SYNTHETIC_NETWORKS
1373template<
class E,
class N,
class V>
1374std::pair<std::unordered_set<const N*>*,
1376 std::unordered_set<const N*>* leftOrLowerSpatialConflictNodes =
new std::unordered_set<const N*>();
1377 std::unordered_set<const N*>* rightOrUpperSpatialConflictNodes =
new std::unordered_set<const N*>();
1378 std::pair<std::unordered_set<const N*>*, std::unordered_set<const N*>*> spatialConflictNodes
1379 = std::make_pair(leftOrLowerSpatialConflictNodes, rightOrUpperSpatialConflictNodes);
1380 std::vector<const N*>::const_iterator iter, prev;
1383 double sharedCoordinate = (*mySortedNodes)[medianIndex]->getPosition().x();
1384 std::vector<const N*>::iterator firstLeftOrLower =
mySortedNodes->begin() + medianIndex;
1386 std::vector<const N*>::iterator last =
mySortedNodes->begin() + myFromInclusive - 1;
1387 for (iter = firstLeftOrLower; ((*iter)->getPosition().x() == sharedCoordinate) && (iter != last); iter--) {
1388 leftOrLowerSpatialConflictNodes->insert(*iter);
1392 if ((*
mySortedNodes)[medianIndex]->getPosition().y() == (*mySortedNodes)[medianIndex + 1]->getPosition().y()) {
1393 double sharedCoordinate = (*mySortedNodes)[medianIndex]->getPosition().y();
1394 std::vector<const N*>::iterator firstRightOrUpper =
mySortedNodes->begin() + medianIndex + 1;
1395 std::vector<const N*>::const_iterator last =
mySortedNodes->begin() + myToExclusive;
1396 for (iter = firstRightOrUpper; ((*iter)->getPosition().y() == sharedCoordinate) && (iter != last); iter++) {
1397 rightOrUpperSpatialConflictNodes->insert(*iter);
1401 return spatialConflictNodes;
1405template<
class E,
class N,
class V>
1407 double nodeX = node->getPosition().x();
1408 double nodeY = node->getPosition().y();
1409 if (nodeX < myMinX || nodeX > myMaxX || nodeY < myMinY || nodeY > myMaxY) {
1415template<
class E,
class N,
class V>
1420 if (!isInBounds(node)) {
1421#ifdef KDTP_DEBUG_LEVEL_2
1422 std::cout <<
"Not in bounds, nX: " << node->getPosition().x() <<
", nY: " << node->getPosition().y() << std::endl;
1426#ifdef KDTP_DEBUG_LEVEL_2
1428 std::cout <<
"Node is in bounds!" << std::endl;
1431#ifdef KDTP_FOR_SYNTHETIC_NETWORKS
1433 double nodeX = node->getPosition().x();
1434 double nodeY = node->getPosition().y();
1435#ifdef KDTP_DEBUG_LEVEL_2
1436 std::cout <<
"Entered contains, nodeX: " << nodeX <<
", nodeY: " << nodeY << std::endl;
1439 if (myNorthernConflictNodes && !myNorthernConflictNodes->empty()) {
1440 northY = (*(myNorthernConflictNodes->begin()))->getPosition().y();
1443 if (myEasternConflictNodes && !myEasternConflictNodes->empty()) {
1444 eastX = (*(myEasternConflictNodes->begin()))->getPosition().x();
1447 if (mySouthernConflictNodes && !mySouthernConflictNodes->empty()) {
1448 southY = (*(mySouthernConflictNodes->begin()))->getPosition().y();
1451 if (myWesternConflictNodes && !myWesternConflictNodes->empty()) {
1452 westX = (*(myWesternConflictNodes->begin()))->getPosition().x();
1454#ifdef KDTP_DEBUG_LEVEL_2
1455 std::cout <<
"northY: " << northY <<
", eastX: " << eastX <<
", southY: " << southY <<
", westX: " << westX << std::endl;
1457 if (nodeX == eastX) {
1458#ifdef KDTP_DEBUG_LEVEL_2
1459 std::cout <<
"On eastern bound, nX: " << node->getPosition().x() <<
", nY: " << node->getPosition().y() << std::endl;
1461 return myEasternConflictNodes->find(node) != myEasternConflictNodes->end();
1463 if (nodeX == westX) {
1464#ifdef KDTP_DEBUG_LEVEL_2
1465 std::cout <<
"On western bound, nX: " << node->getPosition().x() <<
", nY: " << node->getPosition().y() << std::endl;
1467 return myWesternConflictNodes->find(node) != myWesternConflictNodes->end();
1469 if (nodeY == northY) {
1470#ifdef KDTP_DEBUG_LEVEL_2
1471 std::cout <<
"On northern bound, nX: " << node->getPosition().x() <<
", nY: " << node->getPosition().y() << std::endl;
1473 return myNorthernConflictNodes->find(node) != myNorthernConflictNodes->end();
1475 if (nodeY == southY) {
1476#ifdef KDTP_DEBUG_LEVEL_2
1477 std::cout <<
"On southern bound, nX: " << node->getPosition().x() <<
", nY: " << node->getPosition().y() << std::endl;
1479 return mySouthernConflictNodes->find(node) != myEasternConflictNodes->end();
1482#ifdef KDTP_DEBUG_LEVEL_2
1483 std::cout <<
"Node does not lie on a border!" << std::endl;
1488template<
class E,
class N,
class V>
1496 double nodeCoordinate =
cell->
getAxis() ==
Axis::X ? node->getPosition().x() : node->getPosition().y();
1499 if (nextCell ==
nullptr) {
Represents an element of the node partition (i.e. a node set)
const Cell * getRightOrUpperSubcell() const
Returns the right (cell's axis is X) or upper (cell's axis is Y) subcell.
Cell * myRightOrUpperSubcell
The right (cell's axis is X) or upper (cell's axis is Y) subcell.
virtual ~Cell()
Destructor.
std::unordered_set< const E * > myIncomingBoundaryEdges
The incoming edges on the cell boundary.
std::unordered_set< const E * > * edgeSet(const V *const vehicle) const
Returns all edges situated inside the cell.
const std::vector< const N * > & getBoundaryFromNodes() const
Returns the vector of boundary nodes which are from-nodes of outgoing boundary edges.
size_t numberOfEdgesEndingInCell(const V *const vehicle) const
Returns the number of edges ending in the cell.
double getMinX() const
Returns the minimum coordinate of a cell node in X-direction (aka left border coordinate)
std::vector< const N * > myBoundaryFromNodes
Those nodes on the cell boundary, which are from-nodes of outgoing boundary edges.
double myMinX
The minimum x-value of a node in the cell.
const std::unordered_set< const E * > & getIncomingBoundaryEdges() const
Returns the set of incoming boundary edges.
size_t partition()
Performs one partition step on the set of nodes sorted wrt to the k-d tree subdivision scheme.
double myMedianCoordinate
The coordinate in the axis' direction of the node at the median index.
double minAxisValue() const
Returns the minimum coordinate of the cell nodes' positions, in the direction of the cell's axis (X o...
std::unordered_set< const E * > myOutgoingBoundaryEdges
The outgoing edges on the cell boundary.
bool isProhibited(const E *const edge, const V *const vehicle) const
Returns true iff driving the given vehicle on the given edge is prohibited.
double myMinY
The minimum y-value of a node in the cell.
const Axis myAxis
The axis of the spatial extension.
bool contains(const N *node) const
Tests whether the given node belongs to the cell.
double myMaxX
The maximum x-value of a node in the cell.
const size_t myToExclusive
The to-index (exclusive)
void completeSpatialInfo()
Completes the information about the spatial extent.
const int myNumberOfLevels
The total number of levels of the k-d tree.
bool myHasNodesSortedWrtToMyAxis
The boolean flag indicating whether the cell's nodes are sorted wrt to the cell's axis or not.
double myMaxY
The maximum y-value of a node in the cell.
double getMaxY() const
Returns the maximum coordinate of a cell node in Y-direction (aka upper border coordinate)
int getNumberOfCells() const
Returns the number of cells.
Cell * myLeftOrLowerSubcell
The left (cell's axis is X) or lower (cell's axis is Y) subcell.
std::vector< std::vector< const Cell * > > * myLevelCells
The cells of all partitions at all levels of the k-d tree subdivisional scheme.
const int myNumber
The number.
size_t numberOfEdgesStartingInCell(const V *const vehicle) const
Returns the number of edges starting in the cell.
bool myHasCompleteSpatialInfo
The boolean flag indicating whether the information about the cell's spatial extent is complete or no...
std::pair< typename std::vector< const N * >::const_iterator, typename std::vector< const N * >::const_iterator > nodeIterators() const
Returns a pair of iterators (first, last) to iterate over the nodes of the cell.
std::vector< const Cell * > * myCells
The cells.
bool isInBounds(const N *node) const
Tests whether a given node is situated within the spatial bounds of the cell.
int getNumber() const
Returns the cell's number.
double getMinY() const
Returns the minimum coordinate of a cell node in Y-direction (aka lower border coordinate)
double getMaxX() const
Returns the maximum coordinate of a cell node in X-direction (aka right border coordinate)
bool myIsLeftOrLowerCell
The boolean flag indicating whether this cell is a left/lower cell or not.
const int myLevel
The level.
const Cell * getLeftOrLowerSubcell() const
Returns the left (cell's axis is X) or lower (cell's axis is Y) subcell.
const bool myHaveRestrictions
The boolean flag indicating whether edge restrictions need to be considered or not.
static int & cellCounter()
Returns the global cell counter.
const std::unordered_set< const E * > & getOutgoingBoundaryEdges() const
Returns the set of outgoing boundary edges.
double maxAxisValue() const
Returns the maximum coordinate of the cell nodes' positions, in the direction of the cell's axis (X o...
Axis getAxis() const
Returns the axis of the cell's spatial extension (x or y)
std::vector< const N * > * nodes() const
Returns a new vector of nodes in the cell.
const bool myHavePermissions
The boolean flag indicating whether edge permissions need to be considered or not.
double getMedianCoordinate() const
Returns the median coordinate.
Cell * mySupercell
The super cell.
const Cell * getSupercell() const
Returns the supercell.
Cell(std::vector< const Cell * > *cells, std::vector< std::vector< const Cell * > > *levelCells, std::vector< const N * > *sortedNodes, int numberOfLevels, int level, Axis axis, size_t fromInclusive, size_t toExclusive, Cell *supercell, double minX, double maxX, double minY, double maxY, bool isLeftOrLowerCell, const V *const vehicle, const bool havePermissions, const bool haveRestrictions)
Constructor.
bool isLeftOrLowerCell() const
Returns the boolean flag indicating whether this cell is a left or lower cell or not.
int getLevel() const
Returns the cell's level.
std::vector< const N * > * mySortedNodes
The container with all nodes, sorted wrt to the k-d tree subdivisional scheme.
const size_t myFromInclusive
The from-index (inclusive)
bool operator()(const N *firstNode, const N *secondNode) const
Comparing method for X-axis.
bool operator()(const N *firstNode, const N *secondNode) const
Comparing method for Y-axis.
Partitions the router's network wrt a k-d tree subdivision scheme.
void reset(const V *const vehicle)
Delete the k-d tree, and create a new one param[in] vehicle The vehicle.
std::vector< int > * cellNumbers(const N *node) const
Returns the numbers of the cells which the given node is situated in.
void cellNumbersAux(const N *node, const Cell *cell, int level, std::vector< int > *nodeCellNumbers) const
Helper method for cellNumbers().
const std::vector< E * > & myEdges
The reference to a constant container with pointers to edges.
std::vector< std::vector< const Cell * > > myLevelCells
The cells of all partitions at all levels of the k-d tree subdivision scheme.
bool myAmClean
The boolean flag indicating whether the k-d tree is a clean (empty, uninitialized) instance or not.
const bool myHavePermissions
The boolean flag indicating whether edge permissions need to be considered or not.
const std::vector< const Cell * > & getCells()
Returns all cells.
const Cell * searchNode(const N *node) const
Search a node in the bottom cells (i.e., return the respective cell)
static Axis flip(Axis axis)
Returns the conjugated 2D axis.
const std::vector< const Cell * > & getCellsAtLevel(int level) const
Returns all cells of a level.
void init(const V *const vehicle)
Initialize the k-d tree wrt to the given vehicle's permissions.
size_t numberOfRegions() const
Returns the number of regions, i.e. the number of cells at the shallowest (bottom/leaf) level.
const Cell * getRoot() const
Returns the root of the k-d tree.
std::vector< const Cell * > myCells
The cells.
const Cell * myRoot
The root of the k-d tree.
int getNumberOfLevels() const
Returns the number of levels L incl. the zeroth level.
const bool myHaveRestrictions
The boolean flag indicating whether edge restrictions need to be considered or not.
~KDTreePartition()
Destructor.
const int myNumberOfLevels
The number of levels.
Axis
Enum type for cell axis.
int numberOfArcFlags() const
Returns the number of arc flags required in a multi-level approach.
const Cell * cell(int number) const
Returns the cell with the given number.
size_t numberOfCells() const
Returns the number of cells at all levels.
bool isClean()
Returns true iff the k-d tree is uninitialized.
KDTreePartition(int numberOfLevels, const std::vector< E * > &edges, const bool havePermissions, const bool haveRestrictions)
Constructor.
std::vector< const N * > mySortedNodes
The container with all nodes, sorted wrt to the k-d tree subdivision scheme.