#ifndef WIFIMODELPERBBOX_H #define WIFIMODELPERBBOX_H #include "../AccessPoint.h" #include "../../../geo/Point3.h" #include "../../../geo/BBoxes3.h" #include #include "WiFiModelFactory.h" /** * FOR TESTING * * this model allows using a different sub-models * identified by a bound-box to reduce the error */ class WiFiModelPerBBox : public WiFiModel { struct ModelForBBoxes { WiFiModel* mdl; BBoxes3 bboxes; /** ctor */ ModelForBBoxes(WiFiModel* mdl, BBoxes3 bboxes) : mdl(mdl), bboxes(bboxes) {;} /** does this entry apply to the given position? */ bool matches(const Point3 pt) const { if (bboxes.get().empty()) {throw Exception("no bbox(es) given for model!");} return bboxes.contains(pt); } }; Floorplan::IndoorMap* map; /** all contained models [one per bbox] */ std::vector models; public: WiFiModelPerBBox(Floorplan::IndoorMap* map) : map(map) { ; } /** dtor */ virtual ~WiFiModelPerBBox() { } /** get a list of all APs known to the model */ std::vector getAllAPs() const override { // combine all submodels std::vector res; for (const ModelForBBoxes& sub : models) { for (const AccessPoint& ap : sub.mdl->getAllAPs()) { if (std::find(res.begin(), res.end(), ap) == res.end()) { // TODO use map instead? res.push_back(ap); } } } return res; } void add(WiFiModel* mdl, const BBoxes3 bboxes) { if (bboxes.get().empty()) {throw Exception("no bbox(es) given for model!");} ModelForBBoxes mfb(mdl, bboxes); models.push_back(mfb); } float getRSSI(const MACAddress& accessPoint, const Point3 position_m) const override { for (const ModelForBBoxes& mfb : models) { if (mfb.matches(position_m)) {return mfb.mdl->getRSSI(accessPoint, position_m);} } return -120; } void readFromXML(XMLDoc* doc, XMLElem* src) override { // check type if (std::string("WiFiModelPerBBox") != src->Attribute("type")) {throw Exception("invalid model type");} models.clear(); // model factory [create models based on XMl content] WiFiModelFactory fac(map); // parse all contained models [one per floor] XML_FOREACH_ELEM_NAMED("entry", xentry, src) { // all bboxes BBoxes3 bboxes; XML_FOREACH_ELEM_NAMED("bbox", xbbox, xentry) { const float x1 = xbbox->FloatAttribute("x1"); const float y1 = xbbox->FloatAttribute("y1"); const float z1 = xbbox->FloatAttribute("z1"); const float x2 = xbbox->FloatAttribute("x2"); const float y2 = xbbox->FloatAttribute("y2"); const float z2 = xbbox->FloatAttribute("z2"); const BBox3 bbox(Point3(x1,y1,z1), Point3(x2,y2,z2)); bboxes.add(bbox); } // node for the model XMLElem* xmodel = xentry->FirstChildElement("model"); // let the factory instantiate the model WiFiModel* mdl = fac.readFromXML(doc, xmodel); // add models.push_back(ModelForBBoxes(mdl, bboxes)); } } void writeToXML(XMLDoc* doc, XMLElem* dst) override { // set my type dst->SetAttribute("type", "WiFiModelPerBBox"); for (const ModelForBBoxes& mfb : models) { // all models XMLElem* xentry = doc->NewElement("entry"); { // each bbox for (const BBox3& bbox : mfb.bboxes.get()) { XMLElem* xbbox = doc->NewElement("bbox"); { xbbox->SetAttribute("x1", bbox.getMin().x); xbbox->SetAttribute("y1", bbox.getMin().y); xbbox->SetAttribute("z1", bbox.getMin().z); xbbox->SetAttribute("x2", bbox.getMax().x); xbbox->SetAttribute("y2", bbox.getMax().y); xbbox->SetAttribute("z2", bbox.getMax().z); }; xentry->InsertFirstChild(xbbox); } // the corresponding model XMLElem* xmodel = doc->NewElement("model"); { mfb.mdl->writeToXML(doc, xmodel); }; xentry->InsertEndChild(xmodel); }; dst->InsertEndChild(xentry); } } }; #endif // WIFIMODELPERBBOX_H