From 5e749d4da88dd068a4f0f70b9b6c784a065284b2 Mon Sep 17 00:00:00 2001 From: frank Date: Thu, 8 Feb 2018 21:27:24 +0100 Subject: [PATCH] worked on map->3d model generation --- tests/ray/TestModelFac.cpp | 4 +- wifi/estimate/ray3/Cube.h | 53 +++---------- wifi/estimate/ray3/Mesh.h | 60 +++++++++++++++ wifi/estimate/ray3/ModelFactory.h | 92 ++++++++++++++++++---- wifi/estimate/ray3/Tube.h | 122 ++++++++++++++++++++++++++++++ 5 files changed, 273 insertions(+), 58 deletions(-) create mode 100644 wifi/estimate/ray3/Mesh.h create mode 100644 wifi/estimate/ray3/Tube.h diff --git a/tests/ray/TestModelFac.cpp b/tests/ray/TestModelFac.cpp index 5056bef..2ca8667 100644 --- a/tests/ray/TestModelFac.cpp +++ b/tests/ray/TestModelFac.cpp @@ -8,7 +8,9 @@ using namespace Ray3D; TEST(Ray, ModelFac) { - std::string file = "/apps/paper/diss/data/maps/SHL41_nm.xml"; + //std::string file = "/apps/paper/diss/data/maps/SHL42_nm.xml"; + std::string file = "/mnt/vm/paper/diss/data/maps/SHL42_nm.xml"; + Floorplan::IndoorMap* map = Floorplan::Reader::readFromFile(file); ModelFactory fac(map); diff --git a/wifi/estimate/ray3/Cube.h b/wifi/estimate/ray3/Cube.h index dc36332..4c9bc7b 100644 --- a/wifi/estimate/ray3/Cube.h +++ b/wifi/estimate/ray3/Cube.h @@ -1,17 +1,13 @@ #ifndef QUBE_H #define QUBE_H -#include -#include "../../../geo/Triangle3.h" + #include "../../../math/Matrix4.h" +#include "Mesh.h" namespace Ray3D { - class Cube { - - private: - - std::vector trias; + class Cube : public Mesh { public: @@ -21,39 +17,11 @@ namespace Ray3D { } /** ctor with position, size and rotation */ - Cube(Point3 pos, Point3 size, Point3 rot_deg, const bool topAndBottom = true) { + Cube(const Point3 pos, const Point3 size, const Point3 rot_deg, const bool topAndBottom = true) { unitCube(topAndBottom); - const Matrix4 mRot = Matrix4::getRotationDeg(rot_deg.x, rot_deg.y, rot_deg.z); - const Matrix4 mSize = Matrix4::getScale(size.x, size.y, size.z); - const Matrix4 mPos = Matrix4::getTranslation(pos.x, pos.y, pos.z); - const Matrix4 mat = mPos * mRot * mSize; - transform(mat); + transform(pos, size, rot_deg); } - /** get the cube's triangles */ - const std::vector getTriangles() const { - return trias; - } - - void transform(const Matrix4& mat) { - - for (Triangle3& tria : trias) { - - Vector4 v1(tria.p1.x, tria.p1.y, tria.p1.z, 1); - Vector4 v2(tria.p2.x, tria.p2.y, tria.p2.z, 1); - Vector4 v3(tria.p3.x, tria.p3.y, tria.p3.z, 1); - - v1 = mat*v1; - v2 = mat*v2; - v3 = mat*v3; - - tria.p1 = Point3(v1.x, v1.y, v1.z); - tria.p2 = Point3(v2.x, v2.y, v2.z); - tria.p3 = Point3(v3.x, v3.y, v3.z); - - } - - } /** get a transformed version */ Cube transformed(const Matrix4& mat) const { @@ -62,6 +30,13 @@ namespace Ray3D { return res; } + /** get a transformed version */ + Cube transformed(const Point3 pos, const Point3 size, const Point3 rot_deg) const { + Cube res = *this; + res.transform(pos, size, rot_deg); + return res; + } + private: /** build unit-cube faces */ @@ -133,10 +108,6 @@ namespace Ray3D { } - void addQuad(Point3 p1, Point3 p2, Point3 p3, Point3 p4) { - trias.push_back( Triangle3(p1,p2,p3) ); - trias.push_back( Triangle3(p1,p3,p4) ); - } }; diff --git a/wifi/estimate/ray3/Mesh.h b/wifi/estimate/ray3/Mesh.h new file mode 100644 index 0000000..1862f97 --- /dev/null +++ b/wifi/estimate/ray3/Mesh.h @@ -0,0 +1,60 @@ +#ifndef RAY3D_MESH_H +#define RAY3D_MESH_H + +#include +#include "../../../geo/Triangle3.h" +#include "../../../math/Matrix4.h" + +namespace Ray3D { + + class Mesh { + + protected: + + std::vector trias; + + public: + + /** get the mesh's triangles */ + const std::vector& getTriangles() const { + return trias; + } + + void transform(const Point3 pos, Point3 size, Point3 rot_deg) { + const Matrix4 mRot = Matrix4::getRotationDeg(rot_deg.x, rot_deg.y, rot_deg.z); + const Matrix4 mSize = Matrix4::getScale(size.x, size.y, size.z); + const Matrix4 mPos = Matrix4::getTranslation(pos.x, pos.y, pos.z); + const Matrix4 mat = mPos * mRot * mSize; + transform(mat); + } + + void transform(const Matrix4& mat) { + + for (Triangle3& tria : trias) { + + Vector4 v1(tria.p1.x, tria.p1.y, tria.p1.z, 1); + Vector4 v2(tria.p2.x, tria.p2.y, tria.p2.z, 1); + Vector4 v3(tria.p3.x, tria.p3.y, tria.p3.z, 1); + + v1 = mat*v1; + v2 = mat*v2; + v3 = mat*v3; + + tria.p1 = Point3(v1.x, v1.y, v1.z); + tria.p2 = Point3(v2.x, v2.y, v2.z); + tria.p3 = Point3(v3.x, v3.y, v3.z); + + } + + } + + void addQuad(Point3 p1, Point3 p2, Point3 p3, Point3 p4) { + trias.push_back( Triangle3(p1,p2,p3) ); + trias.push_back( Triangle3(p1,p3,p4) ); + } + + }; + +} + +#endif // RAY3D_MESH_H diff --git a/wifi/estimate/ray3/ModelFactory.h b/wifi/estimate/ray3/ModelFactory.h index 66dd6ae..60ae83c 100644 --- a/wifi/estimate/ray3/ModelFactory.h +++ b/wifi/estimate/ray3/ModelFactory.h @@ -6,6 +6,7 @@ #include "ModelFactoryHelper.h" #include "Obstacle3.h" #include "Cube.h" +#include "Tube.h" #include "FloorplanMesh.h" namespace Ray3D { @@ -21,7 +22,8 @@ namespace Ray3D { bool exportObstacles = true; bool exportStairs = true; bool exportHandrails = true; - bool exportDoors = false; + bool exportDoors = true; + bool doorsOpen = true; bool exportWallTops = false; std::vector exportFloors; @@ -130,6 +132,7 @@ namespace Ray3D { types["indoor"].add(fop->poly); } } + } // remove the "remove" regions from EVERY "add" region added within the previous step @@ -139,6 +142,10 @@ namespace Ray3D { 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) @@ -273,27 +280,80 @@ namespace Ray3D { const float thickness_m = 0.10; // TODO?? const Point2 from = door->from; const Point2 to = door->to; - const Point2 cen2 = (from+to)/2; 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 pos(cen2.x, cen2.y, f->atHeight + door->height/2); + float deg = rad * 180 / M_PI; // div by 2.01 to prevent overlapps and z-fighting - const float sx = from.getDistance(to) / 2; - const float sy = thickness_m / 2; - const float sz = door->height / 2.01f; // prevent overlaps - const Point3 size(sx, sy, sz); const Point3 rot(0,0,deg); - // build - Cube cube(pos, size, rot); - - // done + Point3 pos; + Matrix4 mat = Matrix4::identity(); Obstacle3D res(Obstacle3D::Type::DOOR, door->material); - res.triangles = cube.getTriangles(); + + // normal door? (non-spinner) + if (Floorplan::DoorType::SWING == door->type) { + + if (doorsOpen) {deg += (door->swap) ? (-90) : (+90);} + mat = Matrix4::getTranslation(1,0,0); // cube's edge located at 0,0,0 + pos = Point3(from.x, from.y, f->atHeight + door->height/2); + + const float sx = from.getDistance(to) / 2; + const float sy = thickness_m / 2; + const float sz = door->height / 2.01f; // prevent overlaps + const Point3 size(sx, sy, sz); + + Cube cube; + cube.transform(mat); + cube.transform(pos, size, rot); + res.triangles = cube.getTriangles(); + + } else if (Floorplan::DoorType::REVOLVING == door->type) { + + const Point2 cen2 = (from+to)/2; + const Point3 pos(cen2.x, cen2.y, f->atHeight + door->height/2); + + // outer and inner radius + const float rOuter = from.getDistance(to) / 2; + const float rInner = rOuter - 0.1; + const float sz = door->height / 2.01f; // prevent overlaps + const Point3 size(1, 1, sz); + + // around the doors + Tube tube; + tube.addSegment(0+40-90, 180-40-90, rInner, rOuter, 1, true, true); + tube.addSegment(180+40-90, 360-40-90, rInner, rOuter, 1, true, true); + tube.transform(pos, Point3(1,1,1), rot); + res.triangles = tube.getTriangles(); + + // the doors + const int numDoors = 3; + Cube cube; + cube.transform(Matrix4::getTranslation(1,0,0)); + for (int i = 0; i < numDoors; ++i) { + const int deg = 45 + (360*i / numDoors); + Cube c1 = cube + .transformed(Matrix4::getScale(rInner/2-0.05, thickness_m/2, sz)) + .transformed(Matrix4::getTranslation(0.04, 0, 0)) + .transformed(Matrix4::getRotationDeg(0,0,deg)) + .transformed(Matrix4::getTranslation(pos.x, pos.y, pos.z)); + //pos, Point3(rInner/2-0.05, thickness_m/2, sz), Point3(0,0,deg)); + std::vector t1 = c1.getTriangles(); + res.triangles.insert(res.triangles.end(), t1.begin(), t1.end()); + } + + + } else { + + throw "unsupported door type"; + + } + + + + + + return res; } @@ -349,7 +409,7 @@ namespace Ray3D { const float sy = thickness_m / 2; const float sz = thickness_m / 2; const Point3 size(sx, sy, sz); - const Point3 rot(0,0,deg); + const Point3 rot(0,0,deg); // upper bar const Cube cubeUpper(pUp, size, rot); diff --git a/wifi/estimate/ray3/Tube.h b/wifi/estimate/ray3/Tube.h new file mode 100644 index 0000000..3f0fde9 --- /dev/null +++ b/wifi/estimate/ray3/Tube.h @@ -0,0 +1,122 @@ +#ifndef TUBE_H +#define TUBE_H + + +#include "../../../math/Matrix4.h" +#include "Mesh.h" + +namespace Ray3D { + + /** walled cylinder */ + class Tube : public Mesh { + + public: + + /** ctor */ + Tube() { + ; + } + + + /** get a transformed version */ + Tube transformed(const Matrix4& mat) const { + Tube res = *this; + res.transform(mat); + return res; + } + + /** build */ + void addSegment(const float from_deg, const float to_deg, const float rInner, const float rOuter, const float h, bool closeSides, bool topAndBottom) { + + const int tiles = 32; + const float deg_per_tile = 360.0f / tiles; + const float rad_per_tile = deg_per_tile / 180.0f * M_PI; + const int startTile = std::round(from_deg / deg_per_tile); + const int endTile = std::round(to_deg / deg_per_tile); + + for (int i = startTile; i < endTile; ++i) { + + const float startRad = (i+0) * rad_per_tile; + const float endRad = (i+1) * rad_per_tile; + + const float xo0 = std::cos(startRad) * rOuter; + const float yo0 = std::sin(startRad) * rOuter; + const float xo1 = std::cos(endRad) * rOuter; + const float yo1 = std::sin(endRad) * rOuter; + + const float xi0 = std::cos(startRad) * rInner; + const float yi0 = std::sin(startRad) * rInner; + const float xi1 = std::cos(endRad) * rInner; + const float yi1 = std::sin(endRad) * rInner; + + if (closeSides) { + + // close start of segment + if (i == startTile) { + addQuad( + Point3(xi0, yi0, -h), + Point3(xo0, yo0, -h), + Point3(xo0, yo0, +h), + Point3(xi0, yi0, +h) + ); + } + + // close end of segment + if (i == endTile-1) { + addQuad( + Point3(xi1, yi1, +h), + Point3(xo1, yo1, +h), + Point3(xo1, yo1, -h), + Point3(xi1, yi1, -h) + ); + } + + } + + // outer + addQuad( + Point3(xo0, yo0, -h), + Point3(xo1, yo1, -h), + Point3(xo1, yo1, +h), + Point3(xo0, yo0, +h) + ); + + // innser + addQuad( + Point3(xi0, yi0, +h), + Point3(xi1, yi1, +h), + Point3(xi1, yi1, -h), + Point3(xi0, yi0, -h) + ); + + if (topAndBottom) { + + // top + addQuad( + Point3(xi0, yi0, h), + Point3(xo0, yo0, h), + Point3(xo1, yo1, h), + Point3(xi1, yi1, h) + ); + + // bottom + addQuad( + Point3(xi1, yi1, -h), + Point3(xo1, yo1, -h), + Point3(xo0, yo0, -h), + Point3(xi0, yi0, -h) + ); + + } + + } + + } + + + + }; + +} + +#endif // TUBE_H