added more cpp files for faster compile speeds
removed many obsolte elements many improvements and fixes
This commit is contained in:
251
mapview/2D/MV2DElementStair.cpp
Normal file
251
mapview/2D/MV2DElementStair.cpp
Normal 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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user