initial commit
This commit is contained in:
90
mapview/MapView2D.cpp
Normal file
90
mapview/MapView2D.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#include "MapView2D.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QMouseEvent>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "model/MapModelElement.h"
|
||||
#include "model/MapModel.h"
|
||||
|
||||
MapView2D::MapView2D(QWidget* parent) : QOpenGLWidget(parent) {
|
||||
|
||||
// openGL params
|
||||
QSurfaceFormat format;
|
||||
format.setDepthBufferSize(24);
|
||||
format.setStencilBufferSize(8);
|
||||
format.setSamples(1);
|
||||
// format.setVersion(3, 2);
|
||||
format.setProfile(QSurfaceFormat::CoreProfile);
|
||||
setFormat(format);
|
||||
|
||||
// receive mouse-move even when mouse is not down
|
||||
setMouseTracking(true);
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
|
||||
// defaults
|
||||
s.setScale(5);
|
||||
|
||||
}
|
||||
|
||||
void MapView2D::paintGL() {
|
||||
|
||||
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
|
||||
f->glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
QPainter qp(this);
|
||||
Painter p(s, &qp, width(), height());
|
||||
s.setScreenSize(width(), height());
|
||||
|
||||
// background tools
|
||||
tools.paintBefore(this, p);
|
||||
|
||||
// render all visible elements
|
||||
qp.setRenderHint( QPainter::Antialiasing, true );
|
||||
for (MapModelElement* el : getModel()->getVisibleElements()) {el->getMV2D()->paint(p);}
|
||||
qp.setRenderHint( QPainter::Antialiasing, false );
|
||||
|
||||
// foreground tools
|
||||
tools.paintAfter(this, p);
|
||||
|
||||
}
|
||||
|
||||
void MapView2D::initializeGL() {
|
||||
|
||||
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
|
||||
f->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
}
|
||||
|
||||
void MapView2D::resizeGL() {
|
||||
// TODO ?
|
||||
}
|
||||
|
||||
|
||||
void MapView2D::keyPressEvent(QKeyEvent *e) {
|
||||
tools.keyPressEvent(this, e);
|
||||
update();
|
||||
}
|
||||
|
||||
void MapView2D::wheelEvent(QWheelEvent* e) {
|
||||
tools.wheelEvent(this, e);
|
||||
update();
|
||||
}
|
||||
|
||||
void MapView2D::mousePressEvent(QMouseEvent* e) {
|
||||
tools.mousePressEvent(this, e);
|
||||
update();
|
||||
}
|
||||
|
||||
void MapView2D::mouseMoveEvent(QMouseEvent* e) {
|
||||
tools.mouseMoveEvent(this, e);
|
||||
update();
|
||||
}
|
||||
|
||||
void MapView2D::mouseReleaseEvent(QMouseEvent* e) {
|
||||
tools.mouseReleaseEvent(this, e);
|
||||
update();
|
||||
}
|
||||
76
mapview/MapView2D.h
Normal file
76
mapview/MapView2D.h
Normal file
@@ -0,0 +1,76 @@
|
||||
#ifndef MAP2D_H
|
||||
#define MAP2D_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QOpenGLWidget>
|
||||
|
||||
#include "Scaler.h"
|
||||
class MapModel;
|
||||
#include "mapview/tools/Tools.h"
|
||||
|
||||
|
||||
/**
|
||||
* view to render (and edit) MapElements
|
||||
*/
|
||||
class MapView2D : public QOpenGLWidget {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/** scaling within the map */
|
||||
Scaler s;
|
||||
|
||||
/** the currently active tool (if any) */
|
||||
Tools tools;
|
||||
|
||||
/** the underlying data-model */
|
||||
MapModel* model = nullptr;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
MapView2D(QWidget* parent = nullptr);
|
||||
|
||||
void layerChange() {
|
||||
update();
|
||||
tools.layerChange(this);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void paintGL();
|
||||
void initializeGL();
|
||||
void resizeGL();
|
||||
|
||||
|
||||
Tools& getTools() {return tools;}
|
||||
|
||||
/** get the underlying data-model */
|
||||
MapModel* getModel() {return model;}
|
||||
|
||||
/** set the underlying data-model */
|
||||
void setModel(MapModel* mdl) {
|
||||
this->model = mdl;
|
||||
update();
|
||||
}
|
||||
|
||||
/** get the underlying scaling device */
|
||||
Scaler& getScaler() {return s;}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void mousePressEvent(QMouseEvent* e);
|
||||
void mouseMoveEvent(QMouseEvent* e);
|
||||
void mouseReleaseEvent(QMouseEvent* e);
|
||||
|
||||
void wheelEvent(QWheelEvent* e);
|
||||
|
||||
void keyPressEvent(QKeyEvent* e);
|
||||
|
||||
};
|
||||
|
||||
#endif // MAP2D_H
|
||||
102
mapview/Painter.h
Normal file
102
mapview/Painter.h
Normal file
@@ -0,0 +1,102 @@
|
||||
#ifndef PAINTER_H
|
||||
#define PAINTER_H
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
#include <Indoor/geo/Point2.h>
|
||||
#include <Indoor/geo/Point3.h>
|
||||
|
||||
#include "Scaler.h"
|
||||
|
||||
class Painter {
|
||||
|
||||
public:
|
||||
|
||||
Scaler& s;
|
||||
QPainter* p;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
Painter(Scaler& s, QPainter* p, int w, int h) : s(s), p(p), w(w), h(h) {
|
||||
p->setPen(Qt::black);
|
||||
p->setBrush(Qt::NoBrush);
|
||||
}
|
||||
|
||||
int width() {return w;}
|
||||
|
||||
int height() {return h;}
|
||||
|
||||
void drawLine(const Point2 p1, const Point2 p2) {
|
||||
p->drawLine(s.xms(p1.x), s.yms(p1.y), s.xms(p2.x), s.yms(p2.y));
|
||||
}
|
||||
void drawLine(const Point3 p1, const Point3 p2) {
|
||||
p->drawLine(s.xms(p1.x), s.yms(p1.y), s.xms(p2.x), s.yms(p2.y));
|
||||
}
|
||||
|
||||
void drawCircle(const Point3 center) {
|
||||
int r = 5;
|
||||
p->drawEllipse(s.xms(center.x)-r, s.yms(center.y)-r, 2*r, 2*r);
|
||||
}
|
||||
|
||||
void drawCircle(const Point2 center) {
|
||||
int r = 5;
|
||||
p->drawEllipse(s.xms(center.x)-r, s.yms(center.y)-r, 2*r, 2*r);
|
||||
}
|
||||
|
||||
void drawCircle(const Point2 center, const float size_m) {
|
||||
int r = s.ms(size_m);
|
||||
p->drawEllipse(s.xms(center.x)-r, s.yms(center.y)-r, 2*r, 2*r);
|
||||
}
|
||||
|
||||
void drawLine(const float x1, const float y1, const float x2, const float y2) {
|
||||
p->drawLine(s.xms(x1), s.yms(y1), s.xms(x2), s.yms(y2));
|
||||
}
|
||||
|
||||
void drawRect(const float x1, const float y1, const float x2, const float y2) {
|
||||
float w = x2-x1;
|
||||
float h = y1-y2;
|
||||
p->drawRect(s.xms(x1), s.yms(y1), s.ms(w), s.ms(h));
|
||||
}
|
||||
|
||||
void drawText(const Point2 pos, const std::string& text) {
|
||||
p->drawText(s.xms(pos.x), s.xms(pos.y), text.c_str());
|
||||
}
|
||||
|
||||
void drawPolygon(const std::vector<Point2>& points) {
|
||||
std::vector<QPointF> vec;
|
||||
for (const Point2 p : points) {
|
||||
vec.push_back(QPointF(s.xms(p.x), s.yms(p.y)));
|
||||
}
|
||||
p->drawPolygon(vec.data(), vec.size());
|
||||
}
|
||||
void drawPolygon(const std::vector<Point3>& points) {
|
||||
std::vector<QPointF> vec;
|
||||
for (const Point3 p : points) {
|
||||
vec.push_back(QPointF(s.xms(p.x), s.yms(p.y)));
|
||||
}
|
||||
p->drawPolygon(vec.data(), vec.size());
|
||||
}
|
||||
|
||||
void setBrush(const QBrush& brush) { p->setBrush(brush); }
|
||||
void setBrush(const Qt::BrushStyle& brush) { p->setBrush(brush); }
|
||||
|
||||
void setPen(const QPen& pen) {p->setPen(pen); }
|
||||
void setPen(const QColor& pen) {p->setPen(pen); }
|
||||
void setPen(const Qt::PenStyle& pen) {p->setPen(pen); }
|
||||
|
||||
|
||||
|
||||
template <typename Pen, typename Brush> void setPenBrush(const Pen& pen, const Brush& brush) {setPen(pen); setBrush(brush);}
|
||||
|
||||
const Scaler& getScaler() {return s;}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // PAINTER_H
|
||||
104
mapview/Scaler.h
Normal file
104
mapview/Scaler.h
Normal file
@@ -0,0 +1,104 @@
|
||||
#ifndef SCALER_H
|
||||
#define SCALER_H
|
||||
|
||||
#include <Indoor/geo/Point3.h>
|
||||
|
||||
#include <QRectF>
|
||||
|
||||
struct Rect {
|
||||
float x0;
|
||||
float y0;
|
||||
float x1;
|
||||
float y1;
|
||||
};
|
||||
|
||||
/**
|
||||
* - scale between map- and screen-space.
|
||||
* - inverts y-axis (for openGL)
|
||||
*/
|
||||
class Scaler {
|
||||
|
||||
private:
|
||||
|
||||
int w;
|
||||
int h;
|
||||
float _scale = 50;
|
||||
float _snap = 0.1;
|
||||
Point3 _offset;
|
||||
|
||||
public:
|
||||
|
||||
/** map->screen (no offset) */
|
||||
float ms(const float m) const {return m*_scale;}
|
||||
/** x map->screen */
|
||||
float xms(const float x) const {return w/2+(x+_offset.x)*_scale;}
|
||||
/** x map->screen */
|
||||
float yms(const float y) const {return h/2-(y-_offset.y)*_scale;}
|
||||
|
||||
|
||||
/** screen->map (no offset) */
|
||||
float sm(const float s) const {return (s/_scale);}
|
||||
/** x screen->map */
|
||||
float xsm(const float x) const {return ((x-w/2)/_scale)-_offset.x;}
|
||||
/** y screen->map */
|
||||
float ysm(const float y) const {return ((h/2-y)/_scale)+_offset.y;}
|
||||
|
||||
void setScale(const float s) {_scale = s;}
|
||||
float getScale() const {return _scale;}
|
||||
|
||||
void setOffset(Point3 p) {_offset = p;}
|
||||
Point3 getOffset() const {return _offset;}
|
||||
void addOffset(int px, int py) {_offset.x += sm(px); _offset.y += sm(py);}
|
||||
|
||||
float getLODstep() const {
|
||||
float step = 0.01;
|
||||
if (_scale <= 1000) {step = 0.1;}
|
||||
if (_scale <= 500) {step = 0.5;}
|
||||
if (_scale <= 100) {step = 1.0;}
|
||||
if (_scale <= 50) {step = 5.0;}
|
||||
if (_scale <= 10) {step = 10.0;}
|
||||
if (_scale <= 1) {step = 100.0;}
|
||||
return step;
|
||||
}
|
||||
|
||||
/** get the currently visible map-region given the provided screen-size */
|
||||
Rect getMapVisible(const int screenW, const int screenH) const {
|
||||
Rect r;
|
||||
r.x0 = xsm(0);
|
||||
r.x1 = xsm(screenW);
|
||||
r.y0 = ysm(screenH);
|
||||
r.y1 = ysm(0);
|
||||
return r;
|
||||
}
|
||||
|
||||
/** get the currently visible map-region given the provided screen-size, SNAPED to the given grid-size */
|
||||
Rect getMapVisible(const int screenW, const int screenH, const float mapGridSize) const {
|
||||
Rect r = getMapVisible(screenW, screenH);
|
||||
r.x0 = snapFloor(r.x0, mapGridSize);
|
||||
r.y0 = snapFloor(r.y0, mapGridSize);
|
||||
r.x1 = snapCeil(r.x1, mapGridSize);
|
||||
r.y1 = snapCeil(r.y1, mapGridSize);
|
||||
return r;
|
||||
}
|
||||
|
||||
//Point2 getOffset() const {return _offset.xy();}
|
||||
Point2 getCenter() const {return Point2(-_offset.x, _offset.y);}
|
||||
|
||||
void setScreenSize(const int w, const int h) {this->w = w; this->h = h;}
|
||||
|
||||
public:
|
||||
|
||||
static float snap(const float v, const float grid) { return std::round(v/grid)*grid; }
|
||||
static Point2 snap(const Point2 p, const float grid) { return Point2(snap(p.x, grid), snap(p.y, grid)); }
|
||||
static Point3 snap(const Point3 p, const float grid) { return Point3(snap(p.x, grid), snap(p.y, grid), snap(p.z, grid)); }
|
||||
|
||||
static float snapCeil(const float v, const float grid) { return std::ceil(v/grid) * grid; }
|
||||
static float snapFloor(const float v, const float grid) { return std::floor(v/grid) * grid; }
|
||||
|
||||
//float snap(const float v) const { return v; }
|
||||
|
||||
};
|
||||
|
||||
#endif // SCALER_H
|
||||
|
||||
|
||||
74
mapview/elements/MV2DElement.h
Normal file
74
mapview/elements/MV2DElement.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#ifndef MV2DELEMENT_H
|
||||
#define MV2DELEMENT_H
|
||||
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "../MapView2D.h"
|
||||
#include "../Painter.h"
|
||||
|
||||
#include <Indoor/geo/BBox2.h>
|
||||
#include <Indoor/geo/Line2.h>
|
||||
|
||||
/**
|
||||
* represents one drawable, selectable, editable, ...
|
||||
* element shown within the MapView2D
|
||||
*/
|
||||
class MV2DElement {
|
||||
|
||||
private:
|
||||
|
||||
bool _focused = false;
|
||||
|
||||
public:
|
||||
|
||||
/** dtor */
|
||||
virtual ~MV2DElement() {;}
|
||||
|
||||
|
||||
/** get the element's 2D bounding box */
|
||||
virtual BBox2 getBoundingBox() const = 0;
|
||||
|
||||
/** get the element's minimal distance (nearest whatsoever) to the given point */
|
||||
virtual float getMinDistanceXY(const Point2 p) const = 0;
|
||||
|
||||
/** repaint me */
|
||||
virtual void paint(Painter& p) = 0;
|
||||
|
||||
|
||||
|
||||
/** got focus */
|
||||
void focus() {
|
||||
_focused = true;
|
||||
onFocus();
|
||||
}
|
||||
|
||||
/** lost focus */
|
||||
void unfocus() {
|
||||
_focused = false;
|
||||
onUnfocus();
|
||||
}
|
||||
|
||||
bool hasFocus() {return _focused;}
|
||||
|
||||
|
||||
/** mouse pressed at the given point */
|
||||
virtual void mousePressed(MapView2D* v, const Point2 p) = 0;
|
||||
|
||||
/** mouse moved to the given point */
|
||||
virtual void mouseMove(MapView2D* v, const Point2 p) = 0;
|
||||
|
||||
/** mouse released */
|
||||
virtual void mouseReleased(MapView2D* v, const Point2 p) = 0;
|
||||
|
||||
/** key pressed. return true when consumed. */
|
||||
virtual bool keyPressEvent(MapView2D* v, QKeyEvent* e) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void onFocus() = 0;
|
||||
|
||||
virtual void onUnfocus() = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif // MV2DELEMENT_H
|
||||
97
mapview/elements/MV2DElementAccessPoint.h
Normal file
97
mapview/elements/MV2DElementAccessPoint.h
Normal file
@@ -0,0 +1,97 @@
|
||||
#ifndef MV2DELEMENTACCESSPOINT_H
|
||||
#define MV2DELEMENTACCESSPOINT_H
|
||||
|
||||
#include "MV2DElement.h"
|
||||
#include "MapViewElementHelper.h"
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
class MV2DElementAccessPoint : public MV2DElement {
|
||||
|
||||
private:
|
||||
|
||||
bool sel = false;
|
||||
Floorplan::AccessPoint* ap;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor with the AP to render/edit */
|
||||
MV2DElementAccessPoint(Floorplan::AccessPoint* ap) : ap(ap) {;}
|
||||
|
||||
|
||||
/** get the element's 3D bounding box */
|
||||
BBox2 getBoundingBox() const override {
|
||||
BBox2 bbox;
|
||||
bbox.add(Point2(ap->pos.x, ap->pos.y));
|
||||
bbox.grow(Point2(0.1, 0.1));
|
||||
return bbox;
|
||||
}
|
||||
|
||||
/** get the element's minimal distance (nearest whatsoever) to the given point */
|
||||
float getMinDistanceXY(const Point2 p) const override {
|
||||
return p.getDistance(ap->pos.xy());
|
||||
}
|
||||
|
||||
/** repaint me */
|
||||
void paint(Painter& p) override {
|
||||
|
||||
if (sel) {
|
||||
p.setPenBrush(Qt::black, CFG::SEL_COLOR);
|
||||
p.drawCircle(ap->pos.xy());
|
||||
} else if (hasFocus()) {
|
||||
p.setPenBrush(Qt::black, Qt::NoBrush);
|
||||
p.drawCircle(ap->pos.xy());
|
||||
} else {
|
||||
p.setPenBrush(Qt::gray, Qt::NoBrush);
|
||||
p.drawCircle(ap->pos.xy());
|
||||
}
|
||||
|
||||
// label
|
||||
if (p.getScaler().getScale() >= 25) {
|
||||
p.p->drawText(p.getScaler().xms(ap->pos.x) + 10, p.getScaler().yms(ap->pos.y) + 5, ap->mac.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** mouse pressed at the given point */
|
||||
virtual void mousePressed(MapView2D* v, const Point2 p) override {
|
||||
(void) v;
|
||||
(void) p;
|
||||
|
||||
}
|
||||
|
||||
/** mouse moved to the given point */
|
||||
virtual void mouseMove(MapView2D* v, const Point2 _p) override {
|
||||
(void) v;
|
||||
if (sel) {
|
||||
const Point2 p = Scaler::snap(_p, CFG::MOVE_SNAP_SIZE_M);
|
||||
ap->pos.x = p.x;
|
||||
ap->pos.y = p.y;
|
||||
}
|
||||
}
|
||||
|
||||
/** mouse released */
|
||||
virtual void mouseReleased(MapView2D* v, const Point2 _p) override {
|
||||
(void) v;
|
||||
(void) _p;
|
||||
sel = true;
|
||||
}
|
||||
|
||||
virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override {
|
||||
(void) v;
|
||||
(void) e;
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void onFocus() override {
|
||||
|
||||
}
|
||||
|
||||
virtual void onUnfocus() override {
|
||||
sel = false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // MV2DELEMENTACCESSPOINT_H
|
||||
94
mapview/elements/MV2DElementBeacon.h
Normal file
94
mapview/elements/MV2DElementBeacon.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#ifndef MV2DELEMENTBEACON_H
|
||||
#define MV2DELEMENTBEACON_H
|
||||
|
||||
#include "MV2DElement.h"
|
||||
#include "MapViewElementHelper.h"
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
class MV2DElementBeacon : public MV2DElement {
|
||||
|
||||
private:
|
||||
|
||||
bool sel = false;
|
||||
Floorplan::Beacon* b;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor with the Beacon to render/edit */
|
||||
MV2DElementBeacon(Floorplan::Beacon* b) : b(b) {;}
|
||||
|
||||
/** get the element's 3D bounding box */
|
||||
BBox2 getBoundingBox() const override {
|
||||
BBox2 bbox;
|
||||
bbox.add(Point2(b->pos.x, b->pos.y));
|
||||
bbox.grow(Point2(0.1, 0.1));
|
||||
return bbox;
|
||||
}
|
||||
|
||||
/** get the element's minimal distance (nearest whatsoever) to the given point */
|
||||
float getMinDistanceXY(const Point2 p) const override {
|
||||
return p.getDistance(b->pos.xy());
|
||||
}
|
||||
|
||||
/** repaint me */
|
||||
void paint(Painter& p) override {
|
||||
|
||||
if (sel) {
|
||||
p.setPenBrush(Qt::black, CFG::SEL_COLOR);
|
||||
p.drawCircle(b->pos.xy());
|
||||
} else if (hasFocus()) {
|
||||
p.setPenBrush(Qt::black, Qt::NoBrush);
|
||||
p.drawCircle(b->pos.xy());
|
||||
} else {
|
||||
p.setPenBrush(Qt::gray, Qt::NoBrush);
|
||||
p.drawCircle(b->pos.xy());
|
||||
}
|
||||
|
||||
// label
|
||||
if (p.getScaler().getScale() >= 25) {
|
||||
p.p->drawText(p.getScaler().xms(b->pos.x) + 10, p.getScaler().yms(b->pos.y) + 5, b->mac.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void onFocus() override {
|
||||
;
|
||||
}
|
||||
|
||||
virtual void onUnfocus() override {
|
||||
sel = false;
|
||||
}
|
||||
|
||||
/** mouse pressed at the given point */
|
||||
virtual void mousePressed(MapView2D* v, const Point2 p) override {
|
||||
(void) v;
|
||||
(void) p;
|
||||
}
|
||||
|
||||
/** mouse moved to the given point */
|
||||
virtual void mouseMove(MapView2D* v, const Point2 _p) override {
|
||||
(void) v;
|
||||
if (sel) {
|
||||
const Point2 p = Scaler::snap(_p, CFG::MOVE_SNAP_SIZE_M);
|
||||
b->pos.x = p.x;
|
||||
b->pos.y = p.y;
|
||||
}
|
||||
}
|
||||
|
||||
/** mouse released */
|
||||
virtual void mouseReleased(MapView2D* v, const Point2 p) override {
|
||||
(void) v;
|
||||
(void) p;
|
||||
sel = true;
|
||||
}
|
||||
|
||||
virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override {
|
||||
(void) v;
|
||||
(void) e;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // MV2DELEMENTBEACON_H
|
||||
108
mapview/elements/MV2DElementFloorObstacleCircle.h
Normal file
108
mapview/elements/MV2DElementFloorObstacleCircle.h
Normal file
@@ -0,0 +1,108 @@
|
||||
#ifndef MV2DELEMENTFLOOROBSTACLECIRCLE_H
|
||||
#define MV2DELEMENTFLOOROBSTACLECIRCLE_H
|
||||
|
||||
|
||||
#include "MV2DElement.h"
|
||||
#include "MapViewElementHelper.h"
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
class MV2DElementFloorObstacleCircle : public MV2DElement {
|
||||
|
||||
private:
|
||||
|
||||
int selPoint = -1;
|
||||
Floorplan::FloorObstacleCircle* c;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
MV2DElementFloorObstacleCircle(Floorplan::FloorObstacleCircle* c) : c(c) {;}
|
||||
|
||||
/** get the element's 3D bounding box */
|
||||
BBox2 getBoundingBox() const override {
|
||||
BBox2 bbox;
|
||||
bbox.add(c->center);
|
||||
bbox.grow(Point2(c->radius, c->radius));
|
||||
return bbox;
|
||||
}
|
||||
|
||||
/** get the element's minimal distance (nearest whatsoever) to the given point */
|
||||
float getMinDistanceXY(const Point2 p) const override {
|
||||
return std::min(p.getDistance(getSelPoints()[0]), p.getDistance(getSelPoints()[1]));
|
||||
}
|
||||
|
||||
|
||||
/** repaint me */
|
||||
void paint(Painter& p) override {
|
||||
|
||||
QPen pen = MapElementHelper::getPen(c->material, c->type, hasFocus());
|
||||
|
||||
p.setPenBrush(pen, Qt::NoBrush);
|
||||
p.drawCircle(c->center, c->radius);
|
||||
|
||||
//QBrush brush = MapElementHelper::getBru(c->material, c->type, _focused);
|
||||
|
||||
// selected endpoints?
|
||||
if (hasFocus()) {
|
||||
p.setPenBrush(Qt::NoPen, CFG::SEL_COLOR);
|
||||
if (selPoint == 0) {p.drawCircle(getSelPoints()[0]);}
|
||||
if (selPoint == 1) {p.drawCircle(getSelPoints()[1]);}
|
||||
}
|
||||
|
||||
// available endpoints
|
||||
if (hasFocus()) {
|
||||
p.setPenBrush(Qt::black, Qt::NoBrush);
|
||||
p.drawCircle(getSelPoints()[0]);
|
||||
p.drawCircle(getSelPoints()[1]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::vector<Point2> getSelPoints() const {
|
||||
return {c->center, (c->center + Point2(c->radius,0))};
|
||||
}
|
||||
|
||||
virtual void onFocus() override {
|
||||
;
|
||||
}
|
||||
|
||||
virtual void onUnfocus() override {
|
||||
selPoint = -1;
|
||||
}
|
||||
|
||||
/** mouse pressed at the given point */
|
||||
virtual void mousePressed(MapView2D* v, const Point2 p) override {
|
||||
(void) v;
|
||||
(void) p;
|
||||
|
||||
}
|
||||
|
||||
/** mouse moved to the given point */
|
||||
virtual void mouseMove(MapView2D* v, const Point2 _p) override {
|
||||
(void) v;
|
||||
if (selPoint == -1) {return;}
|
||||
const Point2 p = Scaler::snap(_p, CFG::MOVE_SNAP_SIZE_M);
|
||||
if (selPoint == 0) {c->center = p;}
|
||||
if (selPoint == 1) {c->radius = p.getDistance(c->center);}
|
||||
}
|
||||
|
||||
/** mouse released */
|
||||
virtual void mouseReleased(MapView2D* v, const Point2 _p) override {
|
||||
const float t = v->getScaler().sm(CFG::SEL_THRESHOLD_SIZE_PX);
|
||||
const float l1 = _p.getDistance(getSelPoints()[0]);
|
||||
const float l2 = _p.getDistance(getSelPoints()[1]);
|
||||
if (l1 < l2 && l1 <= t) {selPoint = 0;}
|
||||
else if (l2 < l1 && l2 <= t) {selPoint = 1;}
|
||||
else {selPoint = -1;}
|
||||
}
|
||||
|
||||
virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override {
|
||||
(void) v;
|
||||
(void) e;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // MV2DELEMENTFLOOROBSTACLECIRCLE_H
|
||||
108
mapview/elements/MV2DElementFloorObstacleLine.h
Normal file
108
mapview/elements/MV2DElementFloorObstacleLine.h
Normal file
@@ -0,0 +1,108 @@
|
||||
#ifndef MV2DELEMENTFLOOROBSTACLELINE_H
|
||||
#define MV2DELEMENTFLOOROBSTACLELINE_H
|
||||
|
||||
#include "MV2DElement.h"
|
||||
#include "MapViewElementHelper.h"
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
class MV2DElementFloorObstacleLine : public MV2DElement {
|
||||
|
||||
private:
|
||||
|
||||
int selPoint = -1;
|
||||
Floorplan::FloorObstacleLine* fo;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
MV2DElementFloorObstacleLine(Floorplan::FloorObstacleLine* fo) : fo(fo) {;}
|
||||
|
||||
/** get the element's 3D bounding box */
|
||||
BBox2 getBoundingBox() const override {
|
||||
BBox2 bbox;
|
||||
bbox.add(fo->from);
|
||||
bbox.add(fo->to);
|
||||
return bbox;
|
||||
}
|
||||
|
||||
/** get the element's minimal distance (nearest whatsoever) to the given point */
|
||||
float getMinDistanceXY(const Point2 p) const override {
|
||||
return MapElementHelper::getLineDistanceXY(fo->from, fo->to, p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** repaint me */
|
||||
void paint(Painter& p) override {
|
||||
|
||||
// selected endpoints?
|
||||
if (hasFocus()) {
|
||||
p.setPenBrush(Qt::NoPen, CFG::SEL_COLOR);
|
||||
if (selPoint == 0) {p.drawCircle(fo->from);}
|
||||
if (selPoint == 1) {p.drawCircle(fo->to);}
|
||||
}
|
||||
|
||||
// line
|
||||
p.setPenBrush(MapElementHelper::getPen(fo->material, fo->type, hasFocus()), Qt::NoBrush);
|
||||
p.drawLine(fo->from, fo->to);
|
||||
|
||||
// available endpoints
|
||||
if (hasFocus()) {
|
||||
p.setPenBrush(Qt::black, Qt::NoBrush);
|
||||
p.drawCircle(fo->from);
|
||||
p.drawCircle(fo->to);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void onFocus() override {
|
||||
;
|
||||
}
|
||||
|
||||
virtual void onUnfocus() override {
|
||||
selPoint = -1; // clear selection
|
||||
}
|
||||
|
||||
/** mouse pressed at the given point */
|
||||
virtual void mousePressed(MapView2D* v, const Point2 p) override {
|
||||
(void) v;
|
||||
(void) p;
|
||||
|
||||
}
|
||||
|
||||
/** mouse moved to the given point */
|
||||
virtual void mouseMove(MapView2D* v, const Point2 _p) override {
|
||||
(void) v;
|
||||
if (selPoint == -1) {return;}
|
||||
const Point2 p = Scaler::snap(_p, CFG::MOVE_SNAP_SIZE_M);
|
||||
if (selPoint == 0) {fo->from.x = p.x; fo->from.y = p.y;}
|
||||
if (selPoint == 1) {fo->to.x = p.x; fo->to.y = p.y;}
|
||||
}
|
||||
|
||||
/** mouse released */
|
||||
virtual void mouseReleased(MapView2D* v, const Point2 _p) override {
|
||||
// (void) v;
|
||||
// if (selPoint == -1) {return;}
|
||||
// const Point3 p = Scaler::snap(_p, CFG::MOVE_SNAP_SIZE_M);
|
||||
// if (selPoint == 0) {fo.from.x = p.x; fo.from.y = p.y;}
|
||||
// if (selPoint == 1) {fo.to.x = p.x; fo.to.y = p.y;}
|
||||
|
||||
// select a new point on mouse-release (more robust than on mouse-press)
|
||||
const float t = v->getScaler().sm(CFG::SEL_THRESHOLD_SIZE_PX);
|
||||
const float l1 = _p.getDistance(fo->from);
|
||||
const float l2 = _p.getDistance(fo->to);
|
||||
if (l1 < l2 && l1 <= t) {selPoint = 0;}
|
||||
else if (l2 < l1 && l2 <= t) {selPoint = 1;}
|
||||
else {selPoint = -1;}
|
||||
|
||||
}
|
||||
|
||||
virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override {
|
||||
(void) v;
|
||||
(void) e;
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // MV2DELEMENTFLOOROBSTACLELINE_H
|
||||
152
mapview/elements/MV2DElementFloorOutlinePolygon.h
Normal file
152
mapview/elements/MV2DElementFloorOutlinePolygon.h
Normal file
@@ -0,0 +1,152 @@
|
||||
#ifndef MV2DELEMENTFLOOROUTLINEPOLYGON_H
|
||||
#define MV2DELEMENTFLOOROUTLINEPOLYGON_H
|
||||
|
||||
#include "MV2DElement.h"
|
||||
#include "MapViewElementHelper.h"
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
class MV2DElementFloorOutlinePolygon : public MV2DElement {
|
||||
|
||||
private:
|
||||
|
||||
int selPoint = -1;
|
||||
Floorplan::FloorOutlinePolygon& fo;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
MV2DElementFloorOutlinePolygon(Floorplan::FloorOutlinePolygon& fo) : fo(fo) {;}
|
||||
|
||||
/** get the element's 3D bounding box */
|
||||
BBox2 getBoundingBox() const override {
|
||||
BBox2 bbox;
|
||||
for (const Point2 p : fo.poly.points) { bbox.add(p); }
|
||||
return bbox;
|
||||
}
|
||||
|
||||
/** get the element's minimal distance (nearest whatsoever) to the given point */
|
||||
float getMinDistanceXY(const Point2 p) const override {
|
||||
float min = 999999;
|
||||
for (int i = 0; i < (int)fo.poly.points.size()-1; ++i) {
|
||||
const Point2 p1 = fo.poly.points[i];
|
||||
const Point2 p2 = fo.poly.points[i+1];
|
||||
const float dst = MapElementHelper::getLineDistanceXY(p1, p2, p);
|
||||
if (dst < min) {min = dst;}
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
virtual void onFocus() override {
|
||||
|
||||
}
|
||||
|
||||
virtual void onUnfocus() override {
|
||||
selPoint = -1; // clear selection
|
||||
}
|
||||
|
||||
void paint(Painter& p) override {
|
||||
|
||||
QBrush brush;
|
||||
|
||||
// fill-style (depends on the mode)
|
||||
switch (fo.method) {
|
||||
case Floorplan::OutlineMethod::ADD:
|
||||
brush.setStyle(Qt::BrushStyle::SolidPattern);
|
||||
brush.setColor(QColor(0,0,0,24));
|
||||
break;
|
||||
case Floorplan::OutlineMethod::REMOVE:
|
||||
brush.setStyle(Qt::BrushStyle::DiagCrossPattern);
|
||||
brush.setColor(QColor(0,0,0));
|
||||
break;
|
||||
default:
|
||||
brush.setStyle(Qt::BrushStyle::SolidPattern);
|
||||
brush.setColor(QColor(255,0,0));
|
||||
}
|
||||
|
||||
// outline + filled area
|
||||
p.setPenBrush(Qt::black, brush);
|
||||
p.drawPolygon(fo.poly.points);
|
||||
|
||||
// selected endpoints?
|
||||
if (hasFocus() && selPoint != -1) {
|
||||
p.setPenBrush(Qt::NoPen, CFG::SEL_COLOR);
|
||||
p.drawCircle(fo.poly.points[selPoint]);
|
||||
}
|
||||
|
||||
// available endpoints
|
||||
if (hasFocus()) {
|
||||
p.setPenBrush(Qt::black, Qt::NoBrush);
|
||||
for (const Point2 pt : fo.poly.points) {
|
||||
p.drawCircle(pt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
virtual void mousePressed(MapView2D* v, const Point2 p) override {
|
||||
(void) v;
|
||||
(void) p;
|
||||
}
|
||||
|
||||
virtual void mouseMove(MapView2D* v, const Point2 _p) override {
|
||||
(void) v;
|
||||
if (selPoint == -1) {return;}
|
||||
const Point2 p = Scaler::snap(_p, CFG::MOVE_SNAP_SIZE_M);
|
||||
fo.poly.points[selPoint].x = p.x;
|
||||
fo.poly.points[selPoint].y = p.y;
|
||||
}
|
||||
|
||||
virtual void mouseReleased(MapView2D* v, const Point2 _p) override {
|
||||
|
||||
(void) v;
|
||||
|
||||
// if (selPoint != -1) {
|
||||
// const Point3 p = Scaler::snap(_p, CFG::MOVE_SNAP_SIZE_M);
|
||||
// fo.poly.points[selPoint].x = p.x;
|
||||
// fo.poly.points[selPoint].y = p.y;
|
||||
// }
|
||||
|
||||
// select a new point on mouse-release (more robust than on mouse-press)
|
||||
const float t = v->getScaler().sm(CFG::SEL_THRESHOLD_SIZE_PX);
|
||||
auto comp = [&] (const Point2 a, const Point2 b) {return a.getDistance(_p) < b.getDistance(_p);};
|
||||
auto it = std::min_element(fo.poly.points.begin(), fo.poly.points.end(), comp);
|
||||
if (it == fo.poly.points.end()) {selPoint = -1;} // none found -> skip
|
||||
else if ((*it).getDistance(_p) > t) {selPoint = -1;} // nearest distance is above threshold -> skip
|
||||
else {selPoint = it - fo.poly.points.begin();}
|
||||
|
||||
}
|
||||
|
||||
virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override {
|
||||
(void) v;
|
||||
|
||||
|
||||
if (e->key() == Qt::Key_Delete) {
|
||||
|
||||
// delete the currently selected vertex?
|
||||
if (selPoint != -1) {
|
||||
fo.poly.points.erase(fo.poly.points.begin() + selPoint);
|
||||
selPoint = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
} else if (e->key() == Qt::Key_Plus && selPoint != -1) {
|
||||
int idx1 = selPoint;
|
||||
int idx2 = (selPoint + 1) % fo.poly.points.size();
|
||||
int idxNew = idx2;
|
||||
Point2 pNew = (fo.poly.points[idx1] + fo.poly.points[idx2]) / 2.0f;
|
||||
fo.poly.points.insert(fo.poly.points.begin() + idxNew, pNew);
|
||||
selPoint = idxNew;
|
||||
return true;
|
||||
}
|
||||
|
||||
// not consumed
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // MV2DELEMENTFLOOROUTLINEPOLYGON_H
|
||||
136
mapview/elements/MV2DElementFloorUnderlay.h
Normal file
136
mapview/elements/MV2DElementFloorUnderlay.h
Normal file
@@ -0,0 +1,136 @@
|
||||
#ifndef MV2DELEMENTFLOORUNDERLAY_H
|
||||
#define MV2DELEMENTFLOORUNDERLAY_H
|
||||
|
||||
|
||||
#include "MV2DElement.h"
|
||||
#include "MapViewElementHelper.h"
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
/**
|
||||
* display e.g. a PNG-file below the map [as reference]
|
||||
*/
|
||||
class MV2DElementFloorUnderlay : public MV2DElement {
|
||||
|
||||
private:
|
||||
|
||||
QImage img;
|
||||
std::string tmpFile;
|
||||
Floorplan::UnderlayImage* underlay;
|
||||
BBox2 bbox;
|
||||
|
||||
int selPoint = -1;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
MV2DElementFloorUnderlay(Floorplan::UnderlayImage* underlay) : underlay(underlay) {
|
||||
missing();
|
||||
}
|
||||
|
||||
void missing() {
|
||||
//img = QImage(QSize(64, 64), QImage::Format_ARGB32);
|
||||
//img.fill(0xFF000000);
|
||||
img = QImage("://res/icons/cross.png");
|
||||
}
|
||||
|
||||
/** get the element's 3D bounding box */
|
||||
BBox2 getBoundingBox() const override {
|
||||
return bbox;
|
||||
}
|
||||
|
||||
/** get the element's minimal distance (nearest whatsoever) to the given point */
|
||||
float getMinDistanceXY(const Point2 p) const override {
|
||||
(void) p;
|
||||
return CFG::SEL_THRESHOLD_SIZE_PX; // we do not know the distance from the image
|
||||
}
|
||||
|
||||
virtual void onFocus() override {
|
||||
|
||||
}
|
||||
|
||||
virtual void onUnfocus() override {
|
||||
selPoint = -1; // clear selection
|
||||
}
|
||||
|
||||
void paint(Painter& p) override {
|
||||
(void) p;
|
||||
|
||||
if (tmpFile != underlay->filename) {
|
||||
img = QImage(underlay->filename.c_str());
|
||||
if (img.size().width() == 0) {
|
||||
missing();
|
||||
}
|
||||
tmpFile = underlay->filename;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// map coordinates
|
||||
float mx1 = underlay->anchor.x;
|
||||
float my1 = underlay->anchor.y;
|
||||
float mw = img.width() * underlay->scaleX;
|
||||
float mh = img.height() * underlay->scaleY;
|
||||
float mx2 = mx1+mw;
|
||||
float my2 = my1+mh;
|
||||
|
||||
// screen coordinates
|
||||
float sx1 = p.s.xms(mx1);
|
||||
float sy1 = p.s.yms(my1);
|
||||
float sx2 = p.s.xms(mx2);
|
||||
float sy2 = p.s.yms(my2);
|
||||
float sw = abs(sx1-sx2);
|
||||
float sh = abs(sy1-sy2);
|
||||
|
||||
bbox = BBox2();
|
||||
bbox.add(Point2(mx1, my1));
|
||||
bbox.add(Point2(mx2, my2));
|
||||
|
||||
|
||||
p.p->drawImage(QRectF(sx1, sy1-sh, sw, sh), img, QRectF(0,0,img.width(),img.height()));
|
||||
|
||||
// selected endpoint(s)?
|
||||
if (hasFocus()) {
|
||||
p.setPenBrush(Qt::NoPen, CFG::SEL_COLOR);
|
||||
if (selPoint == 0) {p.drawCircle(bbox.getMin());}
|
||||
}
|
||||
|
||||
// just focused?
|
||||
if (hasFocus()) {
|
||||
p.setPenBrush(Qt::black, Qt::NoBrush);
|
||||
p.drawRect(mx1,my1,mx2,my2);
|
||||
p.drawCircle(bbox.getMin());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void mousePressed(MapView2D* v, const Point2 p) override {
|
||||
(void) v;
|
||||
(void) p;
|
||||
}
|
||||
|
||||
virtual void mouseMove(MapView2D* v, const Point2 _p) override {
|
||||
(void) v;
|
||||
if (selPoint == -1) {return;}
|
||||
const Point2 p = Scaler::snap(_p, CFG::MOVE_SNAP_SIZE_M);
|
||||
if (selPoint == 0) {underlay->anchor = p;}
|
||||
}
|
||||
|
||||
virtual void mouseReleased(MapView2D* v, const Point2 _p) override {
|
||||
// select a new point on mouse-release (more robust than on mouse-press)
|
||||
const float t = v->getScaler().sm(CFG::SEL_THRESHOLD_SIZE_PX);
|
||||
const float l1 = _p.getDistance(bbox.getMin());
|
||||
if (l1 <= t) {selPoint = 0;}
|
||||
else {selPoint = -1;}
|
||||
}
|
||||
|
||||
virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override {
|
||||
(void) v;
|
||||
(void) e;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // MV2DELEMENTFLOORUNDERLAY_H
|
||||
74
mapview/elements/MapViewElementHelper.h
Normal file
74
mapview/elements/MapViewElementHelper.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#ifndef MAPELEMENTHELPER_H
|
||||
#define MAPELEMENTHELPER_H
|
||||
|
||||
#include <Indoor/geo/Point2.h>
|
||||
#include <Indoor/geo/Point3.h>
|
||||
#include <Indoor/geo/Line2.h>
|
||||
|
||||
#include <QColor>
|
||||
#include <QPen>
|
||||
#include <QBrush>
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
/** configuration */
|
||||
namespace CFG {
|
||||
const float MOVE_SNAP_SIZE_M = 0.1f; // in meter (= map-space)
|
||||
const int SEL_THRESHOLD_SIZE_PX = 15; // in screen-pixels (-> should depend on the current zoom)
|
||||
const QColor SEL_COLOR = Qt::blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* contains some common helper-methods
|
||||
*/
|
||||
class MapElementHelper {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* get the minimal distance of dst to the line denoted by (p1, p2).
|
||||
* this will generate line l perpendicular to (p1, p2)
|
||||
* move l into dst
|
||||
* and calculate the cut-point between l and (p1, p2)
|
||||
*/
|
||||
static float getLineDistanceXY(Point2 p1, Point2 p2, Point2 dst) {
|
||||
|
||||
// the line (p1, p2)
|
||||
const Line2 line(p1, p2);
|
||||
|
||||
// 90 degree rotation L of the line (p1, p2)
|
||||
const Point2 vec = (p1 - p2).perpendicular();
|
||||
|
||||
// the line L
|
||||
const Line2 perb(dst-vec*100, dst+vec*100);
|
||||
|
||||
// calculate the cut betwen L and (p1,p2) (if any)
|
||||
Point2 cut(0,0);
|
||||
if (line.getSegmentIntersection(perb, cut)) {
|
||||
|
||||
// distance between cut-point and mouse
|
||||
return cut.getDistance(dst);
|
||||
|
||||
} else {
|
||||
|
||||
// no cut detected
|
||||
return 9999999;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static QPen getPen(Floorplan::Material mat, Floorplan::ObstacleType type, bool focus) {
|
||||
using namespace Floorplan;
|
||||
QPen pen; pen.setColor(Qt::darkGray);
|
||||
if (focus) {pen.setColor(Qt::black);}
|
||||
if (mat == Material::CONCRETE) {pen.setWidth(3);}
|
||||
if (mat == Material::GLASS) {pen.setStyle(Qt::PenStyle::DotLine);}
|
||||
if (type == ObstacleType::HANDRAIL) {pen.setStyle(Qt::PenStyle::DashLine);}
|
||||
return pen;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // MAPELEMENTHELPER_H
|
||||
21
mapview/model/IHasAttributes.h
Normal file
21
mapview/model/IHasAttributes.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef IHASATTRIBUTES_H
|
||||
#define IHASATTRIBUTES_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class IHasAttributes {
|
||||
|
||||
public:
|
||||
|
||||
/** set the value for the given key */
|
||||
virtual void setAttribute(const std::string& key, const std::string& val) = 0;
|
||||
|
||||
/** get the value for the given key */
|
||||
virtual const std::string& getAttribute(const std::string& key) const = 0;
|
||||
|
||||
/** get all attributes as map */
|
||||
virtual const std::unordered_map<std::string, std::string> getAttributes() const = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif // IHASATTRIBUTES_H
|
||||
17
mapview/model/IHasFile.h
Normal file
17
mapview/model/IHasFile.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef IHASFILE_H
|
||||
#define IHASFILE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class IHasFile {
|
||||
|
||||
public:
|
||||
|
||||
virtual void setFileName(const std::string& file) = 0;
|
||||
|
||||
virtual const std::string& getFileName() const = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // IHASFILE_H
|
||||
15
mapview/model/IHasMAC.h
Normal file
15
mapview/model/IHasMAC.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef IHASMAC_H
|
||||
#define IHASMAC_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class IHasMAC {
|
||||
public:
|
||||
|
||||
virtual void setMAC(const std::string& mac) = 0;
|
||||
|
||||
virtual const std::string& getMAC() const = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif // IHASMAC_H
|
||||
15
mapview/model/IHasMaterial.h
Normal file
15
mapview/model/IHasMaterial.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef IHASMATERIAL_H
|
||||
#define IHASMATERIAL_H
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
class IHasMaterial {
|
||||
public:
|
||||
|
||||
virtual void setMaterial(const Floorplan::Material m) = 0;
|
||||
|
||||
virtual Floorplan::Material getMaterial() const = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif // IHASMATERIAL_H
|
||||
15
mapview/model/IHasName.h
Normal file
15
mapview/model/IHasName.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef IHASNAME_H
|
||||
#define IHASNAME_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class IHasName {
|
||||
public:
|
||||
|
||||
virtual void setName(const std::string& name) = 0;
|
||||
|
||||
virtual const std::string& getName() const = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif // IHASNAME_H
|
||||
16
mapview/model/IHasObstacleType.h
Normal file
16
mapview/model/IHasObstacleType.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef IHASOBSTACLETYPE_H
|
||||
#define IHASOBSTACLETYPE_H
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
class IHasObstacleType {
|
||||
public:
|
||||
|
||||
virtual void setObstacleType(const Floorplan::ObstacleType t) = 0;
|
||||
|
||||
virtual Floorplan::ObstacleType getObatcleType() const = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // IHASOBSTACLETYPE_H
|
||||
84
mapview/model/IHasParams.h
Normal file
84
mapview/model/IHasParams.h
Normal file
@@ -0,0 +1,84 @@
|
||||
#ifndef IHASPARAMS_H
|
||||
#define IHASPARAMS_H
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
#include <QVariant>
|
||||
|
||||
enum class ParamType {
|
||||
INT,
|
||||
FLOAT,
|
||||
STRING,
|
||||
FILE,
|
||||
};
|
||||
|
||||
class ParamValue {
|
||||
|
||||
private:
|
||||
union {
|
||||
int _int;
|
||||
float _float;
|
||||
};
|
||||
std::string _str;
|
||||
|
||||
public:
|
||||
|
||||
template <typename T> ParamValue(const T val) {
|
||||
setValue(val);
|
||||
}
|
||||
|
||||
void setValue(const std::string& val) {_str = val;}
|
||||
void setValue(float val) {_float = val;}
|
||||
void setValue(int val) {_int = val;}
|
||||
|
||||
std::string toString() const {return _str;}
|
||||
float toFloat() const {return _float;}
|
||||
int toInt() const {return _int;}
|
||||
|
||||
};
|
||||
|
||||
|
||||
//union ParamValue {
|
||||
|
||||
// int _int;
|
||||
// float _float;
|
||||
// std::string _string;
|
||||
|
||||
// template <typename T> ParamValue(const T val) {
|
||||
// setValue(val);
|
||||
// }
|
||||
|
||||
// int toInt() const {return _int;}
|
||||
// float toFloat() const {return _float;}
|
||||
// const std::string& toString() const {return _string;}
|
||||
|
||||
// void setValue(const float val) {_float = val;}
|
||||
// void setValue(const int val) {_int = val;}
|
||||
// void setValue(const std::string& val) {_string = val;}
|
||||
|
||||
//};
|
||||
|
||||
struct Param {
|
||||
std::string name;
|
||||
ParamType type;
|
||||
Param(const std::string& name, const ParamType type) : name(name), type(type) {;}
|
||||
};
|
||||
|
||||
/** free parameters */
|
||||
class IHasParams {
|
||||
public:
|
||||
|
||||
/** get the number of parameters */
|
||||
virtual int getNumParams() const = 0;
|
||||
|
||||
/** get the description of the idx-th parameter */
|
||||
virtual Param getParamDesc(const int idx) const = 0;
|
||||
|
||||
/** get the idx-th param's value */
|
||||
virtual ParamValue getParamValue(const int idx) const = 0;
|
||||
|
||||
/** set the idx-th param's value */
|
||||
virtual void setParamValue(const int idx, const ParamValue& val) const = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif // IHASPARAMS_H
|
||||
19
mapview/model/IHasPosition3D.h
Normal file
19
mapview/model/IHasPosition3D.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef IHASPOSITION3D_H
|
||||
#define IHASPOSITION3D_H
|
||||
|
||||
|
||||
#include <Indoor/geo/Point3.h>
|
||||
|
||||
class IHasPosition3D {
|
||||
|
||||
public:
|
||||
|
||||
/** set the element's 3D position */
|
||||
virtual void setPosition3D(const Point3& p) = 0;
|
||||
|
||||
/** get the element's 3D position */
|
||||
virtual Point3 getPosition3D() const = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif // IHASPOSITION3D_H
|
||||
56
mapview/model/MMFloor.h
Normal file
56
mapview/model/MMFloor.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef MMFLOOR_H
|
||||
#define MMFLOOR_H
|
||||
|
||||
#include "MapLayer.h"
|
||||
#include "MMFloorOutline.h"
|
||||
#include "MMFloorObstacles.h"
|
||||
#include "MMFloorAccessPoints.h"
|
||||
#include "MMFloorBeacons.h"
|
||||
#include "MMFloorUnderlay.h"
|
||||
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
|
||||
/**
|
||||
* floor-layer containing one floor
|
||||
* and its outline, obstacles, access-points, ...
|
||||
*/
|
||||
class MMFloor : public MapLayer, public IHasName {
|
||||
|
||||
private:
|
||||
|
||||
/** the underlying data-structure */
|
||||
Floorplan::Floor* floor;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor. existing floor */
|
||||
MMFloor(MapLayer* parent, Floorplan::Floor* floor) : MapLayer(parent, MapLayerType::FLOOR), floor(floor) {
|
||||
|
||||
new MMFloorOutline(this, floor);
|
||||
new MMFloorObstacles(this, floor);
|
||||
new MMFloorAccessPoints(this, floor);
|
||||
new MMFloorBeacons(this, floor);
|
||||
new MMFloorUnderlay(this, floor);
|
||||
|
||||
}
|
||||
|
||||
/** ctor. new floor. */
|
||||
MMFloor(MapLayer* parent) : MapLayer(parent), floor(nullptr) {
|
||||
throw "not yet implemented";
|
||||
}
|
||||
|
||||
/** get the underlying model */
|
||||
Floorplan::Floor& getFloor() {return *floor;}
|
||||
|
||||
|
||||
std::string getLayerName() const override {return floor->name;}
|
||||
|
||||
|
||||
virtual void setName(const std::string& name) {this->floor->name = name;}
|
||||
virtual const std::string& getName() const {return this->floor->name;}
|
||||
|
||||
};
|
||||
|
||||
#endif // MMFLOOR_H
|
||||
42
mapview/model/MMFloorAccessPoint.h
Normal file
42
mapview/model/MMFloorAccessPoint.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef MAPVIEWELEMENTACCESSPOINT_H
|
||||
#define MAPVIEWELEMENTACCESSPOINT_H
|
||||
|
||||
#include "MapModelElement.h"
|
||||
#include "IHasMAC.h"
|
||||
#include "IHasName.h"
|
||||
|
||||
#include "../elements/MV2DElementAccessPoint.h"
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
class MMFloorAccessPoint : public MapModelElement, public IHasMAC, public IHasName {
|
||||
|
||||
private:
|
||||
|
||||
Floorplan::Floor* floor;
|
||||
Floorplan::AccessPoint* ap;
|
||||
MV2DElementAccessPoint mv2d;
|
||||
|
||||
public:
|
||||
|
||||
MMFloorAccessPoint(MapLayer* parent, Floorplan::Floor* floor, Floorplan::AccessPoint* ap) :
|
||||
MapModelElement(parent), floor(floor), ap(ap), mv2d(ap) {
|
||||
|
||||
}
|
||||
|
||||
virtual void setMAC(const std::string& mac) override {ap->mac = mac;}
|
||||
virtual const std::string& getMAC() const override {return ap->mac;}
|
||||
|
||||
virtual void setName(const std::string& name) override {ap->name = name;}
|
||||
virtual const std::string& getName() const override {return ap->name;}
|
||||
|
||||
MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;}
|
||||
|
||||
void deleteMe() const override {
|
||||
parent->removeElement(this);
|
||||
floor->accesspoints.erase(std::remove(floor->accesspoints.begin(), floor->accesspoints.end(), ap), floor->accesspoints.end());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // MAPVIEWELEMENTACCESSPOINT_H
|
||||
45
mapview/model/MMFloorAccessPoints.h
Normal file
45
mapview/model/MMFloorAccessPoints.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef MMFLOORACCESSPOINTS_H
|
||||
#define MMFLOORACCESSPOINTS_H
|
||||
|
||||
#include "MapLayer.h"
|
||||
#include "MMFloorAccessPoint.h"
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
/**
|
||||
* layer containing all of the map's floors
|
||||
*/
|
||||
class MMFloorAccessPoints : public MapLayer {
|
||||
|
||||
private:
|
||||
|
||||
Floorplan::Floor* floor;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor with the underlying model */
|
||||
MMFloorAccessPoints(MapLayer* parent, Floorplan::Floor* floor) : MapLayer(parent, MapLayerType::FLOOR_ACCESS_POINTS), floor(floor) {
|
||||
|
||||
// add all APs
|
||||
for (Floorplan::AccessPoint* ap : floor->accesspoints) {
|
||||
new MMFloorAccessPoint(this, floor, ap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string getLayerName() const override {return "APs";}
|
||||
|
||||
//TODO: check
|
||||
void createAP(Floorplan::AccessPoint* ap) {
|
||||
|
||||
// add to underlying model
|
||||
floor->accesspoints.push_back(ap);
|
||||
|
||||
// add to myself as element
|
||||
elements.push_back(new MMFloorAccessPoint(this, floor, ap));
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // MMFLOORACCESSPOINTS_H
|
||||
41
mapview/model/MMFloorBeacon.h
Normal file
41
mapview/model/MMFloorBeacon.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef MAPVIEWELEMENTIBEACON_H
|
||||
#define MAPVIEWELEMENTIBEACON_H
|
||||
|
||||
#include "MapModelElement.h"
|
||||
#include "IHasMAC.h"
|
||||
#include "IHasName.h"
|
||||
|
||||
#include "../elements/MV2DElementBeacon.h"
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
class MMFloorBeacon : public MapModelElement, public IHasMAC, public IHasName {
|
||||
|
||||
private:
|
||||
|
||||
Floorplan::Floor* floor;
|
||||
Floorplan::Beacon* b;
|
||||
MV2DElementBeacon mv2d;
|
||||
|
||||
public:
|
||||
|
||||
MMFloorBeacon(MapLayer* parent, Floorplan::Floor* floor, Floorplan::Beacon* b) : MapModelElement(parent), floor(floor), b(b), mv2d(b) {
|
||||
|
||||
}
|
||||
|
||||
virtual void setMAC(const std::string& mac) override {b->mac = mac;}
|
||||
virtual const std::string& getMAC() const override {return b->mac;}
|
||||
|
||||
virtual void setName(const std::string& name) override {b->name = name;}
|
||||
virtual const std::string& getName() const override {return b->name;}
|
||||
|
||||
MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;}
|
||||
|
||||
void deleteMe() const override {
|
||||
parent->removeElement(this);
|
||||
floor->beacons.erase(std::remove(floor->beacons.begin(), floor->beacons.end(), b), floor->beacons.end());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // MAPVIEWELEMENTIBEACON_H
|
||||
44
mapview/model/MMFloorBeacons.h
Normal file
44
mapview/model/MMFloorBeacons.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef MMFLOORBEACONS_H
|
||||
#define MMFLOORBEACONS_H
|
||||
|
||||
#include "MapLayer.h"
|
||||
#include "MMFloorBeacon.h"
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
/**
|
||||
* layer containing all of the floor's beaconss
|
||||
*/
|
||||
class MMFloorBeacons : public MapLayer {
|
||||
|
||||
private:
|
||||
|
||||
Floorplan::Floor* floor;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor with the underlying model */
|
||||
MMFloorBeacons(MapLayer* parent, Floorplan::Floor* floor) : MapLayer(parent, MapLayerType::FLOOR_BEACONS), floor(floor) {
|
||||
|
||||
// add all Beacons
|
||||
for (Floorplan::Beacon* b : floor->beacons) {
|
||||
new MMFloorBeacon(this, floor, b);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string getLayerName() const override {return "Beacons";}
|
||||
|
||||
//TODO: check
|
||||
void createBeacon(Floorplan::Beacon* b) {
|
||||
|
||||
// add to underlying model
|
||||
floor->beacons.push_back(b);
|
||||
|
||||
// add to myself as element
|
||||
elements.push_back(new MMFloorBeacon(this, floor, b));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // MMFLOORBEACONS_H
|
||||
46
mapview/model/MMFloorObstacleCircle.h
Normal file
46
mapview/model/MMFloorObstacleCircle.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef MAPMODELELEMENTFLOOROBSTACLECIRCLE_H
|
||||
#define MAPMODELELEMENTFLOOROBSTACLECIRCLE_H
|
||||
|
||||
|
||||
#include "MapModelElement.h"
|
||||
#include "../elements/MapViewElementHelper.h"
|
||||
|
||||
#include "IHasMaterial.h"
|
||||
#include "IHasObstacleType.h"
|
||||
|
||||
#include "../elements/MV2DElementFloorObstacleCircle.h"
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
|
||||
class MMFloorObstacleCircle : public MapModelElement, public IHasMaterial, public IHasObstacleType {
|
||||
|
||||
private:
|
||||
|
||||
Floorplan::Floor* mf;
|
||||
Floorplan::FloorObstacleCircle* c;
|
||||
MV2DElementFloorObstacleCircle mv2d;
|
||||
|
||||
public:
|
||||
|
||||
MMFloorObstacleCircle(MapLayer* parent, Floorplan::Floor* mf, Floorplan::FloorObstacleCircle* c) :
|
||||
MapModelElement(parent), mf(mf), c(c), mv2d(c) {
|
||||
|
||||
}
|
||||
|
||||
void setMaterial(const Floorplan::Material m) override {c->material = m;}
|
||||
Floorplan::Material getMaterial() const override {return c->material;}
|
||||
|
||||
void setObstacleType(const Floorplan::ObstacleType t) override {c->type = t;}
|
||||
Floorplan::ObstacleType getObatcleType() const override {return c->type;}
|
||||
|
||||
MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;}
|
||||
|
||||
void deleteMe() const override {
|
||||
parent->removeElement(this);
|
||||
mf->obstacles.erase(std::remove(mf->obstacles.begin(), mf->obstacles.end(), c), mf->obstacles.end());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // MAPMODELELEMENTFLOOROBSTACLECIRCLE_H
|
||||
45
mapview/model/MMFloorObstacleLine.h
Normal file
45
mapview/model/MMFloorObstacleLine.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef MAPELEMENTOBSTACLE_H
|
||||
#define MAPELEMENTOBSTACLE_H
|
||||
|
||||
#include "MapModelElement.h"
|
||||
#include "../elements/MapViewElementHelper.h"
|
||||
|
||||
#include "IHasMaterial.h"
|
||||
#include "IHasObstacleType.h"
|
||||
|
||||
#include "../elements/MV2DElementFloorObstacleLine.h"
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
|
||||
class MMFloorObstacleLine : public MapModelElement, public IHasMaterial, public IHasObstacleType {
|
||||
|
||||
public:
|
||||
|
||||
Floorplan::Floor* mf;
|
||||
Floorplan::FloorObstacleLine* fo;
|
||||
MV2DElementFloorObstacleLine mv2d;
|
||||
|
||||
public:
|
||||
|
||||
MMFloorObstacleLine(MapLayer* parent, Floorplan::Floor* mf, Floorplan::FloorObstacleLine* fo) :
|
||||
MapModelElement(parent), mf(mf), fo(fo), mv2d(fo) {
|
||||
|
||||
}
|
||||
|
||||
void setMaterial(const Floorplan::Material m) override {fo->material = m;}
|
||||
Floorplan::Material getMaterial() const override {return fo->material;}
|
||||
|
||||
void setObstacleType(const Floorplan::ObstacleType t) override {fo->type = t;}
|
||||
Floorplan::ObstacleType getObatcleType() const override {return fo->type;}
|
||||
|
||||
MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;}
|
||||
|
||||
void deleteMe() const override {
|
||||
parent->removeElement(this);
|
||||
mf->obstacles.erase(std::remove(mf->obstacles.begin(), mf->obstacles.end(), fo), mf->obstacles.end());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // MAPELEMENTOBSTACLE_H
|
||||
63
mapview/model/MMFloorObstacles.h
Normal file
63
mapview/model/MMFloorObstacles.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef MMFLOOROBSTACLES_H
|
||||
#define MMFLOOROBSTACLES_H
|
||||
|
||||
#include "MapLayer.h"
|
||||
#include "MMFloorObstacleCircle.h"
|
||||
#include "MMFloorObstacleLine.h"
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
/**
|
||||
* layer that contains all of one floor's obstacles
|
||||
*/
|
||||
class MMFloorObstacles : public MapLayer {
|
||||
|
||||
Floorplan::Floor* floor;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor with the floor */
|
||||
MMFloorObstacles(MapLayer* parent, Floorplan::Floor* floor) : MapLayer(parent, MapLayerType::FLOOR_OBSTACLES), floor(floor) {
|
||||
|
||||
// the obstacles
|
||||
for (Floorplan::FloorObstacle* o : floor->obstacles) {
|
||||
if (dynamic_cast<Floorplan::FloorObstacleLine*>(o)) {
|
||||
elements.push_back(new MMFloorObstacleLine(this, floor, (Floorplan::FloorObstacleLine*)o));
|
||||
} else if (dynamic_cast<Floorplan::FloorObstacleCircle*>(o)) {
|
||||
elements.push_back(new MMFloorObstacleCircle(this, floor, (Floorplan::FloorObstacleCircle*)o));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** get the corresponding floor from the underlying model */
|
||||
Floorplan::Floor* getFloor() {return floor;}
|
||||
|
||||
//TODO: check
|
||||
void createLine(Floorplan::FloorObstacleLine* obs) {
|
||||
|
||||
// add to underlying model
|
||||
floor->obstacles.push_back(obs);
|
||||
|
||||
// add to myself as element
|
||||
elements.push_back(new MMFloorObstacleLine(this, floor, obs));
|
||||
|
||||
}
|
||||
|
||||
//TODO: check
|
||||
void createCircle(Floorplan::FloorObstacleCircle* obs) {
|
||||
|
||||
// add to underlying model
|
||||
floor->obstacles.push_back(obs);
|
||||
|
||||
// add to myself as element
|
||||
elements.push_back(new MMFloorObstacleCircle(this, floor, obs));
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::string getLayerName() const override {return "obstacles";}
|
||||
|
||||
};
|
||||
|
||||
#endif // MMFLOOROBSTACLES_H
|
||||
52
mapview/model/MMFloorOutline.h
Normal file
52
mapview/model/MMFloorOutline.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef MMFLOOROUTLINE_H
|
||||
#define MMFLOOROUTLINE_H
|
||||
|
||||
#include "MapLayer.h"
|
||||
#include "MMFloorOutlinePolygon.h"
|
||||
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
/**
|
||||
* layer containing all elements describing a floor's outline
|
||||
*/
|
||||
class MMFloorOutline : public MapLayer {
|
||||
|
||||
private:
|
||||
|
||||
/** the underlying model */
|
||||
Floorplan::Floor* floor;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor with the underlying model */
|
||||
MMFloorOutline(MapLayer* parent, Floorplan::Floor* floor) : MapLayer(parent, MapLayerType::FLOOR_GROUND), floor(floor) {
|
||||
|
||||
// the outline
|
||||
for (Floorplan::FloorOutlinePolygon* poly : floor->outline) {
|
||||
elements.push_back(new MMFloorOutlinePolygon(this, floor, poly));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** get the corresponding floor from the underlying model */
|
||||
Floorplan::Floor* getFloor() {return floor;}
|
||||
|
||||
//TODO: check
|
||||
void create(Floorplan::FloorOutlinePolygon* poly) {
|
||||
|
||||
// add to underlying model
|
||||
floor->outline.push_back(poly);
|
||||
|
||||
// add to myself as element
|
||||
elements.push_back(new MMFloorOutlinePolygon(this, floor, poly));
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::string getLayerName() const override {return "outline";}
|
||||
|
||||
};
|
||||
|
||||
#endif // MMFLOOROUTLINE_H
|
||||
53
mapview/model/MMFloorOutlinePolygon.h
Normal file
53
mapview/model/MMFloorOutlinePolygon.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef MAPELEMENTFLOORGROUND_H
|
||||
#define MAPELEMENTFLOORGROUND_H
|
||||
|
||||
#include "IHasName.h"
|
||||
#include "MapModelElement.h"
|
||||
|
||||
#include "../elements/MV2DElementFloorOutlinePolygon.h"
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
|
||||
/**
|
||||
* describes one polygon within a floor's outline
|
||||
*/
|
||||
class MMFloorOutlinePolygon : public MapModelElement, public IHasName {
|
||||
|
||||
private:
|
||||
|
||||
Floorplan::Floor* mf;
|
||||
Floorplan::FloorOutlinePolygon* fo;
|
||||
MV2DElementFloorOutlinePolygon mv2d;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
MMFloorOutlinePolygon(MapLayer* parent, Floorplan::Floor* mf, Floorplan::FloorOutlinePolygon* fo) : MapModelElement(parent), mf(mf), fo(fo), mv2d(*fo) {
|
||||
;
|
||||
}
|
||||
|
||||
Floorplan::FloorOutlinePolygon* getPolygon() {return fo;}
|
||||
|
||||
Floorplan::OutlineMethod getMethod() const {return fo->method;}
|
||||
void setMethod(const Floorplan::OutlineMethod m) {this->fo->method = m;}
|
||||
|
||||
void setName(const std::string& name) override {fo->name = name;}
|
||||
const std::string& getName() const override {return fo->name;}
|
||||
|
||||
MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;}
|
||||
|
||||
void deleteMe() const override {
|
||||
|
||||
// delete from the parent
|
||||
parent->removeElement(this);
|
||||
|
||||
// delete from the underlying model
|
||||
mf->outline.erase(std::remove(mf->outline.begin(), mf->outline.end(), fo), mf->outline.end());
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // MAPELEMENTFLOORGROUND_H
|
||||
52
mapview/model/MMFloorUnderlay.h
Normal file
52
mapview/model/MMFloorUnderlay.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef MMFLOORUNDERLAY_H
|
||||
#define MMFLOORUNDERLAY_H
|
||||
|
||||
#include "MMFloorUnderlayImage.h"
|
||||
|
||||
#include "../elements/MV2DElementFloorUnderlay.h"
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
/**
|
||||
* add an external file as underlay (to copy it onto the map)
|
||||
*/
|
||||
class MMFloorUnderlay : public MapLayer {
|
||||
|
||||
private:
|
||||
|
||||
Floorplan::Floor* floor;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
MMFloorUnderlay(MapLayer* parent, Floorplan::Floor* floor) : MapLayer(parent, MapLayerType::FLOOR_UNDERLAY), floor(floor) {
|
||||
|
||||
// the underlays
|
||||
for (Floorplan::UnderlayImage* img : floor->underlays) {
|
||||
elements.push_back(new MMFloorUnderlayImage(this, floor, img));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//TODO: check
|
||||
void createImage(const Point2 center) {
|
||||
|
||||
Floorplan::UnderlayImage* elem = new Floorplan::UnderlayImage();
|
||||
|
||||
// add to underlying model
|
||||
floor->underlays.push_back(elem);
|
||||
|
||||
// add to myself as element
|
||||
MMFloorUnderlayImage* img = new MMFloorUnderlayImage(this, floor, elem);
|
||||
elements.push_back(img);
|
||||
img->setAnchor(center);
|
||||
img->setScale(0.1, 0.1);
|
||||
|
||||
}
|
||||
|
||||
virtual std::string getLayerName() const override {return "underlay";}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // MMFLOORUNDERLAY_H
|
||||
78
mapview/model/MMFloorUnderlayImage.h
Normal file
78
mapview/model/MMFloorUnderlayImage.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#ifndef MMFLOORUNDERLAYIMAGE_H
|
||||
#define MMFLOORUNDERLAYIMAGE_H
|
||||
|
||||
|
||||
#include "IHasFile.h"
|
||||
#include "IHasParams.h"
|
||||
#include "MapModelElement.h"
|
||||
|
||||
#include "../elements/MV2DElementFloorUnderlay.h"
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
/**
|
||||
* add an external image file as underlay (to copy it onto the map)
|
||||
*/
|
||||
class MMFloorUnderlayImage : public MapModelElement, public MapLayer, public IHasFile, public IHasParams {
|
||||
|
||||
private:
|
||||
|
||||
Floorplan::Floor* floor;
|
||||
Floorplan::UnderlayImage* img;
|
||||
MV2DElementFloorUnderlay mv2d;
|
||||
std::string fileName;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
MMFloorUnderlayImage(MapLayer* parent, Floorplan::Floor* floor, Floorplan::UnderlayImage* img) : MapModelElement(parent), MapLayer(parent, MapLayerType::FLOOR_UNDERLAY), floor(floor), img(img), mv2d(img) {
|
||||
setFileName(img->filename);
|
||||
}
|
||||
|
||||
virtual void setFileName(const std::string& file) {img->filename = file;}
|
||||
virtual const std::string& getFileName() const {return img->filename;}
|
||||
|
||||
void setAnchor(const Point2 anchor) {img->anchor = anchor;}
|
||||
Point2 getAnchor() const {return img->anchor;}
|
||||
|
||||
void setScale(const float x, const float y) {img->scaleX = x; img->scaleY = y;}
|
||||
|
||||
virtual std::string getLayerName() const override {return "underlay";}
|
||||
|
||||
MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;}
|
||||
|
||||
void deleteMe() const override {
|
||||
;
|
||||
}
|
||||
|
||||
int getNumParams() const override {return 3;}
|
||||
|
||||
virtual Param getParamDesc(const int idx) const override {
|
||||
switch (idx) {
|
||||
case 0: return Param("file", ParamType::FILE);
|
||||
case 1: return Param("scale X", ParamType::FLOAT);
|
||||
case 2: return Param("scale Y", ParamType::FLOAT);
|
||||
default: throw 1;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ParamValue getParamValue(const int idx) const override {
|
||||
switch(idx) {
|
||||
case 0: return ParamValue(img->filename);
|
||||
case 1: return ParamValue(img->scaleX);
|
||||
case 2: return ParamValue(img->scaleY);
|
||||
default: throw 1;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void setParamValue(const int idx, const ParamValue& val) const override {
|
||||
switch (idx) {
|
||||
case 0: img->filename = val.toString();
|
||||
case 1: img->scaleX = val.toFloat();
|
||||
case 2: img->scaleY = val.toFloat();
|
||||
default: throw 1;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // MMFLOORUNDERLAYIMAGE_H
|
||||
37
mapview/model/MMFloors.h
Normal file
37
mapview/model/MMFloors.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef MMFLOORS_H
|
||||
#define MMFLOORS_H
|
||||
|
||||
#include "MapLayer.h"
|
||||
#include "MMFloor.h"
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
/**
|
||||
* layer containing all of the map's floors
|
||||
*/
|
||||
class MMFloors : public MapLayer {
|
||||
|
||||
private:
|
||||
|
||||
Floorplan::IndoorMap* map;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor with the underlying model */
|
||||
MMFloors(MapLayer* parent, Floorplan::IndoorMap* map) : MapLayer(parent, MapLayerType::FLOORS), map(map) {
|
||||
|
||||
// add all floors
|
||||
for (Floorplan::Floor* floor : map->floors) {
|
||||
new MMFloor(this, floor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string getLayerName() const override {return "floors";}
|
||||
|
||||
/** get the underlying model */
|
||||
Floorplan::IndoorMap* getMap() {return map;}
|
||||
|
||||
};
|
||||
|
||||
#endif // MMFLOORS_H
|
||||
38
mapview/model/MMRoot.h
Normal file
38
mapview/model/MMRoot.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef MMROOT_H
|
||||
#define MMROOT_H
|
||||
|
||||
#include "MapLayer.h"
|
||||
#include "MMFloors.h"
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
/**
|
||||
* floor-layer containing one floor
|
||||
* and its outline, obstacles, access-points, ...
|
||||
*/
|
||||
class MMRoot : public MapLayer {
|
||||
|
||||
private:
|
||||
|
||||
/** the underlying data-structure */
|
||||
Floorplan::IndoorMap* map;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor. existing floor */
|
||||
MMRoot(MapLayer* parent, Floorplan::IndoorMap* map) : MapLayer(parent), map(map) {
|
||||
|
||||
// all floors
|
||||
new MMFloors(this, map);
|
||||
|
||||
}
|
||||
|
||||
/** get the underlying model */
|
||||
Floorplan::IndoorMap* getMap() {return map;}
|
||||
|
||||
|
||||
std::string getLayerName() const override {return "root";}
|
||||
|
||||
};
|
||||
|
||||
#endif // MMROOT_H
|
||||
127
mapview/model/MapLayer.h
Normal file
127
mapview/model/MapLayer.h
Normal file
@@ -0,0 +1,127 @@
|
||||
#ifndef MAPLAYER_H
|
||||
#define MAPLAYER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
class MapModelElement;
|
||||
|
||||
|
||||
enum class MapLayerType {
|
||||
UNKNOWN,
|
||||
ROOT,
|
||||
FLOORS,
|
||||
FLOOR,
|
||||
FLOOR_GROUND,
|
||||
FLOOR_OBSTACLES,
|
||||
FLOOR_BEACONS,
|
||||
FLOOR_ACCESS_POINTS,
|
||||
FLOOR_UNDERLAY,
|
||||
};
|
||||
|
||||
|
||||
|
||||
class MapLayer {
|
||||
|
||||
protected:
|
||||
|
||||
/** this layer's parent */
|
||||
MapLayer* parent;
|
||||
|
||||
/** this layer's elements */
|
||||
std::vector<MapModelElement*> elements;
|
||||
|
||||
/** this layer's sublayers */
|
||||
std::vector<MapLayer*> sublayers;
|
||||
|
||||
/** this layer's type */
|
||||
MapLayerType type;
|
||||
|
||||
/** whether this layer is visible */
|
||||
bool visible;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
MapLayer(MapLayer* parent) : parent(parent), type(MapLayerType::UNKNOWN), visible(true) {
|
||||
if (parent) {parent->addSublayer(this);} // attach myself as child of my parent
|
||||
}
|
||||
|
||||
/** ctor */
|
||||
MapLayer(MapLayer* parent, MapLayerType type) : parent(parent), type(type), visible(true) {
|
||||
if (parent) {parent->addSublayer(this);} // attach myself as child of my parent
|
||||
}
|
||||
|
||||
/** dtor */
|
||||
virtual ~MapLayer() {;}
|
||||
|
||||
/** get the layer's parent */
|
||||
MapLayer* getParent() const {return parent;}
|
||||
|
||||
/** get the layer's name */
|
||||
virtual std::string getLayerName() const = 0;
|
||||
|
||||
/** get the layer's type */
|
||||
MapLayerType getLayerType() const {return type;}
|
||||
|
||||
|
||||
/** get all elements within this layer */
|
||||
const std::vector<MapModelElement*>& getElements() const {return elements;}
|
||||
|
||||
/** get all elements within this layer */
|
||||
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()); }
|
||||
|
||||
|
||||
/** is this layer currently visible? */
|
||||
bool isVisible() const {return visible;}
|
||||
|
||||
/** make this layer visible */
|
||||
void setVisible(const bool visible) {this->visible = visible;}
|
||||
|
||||
|
||||
/** get all sub-layers within this layer */
|
||||
const std::vector<MapLayer*>& getSubLayers() const {return sublayers;}
|
||||
|
||||
|
||||
/** 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();
|
||||
el.insert(el.end(), local.begin(), local.end());
|
||||
for (MapLayer* sub : getSubLayers()) {
|
||||
sub->getVisibleElementsRecursive(el);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
/** add a new sublayer to this layer */
|
||||
void addSublayer(MapLayer* ml) {
|
||||
|
||||
// sanity check before adding
|
||||
if (std::find(sublayers.begin(), sublayers.end(), ml) != sublayers.end()) {throw "layer already present!";}
|
||||
sublayers.push_back(ml);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class MapLayerRoot : public MapLayer {
|
||||
|
||||
public:
|
||||
|
||||
MapLayerRoot(MapLayer* parent) : MapLayer(parent, MapLayerType::ROOT) {;}
|
||||
|
||||
std::string getLayerName() const override {return "root";}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // MAPLAYER_H
|
||||
72
mapview/model/MapLayers.h
Normal file
72
mapview/model/MapLayers.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#ifndef MAPLAYERFLOOR_H
|
||||
#define MAPLAYERFLOOR_H
|
||||
|
||||
#include "MapLayer.h"
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
#include "../model/MMFloorObstacleLine.h"
|
||||
#include "../model/MMFloorObstacleCircle.h"
|
||||
#include "../model/MMFloorOutlinePolygon.h"
|
||||
#include "../model/MMFloorBeacon.h"
|
||||
|
||||
|
||||
/*
|
||||
class MapLayerFloorOutlineAdd : public TypedMapLayer {
|
||||
private:
|
||||
Floorplan::Floor& floor;
|
||||
public:
|
||||
MapLayerFloorOutlineAdd(MapLayer* parent, Floorplan::Floor& floor) : TypedMapLayer(parent, MapLayerType::FLOOR_GROUND_ADD), floor(floor) {;}
|
||||
std::string getLayerName() const override {return "add";}
|
||||
Floorplan::Floor& getFloor() {return floor;}
|
||||
std::vector<MapModelElement*> getElements() const override {
|
||||
std::vector<MapModelElement*> vec;
|
||||
for (Floorplan::FloorOutlinePolygon& p : floor.outline.add) {vec.push_back(new MapViewElementFloorOutlinePolygon(floor, p, MapViewElementFloorOutlinePolygon::Type::ADD));}
|
||||
return vec;
|
||||
}
|
||||
void create(const Floorplan::FloorOutlinePolygon& poly) {
|
||||
floor.outline.add.push_back(poly);
|
||||
}
|
||||
virtual size_t getNumElements() const override {return floor.outline.add.size();}
|
||||
};
|
||||
|
||||
class MapLayerFloorOutlineRemove : public TypedMapLayer {
|
||||
private:
|
||||
Floorplan::Floor& floor;
|
||||
public:
|
||||
MapLayerFloorOutlineRemove(MapLayer* parent, Floorplan::Floor& floor) : TypedMapLayer(parent, MapLayerType::FLOOR_GROUND_REMOVE), floor(floor) {;}
|
||||
std::string getLayerName() const override {return "remove";}
|
||||
Floorplan::Floor& getFloor() {return floor;}
|
||||
std::vector<MapModelElement*> getElements() const override {
|
||||
std::vector<MapModelElement*> vec;
|
||||
for (Floorplan::FloorOutlinePolygon& p : floor.outline.remove) {vec.push_back(new MapViewElementFloorOutlinePolygon(floor, p, MapViewElementFloorOutlinePolygon::Type::REMOVE));}
|
||||
return vec;
|
||||
}
|
||||
void create(const Floorplan::FloorOutlinePolygon& poly) {
|
||||
floor.outline.remove.push_back(poly);
|
||||
}
|
||||
virtual size_t getNumElements() const override {return floor.outline.remove.size();}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class MapLayerFloorOutlinePolygon : public TypedMapLayer {
|
||||
private:
|
||||
Floorplan::Floor& floor;
|
||||
public:
|
||||
MapLayerFloorOutlinePolygon(MapLayer* parent, Floorplan::Floor& floor) : TypedMapLayer(parent, MapLayerType::FLOOR_GROUND), floor(floor) {
|
||||
new MapLayerFloorOutlineAdd(this, floor);
|
||||
new MapLayerFloorOutlineRemove(this, floor);
|
||||
}
|
||||
std::string getLayerName() const override {return "ground";}
|
||||
Floorplan::Floor& getFloor() {return floor;}
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // MAPLAYERFLOOR_H
|
||||
0
mapview/model/MapModel.cpp
Normal file
0
mapview/model/MapModel.cpp
Normal file
112
mapview/model/MapModel.h
Normal file
112
mapview/model/MapModel.h
Normal file
@@ -0,0 +1,112 @@
|
||||
#ifndef MAPMODEL_H
|
||||
#define MAPMODEL_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "MapLayer.h"
|
||||
#include "MapModelElement.h"
|
||||
|
||||
#include "MMRoot.h"
|
||||
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
#include <Indoor/floorplan/v2/FloorplanReader.h>
|
||||
#include <Indoor/floorplan/v2/FloorplanWriter.h>
|
||||
|
||||
class MapModel : public QObject {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
///** wrapper-classes for all elements */
|
||||
//std::vector<MapModelElement*> selElements;
|
||||
|
||||
/** 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;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
MapModel() {
|
||||
root = new MapLayerRoot(nullptr);
|
||||
}
|
||||
|
||||
virtual ~MapModel() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
selLayer = nullptr;
|
||||
//selElements.clear();
|
||||
if (root) {delete root; root = nullptr;}
|
||||
}
|
||||
|
||||
void load(const std::string& file) {
|
||||
|
||||
emit aboutToReset();
|
||||
|
||||
cleanup();
|
||||
|
||||
// load the indoor-map using the given XML-file
|
||||
im = Floorplan::Reader::readFromFile(file);
|
||||
root = new MMRoot(nullptr, im);
|
||||
|
||||
emit reset();
|
||||
|
||||
}
|
||||
|
||||
void save(const std::string& file) {
|
||||
|
||||
Floorplan::Writer::writeToFile(im, file);
|
||||
|
||||
}
|
||||
|
||||
/** 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 currently visible elements */
|
||||
std::vector<MapModelElement*> getVisibleElements() {
|
||||
return getSelectedLayerElements();
|
||||
}
|
||||
|
||||
/** 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
|
||||
34
mapview/model/MapModelElement.h
Normal file
34
mapview/model/MapModelElement.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef MAPMODELELEMENT_H
|
||||
#define MAPMODELELEMENT_H
|
||||
|
||||
|
||||
#include "MapLayer.h"
|
||||
|
||||
class MV2DElement;
|
||||
|
||||
class MapModelElement {
|
||||
|
||||
protected:
|
||||
|
||||
MapLayer* parent;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
MapModelElement(MapLayer* parent) : parent(parent) {;}
|
||||
|
||||
/** dtor */
|
||||
virtual ~MapModelElement() {;}
|
||||
|
||||
/** get the 2D interaction class for this element */
|
||||
virtual MV2DElement* getMV2D() const = 0;
|
||||
|
||||
/** delete this element from the model */
|
||||
virtual void deleteMe() const = 0;
|
||||
|
||||
/** get the parent element */
|
||||
MapLayer* getParent() const {return parent;}
|
||||
|
||||
};
|
||||
|
||||
#endif // MAPMODELELEMENT_H
|
||||
0
mapview/tools/Tool.cpp
Normal file
0
mapview/tools/Tool.cpp
Normal file
35
mapview/tools/Tool.h
Normal file
35
mapview/tools/Tool.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef TOOL_H
|
||||
#define TOOL_H
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QObject>
|
||||
|
||||
#include "../Painter.h"
|
||||
|
||||
class MapView2D;
|
||||
|
||||
class Tool : public QObject {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
virtual ~Tool() {;}
|
||||
|
||||
virtual void mousePressEvent(MapView2D* m, QMouseEvent* e) { (void) m; (void) e; }
|
||||
virtual void mouseMoveEvent(MapView2D* m, QMouseEvent* e) { (void) m; (void) e; }
|
||||
virtual void mouseReleaseEvent(MapView2D* m, QMouseEvent* e) { (void) m; (void) e; }
|
||||
|
||||
virtual void wheelEvent(MapView2D* m, QWheelEvent* e) { (void) m; (void) e; }
|
||||
|
||||
virtual void keyPressEvent(MapView2D* m, QKeyEvent* e) { (void) m; (void) e; }
|
||||
|
||||
virtual void paintBefore(MapView2D* m, Painter& p) { (void) m; (void) p; }
|
||||
virtual void paintAfter(MapView2D* m, Painter& p) { (void) m; (void) p; }
|
||||
|
||||
virtual void layerChange(MapView2D* m) { (void) m; }
|
||||
|
||||
};
|
||||
|
||||
#endif // TOOL_H
|
||||
71
mapview/tools/ToolMapGrid.h
Normal file
71
mapview/tools/ToolMapGrid.h
Normal file
@@ -0,0 +1,71 @@
|
||||
#ifndef TOOLMAPGRID_H
|
||||
#define TOOLMAPGRID_H
|
||||
|
||||
#include "Tool.h"
|
||||
|
||||
class ToolMapGrid : public Tool {
|
||||
|
||||
public:
|
||||
|
||||
void paintBefore(MapView2D* m, Painter& p) override {
|
||||
|
||||
(void) m;
|
||||
|
||||
static const QColor cB(250,250,250);
|
||||
static const QColor cN(235,235,235);
|
||||
static const QColor c0(128,128,128);
|
||||
|
||||
int w = p.width();
|
||||
int h = p.height();
|
||||
|
||||
// grid-size
|
||||
const float step = p.getScaler().getLODstep();
|
||||
const float sStep = step/5;
|
||||
|
||||
// map-region visible on the screen
|
||||
const Rect r = p.getScaler().getMapVisible(w, h, step);
|
||||
|
||||
// x-lines
|
||||
for (float x = r.x0; x < r.x1; x += step) {
|
||||
|
||||
// major-lines (without center)
|
||||
if (std::abs(x) > 0.001) {
|
||||
p.setPenBrush(cN, Qt::NoBrush);
|
||||
p.drawLine(x, r.y0, x, r.y1);
|
||||
}
|
||||
|
||||
// minor-lines
|
||||
p.setPenBrush(cB, Qt::NoBrush);
|
||||
for (float x1 = x+sStep; x1 < x+step; x1 += sStep) {
|
||||
p.drawLine(x1, r.y0, x1, r.y1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// y-lines
|
||||
for (float y = r.y0; y < r.y1; y += step) {
|
||||
|
||||
// major-lines (without center)
|
||||
if (std::abs(y) > 0.001) {
|
||||
p.setPenBrush(cN, Qt::NoBrush);
|
||||
p.drawLine(r.x0, y, r.x1, y);
|
||||
}
|
||||
|
||||
// minor-lines
|
||||
p.setPenBrush(cB, Qt::NoBrush);
|
||||
for (float y1 = y+sStep; y1 < y+step; y1 += sStep) {
|
||||
p.drawLine(r.x0, y1, r.x1, y1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// thick center lines
|
||||
p.setPenBrush(c0, Qt::NoBrush);
|
||||
p.drawLine(0, r.y0, 0, r.y1);
|
||||
p.drawLine(r.x0, 0, r.x1, 0);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // TOOLMAPGRID_H
|
||||
28
mapview/tools/ToolMapZoom.h
Normal file
28
mapview/tools/ToolMapZoom.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef TOOLMAPZOOM_H
|
||||
#define TOOLMAPZOOM_H
|
||||
|
||||
#include "Tool.h"
|
||||
#include "../MapView2D.h"
|
||||
|
||||
class ToolMapZoom : public Tool {
|
||||
|
||||
public:
|
||||
|
||||
virtual void wheelEvent(MapView2D* m, QWheelEvent* e) override {
|
||||
|
||||
Scaler& s = m->getScaler();
|
||||
|
||||
if (e->delta() < 0) {
|
||||
s.setScale(s.getScale() * 0.5);
|
||||
} else {
|
||||
s.setScale(s.getScale() / 0.5);
|
||||
}
|
||||
|
||||
if (s.getScale() > 1000) {s.setScale(1000);}
|
||||
if (s.getScale() < 5) {s.setScale(5);}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // TOOLMAPZOOM_H
|
||||
49
mapview/tools/ToolMoveMap.h
Normal file
49
mapview/tools/ToolMoveMap.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef TOOLMOVEMAP_H
|
||||
#define TOOLMOVEMAP_H
|
||||
|
||||
#include "Tool.h"
|
||||
#include "../MapView2D.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class ToolMoveMap : public Tool {
|
||||
|
||||
private:
|
||||
|
||||
bool mouseIsDown = false;
|
||||
Point3 startOffset;
|
||||
int sx;
|
||||
int sy;
|
||||
|
||||
virtual void mousePressEvent(MapView2D* m, QMouseEvent* e) override {
|
||||
if (e->button() == Qt::MouseButton::MidButton) {
|
||||
mouseIsDown = true;
|
||||
this->sx = e->x();
|
||||
this->sy = e->y();
|
||||
this->startOffset = m->getScaler().getOffset();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void mouseMoveEvent(MapView2D* m, QMouseEvent* e) override {
|
||||
if (!mouseIsDown) {return;}
|
||||
m->getScaler().setOffset(startOffset);
|
||||
m->getScaler().addOffset(e->x()-sx, e->y()-sy);
|
||||
}
|
||||
|
||||
virtual void mouseReleaseEvent(MapView2D* m, QMouseEvent* e) override {
|
||||
(void) m;
|
||||
(void) e;
|
||||
mouseIsDown = false;
|
||||
}
|
||||
|
||||
virtual void keyPressEvent(MapView2D* m, QKeyEvent* e) override {
|
||||
(void) m;
|
||||
(void) e;
|
||||
// TODO: move on arrow keys?
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // TOOLMOVEMAP_H
|
||||
140
mapview/tools/ToolRuler.h
Normal file
140
mapview/tools/ToolRuler.h
Normal file
@@ -0,0 +1,140 @@
|
||||
#ifndef TOOLRULER_H
|
||||
#define TOOLRULER_H
|
||||
|
||||
#include "Tool.h"
|
||||
|
||||
class ToolRuler : public Tool {
|
||||
|
||||
private:
|
||||
|
||||
int mouseX;
|
||||
int mouseY;
|
||||
|
||||
const bool fullSize = true;
|
||||
const int rs = 40; // ruler size
|
||||
const int tsMajor = 20; // major-tick size
|
||||
const int tsMinor = 5; // minor-tick size
|
||||
|
||||
public:
|
||||
|
||||
virtual void mouseMoveEvent(MapView2D* m, QMouseEvent* e) override {
|
||||
|
||||
(void) m;
|
||||
|
||||
this->mouseX = e->x();
|
||||
this->mouseY = e->y();
|
||||
}
|
||||
|
||||
virtual void paintBefore(MapView2D* m, Painter& p) override {
|
||||
|
||||
(void) m;
|
||||
|
||||
// mouse-indicator within the image?
|
||||
if (fullSize) {
|
||||
const int w = p.width();
|
||||
const int h = p.height();
|
||||
p.setPenBrush(Qt::lightGray, Qt::NoBrush);
|
||||
p.p->drawLine(rs, mouseY, w, mouseY);
|
||||
p.p->drawLine(mouseX, rs, mouseX, h);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void paintAfter(MapView2D* m, Painter& p) override {
|
||||
|
||||
(void) m;
|
||||
|
||||
static const QColor c1(240,240,240);
|
||||
static const QColor c2(200,200,200);
|
||||
|
||||
const int w = p.width();
|
||||
const int h = p.height();
|
||||
|
||||
// ruler step-size depending on the current zoom level
|
||||
const float step = p.getScaler().getLODstep();
|
||||
const float sStep = step / 10.0f;
|
||||
|
||||
// the visible map-rect
|
||||
const Rect r = p.getScaler().getMapVisible(w, h, step);
|
||||
|
||||
QRect rx(rs,0,w-1-rs,rs);
|
||||
QRect ry(0,rs,rs,h-1-rs);
|
||||
|
||||
// background
|
||||
{
|
||||
|
||||
// samller font
|
||||
QFont f = p.p->font(); f.setPointSize(8);
|
||||
p.p->setFont(f);
|
||||
|
||||
// outline
|
||||
p.setPen(Qt::darkGray);
|
||||
|
||||
// x-axis
|
||||
QLinearGradient gx(0,0,0,rs); gx.setColorAt(0, c1); gx.setColorAt(1, c2); p.setBrush(gx);
|
||||
p.p->drawRect(rx);
|
||||
|
||||
// y-axis
|
||||
QLinearGradient gy(0,0,rs,0); gy.setColorAt(0, c2); gy.setColorAt(1, c1); p.setBrush(gy);
|
||||
p.p->drawRect(ry);
|
||||
|
||||
}
|
||||
|
||||
// mouse-indicator
|
||||
p.setPenBrush(Qt::darkGray, Qt::NoBrush);
|
||||
p.p->drawLine(0, mouseY, rs, mouseY);
|
||||
p.p->drawLine(mouseX, 0, mouseX, rs);
|
||||
|
||||
|
||||
|
||||
p.setPenBrush(Qt::black, Qt::NoBrush);
|
||||
char buf[128];
|
||||
|
||||
|
||||
// y-axis
|
||||
p.p->setClipRect(ry);
|
||||
for (float y = r.y0; y <= r.y1; y += step) {
|
||||
|
||||
// major-lines
|
||||
const float yMajor = p.s.yms(y);
|
||||
//if (yMajor < 0 || yMajor > h) {continue;} // stop at the end
|
||||
p.p->drawLine(0,yMajor, tsMajor,yMajor);
|
||||
|
||||
// minor-lines
|
||||
for (float y1 = y+sStep; y1 < y+step; y1 += sStep) {
|
||||
const float yMinor = p.s.yms(y1);
|
||||
p.p->drawLine(0,yMinor, tsMinor,yMinor);
|
||||
}
|
||||
|
||||
// text-label
|
||||
std::sprintf(buf, "%.1f", y);
|
||||
p.p->drawText(6, yMajor-2, buf);
|
||||
}
|
||||
|
||||
// x-axis
|
||||
p.p->setClipRect(rx);
|
||||
for (float x = r.x0; x <= r.x1; x += step) {
|
||||
|
||||
// major-lines
|
||||
const float xMajor = p.s.xms(x);
|
||||
//if (xMajor < 0 || xMajor > w) {continue;} // stop at the end
|
||||
p.p->drawLine(xMajor,0, xMajor,tsMajor);
|
||||
|
||||
// minor-lines
|
||||
for (float x1 = x+sStep; x1 < x+step; x1 += sStep) {
|
||||
const float xMinor = p.s.xms(x1);
|
||||
p.p->drawLine(xMinor,0, xMinor,tsMinor);
|
||||
}
|
||||
|
||||
// text-label
|
||||
std::sprintf(buf, "%.1f", x);
|
||||
p.p->drawText(xMajor+2, 18, buf);
|
||||
}
|
||||
|
||||
p.p->setClipping(false);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // TOOLRULER_H
|
||||
0
mapview/tools/ToolSelector.cpp
Normal file
0
mapview/tools/ToolSelector.cpp
Normal file
163
mapview/tools/ToolSelector.h
Normal file
163
mapview/tools/ToolSelector.h
Normal file
@@ -0,0 +1,163 @@
|
||||
#ifndef TOOLSELECTOR_H
|
||||
#define TOOLSELECTOR_H
|
||||
|
||||
#include "Tool.h"
|
||||
#include "../model/MapModelElement.h"
|
||||
#include "../MapView2D.h"
|
||||
#include "../model/MapModel.h"
|
||||
|
||||
|
||||
class ToolSelector : public Tool {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
/** the currently focused MapElement (if any) */
|
||||
MapModelElement* focused = nullptr;
|
||||
|
||||
/** whether the mouse-button is currently pressed */
|
||||
bool mouseIsDown = false;
|
||||
|
||||
public:
|
||||
|
||||
virtual ~ToolSelector() {;}
|
||||
|
||||
|
||||
virtual void mousePressEvent(MapView2D* m, QMouseEvent* e) override {
|
||||
|
||||
if (e->button() != Qt::MouseButton::LeftButton) {return;}
|
||||
|
||||
mouseIsDown = true;
|
||||
|
||||
const Scaler& s = m->getScaler();
|
||||
Point2 p2(s.xsm(e->x()), s.ysm(e->y()));
|
||||
//Point3 p3(s.xsm(e->x()), s.ysm(e->y()), 0);
|
||||
|
||||
const float g = m->getScaler().sm(10); // increase each BBox by 10 px (needed mainly for hor/ver lines)
|
||||
|
||||
// get all elements with bounding-box matchings
|
||||
std::vector<MapModelElement*> possible;
|
||||
for (MapModelElement* el : m->getModel()->getSelectedLayerElements()) {
|
||||
BBox2 bbox = el->getMV2D()->getBoundingBox(); // elements 3D bbox
|
||||
bbox.grow(Point2(g, g)); // grow a little (needed for straight lines)
|
||||
if (bbox.contains(p2)) {possible.push_back(el);} // intersection?
|
||||
}
|
||||
|
||||
// among those, find the best-matching one (smallest distance to an intersection)
|
||||
auto lambda = [&] (const MapModelElement* el1, const MapModelElement* el2) {return el1->getMV2D()->getMinDistanceXY(p2) < el2->getMV2D()->getMinDistanceXY(p2);};
|
||||
auto it = std::min_element(possible.begin(), possible.end(), lambda);
|
||||
MapModelElement* el = (it == possible.end()) ? (nullptr) : (*it);
|
||||
|
||||
|
||||
|
||||
// focus changed? -> unfocus the old one (if any)
|
||||
if (setFocused(el)) {
|
||||
|
||||
;
|
||||
|
||||
} else {
|
||||
|
||||
// focus kept. provide the currently focused element with events
|
||||
if (focused) {focused->getMV2D()->mousePressed(m, p2);}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** needed eg. when the focused element gets invalid (switching visible layers) */
|
||||
void layerChange(MapView2D* m) override {
|
||||
(void) m;
|
||||
setFocused(nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief change the currently focused element. throws an event.
|
||||
* @param el the to-be-focused element or null
|
||||
* @return true if the focused element has changed. false otherwise
|
||||
*/
|
||||
bool setFocused(MapModelElement* el) {
|
||||
|
||||
// whether the focus has changed or not
|
||||
const bool focusChanged = (focused != el);
|
||||
|
||||
if (focusChanged) {
|
||||
|
||||
// unfocus the old one (if any)
|
||||
if (focused) {focused->getMV2D()->unfocus();}
|
||||
|
||||
// set the currently focused object (if any)
|
||||
focused = el;
|
||||
|
||||
// focus the new one (if any)
|
||||
if (focused) {focused->getMV2D()->focus();}
|
||||
|
||||
emit onMapElementSelected(el);
|
||||
|
||||
}
|
||||
|
||||
// done
|
||||
return focusChanged;
|
||||
|
||||
}
|
||||
|
||||
virtual void mouseMoveEvent(MapView2D* m, QMouseEvent* e) override {
|
||||
|
||||
const Scaler& s = m->getScaler();
|
||||
Point2 p2(s.xsm(e->x()), s.ysm(e->y()));
|
||||
|
||||
// mouse pressed?
|
||||
if (mouseIsDown) {
|
||||
|
||||
// provide the focused element with the mouse event?
|
||||
if (focused) {focused->getMV2D()->mouseMove(m, p2); return;}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void mouseReleaseEvent(MapView2D* m, QMouseEvent* e) override {
|
||||
|
||||
const Scaler& s = m->getScaler();
|
||||
Point2 p2(s.xsm(e->x()), s.ysm(e->y()));
|
||||
|
||||
// provide the focused element with the mouse event?
|
||||
if (focused) {focused->getMV2D()->mouseReleased(m, p2);}
|
||||
|
||||
mouseIsDown = false;
|
||||
|
||||
}
|
||||
|
||||
virtual void keyPressEvent(MapView2D* m, QKeyEvent* e) override {
|
||||
(void) m;
|
||||
|
||||
if (focused) {
|
||||
|
||||
// pass it to the element which may consume this event
|
||||
if (focused->getMV2D()->keyPressEvent(m, e)) {return;}
|
||||
|
||||
// not consumed -> additional options
|
||||
|
||||
// ESCAPE -> unfocus
|
||||
if (e->key() == Qt::Key_Escape) {setFocused(nullptr);}
|
||||
|
||||
// DELETE -> delete
|
||||
if (e->key() == Qt::Key_Delete) {
|
||||
focused->deleteMe();
|
||||
setFocused(nullptr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
signals:
|
||||
|
||||
/** map element was selected */
|
||||
void onMapElementSelected(MapModelElement* el);
|
||||
|
||||
};
|
||||
|
||||
#endif // TOOLSELECTOR_H
|
||||
59
mapview/tools/Tools.h
Normal file
59
mapview/tools/Tools.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef TOOLS_H
|
||||
#define TOOLS_H
|
||||
|
||||
#include <vector>
|
||||
#include "Tool.h"
|
||||
|
||||
/**
|
||||
* combine several tools under the interface for one tool
|
||||
*/
|
||||
class Tools : public Tool {
|
||||
|
||||
private:
|
||||
|
||||
std::vector<Tool*> tools;
|
||||
|
||||
public:
|
||||
|
||||
/** add this tool */
|
||||
void enable(Tool* t) {tools.push_back(t);}
|
||||
|
||||
/** remove this tool */
|
||||
void disable(Tool* t) {tools.erase(std::remove(tools.begin(), tools.end(), t));}
|
||||
|
||||
|
||||
virtual void mousePressEvent(MapView2D* m, QMouseEvent* e) override {
|
||||
for (Tool* t : tools) {t->mousePressEvent(m, e);}
|
||||
}
|
||||
|
||||
virtual void mouseMoveEvent(MapView2D* m, QMouseEvent* e) override {
|
||||
for (Tool* t : tools) {t->mouseMoveEvent(m, e);}
|
||||
}
|
||||
|
||||
virtual void mouseReleaseEvent(MapView2D* m, QMouseEvent* e) override {
|
||||
for (Tool* t : tools) {t->mouseReleaseEvent(m, e);}
|
||||
}
|
||||
|
||||
virtual void wheelEvent(MapView2D* m, QWheelEvent* e) override {
|
||||
for (Tool* t : tools) {t->wheelEvent(m, e);}
|
||||
}
|
||||
|
||||
virtual void keyPressEvent(MapView2D* m, QKeyEvent* e) override {
|
||||
for (Tool* t : tools) {t->keyPressEvent(m, e);}
|
||||
}
|
||||
|
||||
virtual void paintBefore(MapView2D* m, Painter& p) override {
|
||||
for (Tool* t : tools) {t->paintBefore(m, p);}
|
||||
}
|
||||
|
||||
virtual void paintAfter(MapView2D* m, Painter& p) override {
|
||||
for (Tool* t : tools) {t->paintAfter(m, p);}
|
||||
}
|
||||
|
||||
virtual void layerChange(MapView2D* m) override {
|
||||
for (Tool* t : tools) {t->layerChange(m);}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // TOOLS_H
|
||||
Reference in New Issue
Block a user