geometry changes/fixes/new features

new grid walkers + fixes
new test-cases
worked on step/and turn detection
android offline-data-reader
worked on vap-grouping
This commit is contained in:
2016-09-07 10:16:51 +02:00
parent a203305628
commit d283d9b326
27 changed files with 976 additions and 333 deletions

View File

@@ -18,18 +18,7 @@
#include <functional>
/** listen for events during the build process */
class GridFactoryListener {
public:
virtual void onGridBuildUpdateMajor(const std::string& what) = 0;
virtual void onGridBuildUpdateMajor(const int cnt, const int cur) = 0;
virtual void onGridBuildUpdateMinor(const std::string& what) = 0;
virtual void onGridBuildUpdateMinor(const int cnt, const int cur) = 0;
};
#include "GridFactoryListener.h"
template <typename T> class GridFactory {
@@ -156,7 +145,7 @@ public:
GridNodeBBox bbox(GridPoint(x_cm, y_cm, z_cm), helper.gridSize());
// slightly grow the bbox to ensure even obstacles that are directly aligned to the bbox are hit
bbox.grow(0.012345);
bbox.grow(0.42345);
if (intersects(bbox, floor)) {continue;}
// add to the grid
@@ -170,7 +159,7 @@ public:
}
// connect the g
connectAdjacent(z_cm);
connectAdjacent(floor, z_cm);
}
@@ -186,6 +175,9 @@ public:
if (listener) {listener->onGridBuildUpdateMinor(total, ++cur);}
}
// cleanup
stairs.finalize();
}
@@ -273,7 +265,7 @@ public:
}
/** connect all neighboring nodes located on the given height-plane */
void connectAdjacent(const float z_cm) {
void connectAdjacent(const Floorplan::Floor* floor, const float z_cm) {
Log::add(name, "connecting all adjacent nodes at height " + std::to_string(z_cm), false);
Log::tick();
@@ -285,7 +277,7 @@ public:
if (n1.z_cm != z_cm) {continue;}
// connect the node with its neighbors
connectAdjacent(n1);
connectAdjacent(floor, n1);
}
@@ -293,8 +285,13 @@ public:
}
/** connect the given node with its neighbors */
void connectAdjacent(T& n1) {
/**
* connect the given node with its neighbors.
* even though a node has a neighbor, it might still be blocked by an obstacle:
* e.g. a 45° wall directly between nodes. a neighbor exists, but is unreachable due to the wall.
* we thus perform an additional intersection check with all obstacles within the floor the node n1 belongs to
*/
void connectAdjacent(const Floorplan::Floor* floor, T& n1) {
const int gridSize_cm = grid.getGridSize_cm();
@@ -313,6 +310,7 @@ public:
// does the grid contain the potential neighbor?
const T* n2 = grid.getNodePtrFor(p);
if (n2 != nullptr) {
if (isBlocked(floor, n1, *n2)) {continue;} // is there a (e.g. small) obstacle between the two?
grid.connectUniDir(n1, *n2); // UNI-dir connection as EACH node is processed!
}
@@ -479,7 +477,46 @@ private:
}
}
return false;
}
/**
* normally, the algorithm will not try to connect two nodes that are neighbors but have an obstacle between them.
* however, especially for 45° obstacles it might happen that a neighbor exists but is blocked by an obstacle.
* we thus need this additional check to ensure everything is fine... even though it needs performance...
*/
static inline bool isBlocked(const Floorplan::Floor* floor, const GridPoint& n1, const GridPoint& n2) {
// (obstacles use meter, while the nodes are in centimeter!
const Point2 p1_m = n1.inMeter().xy();
const Point2 p2_m = n2.inMeter().xy();
const Line2 lineNodes(p1_m, p2_m);
// process each obstacle
for (Floorplan::FloorObstacle* fo : floor->obstacles) {
// depends on the type of obstacle
if (dynamic_cast<Floorplan::FloorObstacleLine*>(fo)) {
const Floorplan::FloorObstacleLine* line = (Floorplan::FloorObstacleLine*) fo;
const Line2 lineObstacle(line->from, line->to);
if (lineObstacle.getSegmentIntersection(lineNodes)) {return true;}
} else if (dynamic_cast<Floorplan::FloorObstacleCircle*>(fo)) {
throw Exception("should not happen");
} else if (dynamic_cast<Floorplan::FloorObstacleDoor*>(fo)) {
// DOORS ARE NOT AN OBSTACLE
} else {
throw Exception("TODO: not yet implemented obstacle type");
}
}
return false;
}
/** does the bbox intersect with any of the floor's walls? */