added more cpp files for faster compile speeds

removed many obsolte elements
many improvements and fixes
This commit is contained in:
2018-07-20 15:00:43 +02:00
parent 7ee4e122e8
commit 5d002c3f2b
43 changed files with 1257 additions and 1361 deletions

View File

@@ -60,7 +60,15 @@ SOURCES += \
mapview/2D/MV2DElementFloorObstacleDoor.cpp \ mapview/2D/MV2DElementFloorObstacleDoor.cpp \
mapview/2D/MV2DElementFloorObstacleObject.cpp \ mapview/2D/MV2DElementFloorObstacleObject.cpp \
mapview/3D/grid/GridRenderer.cpp \ mapview/3D/grid/GridRenderer.cpp \
mapview/3D/navMesh/NavMeshRenderer.cpp mapview/3D/navMesh/NavMeshRenderer.cpp \
mapview/2D/MV2DElementFloorObstacleLine.cpp \
mapview/2D/MapViewElementHelper.cpp \
mapview/2D/MV2DElementFloorOutlinePolygon.cpp \
mapview/2D/Painter.cpp \
mapview/3D/floorplan/FloorplanRenderer.cpp \
mapview/2D/MV2DElementStair.cpp \
mapview/2D/MV2DElementElevator.cpp \
mapview/2D/MV2DElementFloorObstacleCircle.cpp
HEADERS += MainWindow.h \ HEADERS += MainWindow.h \
@@ -156,6 +164,7 @@ HEADERS += MainWindow.h \
mapview/model/MMFloorGroundTruthPoint.h \ mapview/model/MMFloorGroundTruthPoint.h \
mapview/2D/MV2DElementGroundTruthPoint.h \ mapview/2D/MV2DElementGroundTruthPoint.h \
misc/LINTView.h \ misc/LINTView.h \
mapview/2D/HasMoveableNodes.h \
mapview/2D/tools/ToolNewElement.h \ mapview/2D/tools/ToolNewElement.h \
mapview/2D/tools/ToolNewDoor.h \ mapview/2D/tools/ToolNewDoor.h \
mapview/2D/tools/ToolNewWall.h \ mapview/2D/tools/ToolNewWall.h \

View File

@@ -126,7 +126,7 @@ MainController::MainController() {
//mapModel->load("/apps/paper/diss/data/maps/walkmodel_stairs3.xml"); //mapModel->load("/apps/paper/diss/data/maps/walkmodel_stairs3.xml");
//mapModel->load("/apps/paper/maps/museum/map43_svg.xml"); //mapModel->load("/apps/paper/maps/museum/map43_svg.xml");
//mapModel->load("/apps/paper/diss/data/maps/SHL41_nm.xml"); mapModel->load("/apps/paper/maps/shl/SHL45_nm.xml");
//mapModel->load("/mnt/sdcard/SHL41_nm.xml"); //mapModel->load("/mnt/sdcard/SHL41_nm.xml");

View File

@@ -3,6 +3,7 @@
#include <Indoor/geo/Point2.h> #include <Indoor/geo/Point2.h>
#include "../2D/MapView2D.h" #include "../2D/MapView2D.h"
#include <vector>
/** the selectable/moveable node */ /** the selectable/moveable node */
struct MoveableNode { struct MoveableNode {

View File

@@ -10,6 +10,7 @@
#include <Indoor/geo/Line2.h> #include <Indoor/geo/Line2.h>
#include "ClickDist.h" #include "ClickDist.h"
#include "HasMoveableNodes.h"
/** /**
* represents one drawable, selectable, editable, ... * represents one drawable, selectable, editable, ...
@@ -36,7 +37,20 @@ public:
/** repaint me */ /** repaint me */
virtual void paint(Painter& p) = 0; virtual void paint(Painter& p) = 0;
/** repaint me, 2nd layer (e.g. moveable nodes) */
virtual void paintAfter(Painter& p) {
// HasMoveableNodes? -> paint them here
HasMoveableNodes* e = dynamic_cast<HasMoveableNodes*>(this);
if (e) {
for (const MoveableNode& n : e->getMoveableNodes()) {
const bool sel = e->getSelectedNode() == n.userIdx; // node is selected
const bool foc = hasFocus(); // element (with nodes) currently focused
p.drawNode(n.pos, foc, sel);
}
}
}
/** got focus */ /** got focus */
void focus() { void focus() {

View File

@@ -47,28 +47,23 @@ public:
static const QPixmap& pixmapFocused = UIHelper::getPixmapColored("wifi", CFG::FOCUS_COLOR, 16); static const QPixmap& pixmapFocused = UIHelper::getPixmapColored("wifi", CFG::FOCUS_COLOR, 16);
static const QPixmap& pixmapSel = UIHelper::getPixmapColored("wifi", CFG::SEL_COLOR, 16); static const QPixmap& pixmapSel = UIHelper::getPixmapColored("wifi", CFG::SEL_COLOR, 16);
if (selectedUserIdx == 0) { if (selectedUserIdx == 0) {
//p.setPenBrush(Qt::black, CFG::SEL_COLOR);
//p.drawCircle(ap->pos.xy());
p.drawPixmap(ap->pos.xy(), pixmapSel); p.drawPixmap(ap->pos.xy(), pixmapSel);
} else if (hasFocus()) { } else if (hasFocus()) {
//p.setPenBrush(Qt::black, Qt::NoBrush);
//p.drawCircle(ap->pos.xy());
p.drawPixmap(ap->pos.xy(), pixmapFocused); p.drawPixmap(ap->pos.xy(), pixmapFocused);
} else { } else {
//p.setPenBrush(Qt::gray, Qt::NoBrush);
//p.drawCircle(ap->pos.xy());
p.drawPixmap(ap->pos.xy(), pixmapUnfocused); p.drawPixmap(ap->pos.xy(), pixmapUnfocused);
} }
// label // label
p.setPenBrush(Qt::black, Qt::NoBrush); //p.setPenBrush(Qt::black, Qt::NoBrush);
p.drawDot(ap->pos.xy()); //p.drawDot(ap->pos.xy());
if (p.getScaler().getScale() >= 25) { if (p.getScaler().getScale() >= 25) {
p.setPenBrush(Qt::black, Qt::NoBrush);
const std::string str = ap->name + " (" + ap->mac + ")"; 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()); 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) { } else if (p.getScaler().getScale() >= 12) {
p.setPenBrush(Qt::black, Qt::NoBrush);
const std::string str = ap->name; const std::string str = ap->name;
p.p->drawText(p.getScaler().xms(ap->pos.x) + 10, p.getScaler().yms(ap->pos.y) + 5, str.c_str()); p.p->drawText(p.getScaler().xms(ap->pos.x) + 10, p.getScaler().yms(ap->pos.y) + 5, str.c_str());
} }
@@ -90,27 +85,6 @@ public:
emit v->onElementChange(this); emit v->onElementChange(this);
} }
virtual void mousePressed(MapView2D* v, const Point2 p) override {
(void) v;
(void) p;
}
virtual void mouseMove(MapView2D* v, const Point2 p) override {
(void) v;
(void) p;
}
virtual void mouseReleased(MapView2D* v, const Point2 p) override {
(void) v;
(void) p;
}
virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override {
(void) v;
(void) e;
return false;
}
virtual void onFocus() override { virtual void onFocus() override {
; ;
} }

View File

@@ -41,27 +41,22 @@ public:
static const QPixmap& pixmapSel = UIHelper::getPixmapColored("beacon", CFG::SEL_COLOR, 16); static const QPixmap& pixmapSel = UIHelper::getPixmapColored("beacon", CFG::SEL_COLOR, 16);
if (selectedUserIdx == 0) { if (selectedUserIdx == 0) {
//p.setPenBrush(Qt::black, CFG::SEL_COLOR);
//p.drawCircle(b->pos.xy());
p.drawPixmap(b->pos.xy(), pixmapSel); p.drawPixmap(b->pos.xy(), pixmapSel);
} else if (hasFocus()) { } else if (hasFocus()) {
//p.setPenBrush(Qt::black, Qt::NoBrush);
//p.drawCircle(b->pos.xy());
p.drawPixmap(b->pos.xy(), pixmapFocused); p.drawPixmap(b->pos.xy(), pixmapFocused);
} else { } else {
//p.setPenBrush(Qt::gray, Qt::NoBrush);
//p.drawCircle(b->pos.xy());
p.drawPixmap(b->pos.xy(), pixmapUnfocused); p.drawPixmap(b->pos.xy(), pixmapUnfocused);
} }
// label // label
p.setPenBrush(Qt::black, Qt::NoBrush); //p.setPenBrush(Qt::black, Qt::NoBrush);
p.drawDot(b->pos.xy()); //p.drawDot(b->pos.xy());
if (p.getScaler().getScale() >= 25) { if (p.getScaler().getScale() >= 25) {
p.setPenBrush(Qt::black, Qt::NoBrush);
const std::string str = b->name + " (" + b->mac + ")"; const std::string str = b->name + " (" + b->mac + ")";
p.p->drawText(p.getScaler().xms(b->pos.x) + 10, p.getScaler().yms(b->pos.y) + 5, str.c_str()); p.p->drawText(p.getScaler().xms(b->pos.x) + 10, p.getScaler().yms(b->pos.y) + 5, str.c_str());
} else if (p.getScaler().getScale() >= 10) { } else if (p.getScaler().getScale() >= 12) {
p.setPenBrush(Qt::black, Qt::NoBrush);
const std::string str = b->name; const std::string str = b->name;
p.p->drawText(p.getScaler().xms(b->pos.x) + 10, p.getScaler().yms(b->pos.y) + 5, str.c_str()); p.p->drawText(p.getScaler().xms(b->pos.x) + 10, p.getScaler().yms(b->pos.y) + 5, str.c_str());
} }
@@ -91,31 +86,6 @@ public:
; ;
} }
/** 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;
(void) p;
}
/** mouse released */
virtual void mouseReleased(MapView2D* v, const Point2 p) override {
(void) v;
(void) p;
}
virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override {
(void) v;
(void) e;
return false;
}
}; };
#endif // MV2DELEMENTBEACON_H #endif // MV2DELEMENTBEACON_H

View File

@@ -0,0 +1,90 @@
#include "MV2DElementElevator.h"
#include "MV2DElement.h"
#include "HasMoveableNodes.h"
#include "MapViewElementHelper.h"
#include <Indoor/floorplan/v2/Floorplan.h>
#include "../../UIHelper.h"
/** is the given elevator's end connected to ANY of the floorplan's floors? */
static inline bool elevatorEndConnected(const Floorplan::IndoorMap* map, const Floorplan::Floor* floor, const Floorplan::Elevator* e) {
const int elevatorEnd_cm = std::round( (floor->atHeight + e->height_m) * 100 );
std::vector<int> floorsAtHeight_cm;
for (const Floorplan::Floor* f : map->floors) {
const int height_cm = std::round(f->atHeight*100);
floorsAtHeight_cm.push_back(height_cm);
}
const bool connected = std::find(floorsAtHeight_cm.begin(), floorsAtHeight_cm.end(), elevatorEnd_cm) != floorsAtHeight_cm.end();
return connected;
}
MV2DElementElevator::MV2DElementElevator(Floorplan::IndoorMap* map, Floorplan::Floor* floor, Floorplan::Elevator* elevator) : map(map), floor(floor), elevator(elevator) {
;
}
BBox2 MV2DElementElevator::getBoundingBox() const {
BBox2 bbox;
const float max = std::max(elevator->width, elevator->depth);
bbox.add(Point2(elevator->center.x, elevator->center.y));
bbox.grow(Point2(max/2, max/2));
return bbox;
}
ClickDist MV2DElementElevator::getMinDistanceXY(const Point2 p) const {
// std::vector<Point2> points = elevator->getPoints().points;
// points.push_back(elevator->center);
// auto it minEl = std::min_element(points.begin(), points.end(),
return ClickDist(p.getDistance(elevator->center), ClickDistType::DIRECT);
}
void MV2DElementElevator::paint(Painter& p) {
// area
const Floorplan::Polygon2 poly = elevator->getPoints();
p.setPenBrush(Qt::gray, Qt::lightGray);
p.drawPolygon(poly.points);
// outline
QPen pen; pen.setWidth(2); pen.setColor(QColor(0,0,0));
if (!elevatorEndConnected(map, floor, elevator)) {pen.setColor(QColor(255,0,0));}
if (elevator->height_m == 0) {pen.setColor(QColor(255,0,0));}
p.setPenBrush(pen, Qt::NoBrush);
//p.drawLine(poly.points[0], poly.points[1]);
p.drawLine(poly.points[1], poly.points[2]);
p.drawLine(poly.points[2], poly.points[3]);
p.drawLine(poly.points[3], poly.points[0]);
}
std::vector<MoveableNode> MV2DElementElevator::getMoveableNodes() const {
return { MoveableNode(0, elevator->center) };
}
void MV2DElementElevator::onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) {
(void) v;
if (userIdx == 0) {elevator->center.x = newPos.x; elevator->center.y = newPos.y;}
}
void MV2DElementElevator::onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos) {
(void) userIdx;
(void) newPos;
emit v->onElementChange(this);
}
void MV2DElementElevator::onFocus() {
;
}
void MV2DElementElevator::onUnfocus() {
;
}

View File

@@ -4,11 +4,8 @@
#include "MV2DElement.h" #include "MV2DElement.h"
#include "HasMoveableNodes.h" #include "HasMoveableNodes.h"
#include "MapViewElementHelper.h"
#include <Indoor/floorplan/v2/Floorplan.h> #include <Indoor/floorplan/v2/Floorplan.h>
#include "../../UIHelper.h"
class MV2DElementElevator : public MV2DElement, public HasMoveableNodes { class MV2DElementElevator : public MV2DElement, public HasMoveableNodes {
private: private:
@@ -20,117 +17,26 @@ private:
public: public:
/** ctor with the AP to render/edit */ /** ctor with the AP to render/edit */
MV2DElementElevator(Floorplan::IndoorMap* map, Floorplan::Floor* floor, Floorplan::Elevator* elevator) : map(map), floor(floor), elevator(elevator) {;} MV2DElementElevator(Floorplan::IndoorMap* map, Floorplan::Floor* floor, Floorplan::Elevator* elevator);
BBox2 getBoundingBox() const override;
BBox2 getBoundingBox() const override {
BBox2 bbox;
const float max = std::max(elevator->width, elevator->depth);
bbox.add(Point2(elevator->center.x, elevator->center.y));
bbox.grow(Point2(max/2, max/2));
return bbox;
}
/** get the element's minimal distance (nearest whatsoever) to the given point */ /** get the element's minimal distance (nearest whatsoever) to the given point */
ClickDist 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 ClickDist(p.getDistance(elevator->center), ClickDistType::DIRECT);
}
/** repaint me */ /** repaint me */
void paint(Painter& p) override { void paint(Painter& p) override;
// area virtual std::vector<MoveableNode> getMoveableNodes() const override;
const Floorplan::Polygon2 poly = elevator->getPoints();
p.setPenBrush(Qt::gray, Qt::lightGray);
p.drawPolygon(poly.points);
// outline virtual void onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) override;
QPen pen; pen.setWidth(2); pen.setColor(QColor(0,0,0));
if (!elevatorEndConnected(map, floor, elevator)) {pen.setColor(QColor(255,0,0));} void onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos) override;
if (elevator->height_m == 0) {pen.setColor(QColor(255,0,0));}
p.setPenBrush(pen, Qt::NoBrush); virtual void onFocus() override;
//p.drawLine(poly.points[0], poly.points[1]);
p.drawLine(poly.points[1], poly.points[2]);
p.drawLine(poly.points[2], poly.points[3]);
p.drawLine(poly.points[3], poly.points[0]);
if (selectedUserIdx == 0) { virtual void onUnfocus() override;
p.setPenBrush(Qt::black, CFG::SEL_COLOR);
p.drawCircle(elevator->center);
} else if (hasFocus()) {
p.setPenBrush(Qt::black, Qt::NoBrush);
p.drawCircle(elevator->center);
} else {
//p.setPenBrush(Qt::gray, Qt::NoBrush);
//p.drawCircle(elevator->center);
p.drawCircle_px(elevator->center, 3);
}
}
/** is the given elevator's end connected to ANY of the floorplan's floors? */
static inline bool elevatorEndConnected(const Floorplan::IndoorMap* map, const Floorplan::Floor* floor, const Floorplan::Elevator* e) {
const int elevatorEnd_cm = std::round( (floor->atHeight + e->height_m) * 100 );
std::vector<int> floorsAtHeight_cm;
for (const Floorplan::Floor* f : map->floors) {
const int height_cm = std::round(f->atHeight*100);
floorsAtHeight_cm.push_back(height_cm);
}
const bool connected = std::find(floorsAtHeight_cm.begin(), floorsAtHeight_cm.end(), elevatorEnd_cm) != floorsAtHeight_cm.end();
return connected;
}
virtual std::vector<MoveableNode> getMoveableNodes() const override {
return { MoveableNode(0, elevator->center) };
}
virtual void onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) override {
(void) v;
if (userIdx == 0) {elevator->center.x = newPos.x; elevator->center.y = newPos.y;}
}
void onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos) override {
(void) userIdx;
(void) newPos;
emit v->onElementChange(this);
}
virtual void mousePressed(MapView2D* v, const Point2 p) override {
(void) v;
(void) p;
}
virtual void mouseMove(MapView2D* v, const Point2 p) override {
(void) v;
(void) p;
}
virtual void mouseReleased(MapView2D* v, const Point2 p) override {
(void) v;
(void) p;
}
virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override {
(void) v;
(void) e;
return false;
}
virtual void onFocus() override {
;
}
virtual void onUnfocus() override {
;
}
}; };
#endif // MV2DELEMENTELEVATOR_H #endif // MV2DELEMENTELEVATOR_H

View File

@@ -49,24 +49,18 @@ public:
if (selectedUserIdx == 0) { if (selectedUserIdx == 0) {
//p.setPenBrush(Qt::black, CFG::SEL_COLOR);
//p.drawCircle(ap->pos.xy());
p.drawPixmap(fpl->posOnFloor, pixmapSel); p.drawPixmap(fpl->posOnFloor, pixmapSel);
} else if (hasFocus()) { } else if (hasFocus()) {
//p.setPenBrush(Qt::black, Qt::NoBrush);
//p.drawCircle(ap->pos.xy());
p.drawPixmap(fpl->posOnFloor, pixmapFocused); p.drawPixmap(fpl->posOnFloor, pixmapFocused);
} else { } else {
//p.setPenBrush(Qt::gray, Qt::NoBrush);
//p.drawCircle(ap->pos.xy());
p.drawPixmap(fpl->posOnFloor, pixmapUnfocused); p.drawPixmap(fpl->posOnFloor, pixmapUnfocused);
} }
// label // label
p.setPenBrush(Qt::black, Qt::NoBrush); //p.setPenBrush(Qt::black, Qt::NoBrush);
p.drawDot(fpl->posOnFloor); //p.drawDot(fpl->posOnFloor);
if (p.getScaler().getScale() >= 12) {
if (p.getScaler().getScale() >= 10) { p.setPenBrush(Qt::black, Qt::NoBrush);
const std::string str = fpl->name; const std::string str = fpl->name;
p.p->drawText(p.getScaler().xms(fpl->posOnFloor.x) + 10, p.getScaler().yms(fpl->posOnFloor.y) + 5, str.c_str()); p.p->drawText(p.getScaler().xms(fpl->posOnFloor.x) + 10, p.getScaler().yms(fpl->posOnFloor.y) + 5, str.c_str());
} }

View File

@@ -0,0 +1,81 @@
#include "MV2DElementFloorObstacleCircle.h"
#include "MV2DElement.h"
#include "MapViewElementHelper.h"
#include <Indoor/floorplan/v2/Floorplan.h>
MV2DElementFloorObstacleCircle::MV2DElementFloorObstacleCircle(Floorplan::FloorObstacleCircle* c) : c(c) {
;
}
BBox2 MV2DElementFloorObstacleCircle::getBoundingBox() const {
BBox2 bbox;
bbox.add(c->center);
bbox.grow(Point2(c->radius, c->radius));
return bbox;
}
ClickDist MV2DElementFloorObstacleCircle::getMinDistanceXY(const Point2 p) const {
return ClickDist(p.getDistance(c->center), ClickDistType::DIRECT);
}
void MV2DElementFloorObstacleCircle::paint(Painter& p) {
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<MoveableNode> MV2DElementFloorObstacleCircle::getMoveableNodes() const {
return {
MoveableNode(0, c->center),
MoveableNode(1, c->center+Point2(c->radius,0))
};
}
void MV2DElementFloorObstacleCircle::onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) {
(void) v;
switch(userIdx) {
case 0: c->center.x = newPos.x; c->center.y = newPos.y; break;
case 1: c->radius = newPos.getDistance(c->center); break;
}
}
void MV2DElementFloorObstacleCircle::onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos) {
(void) userIdx;
(void) newPos;
emit v->onElementChange(this);
}
//std::vector<Point2> MV2DElementFloorObstacleCircle::getSelPoints() const {
// return {c->center, (c->center + Point2(c->radius,0))};
//}
void MV2DElementFloorObstacleCircle::onFocus() {
;
}
void MV2DElementFloorObstacleCircle::onUnfocus() {
selPoint = -1;
}

View File

@@ -1,12 +1,12 @@
#ifndef MV2DELEMENTFLOOROBSTACLECIRCLE_H #ifndef MV2DELEMENTFLOOROBSTACLECIRCLE_H
#define MV2DELEMENTFLOOROBSTACLECIRCLE_H #define MV2DELEMENTFLOOROBSTACLECIRCLE_H
#include "MV2DElement.h" #include "MV2DElement.h"
#include "MapViewElementHelper.h" #include "MapViewElementHelper.h"
#include <Indoor/floorplan/v2/Floorplan.h> #include <Indoor/floorplan/v2/Floorplan.h>
class MV2DElementFloorObstacleCircle : public MV2DElement { class MV2DElementFloorObstacleCircle : public MV2DElement, public HasMoveableNodes {
private: private:
@@ -16,95 +16,28 @@ private:
public: public:
/** ctor */ /** ctor */
MV2DElementFloorObstacleCircle(Floorplan::FloorObstacleCircle* c) : c(c) {;} MV2DElementFloorObstacleCircle(Floorplan::FloorObstacleCircle* c);
/** get the element's 3D bounding box */ /** get the element's 3D bounding box */
BBox2 getBoundingBox() const override { 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 */ /** get the element's minimal distance (nearest whatsoever) to the given point */
ClickDist getMinDistanceXY(const Point2 p) const override { 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]));
}
/** repaint me */ /** repaint me */
void paint(Painter& p) override { void paint(Painter& p) override;
QPen pen;// = MapElementHelper::getPen(c->material, c->type, hasFocus()); //std::vector<Point2> getSelPoints() const;
p.setPenBrush(pen, Qt::NoBrush); virtual std::vector<MoveableNode> getMoveableNodes() const override;
p.drawCircle(c->center, c->radius);
//QBrush brush = MapElementHelper::getBru(c->material, c->type, _focused); virtual void onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) override;
// selected endpoints? void onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos) override;
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 virtual void onFocus() override;
if (hasFocus()) {
p.setPenBrush(Qt::black, Qt::NoBrush);
p.drawCircle(getSelPoints()[0]);
p.drawCircle(getSelPoints()[1]);
}
} virtual void onUnfocus() override;
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 = v->getScaler().snap(_p);
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;
}
}; };

View File

@@ -28,12 +28,13 @@ void MV2DElementFloorObstacleDoor::paint(Painter& p) {
return; return;
} }
// selected endpoints? // DEPRECATED
if (hasFocus()) { // // selected endpoints?
p.setPenBrush(Qt::NoPen, CFG::SEL_COLOR); // if (hasFocus()) {
if (selectedUserIdx == 0) {p.drawCircle(fo->from);} // p.setPenBrush(Qt::NoPen, CFG::SEL_COLOR);
if (selectedUserIdx == 1) {p.drawCircle(fo->to);} // if (selectedUserIdx == 0) {p.drawCircle(fo->from);}
} // if (selectedUserIdx == 1) {p.drawCircle(fo->to);}
// }
QPen pen; QPen pen;
pen.setColor(QColor(0.5,0.5,0.5)); pen.setColor(QColor(0.5,0.5,0.5));
@@ -80,13 +81,13 @@ void MV2DElementFloorObstacleDoor::paint(Painter& p) {
} }
// DEPRECATED
// available endpoints // // available endpoints
if (hasFocus()) { // if (hasFocus()) {
p.setPenBrush(Qt::black, Qt::NoBrush); // p.setPenBrush(Qt::black, Qt::NoBrush);
p.drawCircle(fo->from); // p.drawCircle(fo->from);
p.drawCircle(fo->to); // p.drawCircle(fo->to);
} // }
// obstacle length // obstacle length
if (hasFocus()) { if (hasFocus()) {
@@ -129,10 +130,13 @@ std::vector<MoveableNode> MV2DElementFloorObstacleDoor::getMoveableNodes() const
} }
void MV2DElementFloorObstacleDoor::onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos) { void MV2DElementFloorObstacleDoor::onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos) {
(void) userIdx;
(void) newPos;
emit v->onElementChange(this); emit v->onElementChange(this);
} }
void MV2DElementFloorObstacleDoor::onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) { void MV2DElementFloorObstacleDoor::onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) {
(void) v;
switch (userIdx) { switch (userIdx) {
case 0: fo->from = newPos; break; case 0: fo->from = newPos; break;
case 1: fo->to = newPos; break; case 1: fo->to = newPos; break;

View File

@@ -0,0 +1,92 @@
#include "MV2DElementFloorObstacleLine.h"
#include "MV2DElement.h"
#include "HasMoveableNodes.h"
#include "MapViewElementHelper.h"
#include <Indoor/floorplan/v2/Floorplan.h>
#include <stdio.h>
MV2DElementFloorObstacleLine::MV2DElementFloorObstacleLine(Floorplan::FloorObstacleLine* fo) : fo(fo) {
;
}
BBox2 MV2DElementFloorObstacleLine::getBoundingBox() const {
BBox2 bbox;
bbox.add(fo->from);
bbox.add(fo->to);
return bbox;
}
ClickDist MV2DElementFloorObstacleLine::getMinDistanceXY(const Point2 p) const {
return MapElementHelper::getLineDistanceXY(fo->from, fo->to, p);
}
void MV2DElementFloorObstacleLine::paint(Painter& p) {
// DEPRECATED
// // selected endpoints?
// if (hasFocus()) {
// p.setPenBrush(Qt::NoPen, CFG::SEL_COLOR);
// if (selectedUserIdx == 0) {p.drawCircle(fo->from);}
// if (selectedUserIdx == 1) {p.drawCircle(fo->to);}
// }
// convert wall's thickness from meter to pixels
const float thickness_px = p.s.ms(fo->thickness_m);
// remember the old pen
//QPen pen = p.getPen();
// see notes within MapElementHelper!
// lines only get thicker, but not longer!
p.setPenBrush(MapElementHelper::getPen(fo->material, fo->type, hasFocus(), thickness_px), Qt::NoBrush);
p.drawLine(fo->from, fo->to);
// reset the old pen3
//p.setPen(pen);
// length info
if (hasFocus()) {
// obstacle length
p.setPenBrush(Qt::black, Qt::NoBrush);
p.drawLength(fo->from, fo->to, fo->from.getDistance(fo->to), thickness_px/2);
}
// DEPRECATED
// // available endpoints
// p.drawNode(fo->from, hasFocus(), hasFocus() && selectedUserIdx == 0);
// p.drawNode(fo->to, hasFocus(), hasFocus() && selectedUserIdx == 1);
}
void MV2DElementFloorObstacleLine::onFocus() {
;
}
void MV2DElementFloorObstacleLine::onUnfocus() {
selectedUserIdx = -1; // clear selection
}
std::vector<MoveableNode> MV2DElementFloorObstacleLine::getMoveableNodes() const {
return {
MoveableNode(0, fo->from),
MoveableNode(1, fo->to)
};
}
void MV2DElementFloorObstacleLine::onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) {
(void) v;
if (userIdx == 0) {fo->from.x = newPos.x; fo->from.y = newPos.y;}
if (userIdx == 1) {fo->to.x = newPos.x; fo->to.y = newPos.y;}
}
void MV2DElementFloorObstacleLine::onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos) {
(void) userIdx;
(void) newPos;
emit v->onElementChange(this);
}

View File

@@ -4,9 +4,7 @@
#include "MV2DElement.h" #include "MV2DElement.h"
#include "HasMoveableNodes.h" #include "HasMoveableNodes.h"
#include "MapViewElementHelper.h"
#include <Indoor/floorplan/v2/Floorplan.h> #include <Indoor/floorplan/v2/Floorplan.h>
#include <stdio.h>
class MV2DElementFloorObstacleLine : public MV2DElement, public HasMoveableNodes { class MV2DElementFloorObstacleLine : public MV2DElement, public HasMoveableNodes {
@@ -17,90 +15,26 @@ private:
public: public:
/** ctor */ /** ctor */
MV2DElementFloorObstacleLine(Floorplan::FloorObstacleLine* fo) : fo(fo) {;} MV2DElementFloorObstacleLine(Floorplan::FloorObstacleLine* fo);
/** get the element's 3D bounding box */ /** get the element's 3D bounding box */
BBox2 getBoundingBox() const override { 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 */ /** get the element's minimal distance (nearest whatsoever) to the given point */
ClickDist getMinDistanceXY(const Point2 p) const override { ClickDist getMinDistanceXY(const Point2 p) const override;
return MapElementHelper::getLineDistanceXY(fo->from, fo->to, p);
}
/** repaint me */ /** repaint me */
void paint(Painter& p) override { void paint(Painter& p) override;
// selected endpoints? void onFocus() override;
if (hasFocus()) {
p.setPenBrush(Qt::NoPen, CFG::SEL_COLOR);
if (selectedUserIdx == 0) {p.drawCircle(fo->from);}
if (selectedUserIdx == 1) {p.drawCircle(fo->to);}
}
// convert wall's thickness from meter to pixels void onUnfocus() override;
const float thickness_px = p.s.ms(fo->thickness_m);
// remember the old pen virtual std::vector<MoveableNode> getMoveableNodes() const override;
QPen pen = p.getPen();
// see notes within MapElementHelper! void onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) override;
// lines only get thicker, but not longer!
p.setPenBrush(MapElementHelper::getPen(fo->material, fo->type, hasFocus(), thickness_px), Qt::NoBrush);
p.drawLine(fo->from, fo->to);
// reset the old pen void onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos);
p.setPen(pen);
// available endpoints
if (hasFocus()) {
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), thickness_px/2);
} else {
//p.setPenBrush(Qt::NoPen, Qt::black);
p.drawCircle_px(fo->from, 3);
p.drawCircle_px(fo->to, 3);
}
}
void onFocus() override {
;
}
void onUnfocus() override {
selectedUserIdx = -1; // clear selection
}
virtual std::vector<MoveableNode> getMoveableNodes() const override {
return {
MoveableNode(0, fo->from),
MoveableNode(1, fo->to)
};
}
void onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) override {
(void) v;
if (userIdx == 0) {fo->from.x = newPos.x; fo->from.y = newPos.y;}
if (userIdx == 1) {fo->to.x = newPos.x; fo->to.y = newPos.y;}
}
void onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos) {
(void) userIdx;
(void) newPos;
emit v->onElementChange(this);
}
}; };

View File

@@ -0,0 +1,134 @@
#include "MV2DElementFloorOutlinePolygon.h"
#include "MV2DElement.h"
#include "HasMoveableNodes.h"
#include "MapViewElementHelper.h"
#include <Indoor/floorplan/v2/Floorplan.h>
MV2DElementFloorOutlinePolygon::MV2DElementFloorOutlinePolygon(Floorplan::FloorOutlinePolygon& fo) : fo(fo) {
;
}
BBox2 MV2DElementFloorOutlinePolygon::getBoundingBox() const {
BBox2 bbox;
for (const Point2 p : fo.poly.points) { bbox.add(p); }
return bbox;
}
ClickDist MV2DElementFloorOutlinePolygon::getMinDistanceXY(const Point2 p) const {
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 ClickDist dst = MapElementHelper::getLineDistanceXY(p1, p2, p);
if (dst < min) {min = dst;}
}
return min * 1.1; // penalty.. outlines are everywhere.. reduce priority
}
void MV2DElementFloorOutlinePolygon::onFocus() {
}
void MV2DElementFloorOutlinePolygon::onUnfocus() {
selectedUserIdx = -1; // clear selection
}
void MV2DElementFloorOutlinePolygon::paint(Painter& p) {
QBrush brush;
QPen pen;
// fill-style (depends on the mode)
switch (fo.method) {
case Floorplan::OutlineMethod::ADD:
brush.setStyle(Qt::BrushStyle::SolidPattern);
brush.setColor( fo.outdoor ? QColor(0,255,0,32) : QColor(0,0,0,24) ); // outdoor = green
break;
case Floorplan::OutlineMethod::REMOVE:
brush.setStyle(Qt::BrushStyle::DiagCrossPattern);
brush.setColor(QColor(0,0,0));
break;
default:
// should not happen
brush.setStyle(Qt::BrushStyle::SolidPattern);
brush.setColor(QColor(255,0,0));
}
if (hasFocus()) {
brush.setStyle(Qt::BrushStyle::FDiagPattern);
}
// outline + filled area
pen.setColor(Qt::black);
pen.setWidth( hasFocus() ? 2 : 1 );
p.setPenBrush(pen, brush);
p.drawPolygon(fo.poly.points);
// DEPRECATED
// // selected endpoints?
// if (hasFocus() && selectedUserIdx != -1) {
// p.setPenBrush(Qt::NoPen, CFG::SEL_COLOR);
// p.drawCircle(fo.poly.points[selectedUserIdx]);
// }
// DEPRECATED
// // available endpoints
// if (hasFocus()) {
// p.setPenBrush(Qt::black, Qt::NoBrush);
// for (const Point2 pt : fo.poly.points) {
// p.drawCircle(pt);
// }
// }
}
std::vector<MoveableNode> MV2DElementFloorOutlinePolygon::getMoveableNodes() const {
std::vector<MoveableNode> nodes;
for (int i = 0; i < (int) fo.poly.points.size(); ++i) {
nodes.push_back(MoveableNode(i, fo.poly.points[i]));
}
return nodes;
}
void MV2DElementFloorOutlinePolygon::onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) {
(void) v;
fo.poly.points[userIdx].x = newPos.x;
fo.poly.points[userIdx].y = newPos.y;
}
void MV2DElementFloorOutlinePolygon::onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos) {
(void) userIdx;
(void) newPos;
emit v->onElementChange(this);
}
bool MV2DElementFloorOutlinePolygon::keyPressEvent(MapView2D* v, QKeyEvent *e) {
(void) v;
if (e->key() == Qt::Key_Delete) {
// delete the currently selected vertex?
if (selectedUserIdx != -1) {
fo.poly.points.erase(fo.poly.points.begin() + selectedUserIdx);
selectedUserIdx = -1;
return true;
}
} else if (e->key() == Qt::Key_Plus && selectedUserIdx != -1) {
int idx1 = selectedUserIdx;
int idx2 = (selectedUserIdx + 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);
selectedUserIdx = idxNew;
return true;
}
// not consumed
return false;
}

View File

@@ -3,7 +3,6 @@
#include "MV2DElement.h" #include "MV2DElement.h"
#include "HasMoveableNodes.h" #include "HasMoveableNodes.h"
#include "MapViewElementHelper.h"
#include <Indoor/floorplan/v2/Floorplan.h> #include <Indoor/floorplan/v2/Floorplan.h>
@@ -16,167 +15,29 @@ private:
public: public:
/** ctor */ /** ctor */
MV2DElementFloorOutlinePolygon(Floorplan::FloorOutlinePolygon& fo) : fo(fo) {;} MV2DElementFloorOutlinePolygon(Floorplan::FloorOutlinePolygon& fo);
/** get the element's 3D bounding box */ /** get the element's 3D bounding box */
BBox2 getBoundingBox() const override { 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 */ /** get the element's minimal distance (nearest whatsoever) to the given point */
ClickDist getMinDistanceXY(const Point2 p) const override { 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 ClickDist dst = MapElementHelper::getLineDistanceXY(p1, p2, p);
if (dst < min) {min = dst;}
}
return min * 1.1; // penalty.. outlines are everywhere.. reduce priority
}
virtual void onFocus() override { virtual void onFocus() override;
} virtual void onUnfocus() override;
virtual void onUnfocus() override { void paint(Painter& p) override;
selectedUserIdx = -1; // clear selection
}
void paint(Painter& p) override {
QBrush brush;
QPen pen;
// fill-style (depends on the mode)
switch (fo.method) {
case Floorplan::OutlineMethod::ADD:
brush.setStyle(Qt::BrushStyle::SolidPattern);
brush.setColor( fo.outdoor ? QColor(0,255,0,32) : QColor(0,0,0,24) ); // outdoor = green
break;
case Floorplan::OutlineMethod::REMOVE:
brush.setStyle(Qt::BrushStyle::DiagCrossPattern);
brush.setColor(QColor(0,0,0));
break;
default:
// should not happen
brush.setStyle(Qt::BrushStyle::SolidPattern);
brush.setColor(QColor(255,0,0));
}
if (hasFocus()) {
brush.setStyle(Qt::BrushStyle::FDiagPattern);
}
// outline + filled area
pen.setColor(Qt::black);
pen.setWidth( hasFocus() ? 2 : 1 );
p.setPenBrush(pen, brush);
p.drawPolygon(fo.poly.points);
// selected endpoints?
if (hasFocus() && selectedUserIdx != -1) {
p.setPenBrush(Qt::NoPen, CFG::SEL_COLOR);
p.drawCircle(fo.poly.points[selectedUserIdx]);
}
// available endpoints
if (hasFocus()) {
p.setPenBrush(Qt::black, Qt::NoBrush);
for (const Point2 pt : fo.poly.points) {
p.drawCircle(pt);
}
}
}
/** get a list of all nodes that are selectable / moveable */ /** get a list of all nodes that are selectable / moveable */
virtual std::vector<MoveableNode> getMoveableNodes() const override { virtual std::vector<MoveableNode> getMoveableNodes() const override;
std::vector<MoveableNode> nodes;
for (int i = 0; i < (int) fo.poly.points.size(); ++i) {
nodes.push_back(MoveableNode(i, fo.poly.points[i]));
}
return nodes;
}
/** the given node was moved */ /** the given node was moved */
void onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) override { void onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) override;
(void) v;
fo.poly.points[userIdx].x = newPos.x;
fo.poly.points[userIdx].y = newPos.y;
}
void onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos) override { void onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos) override;
(void) userIdx;
(void) newPos;
emit v->onElementChange(this);
}
// 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 = v->getScaler().snap(_p);
// 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 (selectedUserIdx != -1) {
fo.poly.points.erase(fo.poly.points.begin() + selectedUserIdx);
selectedUserIdx = -1;
return true;
}
} else if (e->key() == Qt::Key_Plus && selectedUserIdx != -1) {
int idx1 = selectedUserIdx;
int idx2 = (selectedUserIdx + 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);
selectedUserIdx = idxNew;
return true;
}
// not consumed
return false;
}
virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override;
}; };

View File

@@ -42,36 +42,29 @@ public:
return; return;
} }
static const QPixmap& pixmapUnfocused = UIHelper::getPixmapColored("gtp", CFG::UNFOCUS_COLOR, 16); static const QPixmap& pixmapUnfocused = UIHelper::getPixmapColored("gtp", CFG::UNFOCUS_COLOR, 16);
static const QPixmap& pixmapFocused = UIHelper::getPixmapColored("gtp", CFG::FOCUS_COLOR, 16); static const QPixmap& pixmapFocused = UIHelper::getPixmapColored("gtp", CFG::FOCUS_COLOR, 16);
static const QPixmap& pixmapSel = UIHelper::getPixmapColored("gtp", CFG::SEL_COLOR, 16); static const QPixmap& pixmapSel = UIHelper::getPixmapColored("gtp", CFG::SEL_COLOR, 16);
if (selectedUserIdx == 0) {
p.drawPixmap(gtp->pos.xy(), pixmapSel);
} else if (hasFocus()) {
p.drawPixmap(gtp->pos.xy(), pixmapFocused);
} else {
p.drawPixmap(gtp->pos.xy(), pixmapUnfocused);
}
if (selectedUserIdx == 0) { // label
// p.setPenBrush(Qt::black, CFG::SEL_COLOR); //p.setPenBrush(Qt::black, Qt::NoBrush);
// p.drawCircle(gtp->pos); //p.drawDot(gtp->pos.xy());
p.drawPixmap(gtp->pos.xy(), pixmapSel); if (p.getScaler().getScale() >= 12) {
} else if (hasFocus()) { p.setPenBrush(Qt::black, Qt::NoBrush);
// p.setPenBrush(Qt::black, Qt::NoBrush); const std::string str = std::to_string(gtp->id);
// p.drawCircle(gtp->pos); p.p->drawText(p.getScaler().xms(gtp->pos.x) + 10, p.getScaler().yms(gtp->pos.y) + 5, str.c_str());
p.drawPixmap(gtp->pos.xy(), pixmapFocused); }
} else {
// p.setPenBrush(Qt::gray, Qt::NoBrush);
// p.drawCircle(gtp->pos);
p.drawPixmap(gtp->pos.xy(), pixmapUnfocused);
}
// label
p.setPenBrush(Qt::black, Qt::NoBrush);
p.drawDot(gtp->pos.xy());
if (p.getScaler().getScale() >= 10) {
const std::string str = std::to_string(gtp->id);
p.p->drawText(p.getScaler().xms(gtp->pos.x) + 10, p.getScaler().yms(gtp->pos.y) + 5, str.c_str());
}
} }
virtual std::vector<MoveableNode> getMoveableNodes() const override { virtual std::vector<MoveableNode> getMoveableNodes() const override {
return { MoveableNode(0, gtp->pos.xy()) }; return { MoveableNode(0, gtp->pos.xy()) };
} }
@@ -87,30 +80,6 @@ public:
emit v->onElementChange(this); emit v->onElementChange(this);
} }
/** 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;
(void) p;
}
/** mouse released */
virtual void mouseReleased(MapView2D* v, const Point2 p) override {
(void) v;
(void) p;
}
virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override {
(void) v;
(void) e;
return false;
}
virtual void onFocus() override { virtual void onFocus() override {
; ;
} }

View File

@@ -62,9 +62,10 @@ public:
} }
// label // label
p.setPenBrush(Qt::black, Qt::NoBrush); //p.setPenBrush(Qt::black, Qt::NoBrush);
p.drawDot(poi->pos); //p.drawDot(poi->pos);
if (p.getScaler().getScale() >= 10) { if (p.getScaler().getScale() >= 12) {
p.setPenBrush(Qt::black, Qt::NoBrush);
const std::string str = poi->name; const std::string str = poi->name;
p.p->drawText(p.getScaler().xms(poi->pos.x) + 10, p.getScaler().yms(poi->pos.y) + 5, str.c_str()); p.p->drawText(p.getScaler().xms(poi->pos.x) + 10, p.getScaler().yms(poi->pos.y) + 5, str.c_str());
} }
@@ -87,35 +88,6 @@ public:
emit v->onElementChange(this); emit v->onElementChange(this);
} }
/** 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;
(void) p;
// if (sel) {
// const Point2 p = v->getScaler().snap(_p);
// poi->pos.x = p.x;
// poi->pos.y = p.y;
// }
}
/** mouse released */
virtual void mouseReleased(MapView2D* v, const Point2 p) override {
(void) v;
(void) p;
}
virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override {
(void) v;
(void) e;
return false;
}
virtual void onFocus() override { virtual void onFocus() override {
; ;
} }

View File

@@ -59,9 +59,10 @@ public:
} }
// label // label
p.setPenBrush(Qt::black, Qt::NoBrush); //p.setPenBrush(Qt::black, Qt::NoBrush);
//p.drawDot(ap->pos.xy()); //p.drawDot(ap->pos.xy());
if (p.getScaler().getScale() >= 10) { if (p.getScaler().getScale() >= 12) {
p.setPenBrush(Qt::black, Qt::NoBrush);
const std::string str = std::to_string(reg->posOnEarth.lat) + " " + std::to_string(reg->posOnEarth.lon); const std::string str = std::to_string(reg->posOnEarth.lat) + " " + std::to_string(reg->posOnEarth.lon);
p.p->drawText(p.getScaler().xms(reg->posOnMap_m.x) + 10, p.getScaler().yms(reg->posOnMap_m.y) + 5, str.c_str()); p.p->drawText(p.getScaler().xms(reg->posOnMap_m.x) + 10, p.getScaler().yms(reg->posOnMap_m.y) + 5, str.c_str());
} }
@@ -83,27 +84,6 @@ public:
emit v->onElementChange(this); emit v->onElementChange(this);
} }
virtual void mousePressed(MapView2D* v, const Point2 p) override {
(void) v;
(void) p;
}
virtual void mouseMove(MapView2D* v, const Point2 p) override {
(void) v;
(void) p;
}
virtual void mouseReleased(MapView2D* v, const Point2 p) override {
(void) v;
(void) p;
}
virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override {
(void) v;
(void) e;
return false;
}
virtual void onFocus() override { virtual void onFocus() override {
; ;
} }

View File

@@ -0,0 +1,251 @@
#include "MV2DElementStair.h"
#include "MV2DElement.h"
#include "HasMoveableNodes.h"
#include "MapViewElementHelper.h"
#include <Indoor/floorplan/v2/Floorplan.h>
/** is the given stair's end connected to ANY of the floorplan's floors? */
static inline bool stairEndConnected(const Floorplan::IndoorMap* map, const Floorplan::Floor* floor, const Floorplan::Stair* stair) {
const int stairEnd_cm = std::round( (floor->atHeight + stair->getParts().back().end.z) * 100 );
std::vector<int> floorsAtHeight_cm;
for (const Floorplan::Floor* f : map->floors) {
const int height_cm = std::round(f->atHeight*100);
floorsAtHeight_cm.push_back(height_cm);
}
const bool connected = std::find(floorsAtHeight_cm.begin(), floorsAtHeight_cm.end(), stairEnd_cm) != floorsAtHeight_cm.end();
return connected;
}
static inline float clamp01(const float val) {
if (val < 0) {return 0;}
if (val > 1) {return 1;}
return val;
}
MV2DElementStair::MV2DElementStair(Floorplan::IndoorMap* map, Floorplan::Floor* floor, Floorplan::Stair* stair)
: map(map), floor(floor), stair(stair) {
;
}
BBox2 MV2DElementStair::getBoundingBox() const {
BBox2 bbox;
if (dynamic_cast<Floorplan::StairFreeform*>(stair)) {
Floorplan::StairFreeform* stair = dynamic_cast<Floorplan::StairFreeform*>(this->stair);
for (const Floorplan::StairPart p : stair->parts) {
bbox.add(p.start.xy());
bbox.add(p.end.xy());
}
}
return bbox;
}
/** get the element's minimal distance (nearest whatsoever) to the given point */
ClickDist MV2DElementStair::getMinDistanceXY(const Point2 p) const {
auto comp = [p] (const Floorplan::StairPart& p1, const Floorplan::StairPart& p2) {
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;
};
auto parts = stair->getParts();
auto min = std::min_element(parts.begin(), parts.end(), comp);
return MapElementHelper::getLineDistanceXY(min->start.xy(), min->end.xy(), p);
}
int MV2DElementStair::getSelPart() const {return getSelectedNode() < 0 ? getSelectedNode() : getSelectedNode() / 2;}
int MV2DElementStair::getSelNode() const {return getSelectedNode() < 0 ? getSelectedNode() : getSelectedNode() % 2;}
void MV2DElementStair::paint(Painter& p) {
Floorplan::StairFreeform* stair = dynamic_cast<Floorplan::StairFreeform*>(this->stair);
// draw all parts of the stair (all polygons)
p.setPenBrush(Qt::black, Qt::NoBrush);
std::vector<Floorplan::StairPart> parts = stair->getParts();
std::vector<Floorplan::Quad3> quads = Floorplan::getQuads(parts, floor);
// skip drawing?
BBox2 bbox;
for (const Floorplan::Quad3& q : quads) {
bbox.add(q.p1.xy());
bbox.add(q.p2.xy());
bbox.add(q.p3.xy());
bbox.add(q.p4.xy());
}
if (!p.isVisible(bbox)) {
return;
}
for (int i = 0; i < (int) parts.size(); ++i) {
const Floorplan::StairPart& part = parts[i];
const Floorplan::Quad3& quad = quads[i];
// fill the polygon with a gradient corresponding with the stair's height relative to the floor's height
QLinearGradient gradient(p.s.xms(part.start.x), p.s.yms(part.start.y), p.s.xms(part.end.x), p.s.yms(part.end.y));
const float p1 = 0.1 + clamp01( part.start.z / floor->height) * 0.8;
const float p2 = 0.1 + clamp01( part.end.z / floor->height) * 0.8;
gradient.setColorAt(0, QColor(p1*128, p1*128, p1*255, 128));
gradient.setColorAt(1, QColor(p2*128, p2*128, p2*255, 128));
p.setBrush(gradient);
p.setPen(QColor(0,0,0,128));
// polygon-construction
//const Floorplan::Quad3 quad = part.getQuad(floor);
const std::vector<Point3> points = {quad.p1, quad.p2, quad.p3, quad.p4};
p.drawPolygon(points);
QPen pen;
pen.setWidth(5);
pen.setColor(QColor(255,0,0));
p.setPen(pen);
// LINT disconnected start
if (i == 0) {
if (quad.p1.z != floor->getStartingZ()) {
p.drawLine(quad.p1, quad.p2);
}
}
// LINT disconnected end
if (i == (int) parts.size() - 1) {
//if (quad.p3.z != floor->getEndingZ()) {
if (!stairEndConnected(map, floor, stair)) {
p.drawLine(quad.p3, quad.p4);
}
}
// LINT disconnected within
if (i > 0) {
if (quads[i-1].p4.z != quads[i-0].p1.z) {
p.drawLine(quad.p1, quad.p2);
}
}
}
if (hasFocus()) {
int cnt = 0;
std::vector<Floorplan::StairPart> parts = stair->getParts();
for (const Floorplan::StairPart& part : parts) {
//p.setPenBrush(Qt::black, (cnt == getSelPart() && getSelNode() == 0) ? CFG::SEL_COLOR : Qt::NoBrush); // part start
//p.drawCircle(part.start.xy()); // DEPRECATED
//p.setPenBrush(Qt::black, (cnt == getSelPart() && getSelNode() == 1) ? CFG::SEL_COLOR : Qt::NoBrush); // part end
//p.drawRect(part.end.xy()); // DEPRECATED
p.setPenBrush(Qt::blue, Qt::NoBrush);
Point2 ctr = (part.start+part.end).xy() / 2;
p.drawText(ctr, "p" + std::to_string(cnt+1)); // part name
++cnt;
}
for (int i = 0; i < (int)parts.size() - 1; ++i) {
const Point3 p1 = parts[i+0][1];
const Point3 p2 = parts[i+1][0];
p.drawLine(p1.xy(), p2.xy());
}
}
}
bool MV2DElementStair::keyPressEvent(MapView2D* v, QKeyEvent *e) {
(void) v;
(void) e;
Floorplan::StairFreeform* stair = dynamic_cast<Floorplan::StairFreeform*>(this->stair);
if (e->key() == Qt::Key_Delete) {
// delete the currently selected vertex?
if (getSelPart() != -1) {
// stair->nodes.erase(stair->nodes.begin() + selIdx);
// selIdx = -1;
// return true;
}
} else if (e->key() == Qt::Key_Plus && getSelPart() != -1) {
// int idx1 = selIdx;
// int idx2 = (selIdx + 1) % stair->nodes.size();
// int idxNew = idx2;
// Point3 pNew = (stair->nodes[idx1] + stair->nodes[idx2]) / 2.0f;
// stair->nodes.insert(stair->nodes.begin() + idxNew, pNew);
// selIdx = idxNew;
// return true;
const int idxNew = getSelPart() + 1;
const Point3 p0 = stair->parts[getSelPart()][1];
const Point3 p1 = p0 + Point3(1,1,0);
const Point3 p2 = p1 + Point3(2,2,0);
const float w = stair->parts[getSelPart()].width;
stair->parts.insert(stair->parts.begin() + idxNew, Floorplan::StairPart(p1, p2, w));
return true;
}
// not consumed
return false;
}
void MV2DElementStair::onFocus() {
// TODO?
}
void MV2DElementStair::onUnfocus() {
sel = false;
}
std::vector<MoveableNode> MV2DElementStair::getMoveableNodes() const {
std::vector<MoveableNode> nodes;
Floorplan::StairFreeform* stair = dynamic_cast<Floorplan::StairFreeform*>(this->stair);
// get a list of all moveable nodes (2 per stair-part)
int idx = 0;
for (size_t part = 0; part < stair->parts.size(); ++part) {
for (int node = 0; node < 2; ++node) {
MoveableNode mn(idx++, stair->parts[part][node].xy());
nodes.push_back(mn);
}
}
return nodes;
}
void MV2DElementStair::onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) {
(void) v;
// convert node-index back to stair-part and node-nr within stair-part
const int selPart = userIdx / 2;
const int selNode = userIdx % 2;
// move the node
Floorplan::StairFreeform* stair = dynamic_cast<Floorplan::StairFreeform*>(this->stair);
stair->parts[selPart][selNode].x = newPos.x;
stair->parts[selPart][selNode].y = newPos.y;
}
void MV2DElementStair::onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos) {
(void) userIdx;
(void) newPos;
emit v->onElementChange(this);
}
void MV2DElementStair::onNodeSelect(MapView2D* v, const int userIdx) {
HasMoveableNodes::onNodeSelect(v, userIdx);
emit v->onElementChange(this);
}

View File

@@ -4,21 +4,8 @@
#include "MV2DElement.h" #include "MV2DElement.h"
#include "HasMoveableNodes.h" #include "HasMoveableNodes.h"
#include "MapViewElementHelper.h"
#include <Indoor/floorplan/v2/Floorplan.h> #include <Indoor/floorplan/v2/Floorplan.h>
/** is the given stair's end connected to ANY of the floorplan's floors? */
static inline bool stairEndConnected(const Floorplan::IndoorMap* map, const Floorplan::Floor* floor, const Floorplan::Stair* stair) {
const int stairEnd_cm = std::round( (floor->atHeight + stair->getParts().back().end.z) * 100 );
std::vector<int> floorsAtHeight_cm;
for (const Floorplan::Floor* f : map->floors) {
const int height_cm = std::round(f->atHeight*100);
floorsAtHeight_cm.push_back(height_cm);
}
const bool connected = std::find(floorsAtHeight_cm.begin(), floorsAtHeight_cm.end(), stairEnd_cm) != floorsAtHeight_cm.end();
return connected;
}
class MV2DElementStair : public MV2DElement, public HasMoveableNodes { class MV2DElementStair : public MV2DElement, public HasMoveableNodes {
private: private:
@@ -27,296 +14,38 @@ private:
Floorplan::IndoorMap* map; Floorplan::IndoorMap* map;
Floorplan::Floor* floor; Floorplan::Floor* floor;
Floorplan::Stair* stair; Floorplan::Stair* stair;
//int selPart = -1;
//int selNode = -1;
public: public:
/** ctor with the stair to render/edit */ /** ctor with the stair to render/edit */
MV2DElementStair(Floorplan::IndoorMap* map, Floorplan::Floor* floor, Floorplan::Stair* stair) : map(map), floor(floor), stair(stair) {;} MV2DElementStair(Floorplan::IndoorMap* map, Floorplan::Floor* floor, Floorplan::Stair* stair);
/** get the element's 3D bounding box */ /** get the element's 3D bounding box */
BBox2 getBoundingBox() const override { BBox2 getBoundingBox() const override;
BBox2 bbox;
if (dynamic_cast<Floorplan::StairFreeform*>(stair)) {
Floorplan::StairFreeform* stair = dynamic_cast<Floorplan::StairFreeform*>(this->stair);
for (const Floorplan::StairPart p : stair->parts) {
bbox.add(p.start.xy());
bbox.add(p.end.xy());
}
}
return bbox;
}
/** get the element's minimal distance (nearest whatsoever) to the given point */ /** get the element's minimal distance (nearest whatsoever) to the given point */
ClickDist getMinDistanceXY(const Point2 p) const override { ClickDist getMinDistanceXY(const Point2 p) const override;
auto comp = [p] (const Floorplan::StairPart& p1, const Floorplan::StairPart& p2) { int getSelPart() const;
const ClickDist d1 = MapElementHelper::getLineDistanceXY(p1.start.xy(), p1.end.xy(), p); int getSelNode() const;
const ClickDist d2 = MapElementHelper::getLineDistanceXY(p2.start.xy(), p2.end.xy(), p);
return d1 < d2;
};
auto parts = stair->getParts();
auto min = std::min_element(parts.begin(), parts.end(), comp);
return MapElementHelper::getLineDistanceXY(min->start.xy(), min->end.xy(), p);
}
int getSelPart() const {return getSelectedNode() < 0 ? getSelectedNode() : getSelectedNode() / 2;}
int getSelNode() const {return getSelectedNode() < 0 ? getSelectedNode() : getSelectedNode() % 2;}
static inline float clamp01(const float val) {
if (val < 0) {return 0;}
if (val > 1) {return 1;}
return val;
}
/** repaint me */ /** repaint me */
void paint(Painter& p) override { void paint(Painter& p) override;
Floorplan::StairFreeform* stair = dynamic_cast<Floorplan::StairFreeform*>(this->stair); virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override;
// if (sel) { virtual void onFocus() override;
// p.setPenBrush(Qt::black, CFG::SEL_COLOR);
// p.drawCircle(stair->center);
// } else if (hasFocus()) {
// p.setPenBrush(Qt::black, Qt::NoBrush);
// p.drawCircle(stair->center);
// } else {
// p.setPenBrush(Qt::gray, Qt::NoBrush);
// p.drawCircle(stair->center);
// }
// draw all parts of the stair (all polygons) virtual void onUnfocus() override;
p.setPenBrush(Qt::black, Qt::NoBrush);
std::vector<Floorplan::StairPart> parts = stair->getParts(); virtual std::vector<MoveableNode> getMoveableNodes() const override;
std::vector<Floorplan::Quad3> quads = Floorplan::getQuads(parts, floor);
// skip drawing? void onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) override;
BBox2 bbox;
for (const Floorplan::Quad3& q : quads) {
bbox.add(q.p1.xy());
bbox.add(q.p2.xy());
bbox.add(q.p3.xy());
bbox.add(q.p4.xy());
}
if (!p.isVisible(bbox)) {
return;
}
for (int i = 0; i < (int) parts.size(); ++i) { void onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos) override;
const Floorplan::StairPart& part = parts[i]; void onNodeSelect(MapView2D* v, const int userIdx) override;
const Floorplan::Quad3& quad = quads[i];
// fill the polygon with a gradient corresponding with the stair's height relative to the floor's height
QLinearGradient gradient(p.s.xms(part.start.x), p.s.yms(part.start.y), p.s.xms(part.end.x), p.s.yms(part.end.y));
const float p1 = 0.1 + clamp01( part.start.z / floor->height) * 0.8;
const float p2 = 0.1 + clamp01( part.end.z / floor->height) * 0.8;
gradient.setColorAt(0, QColor(p1*128, p1*128, p1*255, 128));
gradient.setColorAt(1, QColor(p2*128, p2*128, p2*255, 128));
p.setBrush(gradient);
p.setPen(QColor(0,0,0,128));
// polygon-construction
//const Floorplan::Quad3 quad = part.getQuad(floor);
const std::vector<Point3> points = {quad.p1, quad.p2, quad.p3, quad.p4};
p.drawPolygon(points);
QPen pen;
pen.setWidth(5);
pen.setColor(QColor(255,0,0));
p.setPen(pen);
// LINT disconnected start
if (i == 0) {
if (quad.p1.z != floor->getStartingZ()) {
p.drawLine(quad.p1, quad.p2);
}
}
// LINT disconnected end
if (i == (int) parts.size() - 1) {
//if (quad.p3.z != floor->getEndingZ()) {
if (!stairEndConnected(map, floor, stair)) {
p.drawLine(quad.p3, quad.p4);
}
}
// LINT disconnected within
if (i > 0) {
if (quads[i-1].p4.z != quads[i-0].p1.z) {
p.drawLine(quad.p1, quad.p2);
}
}
}
if (hasFocus()) {
int cnt = 0;
std::vector<Floorplan::StairPart> parts = stair->getParts();
for (const Floorplan::StairPart& part : parts) {
p.setPenBrush(Qt::black, (cnt == getSelPart() && getSelNode() == 0) ? CFG::SEL_COLOR : Qt::NoBrush); // part start
p.drawCircle(part.start.xy());
p.setPenBrush(Qt::black, (cnt == getSelPart() && getSelNode() == 1) ? CFG::SEL_COLOR : Qt::NoBrush); // part end
p.drawRect(part.end.xy());
p.setPenBrush(Qt::blue, Qt::NoBrush);
Point2 ctr = (part.start+part.end).xy() / 2;
p.drawText(ctr, "p" + std::to_string(cnt+1)); // part name
++cnt;
}
for (int i = 0; i < (int)parts.size() - 1; ++i) {
const Point3 p1 = parts[i+0][1];
const Point3 p2 = parts[i+1][0];
p.drawLine(p1.xy(), p2.xy());
}
}
}
// /** 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 (selPart == -1) {return;}
// Floorplan::StairFreeform* stair = dynamic_cast<Floorplan::StairFreeform*>(this->stair);
// const Point2 p = v->getScaler().snap(_p);
// stair->parts[selPart][selNode].x = p.x;
// stair->parts[selPart][selNode].y = p.y;
// }
// /** mouse released */
// virtual void mouseReleased(MapView2D* v, const Point2 _p) override {
// (void) v;
// (void) _p;
// // select a new point on mouse-release (more robust than on mouse-press)
// Floorplan::StairFreeform* stair = dynamic_cast<Floorplan::StairFreeform*>(this->stair);
// const float t = v->getScaler().sm(CFG::SEL_THRESHOLD_SIZE_PX);
//// auto comp = [&] (const Point3 a, const Point3 b) {return a.xy().getDistance(_p) < b.xy().getDistance(_p);};
//// auto it = std::min_element(stair->nodes.begin(), stair->nodes.end(), comp);
//// if (it == stair->nodes.end()) {selIdx = -1;} // none found -> skip
//// else if ((*it).xy().getDistance(_p) > t) {selIdx = -1;} // nearest distance is above threshold -> skip
//// else {selIdx = it - stair->nodes.begin();}
// float best = 999999;
// int minPart; int minNode;
// for (int part = 0; part < (int) stair->parts.size(); ++part) {
// for (int node = 0; node < 2; ++node) {
// const float dist = stair->parts[part][node].xy().getDistance(_p);
// if (dist < best) {best = dist; minPart = part; minNode = node;}
// }
// }
// if (best <= t) {
// selPart = minPart; selNode = minNode;
// } else {
// selPart = -1; selNode = -1;
// }
// emit v->onElementChange(this);
// }
virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override {
(void) v;
(void) e;
Floorplan::StairFreeform* stair = dynamic_cast<Floorplan::StairFreeform*>(this->stair);
if (e->key() == Qt::Key_Delete) {
// delete the currently selected vertex?
if (getSelPart() != -1) {
// stair->nodes.erase(stair->nodes.begin() + selIdx);
// selIdx = -1;
// return true;
}
} else if (e->key() == Qt::Key_Plus && getSelPart() != -1) {
// int idx1 = selIdx;
// int idx2 = (selIdx + 1) % stair->nodes.size();
// int idxNew = idx2;
// Point3 pNew = (stair->nodes[idx1] + stair->nodes[idx2]) / 2.0f;
// stair->nodes.insert(stair->nodes.begin() + idxNew, pNew);
// selIdx = idxNew;
// return true;
const int idxNew = getSelPart() + 1;
const Point3 p0 = stair->parts[getSelPart()][1];
const Point3 p1 = p0 + Point3(1,1,0);
const Point3 p2 = p1 + Point3(2,2,0);
const float w = stair->parts[getSelPart()].width;
stair->parts.insert(stair->parts.begin() + idxNew, Floorplan::StairPart(p1, p2, w));
return true;
}
// not consumed
return false;
}
virtual void onFocus() override {
// TODO?
}
virtual void onUnfocus() override {
sel = false;
}
virtual std::vector<MoveableNode> getMoveableNodes() const override {
std::vector<MoveableNode> nodes;
Floorplan::StairFreeform* stair = dynamic_cast<Floorplan::StairFreeform*>(this->stair);
// get a list of all moveable nodes (2 per stair-part)
int idx = 0;
for (size_t part = 0; part < stair->parts.size(); ++part) {
for (int node = 0; node < 2; ++node) {
MoveableNode mn(idx++, stair->parts[part][node].xy());
nodes.push_back(mn);
}
}
return nodes;
}
void onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) override {
(void) v;
// convert node-index back to stair-part and node-nr within stair-part
const int selPart = userIdx / 2;
const int selNode = userIdx % 2;
// move the node
Floorplan::StairFreeform* stair = dynamic_cast<Floorplan::StairFreeform*>(this->stair);
stair->parts[selPart][selNode].x = newPos.x;
stair->parts[selPart][selNode].y = newPos.y;
}
void onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos) override {
(void) userIdx;
(void) newPos;
emit v->onElementChange(this);
}
void onNodeSelect(MapView2D* v, const int userIdx) override {
HasMoveableNodes::onNodeSelect(v, userIdx);
emit v->onElementChange(this);
}
}; };

View File

@@ -16,7 +16,7 @@ MapView2D::MapView2D(QWidget* parent) : QOpenGLWidget(parent) {
// openGL params // openGL params
QSurfaceFormat format; QSurfaceFormat format;
format.setDepthBufferSize(24); format.setDepthBufferSize(8); // 24
format.setStencilBufferSize(8); format.setStencilBufferSize(8);
format.setSamples(1); format.setSamples(1);
// format.setVersion(3, 2); // format.setVersion(3, 2);
@@ -49,11 +49,19 @@ void MapView2D::paintGL() {
// background tools // background tools
tools.paintBefore(this, p); tools.paintBefore(this, p);
// render all visible elements
qp.setRenderHint( QPainter::Antialiasing, true ); qp.setRenderHint( QPainter::Antialiasing, true );
// render all visible elements. 1st run
for (MapModelElement* el : getModel()->getVisibleElements()) { for (MapModelElement* el : getModel()->getVisibleElements()) {
if (el->getMV2D()) {el->getMV2D()->paint(p);} if (el->getMV2D()) {el->getMV2D()->paint(p);}
} }
// render all visible elements. 2nd run
for (MapModelElement* el : getModel()->getVisibleElements()) {
if (el->getMV2D()) {el->getMV2D()->paintAfter(p);}
}
qp.setRenderHint( QPainter::Antialiasing, false ); qp.setRenderHint( QPainter::Antialiasing, false );
// foreground tools // foreground tools
@@ -68,7 +76,9 @@ void MapView2D::initializeGL() {
} }
void MapView2D::resizeGL() { void MapView2D::resizeGL(int w, int h) {
(void) w;
(void) h;
// TODO ? // TODO ?
} }
@@ -110,10 +120,12 @@ bool MapView2D::event(QEvent* event) {
bool MapView2D::gestureEvent(QGestureEvent* event) { bool MapView2D::gestureEvent(QGestureEvent* event) {
if (QGesture *swipe = event->gesture(Qt::SwipeGesture)) { if (QGesture *swipe = event->gesture(Qt::SwipeGesture)) {
(void) swipe;
//swipeTriggered(static_cast<QSwipeGesture *>(swipe)); //swipeTriggered(static_cast<QSwipeGesture *>(swipe));
} else if (QGesture *pan = event->gesture(Qt::PanGesture)) } else if (QGesture *pan = event->gesture(Qt::PanGesture)) {
panTriggered(static_cast<QPanGesture *>(pan)); panTriggered(static_cast<QPanGesture *>(pan));
return true; return true;
}
if (QGesture *pinch = event->gesture(Qt::PinchGesture)) { if (QGesture *pinch = event->gesture(Qt::PinchGesture)) {
pinchTriggered(static_cast<QPinchGesture *>(pinch)); pinchTriggered(static_cast<QPinchGesture *>(pinch));
return true; return true;

View File

@@ -47,9 +47,9 @@ public:
public: public:
void paintGL(); virtual void paintGL() override;
void initializeGL(); virtual void initializeGL() override;
void resizeGL(); virtual void resizeGL(int w, int h) override;
Tools& getTools() {return tools;} Tools& getTools() {return tools;}

View File

@@ -0,0 +1,66 @@
#include "MapViewElementHelper.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>
ClickDist MapElementHelper::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);
ClickDist cutDist(99999999, ClickDistType::CUT);
if (line.getSegmentIntersection(perb, cut)) {
// distance between cut-point and mouse
cutDist.dst_px = cut.getDistance(dst);
}
// (direct) 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));
}
QPen MapElementHelper::getPen(Floorplan::Material mat, Floorplan::ObstacleType type, bool focus, float thickness_px) {
using namespace Floorplan;
QPen pen;
pen.setColor(Qt::darkGray); // default color
pen.setWidth(thickness_px); // element thickness
// this one is very important!
// as we change the line's width, the line also becomes longer
// but, we do not want this! -> FlatCap
pen.setCapStyle(Qt::FlatCap);
if (focus) {pen.setColor(QColor(64,64,200));}
else if (mat == Material::CONCRETE) {pen.setColor(QColor(32,32,32));}
else if (mat == Material::DRYWALL) {;}
else if (mat == Material::GLASS) {pen.setStyle(Qt::PenStyle::DotLine);}
else if (mat == Material::METALLIZED_GLAS) {pen.setStyle(Qt::PenStyle::DotLine);}
else if (mat == Material::METAL) {pen.setColor(QColor(64, 64, 64));}
else if (type == ObstacleType::HANDRAIL) {pen.setStyle(Qt::PenStyle::DashLine);}
else if (type == ObstacleType::UNKNOWN) {pen.setColor(Qt::red);}
else if (type == ObstacleType::PILLAR) {pen.setColor(Qt::red);}
return pen;
}

View File

@@ -5,9 +5,7 @@
#include <Indoor/geo/Point3.h> #include <Indoor/geo/Point3.h>
#include <Indoor/geo/Line2.h> #include <Indoor/geo/Line2.h>
#include <QColor>
#include <QPen> #include <QPen>
#include <QBrush>
#include <Indoor/floorplan/v2/Floorplan.h> #include <Indoor/floorplan/v2/Floorplan.h>
@@ -35,59 +33,9 @@ public:
* move l into dst * move l into dst
* and calculate the cut-point between l and (p1, p2) * and calculate the cut-point between l and (p1, p2)
*/ */
static ClickDist 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);
// 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);
ClickDist cutDist(99999999, ClickDistType::CUT);
if (line.getSegmentIntersection(perb, cut)) {
// distance between cut-point and mouse
cutDist.dst_px = cut.getDistance(dst);
}
// (direct) 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, float thickness_px) {
using namespace Floorplan;
QPen pen; pen.setColor(Qt::darkGray);
pen.setWidth(thickness_px);
// this one is very important!
// as we change the line's width, the line also becomes longer
// but, we do not want this! -> FlatCap
pen.setCapStyle(Qt::FlatCap);
if (focus) {pen.setColor(Qt::black);}
if (mat == Material::CONCRETE) {;}
if (mat == Material::GLASS) {pen.setStyle(Qt::PenStyle::DotLine);}
if (mat == Material::METALLIZED_GLAS) {pen.setStyle(Qt::PenStyle::DotLine);}
if (mat == Material::METAL) {pen.setColor(QColor(50, 50, 50));}
if (type == ObstacleType::HANDRAIL) {pen.setStyle(Qt::PenStyle::DashLine);}
if (type == ObstacleType::UNKNOWN) {pen.setColor(Qt::red);}
if (type == ObstacleType::PILLAR) {pen.setColor(Qt::red);}
return pen;
}
static QPen getPen(Floorplan::Material mat, Floorplan::ObstacleType type, bool focus, float thickness_px);
}; };

158
mapview/2D/Painter.cpp Normal file
View File

@@ -0,0 +1,158 @@
#include "Painter.h"
#include <QPainter>
#include <QBitmap>
#include <Indoor/geo/Point2.h>
#include <Indoor/geo/Point3.h>
#include <Indoor/geo/BBox2.h>
#include "Scaler.h"
Painter::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 Painter::width() {return w;}
int Painter::height() {return h;}
bool Painter::isVisible(const Point2 p) {
const float x = s.xms(p.x);
const float y = s.yms(p.y);
return (x >= 0 && y >= 0 && x < w && y < h);
}
bool Painter::isVisible(const BBox2 bb) {
const BBox2 bbt(0,0,w,h);
BBox2 bbs;
bbs.add(s.xms(bb.getMin().x), s.yms(bb.getMin().y)); // y might be inverted! -> use the add() method to address this
bbs.add(s.xms(bb.getMax().x), s.yms(bb.getMax().y)); // y might be inverted! -> use the add() method to address this
return bbt.intersects(bbs);
}
void Painter::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));
p->drawLine(QPointF(s.xms(p1.x), s.yms(p1.y)), QPointF(s.xms(p2.x), s.yms(p2.y)));
}
void Painter::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));
p->drawLine(QPointF(s.xms(p1.x), s.yms(p1.y)), QPointF(s.xms(p2.x), s.yms(p2.y)));
}
float Painter::radToDeg(const float rad) const {
return rad * 180 / M_PI;
}
void Painter::drawArc(const Point2 center, const float radius, const float startAngleRad, const float spanAngleRad) {
const float wh = s.ms(radius) * 2;
const float x1 = s.xms(center.x) - wh/2;
const float y1 = s.yms(center.y) - wh/2;
p->drawArc(x1, y1, wh, wh, radToDeg(startAngleRad)*16, radToDeg(spanAngleRad)*16);
}
void Painter::drawCircle(const Point3 center) {
int r = 5;
p->drawEllipse(s.xms(center.x)-r, s.yms(center.y)-r, 2*r, 2*r);
}
void Painter::drawCircle(const Point2 center) {
int r = 5;
p->drawEllipse(s.xms(center.x)-r, s.yms(center.y)-r, 2*r, 2*r);
}
/** draw a dot at the given map coordinates */
void Painter::drawDot(const Point2 center) {
int r = 1;
p->drawEllipse(s.xms(center.x)-r, s.yms(center.y)-r, 2*r, 2*r);
}
void Painter::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 Painter::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 Painter::drawNode(Point2 pt, bool focused, bool selected) {
float rs = 0.05;
if (selected) {setPenBrush(Qt::black, Qt::gray); rs = 0.08;}
else if (focused) {setPenBrush(Qt::black, Qt::white); rs = 0.08;}
else {setPenBrush(Qt::black, Qt::NoBrush); rs = 0.04;}
const float s = this->s.getScale();
if (s > 10) {drawCircle(pt, rs);} // only at a certain zoom level
}
void Painter::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 Painter::drawRect(const Point2 p1, const Point2 p2) {
drawRect(p1.x, p1.y, p2.x, p2.y);
}
void Painter::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 Painter::drawRect(const Point2 center) {
float r = s.sm(5); // 5 pixel
drawRect(center-Point2(r,r), center+Point2(r,r));
}
void Painter::drawText(const Point2 pos, const std::string& text) {
p->drawText(s.xms(pos.x), s.yms(pos.y), text.c_str());
}
void Painter::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 Painter::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 Painter::drawPixmap(const Point2 pt, const QPixmap& img) {
p->drawPixmap(s.xms(pt.x)-img.width()/2, s.yms(pt.y)-img.height()/2, img);
}
void Painter::drawImage(const Point2 pt, const QImage& img) {
p->drawImage(s.xms(pt.x)-img.width()/2, s.yms(pt.y)-img.height()/2, img);
}
void Painter::drawLength(Point2 p1, Point2 p2, const float len, const float offset) {
if (p1.x < p2.x) {swap(p1, p2);}
const Point2 center_m = (p1 + p2) / 2;
Point2 dir_px = (p2 - p1).perpendicular().normalized() * (5+offset);
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 Painter::setBrush(const QBrush& brush) { p->setBrush(brush); }
void Painter::setBrush(const Qt::BrushStyle& brush) { p->setBrush(brush); }
void Painter::setPen(const QPen& pen) {p->setPen(pen); }
void Painter::setPen(const QColor& pen) {p->setPen(pen); }
void Painter::setPen(const Qt::PenStyle& pen) {p->setPen(pen); }
const QPen& Painter::getPen() {return p->pen();}
const Scaler& Painter::getScaler() {return s;}

View File

@@ -1,14 +1,21 @@
#ifndef PAINTER_H #ifndef PAINTER_H
#define PAINTER_H #define PAINTER_H
#include <QPainter>
#include <QBitmap>
#include <Indoor/geo/Point2.h> #include <Indoor/geo/Point2.h>
#include <Indoor/geo/Point3.h> #include <Indoor/geo/Point3.h>
#include <Indoor/geo/BBox2.h> #include <Indoor/geo/BBox2.h>
#include "Scaler.h" //#include "Scaler.h"
class Scaler;
class QPainter;
class QPixmap;
class QImage;
class QPen;
class QColor;
class QBrush;
#include <qnamespace.h>
class Painter { class Painter {
@@ -22,145 +29,66 @@ public:
public: public:
/** ctor */ /** ctor */
Painter(Scaler& s, QPainter* p, int w, int h) : s(s), p(p), w(w), h(h) { Painter(Scaler& s, QPainter* p, int w, int h);
p->setPen(Qt::black);
p->setBrush(Qt::NoBrush);
}
int width() {return w;} int width();
int height() {return h;} int height();
/** is the given point visible on screen? */ /** is the given point visible on screen? */
bool isVisible(const Point2 p) { bool isVisible(const Point2 p);
const float x = s.xms(p.x);
const float y = s.yms(p.y);
return (x >= 0 && y >= 0 && x < w && y < h);
}
/** is the given volume visible on screen? */ /** is the given volume visible on screen? */
bool isVisible(const BBox2 bb) { bool isVisible(const BBox2 bb);
const BBox2 bbt(0,0,w,h);
BBox2 bbs;
bbs.add(s.xms(bb.getMin().x), s.yms(bb.getMin().y)); // y might be inverted! -> use the add() method to address this
bbs.add(s.xms(bb.getMax().x), s.yms(bb.getMax().y)); // y might be inverted! -> use the add() method to address this
return bbt.intersects(bbs);
}
void drawLine(const Point2 p1, const Point2 p2) { 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);
} void drawLine(const float x1, const float y1, const float x2, const float y2);
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));
}
float radToDeg(const float rad) const { float radToDeg(const float rad) const;
return rad * 180 / M_PI;
}
void drawArc(const Point2 center, const float radius, const float startAngleRad, const float spanAngleRad) { void drawArc(const Point2 center, const float radius, const float startAngleRad, const float spanAngleRad);
const float wh = s.ms(radius) * 2;
const float x1 = s.xms(center.x) - wh/2;
const float y1 = s.yms(center.y) - wh/2;
p->drawArc(x1, y1, wh, wh, radToDeg(startAngleRad)*16, radToDeg(spanAngleRad)*16);
}
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);
}
/** draw a dot at the given map coordinates */ /** draw a dot at the given map coordinates */
void drawDot(const Point2 center) { void drawDot(const Point2 center);
int r = 1;
p->drawEllipse(s.xms(center.x)-r, s.yms(center.y)-r, 2*r, 2*r); void drawCircle(const Point3 center);
void drawCircle(const Point2 center);
void drawCircle(const Point2 center, const float size_m);
void drawCircle_px(const Point2 center, const float size_px);
void drawRect(const Point2 p1, const Point2 p2);
void drawRect(const float x1, const float y1, const float x2, const float y2);
void drawRect(const Point2 center);
void drawNode(Point2 pt, bool focused, bool selected);
void drawText(const Point2 pos, const std::string& text);
void drawPolygon(const std::vector<Point2>& points);
void drawPolygon(const std::vector<Point3>& points);
void drawPixmap(const Point2 pt, const QPixmap& img);
void drawImage(const Point2 pt, const QImage& img);
void drawLength(Point2 p1, Point2 p2, const float len, const float offset = 0);
void setBrush(const QBrush& brush);
void setBrush(const Qt::BrushStyle& brush);
void setPen(const QPen& pen);
void setPen(const QColor& pen);
void setPen(const Qt::PenStyle& pen);
const QPen& getPen();
template <typename Pen, typename Brush> void setPenBrush(const Pen& pen, const Brush& brush) {
setPen(pen);
setBrush(brush);
} }
void drawCircle(const Point2 center, const float size_m) { const Scaler& getScaler();
int r = s.ms(size_m);
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));
}
void drawRect(const Point2 p1, const Point2 p2) {
drawRect(p1.x, p1.y, p2.x, p2.y);
}
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 drawRect(const Point2 center) {
float r = s.sm(5); // 5 pixel
drawRect(center-Point2(r,r), center+Point2(r,r));
}
void drawText(const Point2 pos, const std::string& text) {
p->drawText(s.xms(pos.x), s.yms(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 drawPixmap(const Point2 pt, const QPixmap& img) {
p->drawPixmap(s.xms(pt.x)-img.width()/2, s.yms(pt.y)-img.height()/2, img);
}
void drawImage(const Point2 pt, const QImage& img) {
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, const float offset = 0) {
if (p1.x < p2.x) {swap(p1, p2);}
const Point2 center_m = (p1 + p2) / 2;
Point2 dir_px = (p2 - p1).perpendicular().normalized() * (5+offset);
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); }
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); }
const QPen& getPen() {return p->pen();}
template <typename Pen, typename Brush> void setPenBrush(const Pen& pen, const Brush& brush) {setPen(pen); setBrush(brush);}
const Scaler& getScaler() {return s;}
private: private:

View File

@@ -236,10 +236,12 @@ bool MapView3D::event(QEvent* event) {
bool MapView3D::gestureEvent(QGestureEvent* event) { bool MapView3D::gestureEvent(QGestureEvent* event) {
if (QGesture *swipe = event->gesture(Qt::SwipeGesture)) { if (QGesture *swipe = event->gesture(Qt::SwipeGesture)) {
(void) swipe;
//swipeTriggered(static_cast<QSwipeGesture *>(swipe)); //swipeTriggered(static_cast<QSwipeGesture *>(swipe));
} else if (QGesture *pan = event->gesture(Qt::PanGesture)) } else if (QGesture *pan = event->gesture(Qt::PanGesture)) {
panTriggered(static_cast<QPanGesture *>(pan)); panTriggered(static_cast<QPanGesture *>(pan));
return true; return true;
}
if (QGesture *pinch = event->gesture(Qt::PinchGesture)) { if (QGesture *pinch = event->gesture(Qt::PinchGesture)) {
pinchTriggered(static_cast<QPinchGesture *>(pinch)); pinchTriggered(static_cast<QPinchGesture *>(pinch));
return true; return true;
@@ -248,6 +250,7 @@ bool MapView3D::gestureEvent(QGestureEvent* event) {
} }
void MapView3D::pinchTriggered(QPinchGesture* gesture) { void MapView3D::pinchTriggered(QPinchGesture* gesture) {
(void) gesture;
update(); update();
} }

View File

@@ -0,0 +1,82 @@
#include "FloorplanRenderer.h"
#include <unordered_set>
#include <Indoor/navMesh/NavMesh.h>
#include <Indoor/navMesh/NavMeshTriangle.h>
#include <Indoor/navMesh/NavMeshType.h>
#include <QPainter>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include "../misc/Renderable3D.h"
#include "../misc/Shader.h"
#include "../misc/TriangleData.h"
#include <Indoor/wifi/estimate/ray3/ModelFactory.h>
#include "RenderTriangle.h"
/** ctor */
FloorplanRenderer::FloorplanRenderer() {
;
}
void FloorplanRenderer::renderSolid(const RenderSettings& rs, const RenderTriangle& rt, bool wireframe) {
rs.shader->bind();
rs.shader->setModelMatrix(QMatrix4x4());
rs.shader->setVertices(rt.getVertices());
rs.shader->setNormals(rt.getNormals());
rs.shader->setVertexColor(rt.getRGBA());
rs.funcs->glDrawArrays(GL_TRIANGLES, 0, rt.count());
rs.shader->unsetVertices();
rs.shader->unsetNormals();
rs.shader->unsetVertexColor();
if (wireframe) {
RenderTriangle rt2 = rt.toWireframe(false);
rs.shader->setColor(0,0,0,128);
rs.shader->setVertices(rt2.getVertices());
//rs.shader->setVertexColor(rt2.getRGBA());
rs.funcs->glDrawArrays(GL_LINES, 0, rt2.count());
rs.shader->unsetVertices();
//rs.shader->unsetVertexColor();
}
rs.shader->release();
}
void FloorplanRenderer::renderTransp(const RenderSettings& rs, const RenderTriangle& rt, bool wireframe) {
rs.funcs->glEnable(GL_BLEND);
rs.funcs->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
rs.shader->bind();
rs.shader->setModelMatrix(QMatrix4x4());
rs.shader->setVertices(rt.getVertices());
rs.shader->setNormals(rt.getNormals());
rs.shader->setVertexColor(rt.getRGBA());
rs.funcs->glDrawArrays(GL_TRIANGLES, 0, rt.count());
rs.shader->unsetVertices();
rs.shader->unsetNormals();
rs.shader->unsetVertexColor();
if (wireframe) {
RenderTriangle rt2 = rt.toWireframe(false);
rs.shader->setColor(0,0,0,128);
rs.shader->setVertices(rt2.getVertices());
//rs.shader->setVertexColor(rt2.getRGBA());
rs.funcs->glDrawArrays(GL_LINES, 0, rt2.count());
rs.shader->unsetVertices();
//rs.shader->unsetVertexColor();
}
rs.shader->release();
rs.funcs->glDisable(GL_BLEND);
}

View File

@@ -1,91 +1,22 @@
#ifndef FLOORPLANRENDERER_H #ifndef FLOORPLANRENDERER_H
#define FLOORPLANRENDERER_H #define FLOORPLANRENDERER_H
#include <unordered_set>
#include <Indoor/navMesh/NavMesh.h>
#include <Indoor/navMesh/NavMeshTriangle.h>
#include <Indoor/navMesh/NavMeshType.h>
#include <QPainter>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include "../misc/Renderable3D.h" #include "../misc/Renderable3D.h"
#include "../misc/Shader.h"
#include "../misc/TriangleData.h"
#include <Indoor/wifi/estimate/ray3/ModelFactory.h> class RenderTriangle;
#include "RenderTriangle.h"
class FloorplanRenderer { class FloorplanRenderer {
public: public:
/** ctor */ /** ctor */
FloorplanRenderer() { FloorplanRenderer();
;
}
/** render the given grid using GL commands */ /** render the given grid using GL commands */
void renderSolid(const RenderSettings& rs, const RenderTriangle& rt, bool wireframe) { void renderSolid(const RenderSettings& rs, const RenderTriangle& rt, bool wireframe);
rs.shader->bind();
rs.shader->setModelMatrix(QMatrix4x4());
rs.shader->setVertices(rt.getVertices());
rs.shader->setNormals(rt.getNormals());
rs.shader->setVertexColor(rt.getRGBA());
rs.funcs->glDrawArrays(GL_TRIANGLES, 0, rt.count());
rs.shader->unsetVertices();
rs.shader->unsetNormals();
rs.shader->unsetVertexColor();
if (wireframe) {
RenderTriangle rt2 = rt.toWireframe(false);
rs.shader->setColor(0,0,0,128);
rs.shader->setVertices(rt2.getVertices());
//rs.shader->setVertexColor(rt2.getRGBA());
rs.funcs->glDrawArrays(GL_LINES, 0, rt2.count());
rs.shader->unsetVertices();
//rs.shader->unsetVertexColor();
}
rs.shader->release();
}
/** render the given grid using GL commands */ /** render the given grid using GL commands */
void renderTransp(const RenderSettings& rs, const RenderTriangle& rt, bool wireframe) { void renderTransp(const RenderSettings& rs, const RenderTriangle& rt, bool wireframe);
rs.funcs->glEnable(GL_BLEND);
rs.funcs->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
rs.shader->bind();
rs.shader->setModelMatrix(QMatrix4x4());
rs.shader->setVertices(rt.getVertices());
rs.shader->setNormals(rt.getNormals());
rs.shader->setVertexColor(rt.getRGBA());
rs.funcs->glDrawArrays(GL_TRIANGLES, 0, rt.count());
rs.shader->unsetVertices();
rs.shader->unsetNormals();
rs.shader->unsetVertexColor();
if (wireframe) {
RenderTriangle rt2 = rt.toWireframe(false);
rs.shader->setColor(0,0,0,128);
rs.shader->setVertices(rt2.getVertices());
//rs.shader->setVertexColor(rt2.getRGBA());
rs.funcs->glDrawArrays(GL_LINES, 0, rt2.count());
rs.shader->unsetVertices();
//rs.shader->unsetVertexColor();
}
rs.shader->release();
rs.funcs->glDisable(GL_BLEND);
}
}; };

View File

@@ -56,7 +56,7 @@ void NavMeshRenderer::rebuildIfNeeded(NavMeshModel* model) {
case (int) NM::NavMeshType::STAIR_SKEWED: color = Point3(0.4, 0.4, 0.4); break; case (int) NM::NavMeshType::STAIR_SKEWED: color = Point3(0.4, 0.4, 0.4); break;
} }
const float o = 0.001f; //const float o = 0.001f;
outlines.addLine(tria->getP1(), tria->getP2(), color.x, color.y, color.z, 1); outlines.addLine(tria->getP1(), tria->getP2(), color.x, color.y, color.z, 1);
outlines.addLine(tria->getP2(), tria->getP3(), color.x, color.y, color.z, 1); outlines.addLine(tria->getP2(), tria->getP3(), color.x, color.y, color.z, 1);
outlines.addLine(tria->getP3(), tria->getP1(), color.x, color.y, color.z, 1); outlines.addLine(tria->getP3(), tria->getP1(), color.x, color.y, color.z, 1);

View File

@@ -9,7 +9,7 @@
#include "IHasParams.h" #include "IHasParams.h"
#include "../2D/MV2DElementFloorObstacleDoor.h" #include "../2D/MV2DElementFloorObstacleDoor.h"
#include "../3D/MV3DElementFloorObstacleDoor.h" //#include "../3D/MV3DElementFloorObstacleDoor.h"
#include <Indoor/floorplan/v2/Floorplan.h> #include <Indoor/floorplan/v2/Floorplan.h>
@@ -21,12 +21,12 @@ public:
Floorplan::Floor* mf; Floorplan::Floor* mf;
Floorplan::FloorObstacleDoor* fo; Floorplan::FloorObstacleDoor* fo;
MV2DElementFloorObstacleDoor mv2d; MV2DElementFloorObstacleDoor mv2d;
MV3DElementFloorObstacleDoor mv3d; //MV3DElementFloorObstacleDoor mv3d;
public: public:
MMFloorObstacleDoor(MapLayer* parent, Floorplan::Floor* mf, Floorplan::FloorObstacleDoor* fo) : MMFloorObstacleDoor(MapLayer* parent, Floorplan::Floor* mf, Floorplan::FloorObstacleDoor* fo) :
MapModelElement(parent), mf(mf), fo(fo), mv2d(fo), mv3d(mf,fo) { MapModelElement(parent), mf(mf), fo(fo), mv2d(fo) {//, mv3d(mf,fo) {
} }
@@ -37,7 +37,7 @@ public:
Floorplan::DoorType getDoorType() const override {return fo->type;} Floorplan::DoorType getDoorType() const override {return fo->type;}
MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;} MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;}
MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;} //MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;}
void deleteMe() const override { void deleteMe() const override {
parent->removeElement(this); parent->removeElement(this);

View File

@@ -9,7 +9,7 @@
#include "IHasParams.h" #include "IHasParams.h"
#include "../2D/MV2DElementFloorObstacleLine.h" #include "../2D/MV2DElementFloorObstacleLine.h"
#include "../3D/MV3DElementFloorObstacleWall.h" //#include "../3D/MV3DElementFloorObstacleWall.h"
#include <Indoor/floorplan/v2/Floorplan.h> #include <Indoor/floorplan/v2/Floorplan.h>
@@ -21,12 +21,12 @@ public:
Floorplan::Floor* mf; Floorplan::Floor* mf;
Floorplan::FloorObstacleLine* fo; Floorplan::FloorObstacleLine* fo;
MV2DElementFloorObstacleLine mv2d; MV2DElementFloorObstacleLine mv2d;
MV3DElementFloorObstacleWall mv3d; //MV3DElementFloorObstacleWall mv3d;
public: public:
MMFloorObstacleLine(MapLayer* parent, Floorplan::Floor* mf, Floorplan::FloorObstacleLine* fo) : MMFloorObstacleLine(MapLayer* parent, Floorplan::Floor* mf, Floorplan::FloorObstacleLine* fo) :
MapModelElement(parent), mf(mf), fo(fo), mv2d(fo), mv3d(mf,fo) { MapModelElement(parent), mf(mf), fo(fo), mv2d(fo) {//, mv3d(mf,fo) {
} }
@@ -37,7 +37,7 @@ public:
Floorplan::ObstacleType getObatcleType() const override {return fo->type;} Floorplan::ObstacleType getObatcleType() const override {return fo->type;}
MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;} MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;}
MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;} //MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;}
void deleteMe() const override { void deleteMe() const override {
parent->removeElement(this); parent->removeElement(this);

View File

@@ -10,7 +10,7 @@
#include "IHasParams.h" #include "IHasParams.h"
#include "../2D/MV2DElementFloorObstacleObject.h" #include "../2D/MV2DElementFloorObstacleObject.h"
#include "../3D/MV3DElementFloorObstacleObject.h" //#include "../3D/MV3DElementFloorObstacleObject.h"
#include <Indoor/floorplan/v2/Floorplan.h> #include <Indoor/floorplan/v2/Floorplan.h>
@@ -22,17 +22,17 @@ public:
Floorplan::Floor* mf; Floorplan::Floor* mf;
Floorplan::FloorObstacleObject* fo; Floorplan::FloorObstacleObject* fo;
MV2DElementFloorObstacleObject mv2d; MV2DElementFloorObstacleObject mv2d;
MV3DElementFloorObstacleObject mv3d; //MV3DElementFloorObstacleObject mv3d;
public: public:
MMFloorObstacleObject(MapLayer* parent, Floorplan::Floor* mf, Floorplan::FloorObstacleObject* fo) : MMFloorObstacleObject(MapLayer* parent, Floorplan::Floor* mf, Floorplan::FloorObstacleObject* fo) :
MapModelElement(parent), mf(mf), fo(fo), mv2d(fo), mv3d(mf,fo) { MapModelElement(parent), mf(mf), fo(fo), mv2d(fo) {//, mv3d(mf,fo) {
} }
MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;} MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;}
MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;} //MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;}
void deleteMe() const override { void deleteMe() const override {
parent->removeElement(this); parent->removeElement(this);

View File

@@ -5,7 +5,7 @@
#include "MMFloorOutlinePolygon.h" #include "MMFloorOutlinePolygon.h"
#include "MMFloorOutlinePolygonCombined.h" #include "MMFloorOutlinePolygonCombined.h"
#include "../3D/MV3DElementFloorOutline.h" //#include "../3D/MV3DElementFloorOutline.h"
#include <Indoor/floorplan/v2/Floorplan.h> #include <Indoor/floorplan/v2/Floorplan.h>

View File

@@ -3,7 +3,7 @@
#include "MapLayer.h" #include "MapLayer.h"
#include "MMFloorOutlinePolygon.h" #include "MMFloorOutlinePolygon.h"
#include "../3D/MV3DElementFloorOutline.h" //#include "../3D/MV3DElementFloorOutline.h"
#include <Indoor/floorplan/v2/Floorplan.h> #include <Indoor/floorplan/v2/Floorplan.h>
@@ -19,19 +19,19 @@ private:
/** the underlying model */ /** the underlying model */
Floorplan::Floor* floor; Floorplan::Floor* floor;
MV3DElementFloorOutline mv3d; //MV3DElementFloorOutline mv3d;
public: public:
/** ctor with the underlying model */ /** ctor with the underlying model */
MMFloorOutlinePolygonCombined(MapLayer* parent, Floorplan::Floor* floor) : MMFloorOutlinePolygonCombined(MapLayer* parent, Floorplan::Floor* floor) :
MapModelElement(parent), floor(floor), mv3d(floor, &floor->outline) { MapModelElement(parent), floor(floor) {//, mv3d(floor, &floor->outline) {
; ;
} }
MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;} //MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;}
/** get the corresponding floor from the underlying model */ /** get the corresponding floor from the underlying model */
Floorplan::Floor* getFloor() {return floor;} Floorplan::Floor* getFloor() {return floor;}

View File

@@ -6,7 +6,7 @@
#include "MMFloorOutlinePolygon.h" #include "MMFloorOutlinePolygon.h"
#include "../2D/MV2DElementStair.h" #include "../2D/MV2DElementStair.h"
#include "../3D/MV3DElementStair.h" //#include "../3D/MV3DElementStair.h"
#include <Indoor/floorplan/v2/Floorplan.h> #include <Indoor/floorplan/v2/Floorplan.h>
@@ -23,20 +23,20 @@ private:
Floorplan::StairFreeform* stair; Floorplan::StairFreeform* stair;
MV2DElementStair mv2d; MV2DElementStair mv2d;
MV3DElementStair mv3d; //MV3DElementStair mv3d;
public: public:
/** ctor with the underlying model */ /** ctor with the underlying model */
MMFloorStair(MapLayer* parent, Floorplan::IndoorMap* map, Floorplan::Floor* floor, Floorplan::StairFreeform* stair) : MMFloorStair(MapLayer* parent, Floorplan::IndoorMap* map, Floorplan::Floor* floor, Floorplan::StairFreeform* stair) :
MapModelElement(parent), floor(floor), stair(stair), mv2d(map, floor, stair), mv3d(floor, stair) { MapModelElement(parent), floor(floor), stair(stair), mv2d(map, floor, stair) {//, mv3d(floor, stair) {
; ;
} }
MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;} MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;}
MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;} //MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;}
virtual int getNumParams() const override { virtual int getNumParams() const override {

View File

@@ -188,6 +188,7 @@ public:
} }
void setVisible(const bool visible) override { void setVisible(const bool visible) override {
(void) visible;
throw "error"; throw "error";
} }

View File

@@ -7,15 +7,17 @@
#include <QLabel> #include <QLabel>
#include <QPushButton> #include <QPushButton>
#include <QLineEdit> #include <QLineEdit>
#include <QComboBox>
#include <QCheckBox>
#include <QFileDialog>
#include "../mapview/model/IHasParams.h" #include "../mapview/model/IHasParams.h"
class EditFields { class EditFields {
public: public:
static void get(QGridLayout* lay, IHasParams* elem) { static void get(QWidget* parent, int& r, QGridLayout* lay, IHasParams* elem) {
int r = 0;
for(int i = 0; i < elem->getNumParams(); ++i) { for(int i = 0; i < elem->getNumParams(); ++i) {
@@ -29,8 +31,24 @@ public:
switch(param.type) { switch(param.type) {
case ParamType::NOT_AVAILABLE:
break;
case ParamType::ENUM: {
QComboBox* cmb = new QComboBox(parent);
int idx = 0;
for (const std::string& str : param.getEnumValues()) {cmb->addItem(str.c_str(), idx++);}
cmb->setCurrentIndex(value.toInt());
cmb->connect(cmb, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [i, elem, cmb] (int idx) {
(void) idx;
elem->setParamValue(i, cmb->currentData().toInt() );
});
lay->addWidget(cmb,r,1);
break;
}
case ParamType::BOOL: { case ParamType::BOOL: {
QCheckBox* chk = new QCheckBox( ); QCheckBox* chk = new QCheckBox(parent);
chk->setChecked(value.toBool()); chk->setChecked(value.toBool());
if (param.readOnly) { if (param.readOnly) {
chk->setEnabled(false); chk->setEnabled(false);
@@ -46,9 +64,9 @@ public:
case ParamType::FLOAT: { case ParamType::FLOAT: {
const std::string str = std::to_string(value.toFloat()); const std::string str = std::to_string(value.toFloat());
if (param.readOnly) { if (param.readOnly) {
lay->addWidget(new QLabel(str.c_str()),r,1); lay->addWidget(new QLabel(str.c_str(), parent),r,1);
} else { } else {
QLineEdit* le = new QLineEdit( str.c_str() ); QLineEdit* le = new QLineEdit(str.c_str(), parent);
le->connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) { le->connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) {
const float val = str.toFloat(); const float val = str.toFloat();
elem->setParamValue(i, ParamValue(val)); elem->setParamValue(i, ParamValue(val));
@@ -61,11 +79,11 @@ public:
case ParamType::DOUBLE: { case ParamType::DOUBLE: {
const std::string str = std::to_string(value.toDouble()); const std::string str = std::to_string(value.toDouble());
if (param.readOnly) { if (param.readOnly) {
lay->addWidget(new QLabel(str.c_str()),r,1); lay->addWidget(new QLabel(str.c_str(), parent),r,1);
} else { } else {
QLineEdit* le = new QLineEdit( str.c_str() ); QLineEdit* le = new QLineEdit(str.c_str(), parent);
le->connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) { le->connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) {
const float val = str.toDouble(); const double val = str.toDouble();
elem->setParamValue(i, ParamValue(val)); elem->setParamValue(i, ParamValue(val));
}); });
lay->addWidget(le,r,1); lay->addWidget(le,r,1);
@@ -75,7 +93,7 @@ public:
case ParamType::INT: { case ParamType::INT: {
const std::string str = std::to_string(value.toInt()); const std::string str = std::to_string(value.toInt());
QLineEdit* le = new QLineEdit( str.c_str() ); QLineEdit* le = new QLineEdit(str.c_str(), parent);
le->connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) { le->connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) {
const int val = str.toInt(); const int val = str.toInt();
elem->setParamValue(i, ParamValue(val)); elem->setParamValue(i, ParamValue(val));
@@ -86,7 +104,7 @@ public:
case ParamType::STRING: { case ParamType::STRING: {
const std::string str = value.toString(); const std::string str = value.toString();
QLineEdit* le = new QLineEdit( str.c_str() ); QLineEdit* le = new QLineEdit(str.c_str(), parent);
le->connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) { le->connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) {
elem->setParamValue(i, ParamValue(str.toStdString())); elem->setParamValue(i, ParamValue(str.toStdString()));
}); });
@@ -96,8 +114,8 @@ public:
case ParamType::FILE: { case ParamType::FILE: {
const std::string str = value.toString(); const std::string str = value.toString();
QLabel* lblFile = new QLabel(str.c_str()); QLabel* lblFile = new QLabel(str.c_str(), parent);
QPushButton* btn = new QPushButton("<"); QPushButton* btn = new QPushButton("<",parent);
btn->setMaximumSize(32,32); btn->setMaximumSize(32,32);
btn->connect(btn, &QPushButton::clicked, [i,elem,lblFile] (const bool checked) { btn->connect(btn, &QPushButton::clicked, [i,elem,lblFile] (const bool checked) {
(void) checked; (void) checked;
@@ -112,10 +130,10 @@ public:
case ParamType::POINT2: { case ParamType::POINT2: {
const Point2 p2 = value.toPoint2(); const Point2 p2 = value.toPoint2();
QWidget* subWidget = new QWidget(); QWidget* subWidget = new QWidget(parent);
QGridLayout* laySub = new QGridLayout(subWidget); laySub->setMargin(0); QGridLayout* laySub = new QGridLayout(subWidget); laySub->setMargin(0);
QLineEdit* txtX = new QLineEdit(QString::number(p2.x)); QLineEdit* txtX = new QLineEdit(QString::number(p2.x), subWidget);
QLineEdit* txtY = new QLineEdit(QString::number(p2.y)); QLineEdit* txtY = new QLineEdit(QString::number(p2.y), subWidget);
laySub->addWidget(txtX,0,0); laySub->addWidget(txtX,0,0);
laySub->addWidget(txtY,0,1); laySub->addWidget(txtY,0,1);
lay->addWidget(subWidget,r,1); lay->addWidget(subWidget,r,1);
@@ -130,11 +148,11 @@ public:
case ParamType::POINT3: { case ParamType::POINT3: {
const Point3 p3 = value.toPoint3(); const Point3 p3 = value.toPoint3();
QWidget* subWidget = new QWidget(); QWidget* subWidget = new QWidget(parent);
QGridLayout* laySub = new QGridLayout(subWidget); laySub->setMargin(0); QGridLayout* laySub = new QGridLayout(subWidget); laySub->setMargin(0);
QLineEdit* txtX = new QLineEdit(QString::number(p3.x)); QLineEdit* txtX = new QLineEdit(QString::number(p3.x), subWidget);
QLineEdit* txtY = new QLineEdit(QString::number(p3.y)); QLineEdit* txtY = new QLineEdit(QString::number(p3.y), subWidget);
QLineEdit* txtZ = new QLineEdit(QString::number(p3.z)); QLineEdit* txtZ = new QLineEdit(QString::number(p3.z), subWidget);
laySub->addWidget(txtX,0,0); laySub->addWidget(txtX,0,0);
laySub->addWidget(txtY,0,1); laySub->addWidget(txtY,0,1);
laySub->addWidget(txtZ,0,2); laySub->addWidget(txtZ,0,2);
@@ -149,8 +167,8 @@ public:
break; break;
} }
case ParamType::NOT_AVAILABLE:
break;
} }

View File

@@ -10,6 +10,7 @@
#include "../mapview/model/IHasEditableMeta.h" #include "../mapview/model/IHasEditableMeta.h"
#include "MetaEditWidget.h" #include "MetaEditWidget.h"
#include "EditFields.h"
#include <Indoor/floorplan/v2/Floorplan.h> #include <Indoor/floorplan/v2/Floorplan.h>
@@ -19,6 +20,7 @@
#include <QLineEdit> #include <QLineEdit>
#include <QPushButton> #include <QPushButton>
#include <QFileDialog> #include <QFileDialog>
#include <QCheckBox>
QComboBox* getMaterials() { QComboBox* getMaterials() {
using namespace Floorplan; using namespace Floorplan;
@@ -96,7 +98,7 @@ void ElementParamWidget::refresh() {
while ( QWidget* w = this->findChild<QWidget*>() ) {delete w;} while ( QWidget* w = this->findChild<QWidget*>() ) {delete w;}
delete this->layout(); delete this->layout();
this->lay = new QGridLayout(); this->lay = new QGridLayout(this);
this->setLayout(lay); this->setLayout(lay);
int r = 0; int r = 0;
@@ -107,7 +109,7 @@ void ElementParamWidget::refresh() {
IHasMaterial* elem = dynamic_cast<IHasMaterial*>(el); IHasMaterial* elem = dynamic_cast<IHasMaterial*>(el);
if (elem) { if (elem) {
material.cmb = getMaterials(); material.cmb = getMaterials();
material.lbl = new QLabel("material"); material.lbl = new QLabel("material", this);
lay->addWidget(material.lbl,r,0); lay->addWidget(material.lbl,r,0);
lay->addWidget(material.cmb,r,1); lay->addWidget(material.cmb,r,1);
connect(material.cmb , SIGNAL(currentIndexChanged(int)), this, SLOT(onMaterialChange())); connect(material.cmb , SIGNAL(currentIndexChanged(int)), this, SLOT(onMaterialChange()));
@@ -121,7 +123,7 @@ void ElementParamWidget::refresh() {
IHasObstacleType* elem = dynamic_cast<IHasObstacleType*>(el); IHasObstacleType* elem = dynamic_cast<IHasObstacleType*>(el);
if (elem) { if (elem) {
obstacleType.cmb = getObstacleTypes(); obstacleType.cmb = getObstacleTypes();
obstacleType.lbl = new QLabel("type"); obstacleType.lbl = new QLabel("type", this);
lay->addWidget(obstacleType.lbl,r,0); lay->addWidget(obstacleType.lbl,r,0);
lay->addWidget(obstacleType.cmb,r,1); lay->addWidget(obstacleType.cmb,r,1);
connect(obstacleType.cmb, SIGNAL(currentIndexChanged(int)), this, SLOT(onObstacleTypeChange())); connect(obstacleType.cmb, SIGNAL(currentIndexChanged(int)), this, SLOT(onObstacleTypeChange()));
@@ -135,7 +137,7 @@ void ElementParamWidget::refresh() {
MMFloorOutlinePolygon* elem = dynamic_cast<MMFloorOutlinePolygon*>(el); MMFloorOutlinePolygon* elem = dynamic_cast<MMFloorOutlinePolygon*>(el);
if (elem) { if (elem) {
QComboBox* cmb = getOutlineMethods(); QComboBox* cmb = getOutlineMethods();
QLabel* lbl = new QLabel("outline"); QLabel* lbl = new QLabel("outline", this);
lay->addWidget(lbl,r,0); lay->addWidget(lbl,r,0);
lay->addWidget(cmb,r,1); lay->addWidget(cmb,r,1);
cmb->setCurrentIndex((int)elem->getMethod()); cmb->setCurrentIndex((int)elem->getMethod());
@@ -150,176 +152,21 @@ void ElementParamWidget::refresh() {
{ // does the element have "parameters" ? { // does the element have "parameters" ?
IHasParams* elem = dynamic_cast<IHasParams*>(el); IHasParams* elem = dynamic_cast<IHasParams*>(el);
if (elem) { if (elem) {
EditFields::get(this, r, lay, elem);
for(int i = 0; i < elem->getNumParams(); ++i) {
const Param param = elem->getParamDesc(i);
const ParamValue value = elem->getParamValue(i);
// skip Not-Available entries
if (param.type == ParamType::NOT_AVAILABLE) {continue;}
lay->addWidget(new QLabel(param.name.c_str()),r,0);
switch(param.type) {
case ParamType::NOT_AVAILABLE:
break;
case ParamType::ENUM: {
QComboBox* cmb = new QComboBox();
int idx = 0;
for (const std::string& str : param.getEnumValues()) {cmb->addItem(str.c_str(), idx++);}
cmb->setCurrentIndex(value.toInt());
connect(cmb, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [i, elem, cmb] (int idx) {
(void) idx;
elem->setParamValue(i, cmb->currentData().toInt() );
});
lay->addWidget(cmb,r,1);
break;
}
case ParamType::BOOL: {
QCheckBox* chk = new QCheckBox( );
chk->setChecked(value.toBool());
if (param.readOnly) {
chk->setEnabled(false);
} else {
connect(chk, &QCheckBox::clicked, [i,elem] (const bool checked) {
elem->setParamValue(i, ParamValue(checked));
});
}
lay->addWidget(chk,r,1);
break;
}
case ParamType::FLOAT: {
const std::string str = std::to_string(value.toFloat());
if (param.readOnly) {
lay->addWidget(new QLabel(str.c_str()),r,1);
} else {
QLineEdit* le = new QLineEdit( str.c_str() );
connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) {
const float val = str.toFloat();
elem->setParamValue(i, ParamValue(val));
});
lay->addWidget(le,r,1);
}
break;
}
case ParamType::DOUBLE: {
const std::string str = std::to_string(value.toDouble());
if (param.readOnly) {
lay->addWidget(new QLabel(str.c_str()),r,1);
} else {
QLineEdit* le = new QLineEdit( str.c_str() );
connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) {
const double val = str.toDouble();
elem->setParamValue(i, ParamValue(val));
});
lay->addWidget(le,r,1);
}
break;
}
case ParamType::INT: {
const std::string str = std::to_string(value.toInt());
QLineEdit* le = new QLineEdit( str.c_str() );
connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) {
const int val = str.toInt();
elem->setParamValue(i, ParamValue(val));
});
lay->addWidget(le,r,1);
break;
}
case ParamType::STRING: {
const std::string str = value.toString();
QLineEdit* le = new QLineEdit( str.c_str() );
connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) {
elem->setParamValue(i, ParamValue(str.toStdString()));
});
lay->addWidget(le,r,1);
break;
}
case ParamType::FILE: {
const std::string str = value.toString();
QLabel* lblFile = new QLabel(str.c_str());
QPushButton* btn = new QPushButton("<");
btn->setMaximumSize(32,32);
connect(btn, &QPushButton::clicked, [i,elem,lblFile] (const bool checked) {
(void) checked;
QString res = QFileDialog::getOpenFileName();
elem->setParamValue(i, ParamValue(res.toStdString()));
lblFile->setText(res);
});
lay->addWidget(lblFile,r,1);
lay->addWidget(btn,r,2);
break;
}
case ParamType::POINT2: {
const Point2 p2 = value.toPoint2();
QWidget* subWidget = new QWidget();
QGridLayout* laySub = new QGridLayout(subWidget); laySub->setMargin(0);
QLineEdit* txtX = new QLineEdit(QString::number(p2.x));
QLineEdit* txtY = new QLineEdit(QString::number(p2.y));
laySub->addWidget(txtX,0,0);
laySub->addWidget(txtY,0,1);
lay->addWidget(subWidget,r,1);
auto onChange = [i,elem,txtX,txtY] (const QString& str) {
(void) str;
elem->setParamValue(i, ParamValue( Point2(txtX->text().toFloat(), txtY->text().toFloat()) ));
};
connect(txtX, &QLineEdit::textChanged, onChange);
connect(txtY, &QLineEdit::textChanged, onChange);
break;
}
case ParamType::POINT3: {
const Point3 p3 = value.toPoint3();
QWidget* subWidget = new QWidget();
QGridLayout* laySub = new QGridLayout(subWidget); laySub->setMargin(0);
QLineEdit* txtX = new QLineEdit(QString::number(p3.x));
QLineEdit* txtY = new QLineEdit(QString::number(p3.y));
QLineEdit* txtZ = new QLineEdit(QString::number(p3.z));
laySub->addWidget(txtX,0,0);
laySub->addWidget(txtY,0,1);
laySub->addWidget(txtZ,0,2);
lay->addWidget(subWidget,r,1);
auto onChange = [i,elem,txtX,txtY,txtZ] (const QString& str) {
(void) str;
elem->setParamValue(i, ParamValue( Point3(txtX->text().toFloat(), txtY->text().toFloat(), txtZ->text().toFloat()) ));
};
connect(txtX, &QLineEdit::textChanged, onChange);
connect(txtY, &QLineEdit::textChanged, onChange);
connect(txtZ, &QLineEdit::textChanged, onChange);
break;
}
}
++r;
}
} }
{ // does the element have editable metadata? { // does the element have editable metadata?
IHasEditableMeta* elem = dynamic_cast<IHasEditableMeta*>(el); IHasEditableMeta* elem = dynamic_cast<IHasEditableMeta*>(el);
if (elem) { if (elem) {
QPushButton* btn = new QPushButton("edit"); QPushButton* btn = new QPushButton("edit", this);
connect(btn, &QPushButton::clicked, [elem] (const bool checked) { connect(btn, &QPushButton::clicked, [elem] (const bool checked) {
(void) checked; (void) checked;
if (!elem->getMeta()) {elem->setMeta(new Floorplan::Meta());} // ensure meta-object is present if (!elem->getMeta()) {elem->setMeta(new Floorplan::Meta());} // ensure meta-object is present
MetaEditWidget* mew = new MetaEditWidget(elem->getMeta()); // edit MetaEditWidget* mew = new MetaEditWidget(elem->getMeta()); // edit
mew->show(); mew->show();
}); });
lay->addWidget(new QLabel("Meta"),r,0); lay->addWidget(new QLabel("Meta", this),r,0);
lay->addWidget(btn,r,1); lay->addWidget(btn,r,1);
} }
} }

View File

@@ -68,7 +68,7 @@ void LayerParamWidget::setElement(MapLayer* l) {
delete this->layout(); delete this->layout();
this->lay = new QGridLayout(); this->lay = new QGridLayout();
this->setLayout(lay); this->setLayout(lay);
// int r = 0; int r = 0;
// { // {
@@ -97,7 +97,7 @@ void LayerParamWidget::setElement(MapLayer* l) {
{ {
IHasParams* elem = dynamic_cast<IHasParams*>(l); IHasParams* elem = dynamic_cast<IHasParams*>(l);
if (elem) { if (elem) {
EditFields::get(lay, elem); EditFields::get(this, r, lay, elem);
} }
} }

View File

@@ -11,6 +11,7 @@ class QLabel;
class QLineEdit; class QLineEdit;
class QComboBox; class QComboBox;
class QGridLayout; class QGridLayout;
class IHasParams;
class LayerParamWidget : public QWidget { class LayerParamWidget : public QWidget {
@@ -48,6 +49,7 @@ private:
QLabel* lbl; QLabel* lbl;
} height; } height;
void buildFields(QGridLayout* lay, IHasParams* elem);
signals: signals:

View File

@@ -15,11 +15,13 @@ void MetaEditModel::setSource(Floorplan::Meta* meta) {
endResetModel(); endResetModel();
} }
int MetaEditModel::rowCount(const QModelIndex &parent) const { int MetaEditModel::rowCount(const QModelIndex& parent) const {
(void) parent;
return (meta) ? (meta->size()) : (0); return (meta) ? (meta->size()) : (0);
} }
int MetaEditModel::columnCount(const QModelIndex &parent) const { int MetaEditModel::columnCount(const QModelIndex& parent) const {
(void) parent;
return 2; return 2;
} }