/* * © 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 MAPMODEL_H #define MAPMODEL_H #include #include "../../fixC11.h" #include "MapLayer.h" #include "MapModelElement.h" #include "MapModelListener.h" #include "MMRoot.h" #include #include #include class MapModel : public QObject, public MapLayerListener { Q_OBJECT private: /** the map's root-layer containing all other layers */ MapLayer* root = nullptr; /** the currently selected layer (if any) */ MapLayer* selLayer = nullptr; /** the loaded floorplan */ Floorplan::IndoorMap* im; /** listener */ std::vector listeners; public: /** ctor */ MapModel() { root = new MapLayerRoot(nullptr); } virtual ~MapModel() { cleanup(); } /** attach a listener */ void addListener(MapModelListener* l) { listeners.push_back(l); } /** create a new, empty root node */ void startEmpty() { emit aboutToReset(); cleanup(); im = new Floorplan::IndoorMap(); root = new MMRoot(nullptr, im); root->addListener(this); //root->addSublayer(new MMFloors(root, im)); emit reset(); } void cleanup() { selLayer = nullptr; //selElements.clear(); if (root) {delete root; root = nullptr;} } /** load map from file */ void load(const std::string& file) { emit aboutToReset(); cleanup(); // load the indoor-map using the given XML-file im = Floorplan::Reader::readFromFile(file); Floorplan::LINT::assertOK(im); root = new MMRoot(nullptr, im); root->addListener(this); emit reset(); } /** save map to file */ void save(const std::string& file) { Floorplan::Writer::writeToFile(im, file); } float snap(const float val) { const float s = 0.1; return std::round(val / s) * s; } /** resize everything within the floorplay by the given factor */ void resize(const float sx, const float sy, const float sz, const float ox, const float oy, const float oz) { for (Floorplan::Floor* f : im->floors) { f->atHeight = snap(f->atHeight * sz); f->height = snap(f->height * sz); for (Floorplan::FloorOutlinePolygon* poly : f->outline) { for (Point2& p : poly->poly.points) { p.x = snap(p.x * sx + ox); p.y = snap(p.y * sy + oy); } } for (Floorplan::AccessPoint* ap : f->accesspoints) { ap->pos.x = snap(ap->pos.x * sx + ox); ap->pos.y = snap(ap->pos.y * sy + oy); ap->pos.z = snap(ap->pos.z * sz + oz); } for (Floorplan::Beacon* b : f->beacons) { b->pos.x = snap(b->pos.x * sx + ox); b->pos.y = snap(b->pos.y * sy + oy); b->pos.z = snap(b->pos.z * sz + oz); } for (Floorplan::POI* p : f->pois) { p->pos.x = snap(p->pos.x * sx + ox); p->pos.y = snap(p->pos.y * sy + oy); } for (Floorplan::FingerprintLocation* fpl : f->fpLocations) { fpl->posOnFloor.x = snap(fpl->posOnFloor.x * sx + ox); fpl->posOnFloor.y = snap(fpl->posOnFloor.y * sy + oy); fpl->heightAboveFloor = snap(fpl->heightAboveFloor * sz + oz); } for (Floorplan::FloorObstacle* o : f->obstacles) { Floorplan::FloorObstacleLine* line = dynamic_cast(o); Floorplan::FloorObstacleDoor* door = dynamic_cast(o); if (line) { line->from.x = snap(line->from.x * sx + ox); line->from.y = snap(line->from.y * sy + oy); line->to.x = snap(line->to.x * sx + ox); line->to.y = snap(line->to.y * sy + oy); } else if (door) { door->from.x = snap(door->from.x * sx + ox); door->from.y = snap(door->from.y * sy + oy); door->to.x = snap(door->to.x * sx + ox); door->to.y = snap(door->to.y * sy + oy); } } for (Floorplan::Stair* s : f->stairs) { Floorplan::StairFreeform* stair = dynamic_cast(s); for (Floorplan::StairPart& sp : stair->parts) { sp.width = snap(sp.width * sx); sp.end.x = snap(sp.end.x * sx + ox); sp.end.y = snap(sp.end.y * sy + oy); sp.end.z = snap(sp.end.z * sz + oz); sp.start.x = snap(sp.start.x * sx + ox); sp.start.y = snap(sp.start.y * sy + oy); sp.start.z = snap(sp.start.z * sz + oz); } } for (Floorplan::Elevator* e : f->elevators) { e->center.x = snap(e->center.x * sx + ox); e->center.y = snap(e->center.y * sy + oy); e->width = snap(e->width * sx); e->depth = snap(e->depth * sx); } } } void onLayerChanged(MapLayer* layer) override { for (MapModelListener* l : listeners) {l->onLayerChanged(layer);} } void onLayerElementAdded(MapLayer* layer, MapModelElement* elem) override { for (MapModelListener* l : listeners) {l->onLayerElementAdded(layer, elem);} } void onLayerElementRemoved(MapLayer* layer, const MapModelElement* elem) override { for (MapModelListener* l : listeners) {l->onLayerElementRemoved(layer, elem);} } void onLayerVisibilityChanged(MapLayer* layer, const bool visible) override { for (MapModelListener* l : listeners) {l->onLayerVisibilityChanged(layer, visible);} } /** get the constructed map */ Floorplan::IndoorMap* getMap() const { return im; } /** get the map's root-layer containing all other layers */ MapLayer* getRootLayer() { return root; } // /** get all elements within the currently selected layer */ // std::vector getSelectedLayerElements() { // //return selElements; // //return (selLayer) ? (selLayer->getElementsRecursive()) : (std::vector()); //// std::vector elements; //// root->getVisibleElementsRecursive(elements); //// return elements; // } /** get all currently visible elements */ std::vector getVisibleElements() { std::vector elements; root->getVisibleElementsRecursive(elements); return elements; } /** set the currently selected layer */ void setSelectedLayer(MapLayer* ml) { //selElements.clear(); //for (MapModelElement* el : ml->getElementsRecursive()) {selElements.push_back(el);} selLayer = ml; } /** get the currently selected layer */ MapLayer* getSelectedLayer() const { return selLayer; } void reselect() { setSelectedLayer(selLayer); emit reset(); } signals: void aboutToReset(); void reset(); }; #endif // MAPMODEL_H