#ifndef INDOOR_GW3_HELPER_H #define INDOOR_GW3_HELPER_H #include "../../../nav/dijkstra/Dijkstra.h" #include "../../Grid.h" #include "Structs.h" #include namespace GW3 { template class Helper { public: static GridPoint p3ToGp(const Point3 p) { const Point3 p100 = p*100; return GridPoint( std::round(p100.x), std::round(p100.y), std::round(p100.z) ); } static Point3 gpToP3(const GridPoint gp) { return Point3(gp.x_cm / 100.0f, gp.y_cm / 100.0f, gp.z_cm / 100.0f); } /** does the given grid-node contain the provided point-in-question? */ static bool contains(const Grid& grid, const Node* n, Point2 pt) { const float gridSize_m = grid.getGridSize_cm() / 100.0f; const float d = gridSize_m / 2.0f; const Point2 pMin = n->inMeter().xy() - Point2(d, d); const Point2 pMax = n->inMeter().xy() + Point2(d, d); const BBox2 bbox(pMin, pMax); return bbox.contains(pt); } /** does one of the given grid-nodes contains the provided point-in-question? */ static const Node* contains(const Grid& grid, const Nodes& nodes, Point2 pt) { for (const Node* n : nodes) { if (contains(grid, n, pt)) {return n;} } return nullptr; } /** get all possible walks from start within a given region */ static Walks getAllPossibleWalks(Grid& grid, const Node* start, const float dist_m) { struct Access { Grid& grid; Access(Grid& grid) : grid(grid) {;} int getNumNeighbors(const Node& n) const {return n.getNumNeighbors();} Node* getNeighbor(const Node& n, const int idx) const {return &grid.getNeighbor(n, idx);} float getWeightBetween(const Node& n1, const Node& n2) const {return n1.inMeter().getDistance(n2.inMeter());} } acc(grid); const float addDist_m = grid.getGridSize_cm() / 100.0f; const float maxDist_m = dist_m * 1.1 + addDist_m; Dijkstra dijkstra; dijkstra.build(start, nullptr, acc, maxDist_m); const std::unordered_map*>& nodes = dijkstra.getNodes(); Walks walks; for (const auto& it : nodes) { Walk walk; DijkstraNode* node = it.second; do { const Node* gridNode = node->element; walk.insert(walk.begin(), gridNode); // push_front() as dijkstra is inverted node = node->previous; } while (node); walks.push_back(walk); } return walks; } /** get all reachable nodes that are within a given range */ static Nodes getAllReachableNodes(Grid& grid, const Node* start, const float dist_m) { Nodes res; std::unordered_map distances; std::vector toVisit; toVisit.push_back(start->getIdx()); distances[start->getIdx()] = 0.0f; while (!toVisit.empty()) { int curIdx = toVisit.front(); toVisit.erase(toVisit.begin()); const Node& curNode = grid[curIdx]; const float curDistance = distances[curIdx]; res.push_back(&curNode); // remember for output if (curDistance <= dist_m) { for (int i = 0; i < curNode.getNumNeighbors(); ++i) { const int neighborIdx = curNode.getNeighborIdx(i); const Node& neighbor = grid[neighborIdx]; const float addDist = neighbor.inMeter().getDistance(curNode.inMeter()); const float totalDist = curDistance + addDist; // this is like in dijkstra. keep the smallest distance to reach a node: // not yet reached -> store distance if (distances.find(neighborIdx) == distances.end()) { toVisit.push_back(neighborIdx); distances[neighborIdx] = totalDist; // reached earlier but found shorter way } else { if (distances[neighborIdx] > totalDist) { distances[neighborIdx] = totalDist; } } } } } return res; } }; } #endif // INDOOR_GW3_HELPER_H