From 8dd1ba0be6b8e4eca6a4aaa2466b52687b8f060e Mon Sep 17 00:00:00 2001 From: frank Date: Tue, 24 Jul 2018 08:13:16 +0200 Subject: [PATCH] moved from ray3 to floorplan/3D worked on new wall models refactoring --- floorplan/3D/Builder.h | 156 ++++++++++++++++++ .../ray3 => floorplan/3D}/FloorplanMesh.h | 121 +++++++++++--- floorplan/3D/Handrails.h | 83 ++++++++++ floorplan/3D/Objects.h | 52 ++++++ .../ray3 => floorplan/3D}/Obstacle3.h | 14 +- floorplan/3D/Outline.h | 99 +++++++++++ floorplan/3D/Pillars.h | 51 ++++++ floorplan/3D/Stairs.h | 82 +++++++++ {wifi/estimate/ray3 => floorplan/3D}/Walls.h | 8 +- .../ray3 => floorplan/3D}/WallsViaCubes.h | 12 +- .../3D}/WallsViaCuttedQuads.h | 40 +++-- .../ray3/FloorPos.h => floorplan/3D/misc.h | 8 +- .../ray3 => floorplan/3D/objects}/MTLReader.h | 0 .../ray3 => floorplan/3D/objects}/OBJPool.h | 10 +- .../ray3 => floorplan/3D/objects}/OBJReader.h | 0 .../ray3 => floorplan/3D/primitives}/Cube.h | 8 +- .../3D/primitives}/Cylinder.h | 8 +- .../ray3 => floorplan/3D/primitives}/Mesh.h | 8 +- .../ray3 => floorplan/3D/primitives}/Tube.h | 8 +- floorplan/v2/FloorplanLINT.h | 14 +- geo/BBox3.h | 3 + geo/Polygon2.h | 2 +- grid/factory/v2/GridFactory.h | 4 +- navMesh/NavMeshFactory.h | 4 +- .../{ModelFactory.h => ModelFactory_OLD.h} | 0 25 files changed, 703 insertions(+), 92 deletions(-) create mode 100644 floorplan/3D/Builder.h rename {wifi/estimate/ray3 => floorplan/3D}/FloorplanMesh.h (63%) create mode 100644 floorplan/3D/Handrails.h create mode 100644 floorplan/3D/Objects.h rename {wifi/estimate/ray3 => floorplan/3D}/Obstacle3.h (92%) create mode 100644 floorplan/3D/Outline.h create mode 100644 floorplan/3D/Pillars.h create mode 100644 floorplan/3D/Stairs.h rename {wifi/estimate/ray3 => floorplan/3D}/Walls.h (71%) rename {wifi/estimate/ray3 => floorplan/3D}/WallsViaCubes.h (90%) rename {wifi/estimate/ray3 => floorplan/3D}/WallsViaCuttedQuads.h (92%) rename wifi/estimate/ray3/FloorPos.h => floorplan/3D/misc.h (87%) rename {wifi/estimate/ray3 => floorplan/3D/objects}/MTLReader.h (100%) rename {wifi/estimate/ray3 => floorplan/3D/objects}/OBJPool.h (95%) rename {wifi/estimate/ray3 => floorplan/3D/objects}/OBJReader.h (100%) rename {wifi/estimate/ray3 => floorplan/3D/primitives}/Cube.h (96%) rename {wifi/estimate/ray3 => floorplan/3D/primitives}/Cylinder.h (91%) rename {wifi/estimate/ray3 => floorplan/3D/primitives}/Mesh.h (92%) rename {wifi/estimate/ray3 => floorplan/3D/primitives}/Tube.h (95%) rename wifi/estimate/ray3/{ModelFactory.h => ModelFactory_OLD.h} (100%) diff --git a/floorplan/3D/Builder.h b/floorplan/3D/Builder.h new file mode 100644 index 0000000..58c3b59 --- /dev/null +++ b/floorplan/3D/Builder.h @@ -0,0 +1,156 @@ +#ifndef FLOORPLAN_3D_BUILDER_H +#define FLOORPLAN_3D_BUILDER_H + +#include "../v2/Floorplan.h" + +#include "FloorplanMesh.h" +#include "Obstacle3.h" + +#include "Outline.h" +#include "Stairs.h" +#include "Handrails.h" +#include "Objects.h" +#include "Pillars.h" + +#include "Walls.h" +#include "WallsViaCubes.h" +#include "WallsViaCuttedQuads.h" + +namespace Floorplan3D { + + class Builder { + + /** the to-be-exported map */ + const Floorplan::IndoorMap* map; + + public: + + bool exportCeilings = true; + bool exportObstacles = true; + bool exportStairs = true; + bool fancyStairs = true; + bool exportHandrails = true; + bool exportDoors = true; + bool exportAboveDoors = true; + bool doorsOpen = false; + bool exportObjects = true; + bool exportPillars = true; + bool exportWallTops = false; + bool center = true; + + //Walls* walls = new WallsViaCubes(); + //Walls* walls = new WallsViaCuttedQuads(); + + public: + + + /** ctor */ + Builder(const Floorplan::IndoorMap* map) : map(map) { + + } + + /** get the created mesh */ + FloorplanMesh getMesh() { + + FloorplanMesh mesh; + mesh.elements = triangulize(); + + if (center) { + BBox3 bb = mesh.getBBox(); + mesh -= Point3(bb.getCenter().x, bb.getCenter().y, 0); + } + + return mesh; + + } + + private: + + /** get all triangles grouped by obstacle */ + std::vector triangulize() { + + // TODO: filtering?? + std::vector floors = map->floors; + + std::vector res; + + // get the to-be-exported floors (either "all" or "user defined") + //const std::vector& floors = (exportFloors.empty()) ? (map->floors) : (exportFloors); + + // process each floor + for (const Floorplan::Floor* f : floors) { + + if (!f->enabled) {continue;} + + // triangulize the floor itself (floor/ceiling) + if (exportCeilings) { + Outline out; + const std::vector tmp = out.get(f); + res.insert(res.end(), tmp.begin(), tmp.end()); + } + + // process each obstacle within the floor + if (f->obstacles.enabled) { + + if (1 == 1) { + const std::vector tmp = getWalls(f); + res.insert(res.end(), tmp.begin(), tmp.end()); + } + + if (exportHandrails) { + Handrails rails; + const std::vector tmp = rails.getHandrails(f); + res.insert(res.end(), tmp.begin(), tmp.end()); + } + + if (exportObjects) { + Objects objs; + const std::vector tmp = objs.getObjects(f); + res.insert(res.end(), tmp.begin(), tmp.end()); + } + + if (exportPillars) { + Pillars pillars; + const std::vector tmp = pillars.getPillars(f); + res.insert(res.end(), tmp.begin(), tmp.end()); + } + +// for (const Floorplan::FloorObstacle* fo : f->obstacles) { +// std::vector tmp = getWalls(f); +// res.insert(res.end(), tmp.begin(), tmp.end()); +// } + } + +// // stairs + if (f->stairs.enabled && exportStairs) { + Stairs stairs; + const std::vector tmp = stairs.getStairs(f); + res.insert(res.end(), tmp.begin(), tmp.end()); + } + + } + + return res; + + } + + + /** just get all walls */ + std::vector getWalls(const Floorplan::Floor* f) { + + WallsViaCuttedQuads walls; + + for (const Floorplan::FloorObstacle* obs : f->obstacles) { + const Floorplan::FloorObstacleLine* line = dynamic_cast(obs); + if (line) {walls.add(f, line, nullptr);} + } + + return walls.get(); + + } + + }; + +} + +#endif // FLOORPLAN_3D_BUILDER_H diff --git a/wifi/estimate/ray3/FloorplanMesh.h b/floorplan/3D/FloorplanMesh.h similarity index 63% rename from wifi/estimate/ray3/FloorplanMesh.h rename to floorplan/3D/FloorplanMesh.h index c7b949f..5bec327 100644 --- a/wifi/estimate/ray3/FloorplanMesh.h +++ b/floorplan/3D/FloorplanMesh.h @@ -1,10 +1,11 @@ -#ifndef FLOORPLANMESH_H -#define FLOORPLANMESH_H +#ifndef FLOORPLAN_3D_FLOORPLANMESH_H +#define FLOORPLAN_3D_FLOORPLANMESH_H #include "Obstacle3.h" +#include "../../geo/BBox3.h" #include -namespace Ray3D { +namespace Floorplan3D { /** * meshed version of the floorplan @@ -13,6 +14,26 @@ namespace Ray3D { std::vector elements; + BBox3 getBBox() const { + BBox3 bb; + for (const Obstacle3D& o : elements) { + for (const Triangle3& t : o.triangles) { + bb.add(t.p1); + bb.add(t.p2); + bb.add(t.p3); + } + } + return bb; + } + + void operator -= (const Point3 p) { + for (Obstacle3D& o : elements) { + for (Triangle3& t : o.triangles) { + t -= p; + } + } + } + /** export as OBJ file */ void exportOBJsimple(const std::string& file) { std::ofstream out(file.c_str()); @@ -80,6 +101,10 @@ namespace Ray3D { /** DEBUG: convert to .obj file code for exporting */ OBJData toOBJ(const std::string name) { + const BBox3 bb = getBBox(); + const float ox = bb.getCenter().x; + const float oy = bb.getCenter().y; + bool swapYZ = true; int nVerts = 1; int nObjs = 0; @@ -108,13 +133,14 @@ namespace Ray3D { // write the vertices for (const Triangle3& t : o.triangles) { if (!swapYZ) { - res.obj += "v " + std::to_string(t.p1.x) + " " + std::to_string(t.p1.y) + " " + std::to_string(t.p1.z) + "\n"; - res.obj += "v " + std::to_string(t.p2.x) + " " + std::to_string(t.p2.y) + " " + std::to_string(t.p2.z) + "\n"; - res.obj += "v " + std::to_string(t.p3.x) + " " + std::to_string(t.p3.y) + " " + std::to_string(t.p3.z) + "\n"; + res.obj += "v " + std::to_string(t.p1.x-ox) + " " + std::to_string(t.p1.y-oy) + " " + std::to_string(t.p1.z) + "\n"; + res.obj += "v " + std::to_string(t.p2.x-ox) + " " + std::to_string(t.p2.y-oy) + " " + std::to_string(t.p2.z) + "\n"; + res.obj += "v " + std::to_string(t.p3.x-ox) + " " + std::to_string(t.p3.y-oy) + " " + std::to_string(t.p3.z) + "\n"; } else { - res.obj += "v " + std::to_string(t.p1.x) + " " + std::to_string(t.p1.z) + " " + std::to_string(t.p1.y) + "\n"; - res.obj += "v " + std::to_string(t.p2.x) + " " + std::to_string(t.p2.z) + " " + std::to_string(t.p2.y) + "\n"; - res.obj += "v " + std::to_string(t.p3.x) + " " + std::to_string(t.p3.z) + " " + std::to_string(t.p3.y) + "\n"; + res.obj += "v " + std::to_string(t.p1.x-ox) + " " + std::to_string(t.p1.z) + " " + std::to_string(t.p1.y-oy) + "\n"; + res.obj += "v " + std::to_string(t.p3.x-ox) + " " + std::to_string(t.p3.z) + " " + std::to_string(t.p3.y-oy) + "\n"; + res.obj += "v " + std::to_string(t.p2.x-ox) + " " + std::to_string(t.p2.z) + " " + std::to_string(t.p2.y-oy) + "\n"; + } } @@ -221,29 +247,78 @@ namespace Ray3D { }; - // material +// // material +// std::vector mats = { + +// Material(0,128,0,255), // ground outdoor +// Material(64,64,64,255), // ground outdoor +// Material(255,96,96,255), // stair + +// Material(128,128,128,255), // concrete +// Material(64,128,255,64), // glass +// Material(200,200,200,255), // default + +// }; + +// int getMaterial(const Obstacle3D& o) const { +// if (o.type == Obstacle3D::Type::GROUND_OUTDOOR) {return 0;} +// if (o.type == Obstacle3D::Type::GROUND_INDOOR) {return 1;} +// if (o.type == Obstacle3D::Type::STAIR) {return 2;} + +// if (o.mat == Floorplan::Material::CONCRETE) {return 3;} +// if (o.mat == Floorplan::Material::GLASS) {return 4;} +// return 5; +// } + std::vector mats = { - Material(0,128,0,255), // ground outdoor - Material(64,64,64,255), // ground outdoor - Material(255,96,96,255), // stair + Material(255,0,0,255), // error - Material(128,128,128,255), // concrete - Material(64,128,255,64), // glass - Material(200,200,200,255), // default + Material(0,128,0,255), // ground outdoor + Material(64,64,64,255), // ground outdoor + Material(105,105,105,255), // stair + Material(220,220,220,255), // handrail + + Material(200,200,255,96), // door (glass) + Material(140,140,140,255), // door (wood) + + Material(135,135,135,255), // concrete + Material(240,240,255,96), // glass + Material(170,170,255,96), // glass (metallized) + Material(170,120,60,255), // wood + Material(200,200,200,255), // drywall + + Material(255,255,255,255), // object + + Material(235,235,235,255), // default }; int getMaterial(const Obstacle3D& o) const { - if (o.type == Obstacle3D::Type::GROUND_OUTDOOR) {return 0;} - if (o.type == Obstacle3D::Type::GROUND_INDOOR) {return 1;} - if (o.type == Obstacle3D::Type::STAIR) {return 2;} - if (o.mat == Floorplan::Material::CONCRETE) {return 3;} - if (o.mat == Floorplan::Material::GLASS) {return 4;} - return 5; + if (o.type == Floorplan3D::Obstacle3D::Type::ERROR) {return 0;} + + if (o.type == Floorplan3D::Obstacle3D::Type::GROUND_OUTDOOR) {return 1;} + if (o.type == Floorplan3D::Obstacle3D::Type::GROUND_INDOOR) {return 2;} + if (o.type == Floorplan3D::Obstacle3D::Type::STAIR) {return 3;} + if (o.type == Floorplan3D::Obstacle3D::Type::HANDRAIL) {return 4;} + if (o.type == Floorplan3D::Obstacle3D::Type::OBJECT) {return 12;} + + if (o.type == Floorplan3D::Obstacle3D::Type::DOOR && o.mat == Floorplan::Material::GLASS) {return 5;} + if (o.type == Floorplan3D::Obstacle3D::Type::DOOR) {return 6;} + + if (o.mat == Floorplan::Material::CONCRETE) {return 7;} + if (o.mat == Floorplan::Material::GLASS) {return 8;} + if (o.mat == Floorplan::Material::METALLIZED_GLAS) {return 9;} + + if (o.mat == Floorplan::Material::WOOD) {return 10;} + if (o.mat == Floorplan::Material::DRYWALL) {return 11;} + + return 12; + } + // Color getColor(const Obstacle3D& o) const { // if (o.type == Obstacle3D::Type::GROUND_OUTDOOR) {return Color(0,128,0,255);} // if (o.type == Obstacle3D::Type::GROUND_INDOOR) {return Color(64,64,64,255);} @@ -256,4 +331,4 @@ namespace Ray3D { } -#endif // FLOORPLANMESH_H +#endif // FLOORPLAN_3D_FLOORPLANMESH_H diff --git a/floorplan/3D/Handrails.h b/floorplan/3D/Handrails.h new file mode 100644 index 0000000..77f70ee --- /dev/null +++ b/floorplan/3D/Handrails.h @@ -0,0 +1,83 @@ +#ifndef FLOORPLAN_3D_HANDRAILS_H +#define FLOORPLAN_3D_HANDRAILS_H + +#include "Obstacle3.h" +#include "misc.h" + +namespace Floorplan3D { + + class Handrails { + + public: + + std::vector getHandrails(const Floorplan::Floor* f) { + std::vector res; + for (const Floorplan::FloorObstacle* o: f->obstacles) { + const Floorplan::FloorObstacleLine* line = dynamic_cast(o); + if (line && line->type == Floorplan::ObstacleType::HANDRAIL) { + res.push_back(getHandrail(f, line)); + } + } + return res; + } + + Obstacle3D getHandrail(const Floorplan::Floor* f, const Floorplan::FloorObstacleLine* fol) const { + + FloorPos fpos(f); + + // target + Obstacle3D res(getType(fol), fol->material); + + const float thickness_m = 0.05; + const Point2 from = fol->from; + const Point2 to = fol->to; + const Point2 cen2 = (from+to)/2; + + // edges + const float z1 = fpos.z1; + const float z2 = fpos.z1 + 1.0; + Point3 p1 = Point3(from.x, from.y, z1); + Point3 p2 = Point3(to.x, to.y, z1); + Point3 p3 = Point3(from.x, from.y, z2); + Point3 p4 = Point3(to.x, to.y, z2); + + const float rad = std::atan2(to.y - from.y, to.x - from.x); + const float deg = rad * 180 / M_PI; + + // cube's destination center + const Point3 pUp(cen2.x, cen2.y, z2); + + const float sx = from.getDistance(to) / 2; + const float sy = thickness_m / 2; + const float sz = thickness_m / 2; + const Point3 size(sx, sy, sz); + const Point3 rot(0,0,deg); + + // upper bar + const Cube cubeUpper(pUp, size, rot); + const std::vector tmp = cubeUpper.getTriangles(); + res.triangles.insert(res.triangles.end(), tmp.begin(), tmp.end()); + + const Point3 d1 = p2-p1; + const Point3 d2 = p4-p3; + const int numBars = d2.length() / 0.75f; + for (int i = 1; i < numBars; ++i) { + const Point3 s = p1 + d1 * i / numBars; + const Point3 e = p3 + d2 * i / numBars; + const Point3 c = (s+e)/2; + const Point3 size(thickness_m/2, thickness_m/2, s.getDistance(e)/2 - thickness_m); + const Cube cube(c, size, rot); + const std::vector tmp = cube.getTriangles(); + res.triangles.insert(res.triangles.end(), tmp.begin(), tmp.end()); + } + + // done + return res; + + } + + }; + +} + +#endif // FLOORPLAN_3D_HANDRAILS_H diff --git a/floorplan/3D/Objects.h b/floorplan/3D/Objects.h new file mode 100644 index 0000000..c8e9f47 --- /dev/null +++ b/floorplan/3D/Objects.h @@ -0,0 +1,52 @@ +#ifndef FLOORPLAN_3D_OBJECTS_H +#define FLOORPLAN_3D_OBJECTS_H + +#include "Obstacle3.h" +#include "misc.h" +#include "objects/OBJPool.h" + +namespace Floorplan3D { + + class Objects { + + public: + + std::vector getObjects(const Floorplan::Floor* f) { + std::vector res; + for (const Floorplan::FloorObstacle* o: f->obstacles) { + const Floorplan::FloorObstacleObject* obj = dynamic_cast(o); + if (obj) { + res.push_back(getObject(f, obj)); + } + } + return res; + } + + /** 3D Obstacle from .obj 3D mesh */ + Obstacle3D getObject(const Floorplan::Floor* f, const Floorplan::FloorObstacleObject* foo) const { + + FloorPos fpos(f); + + const std::string& name = foo->file; + Obstacle3D obs = OBJPool::get().getObject(name); + + // perform sanity checks + if (!obs.isValid()) { + throw std::runtime_error("invalid obstacle-data detected"); + } + + // apply scaling/rotation/translation + obs = obs.scaled(foo->scale); + obs = obs.rotated_deg( Point3(foo->rot.x, foo->rot.y, foo->rot.z) ); + obs = obs.translated(foo->pos + Point3(0,0,fpos.z1)); + obs.type = Obstacle3D::Type::OBJECT; + + return obs; + + } + + }; + +} + +#endif // FLOORPLAN_3D_OBJECTS_H diff --git a/wifi/estimate/ray3/Obstacle3.h b/floorplan/3D/Obstacle3.h similarity index 92% rename from wifi/estimate/ray3/Obstacle3.h rename to floorplan/3D/Obstacle3.h index 758f230..7af4d8f 100644 --- a/wifi/estimate/ray3/Obstacle3.h +++ b/floorplan/3D/Obstacle3.h @@ -1,13 +1,13 @@ -#ifndef OBSTACLE3_H -#define OBSTACLE3_H +#ifndef FLOORPLAN_3D_OBSTACLE3_H +#define FLOORPLAN_3D_OBSTACLE3_H #include -#include "../../../geo/Triangle3.h" -#include "../../../geo/Sphere3.h" +#include "../../geo/Triangle3.h" +#include "../../geo/Sphere3.h" -#include "../../../floorplan/v2/Floorplan.h" +#include "../v2/Floorplan.h" -namespace Ray3D { +namespace Floorplan3D { /** * 3D obstacle @@ -124,4 +124,4 @@ namespace Ray3D { } -#endif // OBSTACLE3_H +#endif // FLOORPLAN_3D_OBSTACLE3_H diff --git a/floorplan/3D/Outline.h b/floorplan/3D/Outline.h new file mode 100644 index 0000000..e9c4b96 --- /dev/null +++ b/floorplan/3D/Outline.h @@ -0,0 +1,99 @@ +#ifndef FLOORPLAN_3D_OUTLINE_H +#define FLOORPLAN_3D_OUTLINE_H + +#include "Obstacle3.h" +#include "misc.h" +#include +#include "../../geo/GPCPolygon2.h" + +namespace Floorplan3D { + + class Outline { + + public: + + /** convert a floor (floor/ceiling) into triangles */ + std::vector get(const Floorplan::Floor* f) { + + FloorPos fpos(f); + + std::vector res; + if (!f->enabled) {return res;} + if (!f->outline.enabled) {return res;} + + // floor uses an outline based on "add" and "remove" areas + // we need to create the apropriate triangles to model the polygon + // including all holes (remove-areas) + + // process all "add" regions by type + // [this allows for overlaps of the same type] + std::unordered_map types; + for (Floorplan::FloorOutlinePolygon* fop : f->outline) { + if (fop->method == Floorplan::OutlineMethod::ADD) { + if (fop->outdoor) { + types["outdoor"].add(fop->poly); + } else { + types["indoor"].add(fop->poly); + } + } + + } + + // remove the "remove" regions from EVERY "add" region added within the previous step + for (Floorplan::FloorOutlinePolygon* fop : f->outline) { + if (fop->method == Floorplan::OutlineMethod::REMOVE) { + for (auto& it : types) { + it.second.remove(fop->poly); + } + } + // allow for overlapping outdoor/indoor regions -> outdoor wins [remove outdoor part from indoor parts] + if (fop->outdoor) { + types["indoor"].remove(fop->poly); + } + } + + // create an obstacle for each type (indoor, outdoor) + for (auto& it : types) { + + // TODO: variable type? + Obstacle3D::Type type = (it.first == "indoor") ? (Obstacle3D::Type::GROUND_INDOOR) : (Obstacle3D::Type::GROUND_OUTDOOR); + Obstacle3D obs(type, Floorplan::Material::CONCRETE); + + // convert them into polygons + std::vector> polys = it.second.get(fpos.z1); + + // convert polygons (GL_TRIANGLE_STRIP) to triangles + for (const std::vector& pts : polys) { + for (int i = 0; i < (int)pts.size() - 2; ++i) { + + // floor must be double-sided + Triangle3 tria1 (pts[i+0], pts[i+1], pts[i+2]); + Triangle3 tria2 (pts[i+2], pts[i+1], pts[i+0]); + + // ensure the triangle with the normal pointing downwards (towards bulding's cellar) + // is below the triangle that points upwards (towards the sky) + if (tria1.getNormal().z < 0) {std::swap(tria1, tria2);} + + // tria2 = ceiling of previous floor + tria2 -= Point3(0,0,fpos.fh); + + // add both + obs.triangles.push_back(tria1); + obs.triangles.push_back(tria2); + + } + } + + res.push_back(obs); + + } + + return res; + + } + + }; + +} + +#endif // FLOORPLAN_3D_OUTLINE_H diff --git a/floorplan/3D/Pillars.h b/floorplan/3D/Pillars.h new file mode 100644 index 0000000..85cb5f3 --- /dev/null +++ b/floorplan/3D/Pillars.h @@ -0,0 +1,51 @@ +#ifndef FLOORPLAN_3D_PILLARS_H +#define FLOORPLAN_3D_PILLARS_H + +#include "Obstacle3.h" +#include "misc.h" +#include "primitives/Cylinder.h" + +namespace Floorplan3D { + + class Pillars { + + public: + + std::vector getPillars(const Floorplan::Floor* f) { + std::vector res; + for (const Floorplan::FloorObstacle* o: f->obstacles) { + const Floorplan::FloorObstacleCircle* circ = dynamic_cast(o); + if (circ) { + res.push_back(getPillar(f, circ)); + } + } + return res; + } + + + Obstacle3D getPillar(const Floorplan::Floor* f, const Floorplan::FloorObstacleCircle* foc) { + + FloorPos fpos(f); + + // attributes + const float r = foc->radius; + const float h = (foc->height > 0) ? (foc->height) : (fpos.height); // use either floor's height or user height + const Point3 pos(foc->center.x, foc->center.y, fpos.z1 + h/2); + + // build + Cylinder cyl; + cyl.add(r, h/2, true); + cyl.translate(pos); + + // done + Obstacle3D res(getType(foc), foc->material); + res.triangles = cyl.getTriangles(); + return res; + + } + + }; + +} + +#endif // FLOORPLAN_3D_PILLARS_H diff --git a/floorplan/3D/Stairs.h b/floorplan/3D/Stairs.h new file mode 100644 index 0000000..ddf35de --- /dev/null +++ b/floorplan/3D/Stairs.h @@ -0,0 +1,82 @@ +#ifndef FLOORPLAN_3D_STAIRS_H +#define FLOORPLAN_3D_STAIRS_H + +#include "Obstacle3.h" +#include "primitives/Cube.h" + +namespace Floorplan3D { + + class Stairs { + + public: + + std::vector getStairs(const Floorplan::Floor* f) { + std::vector res; + for (const Floorplan::Stair* stair : f->stairs) { + res.push_back(getStair(f, stair)); + } + return res; + } + + Obstacle3D getStair(const Floorplan::Floor* f, const Floorplan::Stair* s) { + + Obstacle3D res(Obstacle3D::Type::STAIR, Floorplan::Material::CONCRETE); + + std::vector quads = Floorplan::getQuads(s->getParts(), f); + for (const Floorplan::Quad3& quad : quads) { + + if (quad.isLeveled()) { + + const float h = 0.2; + const Point3 ph(0,0,h); + const Cube cube = Cube::fromBottomAndHeight(quad.p1-ph, quad.p2-ph, quad.p3-ph, quad.p4-ph, 0.2); + + const std::vector tmp = cube.getTriangles(); + res.triangles.insert(res.triangles.end(), tmp.begin(), tmp.end()); + + } else { + + const Point3 dir1 = quad.p3 - quad.p2; + const Point3 dir2 = quad.p4 - quad.p1; + float stepH = 0.20; + const float totalH = quad.p3.z - quad.p1.z; + const int numStairs = std::round(totalH / stepH); + stepH = totalH / numStairs; + + for (int i = 0; i < numStairs; ++i) { + + //const float y1 = quad.p1.z + (stepH * i); + //const float y2 = y1 + stepH; + + Point3 p1b = quad.p1 + dir1 * (i+0) / numStairs; p1b.z -= stepH; + Point3 p2b = quad.p2 + dir2 * (i+0) / numStairs; p2b.z -= stepH; + + const Point3 p3t = quad.p2 + dir2 * (i+1) / numStairs; + const Point3 p4t = quad.p1 + dir1 * (i+1) / numStairs; + + const Point3 p1t(p1b.x, p1b.y, p4t.z); + const Point3 p2t(p2b.x, p2b.y, p3t.z); + + const Point3 p3b(p3t.x, p3t.y, p2b.z+stepH); + const Point3 p4b(p4t.x, p4t.y, p1b.z+stepH); + + const Cube cube = Cube::fromVertices(p1t, p2t, p3t, p4t, p1b, p2b, p3b, p4b); + const std::vector tmp = cube.getTriangles(); + res.triangles.insert(res.triangles.end(), tmp.begin(), tmp.end()); + + + } + } + + + } + + return res; + + } + + }; + +} + +#endif // FLOORPLAN_3D_STAIRS_H diff --git a/wifi/estimate/ray3/Walls.h b/floorplan/3D/Walls.h similarity index 71% rename from wifi/estimate/ray3/Walls.h rename to floorplan/3D/Walls.h index 067e195..01b0d74 100644 --- a/wifi/estimate/ray3/Walls.h +++ b/floorplan/3D/Walls.h @@ -1,9 +1,9 @@ -#ifndef WALLS_H -#define WALLS_H +#ifndef FLOORPLAN_3D_WALLS_H +#define FLOORPLAN_3D_WALLS_H #include "Obstacle3.h" -namespace Ray3D { +namespace Floorplan3D { class Walls { @@ -19,4 +19,4 @@ namespace Ray3D { } -#endif // WALLS_H +#endif // FLOORPLAN_3D_WALLS_H diff --git a/wifi/estimate/ray3/WallsViaCubes.h b/floorplan/3D/WallsViaCubes.h similarity index 90% rename from wifi/estimate/ray3/WallsViaCubes.h rename to floorplan/3D/WallsViaCubes.h index 3b871d0..a585c3d 100644 --- a/wifi/estimate/ray3/WallsViaCubes.h +++ b/floorplan/3D/WallsViaCubes.h @@ -1,11 +1,11 @@ -#ifndef WALLSVIACUBE_H -#define WALLSVIACUBE_H +#ifndef FLOORPLAN_3D_WALLSVIACUBE_H +#define FLOORPLAN_3D_WALLSVIACUBE_H #include "Walls.h" -#include "FloorPos.h" -#include "Cube.h" +#include "misc.h" +#include "primitives/Cube.h" -namespace Ray3D { +namespace Floorplan3D { /** * simply use one 3D cube per wall @@ -66,4 +66,4 @@ namespace Ray3D { } -#endif // WALLSVIACUBE_H +#endif // FLOORPLAN_3D_WALLSVIACUBE_H diff --git a/wifi/estimate/ray3/WallsViaCuttedQuads.h b/floorplan/3D/WallsViaCuttedQuads.h similarity index 92% rename from wifi/estimate/ray3/WallsViaCuttedQuads.h rename to floorplan/3D/WallsViaCuttedQuads.h index 8e63f9e..901c694 100644 --- a/wifi/estimate/ray3/WallsViaCuttedQuads.h +++ b/floorplan/3D/WallsViaCuttedQuads.h @@ -1,14 +1,14 @@ -#ifndef WALLSVIACUTTEDQUADS_H -#define WALLSVIACUTTEDQUADS_H +#ifndef FLOORPLAN_3D_WALLSVIACUTTEDQUADS_H +#define FLOORPLAN_3D_WALLSVIACUTTEDQUADS_H -#include "../../../geo/Line2.h" -#include "../../../geo/Polygon2.h" +#include "../../geo/Line2.h" +#include "../../geo/Polygon2.h" #include "Walls.h" -#include "FloorPos.h" +#include "misc.h" #include -namespace Ray3D { +namespace Floorplan3D { /** * interpret walls als quads (polygons) @@ -95,7 +95,7 @@ namespace Ray3D { /** does this wall contain the given point */ bool containsPoint(const Point2 p) const { - return polygonContainsPoint({l1.p1, l1.p2, l2.p2, l2.p1}, p); + return polygonContainsPoint({getP1(), getP2(), getP3(), getP4()}, p); } }; @@ -168,11 +168,13 @@ namespace Ray3D { /** convert one wall into an obstacle */ Obstacle3D toObstacle(const Wall& wall, const Floorplan::Floor* f) { + FloorPos fp(f); + Obstacle3D::Type type = (wall.error) ? (Obstacle3D::Type::ERROR) : (getType(wall.line)); Obstacle3D obs(type, wall.line->material); - const float z1 = f->getStartingZ(); - const float z2 = f->getEndingZ(); + const float z1 = fp.z1; + const float z2 = fp.z2; const Point3 p1 = Point3(wall.getP1().x, wall.getP1().y, z1); const Point3 p2 = Point3(wall.getP2().x, wall.getP2().y, z1); @@ -227,19 +229,27 @@ namespace Ray3D { std::cout << "detected strange wall intersection" << std::endl; } - // check all detected intersections + int cut = 0; + + // check the (2) detected intersections for (const auto isect : isects) { // if one of the line-ends p1/p2 from wall1 ends within wall2, crop it by setting it to the intersection - if (w2.containsPoint(isect.l1->p1)) {isect.l1->p1 = isect.p;} - if (w2.containsPoint(isect.l1->p2)) {isect.l1->p2 = isect.p;} + if (w2.containsPoint(isect.l1->p1)) {isect.l1->p1 = isect.p; ++cut;} + if (w2.containsPoint(isect.l1->p2)) {isect.l1->p2 = isect.p; ++cut;} // if one of the line-ends p1/p2 from wall2 ends within wall1, crop it by setting it to the intersection - if (w1.containsPoint(isect.l2->p1)) {isect.l2->p1 = isect.p;} - if (w1.containsPoint(isect.l2->p2)) {isect.l2->p2 = isect.p;} + if (w1.containsPoint(isect.l2->p1)) {isect.l2->p1 = isect.p; ++cut;} + if (w1.containsPoint(isect.l2->p2)) {isect.l2->p2 = isect.p; ++cut;} } + // 2 lines should have been cut. if not, potential issue! + if (cut != 2) { + w1.error = true; + w2.error = true; + } + } } @@ -290,4 +300,4 @@ namespace Ray3D { } -#endif // WALLSVIACUTTEDQUADS_H +#endif // FLOORPLAN_3D_WALLSVIACUTTEDQUADS_H diff --git a/wifi/estimate/ray3/FloorPos.h b/floorplan/3D/misc.h similarity index 87% rename from wifi/estimate/ray3/FloorPos.h rename to floorplan/3D/misc.h index d89241c..9eac973 100644 --- a/wifi/estimate/ray3/FloorPos.h +++ b/floorplan/3D/misc.h @@ -1,9 +1,9 @@ -#ifndef FLOORPOS_H -#define FLOORPOS_H +#ifndef FLOORPLAN_3D_MISC_H +#define FLOORPLAN_3D_MISC_H #include "Obstacle3.h" -namespace Ray3D { +namespace Floorplan3D { /** used to model ceiling thickness */ struct FloorPos { @@ -30,4 +30,4 @@ namespace Ray3D { } -#endif // FLOORPOS_H +#endif // FLOORPLAN_3D_MISC_H diff --git a/wifi/estimate/ray3/MTLReader.h b/floorplan/3D/objects/MTLReader.h similarity index 100% rename from wifi/estimate/ray3/MTLReader.h rename to floorplan/3D/objects/MTLReader.h diff --git a/wifi/estimate/ray3/OBJPool.h b/floorplan/3D/objects/OBJPool.h similarity index 95% rename from wifi/estimate/ray3/OBJPool.h rename to floorplan/3D/objects/OBJPool.h index 037dd5b..fd49930 100644 --- a/wifi/estimate/ray3/OBJPool.h +++ b/floorplan/3D/objects/OBJPool.h @@ -1,12 +1,12 @@ -#ifndef OBJPOOL_H -#define OBJPOOL_H +#ifndef FLOORPLAN_3D_OBJPOOL_H +#define FLOORPLAN_3D_OBJPOOL_H #include #include "../../../geo/Triangle3.h" #include #include "OBJReader.h" -#include "Obstacle3.h" +#include "../Obstacle3.h" // LINUX ONLY //#include @@ -17,7 +17,7 @@ #include "../../../misc/Debug.h" -namespace Ray3D { +namespace Floorplan3D { /** * load several named 3D models for quick re-use @@ -132,4 +132,4 @@ namespace Ray3D { } -#endif // OBJPOOL_H +#endif // FLOORPLAN_3D_OBJPOOL_H diff --git a/wifi/estimate/ray3/OBJReader.h b/floorplan/3D/objects/OBJReader.h similarity index 100% rename from wifi/estimate/ray3/OBJReader.h rename to floorplan/3D/objects/OBJReader.h diff --git a/wifi/estimate/ray3/Cube.h b/floorplan/3D/primitives/Cube.h similarity index 96% rename from wifi/estimate/ray3/Cube.h rename to floorplan/3D/primitives/Cube.h index dcbb426..416c0f5 100644 --- a/wifi/estimate/ray3/Cube.h +++ b/floorplan/3D/primitives/Cube.h @@ -1,11 +1,11 @@ -#ifndef QUBE_H -#define QUBE_H +#ifndef FLOORPLAN_3D_CUBE_H +#define FLOORPLAN_3D_CUBE_H #include "../../../math/Matrix4.h" #include "Mesh.h" -namespace Ray3D { +namespace Floorplan3D { class Cube : public Mesh { @@ -163,4 +163,4 @@ namespace Ray3D { } -#endif // QUBE_H +#endif // FLOORPLAN_3D_CUBE_H diff --git a/wifi/estimate/ray3/Cylinder.h b/floorplan/3D/primitives/Cylinder.h similarity index 91% rename from wifi/estimate/ray3/Cylinder.h rename to floorplan/3D/primitives/Cylinder.h index c8f08ca..a4f2f82 100644 --- a/wifi/estimate/ray3/Cylinder.h +++ b/floorplan/3D/primitives/Cylinder.h @@ -1,11 +1,11 @@ -#ifndef CYLINDER_H -#define CYLINDER_H +#ifndef FLOORPLAN_3D_CYLINDER_H +#define FLOORPLAN_3D_CYLINDER_H #include "../../../math/Matrix4.h" #include "Mesh.h" -namespace Ray3D { +namespace Floorplan3D { /** walled cylinder */ class Cylinder : public Mesh { @@ -79,4 +79,4 @@ namespace Ray3D { } -#endif // CYLINDER_H +#endif // FLOORPLAN_3D_CYLINDER_H diff --git a/wifi/estimate/ray3/Mesh.h b/floorplan/3D/primitives/Mesh.h similarity index 92% rename from wifi/estimate/ray3/Mesh.h rename to floorplan/3D/primitives/Mesh.h index d5fc40e..7a6bef8 100644 --- a/wifi/estimate/ray3/Mesh.h +++ b/floorplan/3D/primitives/Mesh.h @@ -1,11 +1,11 @@ -#ifndef RAY3D_MESH_H -#define RAY3D_MESH_H +#ifndef FLOORPLAN_3D_MESH_H +#define FLOORPLAN_3D_MESH_H #include #include "../../../geo/Triangle3.h" #include "../../../math/Matrix4.h" -namespace Ray3D { +namespace Floorplan3D { class Mesh { @@ -66,4 +66,4 @@ namespace Ray3D { } -#endif // RAY3D_MESH_H +#endif // FLOORPLAN_3D_MESH_H diff --git a/wifi/estimate/ray3/Tube.h b/floorplan/3D/primitives/Tube.h similarity index 95% rename from wifi/estimate/ray3/Tube.h rename to floorplan/3D/primitives/Tube.h index 3f0fde9..8f8a8ad 100644 --- a/wifi/estimate/ray3/Tube.h +++ b/floorplan/3D/primitives/Tube.h @@ -1,11 +1,11 @@ -#ifndef TUBE_H -#define TUBE_H +#ifndef FLOORPLAN_3D_TUBE_H +#define FLOORPLAN_3D_TUBE_H #include "../../../math/Matrix4.h" #include "Mesh.h" -namespace Ray3D { +namespace Floorplan3D { /** walled cylinder */ class Tube : public Mesh { @@ -119,4 +119,4 @@ namespace Ray3D { } -#endif // TUBE_H +#endif // FLOORPLAN_3D_TUBE_H diff --git a/floorplan/v2/FloorplanLINT.h b/floorplan/v2/FloorplanLINT.h index 30314b3..e497a49 100644 --- a/floorplan/v2/FloorplanLINT.h +++ b/floorplan/v2/FloorplanLINT.h @@ -3,7 +3,6 @@ #include "Floorplan.h" #include "../../geo/BBox2.h" -#include "../../wifi/estimate/ray3/ModelFactory.h" #include #include @@ -147,12 +146,13 @@ namespace Floorplan { res.push_back(Issue(Type::ERR, floor, "' door is too narrow: " + std::to_string(len_m) + " meter from " + door->from.asString() + " to " + door->to.asString())); } - try { - Ray3D::ModelFactory fac(map); - fac.getDoorAbove(floor, door); - } catch (Exception e) { - res.push_back(Issue(Type::ERR, floor, std::string(e.what()) + "[from" + door->from.asString() + " to " + door->to.asString() + "]")); - } +#warning "TODO!" +// try { +// Ray3D::ModelFactory fac(map); +// fac.getDoorAbove(floor, door); +// } catch (Exception e) { +// res.push_back(Issue(Type::ERR, floor, std::string(e.what()) + "[from" + door->from.asString() + " to " + door->to.asString() + "]")); +// } } diff --git a/geo/BBox3.h b/geo/BBox3.h index b0fbd1a..2f72d35 100644 --- a/geo/BBox3.h +++ b/geo/BBox3.h @@ -57,6 +57,9 @@ public: /** get the bbox's size */ const Point3 getSize() const {return p2-p1;} + /** get the boox's center */ + const Point3 getCenter() const {return (p2+p1)/2;} + /** equal? */ bool operator == (const BBox3& o) const { return (p1.x == o.p1.x) && diff --git a/geo/Polygon2.h b/geo/Polygon2.h index 436f8a9..f6d76ed 100644 --- a/geo/Polygon2.h +++ b/geo/Polygon2.h @@ -118,7 +118,7 @@ static bool polygonContainsPoint(const std::vector& poly, const Point2 p // only look at the fractional part //const double y = x - std::floor(x); - return std::abs(x) >= 0.975;// && (std::abs(y) >= 0.9 || std::abs(y) < 0.1); + return std::abs(x) >= 0.995;// && (std::abs(y) >= 0.9 || std::abs(y) < 0.1); } diff --git a/grid/factory/v2/GridFactory.h b/grid/factory/v2/GridFactory.h index 61c0601..ce31adf 100755 --- a/grid/factory/v2/GridFactory.h +++ b/grid/factory/v2/GridFactory.h @@ -21,7 +21,7 @@ #include "../../../misc/Debug.h" #include -#include "../../../wifi/estimate/ray3/OBJPool.h" +#include "../../../floorplan/3D/objects/OBJPool.h" #include "../../../geo/ConvexHull2.h" #include "GridFactoryListener.h" @@ -224,7 +224,7 @@ public: if (foo) { // get the obstacle - const Ray3D::Obstacle3D obs = Ray3D::OBJPool::get().getObject(foo->file).scaled(foo->scale).rotated_deg(foo->rot).translated(foo->pos); + const Floorplan3D::Obstacle3D obs = Floorplan3D::OBJPool::get().getObject(foo->file).scaled(foo->scale).rotated_deg(foo->rot).translated(foo->pos); // construct its 2D convex hull (in centimter) HelperPoly poly; diff --git a/navMesh/NavMeshFactory.h b/navMesh/NavMeshFactory.h index be76a10..d46454c 100644 --- a/navMesh/NavMeshFactory.h +++ b/navMesh/NavMeshFactory.h @@ -8,7 +8,7 @@ #include "../geo/ConvexHull2.h" #include "../geo/GPCPolygon2.h" -#include "../wifi/estimate/ray3/OBJPool.h" +#include "../floorplan/3D/objects/OBJPool.h" #include "NavMesh.h" #include "NavMeshTriangle.h" @@ -632,7 +632,7 @@ namespace NM { Floorplan::Polygon2 res; // fetch object from pool - const Ray3D::Obstacle3D obs = Ray3D::OBJPool::get().getObject(obj->file).scaled(obj->scale).rotated_deg(obj->rot).translated(obj->pos); + const Floorplan3D::Obstacle3D obs = Floorplan3D::OBJPool::get().getObject(obj->file).scaled(obj->scale).rotated_deg(obj->rot).translated(obj->pos); // construct 2D convex hull res.points = ConvexHull2::get(obs.getPoints2D()); diff --git a/wifi/estimate/ray3/ModelFactory.h b/wifi/estimate/ray3/ModelFactory_OLD.h similarity index 100% rename from wifi/estimate/ray3/ModelFactory.h rename to wifi/estimate/ray3/ModelFactory_OLD.h