started working on walling, dooring and windowing
refactoring
This commit is contained in:
@@ -36,7 +36,7 @@ namespace Floorplan3D {
|
||||
bool exportObjects = true;
|
||||
bool exportPillars = true;
|
||||
bool exportWallTops = false;
|
||||
bool center = true;
|
||||
bool center = false;
|
||||
|
||||
//Walls* walls = new WallsViaCubes();
|
||||
//Walls* walls = new WallsViaCuttedQuads();
|
||||
@@ -92,6 +92,11 @@ namespace Floorplan3D {
|
||||
// process each obstacle within the floor
|
||||
if (f->obstacles.enabled) {
|
||||
|
||||
if (1 == 1) {
|
||||
const std::vector<Obstacle3D> tmp = getLines(f);
|
||||
res.insert(res.end(), tmp.begin(), tmp.end());
|
||||
}
|
||||
|
||||
if (1 == 1) {
|
||||
const std::vector<Obstacle3D> tmp = getWalls(f);
|
||||
res.insert(res.end(), tmp.begin(), tmp.end());
|
||||
@@ -140,6 +145,20 @@ namespace Floorplan3D {
|
||||
|
||||
WallsViaCuttedQuads walls;
|
||||
|
||||
for (const Floorplan::FloorObstacle* obs : f->obstacles) {
|
||||
const Floorplan::FloorObstacleWall* wall = dynamic_cast<const Floorplan::FloorObstacleWall*>(obs);
|
||||
if (wall) {walls.add(f, wall);}
|
||||
}
|
||||
|
||||
return walls.get();
|
||||
|
||||
}
|
||||
|
||||
/** get all old walls (lines) */
|
||||
std::vector<Obstacle3D> getLines(const Floorplan::Floor* f) {
|
||||
|
||||
WallsViaCubes walls;
|
||||
|
||||
for (const Floorplan::FloorObstacle* obs : f->obstacles) {
|
||||
const Floorplan::FloorObstacleLine* line = dynamic_cast<const Floorplan::FloorObstacleLine*>(obs);
|
||||
if (line) {walls.add(f, line, nullptr);}
|
||||
|
||||
69
floorplan/3D/Lines.h
Normal file
69
floorplan/3D/Lines.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#ifndef FLOORPLAN_3D_LINES_H
|
||||
#define FLOORPLAN_3D_LINES_H
|
||||
|
||||
#include "Walls.h"
|
||||
#include "misc.h"
|
||||
#include "primitives/Cube.h"
|
||||
|
||||
namespace Floorplan3D {
|
||||
|
||||
/**
|
||||
* simply use one 3D cube per wall
|
||||
* if walls intersect in the 2D view, cubes will also intersect
|
||||
*/
|
||||
class LinesViaCubes : public Walls {
|
||||
|
||||
Cube::Part cubeParts = (Cube::Part) 63; // leftright,topbottom,rearfront
|
||||
|
||||
std::vector<Obstacle3D> vec;
|
||||
|
||||
public:
|
||||
|
||||
void clear() override {
|
||||
vec.clear();
|
||||
}
|
||||
|
||||
void add(const Floorplan::Floor* f, const Floorplan::FloorObstacleLine* fol, const Floorplan::FloorObstacleDoor* aboveDoor) override {
|
||||
|
||||
FloorPos fpos(f);
|
||||
|
||||
const float thickness_m = fol->thickness_m;
|
||||
const Point2 from = (!aboveDoor) ? (fol->from) : (aboveDoor->from);
|
||||
const Point2 to = (!aboveDoor) ? (fol->to) : (aboveDoor->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 float _height = (fol->height_m > 0) ? (fol->height_m) : (fpos.height); // use either floor's height or user height
|
||||
const double height = (!aboveDoor) ? (_height) : (fpos.height - aboveDoor->height);
|
||||
const double cenZ = (!aboveDoor) ? (fpos.z1 + height/2) : (fpos.z1 + aboveDoor->height + height/2);// (fpos.z2 - (fpos.height - aboveDoor->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(getType(fol), fol->material);
|
||||
res.triangles = cube.getTriangles();
|
||||
vec.push_back(res);
|
||||
|
||||
}
|
||||
|
||||
const std::vector<Obstacle3D>& get() override {
|
||||
return vec;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FLOORPLAN_3D_LINES_H
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "../../geo/Polygon2.h"
|
||||
#include "../../geo/GPCPolygon2.h"
|
||||
|
||||
#include "Walls.h"
|
||||
//#include "Walls.h"
|
||||
#include "misc.h"
|
||||
|
||||
#include <functional>
|
||||
@@ -17,7 +17,7 @@ namespace Floorplan3D {
|
||||
* interpret walls als quads (polygons)
|
||||
* intersect them with each other to prevent overlaps
|
||||
*/
|
||||
class WallsViaCuttedQuads : public Walls {
|
||||
class WallsViaCuttedQuads {
|
||||
|
||||
private:
|
||||
|
||||
@@ -27,13 +27,13 @@ namespace Floorplan3D {
|
||||
bool error = false;
|
||||
|
||||
/** original line from floorplan */
|
||||
const Floorplan::FloorObstacleLine* line;
|
||||
const Floorplan::FloorObstacleWall* line;
|
||||
|
||||
/** outlines after applying thickness */
|
||||
Line2 l1;
|
||||
Line2 l2;
|
||||
|
||||
Wall(const Floorplan::FloorObstacleLine* line) : line(line) {
|
||||
Wall(const Floorplan::FloorObstacleWall* line) : line(line) {
|
||||
|
||||
const Point2 from = line->from;
|
||||
const Point2 to = line->to;
|
||||
@@ -137,18 +137,17 @@ namespace Floorplan3D {
|
||||
public:
|
||||
|
||||
|
||||
void clear() override {
|
||||
void clear() {
|
||||
walls.clear();
|
||||
}
|
||||
|
||||
void add(const Floorplan::Floor* f, const Floorplan::FloorObstacleLine* fol, const Floorplan::FloorObstacleDoor* aboveDoor) override {
|
||||
if (fol->type != Floorplan::ObstacleType::WALL) {return;}
|
||||
if (aboveDoor) {return;}
|
||||
void add(const Floorplan::Floor* f, const Floorplan::FloorObstacleWall* fow) {
|
||||
if (fow->type != Floorplan::ObstacleType::WALL) {return;}
|
||||
this->floor = f;
|
||||
walls.push_back(Wall(fol));
|
||||
walls.push_back(Wall(fow));
|
||||
}
|
||||
|
||||
virtual const std::vector<Obstacle3D>& get() override {
|
||||
virtual const std::vector<Obstacle3D>& get() {
|
||||
std::vector<Wall> tmp = walls;
|
||||
tmp = cutConnected(tmp);
|
||||
tmp = cutProtruding(tmp);
|
||||
@@ -226,6 +225,9 @@ namespace Floorplan3D {
|
||||
auto unFlattenFront = [o,t,a] (const Point3 p) {return Point3(p.x, +t, p.y).rotZ(a)+o;};
|
||||
auto unFlattenBack = [o,t,a] (const Point3 p) {return Point3(p.x, -t, p.y).rotZ(a)+o;};
|
||||
|
||||
auto unFlattenFront2 = [o,t,a] (const Point2 p) {return Point3(p.x, +t, p.y).rotZ(a)+o;};
|
||||
auto unFlattenBack2 = [o,t,a] (const Point2 p) {return Point3(p.x, -t, p.y).rotZ(a)+o;};
|
||||
|
||||
const Point2 fp1 = flatten(p1);
|
||||
const Point2 fp2 = flatten(p2);
|
||||
const Point2 fp3 = flatten(p3);
|
||||
@@ -248,7 +250,20 @@ namespace Floorplan3D {
|
||||
GPCPolygon2 gpBack;
|
||||
gpBack.add(back);
|
||||
|
||||
for (const Floorplan::FloorObstacleWallDoor* door : wall.line->doors) {
|
||||
// sort doors by their position within the wall (first comes first)
|
||||
std::vector<Floorplan::FloorObstacleWallDoor*> doors = wall.line->doors;
|
||||
auto compDoors = [] (const Floorplan::FloorObstacleWallDoor* d1, Floorplan::FloorObstacleWallDoor* d2) {
|
||||
return d1->atLinePos < d2->atLinePos;
|
||||
};
|
||||
std::sort(doors.begin(), doors.end(), compDoors);
|
||||
|
||||
|
||||
TriangleStrip strip;
|
||||
|
||||
strip.add(p1);
|
||||
strip.add(p4);
|
||||
|
||||
for (const Floorplan::FloorObstacleWallDoor* door : doors) {
|
||||
Polygon2 pDoor;
|
||||
|
||||
const Point2 pds = door->getStart(wall.line);
|
||||
@@ -270,8 +285,41 @@ namespace Floorplan3D {
|
||||
gpFront.remove(pDoor);
|
||||
gpBack.remove(pDoor);
|
||||
|
||||
strip.add(unFlattenFront2(pDoor[0]));
|
||||
strip.add(unFlattenBack2(pDoor[0]));
|
||||
|
||||
strip.add(unFlattenFront2(pDoor[3]));
|
||||
strip.add(unFlattenBack2(pDoor[3]));
|
||||
|
||||
strip.add(unFlattenFront2(pDoor[2]));
|
||||
strip.add(unFlattenBack2(pDoor[2]));
|
||||
|
||||
strip.add(unFlattenFront2(pDoor[1]));
|
||||
strip.add(unFlattenBack2(pDoor[1]));
|
||||
|
||||
}
|
||||
|
||||
strip.add(p2);
|
||||
strip.add(p3);
|
||||
strip.add(p2u);
|
||||
strip.add(p3u);
|
||||
strip.add(p1u);
|
||||
strip.add(p4u);
|
||||
strip.add(p1);
|
||||
strip.add(p4);
|
||||
|
||||
for (Triangle3 t : strip.toTriangles()) {
|
||||
t.reverse();
|
||||
obs.triangles.push_back(t);
|
||||
}
|
||||
|
||||
// std::vector<Point3> ptsToConnect3;
|
||||
// for (const Point2 p2 : ptsToConnect) {
|
||||
// const Point3 p3 = unf
|
||||
// }
|
||||
|
||||
|
||||
// Frontseite triangulieren
|
||||
std::vector<Triangle3> triasFront = gpFront.getTriangles();
|
||||
|
||||
for (Triangle3 tria : triasFront) {
|
||||
@@ -280,6 +328,7 @@ namespace Floorplan3D {
|
||||
obs.triangles.push_back(tria);
|
||||
}
|
||||
|
||||
// Rückseite triangulieren
|
||||
std::vector<Triangle3> triasBack = gpBack.getTriangles();
|
||||
|
||||
for (Triangle3 tria : triasBack) {
|
||||
|
||||
@@ -23,6 +23,15 @@ namespace Floorplan3D {
|
||||
}
|
||||
}
|
||||
|
||||
static Obstacle3D::Type getType(const Floorplan::FloorObstacleWall* l) {
|
||||
switch (l->type) {
|
||||
case Floorplan::ObstacleType::WALL: return Obstacle3D::Type::WALL;
|
||||
case Floorplan::ObstacleType::WINDOW: return Obstacle3D::Type::WINDOW;
|
||||
case Floorplan::ObstacleType::HANDRAIL: return Obstacle3D::Type::HANDRAIL;
|
||||
default: return Obstacle3D::Type::UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static Obstacle3D::Type getType(const Floorplan::FloorObstacleCircle* c) {
|
||||
(void) c;
|
||||
return Obstacle3D::Type::WALL;
|
||||
|
||||
@@ -157,6 +157,12 @@ namespace Floorplan {
|
||||
_END,
|
||||
};
|
||||
|
||||
/** available window types */
|
||||
enum class WindowType {
|
||||
UNKNOWN,
|
||||
_END,
|
||||
};
|
||||
|
||||
/** all supported material types */
|
||||
enum class Material {
|
||||
UNKNOWN,
|
||||
@@ -193,6 +199,7 @@ namespace Floorplan {
|
||||
struct Elevator;
|
||||
struct GroundTruthPoint;
|
||||
struct FloorObstacleWallDoor;
|
||||
struct FloorObstacleWallWindow;
|
||||
|
||||
struct FloorOutline : public std::vector<FloorOutlinePolygon*> {
|
||||
bool enabled = true;
|
||||
@@ -351,7 +358,6 @@ namespace Floorplan {
|
||||
Point2 to;
|
||||
float thickness_m;
|
||||
float height_m = 0; // 0 = floor's height
|
||||
std::vector<FloorObstacleWallDoor*> doors;
|
||||
FloorObstacleLine(const ObstacleType type, const Material material, const Point2 from, const Point2 to, const float thickness_m = 0.2f, const float height_m = 0) : FloorObstacle(material), type(type), from(from), to(to), thickness_m(thickness_m), height_m(height_m) {;}
|
||||
FloorObstacleLine(const ObstacleType type, const Material material, const float x1, const float y1, const float x2, const float y2, const float thickness_m = 0.2f, const float height_m = 0) : FloorObstacle(material), type(type), from(x1,y1), to(x2,y2), thickness_m(thickness_m), height_m(height_m) {;}
|
||||
};
|
||||
@@ -378,7 +384,21 @@ namespace Floorplan {
|
||||
float getSize() const {return (to-from).length();}
|
||||
};
|
||||
|
||||
/** door obstacle */
|
||||
|
||||
/** wall obstacle */
|
||||
struct FloorObstacleWall: public FloorObstacle {
|
||||
ObstacleType type;
|
||||
Point2 from;
|
||||
Point2 to;
|
||||
float thickness_m;
|
||||
float height_m = 0; // 0 = floor's height
|
||||
std::vector<FloorObstacleWallDoor*> doors;
|
||||
std::vector<FloorObstacleWallWindow*> windows;
|
||||
FloorObstacleWall(const ObstacleType type, const Material material, const Point2 from, const Point2 to, const float thickness_m = 0.2f, const float height_m = 0) : FloorObstacle(material), type(type), from(from), to(to), thickness_m(thickness_m), height_m(height_m) {;}
|
||||
FloorObstacleWall(const ObstacleType type, const Material material, const float x1, const float y1, const float x2, const float y2, const float thickness_m = 0.2f, const float height_m = 0) : FloorObstacle(material), type(type), from(x1,y1), to(x2,y2), thickness_m(thickness_m), height_m(height_m) {;}
|
||||
};
|
||||
|
||||
/** wall->door obstacle */
|
||||
struct FloorObstacleWallDoor : public FloorObstacle {
|
||||
DoorType type;
|
||||
float atLinePos;
|
||||
@@ -386,17 +406,40 @@ namespace Floorplan {
|
||||
float height;
|
||||
bool leftRight = false;
|
||||
bool inOut = false;
|
||||
FloorObstacleWallDoor(const DoorType type, const Material material, const float atLinePos, const float width, const float height) : FloorObstacle(material), type(type), atLinePos(atLinePos), width(width), height(height) {;}
|
||||
Point2 getStart(const FloorObstacleLine* wall) const {
|
||||
FloorObstacleWallDoor(const DoorType type, const Material material, const float atLinePos, const float width, const float height, const bool lr = false, const bool io = false) : FloorObstacle(material), type(type), atLinePos(atLinePos), width(width), height(height), leftRight(lr), inOut(io) {;}
|
||||
Point2 getStart(const FloorObstacleWall* wall) const {
|
||||
const Point2 dir = wall->to - wall->from;
|
||||
return wall->from + dir * atLinePos;
|
||||
}
|
||||
Point2 getEnd(const FloorObstacleLine* wall) const {
|
||||
Point2 getEnd(const FloorObstacleWall* wall) const {
|
||||
const Point2 dir = wall->to - wall->from;
|
||||
return getStart(wall) + dir.normalized() * (leftRight ? -width : +width);
|
||||
}
|
||||
};
|
||||
|
||||
/** wall->window obstacle */
|
||||
struct FloorObstacleWallWindow : public FloorObstacle {
|
||||
WindowType type;
|
||||
float atLinePos;
|
||||
float startsAtHeight;
|
||||
float width;
|
||||
float height;
|
||||
bool leftRight = false;
|
||||
bool inOut = false;
|
||||
FloorObstacleWallWindow(const WindowType type, const Material material, const float atLinePos, const float startsAtHeight, const float width, const float height, const bool lr = false, const bool io = false) : FloorObstacle(material), type(type), atLinePos(atLinePos), startsAtHeight(startsAtHeight), width(width), height(height), leftRight(lr), inOut(io) {;}
|
||||
Point2 getStart(const FloorObstacleWall* wall) const {
|
||||
const Point2 dir = wall->to - wall->from;
|
||||
const Point2 cen = wall->from + dir * atLinePos;
|
||||
return cen - dir.normalized() * width/2;
|
||||
}
|
||||
Point2 getEnd(const FloorObstacleWall* wall) const {
|
||||
const Point2 dir = wall->to - wall->from;
|
||||
const Point2 cen = wall->from + dir * atLinePos;
|
||||
return cen + dir.normalized() * width/2;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** 3D obstacle */
|
||||
struct FloorObstacleObject : public FloorObstacle {
|
||||
std::string file;
|
||||
|
||||
@@ -388,6 +388,7 @@ namespace Floorplan {
|
||||
// if (std::string("window") == n->Name()) {obstacles.push_back(parseFloorObstacleWindow(n));}
|
||||
// if (std::string("pillar") == n->Name()) {obstacles.push_back(parseFloorObstaclePillar(n));}
|
||||
//if (std::string("obstacle") == n->Name()) {obstacles.push_back(parseFloorObstacleLine(n));} // OLD
|
||||
if (std::string("wall") == n->Name()) {obstacles.push_back(parseFloorObstacleWall(n));}
|
||||
if (std::string("line") == n->Name()) {obstacles.push_back(parseFloorObstacleLine(n));}
|
||||
if (std::string("circle") == n->Name()) {obstacles.push_back(parseFloorObstacleCircle(n));}
|
||||
if (std::string("door") == n->Name()) {obstacles.push_back(parseFloorObstacleDoor(n));}
|
||||
@@ -396,6 +397,38 @@ namespace Floorplan {
|
||||
return obstacles;
|
||||
}
|
||||
|
||||
/** parse one wall */
|
||||
static FloorObstacleWall* parseFloorObstacleWall(const XMLElem* el) {
|
||||
|
||||
FloorObstacleWall* wall = new FloorObstacleWall(
|
||||
parseObstacleType(el->Attribute("type")),
|
||||
parseMaterial(el->Attribute("material")),
|
||||
el->FloatAttribute("x1"), el->FloatAttribute("y1"),
|
||||
el->FloatAttribute("x2"), el->FloatAttribute("y2"),
|
||||
(el->FloatAttribute("thickness") > 0) ? (el->FloatAttribute("thickness")) : (0.15), // default wall thickness in m
|
||||
el->FloatAttribute("height")
|
||||
);
|
||||
|
||||
// doors
|
||||
FOREACH_NODE(n, el) {
|
||||
if (std::string("door") == n->Name()) {
|
||||
FloorObstacleWallDoor* door = new FloorObstacleWallDoor(
|
||||
parseDoorType(n->Attribute("type")),
|
||||
parseMaterial(n->Attribute("material")),
|
||||
n->FloatAttribute("at"),
|
||||
n->FloatAttribute("width"),
|
||||
n->FloatAttribute("height"),
|
||||
n->BoolAttribute("lr"),
|
||||
n->BoolAttribute("io")
|
||||
);
|
||||
wall->doors.push_back(door);
|
||||
}
|
||||
}
|
||||
|
||||
return wall;
|
||||
|
||||
}
|
||||
|
||||
/** parse one line */
|
||||
static FloorObstacleLine* parseFloorObstacleLine(const XMLElem* el) {
|
||||
return new FloorObstacleLine(
|
||||
|
||||
@@ -311,6 +311,8 @@ namespace Floorplan {
|
||||
for (FloorObstacle* fo : mf->obstacles) {
|
||||
if (dynamic_cast<FloorObstacleLine*>(fo)) {
|
||||
addFloorObstacleLine(doc, obstacles, (FloorObstacleLine*)fo);
|
||||
} else if (dynamic_cast<FloorObstacleWall*>(fo)) {
|
||||
addFloorObstacleWall(doc, obstacles, (FloorObstacleWall*)fo);
|
||||
} else if (dynamic_cast<FloorObstacleCircle*>(fo)) {
|
||||
addFloorObstacleCircle(doc, obstacles, (FloorObstacleCircle*)fo);
|
||||
} else if (dynamic_cast<FloorObstacleDoor*>(fo)) {
|
||||
@@ -324,7 +326,40 @@ namespace Floorplan {
|
||||
|
||||
}
|
||||
|
||||
/** write a line obstacle (wall, handrail, ..) */
|
||||
/** write a wall obstacle (wall) */
|
||||
static void addFloorObstacleWall(XMLDoc& doc, XMLElem* obstacles, FloorObstacleWall* wall) {
|
||||
|
||||
XMLElem* oWall = doc.NewElement("wall");
|
||||
obstacles->InsertEndChild(oWall);
|
||||
|
||||
oWall->SetAttribute("material", toString(wall->material).c_str());
|
||||
oWall->SetAttribute("type", toString(wall->type).c_str());
|
||||
oWall->SetAttribute("x1", wall->from.x);
|
||||
oWall->SetAttribute("y1", wall->from.y);
|
||||
oWall->SetAttribute("x2", wall->to.x);
|
||||
oWall->SetAttribute("y2", wall->to.y);
|
||||
oWall->SetAttribute("thickness", wall->thickness_m);
|
||||
if (wall->height_m != 0) {oWall->SetAttribute("height", wall->height_m);}
|
||||
|
||||
// doors?
|
||||
for (const FloorObstacleWallDoor* door : wall->doors) {
|
||||
|
||||
XMLElem* oDoor = doc.NewElement("door");
|
||||
oWall->InsertEndChild(oDoor);
|
||||
|
||||
oDoor->SetAttribute("type", toString(door->type).c_str());
|
||||
oDoor->SetAttribute("material", toString(door->material).c_str());
|
||||
oDoor->SetAttribute("at", door->atLinePos);
|
||||
oDoor->SetAttribute("width", door->width);
|
||||
oDoor->SetAttribute("height", door->height);
|
||||
oDoor->SetAttribute("io", door->inOut);
|
||||
oDoor->SetAttribute("lr", door->leftRight);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** write a line obstacle (old walls, handrail, ..) */
|
||||
static void addFloorObstacleLine(XMLDoc& doc, XMLElem* obstacles, FloorObstacleLine* line) {
|
||||
XMLElem* obstacle = doc.NewElement("line");
|
||||
obstacle->SetAttribute("material", toString(line->material).c_str());
|
||||
|
||||
Reference in New Issue
Block a user