focused elements always on top

indicate connected walls
fixes int/float issues
refactoring
This commit is contained in:
2018-07-22 17:33:55 +02:00
parent c4fce6c90d
commit 423fbfc545
6 changed files with 121 additions and 69 deletions

View File

@@ -7,7 +7,7 @@
#include <Indoor/floorplan/v2/Floorplan.h> #include <Indoor/floorplan/v2/Floorplan.h>
#include <stdio.h> #include <stdio.h>
MV2DElementFloorObstacleLine::MV2DElementFloorObstacleLine(Floorplan::FloorObstacleLine* fo) : fo(fo) { MV2DElementFloorObstacleLine::MV2DElementFloorObstacleLine(Floorplan::Floor* f, Floorplan::FloorObstacleLine* fo) : f(f), fo(fo) {
; ;
} }
@@ -22,29 +22,47 @@ ClickDist MV2DElementFloorObstacleLine::getMinDistanceXY(const Point2 p) const {
return MapElementHelper::getLineDistanceXY(fo->from, fo->to, p); return MapElementHelper::getLineDistanceXY(fo->from, fo->to, p);
} }
void MV2DElementFloorObstacleLine::paint(Painter& 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;
}
// DEPRECATED void MV2DElementFloorObstacleLine::paint(Painter& p) {
// // 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 // convert wall's thickness from meter to pixels
const float thickness_px = p.s.ms(fo->thickness_m); const float thickness_px = p.s.ms(fo->thickness_m);
// remember the old pen
//QPen pen = p.getPen();
// see notes within MapElementHelper! // see notes within MapElementHelper!
// lines only get thicker, but not longer! // lines only get thicker, but not longer!
p.setPenBrush(MapElementHelper::getPen(fo->material, fo->type, hasFocus(), thickness_px), Qt::NoBrush); p.setPenBrush(MapElementHelper::getPen(fo->material, fo->type, hasFocus(), thickness_px), Qt::NoBrush);
// draw the wall itself
p.drawLine(fo->from, fo->to); p.drawLine(fo->from, fo->to);
// reset the old pen3 const bool c1 = isConnected(fo->from, f, fo);
//p.setPen(pen); 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);}
}
// length info // length info
if (hasFocus()) { if (hasFocus()) {
@@ -55,11 +73,6 @@ void MV2DElementFloorObstacleLine::paint(Painter& p) {
} }
// DEPRECATED
// // available endpoints
// p.drawNode(fo->from, hasFocus(), hasFocus() && selectedUserIdx == 0);
// p.drawNode(fo->to, hasFocus(), hasFocus() && selectedUserIdx == 1);
} }
void MV2DElementFloorObstacleLine::onFocus() { void MV2DElementFloorObstacleLine::onFocus() {

View File

@@ -10,12 +10,13 @@ class MV2DElementFloorObstacleLine : public MV2DElement, public HasMoveableNodes
private: private:
Floorplan::Floor* f;
Floorplan::FloorObstacleLine* fo; Floorplan::FloorObstacleLine* fo;
public: public:
/** ctor */ /** ctor */
MV2DElementFloorObstacleLine(Floorplan::FloorObstacleLine* fo); MV2DElementFloorObstacleLine(Floorplan::Floor* f, 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;

View File

@@ -39,8 +39,8 @@ MapView2D::MapView2D(QWidget* parent) : QOpenGLWidget(parent) {
void MapView2D::paintGL() { void MapView2D::paintGL() {
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); // QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glClear(GL_COLOR_BUFFER_BIT); // f->glClear(GL_COLOR_BUFFER_BIT);
QPainter qp(this); QPainter qp(this);
Painter p(s, &qp, width(), height()); Painter p(s, &qp, width(), height());
@@ -50,19 +50,34 @@ void MapView2D::paintGL() {
tools.paintBefore(this, p); tools.paintBefore(this, p);
std::vector<MV2DElement*> normal;
std::vector<MV2DElement*> focused;
// get all visible elements that can be rendered
// group them whether they currently have focus or not
for (MapModelElement* el : getModel()->getVisibleElements()) {
if (el->getMV2D()) {
if (el->getMV2D()->hasFocus()) {
focused.push_back(el->getMV2D());
} else {
normal.push_back(el->getMV2D());
}
}
}
qp.setRenderHint( QPainter::Antialiasing, true ); qp.setRenderHint( QPainter::Antialiasing, true );
// render all visible elements. 1st run // 2 layer rendering (paint, paintAfter), only UNFOCUSED elements
for (MapModelElement* el : getModel()->getVisibleElements()) { for (MV2DElement* e : normal) {e->paint(p);}
if (el->getMV2D()) {el->getMV2D()->paint(p);} for (MV2DElement* e : normal) {e->paintAfter(p);}
}
// render all visible elements. 2nd run // 2 layer rendering (paint, paintAfter), only FOCUSED elements
for (MapModelElement* el : getModel()->getVisibleElements()) { for (MV2DElement* e : focused) {e->paint(p);}
if (el->getMV2D()) {el->getMV2D()->paintAfter(p);} for (MV2DElement* e : focused) {e->paintAfter(p);}
}
qp.setRenderHint( QPainter::Antialiasing, false ); //qp.setRenderHint( QPainter::Antialiasing, false );
// foreground tools // foreground tools
tools.paintAfter(this, p); tools.paintAfter(this, p);

View File

@@ -18,6 +18,12 @@ int Painter::width() {return w;}
int Painter::height() {return h;} int Painter::height() {return h;}
float Painter::radToDeg(const float rad) const {
return rad * 180 / M_PI;
}
bool Painter::isVisible(const Point2 p) { bool Painter::isVisible(const Point2 p) {
const float x = s.xms(p.x); const float x = s.xms(p.x);
const float y = s.yms(p.y); const float y = s.yms(p.y);
@@ -36,69 +42,82 @@ 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(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))); 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) { 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(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))); 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 { void Painter::drawLine(const float x1, const float y1, const float x2, const float y2) {
return rad * 180 / M_PI; p->drawLine(QPointF(s.xms(x1), s.yms(y1)), QPointF(s.xms(x2), s.yms(y2)));
} }
void Painter::drawArc(const Point2 center, const float radius, const float startAngleRad, const float spanAngleRad) { void Painter::drawArc(const Point2 center, const float radius, const float startAngleRad, const float spanAngleRad) {
const float wh = s.ms(radius) * 2; const float wh = s.ms(radius) * 2;
const float x1 = s.xms(center.x) - wh/2; const float x1 = s.xms(center.x) - wh/2;
const float y1 = s.yms(center.y) - wh/2; const float y1 = s.yms(center.y) - wh/2;
p->drawArc(x1, y1, wh, wh, radToDeg(startAngleRad)*16, radToDeg(spanAngleRad)*16); const QRectF rect(x1, y1, wh, wh);
p->drawArc(rect, radToDeg(startAngleRad)*16, radToDeg(spanAngleRad)*16);
//p->drawArc(x1, y1, wh, wh, radToDeg(startAngleRad)*16, radToDeg(spanAngleRad)*16);
} }
/** draw a dot at the given map coordinates */
void Painter::drawDot(const Point2 center) {
//int r = 1;
//p->drawEllipse(QPointF(s.xms(center.x)-r, s.yms(center.y)-r), 2*r, 2*r);
p->drawPoint(QPointF(s.xms(center.x), s.yms(center.y)));
}
void Painter::drawCircle(const Point3 center) { void Painter::drawCircle(const Point3 center) {
int r = 5; int r = 5;
p->drawEllipse(s.xms(center.x)-r, s.yms(center.y)-r, 2*r, 2*r); p->drawEllipse(QPointF(s.xms(center.x), s.yms(center.y)), r, r);
} }
void Painter::drawCircle(const Point2 center) { void Painter::drawCircle(const Point2 center) {
int r = 5; int r = 5;
p->drawEllipse(s.xms(center.x)-r, s.yms(center.y)-r, 2*r, 2*r); p->drawEllipse(QPointF(s.xms(center.x), s.yms(center.y)), r, 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) { void Painter::drawCircle(const Point2 center, const float size_m) {
int r = s.ms(size_m); int r = s.ms(size_m);
p->drawEllipse(s.xms(center.x)-r, s.yms(center.y)-r, 2*r, 2*r); p->drawEllipse(QPointF(s.xms(center.x), s.yms(center.y)), r, r);
} }
void Painter::drawCircle_px(const Point2 center, const float size_px) { void Painter::drawCircle_px(const Point2 center, const float size_px) {
int r = size_px; int r = size_px;
p->drawEllipse(s.xms(center.x)-r, s.yms(center.y)-r, 2*r, 2*r); p->drawEllipse(QPointF(s.xms(center.x), s.yms(center.y)), r, r);
} }
void Painter::drawNode(Point2 pt, bool focused, bool selected) { void Painter::drawNode(Point2 pt, bool focused, bool selected) {
float rs = 0.05; float rs = 4;
if (selected) {setPenBrush(Qt::black, Qt::gray); rs = 0.08;} if (selected) {setPenBrush(Qt::black, Qt::gray); rs*=2;}
else if (focused) {setPenBrush(Qt::black, Qt::white); rs = 0.08;} else if (focused) {setPenBrush(Qt::black, Qt::white); rs*=2;}
else {setPenBrush(Qt::black, Qt::NoBrush); rs = 0.04;} else {setPenBrush(Qt::black, Qt::NoBrush); rs*=1;}
const float s = this->s.getScale(); const float s = this->s.getScale();
if (s > 10) {drawCircle(pt, rs);} // only at a certain zoom level if (s > 25) {drawCircle_px(pt, rs);} // only at a certain zoom level
else if (s > 10) {drawCircle_px(pt, 1);} // 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) { void Painter::drawRect(const Point2 p1, const Point2 p2) {
drawRect(p1.x, p1.y, p2.x, p2.y); drawRect(p1.x, p1.y, p2.x, p2.y);
} }
void Painter::drawRect(const float x1, const float y1, const float x2, const float y2) { void Painter::drawRect(const float x1, const float y1, const float x2, const float y2) {
float w = x2-x1; const float w = x2-x1;
float h = y1-y2; const float h = y1-y2;
p->drawRect(s.xms(x1), s.yms(y1), s.ms(w), s.ms(h)); const QRectF rect(s.xms(x1), s.yms(y1), s.ms(w), s.ms(h));
p->drawRect(rect);
//p->drawRect(s.xms(x1), s.yms(y1), s.ms(w), s.ms(h));
} }
void Painter::drawRect(const Point2 center) { void Painter::drawRect(const Point2 center) {
@@ -107,7 +126,7 @@ void Painter::drawRect(const Point2 center) {
} }
void Painter::drawText(const Point2 pos, const std::string& text) { void Painter::drawText(const Point2 pos, const std::string& text) {
p->drawText(s.xms(pos.x), s.yms(pos.y), text.c_str()); p->drawText(QPointF(s.xms(pos.x), s.yms(pos.y)), text.c_str());
} }
void Painter::drawPolygon(const std::vector<Point2>& points) { void Painter::drawPolygon(const std::vector<Point2>& points) {

View File

@@ -15,6 +15,8 @@ struct Material {
const std::vector<Material> mats = { const std::vector<Material> mats = {
Material(255,0,0,255), // error
Material(0,128,0,255), // ground outdoor Material(0,128,0,255), // ground outdoor
Material(64,64,64,255), // ground outdoor Material(64,64,64,255), // ground outdoor
Material(105,105,105,255), // stair Material(105,105,105,255), // stair
@@ -37,21 +39,23 @@ const std::vector<Material> mats = {
int FloorplanRendererModel::getMaterial(const Ray3D::Obstacle3D& o) const { int FloorplanRendererModel::getMaterial(const Ray3D::Obstacle3D& o) const {
if (o.type == Ray3D::Obstacle3D::Type::GROUND_OUTDOOR) {return 0;} if (o.type == Ray3D::Obstacle3D::Type::ERROR) {return 0;}
if (o.type == Ray3D::Obstacle3D::Type::GROUND_INDOOR) {return 1;}
if (o.type == Ray3D::Obstacle3D::Type::STAIR) {return 2;}
if (o.type == Ray3D::Obstacle3D::Type::HANDRAIL) {return 3;}
if (o.type == Ray3D::Obstacle3D::Type::OBJECT) {return 11;}
if (o.type == Ray3D::Obstacle3D::Type::DOOR && o.mat == Floorplan::Material::GLASS) {return 4;} if (o.type == Ray3D::Obstacle3D::Type::GROUND_OUTDOOR) {return 1;}
if (o.type == Ray3D::Obstacle3D::Type::DOOR) {return 5;} if (o.type == Ray3D::Obstacle3D::Type::GROUND_INDOOR) {return 2;}
if (o.type == Ray3D::Obstacle3D::Type::STAIR) {return 3;}
if (o.type == Ray3D::Obstacle3D::Type::HANDRAIL) {return 4;}
if (o.type == Ray3D::Obstacle3D::Type::OBJECT) {return 12;}
if (o.mat == Floorplan::Material::CONCRETE) {return 6;} if (o.type == Ray3D::Obstacle3D::Type::DOOR && o.mat == Floorplan::Material::GLASS) {return 5;}
if (o.mat == Floorplan::Material::GLASS) {return 7;} if (o.type == Ray3D::Obstacle3D::Type::DOOR) {return 6;}
if (o.mat == Floorplan::Material::METALLIZED_GLAS) {return 8;}
if (o.mat == Floorplan::Material::WOOD) {return 9;} if (o.mat == Floorplan::Material::CONCRETE) {return 7;}
if (o.mat == Floorplan::Material::DRYWALL) {return 10;} if (o.mat == Floorplan::Material::GLASS) {return 8;}
if (o.mat == Floorplan::Material::METALLIZED_GLAS) {return 9;}
if (o.mat == Floorplan::Material::WOOD) {return 10;}
if (o.mat == Floorplan::Material::DRYWALL) {return 11;}
return 12; return 12;

View File

@@ -26,7 +26,7 @@ public:
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(mf, fo) {//, mv3d(mf,fo) {
} }