merged
This commit is contained in:
59
mapview/2D/ClickDist.h
Normal file
59
mapview/2D/ClickDist.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef CLICKDIST_H
|
||||
#define CLICKDIST_H
|
||||
|
||||
enum class ClickDistType {
|
||||
UNKNOWN,
|
||||
DIRECT, // e.g. distance between cursor and an edge-point, POI, AP, Beacon, ...
|
||||
CUT, // e.g. distance between cursor and an obstacle-line
|
||||
};
|
||||
|
||||
/** describes distances between mouse-cursor and objects within the 2D view */
|
||||
struct ClickDist {
|
||||
|
||||
/** distance in pixels */
|
||||
float dst_px;
|
||||
|
||||
/** distance type */
|
||||
ClickDistType type;
|
||||
|
||||
|
||||
/** ctor */
|
||||
ClickDist(const float dst_px, const ClickDistType type) : dst_px(dst_px), type(type) {;}
|
||||
|
||||
/** max-dummy */
|
||||
static ClickDist max() {return ClickDist(9999999, ClickDistType::UNKNOWN);}
|
||||
|
||||
|
||||
/** distance comparison */
|
||||
bool operator < (const ClickDist o) const {
|
||||
return (this->dst_px * this->mod()) < (o.dst_px * o.mod());
|
||||
}
|
||||
|
||||
/** multiply by constant */
|
||||
ClickDist operator * (const float val) const {return ClickDist(dst_px*val, type);}
|
||||
|
||||
// /** weighted distance comparison based on ClickDistType */
|
||||
// bool compare(const ClickDist o) const {
|
||||
// return ((*this)*mod()) < (o*o.mod());
|
||||
// }
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* artificially modify the distance based on the given type.
|
||||
* this enhances the selection in cases of equal distance
|
||||
* like a POI residing dirctly one a line
|
||||
*/
|
||||
float mod() const {
|
||||
switch (type) {
|
||||
case ClickDistType::UNKNOWN: return 1.1;
|
||||
case ClickDistType::CUT: return 1.0;
|
||||
case ClickDistType::DIRECT: return 0.7;
|
||||
default: throw "code error";
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // CLICKDIST_H
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <Indoor/geo/BBox2.h>
|
||||
#include <Indoor/geo/Line2.h>
|
||||
|
||||
#include "ClickDist.h"
|
||||
|
||||
/**
|
||||
* represents one drawable, selectable, editable, ...
|
||||
* element shown within the MapView2D
|
||||
@@ -29,7 +31,7 @@ public:
|
||||
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;
|
||||
virtual ClickDist getMinDistanceXY(const Point2 p) const = 0;
|
||||
|
||||
/** repaint me */
|
||||
virtual void paint(Painter& p) = 0;
|
||||
|
||||
@@ -31,8 +31,8 @@ public:
|
||||
}
|
||||
|
||||
/** 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());
|
||||
ClickDist getMinDistanceXY(const Point2 p) const override {
|
||||
return ClickDist(p.getDistance(ap->pos.xy()), ClickDistType::DIRECT);
|
||||
}
|
||||
|
||||
/** repaint me */
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
p.setPenBrush(Qt::black, Qt::NoBrush);
|
||||
p.drawDot(ap->pos.xy());
|
||||
if (p.getScaler().getScale() >= 25) {
|
||||
const std::string str = ap->name + " (" + ap->name + ")";
|
||||
const std::string str = ap->name + " (" + ap->mac + ")";
|
||||
p.p->drawText(p.getScaler().xms(ap->pos.x) + 10, p.getScaler().yms(ap->pos.y) + 5, str.c_str());
|
||||
} else if (p.getScaler().getScale() >= 10) {
|
||||
const std::string str = ap->name;
|
||||
|
||||
@@ -29,8 +29,8 @@ public:
|
||||
}
|
||||
|
||||
/** 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());
|
||||
ClickDist getMinDistanceXY(const Point2 p) const override {
|
||||
return ClickDist(p.getDistance(b->pos.xy()), ClickDistType::DIRECT);
|
||||
}
|
||||
|
||||
/** repaint me */
|
||||
|
||||
@@ -30,11 +30,11 @@ public:
|
||||
}
|
||||
|
||||
/** get the element's minimal distance (nearest whatsoever) to the given point */
|
||||
float getMinDistanceXY(const Point2 p) const override {
|
||||
ClickDist getMinDistanceXY(const Point2 p) const override {
|
||||
// std::vector<Point2> points = elevator->getPoints().points;
|
||||
// points.push_back(elevator->center);
|
||||
// auto it minEl = std::min_element(points.begin(), points.end(),
|
||||
return p.getDistance(elevator->center);
|
||||
return ClickDist(p.getDistance(elevator->center), ClickDistType::DIRECT);
|
||||
}
|
||||
|
||||
/** repaint me */
|
||||
|
||||
@@ -27,8 +27,11 @@ public:
|
||||
}
|
||||
|
||||
/** 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]));
|
||||
ClickDist getMinDistanceXY(const Point2 p) const override {
|
||||
const ClickDist d1(p.getDistance(getSelPoints()[0]), ClickDistType::DIRECT);
|
||||
const ClickDist d2(p.getDistance(getSelPoints()[1]), ClickDistType::DIRECT);
|
||||
return std::min(d1, d2);
|
||||
//return std::min(p.getDistance(getSelPoints()[0]), p.getDistance(getSelPoints()[1]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
}
|
||||
|
||||
/** get the element's minimal distance (nearest whatsoever) to the given point */
|
||||
float getMinDistanceXY(const Point2 p) const override {
|
||||
ClickDist getMinDistanceXY(const Point2 p) const override {
|
||||
return MapElementHelper::getLineDistanceXY(fo->from, fo->to, p);
|
||||
}
|
||||
|
||||
@@ -69,6 +69,12 @@ public:
|
||||
p.drawCircle(fo->to);
|
||||
}
|
||||
|
||||
// obstacle length
|
||||
if (hasFocus()) {
|
||||
p.setPenBrush(Qt::black, Qt::NoBrush);
|
||||
p.drawLength(fo->from, fo->to, fo->from.getDistance(fo->to));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "MapViewElementHelper.h"
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
#include <stdio.h>
|
||||
|
||||
class MV2DElementFloorObstacleLine : public MV2DElement, public HasMoveableNodes {
|
||||
|
||||
@@ -27,7 +28,7 @@ public:
|
||||
}
|
||||
|
||||
/** get the element's minimal distance (nearest whatsoever) to the given point */
|
||||
float getMinDistanceXY(const Point2 p) const override {
|
||||
ClickDist getMinDistanceXY(const Point2 p) const override {
|
||||
return MapElementHelper::getLineDistanceXY(fo->from, fo->to, p);
|
||||
}
|
||||
|
||||
@@ -60,33 +61,49 @@ public:
|
||||
p.setPenBrush(Qt::black, Qt::NoBrush);
|
||||
p.drawCircle(fo->from);
|
||||
p.drawCircle(fo->to);
|
||||
|
||||
// obstacle length
|
||||
p.setPenBrush(Qt::black, Qt::NoBrush);
|
||||
p.drawLength(fo->from, fo->to, fo->from.getDistance(fo->to));
|
||||
|
||||
} else {
|
||||
//p.setPenBrush(Qt::NoPen, Qt::black);
|
||||
p.drawCircle_px(fo->from, 3);
|
||||
p.drawCircle_px(fo->to, 3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void paintDoor(Painter& p) {
|
||||
|
||||
QPen pen;
|
||||
pen.setColor(QColor(0.5,0.5,0.5));
|
||||
pen.setStyle(Qt::PenStyle::DotLine);
|
||||
p.setPenBrush(pen, Qt::NoBrush);
|
||||
|
||||
|
||||
// opening indicator
|
||||
const float open = M_PI / 4;
|
||||
const float len = (fo->to - fo->from).length();
|
||||
const float angle1 = std::atan2(fo->to.y-fo->from.y, fo->to.x-fo->from.x);
|
||||
const float angle2 = angle1 + open;
|
||||
const Point2 pOpen = Point2( std::cos(angle2) * len, std::sin(angle2) * len ) + fo->from;
|
||||
|
||||
p.drawLine(fo->from, fo->to);
|
||||
p.drawLine(fo->from, pOpen);
|
||||
|
||||
p.drawArc(fo->from, len, angle1, open);
|
||||
//p.drawLine(fo->to, pOpen);
|
||||
|
||||
}
|
||||
|
||||
// void paintDoor(Painter& p) {
|
||||
|
||||
// QPen pen;
|
||||
// pen.setColor(QColor(0.5,0.5,0.5));
|
||||
// pen.setStyle(Qt::PenStyle::DotLine);
|
||||
// p.setPenBrush(pen, Qt::NoBrush);
|
||||
|
||||
|
||||
// // opening indicator
|
||||
// const float open = M_PI / 4;
|
||||
// const float len = (fo->to - fo->from).length();
|
||||
// const float angle1 = std::atan2(fo->to.y-fo->from.y, fo->to.x-fo->from.x);
|
||||
// const float angle2 = angle1 + open;
|
||||
// const Point2 pOpen = Point2( std::cos(angle2) * len, std::sin(angle2) * len ) + fo->from;
|
||||
|
||||
// p.drawLine(fo->from, fo->to);
|
||||
// p.drawLine(fo->from, pOpen);
|
||||
|
||||
// p.drawArc(fo->from, len, angle1, open);
|
||||
// //p.drawLine(fo->to, pOpen);
|
||||
|
||||
// // obstacle length
|
||||
// p.setPenBrush(Qt::black, Qt::NoBrush);
|
||||
// p.drawLength(fo->from, fo->to, fo->from.getDistance(fo->to));
|
||||
|
||||
// }
|
||||
|
||||
void onFocus() override {
|
||||
;
|
||||
}
|
||||
|
||||
@@ -26,12 +26,12 @@ public:
|
||||
}
|
||||
|
||||
/** get the element's minimal distance (nearest whatsoever) to the given point */
|
||||
float getMinDistanceXY(const Point2 p) const override {
|
||||
float min = 999999;
|
||||
ClickDist getMinDistanceXY(const Point2 p) const override {
|
||||
ClickDist min = ClickDist::max();
|
||||
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);
|
||||
const ClickDist dst = MapElementHelper::getLineDistanceXY(p1, p2, p);
|
||||
if (dst < min) {min = dst;}
|
||||
}
|
||||
return min;
|
||||
|
||||
@@ -42,9 +42,9 @@ public:
|
||||
}
|
||||
|
||||
/** get the element's minimal distance (nearest whatsoever) to the given point */
|
||||
float getMinDistanceXY(const Point2 p) const override {
|
||||
ClickDist getMinDistanceXY(const Point2 p) const override {
|
||||
(void) p;
|
||||
return CFG::SEL_THRESHOLD_SIZE_PX; // we do not know the distance from the image
|
||||
return ClickDist(CFG::SEL_THRESHOLD_SIZE_PX, ClickDistType::UNKNOWN); // we do not know the distance from the image
|
||||
}
|
||||
|
||||
virtual void onFocus() override {
|
||||
|
||||
@@ -30,8 +30,8 @@ public:
|
||||
}
|
||||
|
||||
/** get the element's minimal distance (nearest whatsoever) to the given point */
|
||||
float getMinDistanceXY(const Point2 p) const override {
|
||||
return p.getDistance(poi->pos);
|
||||
ClickDist getMinDistanceXY(const Point2 p) const override {
|
||||
return ClickDist(p.getDistance(poi->pos), ClickDistType::DIRECT);
|
||||
}
|
||||
|
||||
/** repaint me */
|
||||
|
||||
@@ -35,11 +35,11 @@ public:
|
||||
}
|
||||
|
||||
/** get the element's minimal distance (nearest whatsoever) to the given point */
|
||||
float getMinDistanceXY(const Point2 p) const override {
|
||||
ClickDist getMinDistanceXY(const Point2 p) const override {
|
||||
|
||||
auto comp = [p] (const Floorplan::StairPart& p1, const Floorplan::StairPart& p2) {
|
||||
const float d1 = MapElementHelper::getLineDistanceXY(p1.start.xy(), p1.end.xy(), p);
|
||||
const float d2 = MapElementHelper::getLineDistanceXY(p2.start.xy(), p2.end.xy(), p);
|
||||
const ClickDist d1 = MapElementHelper::getLineDistanceXY(p1.start.xy(), p1.end.xy(), p);
|
||||
const ClickDist d2 = MapElementHelper::getLineDistanceXY(p2.start.xy(), p2.end.xy(), p);
|
||||
return d1 < d2;
|
||||
};
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
#include "ClickDist.h"
|
||||
|
||||
/** configuration */
|
||||
namespace CFG {
|
||||
const float MOVE_SNAP_SIZE_M = 0.1f; // in meter (= map-space)
|
||||
@@ -33,7 +35,7 @@ public:
|
||||
* move l into dst
|
||||
* and calculate the cut-point between l and (p1, p2)
|
||||
*/
|
||||
static float getLineDistanceXY(Point2 p1, Point2 p2, Point2 dst) {
|
||||
static ClickDist getLineDistanceXY(Point2 p1, Point2 p2, Point2 dst) {
|
||||
|
||||
// the line (p1, p2)
|
||||
const Line2 line(p1, p2);
|
||||
@@ -46,20 +48,21 @@ public:
|
||||
|
||||
// calculate the cut betwen L and (p1,p2) (if any)
|
||||
Point2 cut(0,0);
|
||||
ClickDist cutDist(99999999, ClickDistType::CUT);
|
||||
if (line.getSegmentIntersection(perb, cut)) {
|
||||
|
||||
// distance between cut-point and mouse
|
||||
return cut.getDistance(dst);
|
||||
|
||||
} else {
|
||||
|
||||
// no cut detected
|
||||
const float d1 = p1.getDistance(dst);
|
||||
const float d2 = p2.getDistance(dst);
|
||||
return std::min(d1, d2);
|
||||
cutDist.dst_px = cut.getDistance(dst);
|
||||
|
||||
}
|
||||
|
||||
// distance from endpoints
|
||||
const ClickDist d1(p1.getDistance(dst), ClickDistType::DIRECT);
|
||||
const ClickDist d2(p2.getDistance(dst), ClickDistType::DIRECT);
|
||||
|
||||
// return the nearest possibility:
|
||||
return std::min(d1, std::min(d2, cutDist));
|
||||
|
||||
}
|
||||
|
||||
static QPen getPen(Floorplan::Material mat, Floorplan::ObstacleType type, bool focus) {
|
||||
|
||||
@@ -69,6 +69,11 @@ public:
|
||||
p->drawEllipse(s.xms(center.x)-r, s.yms(center.y)-r, 2*r, 2*r);
|
||||
}
|
||||
|
||||
void drawCircle_px(const Point2 center, const float size_px) {
|
||||
int r = size_px;
|
||||
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));
|
||||
}
|
||||
@@ -115,6 +120,16 @@ public:
|
||||
p->drawImage(s.xms(pt.x)-img.width()/2, s.yms(pt.y)-img.height()/2, img);
|
||||
}
|
||||
|
||||
void drawLength(Point2 p1, Point2 p2, const float len) {
|
||||
if (p1.x < p2.x) {swap(p1, p2);}
|
||||
const Point2 center_m = (p1 + p2) / 2;
|
||||
Point2 dir_px = (p2 - p1).perpendicular().normalized() * 5;
|
||||
if (dir_px.x <= 0) {dir_px = -dir_px;}
|
||||
const Point2 pos_m = center_m + dir_px / getScaler().getScale();
|
||||
char buf[64]; sprintf(buf, "%.1f", len);
|
||||
drawText(pos_m, buf);
|
||||
}
|
||||
|
||||
void setBrush(const QBrush& brush) { p->setBrush(brush); }
|
||||
void setBrush(const Qt::BrushStyle& brush) { p->setBrush(brush); }
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ public:
|
||||
Scaler& s = m->getScaler();
|
||||
|
||||
if (e->delta() < 0) {
|
||||
s.setScale(s.getScale() * 0.5);
|
||||
s.setScale(s.getScale() * 0.75);
|
||||
} else {
|
||||
s.setScale(s.getScale() / 0.5);
|
||||
s.setScale(s.getScale() / 0.75);
|
||||
}
|
||||
|
||||
if (s.getScale() > 1000) {s.setScale(1000);}
|
||||
|
||||
0
mapview/2D/tools/ToolMeasure.cpp
Normal file
0
mapview/2D/tools/ToolMeasure.cpp
Normal file
132
mapview/2D/tools/ToolMeasure.h
Normal file
132
mapview/2D/tools/ToolMeasure.h
Normal file
@@ -0,0 +1,132 @@
|
||||
#ifndef TOOLMEASURE_H
|
||||
#define TOOLMEASURE_H
|
||||
|
||||
|
||||
#include "Tool.h"
|
||||
#include "../MapView2D.h"
|
||||
|
||||
#include "../../model/MapModelElement.h"
|
||||
#include "../../model/MapModel.h"
|
||||
#include "../MapViewElementHelper.h"
|
||||
|
||||
|
||||
/**
|
||||
* this tool allows:
|
||||
* - selecting elements within the 2D view (focus/unfocus)
|
||||
* - selecting and moving nodes of elements inheriting from HasMoveableNodes
|
||||
*
|
||||
*/
|
||||
class ToolMeasure : public Tool {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/** register this tool into the given tools-queue */
|
||||
Tools& tools;
|
||||
Tool* oldMainTool;
|
||||
|
||||
std::vector<Point2> pts_m;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
ToolMeasure(Tools& tools) : tools(tools) {
|
||||
|
||||
oldMainTool = tools.getMain(); // keep the current tool to reset it later
|
||||
tools.setMain(this);
|
||||
|
||||
resetMe();
|
||||
|
||||
}
|
||||
|
||||
/** dtor */
|
||||
virtual ~ToolMeasure() {
|
||||
tools.setMain(oldMainTool); // reset to the previous tool
|
||||
}
|
||||
|
||||
const std::string getName() const {
|
||||
return "Measure";
|
||||
}
|
||||
|
||||
virtual bool mousePressEvent(MapView2D*, QMouseEvent* e) override {
|
||||
if (e->button() == Qt::MouseButton::LeftButton) {
|
||||
pts_m.push_back(pts_m.back());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool mouseMoveEvent(MapView2D* m, QMouseEvent* e) override {
|
||||
const Point2 onScreen(e->x(), e->y());
|
||||
Point2 onMap = m->getScaler().sm(onScreen);
|
||||
onMap = m->getScaler().snap(onMap);
|
||||
pts_m.back() = onMap;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool mouseReleaseEvent(MapView2D*, QMouseEvent* e) override {
|
||||
if (e->button() == Qt::MouseButton::LeftButton) {
|
||||
return true;
|
||||
} else if (e->button() == Qt::MouseButton::RightButton) {
|
||||
resetMe();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool keyPressEvent(MapView2D* m, QKeyEvent* e) override {
|
||||
(void) m;
|
||||
if (e->key() == Qt::Key_Escape) {
|
||||
disableMe();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void paintAfter(MapView2D*, Painter& p) override {
|
||||
|
||||
if (pts_m.size() < 1) {return;}
|
||||
|
||||
p.setPen(Qt::black);
|
||||
|
||||
for (const Point2 p_m : pts_m) {
|
||||
p.drawCircle(p_m);
|
||||
}
|
||||
|
||||
float totalLen_m = 0;
|
||||
for (size_t i = 0; i < pts_m.size() - 1; ++i) {
|
||||
const Point2 p1 = pts_m[i];
|
||||
const Point2 p2 = pts_m[i+1];
|
||||
const float len_m = p1.getDistance(p2);
|
||||
p.drawLine(p1, p2);
|
||||
p.drawLength(p1, p2, len_m);
|
||||
totalLen_m += len_m;
|
||||
}
|
||||
|
||||
if (pts_m.size() > 1) {
|
||||
emit onHelpTextChange("total length is: " + QString::number(totalLen_m) + "m | right-click to restart");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
void resetMe() {
|
||||
pts_m.resize(1);
|
||||
emit onHelpTextChange("select the starting point for measuring");
|
||||
}
|
||||
|
||||
/** finish creating new elements */
|
||||
void disableMe() {
|
||||
delete this; // see dtor!
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // TOOLMEASURE_H
|
||||
@@ -96,9 +96,19 @@ public:
|
||||
p.p->drawLine(mouseX, 0, mouseX, rs);
|
||||
|
||||
|
||||
|
||||
|
||||
p.setPenBrush(Qt::black, Qt::NoBrush);
|
||||
char buf[128];
|
||||
|
||||
// coordinates
|
||||
QRect ru(0,0,rs-1,rs-1);
|
||||
p.p->fillRect(ru, Qt::white);
|
||||
std::sprintf(buf, "%.1f", p.getScaler().xsm(this->mouseX));
|
||||
p.p->drawText(5,15, buf);
|
||||
std::sprintf(buf, "%.1f", p.getScaler().ysm(this->mouseY));
|
||||
p.p->drawText(5,30, buf);
|
||||
|
||||
// y-axis
|
||||
p.p->setClipRect(ry);
|
||||
for (float y = r.y0; y <= r.y1; y += step) {
|
||||
@@ -141,6 +151,8 @@ public:
|
||||
|
||||
p.p->setClipping(false);
|
||||
|
||||
|
||||
|
||||
// snapped dot
|
||||
const Point2 mouseOnScreen(mouseX, mouseY);
|
||||
const Point2 mouseInMap = p.s.sm(mouseOnScreen);
|
||||
|
||||
@@ -46,6 +46,15 @@ public:
|
||||
setFocused(m, nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 focus(MapView2D* v, MapModelElement* el) {
|
||||
setFocused(v, el);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void processUnfocus(MapView2D* m, MapModelElement* elem) {
|
||||
@@ -202,9 +211,11 @@ private:
|
||||
|
||||
const float g = m->getScaler().sm(15); // increase each BBox by 15 px (needed mainly for hor/ver lines)
|
||||
|
||||
#warning "which elements to select? among all currently visible? or only among the selected layer?"
|
||||
// get all elements with bounding-box matchings
|
||||
std::vector<MapModelElement*> possible;
|
||||
for (MapModelElement* el : m->getModel()->getSelectedLayerElements()) {
|
||||
// for (MapModelElement* el : m->getModel()->getSelectedLayerElements()) {
|
||||
for (MapModelElement* el : m->getModel()->getVisibleElements()) {
|
||||
if (!el->getMV2D()) {continue;}
|
||||
BBox2 bbox = el->getMV2D()->getBoundingBox(); // elements 2D bbox
|
||||
bbox.grow(Point2(g, g)); // grow a little (needed for straight lines)
|
||||
|
||||
@@ -24,7 +24,7 @@ protected:
|
||||
/** repaint me */
|
||||
void paintGL() override {
|
||||
|
||||
Cube cube(ap->getPos(f), 0.5);
|
||||
Cube cube(ap->getPos(f), 0.25);
|
||||
cube.paintGL();
|
||||
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ protected:
|
||||
glColor3f(1,1,1);
|
||||
break;
|
||||
case Floorplan::OutlineMethod::REMOVE:
|
||||
glColor3f(0.2, 0.2, 0.2);
|
||||
glColor3f(0.3, 0.3, 0.3);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,11 +32,12 @@ void MapView3D::initializeGL() {
|
||||
|
||||
QGLWidget::initializeGL();
|
||||
|
||||
//glCullFace(GL_FRONT);
|
||||
glCullFace(GL_FRONT);
|
||||
//glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
// culling, lighting, depth-test, ...
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
|
||||
21
mapview/model/IHasEditableMeta.h
Normal file
21
mapview/model/IHasEditableMeta.h
Normal 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
|
||||
@@ -26,16 +26,18 @@ class MMFloor : public MapLayer, public IHasParams {
|
||||
|
||||
private:
|
||||
|
||||
Floorplan::IndoorMap* map;
|
||||
|
||||
/** the underlying data-structure */
|
||||
Floorplan::Floor* floor;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor. existing floor */
|
||||
MMFloor(MapLayer* parent, Floorplan::Floor* floor) : MapLayer(parent, MapLayerType::FLOOR), floor(floor) {
|
||||
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);
|
||||
@@ -58,12 +60,14 @@ public:
|
||||
std::string getLayerName() const override {return floor->name;}
|
||||
|
||||
virtual int getNumParams() const override {
|
||||
return 1;
|
||||
return 3;
|
||||
}
|
||||
|
||||
virtual Param getParamDesc(const int idx) const override {
|
||||
switch(idx) {
|
||||
case 0: return Param("anem", ParamType::STRING);
|
||||
case 0: return Param("name", ParamType::STRING);
|
||||
case 1: return Param("height", ParamType::FLOAT);
|
||||
case 2: return Param("at height", ParamType::FLOAT);
|
||||
}
|
||||
throw 1;
|
||||
}
|
||||
@@ -71,6 +75,8 @@ public:
|
||||
virtual ParamValue getParamValue(const int idx) const override {
|
||||
switch(idx) {
|
||||
case 0: return floor->name;
|
||||
case 1: return floor->height;
|
||||
case 2: return floor->atHeight;
|
||||
}
|
||||
throw 1;
|
||||
}
|
||||
@@ -78,9 +84,16 @@ public:
|
||||
virtual void setParamValue(const int idx, const ParamValue& val) const override {
|
||||
switch(idx) {
|
||||
case 0: floor->name = val.toString(); break;
|
||||
case 1: floor->height = val.toFloat(); break;
|
||||
case 2: floor->atHeight = val.toFloat(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void deleteMe() {
|
||||
parent->removeSublayer(this);
|
||||
map->floors.erase(std::remove(map->floors.begin(), map->floors.end(), floor), map->floors.end());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // MMFLOOR_H
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -26,7 +27,7 @@ public:
|
||||
}
|
||||
|
||||
virtual int getNumParams() const override {
|
||||
return 3;
|
||||
return 6;
|
||||
}
|
||||
|
||||
virtual Param getParamDesc(const int idx) const override {
|
||||
@@ -34,6 +35,9 @@ public:
|
||||
case 0: return Param("name", ParamType::STRING);
|
||||
case 1: return Param("MAC", ParamType::STRING);
|
||||
case 2: return Param("Position", ParamType::POINT3);
|
||||
case 3: return Param("TXP", ParamType::FLOAT);
|
||||
case 4: return Param("EXP", ParamType::FLOAT);
|
||||
case 5: return Param("WAF", ParamType::FLOAT);
|
||||
}
|
||||
throw 1;
|
||||
}
|
||||
@@ -43,6 +47,9 @@ public:
|
||||
case 0: return ap->name;
|
||||
case 1: return ap->mac;
|
||||
case 2: return ap->pos;
|
||||
case 3: return ap->model.txp;
|
||||
case 4: return ap->model.exp;
|
||||
case 5: return ap->model.waf;
|
||||
}
|
||||
throw 1;
|
||||
}
|
||||
@@ -52,9 +59,20 @@ public:
|
||||
case 0: ap->name = val.toString(); break;
|
||||
case 1: ap->mac = val.toString(); break;
|
||||
case 2: ap->pos = val.toPoint3(); break;
|
||||
case 3: ap->model.txp = val.toFloat(); break;
|
||||
case 4: ap->model.exp = val.toFloat(); break;
|
||||
case 5: ap->model.waf = val.toFloat(); break;
|
||||
}
|
||||
}
|
||||
|
||||
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;}
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -23,14 +23,20 @@ public:
|
||||
}
|
||||
|
||||
virtual int getNumParams() const override {
|
||||
return 3;
|
||||
return 9;
|
||||
}
|
||||
|
||||
virtual Param getParamDesc(const int idx) const override {
|
||||
switch(idx) {
|
||||
case 0: return Param("name", ParamType::STRING);
|
||||
case 1: return Param("MAC", ParamType::STRING);
|
||||
case 2: return Param("Position", ParamType::POINT3);
|
||||
case 1: return Param("Position", ParamType::POINT3);
|
||||
case 2: return Param("MAC", ParamType::STRING);
|
||||
case 3: return Param("major", ParamType::STRING);
|
||||
case 4: return Param("minor", ParamType::STRING);
|
||||
case 5: return Param("UUDI", ParamType::STRING);
|
||||
case 6: return Param("TXP", ParamType::FLOAT);
|
||||
case 7: return Param("EXP", ParamType::FLOAT);
|
||||
case 8: return Param("WAF", ParamType::FLOAT);
|
||||
}
|
||||
throw 1;
|
||||
}
|
||||
@@ -38,8 +44,14 @@ public:
|
||||
virtual ParamValue getParamValue(const int idx) const override {
|
||||
switch(idx) {
|
||||
case 0: return b->name;
|
||||
case 1: return b->mac;
|
||||
case 2: return b->pos;
|
||||
case 1: return b->pos;
|
||||
case 2: return b->mac;
|
||||
case 3: return b->major;
|
||||
case 4: return b->minor;
|
||||
case 5: return b->uuid;
|
||||
case 6: return b->model.txp;
|
||||
case 7: return b->model.exp;
|
||||
case 8: return b->model.waf;
|
||||
}
|
||||
throw 1;
|
||||
}
|
||||
@@ -47,8 +59,14 @@ public:
|
||||
virtual void setParamValue(const int idx, const ParamValue& val) const override {
|
||||
switch(idx) {
|
||||
case 0: b->name = val.toString(); break;
|
||||
case 1: b->mac = val.toString(); break;
|
||||
case 2: b->pos = val.toPoint3(); break;
|
||||
case 1: b->pos = val.toPoint3(); break;
|
||||
case 2: b->mac = val.toString(); break;
|
||||
case 3: b->major = val.toString(); break;
|
||||
case 4: b->minor = val.toString(); break;
|
||||
case 5: b->uuid = val.toString(); break;
|
||||
case 6: b->uuid = val.toFloat(); break;
|
||||
case 7: b->uuid = val.toFloat(); break;
|
||||
case 8: b->uuid = val.toFloat(); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "IHasMaterial.h"
|
||||
#include "IHasObstacleType.h"
|
||||
#include "IHasParams.h"
|
||||
|
||||
#include "../2D/MV2DElementFloorObstacleLine.h"
|
||||
#include "../3D/MV3DElementFloorObstacleWall.h"
|
||||
@@ -13,7 +14,7 @@
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
|
||||
class MMFloorObstacleLine : public MapModelElement, public IHasMaterial, public IHasObstacleType {
|
||||
class MMFloorObstacleLine : public MapModelElement, public IHasMaterial, public IHasObstacleType, public IHasParams {
|
||||
|
||||
public:
|
||||
|
||||
@@ -43,6 +44,31 @@ public:
|
||||
mf->obstacles.erase(std::remove(mf->obstacles.begin(), mf->obstacles.end(), fo), mf->obstacles.end());
|
||||
}
|
||||
|
||||
|
||||
virtual int getNumParams() const override {
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual Param getParamDesc(const int idx) const override {
|
||||
switch(idx) {
|
||||
case 0: return Param("length", ParamType::FLOAT, true);
|
||||
}
|
||||
throw 1;
|
||||
}
|
||||
|
||||
virtual ParamValue getParamValue(const int idx) const override {
|
||||
switch(idx) {
|
||||
case 0: return fo->from.getDistance(fo->to);
|
||||
}
|
||||
throw 1;
|
||||
}
|
||||
|
||||
virtual void setParamValue(const int idx, const ParamValue& val) const override {
|
||||
switch(idx) {
|
||||
case 0: break;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // MAPELEMENTOBSTACLE_H
|
||||
|
||||
@@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
||||
41
mapview/model/MMFloorOutlinePolygonCombined.h
Normal file
41
mapview/model/MMFloorOutlinePolygonCombined.h
Normal 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
|
||||
@@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
|
||||
// add all floors
|
||||
for (Floorplan::Floor* floor : map->floors) {
|
||||
new MMFloor(this, floor);
|
||||
new MMFloor(this, map, floor);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,6 +32,22 @@ public:
|
||||
/** get the underlying model */
|
||||
Floorplan::IndoorMap* getMap() {return map;}
|
||||
|
||||
MMFloor* createFloor() {
|
||||
|
||||
// add to underlying model
|
||||
Floorplan::Floor* floor = new Floorplan::Floor();
|
||||
floor->name = "floor";
|
||||
map->floors.push_back(floor);
|
||||
|
||||
// add to UI model
|
||||
MMFloor* mmfloor = new MMFloor(this, map, floor);
|
||||
//elements.push_back(mmfloor);
|
||||
|
||||
return mmfloor;
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // MMFLOORS_H
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "MapLayerListener.h"
|
||||
|
||||
class MapModelElement;
|
||||
|
||||
|
||||
@@ -28,14 +30,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;
|
||||
|
||||
@@ -60,6 +65,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;}
|
||||
|
||||
@@ -77,14 +87,28 @@ 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()); }
|
||||
|
||||
/** is this layer currently visible? */
|
||||
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 */
|
||||
@@ -94,7 +118,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);
|
||||
@@ -102,9 +126,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/** add a new sublayer to this layer */
|
||||
void addSublayer(MapLayer* ml) {
|
||||
@@ -115,8 +137,35 @@ protected:
|
||||
|
||||
}
|
||||
|
||||
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:
|
||||
|
||||
25
mapview/model/MapLayerListener.h
Normal file
25
mapview/model/MapLayerListener.h
Normal 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
|
||||
@@ -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,6 +46,19 @@ 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));
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
selLayer = nullptr;
|
||||
//selElements.clear();
|
||||
@@ -57,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();
|
||||
|
||||
@@ -68,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;
|
||||
@@ -76,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 */
|
||||
|
||||
13
mapview/model/MapModelListener.h
Normal file
13
mapview/model/MapModelListener.h
Normal 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
|
||||
Reference in New Issue
Block a user