#ifndef FLOORPLANCEILINGS_H #define FLOORPLANCEILINGS_H #include "Floorplan.h" namespace Floorplan { /** * helper-class for floorplan ceilings * e.g. to determine the number of ceilings between two given positions */ class Ceilings { private: /** position (height) of all ceilings (in meter) */ std::vector ceilingsAtHeight_m; public: /** empty ctor */ Ceilings() { ; } /** ctor with the map to work with */ Ceilings(const IndoorMap* map) { // sanity checks Assert::isTrue(map->floors.size() >= 1, "map has no floors?!"); // get position of all ceilings for (Floorplan::Floor* f : map->floors) { const float h1 = f->atHeight; const float h2 = f->atHeight + f->height; if (std::find(ceilingsAtHeight_m.begin(), ceilingsAtHeight_m.end(), h1) == ceilingsAtHeight_m.end()) { ceilingsAtHeight_m.push_back(h1); } if (std::find(ceilingsAtHeight_m.begin(), ceilingsAtHeight_m.end(), h2) == ceilingsAtHeight_m.end()) { ceilingsAtHeight_m.push_back(h2); } } } /** get the number of ceilings between z1 and z2 */ float numCeilingsBetweenFloat(const Point3 pos1, const Point3 pos2) const { // sanity checks Assert::isNot0(ceilingsAtHeight_m.size(), "no ceilings available for testing! incorrect map?"); const float zMin = std::min(pos1.z, pos2.z); const float zMax = std::max(pos1.z, pos2.z); float cnt = 0; for (const float z : ceilingsAtHeight_m) { if (zMin < z && zMax > z) { const float dmax = zMax - z; cnt += (dmax > 1) ? (1) : (dmax); } } return cnt; } /** get the number of ceilings between z1 and z2 */ int numCeilingsBetween(const Point3 pos1, const Point3 pos2) const { // sanity checks Assert::isNot0(ceilingsAtHeight_m.size(), "no ceilings available for testing! incorrect map?"); // find min and max height given the to-be-compared points const float zMin = std::min(pos1.z, pos2.z); const float zMax = std::max(pos1.z, pos2.z); #ifdef WITH_ASSERTIONS static int numNear = 0; static int numFar = 0; for (const float z : ceilingsAtHeight_m) { const float diff = std::min( std::abs(z-zMin), std::abs(z-zMax) ); if (diff < 0.1) {++numNear;} else {++numFar;} } if ((numNear + numFar) > 150000) { Assert::isTrue(numNear < numFar*0.1, "many requests to Floorplan::Ceilings::numCeilingsBetween address nodes (very) near to a ground! \ due to rounding issues, determining the number of floors between AP and point-in-question is NOT possible! \ expect very wrong outputs! \ consider adding the person's height to the questioned positions: p += Point3(0,0,1.3) " ); } #endif int cnt = 0; for (const float z : ceilingsAtHeight_m) { if (zMin < z && zMax > z) {++cnt;} } return cnt; } }; } #endif // FLOORPLANCEILINGS_H