This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Indoor/floorplan/3D/Outline.h
2018-10-25 11:50:12 +02:00

110 lines
3.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* © Copyright 2014 Urheberrechtshinweis
* Alle Rechte vorbehalten / All Rights Reserved
*
* Programmcode ist urheberrechtlich geschuetzt.
* Das Urheberrecht liegt, soweit nicht ausdruecklich anders gekennzeichnet, bei Frank Ebner.
* Keine Verwendung ohne explizite Genehmigung.
* (vgl. § 106 ff UrhG / § 97 UrhG)
*/
#ifndef FLOORPLAN_3D_OUTLINE_H
#define FLOORPLAN_3D_OUTLINE_H
#include "Obstacle3.h"
#include "misc.h"
#include <unordered_map>
#include "../../geo/GPCPolygon2.h"
namespace Floorplan3D {
class Outline {
public:
/** convert a floor (floor/ceiling) into triangles */
std::vector<Obstacle3D> get(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;
}
};
}
#endif // FLOORPLAN_3D_OUTLINE_H