diff --git a/IndoorMap.pro b/IndoorMap.pro index 3db9253..894d672 100644 --- a/IndoorMap.pro +++ b/IndoorMap.pro @@ -65,6 +65,7 @@ HEADERS += MainWindow.h \ mapview/2D/MV2DElementBeacon.h \ mapview/2D/MV2DElementAccessPoint.h \ mapview/2D/MV2DElementFloorObstacleCircle.h \ + mapview/2D/MV2DElementFloorObstacleDoor.h \ mapview/2D/MapViewElementHelper.h \ mapview/2D/MV2DElementFloorUnderlay.h \ mapview/2D/MV2DElementPOI.h \ @@ -128,7 +129,8 @@ HEADERS += MainWindow.h \ mapview/model/MMFloorElevators.h \ mapview/model/MMFloorElevator.h \ params/LayerTree.h \ - params/EditFields.h + params/EditFields.h \ + mapview/2D/ClickDist.h FORMS += MainWindow.ui diff --git a/MainController.cpp b/MainController.cpp index ecea8f7..e4ec417 100644 --- a/MainController.cpp +++ b/MainController.cpp @@ -94,7 +94,8 @@ MainController::MainController() { //mapModel->load("/mnt/data/workspaces/Indoor/tests/data/WalkHeadingMap.xml"); //mapModel->load("/mnt/data/workspaces/IPIN2016/IPIN2016/competition/maps/test.xml"); //mapModel->load("/mnt/vm/workspace/IRGame/IndoorServer/maps/map6.xml"); - //mapModel->load("/mnt/vm/workspace/IRGame/IndoorServer/maps/keller.xml"); + //mapModel->load("/mnt/vm/workspace/IRGame/IndoorServer/maps/keller1.xml"); + mapModel->load("/mnt/vm/workspace/IRGame/IndoorServer/maps/wohnung3.xml"); //mapModel->startEmpty(); diff --git a/mapview/2D/ClickDist.h b/mapview/2D/ClickDist.h new file mode 100644 index 0000000..b8886b2 --- /dev/null +++ b/mapview/2D/ClickDist.h @@ -0,0 +1,59 @@ +#ifndef CLICKDIST_H +#define CLICKDIST_H + +enum class ClickDistType { + UNKNOWN, + DIRECT, // e.g. distance between cursor and an edge-point, POI, AP, Beacon, ... + CUT, // e.g. distance between cursor and an obstacle-line +}; + +/** describes distances between mouse-cursor and objects within the 2D view */ +struct ClickDist { + + /** distance in pixels */ + float dst_px; + + /** distance type */ + ClickDistType type; + + + /** ctor */ + ClickDist(const float dst_px, const ClickDistType type) : dst_px(dst_px), type(type) {;} + + /** max-dummy */ + static ClickDist max() {return ClickDist(9999999, ClickDistType::UNKNOWN);} + + + /** distance comparison */ + bool operator < (const ClickDist o) const { + return (this->dst_px * this->mod()) < (o.dst_px * o.mod()); + } + + /** multiply by constant */ + ClickDist operator * (const float val) const {return ClickDist(dst_px*val, type);} + +// /** weighted distance comparison based on ClickDistType */ +// bool compare(const ClickDist o) const { +// return ((*this)*mod()) < (o*o.mod()); +// } + +private: + + /** + * artificially modify the distance based on the given type. + * this enhances the selection in cases of equal distance + * like a POI residing dirctly one a line + */ + float mod() const { + switch (type) { + case ClickDistType::UNKNOWN: return 1.1; + case ClickDistType::CUT: return 1.0; + case ClickDistType::DIRECT: return 0.7; + default: throw "code error"; + } + } + +}; + + +#endif // CLICKDIST_H diff --git a/mapview/2D/MV2DElement.h b/mapview/2D/MV2DElement.h index 32cf049..6785b57 100644 --- a/mapview/2D/MV2DElement.h +++ b/mapview/2D/MV2DElement.h @@ -9,6 +9,8 @@ #include #include +#include "ClickDist.h" + /** * represents one drawable, selectable, editable, ... * element shown within the MapView2D @@ -29,7 +31,7 @@ public: virtual BBox2 getBoundingBox() const = 0; /** get the element's minimal distance (nearest whatsoever) to the given point */ - virtual float getMinDistanceXY(const Point2 p) const = 0; + virtual ClickDist getMinDistanceXY(const Point2 p) const = 0; /** repaint me */ virtual void paint(Painter& p) = 0; diff --git a/mapview/2D/MV2DElementAccessPoint.h b/mapview/2D/MV2DElementAccessPoint.h index a9d3c37..8c6b132 100644 --- a/mapview/2D/MV2DElementAccessPoint.h +++ b/mapview/2D/MV2DElementAccessPoint.h @@ -31,8 +31,8 @@ public: } /** get the element's minimal distance (nearest whatsoever) to the given point */ - float getMinDistanceXY(const Point2 p) const override { - return p.getDistance(ap->pos.xy()); + ClickDist getMinDistanceXY(const Point2 p) const override { + return ClickDist(p.getDistance(ap->pos.xy()), ClickDistType::DIRECT); } /** repaint me */ @@ -61,7 +61,7 @@ public: p.setPenBrush(Qt::black, Qt::NoBrush); p.drawDot(ap->pos.xy()); if (p.getScaler().getScale() >= 25) { - const std::string str = ap->name + " (" + ap->name + ")"; + 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()); } else if (p.getScaler().getScale() >= 10) { const std::string str = ap->name; diff --git a/mapview/2D/MV2DElementBeacon.h b/mapview/2D/MV2DElementBeacon.h index 34503d3..d836def 100644 --- a/mapview/2D/MV2DElementBeacon.h +++ b/mapview/2D/MV2DElementBeacon.h @@ -29,8 +29,8 @@ public: } /** get the element's minimal distance (nearest whatsoever) to the given point */ - float getMinDistanceXY(const Point2 p) const override { - return p.getDistance(b->pos.xy()); + ClickDist getMinDistanceXY(const Point2 p) const override { + return ClickDist(p.getDistance(b->pos.xy()), ClickDistType::DIRECT); } /** repaint me */ diff --git a/mapview/2D/MV2DElementElevator.h b/mapview/2D/MV2DElementElevator.h index 3533ef8..aedd7b1 100644 --- a/mapview/2D/MV2DElementElevator.h +++ b/mapview/2D/MV2DElementElevator.h @@ -30,11 +30,11 @@ public: } /** get the element's minimal distance (nearest whatsoever) to the given point */ - float getMinDistanceXY(const Point2 p) const override { + ClickDist getMinDistanceXY(const Point2 p) const override { // std::vector points = elevator->getPoints().points; // points.push_back(elevator->center); // auto it minEl = std::min_element(points.begin(), points.end(), - return p.getDistance(elevator->center); + return ClickDist(p.getDistance(elevator->center), ClickDistType::DIRECT); } /** repaint me */ diff --git a/mapview/2D/MV2DElementFloorObstacleCircle.h b/mapview/2D/MV2DElementFloorObstacleCircle.h index f8c7bf4..cb33604 100644 --- a/mapview/2D/MV2DElementFloorObstacleCircle.h +++ b/mapview/2D/MV2DElementFloorObstacleCircle.h @@ -27,8 +27,11 @@ public: } /** get the element's minimal distance (nearest whatsoever) to the given point */ - float getMinDistanceXY(const Point2 p) const override { - return std::min(p.getDistance(getSelPoints()[0]), p.getDistance(getSelPoints()[1])); + 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])); } diff --git a/mapview/2D/MV2DElementFloorObstacleDoor.h b/mapview/2D/MV2DElementFloorObstacleDoor.h index d219054..63d2880 100644 --- a/mapview/2D/MV2DElementFloorObstacleDoor.h +++ b/mapview/2D/MV2DElementFloorObstacleDoor.h @@ -27,7 +27,7 @@ public: } /** get the element's minimal distance (nearest whatsoever) to the given point */ - float getMinDistanceXY(const Point2 p) const override { + ClickDist getMinDistanceXY(const Point2 p) const override { return MapElementHelper::getLineDistanceXY(fo->from, fo->to, p); } @@ -69,6 +69,12 @@ public: p.drawCircle(fo->to); } + // obstacle length + if (hasFocus()) { + p.setPenBrush(Qt::black, Qt::NoBrush); + p.drawLength(fo->from, fo->to, fo->from.getDistance(fo->to)); + } + } diff --git a/mapview/2D/MV2DElementFloorObstacleLine.h b/mapview/2D/MV2DElementFloorObstacleLine.h index 4aab07c..ac515bf 100644 --- a/mapview/2D/MV2DElementFloorObstacleLine.h +++ b/mapview/2D/MV2DElementFloorObstacleLine.h @@ -6,6 +6,7 @@ #include "MapViewElementHelper.h" #include +#include class MV2DElementFloorObstacleLine : public MV2DElement, public HasMoveableNodes { @@ -27,7 +28,7 @@ public: } /** get the element's minimal distance (nearest whatsoever) to the given point */ - float getMinDistanceXY(const Point2 p) const override { + ClickDist getMinDistanceXY(const Point2 p) const override { return MapElementHelper::getLineDistanceXY(fo->from, fo->to, p); } @@ -60,37 +61,49 @@ public: 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)); + } else { //p.setPenBrush(Qt::NoPen, Qt::black); - p.drawCircle(fo->from, 0.1); - p.drawCircle(fo->to, 0.1); + p.drawCircle_px(fo->from, 3); + p.drawCircle_px(fo->to, 3); } - } - - void paintDoor(Painter& p) { - - QPen pen; - pen.setColor(QColor(0.5,0.5,0.5)); - pen.setStyle(Qt::PenStyle::DotLine); - p.setPenBrush(pen, Qt::NoBrush); - // opening indicator - const float open = M_PI / 4; - const float len = (fo->to - fo->from).length(); - const float angle1 = std::atan2(fo->to.y-fo->from.y, fo->to.x-fo->from.x); - const float angle2 = angle1 + open; - const Point2 pOpen = Point2( std::cos(angle2) * len, std::sin(angle2) * len ) + fo->from; - - p.drawLine(fo->from, fo->to); - p.drawLine(fo->from, pOpen); - - p.drawArc(fo->from, len, angle1, open); - //p.drawLine(fo->to, pOpen); } +// void paintDoor(Painter& p) { + +// QPen pen; +// pen.setColor(QColor(0.5,0.5,0.5)); +// pen.setStyle(Qt::PenStyle::DotLine); +// p.setPenBrush(pen, Qt::NoBrush); + + +// // opening indicator +// const float open = M_PI / 4; +// const float len = (fo->to - fo->from).length(); +// const float angle1 = std::atan2(fo->to.y-fo->from.y, fo->to.x-fo->from.x); +// const float angle2 = angle1 + open; +// const Point2 pOpen = Point2( std::cos(angle2) * len, std::sin(angle2) * len ) + fo->from; + +// p.drawLine(fo->from, fo->to); +// p.drawLine(fo->from, pOpen); + +// p.drawArc(fo->from, len, angle1, open); +// //p.drawLine(fo->to, pOpen); + +// // obstacle length +// p.setPenBrush(Qt::black, Qt::NoBrush); +// p.drawLength(fo->from, fo->to, fo->from.getDistance(fo->to)); + +// } + void onFocus() override { ; } diff --git a/mapview/2D/MV2DElementFloorOutlinePolygon.h b/mapview/2D/MV2DElementFloorOutlinePolygon.h index f9bd0a4..aaa655b 100644 --- a/mapview/2D/MV2DElementFloorOutlinePolygon.h +++ b/mapview/2D/MV2DElementFloorOutlinePolygon.h @@ -26,12 +26,12 @@ public: } /** get the element's minimal distance (nearest whatsoever) to the given point */ - float getMinDistanceXY(const Point2 p) const override { - float min = 999999; + 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 float dst = MapElementHelper::getLineDistanceXY(p1, p2, p); + const ClickDist dst = MapElementHelper::getLineDistanceXY(p1, p2, p); if (dst < min) {min = dst;} } return min; diff --git a/mapview/2D/MV2DElementFloorUnderlay.h b/mapview/2D/MV2DElementFloorUnderlay.h index 79a3d1a..bf324dd 100644 --- a/mapview/2D/MV2DElementFloorUnderlay.h +++ b/mapview/2D/MV2DElementFloorUnderlay.h @@ -42,9 +42,9 @@ public: } /** get the element's minimal distance (nearest whatsoever) to the given point */ - float getMinDistanceXY(const Point2 p) const override { + ClickDist getMinDistanceXY(const Point2 p) const override { (void) p; - return CFG::SEL_THRESHOLD_SIZE_PX; // we do not know the distance from the image + return ClickDist(CFG::SEL_THRESHOLD_SIZE_PX, ClickDistType::UNKNOWN); // we do not know the distance from the image } virtual void onFocus() override { diff --git a/mapview/2D/MV2DElementPOI.h b/mapview/2D/MV2DElementPOI.h index 839e2ad..aee6d92 100644 --- a/mapview/2D/MV2DElementPOI.h +++ b/mapview/2D/MV2DElementPOI.h @@ -30,8 +30,8 @@ public: } /** get the element's minimal distance (nearest whatsoever) to the given point */ - float getMinDistanceXY(const Point2 p) const override { - return p.getDistance(poi->pos); + ClickDist getMinDistanceXY(const Point2 p) const override { + return ClickDist(p.getDistance(poi->pos), ClickDistType::DIRECT); } /** repaint me */ diff --git a/mapview/2D/MV2DElementStair.h b/mapview/2D/MV2DElementStair.h index 05c196f..2dc2962 100644 --- a/mapview/2D/MV2DElementStair.h +++ b/mapview/2D/MV2DElementStair.h @@ -35,11 +35,11 @@ public: } /** get the element's minimal distance (nearest whatsoever) to the given point */ - float getMinDistanceXY(const Point2 p) const override { + ClickDist getMinDistanceXY(const Point2 p) const override { auto comp = [p] (const Floorplan::StairPart& p1, const Floorplan::StairPart& p2) { - const float d1 = MapElementHelper::getLineDistanceXY(p1.start.xy(), p1.end.xy(), p); - const float d2 = MapElementHelper::getLineDistanceXY(p2.start.xy(), p2.end.xy(), p); + 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; }; diff --git a/mapview/2D/MapViewElementHelper.h b/mapview/2D/MapViewElementHelper.h index 6ad31ba..f2c76d2 100644 --- a/mapview/2D/MapViewElementHelper.h +++ b/mapview/2D/MapViewElementHelper.h @@ -11,6 +11,8 @@ #include +#include "ClickDist.h" + /** configuration */ namespace CFG { const float MOVE_SNAP_SIZE_M = 0.1f; // in meter (= map-space) @@ -33,7 +35,7 @@ public: * move l into dst * and calculate the cut-point between l and (p1, p2) */ - static float 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); @@ -46,20 +48,21 @@ public: // 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 - return cut.getDistance(dst); - - } else { - - // no cut detected - const float d1 = p1.getDistance(dst); - const float d2 = p2.getDistance(dst); - return std::min(d1, d2); + cutDist.dst_px = cut.getDistance(dst); } + // 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) { diff --git a/mapview/2D/Painter.h b/mapview/2D/Painter.h index b2a9f07..1f4ebac 100644 --- a/mapview/2D/Painter.h +++ b/mapview/2D/Painter.h @@ -69,6 +69,11 @@ public: 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)); } @@ -115,6 +120,16 @@ public: 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) { + if (p1.x < p2.x) {swap(p1, p2);} + const Point2 center_m = (p1 + p2) / 2; + Point2 dir_px = (p2 - p1).perpendicular().normalized() * 5; + 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); } diff --git a/mapview/3D/MV3DElementAccessPoint.h b/mapview/3D/MV3DElementAccessPoint.h index 1d87fb9..45af97e 100644 --- a/mapview/3D/MV3DElementAccessPoint.h +++ b/mapview/3D/MV3DElementAccessPoint.h @@ -24,7 +24,7 @@ protected: /** repaint me */ void paintGL() override { - Cube cube(ap->getPos(f), 0.5); + Cube cube(ap->getPos(f), 0.25); cube.paintGL(); }