moved from ray3 to floorplan/3D
worked on new wall models refactoring
This commit is contained in:
643
wifi/estimate/ray3/ModelFactory_OLD.h
Normal file
643
wifi/estimate/ray3/ModelFactory_OLD.h
Normal file
@@ -0,0 +1,643 @@
|
||||
#ifndef MODELFACTORY_H
|
||||
#define MODELFACTORY_H
|
||||
|
||||
#include "../../../floorplan/v2/Floorplan.h"
|
||||
#include "../../../geo/Triangle3.h"
|
||||
#include "../../../geo/GPCPolygon2.h"
|
||||
|
||||
#include "Obstacle3.h"
|
||||
#include "Cube.h"
|
||||
#include "Tube.h"
|
||||
#include "Cylinder.h"
|
||||
#include "FloorplanMesh.h"
|
||||
#include "FloorPos.h"
|
||||
|
||||
#include "Walls.h"
|
||||
#include "WallsViaCubes.h"
|
||||
#include "WallsViaCuttedQuads.h"
|
||||
|
||||
#include "OBJPool.h"
|
||||
|
||||
namespace Ray3D {
|
||||
|
||||
/**
|
||||
* convert an indoor map into a 3D model based on triangles
|
||||
*/
|
||||
class ModelFactory {
|
||||
|
||||
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 exportWallTops = false;
|
||||
Cube::Part cubeParts = (Cube::Part) 63; // leftright,topbottom,rearfront
|
||||
|
||||
std::vector<Floorplan::Floor*> exportFloors;
|
||||
|
||||
/** the to-be-exported map */
|
||||
const Floorplan::IndoorMap* map;
|
||||
|
||||
//Walls* walls = new WallsViaCubes();
|
||||
Walls* walls = new WallsViaCuttedQuads();
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/** ctor */
|
||||
ModelFactory(const Floorplan::IndoorMap* map) : map(map) {
|
||||
|
||||
}
|
||||
|
||||
/** whether or not to export ceilings */
|
||||
void setExportCeilings(bool exp) {
|
||||
this->exportCeilings = exp;
|
||||
}
|
||||
|
||||
/** limit to-be-exported floors */
|
||||
void setFloors(const std::vector<Floorplan::Floor*> floors) {
|
||||
this->exportFloors = floors;
|
||||
}
|
||||
|
||||
/** convert floorplan to mesh */
|
||||
FloorplanMesh getMesh() {
|
||||
|
||||
FloorplanMesh mesh;
|
||||
mesh.elements = triangulize();
|
||||
return mesh;
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
/** get all triangles grouped by obstacle */
|
||||
std::vector<Obstacle3D> triangulize() {
|
||||
|
||||
std::vector<Obstacle3D> res;
|
||||
|
||||
// get the to-be-exported floors (either "all" or "user defined")
|
||||
const std::vector<Floorplan::Floor*>& floors = (exportFloors.empty()) ? (map->floors) : (exportFloors);
|
||||
|
||||
// process each floor
|
||||
for (const Floorplan::Floor* f : floors) {
|
||||
|
||||
if (!f->enabled) {continue;}
|
||||
|
||||
// reset wall-factory
|
||||
walls->clear();
|
||||
|
||||
// triangulize the floor itself (floor/ceiling)
|
||||
if (exportCeilings) {
|
||||
std::vector<Obstacle3D> tmp = getFloor(f);
|
||||
res.insert(res.end(), tmp.begin(), tmp.end());
|
||||
}
|
||||
|
||||
// process each obstacle within the floor
|
||||
if (f->obstacles.enabled) {
|
||||
for (const Floorplan::FloorObstacle* fo : f->obstacles) {
|
||||
std::vector<Obstacle3D> tmp = getObstacle(f, fo);
|
||||
res.insert(res.end(), tmp.begin(), tmp.end());
|
||||
}
|
||||
}
|
||||
|
||||
// append all created walls
|
||||
const std::vector<Obstacle3D>& oWalls = walls->get();
|
||||
res.insert(res.end(),oWalls.begin(), oWalls.end());
|
||||
|
||||
// stairs
|
||||
if (f->stairs.enabled) {
|
||||
for (const Floorplan::Stair* stair : f->stairs) {
|
||||
if (exportStairs) {res.push_back(getStairs(f, stair));}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove
|
||||
//break;
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/** convert a floor (floor/ceiling) into triangles */
|
||||
std::vector<Obstacle3D> getFloor(const Floorplan::Floor* f) {
|
||||
|
||||
FloorPos fpos(f);
|
||||
|
||||
std::vector<Obstacle3D> 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<std::string, GPCPolygon2> 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<std::vector<Point3>> polys = it.second.get(fpos.z1);
|
||||
|
||||
// convert polygons (GL_TRIANGLE_STRIP) to triangles
|
||||
for (const std::vector<Point3>& 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;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief build the given obstacle
|
||||
* @param f the floor
|
||||
* @param fo the obstacle
|
||||
* @param aboveDoor whether to place this obstacle ABOVE the given door (overwrite)
|
||||
* @return
|
||||
*/
|
||||
std::vector<Obstacle3D> getObstacle(const Floorplan::Floor* f, const Floorplan::FloorObstacle* fo, const Floorplan::FloorObstacleDoor* aboveDoor = nullptr) const {
|
||||
|
||||
std::vector<Obstacle3D> res;
|
||||
|
||||
// handle line obstacles
|
||||
const Floorplan::FloorObstacleLine* fol = dynamic_cast<const Floorplan::FloorObstacleLine*>(fo);
|
||||
if (fol) {
|
||||
if (exportObstacles) {
|
||||
if (fol->type != Floorplan::ObstacleType::HANDRAIL || exportHandrails) {
|
||||
res.push_back(getObstacleLine(f, fol, aboveDoor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handle circle obstacles
|
||||
const Floorplan::FloorObstacleCircle* foc = dynamic_cast<const Floorplan::FloorObstacleCircle*>(fo);
|
||||
if (foc) {
|
||||
if (exportObstacles) {
|
||||
res.push_back(getPillar(f, foc));
|
||||
}
|
||||
}
|
||||
|
||||
// handle object obstacles
|
||||
const Floorplan::FloorObstacleObject* foo = dynamic_cast<const Floorplan::FloorObstacleObject*>(fo);
|
||||
if (foo) {
|
||||
if (exportObjects) {
|
||||
if (!foo->file.empty()) {
|
||||
res.push_back(getObject(f, foo));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Floorplan::FloorObstacleDoor* door = dynamic_cast<const Floorplan::FloorObstacleDoor*>(fo);
|
||||
if (door) {
|
||||
if (exportObstacles) {
|
||||
if (exportDoors) {
|
||||
res.push_back(getDoor(f, door));
|
||||
}
|
||||
//std::vector<Obstacle3D> tmp = getDoorAbove(f, door);
|
||||
//res.insert(res.end(), tmp.begin(), tmp.end());
|
||||
if (exportAboveDoors) {
|
||||
res.push_back(getDoorAbove(f, door));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
/** convert a line obstacle to 3D triangles */
|
||||
Obstacle3D getObstacleLine(const Floorplan::Floor* f, const Floorplan::FloorObstacleLine* fol, const Floorplan::FloorObstacleDoor* aboveDoor = nullptr) const {
|
||||
|
||||
switch (fol->type) {
|
||||
case Floorplan::ObstacleType::HANDRAIL:
|
||||
return getHandrail(f, fol);
|
||||
case Floorplan::ObstacleType::WINDOW:
|
||||
return getWindow(f, fol, aboveDoor);
|
||||
case Floorplan::ObstacleType::WALL:
|
||||
addWall(f, fol, aboveDoor);
|
||||
return Obstacle3D();
|
||||
default:
|
||||
throw Exception("invalid obstacle type");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Obstacle3D getWindow(const Floorplan::Floor* f, const Floorplan::FloorObstacleLine* fol, const Floorplan::FloorObstacleDoor* aboveDoor) const {
|
||||
//return getWall(f, fol, aboveDoor);
|
||||
return Obstacle3D();
|
||||
}
|
||||
|
||||
Obstacle3D getPillar(const Floorplan::Floor* f, const Floorplan::FloorObstacleCircle* foc) const {
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
void addWall(const Floorplan::Floor* f, const Floorplan::FloorObstacleLine* fol, const Floorplan::FloorObstacleDoor* aboveDoor) const {
|
||||
walls->add(f, fol, aboveDoor);
|
||||
}
|
||||
|
||||
/** 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;
|
||||
|
||||
}
|
||||
|
||||
Obstacle3D getDoor(const Floorplan::Floor* f, const Floorplan::FloorObstacleDoor* door) const {
|
||||
|
||||
FloorPos fpos(f);
|
||||
|
||||
const float thickness_m = 0.10; // TODO??
|
||||
const Point2 from = door->from;
|
||||
const Point2 to = door->to;
|
||||
|
||||
const float rad = std::atan2(to.y - from.y, to.x - from.x);
|
||||
float deg = rad * 180 / M_PI;
|
||||
|
||||
// div by 2.01 to prevent overlapps and z-fighting
|
||||
const Point3 rot(0,0,deg);
|
||||
|
||||
Point3 pos;
|
||||
Matrix4 mat = Matrix4::identity();
|
||||
Obstacle3D res(Obstacle3D::Type::DOOR, door->material);
|
||||
|
||||
// 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, fpos.z1 + 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::unit(cubeParts);
|
||||
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, fpos.z1 + 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::unit();
|
||||
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<Triangle3> t1 = c1.getTriangles();
|
||||
res.triangles.insert(res.triangles.end(), t1.begin(), t1.end());
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
throw "unsupported door type";
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
/** get the missing part/gap, above the given door */
|
||||
Obstacle3D getDoorAbove(const Floorplan::Floor* f, const Floorplan::FloorObstacleDoor* door) const {
|
||||
|
||||
// find the element above the door (= a connected element)
|
||||
auto comp = [door] (const Floorplan::FloorObstacle* obs) {
|
||||
if (obs == door) {return false;}
|
||||
const Floorplan::FloorObstacleLine* line = dynamic_cast<const Floorplan::FloorObstacleLine*>(obs);
|
||||
if (!line) {return false;}
|
||||
return (line->from == door->from || line->to == door->from || line->from == door->to || line->to == door->to);
|
||||
};
|
||||
auto it = std::find_if(f->obstacles.begin(), f->obstacles.end(), comp);
|
||||
|
||||
// there is absolutely nothing attached directly to the door...
|
||||
if (it == f->obstacles.end()) {
|
||||
throw Exception("did not find a matching element to place above the door");
|
||||
}
|
||||
|
||||
// try to convert the element directly connected to the door into a line-obstacle
|
||||
const Floorplan::FloorObstacleLine* line = dynamic_cast<const Floorplan::FloorObstacleLine*> (*it);
|
||||
|
||||
// there seems to be no wall (but something else?!) attached to the door. fishy..
|
||||
if (!line) {
|
||||
throw Exception("did not find a matching wall to place above the door");
|
||||
}
|
||||
|
||||
// get the obstacle to place above the door
|
||||
return getObstacleLine(f, line, door);
|
||||
|
||||
}
|
||||
|
||||
Obstacle3D getHandrail(const Floorplan::Floor* f, const Floorplan::FloorObstacleLine* fol) const {
|
||||
|
||||
FloorPos fpos(f);
|
||||
|
||||
// target
|
||||
Obstacle3D res(getType(fol), fol->material);
|
||||
if (!exportHandrails) {return res;}
|
||||
|
||||
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<Triangle3> 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<Triangle3> tmp = cube.getTriangles();
|
||||
res.triangles.insert(res.triangles.end(), tmp.begin(), tmp.end());
|
||||
}
|
||||
|
||||
// done
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Obstacle3D getStairs(const Floorplan::Floor* f, const Floorplan::Stair* s) {
|
||||
|
||||
Obstacle3D res(Obstacle3D::Type::STAIR, Floorplan::Material::CONCRETE);
|
||||
|
||||
std::vector<Floorplan::Quad3> 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<Triangle3> 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<Triangle3> tmp = cube.getTriangles();
|
||||
res.triangles.insert(res.triangles.end(), tmp.begin(), tmp.end());
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
/** convert a line obstacle to 3D triangles */
|
||||
/*
|
||||
Obstacle3D getStairs(const Floorplan::Floor* f, const Floorplan::Stair* s) {
|
||||
|
||||
Obstacle3D res(Obstacle3D::Type::STAIR, Floorplan::Material::CONCRETE);
|
||||
|
||||
std::vector<Floorplan::Quad3> quads = Floorplan::getQuads(s->getParts(), f);
|
||||
for (const Floorplan::Quad3& quad : quads) {
|
||||
|
||||
if (!fancyStairs || quad.isLeveled()) {
|
||||
|
||||
const Triangle3 t1(quad.p1, quad.p2, quad.p3);
|
||||
const Triangle3 t2(quad.p3, quad.p4, quad.p1);
|
||||
res.triangles.push_back(t1);
|
||||
res.triangles.push_back(t2);
|
||||
|
||||
} else {
|
||||
|
||||
const Point3 dir1 = quad.p3 - quad.p2;
|
||||
const Point3 dir2 = quad.p4 - quad.p1;
|
||||
const float stepH = 0.20;
|
||||
const float totalH = quad.p3.z - quad.p1.z;
|
||||
const int numStairs = std::round(totalH / stepH);
|
||||
for (int i = 0; i < numStairs; ++i) {
|
||||
|
||||
//const float y1 = quad.p1.z + (stepH * i);
|
||||
//const float y2 = y1 + stepH;
|
||||
|
||||
const Point3 p1 = quad.p1 + dir1 * (i+0) / numStairs;
|
||||
const Point3 p2 = quad.p2 + dir2 * (i+0) / numStairs;
|
||||
|
||||
const Point3 p3 = quad.p2 + dir2 * (i+1) / numStairs;
|
||||
const Point3 p4 = quad.p1 + dir1 * (i+1) / numStairs;
|
||||
|
||||
//const Point3 p14(p4.x, p4.y, p1.z);
|
||||
//const Point3 p23(p3.x, p3.y, p2.z);
|
||||
const Point3 p14(p1.x, p1.y, p4.z);
|
||||
const Point3 p23(p2.x, p2.y, p3.z);
|
||||
|
||||
// up
|
||||
const Triangle3 t1(p1, p2, p23);
|
||||
const Triangle3 t2(p23, p14, p1);
|
||||
res.triangles.push_back(t1);
|
||||
res.triangles.push_back(t2);
|
||||
|
||||
// group
|
||||
const Triangle3 t3(p14, p23, p3);
|
||||
const Triangle3 t4(p3, p4, p14);
|
||||
res.triangles.push_back(t3);
|
||||
res.triangles.push_back(t4);
|
||||
|
||||
// side s
|
||||
const Triangle3 s1(p2, p3, p23);
|
||||
const Triangle3 s2(p1, p14, p4);
|
||||
res.triangles.push_back(s1);
|
||||
res.triangles.push_back(s2);
|
||||
|
||||
// facing down
|
||||
const Triangle3 d1(quad.p1, quad.p3, quad.p2);
|
||||
const Triangle3 d2(quad.p3, quad.p1, quad.p4);
|
||||
res.triangles.push_back(d1);
|
||||
res.triangles.push_back(d2);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MODELFACTORY_H
|
||||
Reference in New Issue
Block a user