/* * © Copyright 2014 – Urheberrechtshinweis * Alle Rechte vorbehalten / All Rights Reserved * * Programmcode ist urheberrechtlich geschuetzt. * Das Urheberrecht liegt, soweit nicht ausdruecklich anders gekennzeichnet, bei Frank Ebner. * Keine Verwendung ohne explizite Genehmigung. * (vgl. § 106 ff UrhG / § 97 UrhG) */ #ifndef GRID_ELEVATORS_H #define GRID_ELEVATORS_H #include #include #include "../../Grid.h" #include "Helper.h" #include "../../../floorplan/v2/Floorplan.h" #include template class Elevators { private: /** the grid to build into */ Grid& grid; /** calculation helper */ Helper helper; public: /** ctor */ Elevators(Grid& grid) : grid(grid), helper(grid) { ; } ~Elevators() { ; } /** build the given elevator */ void build(const Floorplan::Floor* floor, const Floorplan::Elevator* elevator) { const int gs_cm = grid.getGridSize_cm(); struct IntPos { int x_cm; int y_cm; IntPos(int x_cm, int y_cm) : x_cm(x_cm), y_cm(y_cm) {;} }; // identify all grid-aligned nodes that belong to the elevator std::vector nodesWithin; const HelperPoly poly(elevator->getPoints()); // elevator starts at the current floor, but where does the elevator end? const int f1_cm = grid.snapZ(floor->getStartingZ()*100); // elevator's end is given by its height const int f2_cm = grid.snapZ( (floor->getStartingZ() + elevator->height_m) * 100); auto callback = [&] (const int x_cm, const int y_cm) { const GridPoint gp1(x_cm, y_cm, f1_cm); // starting floor const GridPoint gp2(x_cm, y_cm, f2_cm); // the floor above // ensure such a node is present in both floors (and thus a connection is possible) if (grid.hasNodeFor(gp1) && grid.hasNodeFor(gp2)) { nodesWithin.push_back(IntPos(x_cm, y_cm)); } }; poly.forEachGridPoint(gs_cm, callback); if (nodesWithin.empty()) { throw Exception("faild to determine starting and ending nodes for elevator. disconnected?"); } // now create the interconnection in z-direction //const int z1_cm = std::ceil((floor->getStartingZ()*100+1) / gs_cm) * gs_cm; // the next node above the current flor //const int z2_cm = std::floor((floor->getEndingZ()*100-1) / gs_cm) * gs_cm; // the last node below the next floor int z1_cm = std::ceil((f1_cm+1.0f) / gs_cm) * gs_cm; int z2_cm = std::floor((f2_cm-1.0f) / gs_cm) * gs_cm; // ensure the nodes between (z1,z2) are not directly the floor (f1,f2) //if (grid.snapZ(z1_cm) == grid.snapZ(f1_cm)) {z1_cm += gs_cm;} //if (grid.snapZ(z2_cm) == grid.snapZ(f2_cm)) {z2_cm -= gs_cm;} for (const IntPos nodePos : nodesWithin) { // create nodes BETWEEN the two floors (skip the floors themselves! -> floor1+gridSize <-> floor2-gridSize for (int z_cm = z1_cm; z_cm <= z2_cm; z_cm += gs_cm) { const GridPoint gp1(nodePos.x_cm, nodePos.y_cm, z_cm); // the to-be-added node //Assert::isFalse(grid.hasNodeFor(gp1), "elevator collission"); // such a node must not yet exist! otherwise we e.g. collide with a stari if (grid.hasNodeFor(gp1)) { const int idx = grid.getNodeFor(gp1).getIdx(); grid[idx].setType(GridNode::TYPE_ELEVATOR); // set the node-type } else { const int idx = grid.add(T(gp1.x_cm, gp1.y_cm, gp1.z_cm)); // create the node grid[idx].setType(GridNode::TYPE_ELEVATOR); // set the node-type } } // connect each of the new nodes with the node below it // also connect the elevator to the starting and ending floor for (int z_cm = z1_cm; z_cm <= z2_cm; z_cm += gs_cm) { // directly above starting floor if (z_cm == z1_cm) { // connect with floor below const GridPoint gpBelow(nodePos.x_cm, nodePos.y_cm, f1_cm); const GridPoint gp(nodePos.x_cm, nodePos.y_cm, z_cm); Assert::isTrue(grid.hasNodeFor(gpBelow), "missing node"); Assert::isTrue(grid.hasNodeFor(gp), "missing node"); const T& n1 = grid.getNodeFor(gpBelow); const T& n2 = grid.getNodeFor(gp); grid.connectBiDir(n1.getIdx(), n2.getIdx()); grid[n1.getIdx()].setType(GridNode::TYPE_ELEVATOR); } else { // connect with node below const GridPoint gpBelow(nodePos.x_cm, nodePos.y_cm, z_cm-gs_cm); const GridPoint gp(nodePos.x_cm, nodePos.y_cm, z_cm); Assert::isTrue(grid.hasNodeFor(gpBelow), "missing node"); Assert::isTrue(grid.hasNodeFor(gp), "missing node"); const T& n1 = grid.getNodeFor(gpBelow); const T& n2 = grid.getNodeFor(gp); grid.connectBiDir(n1.getIdx(), n2.getIdx()); } // directly below ending floor if (z_cm == z2_cm) { // connect with floor above const GridPoint gpAbove(nodePos.x_cm, nodePos.y_cm, f2_cm); const GridPoint gp(nodePos.x_cm, nodePos.y_cm, z_cm); Assert::isTrue(grid.hasNodeFor(gpAbove), "missing node"); Assert::isTrue(grid.hasNodeFor(gp), "missing node"); const T& n1 = grid.getNodeFor(gpAbove); const T& n2 = grid.getNodeFor(gp); //if (n1.getIdx() == n2.getIdx()) {continue;} grid.connectBiDir(n1.getIdx(), n2.getIdx()); grid[n1.getIdx()].setType(GridNode::TYPE_ELEVATOR); } } } } }; #endif // GRID_ELEVATORS_H