fixed grid factory issue with stairs

added some sanity checks
This commit is contained in:
2017-05-24 17:51:29 +02:00
parent fdc47215ac
commit 34271b5cb7
3 changed files with 83 additions and 16 deletions

View File

@@ -42,6 +42,8 @@ private:
Elevators<T> elevators;
std::vector<GridPoint> withinRemovePolygon;
bool _buildStairs = true;
bool _removeIsolated = true;
@@ -60,6 +62,14 @@ public:
void setRemoveIsolated(const bool remove) {this->_removeIsolated = remove;}
/** does the given grid-node have a stair-neighbor? */
bool hasStairNeighbor(const T& node) const {
for (const T& n : grid.neighbors(node)) {
if (n.getType() == GridNode::TYPE_STAIR) {return true;}
}
return false;
}
/** build using the given map */
void build(const Floorplan::IndoorMap* map, GridFactoryListener* listener = nullptr) {
@@ -93,6 +103,27 @@ public:
}
}
// remove nodes within remove-OutlinePolygons
// this must happen AFTER stairs have been added, otherwise stairs might not be connectable due to removed/missing nodes.
// also, within this loop we prevent the deltion of nodes that are a direct neighbor of a stair!
// [otherwise the same thing would happen again!]
if (true) {
for (const GridPoint& gp : withinRemovePolygon) {
T* n = (T*) grid.getNodePtrFor(gp);
// delete if node is present and is no direct neighbor of a stair
if (n && !hasStairNeighbor(*n)) {
grid.remove(*n);
}
}
// remove all nodes that were just marked for removal
grid.cleanup();
}
// remove isolated nodes
if (_removeIsolated) {
if (listener) {listener->onGridBuildUpdateMajor("removing isolated nodes");}
@@ -114,31 +145,36 @@ public:
return bb;
}
enum class PartOfOutline {
NO,
INDOOR,
OUTDOOR,
struct PartOfOutline {
bool contained = false; // contained within at-least one polygon?
bool markedForRemove = false; // part of a "to-be-removed" polygon?
bool outdoor = false; // otherwise: indoor
};
/** get the part of outline the given location belongs to. currently: none, indoor, outdoor */
static PartOfOutline isPartOfFloorOutline(const int x_cm, const int y_cm, const Floorplan::FloorOutline& outline) {
// assume the point is not part of the outline
PartOfOutline res = PartOfOutline::NO;
PartOfOutline res;
res.contained = false;
res.markedForRemove = false;
// process every outline polygon
for (Floorplan::FloorOutlinePolygon* poly : outline) {
HelperPoly pol(*poly);
if (pol.contains(Point2(x_cm, y_cm))) {
// mark as "contained"
res.contained = true;
// belongs to a "remove" polygon? -> directly ignore this location!
if (poly->method == Floorplan::OutlineMethod::REMOVE) {
return PartOfOutline::NO;
res.markedForRemove = true;
}
// belongs to a "add" polygon? -> remember until all polygons were checked
// [might still belong to a "remove" polygon]
res = poly->outdoor ? PartOfOutline::OUTDOOR : PartOfOutline::INDOOR;
res.outdoor = poly->outdoor;
}
}
@@ -173,7 +209,7 @@ public:
// does the outline-polygon contain this position?
const PartOfOutline part = isPartOfFloorOutline(x_cm, y_cm, floor->outline);
if (part == PartOfOutline::NO) {continue;}
if (!part.contained) {continue;}
// check intersection with the floorplan
GridNodeBBox bbox(GridPoint(x_cm, y_cm, z_cm), helper.gridSize());
@@ -188,6 +224,11 @@ public:
updateType(t, part, bbox, floor);
grid.add(t);
// node part of remove-region?
// if so, remove >>AFTER<< stairs have been added
if (part.markedForRemove) {
withinRemovePolygon.push_back(t);
}
// debug
++numNodes;
@@ -395,7 +436,19 @@ public:
Log::add(name, "removing all nodes NOT connected to " + (std::string) n1, false);
Log::tick();
for (T& n2 : grid) {
if (set.find(n2.getIdx()) == set.end()) {grid.remove(n2);}
if (set.find(n2.getIdx()) == set.end()) {
// sanity check
// wouldn't make sense that a stair-node is removed..
// maybe something went wrong elsewhere???
Assert::notEqual(n2.getType(), GridNode::TYPE_STAIR, "detected an isolated stair?!");
Assert::notEqual(n2.getType(), GridNode::TYPE_ELEVATOR, "detected an isolated elevator?!");
//Assert::notEqual(n2.getType(), GridNode::TYPE_DOOR, "detected an isolated door?!");
// proceed ;)
grid.remove(n2);
}
}
Log::tock();
@@ -510,10 +563,10 @@ private:
static inline void updateType(T& t, const PartOfOutline part, const GridNodeBBox& bbox, const Floorplan::Floor* floor) {
// first, assume the type of the outline polygon
switch (part) {
case PartOfOutline::OUTDOOR: t.setType(GridNode::TYPE_OUTDOOR); break;
case PartOfOutline::INDOOR: t.setType(GridNode::TYPE_FLOOR); break;
default: throw Exception("should not happen");
if (part.outdoor) {
t.setType(GridNode::TYPE_OUTDOOR);
} else {
//t.setType(GridNode::TYPE_FLOOR);
}
// hereafter, process each obstacle and mark doors