fixed some potential issues with MAC addresses
added corresponding test-cases switched to newer version of tinyxml due to some issues adjusted affected code-parts accordingly for better re-use, moved ceiling-calculation to a new class some minor fixes new helper methods worked on wifi-opt
This commit is contained in:
112
floorplan/v2/FloorplanCeilings.h
Normal file
112
floorplan/v2/FloorplanCeilings.h
Normal file
@@ -0,0 +1,112 @@
|
||||
#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<float> 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
|
||||
@@ -7,11 +7,28 @@
|
||||
|
||||
#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<Floorplan::AccessPoint*, Floorplan::Floor*> 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);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/** align all floorplan values to the given grid size. needed for the grid factory */
|
||||
|
||||
@@ -35,11 +35,12 @@ namespace Floorplan {
|
||||
if (res != tinyxml2::XMLError::XML_SUCCESS) {
|
||||
throw Exception(
|
||||
std::string() + "error while loading XML " + file + "\n" +
|
||||
((doc.GetErrorStr1()) ? (doc.GetErrorStr1()) : ("")) + "\n" +
|
||||
((doc.GetErrorStr2()) ? (doc.GetErrorStr2()) : (""))
|
||||
((doc.GetErrorStr1()) ? (doc.GetErrorStr1()) : ("")) + "\n" +
|
||||
((doc.GetErrorStr2()) ? (doc.GetErrorStr2()) : (""))
|
||||
);
|
||||
}
|
||||
return parse(doc);
|
||||
IndoorMap* map = parse(doc);
|
||||
return map;
|
||||
}
|
||||
|
||||
/** read an IndoorMap from the given XMl-string */
|
||||
@@ -51,16 +52,17 @@ namespace Floorplan {
|
||||
if (res != tinyxml2::XMLError::XML_SUCCESS) {
|
||||
throw Exception(
|
||||
std::string() + "error while parsing XML\n" +
|
||||
((doc.GetErrorStr1()) ? (doc.GetErrorStr1()) : ("")) + "\n" +
|
||||
((doc.GetErrorStr2()) ? (doc.GetErrorStr2()) : (""))
|
||||
((doc.GetErrorStr1()) ? (doc.GetErrorStr1()) : ("")) + "\n" +
|
||||
((doc.GetErrorStr2()) ? (doc.GetErrorStr2()) : (""))
|
||||
);
|
||||
}
|
||||
return parse(doc);
|
||||
IndoorMap* map = parse(doc);
|
||||
return map;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
#define FOREACH_NODE(out, in) for( const XMLElem* out = (XMLElem*) in->FirstChild(); out; out = (XMLElem*) out->NextSibling() )
|
||||
#define FOREACH_NODE(out, in) for( const XMLElem* out = in->FirstChildElement(); out; out = out->NextSiblingElement() )
|
||||
|
||||
static void assertNode(const std::string& node, const XMLElem* el) {
|
||||
std::string err = std::string("unexpected node '") + el->Name() + "' expected '" + node + "'";
|
||||
@@ -69,7 +71,7 @@ namespace Floorplan {
|
||||
|
||||
/** parse the complete document */
|
||||
static IndoorMap* parse(tinyxml2::XMLDocument& doc) {
|
||||
return parseMap((XMLElem*)doc.FirstChild());
|
||||
return parseMap(doc.FirstChildElement());
|
||||
}
|
||||
|
||||
/** parse the <map> node */
|
||||
@@ -266,7 +268,9 @@ namespace Floorplan {
|
||||
const XMLElem* sub = n->FirstChildElement();
|
||||
while(sub) {
|
||||
// <entry key="123">abc</entry>
|
||||
elem->add(sub->Attribute("key"), sub->FirstChild()->Value());
|
||||
const std::string key = sub->Attribute("key");
|
||||
const std::string val = sub->GetText();
|
||||
elem->add(key, val);
|
||||
sub = sub->NextSiblingElement();
|
||||
}
|
||||
return elem;
|
||||
@@ -402,7 +406,7 @@ namespace Floorplan {
|
||||
FloorOutline outline;
|
||||
FOREACH_NODE(n, el) {
|
||||
if (std::string("polygon") == n->Name()) {
|
||||
outline.push_back(parseFloorPolygon(n)); // TODO
|
||||
outline.push_back(parseFloorPolygon(n));
|
||||
}
|
||||
}
|
||||
return outline;
|
||||
@@ -427,6 +431,9 @@ namespace Floorplan {
|
||||
poly.points.push_back(p2);
|
||||
}
|
||||
}
|
||||
if (poly.points.size() < 4 || poly.points.size() > 1024) {
|
||||
throw Exception("detected invalid outline-polygon during XML parsing");
|
||||
}
|
||||
return poly;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user