From 7ec5fef69743f0ea57f8c0ce9927f3b5c9b7a5e2 Mon Sep 17 00:00:00 2001 From: FrankE Date: Sun, 12 Mar 2017 16:47:29 +0100 Subject: [PATCH] added "outdoor" support to floorplan and grid-nodes --- floorplan/v2/Floorplan.h | 10 ++--- floorplan/v2/FloorplanReader.h | 1 + floorplan/v2/FloorplanWriter.h | 1 + grid/GridNode.h | 2 + grid/factory/v2/GridFactory.h | 68 +++++++++++++++++++++++----------- 5 files changed, 55 insertions(+), 27 deletions(-) diff --git a/floorplan/v2/Floorplan.h b/floorplan/v2/Floorplan.h index d6d4ac0..cfdee4c 100644 --- a/floorplan/v2/Floorplan.h +++ b/floorplan/v2/Floorplan.h @@ -298,15 +298,13 @@ namespace Floorplan { OutlineMethod method; std::string name; Polygon2 poly; - FloorOutlinePolygon() : method(OutlineMethod::ADD), name(), poly() {;} - FloorOutlinePolygon(const OutlineMethod method, const std::string& name, const Polygon2& poly) : method(method), name(name), poly(poly) {;} - bool operator == (const FloorOutlinePolygon& o) const {return (o.method == method) && (o.name == name) && (o.poly == poly);} + bool outdoor; // special marker + FloorOutlinePolygon() : method(OutlineMethod::ADD), name(), poly(), outdoor(false) {;} + FloorOutlinePolygon(const OutlineMethod method, const std::string& name, const Polygon2& poly, bool outdoor) : method(method), name(name), poly(poly), outdoor(outdoor) {;} + bool operator == (const FloorOutlinePolygon& o) const {return (o.method == method) && (o.name == name) && (o.poly == poly) && (o.outdoor == outdoor);} }; - - - /** base-class for one obstacle (wall, door, window, pillar, ..) within a floor */ struct FloorObstacle { Material material; diff --git a/floorplan/v2/FloorplanReader.h b/floorplan/v2/FloorplanReader.h index b57c0b2..cb29bcc 100644 --- a/floorplan/v2/FloorplanReader.h +++ b/floorplan/v2/FloorplanReader.h @@ -412,6 +412,7 @@ namespace Floorplan { static FloorOutlinePolygon* parseFloorPolygon(const XMLElem* el) { FloorOutlinePolygon* poly = new FloorOutlinePolygon(); poly->name = el->Attribute("name"); + poly->outdoor = el->BoolAttribute("outdoor"); poly->method = parseOutlineMethod(el->Attribute("method")); poly->poly = parsePoly2(el); return poly; diff --git a/floorplan/v2/FloorplanWriter.h b/floorplan/v2/FloorplanWriter.h index ed4b0e6..c8257d1 100644 --- a/floorplan/v2/FloorplanWriter.h +++ b/floorplan/v2/FloorplanWriter.h @@ -227,6 +227,7 @@ namespace Floorplan { XMLElem* polygon = doc.NewElement("polygon"); polygon->SetAttribute("name", poly->name.c_str()); polygon->SetAttribute("method", method.c_str()); + polygon->SetAttribute("outdoor", poly->outdoor); dst->InsertEndChild(polygon); for (Point2 p : poly->poly.points) { diff --git a/grid/GridNode.h b/grid/GridNode.h index d648b82..863ee43 100755 --- a/grid/GridNode.h +++ b/grid/GridNode.h @@ -52,6 +52,8 @@ public: static const uint8_t TYPE_ELEVATOR = 2; static const uint8_t TYPE_DOOR = 3; + static const uint8_t TYPE_OUTDOOR = 100; + public: /** ctor */ diff --git a/grid/factory/v2/GridFactory.h b/grid/factory/v2/GridFactory.h index d6beece..0303c51 100755 --- a/grid/factory/v2/GridFactory.h +++ b/grid/factory/v2/GridFactory.h @@ -114,21 +114,38 @@ public: return bb; } - bool isPartOfFloorOutline(const int x_cm, const int y_cm, const Floorplan::FloorOutline& outline) { + enum class PartOfOutline { + NO, + INDOOR, + OUTDOOR, + }; - bool add = false; + /** get the part of outline the given location belongs to. currently: none, indoor, outdoor */ + 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; + + // process every outline polygon for (Floorplan::FloorOutlinePolygon* poly : outline) { - if (poly->method != Floorplan::OutlineMethod::ADD) {continue;} HelperPoly pol(*poly); - if (pol.contains(Point2(x_cm, y_cm))) {add = true;} + if (pol.contains(Point2(x_cm, y_cm))) { + + // belongs to a "remove" polygon? -> directly ignore this location! + if (poly->method == Floorplan::OutlineMethod::REMOVE) { + return PartOfOutline::NO; + } + + // 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; + + } } - if (!add) {return false;} - for (Floorplan::FloorOutlinePolygon* poly : outline) { - if (poly->method != Floorplan::OutlineMethod::REMOVE) {continue;} - HelperPoly pol(*poly); - if (pol.contains(Point2(x_cm, y_cm))) {add = false;} // TODO - } - return add; + + // done + return res; + } @@ -155,7 +172,8 @@ public: for (int y_cm = y1; y_cm < y2; y_cm += helper.gridSize()) { // does the outline-polygon contain this position? - if (!isPartOfFloorOutline(x_cm, y_cm, floor->outline)) {continue;} + const PartOfOutline part = isPartOfFloorOutline(x_cm, y_cm, floor->outline); + if (part == PartOfOutline::NO) {continue;} // check intersection with the floorplan GridNodeBBox bbox(GridPoint(x_cm, y_cm, z_cm), helper.gridSize()); @@ -164,12 +182,13 @@ public: bbox.grow(0.42345); if (intersects(bbox, floor)) {continue;} - // add to the grid + // add to the grid [once] T t(x_cm, y_cm, z_cm); - t.setType(getType(bbox, floor)); if (grid.hasNodeFor(t)) {continue;} + updateType(t, part, bbox, floor); grid.add(t); + // debug ++numNodes; @@ -487,23 +506,30 @@ private: } - /** does the bbox intersect with any of the floor's walls? */ - static inline int getType(const GridNodeBBox& bbox, const Floorplan::Floor* floor) { + /** adjust the given gridNode's type if needed [e.g. from "floor" to "door"] */ + static inline void updateType(T& t, const PartOfOutline part, const GridNodeBBox& bbox, const Floorplan::Floor* floor) { - // process each obstacle + // 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"); + } + + // hereafter, process each obstacle and mark doors for (Floorplan::FloorObstacle* fo : floor->obstacles) { if (dynamic_cast(fo)) { const Floorplan::FloorObstacleDoor* door = (Floorplan::FloorObstacleDoor*) fo; const Line2 l2(door->from*100, door->to*100); - if (bbox.intersects(l2)) {return GridNode::TYPE_DOOR;} - + if (bbox.intersects(l2)) { + t.setType(GridNode::TYPE_DOOR); + return; // done + } } } - return GridNode::TYPE_FLOOR; - }