split line(old) and wall(new)

added new walling
started working on windows
This commit is contained in:
k-a-z-u
2018-07-25 16:20:34 +02:00
parent 4938987063
commit 8017241c6e
14 changed files with 703 additions and 122 deletions

View File

@@ -7,6 +7,7 @@
#include <Indoor/floorplan/v2/Floorplan.h>
#include <stdio.h>
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<const Floorplan::FloorObstacleLine*>(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<const Floorplan::FloorObstacleLine*>(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<MoveableNode> 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);
}

View File

@@ -0,0 +1,292 @@
#include "MV2DElementFloorObstacleWall.h"
#include "MV2DElement.h"
#include "HasMoveableNodes.h"
#include "MapViewElementHelper.h"
#include <Indoor/floorplan/v2/Floorplan.h>
#include <stdio.h>
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::milliseconds>(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<const Floorplan::FloorObstacleWall*>(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<Floorplan::FloorObstacleWallDoor*> 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<Point2> 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<MoveableNode> MV2DElementFloorObstacleWall::getMoveableNodes() const {
std::vector<MoveableNode> 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 <iostream>
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;
}

View File

@@ -0,0 +1,45 @@
#ifndef MV2DELEMENTFLOOROBSTACLEWALL_H
#define MV2DELEMENTFLOOROBSTACLEWALL_H
#include "MV2DElement.h"
#include "HasMoveableNodes.h"
#include <Indoor/floorplan/v2/Floorplan.h>
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<MoveableNode> 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

View File

@@ -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<Floorplan::FloorObstacleLine, MMFloorObstacleLine> {
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

View File

@@ -3,9 +3,10 @@
#include "ToolNewElement.h"
#include "../../model/MMFloorObstacles.h"
#include "../../model/MMFloorObstacleLine.h"
#include "../../model/MMFloorObstacleWall.h"
class ToolNewWall : public ToolNewElement<Floorplan::FloorObstacleLine, MMFloorObstacleLine> {
/** new walls */
class ToolNewWall : public ToolNewElement<Floorplan::FloorObstacleWall, MMFloorObstacleWall> {
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);
}