From 8017241c6ef4d21326237b55d3d006ea366cceee Mon Sep 17 00:00:00 2001 From: k-a-z-u Date: Wed, 25 Jul 2018 16:20:34 +0200 Subject: [PATCH] split line(old) and wall(new) added new walling started working on windows --- IndoorMap.pro | 8 +- MainController.cpp | 2 +- mapview/2D/MV2DElementFloorObstacleLine.cpp | 53 ++-- mapview/2D/MV2DElementFloorObstacleWall.cpp | 292 ++++++++++++++++++++ mapview/2D/MV2DElementFloorObstacleWall.h | 45 +++ mapview/2D/tools/ToolNewLine.h | 83 ++++++ mapview/2D/tools/ToolNewWall.h | 9 +- mapview/model/MMFloorObstacleLine.h | 29 +- mapview/model/MMFloorObstacleWall.h | 116 ++++++++ mapview/model/MMFloorObstacles.h | 22 +- params/ToolBoxWidget.cpp | 83 +----- params/ToolBoxWidget.h | 2 + res.qrc | 1 + res/icons/line.svg | 80 ++++++ 14 files changed, 703 insertions(+), 122 deletions(-) create mode 100644 mapview/2D/MV2DElementFloorObstacleWall.cpp create mode 100644 mapview/2D/MV2DElementFloorObstacleWall.h create mode 100644 mapview/2D/tools/ToolNewLine.h create mode 100644 mapview/model/MMFloorObstacleWall.h create mode 100644 res/icons/line.svg diff --git a/IndoorMap.pro b/IndoorMap.pro index b6707c5..a919fe8 100644 --- a/IndoorMap.pro +++ b/IndoorMap.pro @@ -70,7 +70,8 @@ SOURCES += \ mapview/2D/MV2DElementStair.cpp \ mapview/2D/MV2DElementElevator.cpp \ mapview/2D/MV2DElementFloorObstacleCircle.cpp \ - mapview/3D/floorplan/FloorplanRendererModel.cpp + mapview/3D/floorplan/FloorplanRendererModel.cpp \ + mapview/2D/MV2DElementFloorObstacleWall.cpp HEADERS += MainWindow.h \ @@ -204,7 +205,10 @@ HEADERS += MainWindow.h \ mapview/model/MMFloorObstacleObject.h \ mapview/3D/MV3DElementFloorObstacleObject.h \ mapview/2D/tools/ToolNewObject.h \ - mapview/2D/tools/ToolNewPillar.h + mapview/2D/tools/ToolNewPillar.h \ + mapview/model/MMFloorObstacleWall.h \ + mapview/2D/MV2DElementFloorObstacleWall.h \ + mapview/2D/tools/ToolNewLine.h FORMS += MainWindow.ui diff --git a/MainController.cpp b/MainController.cpp index 5c07923..2479596 100644 --- a/MainController.cpp +++ b/MainController.cpp @@ -127,7 +127,7 @@ MainController::MainController() { //mapModel->load("/apps/paper/maps/museum/map43_svg.xml"); //mapModel->load("/apps/paper/maps/shl/SHL45_nm.xml"); - mapModel->load("/apps/paper/maps/test/polyMergeTest2.xml"); + mapModel->load("/apps/paper/maps/test/doors1.xml"); //mapModel->load("/mnt/sdcard/SHL41_nm.xml"); diff --git a/mapview/2D/MV2DElementFloorObstacleLine.cpp b/mapview/2D/MV2DElementFloorObstacleLine.cpp index 502d4f5..b11561b 100644 --- a/mapview/2D/MV2DElementFloorObstacleLine.cpp +++ b/mapview/2D/MV2DElementFloorObstacleLine.cpp @@ -7,6 +7,7 @@ #include #include + MV2DElementFloorObstacleLine::MV2DElementFloorObstacleLine(Floorplan::Floor* f, Floorplan::FloorObstacleLine* fo) : f(f), fo(fo) { ; } @@ -22,18 +23,18 @@ ClickDist MV2DElementFloorObstacleLine::getMinDistanceXY(const Point2 p) const { return MapElementHelper::getLineDistanceXY(fo->from, fo->to, p); } -bool isConnected(const Point2 p, const Floorplan::Floor* f, const Floorplan::FloorObstacleLine* fo) { - const float delta = 0.001; - for (const Floorplan::FloorObstacle* fo1 : f->obstacles) { - if (fo1 == fo) {continue;} - const Floorplan::FloorObstacleLine* line = dynamic_cast(fo1); - if (line) { - if (line->from.eq(p, delta)) {return true;} - if (line->to.eq(p, delta)) {return true;} - } - } - return false; -} +//bool isConnected(const Point2 p, const Floorplan::Floor* f, const Floorplan::FloorObstacleLine* fo) { +// const float delta = 0.001; +// for (const Floorplan::FloorObstacle* fo1 : f->obstacles) { +// if (fo1 == fo) {continue;} +// const Floorplan::FloorObstacleLine* line = dynamic_cast(fo1); +// if (line) { +// if (line->from.eq(p, delta)) {return true;} +// if (line->to.eq(p, delta)) {return true;} +// } +// } +// return false; +//} void MV2DElementFloorObstacleLine::paint(Painter& p) { @@ -47,22 +48,22 @@ void MV2DElementFloorObstacleLine::paint(Painter& p) { // draw the wall itself p.drawLine(fo->from, fo->to); - const bool c1 = isConnected(fo->from, f, fo); - const bool c2 = isConnected(fo->to, f, fo); +// const bool c1 = isConnected(fo->from, f, fo); +// const bool c2 = isConnected(fo->to, f, fo); - // wall conencted to other walls? - if (c1 || c2) { +// // wall conencted to other walls? +// if (c1 || c2) { - // QPen change is costly! - QPen pp = p.getPen(); - pp.setCapStyle(Qt::RoundCap); - p.setPen(pp); +// // QPen change is costly! +// QPen pp = p.getPen(); +// pp.setCapStyle(Qt::RoundCap); +// p.setPen(pp); - // indicate connection with other wall - if (c1) {p.drawDot(fo->from);} - if (c2) {p.drawDot(fo->to);} +// // indicate connection with other wall +// if (c1) {p.drawDot(fo->from);} +// if (c2) {p.drawDot(fo->to);} - } +// } // length info if (hasFocus()) { @@ -91,9 +92,11 @@ std::vector MV2DElementFloorObstacleLine::getMoveableNodes() const } 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) { @@ -101,5 +104,3 @@ void MV2DElementFloorObstacleLine::onNodeMoved(MapView2D* v, const int userIdx, (void) newPos; emit v->onElementChange(this); } - - diff --git a/mapview/2D/MV2DElementFloorObstacleWall.cpp b/mapview/2D/MV2DElementFloorObstacleWall.cpp new file mode 100644 index 0000000..2eb3c6c --- /dev/null +++ b/mapview/2D/MV2DElementFloorObstacleWall.cpp @@ -0,0 +1,292 @@ +#include "MV2DElementFloorObstacleWall.h" + +#include "MV2DElement.h" +#include "HasMoveableNodes.h" + +#include "MapViewElementHelper.h" +#include +#include + + +void drawDoorSwing(const Floorplan::FloorObstacleWall* wall, const Floorplan::FloorObstacleWallDoor* door, Painter& p, QPen& pen) { + + const float len = door->width; + //const Point2 dir = line->to - line->from; + Point2 start = door->getStart(wall); + Point2 end = door->getEnd(wall); + + // opening indicator + float open = (+M_PI * 0.5); + if (door->inOut) {open = -open;} + if (door->leftRight) {open = -open;} + + const float angle1 = std::atan2(end.y - start.y, end.x - start.x); + const float angle2 = angle1 + open; + + if (std::isnan(angle1)) {return;} + if (std::isnan(angle2)) {return;} + + const Point2 pOpen = Point2( std::cos(angle2) * len, std::sin(angle2) * len ) + start; + + pen.setWidth(2); p.setPen(pen); + p.drawLine(start, end); + + pen.setWidth(1); p.setPen(pen); + p.drawLine(start, pOpen); + p.drawArc(start, door->width, angle1, open); + +} + +void drawDoorRevolve(const Floorplan::FloorObstacleWallDoor* door, Painter& p, QPen& pen) { + +// const float angle_rad = std::atan2(fo->to.y-fo->from.y, fo->to.x-fo->from.x); + +// // arcs +// const Point2 cen = (fo->from + fo->to) / 2; +// const float rad = (fo->to - fo->from).length() / 2; +// p.drawArc(cen, rad, (40-90)/180.0f*M_PI+angle_rad, 100/180.0f*M_PI); +// p.drawArc(cen, rad, (180+40-90)/180.0f*M_PI+angle_rad, 100/180.0f*M_PI); + +// const int funAngle = (std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count() / 50) % 360; + +// // inner spinner +// int numDoors = 3; +// for (int i = 0; i < numDoors; ++i) { +// const int deg = 360 * i / numDoors + angle_rad*180.0f/M_PI + funAngle; +// const float sx = std::cos(deg / 180.0f * M_PI); +// const float sy = std::sin(deg / 180.0f * M_PI); +// const Point2 dst = cen + Point2(sx,sy) * rad; +// p.drawLine(cen, dst); +// } + +} + +void drawDoor(const Floorplan::FloorObstacleWall* line, const Floorplan::FloorObstacleWallDoor* door, Painter& p) { + + QPen pen; + pen.setColor(QColor(0.5,0.5,0.5)); + pen.setStyle(Qt::PenStyle::DotLine); + p.setPenBrush(pen, Qt::NoBrush); + + if (Floorplan::DoorType::SWING == door->type) { + drawDoorSwing(line, door, p, pen); + } else if (Floorplan::DoorType::REVOLVING == door->type) { + drawDoorRevolve(door, p, pen); + } + +} + +void drawWindow(const Floorplan::FloorObstacleWall* wall, const Floorplan::FloorObstacleWallWindow* win, Painter& p) { + + QPen pen; + pen.setColor(QColor(0.5,0.5,0.5)); + pen.setWidth(3); + pen.setStyle(Qt::PenStyle::DotLine); + p.setPenBrush(pen, Qt::NoBrush); + + const Point2 p1 = win->getStart(wall); + const Point2 p2 = win->getEnd(wall); + + p.drawLine(p1, p2); + +} + +bool isConnected(const Point2 p, const Floorplan::Floor* f, const Floorplan::FloorObstacleWall* fo) { + const float delta = 0.001; + for (const Floorplan::FloorObstacle* fo1 : f->obstacles) { + if (fo1 == fo) {continue;} + const Floorplan::FloorObstacleWall* wall = dynamic_cast(fo1); + if (wall) { + if (wall->from.eq(p, delta)) {return true;} + if (wall->to.eq(p, delta)) {return true;} + } + } + return false; +} + + + +MV2DElementFloorObstacleWall::MV2DElementFloorObstacleWall(Floorplan::Floor* f, Floorplan::FloorObstacleWall* fo) : f(f), fo(fo) { + ; +} + +BBox2 MV2DElementFloorObstacleWall::getBoundingBox() const { + BBox2 bbox; + bbox.add(fo->from); + bbox.add(fo->to); + return bbox; +} + +ClickDist MV2DElementFloorObstacleWall::getMinDistanceXY(const Point2 p) const { + return MapElementHelper::getLineDistanceXY(fo->from, fo->to, p); +} + + + +void MV2DElementFloorObstacleWall::paint(Painter& p) { + + // convert wall's thickness from meter to pixels + const float thickness_px = p.s.ms(fo->thickness_m); + + // see notes within MapElementHelper! + // lines only get thicker, but not longer! + p.setPenBrush(MapElementHelper::getPen(fo->material, fo->type, hasFocus(), thickness_px), Qt::NoBrush); + + // draw the wall itself + + // sort all doors by position on the line + std::vector doors = fo->doors; + auto comp = [] (const Floorplan::FloorObstacleWallDoor* d1, const Floorplan::FloorObstacleWallDoor* d2) { + return d1->atLinePos < d2->atLinePos; + }; + std::sort(doors.begin(), doors.end(), comp); + + std::vector pts; + pts.push_back(fo->from); + for (const Floorplan::FloorObstacleWallDoor* door : doors) { + pts.push_back(door->getStart(fo)); + pts.push_back(door->getEnd(fo)); + } + pts.push_back(fo->to); + + for (size_t i = 0; i < pts.size(); i+=2) { + p.drawLine(pts[i], pts[i+1]); + } + //p.drawLine(fo->from, fo->to); + + const bool c1 = isConnected(fo->from, f, fo); + const bool c2 = isConnected(fo->to, f, fo); + + // wall conencted to other walls? + if (c1 || c2) { + + // QPen change is costly! + QPen pp = p.getPen(); + pp.setCapStyle(Qt::RoundCap); + p.setPen(pp); + + // indicate connection with other wall + if (c1) {p.drawDot(fo->from);} + if (c2) {p.drawDot(fo->to);} + + } + + for (const Floorplan::FloorObstacleWallDoor* door : fo->doors) { + drawDoor(fo, door, p); + } + + for (const Floorplan::FloorObstacleWallWindow* window : fo->windows) { + drawWindow(fo, window, p); + } + + // 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); + + } + +} + +void MV2DElementFloorObstacleWall::onFocus() { + ; +} + +void MV2DElementFloorObstacleWall::onUnfocus() { + selectedUserIdx = -1; // clear selection +} + +std::vector MV2DElementFloorObstacleWall::getMoveableNodes() const { + + std::vector nodes; + nodes.push_back(MoveableNode(0, fo->from)); + nodes.push_back(MoveableNode(1, fo->to)); + + int cnt = 0; + for (const Floorplan::FloorObstacleWallDoor* door : fo->doors) { + const Point2 pos = fo->from + (fo->to - fo->from) * door->atLinePos; + nodes.push_back(MoveableNode(cnt+1000, pos)); + ++cnt; + } + + cnt = 0; + for (const Floorplan::FloorObstacleWallWindow* win : fo->windows) { + const Point2 pos = fo->from + (fo->to - fo->from) * win->atLinePos; + nodes.push_back(MoveableNode(cnt+2000, pos)); + ++cnt; + } + + return nodes; + +} + +#include + + + +void MV2DElementFloorObstacleWall::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;} + + Point2 perp = (fo->from - fo->to).perpendicular() * 100; + Line2 l1(newPos-perp, newPos+perp); + Line2 l2(fo->from, fo->to); + + Point2 p; + float u = 0; + bool isects = intersects(l2, l1, true, p, &u); + if (u < 0.1) {u = 0.1;} + if (u > 0.9) {u = 0.9;} + + if (userIdx >= 1000 && userIdx < 2000) { + + Floorplan::FloorObstacleWallDoor* door = fo->doors[userIdx-1000]; + + if (isects) { + door->atLinePos = u; + } + + } else if (userIdx >= 2000 && userIdx < 3000) { + + Floorplan::FloorObstacleWallWindow* win = fo->windows[userIdx-2000]; + + if (isects) { + win->atLinePos = u; + } + + } + +} + +void MV2DElementFloorObstacleWall::onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos) { + (void) userIdx; + (void) newPos; + emit v->onElementChange(this); +} + + +bool MV2DElementFloorObstacleWall::keyPressEvent(MapView2D* v, QKeyEvent* e) { + + if (e->key() == Qt::Key_D) { + Floorplan::FloorObstacleWallDoor* door = new Floorplan::FloorObstacleWallDoor(Floorplan::DoorType::SWING, Floorplan::Material::WOOD, 0.5, 1.0, 2.1); + fo->doors.push_back(door); + return true; + } else if (e->key() == Qt::Key_W) { + Floorplan::FloorObstacleWallWindow* win = new Floorplan::FloorObstacleWallWindow(Floorplan::WindowType::UNKNOWN, Floorplan::Material::WOOD, 0.5, 0.5, 1.0, 1.0); + fo->windows.push_back(win); + return true; + } else if (e->key() == Qt::Key_Delete && getSelectedNode() >= 1000) { + const int idx = getSelectedNode() - 1000; + fo->doors.erase(fo->doors.begin()+idx); + return true; + } + + return false; + +} + + diff --git a/mapview/2D/MV2DElementFloorObstacleWall.h b/mapview/2D/MV2DElementFloorObstacleWall.h new file mode 100644 index 0000000..b5aaebb --- /dev/null +++ b/mapview/2D/MV2DElementFloorObstacleWall.h @@ -0,0 +1,45 @@ +#ifndef MV2DELEMENTFLOOROBSTACLEWALL_H +#define MV2DELEMENTFLOOROBSTACLEWALL_H + + +#include "MV2DElement.h" +#include "HasMoveableNodes.h" + +#include + +class MV2DElementFloorObstacleWall : public MV2DElement, public HasMoveableNodes { + +private: + + Floorplan::Floor* f; + Floorplan::FloorObstacleWall* fo; + +public: + + /** ctor */ + MV2DElementFloorObstacleWall(Floorplan::Floor* f, Floorplan::FloorObstacleWall* fo); + + /** get the element's 3D bounding box */ + BBox2 getBoundingBox() const override; + + /** get the element's minimal distance (nearest whatsoever) to the given point */ + ClickDist getMinDistanceXY(const Point2 p) const override; + + /** repaint me */ + void paint(Painter& p) override; + + void onFocus() override; + + void onUnfocus() override; + + virtual std::vector getMoveableNodes() const override; + + void onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) override; + + void onNodeMoved(MapView2D* v, const int userIdx, const Point2 newPos); + + bool keyPressEvent(MapView2D* v, QKeyEvent* e) override; + +}; + +#endif // MV2DELEMENTFLOOROBSTACLEWALL_H diff --git a/mapview/2D/tools/ToolNewLine.h b/mapview/2D/tools/ToolNewLine.h new file mode 100644 index 0000000..50ee3a4 --- /dev/null +++ b/mapview/2D/tools/ToolNewLine.h @@ -0,0 +1,83 @@ +#ifndef TOOLNEWLINE_H +#define TOOLNEWLINE_H + +#include "ToolNewElement.h" +#include "../../model/MMFloorObstacles.h" +#include "../../model/MMFloorObstacleLine.h" + +/** old walls, based on lines */ +class ToolNewLine : public ToolNewElement { + +private: + + /** currently edited line node (has 2) */ + int idx = 0; + +public: + + ToolNewLine(Tools& tools, MapLayer* layer) : ToolNewElement(tools, layer) { + ; + } + + void becomesActive() override { + //create(); // start adding an new element + } + + void becomesInactive() override { + deleteCurrent(); // delete the currently pending and not yet finished wall element + } + + const std::string getName() const override { + return "new Line"; + } + + + + /** mouse is currently moved */ + void moving(const Point2 mapPoint) override { + + // live-moving of the ending point + if (idx == 1) { foEL->to = mapPoint; } + + } + + /** next point */ + void leftMouse(const Point2 mapPoint) override { + + // 1st click (where to start the line) + if (idx == 0) { + createEmptyElement(); + foEL->from = mapPoint; foEL->to = mapPoint; + ++idx; + + // 2nd click (wehere the line ends) + } else if (idx == 1) { + finalizeCurrent(); + idx = 0; + if (!addAnother) {disableMe();} + + } + + } + + void rightMouse(const Point2 mapPoint) override { + + (void) mapPoint; + finalizeCurrent(); + disableMe(); + + } + +private: + + void createEmptyElement() { + + foEL = new Floorplan::FloorObstacleLine(Floorplan::ObstacleType::WALL, Floorplan::Material::DRYWALL, Point2(0, 0), Point2(0, 0)); + MMFloorObstacles* obs = (MMFloorObstacles*)layer; + mmEL = obs->createLine(foEL); + + } + +}; + +#endif // TOOLNEWLINE_H diff --git a/mapview/2D/tools/ToolNewWall.h b/mapview/2D/tools/ToolNewWall.h index 092208d..a693ddd 100644 --- a/mapview/2D/tools/ToolNewWall.h +++ b/mapview/2D/tools/ToolNewWall.h @@ -3,9 +3,10 @@ #include "ToolNewElement.h" #include "../../model/MMFloorObstacles.h" -#include "../../model/MMFloorObstacleLine.h" +#include "../../model/MMFloorObstacleWall.h" -class ToolNewWall : public ToolNewElement { +/** new walls */ +class ToolNewWall : public ToolNewElement { private: @@ -71,9 +72,9 @@ private: void createEmptyElement() { - foEL = new Floorplan::FloorObstacleLine(Floorplan::ObstacleType::WALL, Floorplan::Material::DRYWALL, Point2(0, 0), Point2(0, 0)); + foEL = new Floorplan::FloorObstacleWall(Floorplan::ObstacleType::WALL, Floorplan::Material::DRYWALL, Point2(0, 0), Point2(0, 0)); MMFloorObstacles* obs = (MMFloorObstacles*)layer; - mmEL = obs->createLine(foEL); + mmEL = obs->createWall(foEL); } diff --git a/mapview/model/MMFloorObstacleLine.h b/mapview/model/MMFloorObstacleLine.h index e10aedf..7828124 100644 --- a/mapview/model/MMFloorObstacleLine.h +++ b/mapview/model/MMFloorObstacleLine.h @@ -9,7 +9,6 @@ #include "IHasParams.h" #include "../2D/MV2DElementFloorObstacleLine.h" -//#include "../3D/MV3DElementFloorObstacleWall.h" #include @@ -21,13 +20,12 @@ public: Floorplan::Floor* mf; Floorplan::FloorObstacleLine* fo; MV2DElementFloorObstacleLine mv2d; - //MV3DElementFloorObstacleWall mv3d; public: MMFloorObstacleLine(MapLayer* parent, Floorplan::Floor* mf, Floorplan::FloorObstacleLine* fo) : - MapModelElement(parent), mf(mf), fo(fo), mv2d(mf, fo) {//, mv3d(mf,fo) { - + MapModelElement(parent), mf(mf), fo(fo), mv2d(mf, fo) { + ; } void setMaterial(const Floorplan::Material m) override {fo->material = m;} @@ -37,44 +35,41 @@ public: Floorplan::ObstacleType getObatcleType() const override {return fo->type;} MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;} - //MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;} void deleteMe() const override { parent->removeElement(this); mf->obstacles.erase(std::remove(mf->obstacles.begin(), mf->obstacles.end(), fo), mf->obstacles.end()); } - - virtual int getNumParams() const override { + int getNumParams() const override { return 3; } virtual Param getParamDesc(const int idx) const override { switch(idx) { - case 0: return Param("thickness (m)", ParamType::FLOAT); - case 1: return Param("height (m)", ParamType::FLOAT); - case 2: return Param("length", ParamType::FLOAT, true); + case 0: return Param("thickness (m)", ParamType::FLOAT); + case 1: return Param("height (m)", ParamType::FLOAT); + case 2: return Param("length", ParamType::FLOAT, true); } throw 1; } virtual ParamValue getParamValue(const int idx) const override { switch(idx) { - case 0: return fo->thickness_m; - case 1: return fo->height_m; - case 2: return fo->from.getDistance(fo->to); + case 0: return fo->thickness_m; + case 1: return fo->height_m; + case 2: return fo->from.getDistance(fo->to); } throw 1; } virtual void setParamValue(const int idx, const ParamValue& val) override { switch(idx) { - case 0: fo->thickness_m = val.toFloat(); break; - case 1: fo->height_m = val.toFloat(); break; - case 2: break; + case 0: fo->thickness_m = val.toFloat(); return; + case 1: fo->height_m = val.toFloat(); return; + case 2: return; } } - }; #endif // MAPELEMENTOBSTACLE_H diff --git a/mapview/model/MMFloorObstacleWall.h b/mapview/model/MMFloorObstacleWall.h new file mode 100644 index 0000000..e2ef0ca --- /dev/null +++ b/mapview/model/MMFloorObstacleWall.h @@ -0,0 +1,116 @@ +#ifndef MMFLOOROBSTACLEWALL_H +#define MMFLOOROBSTACLEWALL_H + + +#include "MapModelElement.h" +#include "../2D/MapViewElementHelper.h" + +#include "IHasMaterial.h" +#include "IHasObstacleType.h" +#include "IHasParams.h" + +#include "../2D/MV2DElementFloorObstacleWall.h" + +#include + +class MMFloorObstacleWall : public MapModelElement, public IHasMaterial, public IHasObstacleType, public IHasParams { + +public: + + Floorplan::Floor* mf; + Floorplan::FloorObstacleWall* wall; + MV2DElementFloorObstacleWall mv2d; + +public: + + MMFloorObstacleWall(MapLayer* parent, Floorplan::Floor* mf, Floorplan::FloorObstacleWall* wall) : + MapModelElement(parent), mf(mf), wall(wall), mv2d(mf, wall) { + ; + } + + void setMaterial(const Floorplan::Material m) override {wall->material = m;} + Floorplan::Material getMaterial() const override {return wall->material;} + + void setObstacleType(const Floorplan::ObstacleType t) override {wall->type = t;} + Floorplan::ObstacleType getObatcleType() const override {return wall->type;} + + MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;} + + void deleteMe() const override { + parent->removeElement(this); + mf->obstacles.erase(std::remove(mf->obstacles.begin(), mf->obstacles.end(), wall), mf->obstacles.end()); + } + + int getType() const { + const int idx = mv2d.getSelectedNode(); + if (idx < 1000) {return 0;} // line + if (idx < 2000) {return 1;} // door + return 2; // window + } + + Floorplan::FloorObstacleWallDoor* getCurDoor() const { + const int idx = mv2d.getSelectedNode()-1000; + return wall->doors[idx]; + } + + int getNumParams() const override { + switch(getType()) { + case 0: return 3; + case 1: return 4; + case 2: return 0; + } + throw 1; + } + + virtual Param getParamDesc(const int idx) const override { + switch(getType()) { + case 0: switch(idx) { + case 0: return Param("thickness (m)", ParamType::FLOAT); + case 1: return Param("height (m)", ParamType::FLOAT); + case 2: return Param("length", ParamType::FLOAT, true); + } + case 1: switch(idx) { + case 0: return Param("width (m)", ParamType::FLOAT); + case 1: return Param("height (m)", ParamType::FLOAT); + case 2: return Param("left/right", ParamType::BOOL); + case 3: return Param("in/out", ParamType::BOOL); + } + } + throw 1; + } + + virtual ParamValue getParamValue(const int idx) const override { + switch(getType()) { + case 0: switch(idx) { + case 0: return wall->thickness_m; + case 1: return wall->height_m; + case 2: return wall->from.getDistance(wall->to); + } + case 1: switch(idx) { + case 0: return getCurDoor()->width; + case 1: return getCurDoor()->height; + case 2: return getCurDoor()->leftRight; + case 3: return getCurDoor()->inOut; + } + } + throw 1; + } + + virtual void setParamValue(const int idx, const ParamValue& val) override { + switch(getType()) { + case 0: switch(idx) { + case 0: wall->thickness_m = val.toFloat(); return; + case 1: wall->height_m = val.toFloat(); return; + case 2: return; + } + case 1: switch(idx) { + case 0: getCurDoor()->width = val.toFloat(); return; + case 1: getCurDoor()->height = val.toFloat(); return; + case 2: getCurDoor()->leftRight = val.toBool(); return; + case 3: getCurDoor()->inOut = val.toBool(); return; + } + } + } +}; + +#endif // MMFLOOROBSTACLEWALL_H diff --git a/mapview/model/MMFloorObstacles.h b/mapview/model/MMFloorObstacles.h index a210ac6..ef591c5 100644 --- a/mapview/model/MMFloorObstacles.h +++ b/mapview/model/MMFloorObstacles.h @@ -4,6 +4,7 @@ #include "MapLayer.h" #include "MMFloorObstacleCircle.h" #include "MMFloorObstacleLine.h" +#include "MMFloorObstacleWall.h" #include "MMFloorObstacleDoor.h" #include "MMFloorObstacleObject.h" @@ -25,12 +26,14 @@ public: for (Floorplan::FloorObstacle* o : floor->obstacles) { if (dynamic_cast(o)) { addElement(new MMFloorObstacleLine(this, floor, (Floorplan::FloorObstacleLine*)o)); + } else if (dynamic_cast(o)) { + addElement(new MMFloorObstacleWall(this, floor, (Floorplan::FloorObstacleWall*)o)); } else if (dynamic_cast(o)) { addElement(new MMFloorObstacleCircle(this, floor, (Floorplan::FloorObstacleCircle*)o)); } else if (dynamic_cast(o)) { - addElement(new MMFloorObstacleDoor(this, floor, (Floorplan::FloorObstacleDoor*)o)); + addElement(new MMFloorObstacleDoor(this, floor, (Floorplan::FloorObstacleDoor*)o)); } else if (dynamic_cast(o)) { - addElement(new MMFloorObstacleObject(this, floor, (Floorplan::FloorObstacleObject*)o)); + addElement(new MMFloorObstacleObject(this, floor, (Floorplan::FloorObstacleObject*)o)); } else { throw new Exception("todo: not yet implemented obstacle type"); } @@ -50,6 +53,21 @@ public: /** get the corresponding floor from the underlying model */ Floorplan::Floor* getFloor() {return floor;} + + //TODO: check + MMFloorObstacleWall* createWall(Floorplan::FloorObstacleWall* obs) { + + // add to underlying model + floor->obstacles.push_back(obs); + + // add to myself as element + MMFloorObstacleWall* mm = new MMFloorObstacleWall(this, floor, obs); + addElement(mm); + return mm; + + } + + //TODO: check MMFloorObstacleDoor* createDoor(Floorplan::FloorObstacleDoor* obs) { diff --git a/params/ToolBoxWidget.cpp b/params/ToolBoxWidget.cpp index d7cc601..a6f4758 100644 --- a/params/ToolBoxWidget.cpp +++ b/params/ToolBoxWidget.cpp @@ -21,6 +21,7 @@ #include "../mapview/2D/tools/ToolSelector.h" #include "../mapview/2D/tools/ToolNewElement.h" #include "../mapview/2D/tools/ToolNewWall.h" +#include "../mapview/2D/tools/ToolNewLine.h" #include "../mapview/2D/tools/ToolNewDoor.h" #include "../mapview/2D/tools/ToolNewStair.h" #include "../mapview/2D/tools/ToolNewElevator.h" @@ -81,6 +82,11 @@ ToolBoxWidget::ToolBoxWidget(MapView2D* view, QWidget *parent) : QWidget(parent) lay->addWidget(btnWall, r++, 0, 1,1,Qt::AlignTop); connect(btnWall, SIGNAL(clicked(bool)), this, SLOT(onNewWall())); + btnLine = new QPushButton(UIHelper::getIcon("line"), ""); + btnLine->setMinimumSize(s,s); + lay->addWidget(btnLine, r++, 0, 1,1,Qt::AlignTop); + connect(btnLine, SIGNAL(clicked(bool)), this, SLOT(onNewLine())); + btnPillar = new QPushButton(UIHelper::getIcon("pillar"), ""); btnPillar->setMinimumSize(s,s); lay->addWidget(btnPillar, r++, 0, 1,1,Qt::AlignTop); @@ -184,6 +190,7 @@ void ToolBoxWidget::onMainToolChanged() { btnGround->setStyleSheet( dynamic_cast(t) ? styleSel : styleNor ); + btnLine->setStyleSheet( dynamic_cast(t) ? styleSel : styleNor ); btnDoor->setStyleSheet( dynamic_cast(t) ? styleSel : styleNor ); btnWall->setStyleSheet( dynamic_cast(t) ? styleSel : styleNor ); btnObject->setStyleSheet( dynamic_cast(t) ? styleSel : styleNor ); @@ -206,6 +213,7 @@ void ToolBoxWidget::setSelectedLayer(MapLayer *ml) { btnGround->setEnabled(ml && (ml->getLayerType() == MapLayerType::FLOOR_GROUND)); + btnLine->setEnabled(ml && (ml->getLayerType() == MapLayerType::FLOOR_OBSTACLES)); btnWall->setEnabled(ml && (ml->getLayerType() == MapLayerType::FLOOR_OBSTACLES)); btnPillar->setEnabled(ml && (ml->getLayerType() == MapLayerType::FLOOR_OBSTACLES)); btnDoor->setEnabled(ml && (ml->getLayerType() == MapLayerType::FLOOR_OBSTACLES)); @@ -258,6 +266,10 @@ void ToolBoxWidget::onMeasure() { view->getTools().setMain(new ToolMeasure(view->getTools())); } +void ToolBoxWidget::onNewLine() { + view->getTools().setMain(new ToolNewLine(view->getTools(), curLayer)); +} + void ToolBoxWidget::onNewWall() { view->getTools().setMain(new ToolNewWall(view->getTools(), curLayer)); } @@ -277,105 +289,36 @@ void ToolBoxWidget::onNewPillar() { void ToolBoxWidget::onNewStair() { - view->getTools().setMain(new ToolNewStair(view->getTools(), curLayer)); - - -// const Point2 center = view->getScaler().getCenter(); - -// Floorplan::StairFreeform* stair = new Floorplan::StairFreeform(); -// Floorplan::StairPart part(Point3(center.x-3, center.y, 0), Point3(center.x+3, center.y, 3), 3); -// stair->parts.push_back( part ); - -// MMFloorStairs* stairs = (MMFloorStairs*)curLayer; -// stairs->create(stair); - - } void ToolBoxWidget::onNewElevator() { - -// const Point2 center = view->getScaler().getCenter(); - -// Floorplan::Elevator* elevator = new Floorplan::Elevator(center); - -// MMFloorElevators* elevators = (MMFloorElevators*)curLayer; -// elevators->create(elevator); - view->getTools().setMain(new ToolNewElevator(view->getTools(), curLayer)); - } void ToolBoxWidget::onNewAccessPoint() { - -// const Point2 center = view->getScaler().getCenter(); -// Floorplan::AccessPoint* ap = new Floorplan::AccessPoint( -// "noname", "00:00:00:00:00:00", Point3(center.x, center.y, 0) -// ); - -// MMFloorAccessPoints* aps = (MMFloorAccessPoints*) curLayer; -// aps->createAP(ap); - view->getTools().setMain(new ToolNewAccessPoint(view->getTools(), curLayer)); - } void ToolBoxWidget::onNewBeacon() { - -// const Point2 center = view->getScaler().getCenter(); -// Floorplan::Beacon* b = new Floorplan::Beacon( -// "noname", "00:00:00:00:00:00", Point3(center.x, center.y, 0) -// ); - -// MMFloorBeacons* beacons = (MMFloorBeacons*) curLayer; -// beacons->createBeacon(b); - view->getTools().setMain(new ToolNewBeacon(view->getTools(), curLayer)); - } void ToolBoxWidget::onNewFingerprintLocation() { - -// const Point2 center = view->getScaler().getCenter(); -// Floorplan::FingerprintLocation* fpl = new Floorplan::FingerprintLocation("noname", center, 0); - -// MMFloorFingerprints* fps = (MMFloorFingerprints*) curLayer; -// fps->create(fpl); - view->getTools().setMain(new ToolNewFingerprint(view->getTools(), curLayer)); - } void ToolBoxWidget::onNewPOI() { - -// const Point2 center = view->getScaler().getCenter(); -// Floorplan::POI* poi = new Floorplan::POI( -// Floorplan::POIType::ROOM, "noname", Point2(center.x, center.y) -// ); - -// MMFloorPOIs* pois = (MMFloorPOIs*) curLayer; -// pois->createPOI(poi); - view->getTools().setMain(new ToolNewPOI(view->getTools(), curLayer)); - } void ToolBoxWidget::onNewGTP() { - -// const Point2 center = view->getScaler().getCenter(); -// Floorplan::GroundTruthPoint* gtp = new Floorplan::GroundTruthPoint( -// 0, Point3(center.x, center.y, 0) -// ); - -// MMFloorGroundTruthPoints* gtps = (MMFloorGroundTruthPoints*) curLayer; -// gtps->createGroundTruthPoint(gtp); - view->getTools().setMain(new ToolNewGroundTruth(view->getTools(), curLayer)); - } + void ToolBoxWidget::onNewEarthReg() { const Point2 center = view->getScaler().getCenter(); diff --git a/params/ToolBoxWidget.h b/params/ToolBoxWidget.h index 2ecc967..4ef2cac 100644 --- a/params/ToolBoxWidget.h +++ b/params/ToolBoxWidget.h @@ -39,6 +39,7 @@ private: QPushButton* btnMeasure; QPushButton* btnGround; + QPushButton* btnLine; QPushButton* btnWall; QPushButton* btnPillar; QPushButton* btnDoor; @@ -63,6 +64,7 @@ private slots: void onNewGround(); void onNewWall(); + void onNewLine(); void onNewPillar(); void onNewDoor(); void onNewObject(); diff --git a/res.qrc b/res.qrc index 0870d68..453c387 100644 --- a/res.qrc +++ b/res.qrc @@ -28,5 +28,6 @@ res/icons/save.svg res/icons/load.svg res/icons/objects.svg + res/icons/line.svg diff --git a/res/icons/line.svg b/res/icons/line.svg new file mode 100644 index 0000000..6ff0485 --- /dev/null +++ b/res/icons/line.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + +