This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Indoor/grid/factory/v2/Elevators.h
2018-10-25 11:50:12 +02:00

170 lines
5.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* © 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