170 lines
5.1 KiB
C++
170 lines
5.1 KiB
C++
/*
|
||
* © 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 <vector>
|
||
#include <set>
|
||
|
||
#include "../../Grid.h"
|
||
#include "Helper.h"
|
||
#include "../../../floorplan/v2/Floorplan.h"
|
||
|
||
#include <fstream>
|
||
|
||
|
||
|
||
template <typename T> class Elevators {
|
||
|
||
private:
|
||
|
||
/** the grid to build into */
|
||
Grid<T>& grid;
|
||
|
||
/** calculation helper */
|
||
Helper<T> helper;
|
||
|
||
|
||
public:
|
||
|
||
/** ctor */
|
||
Elevators(Grid<T>& 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<IntPos> 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
|