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/FloorplanFactorySVG.h
2018-10-25 11:50:12 +02:00

222 lines
4.7 KiB
C++
Executable File
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 FLOORPLANFACTORYSVG_H
#define FLOORPLANFACTORYSVG_H
#include "Floor.h"
#include "Stairs.h"
#include <string>
#include "../Exception.h"
#include <KLib/gfx/svg/SVGLoader.h>
/**
* load floorplans from SVG files
*/
class FloorplanFactorySVG {
/**
* helper class for SVG floorplans.
*
* converts between the SVG's scale and real-world scale
*/
class SVGScaler {
private:
/** the scaling factor to apply to the svg data */
const double scalingFactor;
public:
/** ctor */
SVGScaler(const double scalingFactor) : scalingFactor(scalingFactor) {
;
}
/** scale (x, y) into (_x, _y) */
void scale(const double x, const double y, float& _x, float& _y) const {
_x = x * scalingFactor;
_y = y * scalingFactor;
}
// /** scale the given point into a new output point */
// K::Point scale(const K::Point p) const {
// K::Point ret;
// scale (p.x, p.y, ret.x, ret.y);
// return ret;
// }
/** scale the given line into a new output line */
Line2 scale(const K::Line l) const {
Line2 ret;
scale (l.p1.x, l.p1.y, ret.p1.x, ret.p1.y);
scale (l.p2.x, l.p2.y, ret.p2.x, ret.p2.y);
return ret;
}
};
private:
K::SVGFile svg;
SVGScaler scaler;
float width;
float depth;
public:
/** ctor with svg filename and scaling factor */
FloorplanFactorySVG(const std::string& file, const float scaling) : scaler(scaling) {
// load the SVG
K::SVGLoader::load(K::File(file), &svg);
scaler.scale(svg.getWidth(), svg.getHeight(), width, depth);
}
/** get the width of the building */
float getWidth() const {return width;}
/** get the depth of the building */
float getDepth() const {return depth;}
/** get the floor identified by the given layer name */
Floor getFloor(const std::string layerName) {
// get the requested SVG layer
K::SVGComposite* sc = svg.getLayers();
K::SVGLayer* layer = sc->getContainedLayerNamed(layerName);
if (!layer) {throw Exception("SVG has no layer named '" + layerName + "'");}
// create and parse the new floor
Floor floor(width, depth);
loadFloor(layer, floor);
return floor;
}
/** get all stairs within the given layer */
Stairs getStairs(const std::string& layerName) {
// get the requested SVG layer
K::SVGComposite* sc = svg.getLayers();
K::SVGLayer* layer = sc->getContainedLayerNamed(layerName);
if (!layer) {throw Exception("SVG has no layer named '" + layerName + "'");}
// create and parse the new floor
Stairs stairs;
loadStairs(layer, stairs);
return stairs;
}
private:
/** recursive loading/parsing of nested SVG elements */
void loadFloor(K::SVGElement* el, Floor& floor) {
switch (el->getType()) {
case SVGElementType::COMPOSITE: {
for (K::SVGElement* sub : ((K::SVGComposite*)el)->getChilds()) {
loadFloor(sub, floor);
}
break;
}
case SVGElementType::LAYER: {
K::SVGLayer* layer = (K::SVGLayer*) el;
for (K::SVGElement* sub : layer->getChilds()) {
loadFloor(sub, floor);
}
break;
}
case SVGElementType::PATH: {
for (const K::Line& line : ((K::SVGPath*)el)->getLines()) {
floor.addObstacle( scaler.scale(line) );
}
break;
}
case SVGElementType::TEXT: {
break;
}
default:
throw "should not happen!";
}
}
/** recursive loading/parsing of nested SVG elements */
void loadStairs(K::SVGElement* el, Stairs& stairs) {
switch (el->getType()) {
case SVGElementType::COMPOSITE: {
for (K::SVGElement* sub : ((K::SVGComposite*)el)->getChilds()) {
loadStairs(sub, stairs);
}
break;
}
case SVGElementType::LAYER: {
K::SVGLayer* layer = (K::SVGLayer*) el;
for (K::SVGElement* sub : layer->getChilds()) {
loadStairs(sub, stairs);
}
break;
}
case SVGElementType::PATH: {
int i = 0;
Line2 start;
Line2 dir;
for (const K::Line& line : ((K::SVGPath*)el)->getLines()) {
if (++i == 1) {
start = scaler.scale(line);
} else {
Stair s;
Line2 dir = scaler.scale(line);
s.dir = (dir.p2 - dir.p1);
// const float d = 50;
s.start = start;
// s.from.add(start.p1 + Point2(-d,-d));
// s.from.add(start.p1 + Point2(+d,+d));
// s.from.add(start.p2 + Point2(-d,-d));
// s.from.add(start.p2 + Point2(+d,+d));
stairs.push_back(s);
}
}
break;
}
case SVGElementType::TEXT: {
break;
}
default:
throw "should not happen!";
}
}
};
#endif // FLOORPLANFACTORYSVG_H