added a ruler for measuring

added support for meta-data editing
improved element selection
changed zooming
fixed some issues with layer events
fixed issue with 3D outline
fixed loading issue for old maps
some interface changes
This commit is contained in:
2017-03-10 13:44:17 +01:00
parent 2297a76c53
commit f40fc9a823
32 changed files with 809 additions and 198 deletions

View File

@@ -0,0 +1,21 @@
#ifndef IHASEDITABLEMETA_H
#define IHASEDITABLEMETA_H
#include <Indoor/floorplan/v2/Floorplan.h>
/**
* interface for all classes that provide editable meta information
*/
class IHasEditableMeta {
public:
/** get the meta-information object [if any] */
virtual Floorplan::Meta* getMeta() = 0;
/** set/overwrite the meta-information object */
virtual void setMeta(Floorplan::Meta* meta) = 0;
};
#endif // IHASEDITABLEMETA_H

View File

@@ -36,7 +36,7 @@ public:
MMFloor(MapLayer* parent, Floorplan::IndoorMap* map, Floorplan::Floor* floor) : MapLayer(parent, MapLayerType::FLOOR), map(map), floor(floor) {
new MMFloorUnderlays(this, floor);
elements.push_back(new MMFloorOutline(this, floor));
new MMFloorOutline(this, floor);
new MMFloorObstacles(this, floor);
new MMFloorAccessPoints(this, floor);
new MMFloorBeacons(this, floor);

View File

@@ -3,13 +3,14 @@
#include "MapModelElement.h"
#include "IHasParams.h"
#include "IHasEditableMeta.h"
#include "../2D/MV2DElementAccessPoint.h"
#include "../3D/MV3DElementAccessPoint.h"
#include <Indoor/floorplan/v2/Floorplan.h>
class MMFloorAccessPoint : public MapModelElement, public IHasParams {
class MMFloorAccessPoint : public MapModelElement, public IHasParams, public IHasEditableMeta {
private:
@@ -64,6 +65,14 @@ public:
}
}
virtual Floorplan::Meta* getMeta() override {
return ap->getMeta();
}
virtual void setMeta(Floorplan::Meta* meta) override {
ap->setMeta(meta);
}
MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;}
MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;}

View File

@@ -22,7 +22,7 @@ public:
// add all APs
for (Floorplan::AccessPoint* ap : floor->accesspoints) {
elements.push_back(new MMFloorAccessPoint(this, floor, ap));
addElement(new MMFloorAccessPoint(this, floor, ap));
}
}
@@ -36,7 +36,7 @@ public:
floor->accesspoints.push_back(ap);
// add to myself as element
elements.push_back(new MMFloorAccessPoint(this, floor, ap));
addElement(new MMFloorAccessPoint(this, floor, ap));
}

View File

@@ -22,7 +22,7 @@ public:
// add all Beacons
for (Floorplan::Beacon* b : floor->beacons) {
elements.push_back(new MMFloorBeacon(this, floor, b));
addElement(new MMFloorBeacon(this, floor, b));
}
}
@@ -36,7 +36,7 @@ public:
floor->beacons.push_back(b);
// add to myself as element
elements.push_back(new MMFloorBeacon(this, floor, b));
addElement(new MMFloorBeacon(this, floor, b));
}
};

View File

@@ -23,7 +23,7 @@ public:
// add all elevators
for (Floorplan::Elevator* elevator : floor->elevators) {
elements.push_back(new MMFloorElevator(this, floor, elevator));
addElement(new MMFloorElevator(this, floor, elevator));
}
}
@@ -37,7 +37,7 @@ public:
floor->elevators.push_back(elevator);
// add to myself as element
elements.push_back(new MMFloorElevator(this, floor, elevator));
addElement(new MMFloorElevator(this, floor, elevator));
}

View File

@@ -23,11 +23,11 @@ public:
// the obstacles
for (Floorplan::FloorObstacle* o : floor->obstacles) {
if (dynamic_cast<Floorplan::FloorObstacleLine*>(o)) {
elements.push_back(new MMFloorObstacleLine(this, floor, (Floorplan::FloorObstacleLine*)o));
addElement(new MMFloorObstacleLine(this, floor, (Floorplan::FloorObstacleLine*)o));
} else if (dynamic_cast<Floorplan::FloorObstacleCircle*>(o)) {
elements.push_back(new MMFloorObstacleCircle(this, floor, (Floorplan::FloorObstacleCircle*)o));
addElement(new MMFloorObstacleCircle(this, floor, (Floorplan::FloorObstacleCircle*)o));
} else if (dynamic_cast<Floorplan::FloorObstacleDoor*>(o)) {
elements.push_back(new MMFloorObstacleDoor(this, floor, (Floorplan::FloorObstacleDoor*)o));
addElement(new MMFloorObstacleDoor(this, floor, (Floorplan::FloorObstacleDoor*)o));
} else {
throw new Exception("todo: not yet implemented obstacle type");
}
@@ -46,7 +46,7 @@ public:
// add to myself as element
MMFloorObstacleDoor* mm = new MMFloorObstacleDoor(this, floor, obs);
elements.push_back(mm);
addElement(mm);
return mm;
}
@@ -59,7 +59,7 @@ public:
// add to myself as element
MMFloorObstacleLine* mm = new MMFloorObstacleLine(this, floor, obs);
elements.push_back(mm);
addElement(mm);
return mm;
}
@@ -71,7 +71,7 @@ public:
floor->obstacles.push_back(obs);
// add to myself as element
elements.push_back(new MMFloorObstacleCircle(this, floor, obs));
addElement(new MMFloorObstacleCircle(this, floor, obs));
}

View File

@@ -3,37 +3,38 @@
#include "MapLayer.h"
#include "MMFloorOutlinePolygon.h"
#include "../3D/MV3DElementFloorOutline.h"
#include "MMFloorOutlinePolygonCombined.h"
#include "../3D/MV3DElementFloorOutline.h"
#include <Indoor/floorplan/v2/Floorplan.h>
/**
* layer containing all elements describing a floor's outline
*/
class MMFloorOutline : public MapLayer, public MapModelElement {
class MMFloorOutline : public MapLayer {
private:
/** the underlying model */
Floorplan::Floor* floor;
MV3DElementFloorOutline mv3d;
public:
/** ctor with the underlying model */
MMFloorOutline(MapLayer* parent, Floorplan::Floor* floor) :
MapLayer(parent, MapLayerType::FLOOR_GROUND), MapModelElement(parent), floor(floor), mv3d(floor, &floor->outline) {
MapLayer(parent, MapLayerType::FLOOR_GROUND), floor(floor) {
// the outline
// each polygon that is part of the outline
for (Floorplan::FloorOutlinePolygon* poly : floor->outline) {
elements.push_back(new MMFloorOutlinePolygon(this, floor, poly));
addElement(new MMFloorOutlinePolygon(this, floor, poly));
}
}
// for 3D, alle polygons [add/remove] are combined into one renderable polygons
addElement(new MMFloorOutlinePolygonCombined(this, floor));
MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;}
}
/** get the corresponding floor from the underlying model */
@@ -46,7 +47,7 @@ public:
floor->outline.push_back(poly);
// add to myself as element
elements.push_back(new MMFloorOutlinePolygon(this, floor, poly));
addElement(new MMFloorOutlinePolygon(this, floor, poly));
}

View File

@@ -0,0 +1,41 @@
#ifndef MMFLOOROUTLINEPOLYGONCOMBINED_H
#define MMFLOOROUTLINEPOLYGONCOMBINED_H
#include "MapLayer.h"
#include "MMFloorOutlinePolygon.h"
#include "../3D/MV3DElementFloorOutline.h"
#include <Indoor/floorplan/v2/Floorplan.h>
/**
* this element combines all polygons of one layer
* into one large, 3D renderable polygon
*/
class MMFloorOutlinePolygonCombined : public MapModelElement {
private:
/** the underlying model */
Floorplan::Floor* floor;
MV3DElementFloorOutline mv3d;
public:
/** ctor with the underlying model */
MMFloorOutlinePolygonCombined(MapLayer* parent, Floorplan::Floor* floor) :
MapModelElement(parent), floor(floor), mv3d(floor, &floor->outline) {
;
}
MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;}
/** get the corresponding floor from the underlying model */
Floorplan::Floor* getFloor() {return floor;}
};
#endif // MMFLOOROUTLINEPOLYGONCOMBINED_H

View File

@@ -20,7 +20,7 @@ public:
// the POIs
for (Floorplan::POI* poi : floor->pois) {
elements.push_back(new MMFloorPOI(this, floor, poi));
addElement(new MMFloorPOI(this, floor, poi));
}
}
@@ -35,7 +35,7 @@ public:
floor->pois.push_back(poi);
// add to myself as element
elements.push_back(new MMFloorPOI(this, floor, poi));
addElement(new MMFloorPOI(this, floor, poi));
}

View File

@@ -23,7 +23,7 @@ public:
// add all floors
for (Floorplan::Stair* stair : floor->stairs) {
if (dynamic_cast<Floorplan::StairFreeform*>(stair)) {
elements.push_back( new MMFloorStair(this, floor, (Floorplan::StairFreeform*)stair) );
addElement( new MMFloorStair(this, floor, (Floorplan::StairFreeform*)stair) );
}
}
@@ -35,7 +35,7 @@ public:
floor->stairs.push_back(stair);
// add to myself as element
elements.push_back(new MMFloorStair(this, floor, stair));
addElement(new MMFloorStair(this, floor, stair));
}

View File

@@ -23,7 +23,7 @@ public:
// the underlays
for (Floorplan::UnderlayImage* img : floor->underlays) {
elements.push_back(new MMFloorUnderlayImage(this, floor, img));
addElement(new MMFloorUnderlayImage(this, floor, img));
}
}
@@ -38,7 +38,7 @@ public:
// add to myself as element
MMFloorUnderlayImage* img = new MMFloorUnderlayImage(this, floor, elem);
elements.push_back(img);
addElement(img);
img->setAnchor(center);
img->setScale(0.1, 0.1);

View File

@@ -5,6 +5,8 @@
#include <vector>
#include <algorithm>
#include "MapLayerListener.h"
class MapModelElement;
@@ -27,14 +29,17 @@ enum class MapLayerType {
class MapLayer {
/** this layer's elements */
std::vector<MapModelElement*> elements;
/** attached listeners (if any) */
std::vector<MapLayerListener*> listeners;
protected:
/** this layer's parent */
MapLayer* parent;
/** this layer's elements */
std::vector<MapModelElement*> elements;
/** this layer's sublayers */
std::vector<MapLayer*> sublayers;
@@ -59,6 +64,11 @@ public:
/** dtor */
virtual ~MapLayer() {;}
/** attach a listener to this layer [usually only added to the root layer] */
void addListener(MapLayerListener* listener) {
listeners.push_back(listener);
}
/** get the layer's parent */
MapLayer* getParent() const {return parent;}
@@ -76,7 +86,16 @@ public:
size_t getNumElements() const {return elements.size();}
/** remove the given element from the elements list */
void removeElement(const MapModelElement* elem) { elements.erase(std::remove(elements.begin(), elements.end(), elem), elements.end()); }
void removeElement(const MapModelElement* elem) {
elements.erase(std::remove(elements.begin(), elements.end(), elem), elements.end());
onElemRemoved(elem);
}
/** add a new element to this layer */
void addElement(MapModelElement* el) {
elements.push_back(el);
onElemAdded(el);
}
/** remove the given sublayer from this layer */
void removeSublayer(const MapLayer* layer) { sublayers.erase(std::remove(sublayers.begin(), sublayers.end(), layer), sublayers.end()); }
@@ -85,7 +104,10 @@ public:
bool isVisible() const {return visible;}
/** make this layer visible */
void setVisible(const bool visible) {this->visible = visible;}
void setVisible(const bool visible) {
this->visible = visible;
onVisibilityChanged(visible);
}
/** get all sub-layers within this layer */
@@ -95,7 +117,7 @@ public:
/** helper method to get all elements and those of all sub-layers */
void getVisibleElementsRecursive(std::vector<MapModelElement*>& el) {
if (isVisible()) {
std::vector<MapModelElement*> local = getElements();
const std::vector<MapModelElement*> local = getElements();
el.insert(el.end(), local.begin(), local.end());
for (MapLayer* sub : getSubLayers()) {
sub->getVisibleElementsRecursive(el);
@@ -105,8 +127,6 @@ public:
public:
/** add a new sublayer to this layer */
void addSublayer(MapLayer* ml) {
@@ -116,8 +136,35 @@ public:
}
private:
void onElemAdded(MapModelElement* e) {
if (parent) {parent->onElemAdded(e);}
for (MapLayerListener* listener : listeners) {
listener->onLayerChanged(this);
listener->onLayerElementAdded(this, e);
}
}
void onElemRemoved(const MapModelElement* e) {
if (parent) {parent->onElemRemoved(e);}
for (MapLayerListener* listener : listeners) {
listener->onLayerChanged(this);
listener->onLayerElementRemoved(this, e);
}
}
void onVisibilityChanged(const bool visibile) {
if (parent) {parent->onVisibilityChanged(visibile);}
for (MapLayerListener* listener : listeners) {
listener->onLayerChanged(this);
listener->onLayerVisibilityChanged(this, visibile);
}
}
};
class MapLayerRoot : public MapLayer {
public:

View File

@@ -0,0 +1,25 @@
#ifndef MAPLAYERLISTENER_H
#define MAPLAYERLISTENER_H
class MapLayer;
class MapModelElement;
class MapLayerListener {
public:
/** the map layer has changed. e.g. new elements were added */
virtual void onLayerChanged(MapLayer* layer) = 0;
/** a new element was added to a layer */
virtual void onLayerElementAdded(MapLayer* layer, MapModelElement* elem) = 0;
/** an element was removed from the layer */
virtual void onLayerElementRemoved(MapLayer* layer, const MapModelElement* elem) = 0;
/** the layer's visibility has changed */
virtual void onLayerVisibilityChanged(MapLayer* layer, const bool visible) = 0;
};
#endif // MAPLAYERLISTENER_H

View File

@@ -5,6 +5,7 @@
#include "MapLayer.h"
#include "MapModelElement.h"
#include "MapModelListener.h"
#include "MMRoot.h"
@@ -13,7 +14,7 @@
#include <Indoor/floorplan/v2/FloorplanReader.h>
#include <Indoor/floorplan/v2/FloorplanWriter.h>
class MapModel : public QObject {
class MapModel : public QObject, public MapLayerListener {
Q_OBJECT
@@ -31,6 +32,9 @@ private:
/** the loaded floorplan */
Floorplan::IndoorMap* im;
/** listener */
std::vector<MapModelListener*> listeners;
public:
/** ctor */
@@ -42,10 +46,16 @@ public:
cleanup();
}
/** attach a listener */
void addListener(MapModelListener* l) {
listeners.push_back(l);
}
/** create a new, empty root node */
void startEmpty() {
im = new Floorplan::IndoorMap();
root = new MMRoot(nullptr, im);
root->addListener(this);
//root->addSublayer(new MMFloors(root, im));
}
@@ -64,6 +74,7 @@ public:
// load the indoor-map using the given XML-file
im = Floorplan::Reader::readFromFile(file);
root = new MMRoot(nullptr, im);
root->addListener(this);
emit reset();
@@ -75,6 +86,22 @@ public:
}
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;
@@ -83,18 +110,21 @@ public:
/** get the map's root-layer containing all other layers */
MapLayer* getRootLayer() { return root; }
/** get all elements within the currently selected layer */
std::vector<MapModelElement*> getSelectedLayerElements() {
//return selElements;
//return (selLayer) ? (selLayer->getElementsRecursive()) : (std::vector<MapModelElement*>());
std::vector<MapModelElement*> elements;
root->getVisibleElementsRecursive(elements);
return elements;
}
// /** get all elements within the currently selected layer */
// std::vector<MapModelElement*> getSelectedLayerElements() {
// //return selElements;
// //return (selLayer) ? (selLayer->getElementsRecursive()) : (std::vector<MapModelElement*>());
//// std::vector<MapModelElement*> elements;
//// root->getVisibleElementsRecursive(elements);
//// return elements;
// }
/** get all currently visible elements */
std::vector<MapModelElement*> getVisibleElements() {
return getSelectedLayerElements();
std::vector<MapModelElement*> elements;
root->getVisibleElementsRecursive(elements);
return elements;
}
/** set the currently selected layer */

View File

@@ -0,0 +1,13 @@
#ifndef MAPMODELLISTENER_H
#define MAPMODELLISTENER_H
#include "MapLayerListener.h"
/**
* listen for changes to the map model
*/
class MapModelListener : public MapLayerListener {
};
#endif // MAPMODELLISTENER_H