many changes :P

This commit is contained in:
kazu
2016-06-06 22:08:53 +02:00
parent db6b479d86
commit 6243165084
56 changed files with 4399 additions and 245 deletions

25
mapview/3D/MV3DElement.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef MV3DELEMENT_H
#define MV3DELEMENT_H
#include "MapView3D.h"
/**
* represents one drawable
* element shown within the MapView3D
*/
class MV3DElement {
public:
/** dtor */
virtual ~MV3DElement() {;}
public:
/** repaint me */
virtual void paintGL() = 0;
};
#endif // MV3DELEMENT_H

View File

@@ -0,0 +1,34 @@
#ifndef MV3DELEMENTACCESSPOINT_H
#define MV3DELEMENTACCESSPOINT_H
#include <Indoor/floorplan/v2/Floorplan.h>
#include "misc/Cube.h"
#include "MV3DElement.h"
class MV3DElementAccessPoint : public MV3DElement {
Floorplan::Floor* f;
Floorplan::AccessPoint* ap;
public:
/** ctor */
MV3DElementAccessPoint(Floorplan::Floor* f, Floorplan::AccessPoint* ap) : f(f), ap(ap) {
;
}
protected:
/** repaint me */
void paintGL() override {
Cube cube(ap->getPos(f), 0.5);
cube.paintGL();
}
};
#endif // MV3DELEMENTACCESSPOINT_H

View File

@@ -0,0 +1,4 @@
#ifndef MV3DELEMENTFLOOROBSTACLEPILLAR_H
#define MV3DELEMENTFLOOROBSTACLEPILLAR_H
#endif // MV3DELEMENTFLOOROBSTACLEPILLAR_H

View File

@@ -0,0 +1,86 @@
#ifndef MV3DELEMENTFLOOROBSTACLEWALL_H
#define MV3DELEMENTFLOOROBSTACLEWALL_H
#include <Indoor/floorplan/v2/Floorplan.h>
#include "MV3DElement.h"
class MV3DElementFloorObstacleWall : public MV3DElement {
Floorplan::Floor* f;
Floorplan::FloorObstacleLine* fo;
public:
/** ctor */
MV3DElementFloorObstacleWall(Floorplan::Floor* f, Floorplan::FloorObstacleLine* fo) : f(f), fo(fo) {
;
}
protected:
Point3 cross(Point3 u, Point3 v) {
float x = u.y*v.z - u.z*v.y;
float y = u.z*v.x - u.x*v.z;
float z = u.x*v.y - u.y*v.x;
return Point3(x,y,z);
}
/** repaint me */
void paintGL() override {
float y1 = f->atHeight;
float y2 = y1+f->height;
Point3 p1 = Point3(fo->from.x, y1, fo->from.y);
Point3 p2 = Point3(fo->to.x, y1, fo->to.y);
Point3 p3 = Point3(fo->to.x, y2, fo->to.y);
Point3 p4 = Point3(fo->from.x, y2, fo->from.y);
Point3 v1 = p2-p1;
Point3 v2 = p3-p1;
Point3 n = cross(v1, v2);
n/=n.length();
// align normals to virtual viewport
Point3 view(99,99,99);
if ((view-n).length() > (view+n).length()) {n = -n;}
if (fo->type == Floorplan::ObstacleType::WALL) {
// fill the wall
glColor3f(0.75, 0.75, 0.75);
glDisable(GL_CULL_FACE);
glBegin(GL_QUADS);
glNormal3f(n.x, n.y, n.z);
glVertex3f(p1.x, p1.y, p1.z);
glVertex3f(p2.x, p2.y, p2.z);
glVertex3f(p3.x, p3.y, p3.z);
glVertex3f(p4.x, p4.y, p4.z);
glEnd();
glEnable(GL_CULL_FACE);
}
glColor3f(0,0,0);
// glDisable(GL_LIGHTING);
// glBegin(GL_LINE_STRIP);
// glVertex3f(p1.x, p1.y, p1.z);
// glVertex3f(p2.x, p2.y, p2.z);
// glVertex3f(p3.x, p3.y, p3.z);
// glVertex3f(p4.x, p4.y, p4.z);
// glVertex3f(p1.x, p1.y, p1.z);
// glEnd();
// glEnable(GL_LIGHTING);
}
};
#endif // MV3DELEMENTFLOOROBSTACLEWALL_H

View File

@@ -0,0 +1,71 @@
#ifndef MV3DELEMENTFLOOROUTLINE_H
#define MV3DELEMENTFLOOROUTLINE_H
#include <Indoor/floorplan/v2/Floorplan.h>
#include "misc/Cube.h"
#include "MV3DElement.h"
#include "../../lib/gpc/gpc.h"
#include "misc/Polygon.h"
class MV3DElementFloorOutline : public MV3DElement {
Floorplan::Floor* f;
Floorplan::FloorOutline* out;
public:
/** ctor */
MV3DElementFloorOutline(Floorplan::Floor* f, Floorplan::FloorOutline* out) : f(f), out(out) {
;
}
protected:
/** repaint me */
void paintGL() override {
std::vector<gpc_polygon> add;
std::vector<gpc_polygon> rem;
std::vector<Floorplan::FloorOutlinePolygon*> polys = *out;
Polygon pol;
for (Floorplan::FloorOutlinePolygon* poly : polys) {
switch (poly->method) {
case Floorplan::OutlineMethod::ADD: pol.add(poly->poly); break;
case Floorplan::OutlineMethod::REMOVE: pol.remove(poly->poly); break;
default: throw 1;
}
}
std::vector<std::vector<Point3>> trias = pol.get(f->atHeight);
glColor3f(0.2, 0.2, 0.2);
glDisable(GL_CULL_FACE);
for (const std::vector<Point3>& tria : trias) {
glBegin(GL_TRIANGLE_STRIP);
for (const Point3& p3 : tria) {
glVertex3f(p3.x, p3.z, p3.y);
}
glEnd();
}
glEnable(GL_CULL_FACE);
}
};
#endif // MV3DELEMENTFLOOROUTLINE_H

View File

@@ -0,0 +1,53 @@
#ifndef MV3DELEMENTFLOOROUTLINEPOLYGON_H
#define MV3DELEMENTFLOOROUTLINEPOLYGON_H
#include <Indoor/floorplan/v2/Floorplan.h>
#include "misc/Cube.h"
#include "MV3DElement.h"
class MV3DElementFloorOutlinePolygon : public MV3DElement {
Floorplan::Floor* f;
Floorplan::FloorOutlinePolygon* poly;
public:
/** ctor */
MV3DElementFloorOutlinePolygon(Floorplan::Floor* f, Floorplan::FloorOutlinePolygon* poly) : f(f), poly(poly) {
;
}
protected:
/** repaint me */
void paintGL() override {
glDisable(GL_CULL_FACE);
switch (poly->method) {
case Floorplan::OutlineMethod::ADD:
glColor3f(1,1,1);
break;
case Floorplan::OutlineMethod::REMOVE:
glColor3f(0.2, 0.2, 0.2);
break;
}
glBegin(GL_POLYGON);
glNormal3f(0,1,0);
for (Point2 p2 : poly->poly.points) {
Point3 p3(p2.x, p2.y, f->atHeight);
glVertex3f(p3.x, p3.z, p3.y);
}
glEnd();
glEnable(GL_CULL_FACE);
}
};
#endif // MV3DELEMENTFLOOROUTLINEPOLYGON_H

194
mapview/3D/MapView3D.cpp Normal file
View File

@@ -0,0 +1,194 @@
#include "MapView3D.h"
#include "../model/MapModelElement.h"
#include "../model/MapModel.h"
#include "../3DGrid/GridModel.h"
#include "../3DGrid/GridRenderer.h"
MapView3D::MapView3D(QWidget *parent) : QGLWidget(parent) {
rot.x = 45;
rot.y = 0;
rot.z = 45;
center.x = 0;
center.y = 0;
center.z = 0;
scale.x = 0.05f;
scale.y = 0.05f;
scale.z = 0.05f;
}
void MapView3D::initializeGL() {
//setFormat(QGLFormat(QGL::SampleBuffers));
QGLWidget::initializeGL();
// culling, lighting, depth-test, ...
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glShadeModel(GL_SMOOTH);
glEnable(GL_MULTISAMPLE);
// glEnable(GL_LINE_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
GLfloat light0_position [] = {+5, 5, +5, 1};
GLfloat light1_position [] = {-5, 5, -5, 1};
glLightfv ( GL_LIGHT0, GL_POSITION, light0_position );
glLightfv ( GL_LIGHT1, GL_POSITION, light1_position );
GLfloat light_diffuse []={ 0.7, 0.7, 0.7, 1.0 };
glLightfv ( GL_LIGHT0, GL_DIFFUSE, light_diffuse );
glLightfv ( GL_LIGHT1, GL_DIFFUSE, light_diffuse );
// otherwise scaling the scene kills lighting normals!
glEnable(GL_NORMALIZE);
// allow using glColor3(r,g,b)
glEnable(GL_COLOR_MATERIAL);
// GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
// GLfloat mat_shininess[] = { 50.0 };
// glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
// glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
// background color
qglClearColor(Qt::white);
}
void MapView3D::paintGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// 3) scale
glScalef(scale.x, scale.y, scale.z);
// 2) rotate around center
glRotatef(rot.x, 1.0, 0.0, 0.0);
glRotatef(rot.z, 0.0, 1.0, 0.0);
glRotatef(rot.y, 0.0, 0.0, 1.0);
// 1) post translate (mouse moving)
glTranslatef(center.x, center.z, center.y);
// 0) swap the y axis
//glScalef(+1, -1, +1);
// // 1) translate into center
// glTranslatef(tra.x, tra.y, tra.z);
draw();
}
void MapView3D::resizeGL(int width, int height) {
//int side = qMin(width, height);
//glViewport((width - side) / 2, (height - side) / 2, side, side);
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
#ifdef QT_OPENGL_ES_1
//glOrthof(-2, +2, -2, +2, 1.0, 15.0);
#else
//glOrtho(-2, +2, -2, +2, 1.0, 25.0);
//glFrustum(-1,1, -1,1, 0.1,20);
viewport.size.x = 2.0f;
viewport.size.y = 2.0f * height / width;
const float w = viewport.size.x;
const float h = viewport.size.y;
glOrtho(-w, +w, -h, +h, -20, +20);
//glFrustum(+w, -w, -h, +h, -20, +20);
#endif
glMatrixMode(GL_MODELVIEW);
}
void MapView3D::mousePressEvent(QMouseEvent* e) {
mouse.btn = e->button();
mouse.x = e->x();
mouse.y = e->y();
update();
}
void MapView3D::mouseMoveEvent(QMouseEvent* e) {
float dx = mouse.x - e->x();
float dy = mouse.y - e->y();
if (mouse.btn == 1) {
rot.z -= dx/2.0f; // upward
rot.x -= dy/2.0f;
} else if (mouse.btn == 4) {
Point3 vec(-dx / width() * 2 * viewport.size.x, 0, dy / height() * 2 * viewport.size.y);
vec = vec.rot(rot.x/180*M_PI, rot.y/180*M_PI, rot.z/180*M_PI);
vec /= scale;
center += vec;
}
mouse.x = e->x();
mouse.y = e->y();
update();
}
void MapView3D::mouseReleaseEvent(QMouseEvent* e) {
update();
}
void MapView3D::wheelEvent(QWheelEvent* e) {
float f = e->delta() / 120.0f;
scale *= (f > 0) ? (2) : (0.5);
update();
}
void MapView3D::showFloorplan() {
if (gridModel) {delete gridModel; gridModel = nullptr;}
update();
}
void MapView3D::showGrid() {
if (gridModel) {delete gridModel; gridModel = nullptr;}
GridModel* gm = new GridModel();
Floorplan::IndoorMap* im = getModel()->getMap();
gm->rebuild(im);
this->gridModel = gm;
update();
}
void MapView3D::draw() {
if (gridModel) {
// show grid
GridRenderer renderer(gridModel->getGrid());
renderer.paintGL();
} else {
// show floorplan
for (MapModelElement* el : getModel()->getVisibleElements()) {
if (el->getMV3D()) {el->getMV3D()->paintGL();}
}
}
}

72
mapview/3D/MapView3D.h Normal file
View File

@@ -0,0 +1,72 @@
#ifndef MAPVIEW3D_H
#define MAPVIEW3D_H
#include <QtWidgets>
#include <QtOpenGL>
#include <Indoor/geo/Point3.h>
class MapModel;
class GridModel;
class MapView3D : public QGLWidget {
Q_OBJECT
public:
MapView3D(QWidget* parent = 0);
/** set the underlying data-model */
void setModel(MapModel* mdl) {
this->model = mdl;
update();
}
/** get the underlying data-model */
MapModel* getModel() {return model;}
/** show 3D rendered floorplan */
void showFloorplan();
/** show 3D rendered grid derived from the floorplan */
void showGrid();
private:
/** the underlying data-model */
MapModel* model = nullptr;
GridModel* gridModel = nullptr;
Point3 rot;
Point3 center;
Point3 scale;
struct Mouse {
int btn;
float x;
float y;
} mouse;
struct Viewport {
Point2 size;
} viewport;
protected:
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
void mousePressEvent(QMouseEvent* e);
void mouseMoveEvent(QMouseEvent* e);
void mouseReleaseEvent(QMouseEvent* e);
void wheelEvent(QWheelEvent* e);
private:
void draw();
};
#endif // MAPVIEW3D_H

82
mapview/3D/misc/Cube.h Normal file
View File

@@ -0,0 +1,82 @@
#ifndef CUBE_H
#define CUBE_H
#include <Indoor/geo/Point3.h>
#include <QtOpenGL>
class Cube {
private:
Point3 pos;
float size;
public:
Cube(Point3 pos, float size) : pos(pos), size(size) {
}
void paintGL() {
float s = size;
glPushMatrix();
glTranslatef(pos.x, pos.z, pos.y);
glColor3f(0,0,1);
glBegin(GL_QUADS);
// bottom
glNormal3f(0,-1,0);
glVertex3f(+s, -s, -s);
glVertex3f(+s, -s, +s);
glVertex3f(-s, -s, +s);
glVertex3f(-s, -s, -s);
// top
glNormal3f(0,+1,0);
glVertex3f(-s, +s, -s);
glVertex3f(-s, +s, +s);
glVertex3f(+s, +s, +s);
glVertex3f(+s, +s, -s);
// left
glNormal3f(-1,0,0);
glVertex3f(-s, -s, -s);
glVertex3f(-s, -s, +s);
glVertex3f(-s, +s, +s);
glVertex3f(-s, +s, -s);
// right
glNormal3f(+1,0,0);
glVertex3f(+s, +s, -s);
glVertex3f(+s, +s, +s);
glVertex3f(+s, -s, +s);
glVertex3f(+s, -s, -s);
// front
glNormal3f(0,0,+1);
glVertex3f(+s, +s, +s);
glVertex3f(-s, +s, +s);
glVertex3f(-s, -s, +s);
glVertex3f(+s, -s, +s);
// rear
glNormal3f(0,0,-1);
glVertex3f(+s, -s, -s);
glVertex3f(-s, -s, -s);
glVertex3f(-s, +s, -s);
glVertex3f(+s, +s, -s);
glEnd();
glPopMatrix();
}
};
#endif // CUBE_H

109
mapview/3D/misc/Polygon.h Normal file
View File

@@ -0,0 +1,109 @@
#ifndef POLYGON_H
#define POLYGON_H
#include <Indoor/floorplan/v2/Floorplan.h>
#include "../../../lib/gpc/gpc.h"
class Polygon {
struct GPCPolygon : gpc_polygon {
GPCPolygon() {
// contour = (gpc_vertex_list*) calloc(0, 1024);
// contour->num_vertices = 0;
// contour->vertex = (gpc_vertex*) calloc(0, 1024);
// hole = (int*) calloc(0, 1024);
num_contours = 0;
contour = nullptr;
hole = nullptr;
}
~GPCPolygon() {
if (contour) {
gpc_free_polygon(this);
//free(contour->vertex); contour->vertex = nullptr;
}
free(contour); contour = nullptr;
free(hole); hole = nullptr;
}
GPCPolygon& operator = (const GPCPolygon& o) = delete;
GPCPolygon& operator = (GPCPolygon& o) {
this->contour = o.contour;
this->hole = o.hole;
this->num_contours = o.num_contours;
o.contour = nullptr;
o.hole = nullptr;
return *this;
}
};
private:
GPCPolygon state;
public:
void add(const Floorplan::Polygon2& poly) {
GPCPolygon cur = toGPC(poly);
//GPCPolygon out;
gpc_polygon_clip(GPC_UNION, &state, &cur, &state);
//state = out;
}
void remove(const Floorplan::Polygon2& poly) {
GPCPolygon cur = toGPC(poly);
//GPCPolygon out;
gpc_polygon_clip(GPC_DIFF, &state, &cur, &state);
//state = out;
}
std::vector<std::vector<Point3>> get(float z) {
gpc_tristrip res;
res.num_strips = 0;
res.strip = nullptr;
//res.strip = (gpc_vertex_list*) malloc(1024);
gpc_polygon_to_tristrip(&state, &res);
std::vector<std::vector<Point3>> trias;
for (int i = 0; i < res.num_strips; ++i) {
gpc_vertex_list lst = res.strip[i];
std::vector<Point3> tria;
for (int j = 0; j < lst.num_vertices; ++j) {
gpc_vertex& vert = lst.vertex[j];
Point3 p3(vert.x, vert.y, z);
tria.push_back(p3);
}
trias.push_back(tria);
}
gpc_free_tristrip(&res);
return std::move(trias);
}
private:
GPCPolygon toGPC(Floorplan::Polygon2 poly) {
std::vector<gpc_vertex> verts;
for (Point2 p2 : poly.points) {
gpc_vertex vert; vert.x = p2.x; vert.y = p2.y;
verts.push_back(vert);
}
GPCPolygon gpol;
gpc_vertex_list list;
list.num_vertices = verts.size();
list.vertex = verts.data();
gpc_add_contour(&gpol, &list, 0);
return gpol;
}
};
#endif // POLYGON_H

View File

@@ -0,0 +1,38 @@
#ifndef GRIDMODEL_H
#define GRIDMODEL_H
#include <Indoor/floorplan/v2/Floorplan.h>
#include <Indoor/grid/Grid.h>
#include <Indoor/grid/factory/v2/GridFactory.h>
#include "MyNode.h"
/**
* used for 3D grid rendering
*/
class GridModel {
private:
int gridSize_cm = 40;
Grid<MyNode> grid;
Floorplan::IndoorMap* im;
public:
GridModel() : grid(gridSize_cm) {
;
}
Grid<MyNode>* getGrid() {return &grid;}
void rebuild(Floorplan::IndoorMap* im) {
GridFactory<MyNode> fac(grid);
fac.build(im);
int i = 0;(void) i;
}
};
#endif // GRIDMODEL_H

View File

@@ -0,0 +1,40 @@
#ifndef GRIDRENDERER_H
#define GRIDRENDERER_H
#include "../3D/MV3DElement.h"
#include "MyNode.h"
#include <Indoor/grid/Grid.h>
class GridRenderer : public MV3DElement {
private:
Grid<MyNode>* grid;
public:
GridRenderer(Grid<MyNode>* grid) : grid(grid) {
;
}
virtual void paintGL() override {
glDisable(GL_LIGHTING);
glColor3f(0,0,0);
glPointSize(0.1f);
glBegin(GL_POINTS);
for (MyNode& n : *grid) {
glVertex3f(n.x_cm/100.0f, n.z_cm/100.0f*5, n.y_cm/100.0f);
}
glEnd();
glEnable(GL_LIGHTING);
}
};
#endif // GRIDRENDERER_H

10
mapview/3DGrid/MyNode.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef MYNODE_H
#define MYNODE_H
#include <Indoor/grid/Grid.h>
struct MyNode : public GridNode, public GridPoint {
MyNode(float x, float y, float z) : GridPoint(x,y,z) {;}
};
#endif // MYNODE_H

View File

@@ -44,7 +44,9 @@ void MapView2D::paintGL() {
// render all visible elements
qp.setRenderHint( QPainter::Antialiasing, true );
for (MapModelElement* el : getModel()->getVisibleElements()) {el->getMV2D()->paint(p);}
for (MapModelElement* el : getModel()->getVisibleElements()) {
if (el->getMV2D()) {el->getMV2D()->paint(p);}
}
qp.setRenderHint( QPainter::Antialiasing, false );
// foreground tools

View File

@@ -46,8 +46,13 @@ public:
}
// label
p.setPenBrush(Qt::black, Qt::NoBrush);
if (p.getScaler().getScale() >= 25) {
p.p->drawText(p.getScaler().xms(ap->pos.x) + 10, p.getScaler().yms(ap->pos.y) + 5, ap->mac.c_str());
const std::string str = ap->name + " (" + ap->name + ")";
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;
p.p->drawText(p.getScaler().xms(ap->pos.x) + 10, p.getScaler().yms(ap->pos.y) + 5, str.c_str());
}
}

View File

@@ -45,8 +45,13 @@ public:
}
// label
p.setPenBrush(Qt::black, Qt::NoBrush);
if (p.getScaler().getScale() >= 25) {
p.p->drawText(p.getScaler().xms(b->pos.x) + 10, p.getScaler().yms(b->pos.y) + 5, b->mac.c_str());
const std::string str = b->name + " (" + b->mac + ")";
p.p->drawText(p.getScaler().xms(b->pos.x) + 10, p.getScaler().yms(b->pos.y) + 5, str.c_str());
} else if (p.getScaler().getScale() >= 10) {
const std::string str = b->name;
p.p->drawText(p.getScaler().xms(b->pos.x) + 10, p.getScaler().yms(b->pos.y) + 5, str.c_str());
}
}

View File

@@ -87,7 +87,10 @@ public:
bbox.add(Point2(mx2, my2));
float opacity = p.p->opacity();
p.p->setOpacity(0.65f);
p.p->drawImage(QRectF(sx1, sy1-sh, sw, sh), img, QRectF(0,0,img.width(),img.height()));
p.p->setOpacity(opacity);
// selected endpoint(s)?
if (hasFocus()) {
@@ -125,9 +128,19 @@ public:
}
virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override {
(void) v;
(void) e;
const float s = (e->modifiers() & Qt::ShiftModifier) ? (1.0f) : (0.1f);
if (e->key() == Qt::Key_Up) {underlay->anchor += Point2(0, +s); return true;}
if (e->key() == Qt::Key_Down) {underlay->anchor += Point2(0, -s); return true;}
if (e->key() == Qt::Key_Left) {underlay->anchor += Point2(-s, 0); return true;}
if (e->key() == Qt::Key_Right) {underlay->anchor += Point2(+s, 0); return true;}
return false;
}

View File

@@ -0,0 +1,99 @@
#ifndef MV2DELEMENTPOI_H
#define MV2DELEMENTPOI_H
#include "MV2DElement.h"
#include "MapViewElementHelper.h"
#include <Indoor/floorplan/v2/Floorplan.h>
class MV2DElementPOI : public MV2DElement {
private:
bool sel = false;
Floorplan::POI* poi;
public:
/** ctor with the AP to render/edit */
MV2DElementPOI(Floorplan::POI* poi) : poi(poi) {;}
/** get the element's 3D bounding box */
BBox2 getBoundingBox() const override {
BBox2 bbox;
bbox.add(Point2(poi->pos.x, poi->pos.y));
bbox.grow(Point2(0.1, 0.1));
return bbox;
}
/** get the element's minimal distance (nearest whatsoever) to the given point */
float getMinDistanceXY(const Point2 p) const override {
return p.getDistance(poi->pos);
}
/** repaint me */
void paint(Painter& p) override {
if (sel) {
p.setPenBrush(Qt::black, CFG::SEL_COLOR);
p.drawCircle(poi->pos);
} else if (hasFocus()) {
p.setPenBrush(Qt::black, Qt::NoBrush);
p.drawCircle(poi->pos);
} else {
p.setPenBrush(Qt::gray, Qt::NoBrush);
p.drawCircle(poi->pos);
}
// label
p.setPenBrush(Qt::black, Qt::NoBrush);
if (p.getScaler().getScale() >= 10) {
const std::string str = poi->name;
p.p->drawText(p.getScaler().xms(poi->pos.x) + 10, p.getScaler().yms(poi->pos.y) + 5, str.c_str());
}
}
/** mouse pressed at the given point */
virtual void mousePressed(MapView2D* v, const Point2 p) override {
(void) v;
(void) p;
}
/** mouse moved to the given point */
virtual void mouseMove(MapView2D* v, const Point2 _p) override {
(void) v;
if (sel) {
const Point2 p = Scaler::snap(_p, CFG::MOVE_SNAP_SIZE_M);
poi->pos.x = p.x;
poi->pos.y = p.y;
}
}
/** mouse released */
virtual void mouseReleased(MapView2D* v, const Point2 _p) override {
(void) v;
(void) _p;
sel = true;
}
virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override {
(void) v;
(void) e;
return false;
}
virtual void onFocus() override {
}
virtual void onUnfocus() override {
sel = false;
}
};
#endif // MV2DELEMENTPOI_H

View File

@@ -1,21 +1,21 @@
#ifndef IHASATTRIBUTES_H
#define IHASATTRIBUTES_H
#include <string>
//#include <string>
class IHasAttributes {
//class IHasAttributes {
public:
//public:
/** set the value for the given key */
virtual void setAttribute(const std::string& key, const std::string& val) = 0;
// /** set the value for the given key */
// virtual void setAttribute(const std::string& key, const std::string& val) = 0;
/** get the value for the given key */
virtual const std::string& getAttribute(const std::string& key) const = 0;
// /** get the value for the given key */
// virtual const std::string& getAttribute(const std::string& key) const = 0;
/** get all attributes as map */
virtual const std::unordered_map<std::string, std::string> getAttributes() const = 0;
// /** get all attributes as map */
// virtual const std::unordered_map<std::string, std::string> getAttributes() const = 0;
};
//};
#endif // IHASATTRIBUTES_H

View File

@@ -1,17 +1,17 @@
#ifndef IHASFILE_H
#define IHASFILE_H
#include <string>
//#include <string>
class IHasFile {
//class IHasFile {
public:
//public:
virtual void setFileName(const std::string& file) = 0;
// virtual void setFileName(const std::string& file) = 0;
virtual const std::string& getFileName() const = 0;
// virtual const std::string& getFileName() const = 0;
};
//};
#endif // IHASFILE_H

View File

@@ -1,15 +1,15 @@
#ifndef IHASMAC_H
#define IHASMAC_H
#include <string>
//#include <string>
class IHasMAC {
public:
//class IHasMAC {
//public:
virtual void setMAC(const std::string& mac) = 0;
// virtual void setMAC(const std::string& mac) = 0;
virtual const std::string& getMAC() const = 0;
// virtual const std::string& getMAC() const = 0;
};
//};
#endif // IHASMAC_H

View File

@@ -2,13 +2,16 @@
#define IHASPARAMS_H
#include <Indoor/floorplan/v2/Floorplan.h>
#include <QVariant>
#include <Indoor/geo/Point2.h>
#include <Indoor/geo/Point3.h>
enum class ParamType {
INT,
FLOAT,
STRING,
FILE,
POINT2,
POINT3,
};
class ParamValue {
@@ -17,6 +20,7 @@ private:
union {
int _int;
float _float;
float _arr[3];
};
std::string _str;
@@ -29,7 +33,11 @@ public:
void setValue(const std::string& val) {_str = val;}
void setValue(float val) {_float = val;}
void setValue(int val) {_int = val;}
void setValue(Point2 p) {_arr[0] = p.x; _arr[1] = p.y;}
void setValue(Point3 p) {_arr[0] = p.x; _arr[1] = p.y; _arr[2] = p.z;}
Point2 toPoint2() const {return Point2(_arr[0], _arr[1]);}
Point3 toPoint3() const {return Point3(_arr[0], _arr[1], _arr[2]);}
std::string toString() const {return _str;}
float toFloat() const {return _float;}
int toInt() const {return _int;}

View File

@@ -1,19 +1,18 @@
#ifndef IHASPOSITION3D_H
#define IHASPOSITION3D_H
//#include <Indoor/geo/Point3.h>
#include <Indoor/geo/Point3.h>
//class IHasPosition3D {
class IHasPosition3D {
//public:
public:
// /** set the element's 3D position */
// virtual void setPosition3D(const Point3& p) = 0;
/** set the element's 3D position */
virtual void setPosition3D(const Point3& p) = 0;
// /** get the element's 3D position */
// virtual Point3 getPosition3D() const = 0;
/** get the element's 3D position */
virtual Point3 getPosition3D() const = 0;
};
//};
#endif // IHASPOSITION3D_H

View File

@@ -6,7 +6,10 @@
#include "MMFloorObstacles.h"
#include "MMFloorAccessPoints.h"
#include "MMFloorBeacons.h"
#include "MMFloorUnderlay.h"
#include "MMFloorUnderlays.h"
#include "MMFloorPOIs.h"
#include "IHasParams.h"
#include <Indoor/floorplan/v2/Floorplan.h>
@@ -16,7 +19,7 @@
* floor-layer containing one floor
* and its outline, obstacles, access-points, ...
*/
class MMFloor : public MapLayer, public IHasName {
class MMFloor : public MapLayer, public IHasParams {
private:
@@ -28,11 +31,13 @@ public:
/** ctor. existing floor */
MMFloor(MapLayer* parent, Floorplan::Floor* floor) : MapLayer(parent, MapLayerType::FLOOR), floor(floor) {
new MMFloorOutline(this, floor);
new MMFloorUnderlays(this, floor);
elements.push_back(new MMFloorOutline(this, floor));
new MMFloorObstacles(this, floor);
new MMFloorAccessPoints(this, floor);
new MMFloorBeacons(this, floor);
new MMFloorUnderlay(this, floor);
new MMFloorPOIs(this, floor);
}
@@ -47,9 +52,29 @@ public:
std::string getLayerName() const override {return floor->name;}
virtual int getNumParams() const override {
return 1;
}
virtual void setName(const std::string& name) {this->floor->name = name;}
virtual const std::string& getName() const {return this->floor->name;}
virtual Param getParamDesc(const int idx) const override {
switch(idx) {
case 0: return Param("anem", ParamType::STRING);
}
throw 1;
}
virtual ParamValue getParamValue(const int idx) const override {
switch(idx) {
case 0: return floor->name;
}
throw 1;
}
virtual void setParamValue(const int idx, const ParamValue& val) const override {
switch(idx) {
case 0: floor->name = val.toString(); break;
}
}
};

View File

@@ -2,35 +2,61 @@
#define MAPVIEWELEMENTACCESSPOINT_H
#include "MapModelElement.h"
#include "IHasMAC.h"
#include "IHasName.h"
#include "IHasParams.h"
#include "../elements/MV2DElementAccessPoint.h"
#include "../3D/MV3DElementAccessPoint.h"
#include <Indoor/floorplan/v2/Floorplan.h>
class MMFloorAccessPoint : public MapModelElement, public IHasMAC, public IHasName {
class MMFloorAccessPoint : public MapModelElement, public IHasParams {
private:
Floorplan::Floor* floor;
Floorplan::AccessPoint* ap;
MV2DElementAccessPoint mv2d;
MV3DElementAccessPoint mv3d;
public:
MMFloorAccessPoint(MapLayer* parent, Floorplan::Floor* floor, Floorplan::AccessPoint* ap) :
MapModelElement(parent), floor(floor), ap(ap), mv2d(ap) {
MapModelElement(parent), floor(floor), ap(ap), mv2d(ap), mv3d(floor, ap) {
}
virtual void setMAC(const std::string& mac) override {ap->mac = mac;}
virtual const std::string& getMAC() const override {return ap->mac;}
virtual int getNumParams() const override {
return 3;
}
virtual void setName(const std::string& name) override {ap->name = name;}
virtual const std::string& getName() const override {return ap->name;}
virtual Param getParamDesc(const int idx) const override {
switch(idx) {
case 0: return Param("name", ParamType::STRING);
case 1: return Param("MAC", ParamType::STRING);
case 2: return Param("Position", ParamType::POINT3);
}
throw 1;
}
virtual ParamValue getParamValue(const int idx) const override {
switch(idx) {
case 0: return ap->name;
case 1: return ap->mac;
case 2: return ap->pos;
}
throw 1;
}
virtual void setParamValue(const int idx, const ParamValue& val) const override {
switch(idx) {
case 0: ap->name = val.toString(); break;
case 1: ap->mac = val.toString(); break;
case 2: ap->pos = val.toPoint3(); break;
}
}
MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;}
MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;}
void deleteMe() const override {
parent->removeElement(this);

View File

@@ -22,7 +22,7 @@ public:
// add all APs
for (Floorplan::AccessPoint* ap : floor->accesspoints) {
new MMFloorAccessPoint(this, floor, ap);
elements.push_back(new MMFloorAccessPoint(this, floor, ap));
}
}

View File

@@ -2,14 +2,13 @@
#define MAPVIEWELEMENTIBEACON_H
#include "MapModelElement.h"
#include "IHasMAC.h"
#include "IHasName.h"
#include "IHasParams.h"
#include "../elements/MV2DElementBeacon.h"
#include <Indoor/floorplan/v2/Floorplan.h>
class MMFloorBeacon : public MapModelElement, public IHasMAC, public IHasName {
class MMFloorBeacon : public MapModelElement, public IHasParams {
private:
@@ -20,14 +19,38 @@ private:
public:
MMFloorBeacon(MapLayer* parent, Floorplan::Floor* floor, Floorplan::Beacon* b) : MapModelElement(parent), floor(floor), b(b), mv2d(b) {
;
}
virtual void setMAC(const std::string& mac) override {b->mac = mac;}
virtual const std::string& getMAC() const override {return b->mac;}
virtual int getNumParams() const override {
return 3;
}
virtual void setName(const std::string& name) override {b->name = name;}
virtual const std::string& getName() const override {return b->name;}
virtual Param getParamDesc(const int idx) const override {
switch(idx) {
case 0: return Param("name", ParamType::STRING);
case 1: return Param("MAC", ParamType::STRING);
case 2: return Param("Position", ParamType::POINT3);
}
throw 1;
}
virtual ParamValue getParamValue(const int idx) const override {
switch(idx) {
case 0: return b->name;
case 1: return b->mac;
case 2: return b->pos;
}
throw 1;
}
virtual void setParamValue(const int idx, const ParamValue& val) const override {
switch(idx) {
case 0: b->name = val.toString(); break;
case 1: b->mac = val.toString(); break;
case 2: b->pos = val.toPoint3(); break;
}
}
MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;}

View File

@@ -22,7 +22,7 @@ public:
// add all Beacons
for (Floorplan::Beacon* b : floor->beacons) {
new MMFloorBeacon(this, floor, b);
elements.push_back(new MMFloorBeacon(this, floor, b));
}
}

View File

@@ -8,6 +8,7 @@
#include "IHasObstacleType.h"
#include "../elements/MV2DElementFloorObstacleLine.h"
#include "../3D/MV3DElementFloorObstacleWall.h"
#include <Indoor/floorplan/v2/Floorplan.h>
@@ -19,11 +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(fo) {
MapModelElement(parent), mf(mf), fo(fo), mv2d(fo), mv3d(mf,fo) {
}
@@ -34,6 +36,7 @@ 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);

View File

@@ -3,6 +3,7 @@
#include "MapLayer.h"
#include "MMFloorOutlinePolygon.h"
#include "../3D/MV3DElementFloorOutline.h"
#include <Indoor/floorplan/v2/Floorplan.h>
@@ -10,17 +11,20 @@
/**
* layer containing all elements describing a floor's outline
*/
class MMFloorOutline : public MapLayer {
class MMFloorOutline : public MapLayer, public MapModelElement {
private:
/** the underlying model */
Floorplan::Floor* floor;
MV3DElementFloorOutline mv3d;
public:
/** ctor with the underlying model */
MMFloorOutline(MapLayer* parent, Floorplan::Floor* floor) : MapLayer(parent, MapLayerType::FLOOR_GROUND), floor(floor) {
MMFloorOutline(MapLayer* parent, Floorplan::Floor* floor) :
MapLayer(parent, MapLayerType::FLOOR_GROUND), MapModelElement(parent), floor(floor), mv3d(floor, &floor->outline) {
// the outline
for (Floorplan::FloorOutlinePolygon* poly : floor->outline) {
@@ -29,6 +33,8 @@ public:
}
MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;}
/** get the corresponding floor from the underlying model */
Floorplan::Floor* getFloor() {return floor;}

View File

@@ -1,10 +1,11 @@
#ifndef MAPELEMENTFLOORGROUND_H
#define MAPELEMENTFLOORGROUND_H
#include "IHasName.h"
#include "IHasParams.h"
#include "MapModelElement.h"
#include "../elements/MV2DElementFloorOutlinePolygon.h"
#include "../3D/MV3DElementFloorOutlinePolygon.h"
#include <Indoor/floorplan/v2/Floorplan.h>
@@ -12,18 +13,20 @@
/**
* describes one polygon within a floor's outline
*/
class MMFloorOutlinePolygon : public MapModelElement, public IHasName {
class MMFloorOutlinePolygon : public MapModelElement, public IHasParams {
private:
Floorplan::Floor* mf;
Floorplan::FloorOutlinePolygon* fo;
MV2DElementFloorOutlinePolygon mv2d;
MV3DElementFloorOutlinePolygon mv3d;
public:
/** ctor */
MMFloorOutlinePolygon(MapLayer* parent, Floorplan::Floor* mf, Floorplan::FloorOutlinePolygon* fo) : MapModelElement(parent), mf(mf), fo(fo), mv2d(*fo) {
MMFloorOutlinePolygon(MapLayer* parent, Floorplan::Floor* mf, Floorplan::FloorOutlinePolygon* fo) :
MapModelElement(parent), mf(mf), fo(fo), mv2d(*fo), mv3d(mf, fo) {
;
}
@@ -32,10 +35,32 @@ public:
Floorplan::OutlineMethod getMethod() const {return fo->method;}
void setMethod(const Floorplan::OutlineMethod m) {this->fo->method = m;}
void setName(const std::string& name) override {fo->name = name;}
const std::string& getName() const override {return fo->name;}
MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;}
//MV3DElement* getMV3D() const override {return (MV3DElement*) &mv3d;}
virtual int getNumParams() const override {
return 1;
}
virtual Param getParamDesc(const int idx) const override {
switch(idx) {
case 0: return Param("anem", ParamType::STRING);
}
throw 1;
}
virtual ParamValue getParamValue(const int idx) const override {
switch(idx) {
case 0: return fo->name;
}
throw 1;
}
virtual void setParamValue(const int idx, const ParamValue& val) const override {
switch(idx) {
case 0: fo->name = val.toString(); break;
}
}
void deleteMe() const override {

View File

@@ -0,0 +1,65 @@
#ifndef MMFLOORPOI_H
#define MMFLOORPOI_H
#include "MapModelElement.h"
#include "IHasParams.h"
#include "../elements/MV2DElementPOI.h"
#include <Indoor/floorplan/v2/Floorplan.h>
class MMFloorPOI : public MapModelElement, public IHasParams {
private:
Floorplan::Floor* floor;
Floorplan::POI* poi;
MV2DElementPOI mv2d;
public:
MMFloorPOI(MapLayer* parent, Floorplan::Floor* floor, Floorplan::POI* poi) : MapModelElement(parent), floor(floor), poi(poi), mv2d(poi) {
;
}
virtual int getNumParams() const override {
return 3;
}
virtual Param getParamDesc(const int idx) const override {
switch(idx) {
case 0: return Param("name", ParamType::STRING);
case 1: return Param("type", ParamType::INT);
case 2: return Param("position", ParamType::POINT2);
}
throw 1;
}
virtual ParamValue getParamValue(const int idx) const override {
switch(idx) {
case 0: return poi->name;
case 1: return (int) poi->type;
case 2: return poi->pos;
}
throw 1;
}
virtual void setParamValue(const int idx, const ParamValue& val) const override {
switch(idx) {
case 0: poi->name = val.toString(); break;
case 1: poi->type = (Floorplan::POIType) val.toInt(); break;
case 2: poi->pos = val.toPoint2(); break;
}
}
MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;}
void deleteMe() const override {
parent->removeElement(this);
floor->pois.erase(std::remove(floor->pois.begin(), floor->pois.end(), poi), floor->pois.end());
}
};
#endif // MMFLOORPOI_H

View File

@@ -0,0 +1,46 @@
#ifndef MMFLOORPOIS_H
#define MMFLOORPOIS_H
#include "MapLayer.h"
#include "MMFloorPOI.h"
#include <Indoor/floorplan/v2/Floorplan.h>
/**
* layer that contains all of one floor's POIs
*/
class MMFloorPOIs : public MapLayer {
Floorplan::Floor* floor;
public:
/** ctor with the floor */
MMFloorPOIs(MapLayer* parent, Floorplan::Floor* floor) : MapLayer(parent, MapLayerType::FLOOR_POIS), floor(floor) {
// the POIs
for (Floorplan::POI* poi : floor->pois) {
elements.push_back(new MMFloorPOI(this, floor, poi));
}
}
/** get the corresponding floor from the underlying model */
Floorplan::Floor* getFloor() {return floor;}
//TODO: check
void createPOI(Floorplan::POI* poi) {
// add to underlying model
floor->pois.push_back(poi);
// add to myself as element
elements.push_back(new MMFloorPOI(this, floor, poi));
}
std::string getLayerName() const override {return "POIs";}
};
#endif // MMFLOORPOIS_H

View File

@@ -2,7 +2,6 @@
#define MMFLOORUNDERLAYIMAGE_H
#include "IHasFile.h"
#include "IHasParams.h"
#include "MapModelElement.h"
@@ -12,7 +11,7 @@
/**
* add an external image file as underlay (to copy it onto the map)
*/
class MMFloorUnderlayImage : public MapModelElement, public MapLayer, public IHasFile, public IHasParams {
class MMFloorUnderlayImage : public MapModelElement, public IHasParams {
private:
@@ -24,19 +23,15 @@ private:
public:
/** ctor */
MMFloorUnderlayImage(MapLayer* parent, Floorplan::Floor* floor, Floorplan::UnderlayImage* img) : MapModelElement(parent), MapLayer(parent, MapLayerType::FLOOR_UNDERLAY), floor(floor), img(img), mv2d(img) {
setFileName(img->filename);
MMFloorUnderlayImage(MapLayer* parent, Floorplan::Floor* floor, Floorplan::UnderlayImage* img) : MapModelElement(parent), floor(floor), img(img), mv2d(img) {
;
}
virtual void setFileName(const std::string& file) {img->filename = file;}
virtual const std::string& getFileName() const {return img->filename;}
void setAnchor(const Point2 anchor) {img->anchor = anchor;}
Point2 getAnchor() const {return img->anchor;}
void setScale(const float x, const float y) {img->scaleX = x; img->scaleY = y;}
virtual std::string getLayerName() const override {return "underlay";}
MV2DElement* getMV2D() const override {return (MV2DElement*) &mv2d;}
@@ -44,13 +39,14 @@ public:
;
}
int getNumParams() const override {return 3;}
int getNumParams() const override {return 4;}
virtual Param getParamDesc(const int idx) const override {
switch (idx) {
case 0: return Param("file", ParamType::FILE);
case 1: return Param("scale X", ParamType::FLOAT);
case 2: return Param("scale Y", ParamType::FLOAT);
case 3: return Param("Anchor", ParamType::POINT2);
default: throw 1;
}
}
@@ -60,15 +56,17 @@ public:
case 0: return ParamValue(img->filename);
case 1: return ParamValue(img->scaleX);
case 2: return ParamValue(img->scaleY);
case 3: return ParamValue(img->anchor);
default: throw 1;
}
}
virtual void setParamValue(const int idx, const ParamValue& val) const override {
switch (idx) {
case 0: img->filename = val.toString();
case 1: img->scaleX = val.toFloat();
case 2: img->scaleY = val.toFloat();
case 0: img->filename = val.toString(); break;
case 1: img->scaleX = val.toFloat(); break;
case 2: img->scaleY = val.toFloat(); break;
case 3: img->anchor = val.toPoint2(); break;
default: throw 1;
}
}

View File

@@ -10,7 +10,7 @@
/**
* add an external file as underlay (to copy it onto the map)
*/
class MMFloorUnderlay : public MapLayer {
class MMFloorUnderlays : public MapLayer {
private:
@@ -19,7 +19,7 @@ private:
public:
/** ctor */
MMFloorUnderlay(MapLayer* parent, Floorplan::Floor* floor) : MapLayer(parent, MapLayerType::FLOOR_UNDERLAY), floor(floor) {
MMFloorUnderlays(MapLayer* parent, Floorplan::Floor* floor) : MapLayer(parent, MapLayerType::FLOOR_UNDERLAYS), floor(floor) {
// the underlays
for (Floorplan::UnderlayImage* img : floor->underlays) {

View File

@@ -17,7 +17,8 @@ enum class MapLayerType {
FLOOR_OBSTACLES,
FLOOR_BEACONS,
FLOOR_ACCESS_POINTS,
FLOOR_UNDERLAY,
FLOOR_UNDERLAYS,
FLOOR_POIS,
};

View File

@@ -68,6 +68,11 @@ public:
}
/** get the constructed map */
Floorplan::IndoorMap* getMap() const {
return im;
}
/** get the map's root-layer containing all other layers */
MapLayer* getRootLayer() { return root; }

View File

@@ -5,6 +5,7 @@
#include "MapLayer.h"
class MV2DElement;
class MV3DElement;
class MapModelElement {
@@ -21,10 +22,13 @@ public:
virtual ~MapModelElement() {;}
/** get the 2D interaction class for this element */
virtual MV2DElement* getMV2D() const = 0;
virtual MV2DElement* getMV2D() const {return nullptr;}
/** get the 3D interaction class for this element */
virtual MV3DElement* getMV3D() const {return nullptr;}
/** delete this element from the model */
virtual void deleteMe() const = 0;
virtual void deleteMe() const {;}
/** get the parent element */
MapLayer* getParent() const {return parent;}

View File

@@ -5,12 +5,23 @@
class ToolMapGrid : public Tool {
private:
bool show = true;
public:
virtual void keyPressEvent(MapView2D* m, QKeyEvent* e) {
(void) m;
if (e->key() == Qt::Key_NumberSign) { show = !show; }
}
void paintBefore(MapView2D* m, Painter& p) override {
(void) m;
if (!show) {return;}
static const QColor cB(250,250,250);
static const QColor cN(235,235,235);
static const QColor c0(128,128,128);

View File

@@ -86,11 +86,9 @@ public:
p.p->drawLine(mouseX, 0, mouseX, rs);
p.setPenBrush(Qt::black, Qt::NoBrush);
char buf[128];
// y-axis
p.p->setClipRect(ry);
for (float y = r.y0; y <= r.y1; y += step) {
@@ -131,6 +129,7 @@ public:
p.p->drawText(xMajor+2, 18, buf);
}
p.p->setClipping(false);
}

View File

@@ -39,6 +39,7 @@ public:
// get all elements with bounding-box matchings
std::vector<MapModelElement*> possible;
for (MapModelElement* el : m->getModel()->getSelectedLayerElements()) {
if (!el->getMV2D()) {continue;}
BBox2 bbox = el->getMV2D()->getBoundingBox(); // elements 3D bbox
bbox.grow(Point2(g, g)); // grow a little (needed for straight lines)
if (bbox.contains(p2)) {possible.push_back(el);} // intersection?