/* * © 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 FLOORPLANHELPER2_H #define FLOORPLANHELPER2_H #include "../../geo/BBox3.h" #include "../../geo/Line2.h" #include "../../Assertions.h" #include "Floorplan.h" #include "../../sensors/MACAddress.h" /** * helper methods for the floorplan */ class FloorplanHelper { public: /** get the AP for the given MAC [if available] */ static std::pair getAP(const Floorplan::IndoorMap* map, const MACAddress& mac) { for (Floorplan::Floor* f : map->floors) { for (Floorplan::AccessPoint* ap : f->accesspoints) { if (MACAddress(ap->mac) == mac) { return std::make_pair(ap, f); } } } return std::make_pair(nullptr, nullptr); } /** get the AP for the given Name [if available] */ static std::pair getAPByName(const Floorplan::IndoorMap* map, const std::string& name) { for (Floorplan::Floor* f : map->floors) { for (Floorplan::AccessPoint* ap : f->accesspoints) { if (name == ap->name) { return std::make_pair(ap, f); } } } return std::make_pair(nullptr, nullptr); } /** get all APs within the map */ static std::vector> getAPs(const Floorplan::IndoorMap* map) { std::vector> res; for (Floorplan::Floor* f : map->floors) { for (Floorplan::AccessPoint* ap : f->accesspoints) { res.push_back(std::make_pair(ap,f)); } } return res; } /** get the Fingerprint-Loation for the given Name [if available] */ static std::pair getFingerprintLocationByName(const Floorplan::IndoorMap* map, const std::string& name) { for (Floorplan::Floor* f : map->floors) { for (Floorplan::FingerprintLocation* fpl : f->fpLocations) { if (name == fpl->name) { return std::make_pair(fpl, f); } } } return std::make_pair(nullptr, nullptr); } /** get all ground-truth points within the map as hash-map: id->pos */ static std::unordered_map getGroundTruthPoints(const Floorplan::IndoorMap* map) { std::unordered_map res; for (const Floorplan::Floor* f : map->floors) { for (const Floorplan::GroundTruthPoint* gtp : f->gtpoints) { res[gtp->id] = gtp->getPosition(*f); } } return res; } /** get all ground-truth points, identified by the given indices */ static std::vector getGroundTruth(const Floorplan::IndoorMap* map, const std::vector indices) { // get a map id->pos for all ground-truth-points within the map const std::unordered_map src = getGroundTruthPoints(map); std::vector res; for (const int idx : indices) { const auto& it = src.find(idx); if (it == src.end()) {throw Exception("map does not contain a ground-truth-point with ID " + std::to_string(idx));} res.push_back(it->second); } return res; } public: /** align all floorplan values to the given grid size. needed for the grid factory */ static void align(Floorplan::IndoorMap* map, const int gridSize_cm) { for (Floorplan::Floor* floor : map->floors) { floor->atHeight = align_m(floor->atHeight, gridSize_cm); floor->height = align_m(floor->height, gridSize_cm); for (Floorplan::Stair* stair : floor->stairs) { for (Floorplan::StairPart& part : ((Floorplan::StairFreeform*)stair)->parts) { part.start.z = align_m(part.start.z, gridSize_cm); part.end.z = align_m(part.end.z, gridSize_cm); } } } } static inline float align_m(const float val_m, const int gridSize_cm) { const float val_cm = val_m * 100; const int snapped = std::round(val_cm / gridSize_cm); const float res_cm = snapped * gridSize_cm; return res_cm / 100.0f; } /** get a BBox for the whole map */ static BBox3 getBBox(const Floorplan::IndoorMap* map) { BBox3 bbox; for (const Floorplan::Floor* floor : map->floors) { const BBox3 bbFloor = getBBox(floor); bbox.add(bbFloor); } return bbox; } /** get a BBox for the whole floor */ static BBox3 getBBox(const Floorplan::Floor* floor) { BBox3 bbox; Assert::isNot0(floor->outline.size(), "floor " + floor->name + " has no outline!"); for (const Floorplan::FloorOutlinePolygon* poly : floor->outline) { for (const Point2 p2 : poly->poly.points) { bbox.add(Point3(p2.x, p2.y, floor->atHeight)); bbox.add(Point3(p2.x, p2.y, floor->atHeight + floor->height)); } } return bbox; } /** does the map contain an obstacle that intersects the given line? (in meter!) */ static bool intersectsObstacle(const Floorplan::IndoorMap* map, const Point3& p1, const Point3& p2) { // sanity check if (std::abs(p2.z-p1.z) > 0.5) { return false;} for (const Floorplan::Floor* floor : map->floors) { if (intersectsObstacle(floor, p1, p2)) {return true;} } return false; } /** does the floor contain an obstacle that intersects the given line? (in meter!) */ static bool intersectsObstacle(const Floorplan::Floor* floor, const Point3& p1, const Point3& p2) { // sanity check if (std::abs(p2.z-p1.z) > 0.5) { return false;} // only inspect elements that lie near the ground if (p1.z < floor->getStartingZ() - 0.15) {return false;} if (p1.z > floor->getStartingZ() + 0.15) {return false;} const Line2 line1(p1.x,p1.y, p2.x,p2.y); for (const Floorplan::FloorObstacle* obs : floor->obstacles) { if (dynamic_cast(obs)) { const Floorplan::FloorObstacleLine* obsLine = dynamic_cast(obs); const Line2 line2(obsLine->from.x, obsLine->from.y, obsLine->to.x, obsLine->to.y); if (line1.getSegmentIntersection(line2)) {return true;} } else if (dynamic_cast(obs)) { ; } else { throw "not yet supported"; } } return false; } }; #endif // FLOORPLANHELPER2_H