changes to Floorplan 3D
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include "Handrails.h"
|
||||
#include "Objects.h"
|
||||
#include "Pillars.h"
|
||||
#include "Doors.h"
|
||||
|
||||
#include "Walls.h"
|
||||
#include "WallsViaCubes.h"
|
||||
@@ -102,6 +103,8 @@ namespace Floorplan3D {
|
||||
res.insert(res.end(), tmp.begin(), tmp.end());
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (exportHandrails) {
|
||||
Handrails rails;
|
||||
const std::vector<Obstacle3D> tmp = rails.getHandrails(f);
|
||||
@@ -120,6 +123,12 @@ namespace Floorplan3D {
|
||||
res.insert(res.end(), tmp.begin(), tmp.end());
|
||||
}
|
||||
|
||||
if (exportDoors) {
|
||||
Doors doors;
|
||||
const std::vector<Obstacle3D> tmp = doors.getDoors(f);
|
||||
res.insert(res.end(), tmp.begin(), tmp.end());
|
||||
}
|
||||
|
||||
// for (const Floorplan::FloorObstacle* fo : f->obstacles) {
|
||||
// std::vector<Obstacle3D> tmp = getWalls(f);
|
||||
// res.insert(res.end(), tmp.begin(), tmp.end());
|
||||
@@ -161,7 +170,11 @@ namespace Floorplan3D {
|
||||
|
||||
for (const Floorplan::FloorObstacle* obs : f->obstacles) {
|
||||
const Floorplan::FloorObstacleLine* line = dynamic_cast<const Floorplan::FloorObstacleLine*>(obs);
|
||||
if (line) {walls.add(f, line, nullptr);}
|
||||
if (line) {
|
||||
if (line->type == Floorplan::ObstacleType::WALL) {
|
||||
walls.add(f, line, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return walls.get();
|
||||
|
||||
67
floorplan/3D/Doors.h
Normal file
67
floorplan/3D/Doors.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#ifndef FLOORPLAN_3D_DOORS_H
|
||||
#define FLOORPLAN_3D_DOORS_H
|
||||
|
||||
#include "Walls.h"
|
||||
#include "misc.h"
|
||||
#include "primitives/Cube.h"
|
||||
|
||||
namespace Floorplan3D {
|
||||
|
||||
class Doors {
|
||||
|
||||
Cube::Part cubeParts = (Cube::Part) 63; // leftright,topbottom,rearfront
|
||||
|
||||
public:
|
||||
|
||||
std::vector<Obstacle3D> getDoors(const Floorplan::Floor* floor) {
|
||||
std::vector<Obstacle3D> res;
|
||||
for (const Floorplan::FloorObstacle* o: floor->obstacles) {
|
||||
const Floorplan::FloorObstacleWall* wall = dynamic_cast<const Floorplan::FloorObstacleWall*>(o);
|
||||
if (wall) {
|
||||
for (const Floorplan::FloorObstacleWallDoor* door : wall->doors) {
|
||||
res.push_back(getDoor(floor, wall, door));
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Obstacle3D getDoor(const Floorplan::Floor* f, const Floorplan::FloorObstacleWall* wall, const Floorplan::FloorObstacleWallDoor* door) {
|
||||
|
||||
FloorPos fpos(f);
|
||||
|
||||
const float thickness_m = 0.1;
|
||||
const Point2 from = door->getStart(wall);
|
||||
const Point2 to = door->getEnd(wall);
|
||||
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 double height = door->height;
|
||||
const double cenZ = (fpos.z1 + height/2);
|
||||
const Point3 pos(cen2.x, cen2.y, cenZ);
|
||||
|
||||
// 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 = height / 2.01f; // prevent overlaps
|
||||
const Point3 size(sx, sy, sz);
|
||||
const Point3 rot(0,0,deg);
|
||||
|
||||
// build
|
||||
Cube cube(pos, size, rot, cubeParts);
|
||||
|
||||
// done
|
||||
Obstacle3D res(Obstacle3D::Type::DOOR, door->material);
|
||||
res.triangles = cube.getTriangles();
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FLOORPLAN_3D_DOORS_H
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <vector>
|
||||
#include "../../geo/Triangle3.h"
|
||||
#include "../../geo/Sphere3.h"
|
||||
#include "../../geo/TriangleStrip3.h"
|
||||
|
||||
#include "../v2/Floorplan.h"
|
||||
|
||||
@@ -41,15 +42,35 @@ namespace Floorplan3D {
|
||||
|
||||
|
||||
/** append a new triangle. REFERENCE ONLY VALID UNTIL NEXT ADD */
|
||||
Triangle3& addTriangle(const Point3 p1, const Point3 p2, const Point3 p3) {
|
||||
triangles.push_back(Triangle3(p1, p2, p3));
|
||||
Triangle3& addTriangle(const Point3 p1, const Point3 p2, const Point3 p3, const bool reverse) {
|
||||
Triangle3 t(p1, p2, p3);
|
||||
if (reverse) {t.reverse();}
|
||||
triangles.push_back(t);
|
||||
return triangles.back();
|
||||
}
|
||||
|
||||
void addTriangleStrip(std::initializer_list<Point3> pts, bool reverse = false) {
|
||||
TriangleStrip3 strip;
|
||||
for (const Point3& p : pts) {strip.add(p);}
|
||||
for (Triangle3 t : strip.toTriangles()) {
|
||||
if (reverse) {t.reverse();}
|
||||
triangles.push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
void addTriangleStrip(const std::vector<Point3>& pts, bool reverse = false) {
|
||||
TriangleStrip3 strip;
|
||||
for (const Point3& p : pts) {strip.add(p);}
|
||||
for (Triangle3 t : strip.toTriangles()) {
|
||||
if (reverse) {t.reverse();}
|
||||
triangles.push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
/** append a new quad by splitting into two triangles */
|
||||
void addQuad(const Point3 p1, const Point3 p2, const Point3 p3, const Point3 p4) {
|
||||
addTriangle(p1, p2, p3);
|
||||
addTriangle(p1, p3, p4);
|
||||
void addQuad(const Point3 p1, const Point3 p2, const Point3 p3, const Point3 p4, const bool reverse = false) {
|
||||
addTriangle(p1, p2, p3, reverse);
|
||||
addTriangle(p1, p3, p4, reverse);
|
||||
}
|
||||
|
||||
/** reverse all faces (CW<->CCW) */
|
||||
|
||||
@@ -167,26 +167,205 @@ namespace Floorplan3D {
|
||||
}
|
||||
|
||||
|
||||
/** convert one wall into an obstacle */
|
||||
Obstacle3D toObstacle(const Wall& wall, const Floorplan::Floor* f) {
|
||||
Obstacle3D toObstacle(const Wall& w, 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 Floorplan::FloorObstacleWall* wall = w.line;
|
||||
Obstacle3D::Type type = (w.error) ? (Obstacle3D::Type::ERROR) : (getType(wall));
|
||||
Obstacle3D obs(type, wall->material);
|
||||
|
||||
const float z1 = fp.z1;
|
||||
const float z2 = (wall.line->height_m > 0) ? (fp.z1 + wall.line->height_m) : (fp.z2);
|
||||
const float z2 = (wall->height_m > 0) ? (fp.z1 + wall->height_m) : (fp.z2);
|
||||
|
||||
// const Point3 p1 = Point3(wall.getP1().x, wall.getP1().y, z1);
|
||||
// const Point3 p2 = Point3(wall.getP2().x, wall.getP2().y, z1);
|
||||
// const Point3 p3 = Point3(wall.getP3().x, wall.getP3().y, z1);
|
||||
// const Point3 p4 = Point3(wall.getP4().x, wall.getP4().y, z1);
|
||||
const Point3 p1 = Point3(w.getP1().x, w.getP1().y, z1); // front
|
||||
const Point3 p2 = Point3(w.getP2().x, w.getP2().y, z1); // front
|
||||
const Point3 p3 = Point3(w.getP3().x, w.getP3().y, z1); // back
|
||||
const Point3 p4 = Point3(w.getP4().x, w.getP4().y, z1); // back
|
||||
|
||||
const Point3 p1u = Point3(w.getP1().x, w.getP1().y, z2); // front upper
|
||||
const Point3 p2u = Point3(w.getP2().x, w.getP2().y, z2); // front upper
|
||||
const Point3 p3u = Point3(w.getP3().x, w.getP3().y, z2); // back upper
|
||||
const Point3 p4u = Point3(w.getP4().x, w.getP4().y, z2); // back upper
|
||||
|
||||
const Point2 dir = (wall->to - wall->from).normalized();
|
||||
const Point2 perp = dir.perpendicular().normalized() * (wall->thickness_m/2);
|
||||
|
||||
// move from wall's center line towards front (- half thickness)
|
||||
auto toFront = [perp] (const Point2 pt, const float z) {
|
||||
const Point2 tmp = pt + perp;
|
||||
return Point3(tmp.x, tmp.y, z);
|
||||
};
|
||||
|
||||
// move from wall's center line towards back (+ half thickness)
|
||||
auto toBack = [perp] (const Point2 pt, const float z) {
|
||||
const Point2 tmp = pt - perp;
|
||||
return Point3(tmp.x, tmp.y, z);
|
||||
};
|
||||
|
||||
// above window, below window, window frame
|
||||
for (const Floorplan::FloorObstacleWallWindow* win : wall->windows) {
|
||||
|
||||
// quad below the window (1,2,3,4) CCW
|
||||
// quad above the window (5,6,7,8) CCW
|
||||
// -> window = (4,3,6,5) CCW
|
||||
|
||||
const float za = z1 + win->startsAtHeight;
|
||||
const float zb = za + win->height;
|
||||
|
||||
const Point3 p1f = toFront(win->getStart(wall), z1);
|
||||
const Point3 p2f = toFront(win->getEnd(wall), z1);
|
||||
const Point3 p3f = toFront(win->getEnd(wall), za);
|
||||
const Point3 p4f = toFront(win->getStart(wall), za);
|
||||
|
||||
const Point3 p1b = toBack(win->getStart(wall), z1);
|
||||
const Point3 p2b = toBack(win->getEnd(wall), z1);
|
||||
const Point3 p3b = toBack(win->getEnd(wall), za);
|
||||
const Point3 p4b = toBack(win->getStart(wall), za);
|
||||
|
||||
const Point3 p5f = toFront(win->getStart(wall), zb);
|
||||
const Point3 p6f = toFront(win->getEnd(wall), zb);
|
||||
const Point3 p7f = toFront(win->getEnd(wall), z2);
|
||||
const Point3 p8f = toFront(win->getStart(wall), z2);
|
||||
|
||||
const Point3 p5b = toBack(win->getStart(wall), zb);
|
||||
const Point3 p6b = toBack(win->getEnd(wall), zb);
|
||||
const Point3 p7b = toBack(win->getEnd(wall), z2);
|
||||
const Point3 p8b = toBack(win->getStart(wall), z2);
|
||||
|
||||
// quad below the window
|
||||
obs.addQuad(p1f, p2f, p3f, p4f, true); // front
|
||||
obs.addQuad(p1b, p2b, p3b, p4b, false); // back
|
||||
|
||||
// quad above the window
|
||||
obs.addQuad(p5f, p6f, p7f, p8f, true); // front
|
||||
obs.addQuad(p5b, p6b, p7b, p8b, false); // back
|
||||
|
||||
// window frame
|
||||
obs.addTriangleStrip({p4f, p4b, p3f, p3b, p6f, p6b, p5f, p5b, p4f, p4b});
|
||||
|
||||
}
|
||||
|
||||
// start mantle surface (zig-zag around the wall)
|
||||
std::vector<Point3> ptsLateralSurface;
|
||||
ptsLateralSurface.push_back(p1);
|
||||
ptsLateralSurface.push_back(p4);
|
||||
|
||||
|
||||
// sort doors along the wall
|
||||
std::vector<Floorplan::FloorObstacleWallDoor*> doors = wall->doors;
|
||||
std::sort(doors.begin(), doors.end(), [] (const Floorplan::FloorObstacleWallDoor* d1, const Floorplan::FloorObstacleWallDoor* d2) {
|
||||
return d1->atLinePos < d2->atLinePos;
|
||||
});
|
||||
|
||||
// above door, append lateral surface around wall
|
||||
for (const Floorplan::FloorObstacleWallDoor* door : doors) {
|
||||
|
||||
Point2 ps = door->getStart(wall);
|
||||
Point2 pe = door->getEnd(wall);
|
||||
if (door->leftRight) {std::swap(ps,pe);}
|
||||
|
||||
const float zb = z1 + door->height;
|
||||
|
||||
{
|
||||
|
||||
const Point3 p1f = toFront(ps, zb);
|
||||
const Point3 p2f = toFront(pe, zb);
|
||||
const Point3 p3f = toFront(pe, z2);
|
||||
const Point3 p4f = toFront(ps, z2);
|
||||
|
||||
const Point3 p1b = toBack(ps, zb);
|
||||
const Point3 p2b = toBack(pe, zb);
|
||||
const Point3 p3b = toBack(pe, z2);
|
||||
const Point3 p4b = toBack(ps, z2);
|
||||
|
||||
// quad above the door (front)
|
||||
obs.addQuad(p1f, p2f, p3f, p4f, true);
|
||||
|
||||
// quad above the door (back)
|
||||
obs.addQuad(p1b, p2b, p3b, p4b, false);
|
||||
|
||||
}
|
||||
|
||||
const Point3 p1f = toFront(ps, z1);
|
||||
const Point3 p2f = toFront(pe, z1);
|
||||
const Point3 p3f = toFront(pe, zb);
|
||||
const Point3 p4f = toFront(ps, zb);
|
||||
|
||||
const Point3 p1b = toBack(ps, z1);
|
||||
const Point3 p2b = toBack(pe, z1);
|
||||
const Point3 p3b = toBack(pe, zb);
|
||||
const Point3 p4b = toBack(ps, zb);
|
||||
|
||||
// continue mantle surface
|
||||
ptsLateralSurface.push_back(p1f);
|
||||
ptsLateralSurface.push_back(p1b);
|
||||
ptsLateralSurface.push_back(p4f);
|
||||
ptsLateralSurface.push_back(p4b);
|
||||
ptsLateralSurface.push_back(p3f);
|
||||
ptsLateralSurface.push_back(p3b);
|
||||
ptsLateralSurface.push_back(p2f);
|
||||
ptsLateralSurface.push_back(p2b);
|
||||
|
||||
}
|
||||
|
||||
// complete mantle surface
|
||||
ptsLateralSurface.push_back(p2);
|
||||
ptsLateralSurface.push_back(p3);
|
||||
ptsLateralSurface.push_back(p2u);
|
||||
ptsLateralSurface.push_back(p3u);
|
||||
ptsLateralSurface.push_back(p1u);
|
||||
ptsLateralSurface.push_back(p4u);
|
||||
ptsLateralSurface.push_back(p1);
|
||||
ptsLateralSurface.push_back(p4);
|
||||
obs.addTriangleStrip(ptsLateralSurface, true);
|
||||
|
||||
// get all points along the wall start, doorstart,doorend, doorstart,doorend, .., end
|
||||
std::vector<Point3> ptsFront;
|
||||
ptsFront.push_back(p1);
|
||||
ptsFront.push_back(p2);
|
||||
|
||||
std::vector<Point3> ptsBack;
|
||||
ptsBack.push_back(p3);
|
||||
ptsBack.push_back(p4);
|
||||
|
||||
for (const Floorplan::FloorObstacleWallDoor* door : wall->doors) {
|
||||
ptsFront.push_back(toFront(door->getStart(wall), z1));
|
||||
ptsFront.push_back(toFront(door->getEnd(wall), z1));
|
||||
ptsBack.push_back(toBack(door->getStart(wall), z1));
|
||||
ptsBack.push_back(toBack(door->getEnd(wall), z1));
|
||||
}
|
||||
for (const Floorplan::FloorObstacleWallWindow* window : wall->windows) {
|
||||
ptsFront.push_back(toFront(window->getStart(wall), z1));
|
||||
ptsFront.push_back(toFront(window->getEnd(wall), z1));
|
||||
ptsBack.push_back(toBack(window->getStart(wall), z1));
|
||||
ptsBack.push_back(toBack(window->getEnd(wall), z1));
|
||||
}
|
||||
|
||||
// sort all points by distance from start (correct on-off-on-off-on order)
|
||||
auto compFront = [p1] (const Point3 _p1, const Point3 _p2) { return p1.getDistance(_p1) < p1.getDistance(_p2); };
|
||||
std::sort(ptsFront.begin(), ptsFront.end(), compFront);
|
||||
auto compBack = [p4] (const Point3 _p1, const Point3 _p2) { return p4.getDistance(_p1) < p4.getDistance(_p2); };
|
||||
std::sort(ptsBack.begin(), ptsBack.end(), compBack);
|
||||
|
||||
// from wall segment to wall segment, excluding doors
|
||||
|
||||
for (size_t i = 0; i < ptsFront.size(); i += 2) {
|
||||
const Point3 p1 = ptsFront[i+0];
|
||||
const Point3 p2 = ptsFront[i+1];
|
||||
const Point3 p3(p2.x, p2.y, z2);
|
||||
const Point3 p4(p1.x, p1.y, z2);
|
||||
obs.addQuad(p1, p2, p3, p4, true);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ptsBack.size(); i += 2) {
|
||||
const Point3 p1 = ptsBack[i+0];
|
||||
const Point3 p2 = ptsBack[i+1];
|
||||
const Point3 p3(p2.x, p2.y, z2);
|
||||
const Point3 p4(p1.x, p1.y, z2);
|
||||
obs.addQuad(p1, p2, p3, p4, false);
|
||||
}
|
||||
|
||||
// const Point3 p1u = Point3(wall.getP1().x, wall.getP1().y, z2);
|
||||
// const Point3 p2u = Point3(wall.getP2().x, wall.getP2().y, z2);
|
||||
// const Point3 p3u = Point3(wall.getP3().x, wall.getP3().y, z2);
|
||||
// const Point3 p4u = Point3(wall.getP4().x, wall.getP4().y, z2);
|
||||
|
||||
// obs.addQuad(p1, p2, p2u, p1u);
|
||||
// obs.addQuad(p2, p3, p3u, p2u);
|
||||
@@ -198,7 +377,58 @@ namespace Floorplan3D {
|
||||
|
||||
// obs.reverseFaces();
|
||||
|
||||
// return obs;
|
||||
return obs;
|
||||
}
|
||||
|
||||
/*
|
||||
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 = fp.z1;
|
||||
const float z2 = (wall.line->height_m > 0) ? (fp.z1 + wall.line->height_m) : (fp.z2);
|
||||
|
||||
const Point3 p1 = Point3(wall.getP1().x, wall.getP1().y, z1);
|
||||
const Point3 p2 = Point3(wall.getP2().x, wall.getP2().y, z1);
|
||||
const Point3 p3 = Point3(wall.getP3().x, wall.getP3().y, z1);
|
||||
const Point3 p4 = Point3(wall.getP4().x, wall.getP4().y, z1);
|
||||
|
||||
const Point3 p1u = Point3(wall.getP1().x, wall.getP1().y, z2);
|
||||
const Point3 p2u = Point3(wall.getP2().x, wall.getP2().y, z2);
|
||||
const Point3 p3u = Point3(wall.getP3().x, wall.getP3().y, z2);
|
||||
const Point3 p4u = Point3(wall.getP4().x, wall.getP4().y, z2);
|
||||
|
||||
obs.addQuad(p1, p2, p2u, p1u);
|
||||
obs.addQuad(p2, p3, p3u, p2u);
|
||||
obs.addQuad(p3, p4, p4u, p3u);
|
||||
obs.addQuad(p4, p1, p1u, p4u);
|
||||
|
||||
obs.addQuad(p1u, p2u, p3u, p4u);
|
||||
obs.addQuad(p4, p3, p2, p1);
|
||||
|
||||
obs.reverseFaces();
|
||||
|
||||
return obs;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/** 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 = fp.z1;
|
||||
const float z2 = (wall.line->height_m > 0) ? (fp.z1 + wall.line->height_m) : (fp.z2);
|
||||
|
||||
|
||||
|
||||
Point3 p0 = Point3(wall.line->from.x, wall.line->from.y, z1);
|
||||
|
||||
@@ -394,6 +624,7 @@ namespace Floorplan3D {
|
||||
return obs;
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
void fixTria(Triangle3& t, std::function<Point3(Point3)> func) {
|
||||
t.p1 = func(t.p1);
|
||||
|
||||
Reference in New Issue
Block a user