worked on floorplan (v2)
worked on grid-generation (v2) new helper methods for geometry new test cases
This commit is contained in:
@@ -11,7 +11,28 @@
|
||||
|
||||
namespace Floorplan {
|
||||
|
||||
/** 3D polygon */
|
||||
|
||||
/** a free key-value meta element */
|
||||
struct Meta {
|
||||
|
||||
const std::string EMPTY = "";
|
||||
std::unordered_map<std::string, std::string> params;
|
||||
|
||||
const std::string& getVal(const std::string& key) const {
|
||||
const auto it = params.find(key);
|
||||
return (it == params.end()) ? (EMPTY) : (it->second);
|
||||
}
|
||||
void setVal(const std::string& key, const std::string& val) {params[key] = val;}
|
||||
|
||||
float getFloat(const std::string& key) const { return std::stof(getVal(key)); }
|
||||
void setFloat(const std::string& key, const float val) { params[key] = std::to_string(val); }
|
||||
|
||||
int getInt(const std::string& key) const { return std::stoi(getVal(key)); }
|
||||
void setInt(const std::string& key, const int val) { params[key] = std::to_string(val); }
|
||||
|
||||
};
|
||||
|
||||
/** 2D polygon */
|
||||
struct Polygon2 {
|
||||
std::vector<Point2> points;
|
||||
Polygon2() : points() {;}
|
||||
@@ -19,17 +40,37 @@ namespace Floorplan {
|
||||
bool operator == (const Polygon2& o) const {return std::equal(o.points.begin(), o.points.end(), this->points.begin());}
|
||||
};
|
||||
|
||||
/** 3D quad */
|
||||
struct Quad3 {
|
||||
Point3 p1;
|
||||
Point3 p2;
|
||||
Point3 p3;
|
||||
Point3 p4;
|
||||
Quad3(const Point3 p1, const Point3 p2, const Point3 p3, const Point3 p4) : p1(p1), p2(p2), p3(p3), p4(p4) {;}
|
||||
Quad3 operator * (const float v) const {return Quad3(p1*v, p2*v, p3*v, p4*v);}
|
||||
};
|
||||
|
||||
/** additional type-info for obstacles */
|
||||
enum class ObstacleType {
|
||||
UNKNOWN,
|
||||
WALL,
|
||||
DOOR,
|
||||
WINDOW,
|
||||
HANDRAIL,
|
||||
PILLAR,
|
||||
_END,
|
||||
};
|
||||
|
||||
/** available door types */
|
||||
enum class DoorType {
|
||||
UNKNOWN,
|
||||
SWING, // normal
|
||||
DOUBLE_SWING,
|
||||
SLIDE, // schiebetuer
|
||||
DOUBLE_SLIDE,
|
||||
REVOLVING, // drehtuer
|
||||
_END,
|
||||
};
|
||||
|
||||
/** all supported material types */
|
||||
enum class Material {
|
||||
UNKNOWN,
|
||||
@@ -40,6 +81,10 @@ namespace Floorplan {
|
||||
_END,
|
||||
};
|
||||
|
||||
enum class POIType {
|
||||
ROOM,
|
||||
};
|
||||
|
||||
/** types of outlines. either add or remove the selected region */
|
||||
enum class OutlineMethod {
|
||||
ADD,
|
||||
@@ -47,23 +92,78 @@ namespace Floorplan {
|
||||
_END,
|
||||
};
|
||||
|
||||
struct Floor;
|
||||
struct FloorOutlinePolygon;
|
||||
struct FloorObstacle;
|
||||
struct AccessPoint;
|
||||
struct Beacon;
|
||||
struct FloorRegion;
|
||||
struct UnderlayImage;
|
||||
struct POI;
|
||||
struct Stair;
|
||||
|
||||
using FloorOutline = std::vector<FloorOutlinePolygon*>;
|
||||
using FloorObstacles = std::vector<FloorObstacle*>;
|
||||
using FloorAccessPoints = std::vector<AccessPoint*>;
|
||||
using FloorBeacons = std::vector<Beacon*>;
|
||||
using FloorRegions = std::vector<FloorRegion*>;
|
||||
using FloorUnderlays = std::vector<UnderlayImage*>;
|
||||
using FloorPOIs = std::vector<POI*>;
|
||||
using FloorStairs = std::vector<Stair*>;
|
||||
|
||||
/** describes one floor within the map, starting at a given height */
|
||||
struct Floor {
|
||||
|
||||
float atHeight; // the floor's starting height
|
||||
float height; // the floor's total height (from start)
|
||||
std::string name; // the floor's name
|
||||
FloorOutline outline; // the floor's outline (ground)
|
||||
FloorObstacles obstacles; // all obstacles (wall, door, window, ..) within the floor
|
||||
FloorRegions regions; // all regions within the floor (rooms, ...)
|
||||
FloorAccessPoints accesspoints;
|
||||
FloorBeacons beacons;
|
||||
FloorUnderlays underlays; // underlay images (used for map-building)
|
||||
FloorPOIs pois; // POIs within the floor
|
||||
FloorStairs stairs; // all stairs within one floor
|
||||
//FloorKeyValue other; // other, free elements
|
||||
|
||||
Floor() {;}
|
||||
|
||||
Floor(const Floor& o) = delete;
|
||||
void operator = (const Floor& o) = delete;
|
||||
|
||||
float getStartingZ() const {return atHeight;}
|
||||
float getEndingZ() const {return atHeight + height;}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/** an AccessPoint located somewhere within the map */
|
||||
/** a POI located somewhere on a floor */
|
||||
struct POI {
|
||||
POIType type;
|
||||
std::string name;
|
||||
Point2 pos;
|
||||
POI() : type(), name(), pos() {;}
|
||||
POI(const POIType type, const std::string& name, const Point2& pos) : type(type), name(name), pos(pos) {;}
|
||||
bool operator == (const POI& o) const {return (o.type == type) && (o.name == name) && (o.pos == pos);}
|
||||
};
|
||||
|
||||
/** an AccessPoint located somewhere on a floor */
|
||||
struct AccessPoint {
|
||||
std::string name;
|
||||
std::string mac;
|
||||
Point3 pos;
|
||||
Point3 pos; // z is relative to the floor's height
|
||||
AccessPoint() : name(), mac(), pos() {;}
|
||||
AccessPoint(const std::string& name, const std::string& mac, const Point3& pos) : name(name), mac(mac), pos(pos) {;}
|
||||
bool operator == (const AccessPoint& o) const {return (o.name == name) && (o.mac == mac) && (o.pos == pos);}
|
||||
Point3 getPos(const Floor* f) const {return pos + Point3(0,0,f->atHeight);} // relative to the floor's ground
|
||||
};
|
||||
|
||||
/** a beacon located somewhere within the map */
|
||||
/** a beacon located somewhere on a floor */
|
||||
struct Beacon {
|
||||
std::string name;
|
||||
std::string mac;
|
||||
Point3 pos;
|
||||
Point3 pos; // z is relative to the floor's height
|
||||
Beacon() : name(), mac(), pos() {;}
|
||||
Beacon(const std::string& name, const std::string& mac, const Point3& pos) : name(name), mac(mac), pos(pos) {;}
|
||||
bool operator == (const Beacon& o) const {return (o.name == name) && (o.mac == mac) && (o.pos == pos);}
|
||||
@@ -80,31 +180,51 @@ namespace Floorplan {
|
||||
bool operator == (const FloorOutlinePolygon& o) const {return (o.method == method) && (o.name == name) && (o.poly == poly);}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** base-class for one obstacle (wall, door, window, pillar, ..) within a floor */
|
||||
struct FloorObstacle {
|
||||
ObstacleType type;
|
||||
Material material;
|
||||
FloorObstacle() : type(), material() {;}
|
||||
FloorObstacle(const ObstacleType type, const Material material) : type(type), material(material) {;}
|
||||
FloorObstacle() : material() {;}
|
||||
FloorObstacle(const Material material) : material(material) {;}
|
||||
virtual ~FloorObstacle() {;}
|
||||
};
|
||||
|
||||
/** line obstacle */
|
||||
struct FloorObstacleLine : public FloorObstacle {
|
||||
ObstacleType type;
|
||||
Point2 from;
|
||||
Point2 to;
|
||||
FloorObstacleLine(const ObstacleType type, const Material material, const Point2 from, const Point2 to) : FloorObstacle(type, material), from(from), to(to) {;}
|
||||
FloorObstacleLine(const ObstacleType type, const Material material, const float x1, const float y1, const float x2, const float y2) : FloorObstacle(type, material), from(x1,y1), to(x2,y2) {;}
|
||||
FloorObstacleLine(const ObstacleType type, const Material material, const Point2 from, const Point2 to) : FloorObstacle(material), type(type), from(from), to(to) {;}
|
||||
FloorObstacleLine(const ObstacleType type, const Material material, const float x1, const float y1, const float x2, const float y2) : FloorObstacle(material), type(type), from(x1,y1), to(x2,y2) {;}
|
||||
};
|
||||
|
||||
/** circle obstacle */
|
||||
struct FloorObstacleCircle : public FloorObstacle {
|
||||
Point2 center;
|
||||
float radius;
|
||||
FloorObstacleCircle(const ObstacleType type, const Material material, const Point2 center, const float radius) : FloorObstacle(type, material), center(center), radius(radius) {;}
|
||||
FloorObstacleCircle(const ObstacleType type, const Material material, const float cx, const float cy, const float radius) : FloorObstacle(type, material), center(cx,cy), radius(radius) {;}
|
||||
FloorObstacleCircle(const Material material, const Point2 center, const float radius) : FloorObstacle(material), center(center), radius(radius) {;}
|
||||
FloorObstacleCircle(const Material material, const float cx, const float cy, const float radius) : FloorObstacle(material), center(cx,cy), radius(radius) {;}
|
||||
};
|
||||
|
||||
/** door obstacle */
|
||||
struct FloorObstacleDoor : public FloorObstacle {
|
||||
DoorType type;
|
||||
Point2 from;
|
||||
Point2 to;
|
||||
float height;
|
||||
bool swap;
|
||||
FloorObstacleDoor(const DoorType type, const Material material, const Point2 from, const Point2 to) : FloorObstacle(material), type(type), from(from), to(to), height(2.1), swap(false) {;}
|
||||
FloorObstacleDoor(const DoorType type, const Material material, const float x1, const float y1, const float x2, const float y2, const float height, const bool swap) : FloorObstacle(material), type(type), from(x1,y1), to(x2,y2), height(height), swap(swap) {;}
|
||||
float getSize() const {return (to-from).length();}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** one region (e.g. a room) within the floor, described using a polygon */
|
||||
struct FloorRegion {
|
||||
std::string name;
|
||||
@@ -115,6 +235,158 @@ namespace Floorplan {
|
||||
|
||||
|
||||
|
||||
static Point3 xy0(const Point2 p) {
|
||||
return Point3(p.x, p.y, 0);
|
||||
}
|
||||
|
||||
/** describes a plane as starting point, ending point and fixed width */
|
||||
struct StairPart {
|
||||
|
||||
/** z is relative to the floor's height */
|
||||
Point3 start;
|
||||
|
||||
/** z is relative to the floor's height */
|
||||
Point3 end;
|
||||
|
||||
/** the width for this element */
|
||||
float width;
|
||||
|
||||
/** whether to connect this element with the previous one */
|
||||
bool connectWithPrev;
|
||||
|
||||
StairPart() {;}
|
||||
|
||||
StairPart(const Point3 start, const Point3 end, const float width) : start(start), end(end), width(width), connectWithPrev(false) {;}
|
||||
|
||||
StairPart(Point3 center, float deg, float length, float width, float height) {
|
||||
this->start = Point3(-length/2, 0, -height/2);
|
||||
this->end = Point3(+length/2, 0, +height/2);
|
||||
this->width = width;
|
||||
rotate(deg/180.0*M_PI);
|
||||
move(center);
|
||||
}
|
||||
|
||||
/** convenience method for array access [0:1] to start and end */
|
||||
Point3& operator [] (const int idx) {
|
||||
switch (idx) {
|
||||
case 0: return start;
|
||||
case 1: return end;
|
||||
default: throw "error";
|
||||
}
|
||||
}
|
||||
|
||||
void rotate(const float rad) {
|
||||
const float ca = std::cos(rad);
|
||||
const float sa = std::sin(rad);
|
||||
start = Point3(ca*start.x - sa*start.y, sa*start.x + ca * start.y, start.z);
|
||||
end = Point3(ca*end.x - sa*end.y, sa*end.x + ca * end.y, end.z);;
|
||||
}
|
||||
|
||||
void move(const Point3 p) {
|
||||
start += p;
|
||||
end += p;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static std::vector<Quad3> getQuads(const std::vector<StairPart>& parts, const Floor* floor) {
|
||||
|
||||
std::vector<Quad3> vec;
|
||||
|
||||
for (const StairPart& part : parts) {
|
||||
|
||||
const float width = part.width;
|
||||
const Point3 start = part.start;
|
||||
const Point3 end = part.end;
|
||||
const Point3 dir = end - start; // direction vector
|
||||
const Point2 dir2(dir.x, dir.y); // direction without height (just 2D)
|
||||
const Point2 perp = dir2.perpendicular(); // perendicular vector
|
||||
const Point2 perpN = perp / perp.length(); // normalized perpendicular vector
|
||||
const Point3 p1 = start + xy0(perpN * width / 2) + Point3(0,0,floor->atHeight);
|
||||
const Point3 p2 = start - xy0(perpN * width / 2) + Point3(0,0,floor->atHeight);
|
||||
const Point3 p3 = end - xy0(perpN * width / 2) + Point3(0,0,floor->atHeight);
|
||||
const Point3 p4 = end + xy0(perpN * width / 2) + Point3(0,0,floor->atHeight);
|
||||
const Quad3 q(p1,p2,p3,p4);
|
||||
vec.push_back(q);
|
||||
|
||||
// connect
|
||||
if (part.connectWithPrev) {
|
||||
if (vec.size() >= 2) {
|
||||
Quad3& a = vec[vec.size()-2];
|
||||
Quad3& b = vec[vec.size()-1];
|
||||
Point3 pa = (a.p3 + b.p2)/2; a.p3 = pa; b.p2 = pa;
|
||||
Point3 pb = (a.p4 + b.p1)/2; a.p4 = pb; b.p1 = pb;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return vec;
|
||||
|
||||
}
|
||||
|
||||
// /**
|
||||
// * get the ABSOLUTE quad for this stair-part
|
||||
// * (relative-height + floor-height = absolute-height
|
||||
// */
|
||||
// Quad3 getQuad(const Floor* floor) const {
|
||||
|
||||
// }
|
||||
|
||||
/** base-class for stairs */
|
||||
struct Stair {
|
||||
Meta* meta = nullptr;
|
||||
virtual std::vector<StairPart> getParts() const = 0;
|
||||
};
|
||||
|
||||
// /** just a normal, straigt stair */
|
||||
// struct StairNormal : public Stair {
|
||||
// Point2 center;
|
||||
// float angleDeg;
|
||||
// float atHeight;
|
||||
// float height;
|
||||
// float width;
|
||||
// float length;
|
||||
// StairNormal(const Point2 center, const float atHeight, const float angleDeg, const float height, const float width, const float length) :
|
||||
// center(center), angleDeg(angleDeg), atHeight(atHeight), height(height), width(width), length(length) {
|
||||
|
||||
|
||||
// }
|
||||
// std::vector<StairPart> getParts() const {
|
||||
// std::vector<StairPart> parts;
|
||||
// Point3 cen(center.x, center.y, atHeight);
|
||||
// parts.push_back(StairPart(cen, angleDeg, length, width, height));
|
||||
// return parts;
|
||||
// }
|
||||
// };
|
||||
|
||||
// /** OLD 3-part stair, up[left]->platform->up[right] */
|
||||
// struct StairFreeformOLD : public Stair {
|
||||
// float width;
|
||||
// std::vector<Point3> nodes;
|
||||
// StairFreeformOLD() {;}
|
||||
// std::vector<StairPart> getParts() const {
|
||||
// std::vector<StairPart> parts;
|
||||
// for (int i = 1; i < (int)nodes.size(); ++i) {
|
||||
// const Point3 p1 = nodes[i-1];
|
||||
// const Point3 p2 = nodes[i ];
|
||||
// parts.push_back(StairPart(p1, p2, width));
|
||||
// }
|
||||
// return parts;
|
||||
// }
|
||||
// };
|
||||
|
||||
/** 3-part stair, up[left]->platform->up[right] */
|
||||
struct StairFreeform : public Stair {
|
||||
std::vector<StairPart> parts;
|
||||
StairFreeform() {;}
|
||||
std::vector<StairPart> getParts() const {return parts;}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** an image file that can be added to the map */
|
||||
struct UnderlayImage {
|
||||
std::string name;
|
||||
@@ -124,50 +396,7 @@ namespace Floorplan {
|
||||
float scaleY;
|
||||
};
|
||||
|
||||
/** a free key-value element */
|
||||
struct KeyValueElement {
|
||||
std::string empty;
|
||||
std::unordered_map<std::string, std::string> params;
|
||||
const std::string& getVal(const std::string& key) const {
|
||||
auto it = params.find(key);
|
||||
return (it == params.end()) ? (empty) : (it->second);
|
||||
}
|
||||
float getFloat(const std::string& key) const { return std::stof(getVal(key)); }
|
||||
void setVal(const std::string& key, const std::string& val) {
|
||||
params[key] = val;
|
||||
}
|
||||
void setFloat(const std::string& key, const float val) {
|
||||
params[key] = std::to_string(val);
|
||||
}
|
||||
};
|
||||
|
||||
using FloorOutline = std::vector<FloorOutlinePolygon*>;
|
||||
using FloorObstacles = std::vector<FloorObstacle*>;
|
||||
using FloorAccessPoints = std::vector<AccessPoint*>;
|
||||
using FloorBeacons = std::vector<Beacon*>;
|
||||
using FloorRegions = std::vector<FloorRegion*>;
|
||||
using FloorUnderlays = std::vector<UnderlayImage*>;
|
||||
|
||||
/** describes one floor within the map, starting at a given height */
|
||||
struct Floor {
|
||||
|
||||
float atHeight; // the floor's starting height
|
||||
float height; // the floor's total height (from start)
|
||||
std::string name; // the floor's name
|
||||
FloorOutline outline; // the floor's outline (ground)
|
||||
FloorObstacles obstacles; // all obstacles (wall, door, window, ..) within the floor
|
||||
FloorRegions regions; // all regions within the floor (rooms, ...)
|
||||
FloorAccessPoints accesspoints;
|
||||
FloorBeacons beacons;
|
||||
FloorUnderlays underlays; // underlay images (used for map-building)
|
||||
//FloorKeyValue other; // other, free elements
|
||||
|
||||
Floor() {;}
|
||||
|
||||
Floor(const Floor& o) = delete;
|
||||
void operator = (const Floor& o) = delete;
|
||||
|
||||
};
|
||||
|
||||
/** describes the whole indoor map */
|
||||
struct IndoorMap {
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
|
||||
namespace Floorplan {
|
||||
|
||||
using namespace tinyxml2;
|
||||
using XMLAttr = tinyxml2::XMLAttribute;
|
||||
using XMLElem = tinyxml2::XMLElement;
|
||||
|
||||
/**
|
||||
* read an IndoorMaps from XML-data
|
||||
@@ -22,35 +23,37 @@ namespace Floorplan {
|
||||
/** read an IndoorMap from the given XML-file */
|
||||
static IndoorMap* readFromFile(const std::string& file) {
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
XMLDocument doc;
|
||||
doc.LoadFile(file.c_str());
|
||||
tinyxml2::XMLDocument doc;
|
||||
const tinyxml2::XMLError res = doc.LoadFile(file.c_str());
|
||||
if (res != tinyxml2::XMLError::XML_SUCCESS) {throw Exception("error while loading XML " + file);}
|
||||
return parse(doc);
|
||||
}
|
||||
|
||||
/** read an IndoorMap from the given XMl-string */
|
||||
static IndoorMap* readFromString(const std::string& str) {
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
XMLDocument doc;
|
||||
doc.Parse(str.c_str(), str.length());
|
||||
tinyxml2::XMLDocument doc;
|
||||
const tinyxml2::XMLError res = doc.Parse(str.c_str(), str.length());
|
||||
if (res != tinyxml2::XMLError::XML_SUCCESS) {throw Exception("error while parsing XML");}
|
||||
return parse(doc);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
#define FOREACH_NODE(out, in) for( const XMLElement* out = (XMLElement*) in->FirstChild(); out; out = (XMLElement*) out->NextSibling() )
|
||||
#define FOREACH_NODE(out, in) for( const XMLElem* out = (XMLElem*) in->FirstChild(); out; out = (XMLElem*) out->NextSibling() )
|
||||
|
||||
static void assertNode(const std::string& node, const XMLElement* el) {
|
||||
static void assertNode(const std::string& node, const XMLElem* el) {
|
||||
std::string err = std::string("unexpected node '") + el->Name() + "' expected '" + node + "'";
|
||||
Assert::equal(node, std::string(el->Name()), err);
|
||||
}
|
||||
|
||||
/** parse the complete document */
|
||||
static IndoorMap* parse(XMLDocument& doc) {
|
||||
return parseMap((XMLElement*)doc.FirstChild());
|
||||
static IndoorMap* parse(tinyxml2::XMLDocument& doc) {
|
||||
return parseMap((XMLElem*)doc.FirstChild());
|
||||
}
|
||||
|
||||
/** parse the <map> node */
|
||||
static IndoorMap* parseMap(const XMLElement* el) {
|
||||
static IndoorMap* parseMap(const XMLElem* el) {
|
||||
std::cout << el->Name() << std::endl;
|
||||
IndoorMap* map = new IndoorMap();
|
||||
map->width = el->FloatAttribute("width");
|
||||
@@ -62,7 +65,7 @@ namespace Floorplan {
|
||||
}
|
||||
|
||||
/** parse the <floors> node */
|
||||
static std::vector<Floor*> parseFloors(const XMLElement* el) {
|
||||
static std::vector<Floor*> parseFloors(const XMLElem* el) {
|
||||
std::vector<Floor*> floors;
|
||||
FOREACH_NODE(n, el) {
|
||||
if (std::string("floor") == n->Name()) {floors.push_back(parseFloor(n));}
|
||||
@@ -71,25 +74,91 @@ namespace Floorplan {
|
||||
}
|
||||
|
||||
/** parse one <floor> node */
|
||||
static Floor* parseFloor(const XMLElement* el) {
|
||||
static Floor* parseFloor(const XMLElem* el) {
|
||||
Floor* floor = new Floor();
|
||||
floor->atHeight = el->FloatAttribute("atHeight");
|
||||
floor->height = el->FloatAttribute("height");
|
||||
floor->name = el->Attribute("name");
|
||||
FOREACH_NODE(n, el) {
|
||||
if (std::string("outline") == n->Name()) {floor->outline = parseFloorOutline(n);}
|
||||
if (std::string("obstacles") == n->Name()) {floor->obstacles = parseFloorObstacles(n);}
|
||||
if (std::string("outline") == n->Name()) {floor->outline = parseFloorOutline(n);}
|
||||
if (std::string("obstacles") == n->Name()) {floor->obstacles = parseFloorObstacles(n);}
|
||||
if (std::string("accesspoints") == n->Name()) {floor->accesspoints = parseFloorAccessPoints(n);}
|
||||
if (std::string("beacons") == n->Name()) {floor->beacons = parseFloorBeacons(n);}
|
||||
if (std::string("regions") == n->Name()) {floor->regions = parseFloorRegions(n);}
|
||||
if (std::string("underlays") == n->Name()) {floor->underlays = parseFloorUnderlays(n);}
|
||||
if (std::string("beacons") == n->Name()) {floor->beacons = parseFloorBeacons(n);}
|
||||
if (std::string("regions") == n->Name()) {floor->regions = parseFloorRegions(n);}
|
||||
if (std::string("underlays") == n->Name()) {floor->underlays = parseFloorUnderlays(n);}
|
||||
if (std::string("pois") == n->Name()) {floor->pois = parseFloorPOIs(n);}
|
||||
if (std::string("stairs") == n->Name()) {floor->stairs = parseFloorStairs(n);}
|
||||
}
|
||||
return floor;
|
||||
}
|
||||
|
||||
|
||||
/** parse the <stairs> tag */
|
||||
static std::vector<Stair*> parseFloorStairs(const XMLElem* el) {
|
||||
std::vector<Stair*> vec;
|
||||
FOREACH_NODE(n, el) {
|
||||
if (std::string("stair") == n->Name()) { vec.push_back(parseFloorStair(n)); }
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
/** parse a <stair> tag */
|
||||
static Stair* parseFloorStair(const XMLElem* el) {
|
||||
Stair* stair = nullptr;
|
||||
if (el->IntAttribute("type") == 0) {
|
||||
stair = new StairFreeform();
|
||||
FOREACH_NODE(n, el) {
|
||||
if (std::string("part") == n->Name()) {
|
||||
StairPart part;
|
||||
part.connectWithPrev = n->BoolAttribute("connect");
|
||||
part.start.x = n->FloatAttribute("x1");
|
||||
part.start.y = n->FloatAttribute("y1");
|
||||
part.start.z = n->FloatAttribute("z1");
|
||||
part.end.x = n->FloatAttribute("x2");
|
||||
part.end.y = n->FloatAttribute("y2");
|
||||
part.end.z = n->FloatAttribute("z2");
|
||||
part.width = n->FloatAttribute("w");
|
||||
((StairFreeform*)stair)->parts.push_back(part);
|
||||
} else {
|
||||
throw "not yet implemented";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw "not yet implemented";
|
||||
}
|
||||
|
||||
// stair meta information?
|
||||
const XMLElem* meta = el->FirstChildElement("meta");
|
||||
if (meta) {
|
||||
stair->meta = parseMetaElement(meta);
|
||||
}
|
||||
|
||||
return stair;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** parse the <pois> tag */
|
||||
static std::vector<POI*> parseFloorPOIs(const XMLElem* el) {
|
||||
std::vector<POI*> vec;
|
||||
FOREACH_NODE(n, el) {
|
||||
if (std::string("poi") == n->Name()) { vec.push_back(parseFloorPOI(n)); }
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
/** parse a <poi> tag */
|
||||
static POI* parseFloorPOI(const XMLElem* el) {
|
||||
POI* poi = new POI();
|
||||
poi->name = el->Attribute("name");
|
||||
poi->type = (POIType) el->IntAttribute("type");
|
||||
poi->pos = parsePoint2(el);
|
||||
return poi;
|
||||
}
|
||||
|
||||
|
||||
/** parse the <accesspoints> tag */
|
||||
static std::vector<AccessPoint*> parseFloorAccessPoints(const XMLElement* el) {
|
||||
assertNode("accesspoints", el);
|
||||
static std::vector<AccessPoint*> parseFloorAccessPoints(const XMLElem* el) {
|
||||
std::vector<AccessPoint*> vec;
|
||||
FOREACH_NODE(n, el) {
|
||||
if (std::string("accesspoint") == n->Name()) { vec.push_back(parseAccessPoint(n)); }
|
||||
@@ -97,29 +166,29 @@ namespace Floorplan {
|
||||
return vec;
|
||||
}
|
||||
|
||||
/** parse the <underlays> tag */
|
||||
static FloorUnderlays parseFloorUnderlays(const XMLElement* el) {
|
||||
FloorUnderlays res;
|
||||
FOREACH_NODE(n, el) {
|
||||
if (std::string("underlay") == n->Name()) { res.push_back(parseFloorUnderlay(n)); }
|
||||
}
|
||||
return res;
|
||||
}
|
||||
/** parse the <underlays> tag */
|
||||
static FloorUnderlays parseFloorUnderlays(const XMLElem* el) {
|
||||
FloorUnderlays res;
|
||||
FOREACH_NODE(n, el) {
|
||||
if (std::string("underlay") == n->Name()) { res.push_back(parseFloorUnderlay(n)); }
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/** parse an underlay image */
|
||||
static UnderlayImage* parseFloorUnderlay(const XMLElement* el) {
|
||||
UnderlayImage* img = new UnderlayImage();
|
||||
img->anchor.x = el->FloatAttribute("x");
|
||||
img->anchor.y = el->FloatAttribute("y");
|
||||
img->scaleX = el->FloatAttribute("sx");
|
||||
img->scaleY = el->FloatAttribute("sy");
|
||||
img->name = el->Attribute("name");
|
||||
img->filename = el->Attribute("file");
|
||||
return img;
|
||||
}
|
||||
/** parse an underlay image */
|
||||
static UnderlayImage* parseFloorUnderlay(const XMLElem* el) {
|
||||
UnderlayImage* img = new UnderlayImage();
|
||||
img->anchor.x = el->FloatAttribute("x");
|
||||
img->anchor.y = el->FloatAttribute("y");
|
||||
img->scaleX = el->FloatAttribute("sx");
|
||||
img->scaleY = el->FloatAttribute("sy");
|
||||
img->name = el->Attribute("name");
|
||||
img->filename = el->Attribute("file");
|
||||
return img;
|
||||
}
|
||||
|
||||
// /** parse the <other> tag */
|
||||
// static FloorKeyValue parseFloorKeyValue(const XMLElement* el) {
|
||||
// static FloorKeyValue parseFloorKeyValue(const XMLElem* el) {
|
||||
// FloorKeyValue res;
|
||||
// FOREACH_NODE(n, el) {
|
||||
// if (std::string("keyval") == n->Name()) { res.elements.push_back(parseKeyValueElement(n)); }
|
||||
@@ -127,10 +196,10 @@ namespace Floorplan {
|
||||
// return res;
|
||||
// }
|
||||
|
||||
/** parse one <keyval> element */
|
||||
static KeyValueElement* parseKeyValueElement(const XMLElement* n) {
|
||||
KeyValueElement* elem = new KeyValueElement();
|
||||
const XMLAttribute* attr = n->FirstAttribute();
|
||||
/** parse one <meta> element */
|
||||
static Meta* parseMetaElement(const XMLElem* n) {
|
||||
Meta* elem = new Meta();
|
||||
const XMLAttr* attr = n->FirstAttribute();
|
||||
while (attr) {
|
||||
elem->params[attr->Name()] = attr->Value();
|
||||
attr = attr->Next();
|
||||
@@ -138,7 +207,7 @@ namespace Floorplan {
|
||||
return elem;
|
||||
}
|
||||
|
||||
static AccessPoint* parseAccessPoint(const XMLElement* n) {
|
||||
static AccessPoint* parseAccessPoint(const XMLElem* n) {
|
||||
assertNode("accesspoint", n);
|
||||
AccessPoint* ap = new AccessPoint();
|
||||
ap->mac = n->Attribute("mac");
|
||||
@@ -149,7 +218,7 @@ namespace Floorplan {
|
||||
|
||||
|
||||
/** parse the <beacons> tag */
|
||||
static std::vector<Beacon*> parseFloorBeacons(const XMLElement* el) {
|
||||
static std::vector<Beacon*> parseFloorBeacons(const XMLElem* el) {
|
||||
std::vector<Beacon*> vec;
|
||||
FOREACH_NODE(n, el) {
|
||||
if (std::string("beacon") == n->Name()) { vec.push_back(parseBeacon(n)); }
|
||||
@@ -157,7 +226,7 @@ namespace Floorplan {
|
||||
return vec;
|
||||
}
|
||||
|
||||
static Beacon* parseBeacon(const XMLElement* n) {
|
||||
static Beacon* parseBeacon(const XMLElem* n) {
|
||||
assertNode("beacon", n);
|
||||
Beacon* b = new Beacon();
|
||||
b->mac = n->Attribute("mac");
|
||||
@@ -167,7 +236,7 @@ namespace Floorplan {
|
||||
}
|
||||
|
||||
|
||||
static std::vector<FloorRegion*> parseFloorRegions(const XMLElement* el) {
|
||||
static std::vector<FloorRegion*> parseFloorRegions(const XMLElem* el) {
|
||||
std::vector<FloorRegion*> vec;
|
||||
FOREACH_NODE(n, el) {
|
||||
if (std::string("region") == n->Name()) { vec.push_back(parseFloorRegion(n)); }
|
||||
@@ -175,7 +244,7 @@ namespace Floorplan {
|
||||
return vec;
|
||||
}
|
||||
|
||||
static FloorRegion* parseFloorRegion(const XMLElement* n) {
|
||||
static FloorRegion* parseFloorRegion(const XMLElem* n) {
|
||||
assertNode("region", n);
|
||||
FloorRegion* reg = new FloorRegion();
|
||||
reg->name = n->Attribute("name");
|
||||
@@ -184,7 +253,7 @@ namespace Floorplan {
|
||||
}
|
||||
|
||||
/** parse the <obstacles> tag */
|
||||
static std::vector<FloorObstacle*> parseFloorObstacles(const XMLElement* el) {
|
||||
static std::vector<FloorObstacle*> parseFloorObstacles(const XMLElem* el) {
|
||||
assertNode("obstacles", el);
|
||||
std::vector<FloorObstacle*> obstacles;
|
||||
FOREACH_NODE(n, el) {
|
||||
@@ -192,38 +261,46 @@ namespace Floorplan {
|
||||
// if (std::string("door") == n->Name()) {obstacles.push_back(parseFloorObstacleDoor(n));}
|
||||
// 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("line") == n->Name()) {obstacles.push_back(parseFloorObstacleLine(n));}
|
||||
if (std::string("circle") == n->Name()) {obstacles.push_back(parseFloorObstacleCircle(n));}
|
||||
//if (std::string("obstacle") == n->Name()) {obstacles.push_back(parseFloorObstacleLine(n));} // OLD
|
||||
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));}
|
||||
}
|
||||
return obstacles;
|
||||
}
|
||||
|
||||
/** parse one line */
|
||||
static FloorObstacleLine* parseFloorObstacleLine(const XMLElement* el) {
|
||||
static FloorObstacleLine* parseFloorObstacleLine(const XMLElem* el) {
|
||||
return new FloorObstacleLine(
|
||||
parseObstacleType(el->Attribute("type")),
|
||||
parseMaterial(el->Attribute("material")),
|
||||
el->FloatAttribute("x1"), el->FloatAttribute("y1"),
|
||||
el->FloatAttribute("x2"), el->FloatAttribute("y2")
|
||||
// parsePoint2((XMLElement*) el->FirstChildElement("from")),
|
||||
// parsePoint2((XMLElement*) el->FirstChildElement("to"))
|
||||
);
|
||||
parseObstacleType(el->Attribute("type")),
|
||||
parseMaterial(el->Attribute("material")),
|
||||
el->FloatAttribute("x1"), el->FloatAttribute("y1"),
|
||||
el->FloatAttribute("x2"), el->FloatAttribute("y2")
|
||||
);
|
||||
}
|
||||
|
||||
/** parse one cirlce */
|
||||
static FloorObstacleCircle* parseFloorObstacleCircle(const XMLElement* el) {
|
||||
static FloorObstacleCircle* parseFloorObstacleCircle(const XMLElem* el) {
|
||||
return new FloorObstacleCircle(
|
||||
parseObstacleType(el->Attribute("type")),
|
||||
parseMaterial(el->Attribute("material")),
|
||||
el->FloatAttribute("cx"), el->FloatAttribute("cy"),
|
||||
//parsePoint2((XMLElement*) el->FirstChildElement("from")),
|
||||
el->FloatAttribute("radius")
|
||||
);
|
||||
parseMaterial(el->Attribute("material")),
|
||||
el->FloatAttribute("cx"), el->FloatAttribute("cy"),
|
||||
el->FloatAttribute("radius")
|
||||
);
|
||||
}
|
||||
|
||||
/** parse one door */
|
||||
static FloorObstacleDoor* parseFloorObstacleDoor(const XMLElem* el) {
|
||||
return new FloorObstacleDoor(
|
||||
parseDoorType(el->Attribute("type")),
|
||||
parseMaterial(el->Attribute("material")),
|
||||
el->FloatAttribute("x1"), el->FloatAttribute("y1"),
|
||||
el->FloatAttribute("x2"), el->FloatAttribute("y2"),
|
||||
el->FloatAttribute("height"), el->BoolAttribute("swap")
|
||||
);
|
||||
}
|
||||
|
||||
/** parse a floor's <outline> tag */
|
||||
static FloorOutline parseFloorOutline(const XMLElement* el) {
|
||||
static FloorOutline parseFloorOutline(const XMLElem* el) {
|
||||
FloorOutline outline;
|
||||
FOREACH_NODE(n, el) {
|
||||
if (std::string("polygon") == n->Name()) {
|
||||
@@ -234,7 +311,7 @@ namespace Floorplan {
|
||||
}
|
||||
|
||||
/** parse one polygon */
|
||||
static FloorOutlinePolygon* parseFloorPolygon(const XMLElement* el) {
|
||||
static FloorOutlinePolygon* parseFloorPolygon(const XMLElem* el) {
|
||||
FloorOutlinePolygon* poly = new FloorOutlinePolygon();
|
||||
poly->name = el->Attribute("name");
|
||||
poly->method = parseOutlineMethod(el->Attribute("method"));
|
||||
@@ -243,7 +320,7 @@ namespace Floorplan {
|
||||
}
|
||||
|
||||
/** parse a 2d-polygon denoted by several points */
|
||||
static Polygon2 parsePoly2(const XMLElement* el) {
|
||||
static Polygon2 parsePoly2(const XMLElem* el) {
|
||||
Polygon2 poly;
|
||||
FOREACH_NODE(n, el) {
|
||||
if (std::string("point") == n->Name()) {
|
||||
@@ -255,7 +332,7 @@ namespace Floorplan {
|
||||
}
|
||||
|
||||
/** parse a 2D point (x,y) using the given tag's attributes. missing attributes are set to 0 */
|
||||
static Point2 parsePoint2(const XMLElement* el) {
|
||||
static Point2 parsePoint2(const XMLElem* el) {
|
||||
Point2 point;
|
||||
point.x = el->FloatAttribute("x");
|
||||
point.y = el->FloatAttribute("y");
|
||||
@@ -263,7 +340,7 @@ namespace Floorplan {
|
||||
}
|
||||
|
||||
/** parse a 3D point (x,y,z) using the given tag's attributes. missing attributes are set to 0 */
|
||||
static Point3 parsePoint3(const XMLElement* el) {
|
||||
static Point3 parsePoint3(const XMLElem* el) {
|
||||
Point3 point;
|
||||
point.x = el->FloatAttribute("x");
|
||||
point.y = el->FloatAttribute("y");
|
||||
@@ -279,6 +356,10 @@ namespace Floorplan {
|
||||
}
|
||||
}
|
||||
|
||||
static DoorType parseDoorType(const std::string type) {
|
||||
try { return (DoorType) std::stoi(type); } catch (...) { return DoorType::UNKNOWN; }
|
||||
}
|
||||
|
||||
static Material parseMaterial(const std::string material) {
|
||||
try {
|
||||
return (Material) std::stoi(material);
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
|
||||
namespace Floorplan {
|
||||
|
||||
using namespace tinyxml2;
|
||||
using XMLAttr = tinyxml2::XMLAttribute;
|
||||
using XMLElem = tinyxml2::XMLElement;
|
||||
using XMLDoc = tinyxml2::XMLDocument;
|
||||
|
||||
/**
|
||||
* write floorplans as XML
|
||||
@@ -20,36 +22,29 @@ namespace Floorplan {
|
||||
public:
|
||||
|
||||
static void writeToFile(const IndoorMap* map, const std::string& file) {
|
||||
XMLDocument doc;
|
||||
XMLDoc doc;
|
||||
construct(doc, map);
|
||||
doc.SaveFile(file.c_str(), false);
|
||||
}
|
||||
|
||||
static std::string writeToString(const IndoorMap* map) {
|
||||
XMLDocument doc;
|
||||
XMLDoc doc;
|
||||
construct(doc, map);
|
||||
XMLPrinter printer;
|
||||
tinyxml2::XMLPrinter printer;
|
||||
doc.Accept( &printer );
|
||||
return printer.CStr();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static std::string toString(const ObstacleType t) {
|
||||
return std::to_string((int)t);
|
||||
}
|
||||
static std::string toString(const ObstacleType t) { return std::to_string((int)t); }
|
||||
static std::string toString(const DoorType t) { return std::to_string((int)t); }
|
||||
static std::string toString(const Material m) { return std::to_string((int)m); }
|
||||
static std::string toString(const OutlineMethod m) { return std::to_string((int)m); }
|
||||
|
||||
static std::string toString(const Material m) {
|
||||
return std::to_string((int)m);
|
||||
}
|
||||
static void construct(XMLDoc& doc, const IndoorMap* map) {
|
||||
|
||||
static std::string toString(const OutlineMethod m) {
|
||||
return std::to_string((int)m);
|
||||
}
|
||||
|
||||
static void construct(XMLDocument& doc, const IndoorMap* map) {
|
||||
|
||||
XMLElement* root = doc.NewElement("map");
|
||||
XMLElem* root = doc.NewElement("map");
|
||||
doc.InsertEndChild(root);
|
||||
root->SetAttribute("width", map->width);
|
||||
root->SetAttribute("depth", map->depth);
|
||||
@@ -60,16 +55,16 @@ namespace Floorplan {
|
||||
}
|
||||
|
||||
/** add all floors to the map */
|
||||
static void addFloors(XMLDocument& doc, XMLElement* root, const IndoorMap* map) {
|
||||
XMLElement* floors = doc.NewElement("floors");
|
||||
static void addFloors(XMLDoc& doc, XMLElem* root, const IndoorMap* map) {
|
||||
XMLElem* floors = doc.NewElement("floors");
|
||||
for(const Floor* mf : map->floors) {addFloor(doc, floors, mf);}
|
||||
root->InsertEndChild(floors);
|
||||
}
|
||||
|
||||
/** add one floor to the floors-node */
|
||||
static void addFloor(XMLDocument& doc, XMLElement* floors, const Floor* mf) {
|
||||
static void addFloor(XMLDoc& doc, XMLElem* floors, const Floor* mf) {
|
||||
|
||||
XMLElement* floor = doc.NewElement("floor");
|
||||
XMLElem* floor = doc.NewElement("floor");
|
||||
floor->SetAttribute("atHeight", mf->atHeight);
|
||||
floor->SetAttribute("height", mf->height);
|
||||
floor->SetAttribute("name", mf->name.c_str());
|
||||
@@ -77,19 +72,64 @@ namespace Floorplan {
|
||||
|
||||
addFloorOutline(doc, floor, mf);
|
||||
addFloorObstacles(doc, floor, mf);
|
||||
addFloorUnderlays(doc, floor, mf);
|
||||
addFloorUnderlays(doc, floor, mf);
|
||||
|
||||
// add all sorts of POI
|
||||
addFloorPOI(doc, floor, mf);
|
||||
|
||||
addStairs(doc, floor, mf);
|
||||
|
||||
}
|
||||
|
||||
/** add all stairs to the floor */
|
||||
static void addStairs(XMLDoc& doc, XMLElem* floor, const Floor* mf) {
|
||||
|
||||
XMLElem* stairs = doc.NewElement("stairs");
|
||||
for (const Stair* _stair : mf->stairs) {
|
||||
XMLElem* elem = doc.NewElement("stair");
|
||||
addMetaElement(doc, elem, _stair->meta);
|
||||
if (dynamic_cast<const StairFreeform*>(_stair)) {
|
||||
const StairFreeform* stair = (StairFreeform*) _stair;
|
||||
elem->SetAttribute("type", 0); // TODO: other types?
|
||||
for (const StairPart& part : stair->parts) {
|
||||
XMLElem* elemPart = doc.NewElement("part");
|
||||
elemPart->SetAttribute("connect", part.connectWithPrev);
|
||||
elemPart->SetAttribute("x1", part.start.x);
|
||||
elemPart->SetAttribute("y1", part.start.y);
|
||||
elemPart->SetAttribute("z1", part.start.z);
|
||||
elemPart->SetAttribute("x2", part.end.x);
|
||||
elemPart->SetAttribute("y2", part.end.y);
|
||||
elemPart->SetAttribute("z2", part.end.z);
|
||||
elemPart->SetAttribute("w", part.width);
|
||||
elem->InsertEndChild(elemPart);
|
||||
}
|
||||
|
||||
} else {
|
||||
throw "not yet implemented";
|
||||
}
|
||||
stairs->InsertEndChild(elem);
|
||||
}
|
||||
floor->InsertEndChild(stairs);
|
||||
|
||||
}
|
||||
|
||||
/** add all sorts of POI to the floor */
|
||||
static void addFloorPOI(XMLDocument& doc, XMLElement* floor, const Floor* mf) {
|
||||
static void addFloorPOI(XMLDoc& doc, XMLElem* floor, const Floor* mf) {
|
||||
|
||||
XMLElement* accesspoints = doc.NewElement("accesspoints");
|
||||
XMLElem* pois = doc.NewElement("pois");
|
||||
for (const POI* poi : mf->pois) {
|
||||
XMLElem* elem = doc.NewElement("poi");
|
||||
elem->SetAttribute("name", poi->name.c_str());
|
||||
elem->SetAttribute("type", (int) poi->type);
|
||||
elem->SetAttribute("x", poi->pos.x);
|
||||
elem->SetAttribute("y", poi->pos.y);
|
||||
pois->InsertEndChild(elem);
|
||||
}
|
||||
floor->InsertEndChild(pois);
|
||||
|
||||
XMLElem* accesspoints = doc.NewElement("accesspoints");
|
||||
for (const AccessPoint* ap : mf->accesspoints) {
|
||||
XMLElement* accesspoint = doc.NewElement("accesspoint");
|
||||
XMLElem* accesspoint = doc.NewElement("accesspoint");
|
||||
accesspoint->SetAttribute("name", ap->name.c_str());
|
||||
accesspoint->SetAttribute("mac", ap->mac.c_str());
|
||||
accesspoint->SetAttribute("x", ap->pos.x);
|
||||
@@ -99,9 +139,9 @@ namespace Floorplan {
|
||||
}
|
||||
floor->InsertEndChild(accesspoints);
|
||||
|
||||
XMLElement* beacons = doc.NewElement("beacons");
|
||||
XMLElem* beacons = doc.NewElement("beacons");
|
||||
for (const Beacon* b : mf->beacons) {
|
||||
XMLElement* beacon = doc.NewElement("beacon");
|
||||
XMLElem* beacon = doc.NewElement("beacon");
|
||||
beacon->SetAttribute("name", b->name.c_str());
|
||||
beacon->SetAttribute("mac", b->mac.c_str());
|
||||
beacon->SetAttribute("x", b->pos.x);
|
||||
@@ -114,32 +154,32 @@ namespace Floorplan {
|
||||
|
||||
}
|
||||
|
||||
static void addFloorOutline(XMLDocument& doc, XMLElement* floor, const Floor* mf) {
|
||||
static void addFloorOutline(XMLDoc& doc, XMLElem* floor, const Floor* mf) {
|
||||
|
||||
XMLElement* outline = doc.NewElement("outline");
|
||||
XMLElem* outline = doc.NewElement("outline");
|
||||
floor->InsertEndChild(outline);
|
||||
|
||||
// XMLElement* add = doc.NewElement("add");
|
||||
// XMLElem* add = doc.NewElement("add");
|
||||
// outline->InsertEndChild(add);
|
||||
for (const FloorOutlinePolygon* poly : mf->outline) { addFloorOutlinePolygon(doc, outline, poly); }
|
||||
|
||||
// XMLElement* remove = doc.NewElement("remove");
|
||||
// XMLElem* remove = doc.NewElement("remove");
|
||||
// outline->InsertEndChild(remove);
|
||||
// for (const FloorOutlinePolygon& poly : mf.outline.remove) { addFloorOutlinePolygon(doc, remove, poly); }
|
||||
|
||||
}
|
||||
|
||||
static void addFloorOutlinePolygon(XMLDocument& doc, XMLElement* dst, const FloorOutlinePolygon* poly) {
|
||||
static void addFloorOutlinePolygon(XMLDoc& doc, XMLElem* dst, const FloorOutlinePolygon* poly) {
|
||||
|
||||
std::string method = toString(poly->method);
|
||||
|
||||
XMLElement* polygon = doc.NewElement("polygon");
|
||||
XMLElem* polygon = doc.NewElement("polygon");
|
||||
polygon->SetAttribute("name", poly->name.c_str());
|
||||
polygon->SetAttribute("method", method.c_str());
|
||||
dst->InsertEndChild(polygon);
|
||||
|
||||
for (Point2 p : poly->poly.points) {
|
||||
XMLElement* point = doc.NewElement("point");
|
||||
XMLElem* point = doc.NewElement("point");
|
||||
point->SetAttribute("x", p.x);
|
||||
point->SetAttribute("y", p.y);
|
||||
// skip the z-attribute as the value is also given by the polygons floor: floor.atHeight
|
||||
@@ -148,58 +188,49 @@ namespace Floorplan {
|
||||
|
||||
}
|
||||
|
||||
/** write one <keyval> element */
|
||||
static void addKeyValueElement(XMLDocument& doc, XMLElement* other, const KeyValueElement* kv) {
|
||||
XMLElement* elem = doc.NewElement("keyval");
|
||||
for (auto it : kv->params) {
|
||||
/** write one <meta> element */
|
||||
static void addMetaElement(XMLDoc& doc, XMLElem* other, const Meta* meta) {
|
||||
if (meta == nullptr) {return;} // nothing to add
|
||||
XMLElem* elem = doc.NewElement("meta");
|
||||
for (auto it : meta->params) {
|
||||
elem->Attribute(it.first.c_str(), it.second.c_str());
|
||||
}
|
||||
other->InsertEndChild(elem);
|
||||
}
|
||||
|
||||
|
||||
/** write the <underlays> tag */
|
||||
static void addFloorUnderlays(XMLDocument& doc, XMLElement* floor, const Floor* mf) {
|
||||
XMLElement* other = doc.NewElement("underlays");
|
||||
for (const UnderlayImage* kv : mf->underlays) {
|
||||
addFloorUnderlay(doc, other, kv);
|
||||
}
|
||||
floor->InsertEndChild(other);
|
||||
}
|
||||
/** write the <underlays> tag */
|
||||
static void addFloorUnderlays(XMLDoc& doc, XMLElem* floor, const Floor* mf) {
|
||||
XMLElem* other = doc.NewElement("underlays");
|
||||
for (const UnderlayImage* kv : mf->underlays) {
|
||||
addFloorUnderlay(doc, other, kv);
|
||||
}
|
||||
floor->InsertEndChild(other);
|
||||
}
|
||||
|
||||
/** write one underlay */
|
||||
static void addFloorUnderlay(XMLDocument& doc, XMLElement* underlays, const UnderlayImage* img) {
|
||||
XMLElement* underlay = doc.NewElement("underlay");
|
||||
underlay->SetAttribute("x", img->anchor.x);
|
||||
underlay->SetAttribute("y", img->anchor.y);
|
||||
underlay->SetAttribute("sx", img->scaleX);
|
||||
underlay->SetAttribute("sy", img->scaleY);
|
||||
underlay->SetAttribute("name", img->name.c_str());
|
||||
underlay->SetAttribute("file", img->filename.c_str());
|
||||
underlays->InsertEndChild(underlay);
|
||||
}
|
||||
/** write one underlay */
|
||||
static void addFloorUnderlay(XMLDoc& doc, XMLElem* underlays, const UnderlayImage* img) {
|
||||
XMLElem* underlay = doc.NewElement("underlay");
|
||||
underlay->SetAttribute("x", img->anchor.x);
|
||||
underlay->SetAttribute("y", img->anchor.y);
|
||||
underlay->SetAttribute("sx", img->scaleX);
|
||||
underlay->SetAttribute("sy", img->scaleY);
|
||||
underlay->SetAttribute("name", img->name.c_str());
|
||||
underlay->SetAttribute("file", img->filename.c_str());
|
||||
underlays->InsertEndChild(underlay);
|
||||
}
|
||||
|
||||
static void addFloorObstacles(XMLDoc& doc, XMLElem* floor, const Floor* mf) {
|
||||
|
||||
// /** write the <other> tag */
|
||||
// static void addFloorKeyValue(XMLDocument& doc, XMLElement* floor, const Floor* mf) {
|
||||
// XMLElement* other = doc.NewElement("other");
|
||||
// for (const KeyValueElement* kv : mf->other.elements) {
|
||||
// addKeyValueElement(doc, other, kv);
|
||||
// }
|
||||
// floor->InsertEndChild(other);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
static void addFloorObstacles(XMLDocument& doc, XMLElement* floor, const Floor* mf) {
|
||||
|
||||
XMLElement* obstacles = doc.NewElement("obstacles");
|
||||
XMLElem* obstacles = doc.NewElement("obstacles");
|
||||
|
||||
for (FloorObstacle* fo : mf->obstacles) {
|
||||
if (dynamic_cast<FloorObstacleLine*>(fo)) {
|
||||
addFloorObstacleLine(doc, obstacles, (FloorObstacleLine*)fo);
|
||||
} else if (dynamic_cast<FloorObstacleCircle*>(fo)) {
|
||||
addFloorObstacleCircle(doc, obstacles, (FloorObstacleCircle*)fo);
|
||||
} else if (dynamic_cast<FloorObstacleDoor*>(fo)) {
|
||||
addFloorObstacleDoor(doc, obstacles, (FloorObstacleDoor*)fo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,37 +238,46 @@ namespace Floorplan {
|
||||
|
||||
}
|
||||
|
||||
static void addFloorObstacleLine(XMLDocument& doc, XMLElement* obstacles, FloorObstacleLine* line) {
|
||||
|
||||
XMLElement* obstacle = doc.NewElement("line");
|
||||
const std::string type = toString(line->type);
|
||||
const std::string material = toString(line->material);
|
||||
obstacle->SetAttribute("material", material.c_str());
|
||||
obstacle->SetAttribute("type", type.c_str());
|
||||
/** write a line obstacle (wall, handrail, ..) */
|
||||
static void addFloorObstacleLine(XMLDoc& doc, XMLElem* obstacles, FloorObstacleLine* line) {
|
||||
XMLElem* obstacle = doc.NewElement("line");
|
||||
obstacle->SetAttribute("material", toString(line->material).c_str());
|
||||
obstacle->SetAttribute("type", toString(line->type).c_str());
|
||||
obstacle->SetAttribute("x1", line->from.x);
|
||||
obstacle->SetAttribute("y1", line->from.y);
|
||||
obstacle->SetAttribute("x2", line->to.x);
|
||||
obstacle->SetAttribute("y2", line->to.y);
|
||||
obstacles->InsertEndChild(obstacle);
|
||||
|
||||
}
|
||||
|
||||
static void addFloorObstacleCircle(XMLDocument& doc, XMLElement* obstacles, FloorObstacleCircle* circle) {
|
||||
|
||||
XMLElement* obstacle = doc.NewElement("line");
|
||||
const std::string type = toString(circle->type);
|
||||
const std::string material = toString(circle->material);
|
||||
obstacle->SetAttribute("material", material.c_str());
|
||||
obstacle->SetAttribute("type", type.c_str());
|
||||
/** write a circle obstacle (pillar, ..) */
|
||||
static void addFloorObstacleCircle(XMLDoc& doc, XMLElem* obstacles, FloorObstacleCircle* circle) {
|
||||
XMLElem* obstacle = doc.NewElement("circle");
|
||||
obstacle->SetAttribute("material", toString(circle->material).c_str());
|
||||
obstacle->SetAttribute("cx", circle->center.x);
|
||||
obstacle->SetAttribute("cy", circle->center.y);
|
||||
obstacle->SetAttribute("radius", circle->radius);
|
||||
obstacles->InsertEndChild(obstacle);
|
||||
}
|
||||
|
||||
/** write a door obstacle */
|
||||
static void addFloorObstacleDoor(XMLDoc& doc, XMLElem* obstacles, FloorObstacleDoor* door) {
|
||||
XMLElem* obstacle = doc.NewElement("door");
|
||||
obstacle->SetAttribute("material", toString(door->material).c_str());
|
||||
obstacle->SetAttribute("type", toString(door->type).c_str());
|
||||
obstacle->SetAttribute("x1", door->from.x);
|
||||
obstacle->SetAttribute("y1", door->from.y);
|
||||
obstacle->SetAttribute("x2", door->to.x);
|
||||
obstacle->SetAttribute("y2", door->to.y);
|
||||
obstacle->SetAttribute("height", door->height);
|
||||
obstacle->SetAttribute("swap", door->swap);
|
||||
obstacles->InsertEndChild(obstacle);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // FLOORPLANWRITER_H
|
||||
|
||||
Reference in New Issue
Block a user