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

452 lines
16 KiB
C++
Raw Permalink 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.
* Einige Aenderungen beigetragen von Toni Fetzer
* Keine Verwendung ohne explizite Genehmigung.
* (vgl. § 106 ff UrhG / § 97 UrhG)
*/
#ifndef FLOORPLANWRITER_H
#define FLOORPLANWRITER_H
#include <iostream>
#include "Floorplan.h"
#include "../../Assertions.h"
#include "../../lib/tinyxml/tinyxml2.h"
namespace Floorplan {
using XMLAttr = tinyxml2::XMLAttribute;
using XMLElem = tinyxml2::XMLElement;
using XMLDoc = tinyxml2::XMLDocument;
/**
* write floorplans as XML
*/
class Writer {
public:
static void writeToFile(const IndoorMap* map, const std::string& file) {
XMLDoc doc;
construct(doc, map);
doc.SaveFile(file.c_str(), false);
}
static std::string writeToString(const IndoorMap* map) {
XMLDoc doc;
construct(doc, map);
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 WindowType 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 void construct(XMLDoc& doc, const IndoorMap* map) {
XMLElem* root = doc.NewElement("map");
doc.InsertEndChild(root);
root->SetAttribute("width", map->width);
root->SetAttribute("depth", map->depth);
// add earth registration to the map
addEarthReg(doc, root, map);
// add all floors to the map
addFloors(doc, root, map);
}
/** add earth registration to the map */
static void addEarthReg(XMLDoc& doc, XMLElem* root, const IndoorMap* map) {
XMLElem* earthReg = doc.NewElement("earthReg"); {
XMLElem* correspondences = doc.NewElement("correspondences");
for (const Floorplan::EarthPosMapPos* reg : map->earthReg.correspondences) {
XMLElem* point = doc.NewElement("point");
point->SetAttribute("lat", reg->posOnEarth.lat);
point->SetAttribute("lon", reg->posOnEarth.lon);
point->SetAttribute("alt", reg->posOnEarth.height);
point->SetAttribute("mx", reg->posOnMap_m.x);
point->SetAttribute("my", reg->posOnMap_m.y);
point->SetAttribute("mz", reg->posOnMap_m.z);
correspondences->InsertEndChild(point);
}
earthReg->InsertEndChild(correspondences);
} root->InsertEndChild(earthReg);
}
/** add all floors to the map */
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(XMLDoc& doc, XMLElem* floors, const Floor* mf) {
XMLElem* floor = doc.NewElement("floor");
floor->SetAttribute("atHeight", mf->atHeight);
floor->SetAttribute("height", mf->height);
floor->SetAttribute("name", mf->name.c_str());
floors->InsertEndChild(floor);
addFloorOutline(doc, floor, mf);
addFloorObstacles(doc, floor, mf);
addFloorUnderlays(doc, floor, mf);
// add all sorts of POI
addFloorPOI(doc, floor, mf);
addStairs(doc, floor, mf);
addElevators(doc, floor, mf);
}
/** add all elevators to the floor */
static void addElevators(XMLDoc& doc, XMLElem* floor, const Floor* mf) {
XMLElem* elevators = doc.NewElement("elevators");
for (const Elevator* elevator : mf->elevators) {
XMLElem* elem = doc.NewElement("elevator");
elem->SetAttribute("cx", elevator->center.x);
elem->SetAttribute("cy", elevator->center.y);
elem->SetAttribute("width", elevator->width);
elem->SetAttribute("depth", elevator->depth);
elem->SetAttribute("height", elevator->height_m);
elem->SetAttribute("rotation", elevator->rotation);
elevators->InsertEndChild(elem);
}
floor->InsertEndChild(elevators);
}
/** 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->getMeta());
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(XMLDoc& doc, XMLElem* floor, const Floor* mf) {
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* gtpoints = doc.NewElement("gtpoints");
for (const GroundTruthPoint* gtp : mf->gtpoints) {
XMLElem* elem = doc.NewElement("gtpoint");
elem->SetAttribute("id", gtp->id);
elem->SetAttribute("x", gtp->pos.x);
elem->SetAttribute("y", gtp->pos.y);
elem->SetAttribute("z", gtp->pos.z);
gtpoints->InsertEndChild(elem);
}
floor->InsertEndChild(gtpoints);
XMLElem* accesspoints = doc.NewElement("accesspoints");
for (const AccessPoint* ap : mf->accesspoints) {
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);
accesspoint->SetAttribute("y", ap->pos.y);
accesspoint->SetAttribute("z", ap->pos.z);
accesspoint->SetAttribute("mdl_txp", ap->model.txp);
accesspoint->SetAttribute("mdl_exp", ap->model.exp);
accesspoint->SetAttribute("mdl_waf", ap->model.waf);
addMetaElement(doc, accesspoint, ap->getMeta());
accesspoints->InsertEndChild(accesspoint);
}
floor->InsertEndChild(accesspoints);
XMLElem* beacons = doc.NewElement("beacons");
for (const Beacon* b : mf->beacons) {
XMLElem* beacon = doc.NewElement("beacon");
beacon->SetAttribute("name", b->name.c_str());
beacon->SetAttribute("mac", b->mac.c_str());
beacon->SetAttribute("major", b->major.c_str());
beacon->SetAttribute("minor", b->minor.c_str());
beacon->SetAttribute("uuid", b->uuid.c_str());
beacon->SetAttribute("x", b->pos.x);
beacon->SetAttribute("y", b->pos.y);
beacon->SetAttribute("z", b->pos.z);
beacon->SetAttribute("mdl_txp", b->model.txp);
beacon->SetAttribute("mdl_exp", b->model.exp);
beacon->SetAttribute("mdl_waf", b->model.waf);
beacons->InsertEndChild(beacon);
}
floor->InsertEndChild(beacons);
XMLElem* fingerprints = doc.NewElement("fingerprints");
for (const FingerprintLocation* fpl : mf->fpLocations) {
XMLElem* efpl = doc.NewElement("location");
efpl->SetAttribute("name", fpl->name.c_str());
efpl->SetAttribute("x", fpl->posOnFloor.x);
efpl->SetAttribute("y", fpl->posOnFloor.y);
efpl->SetAttribute("dz", fpl->heightAboveFloor);
addMetaElement(doc, efpl, fpl->getMeta());
fingerprints->InsertEndChild(efpl);
}
floor->InsertEndChild(fingerprints);
}
static void addFloorOutline(XMLDoc& doc, XMLElem* floor, const Floor* mf) {
XMLElem* outline = doc.NewElement("outline");
floor->InsertEndChild(outline);
// XMLElem* add = doc.NewElement("add");
// outline->InsertEndChild(add);
for (const FloorOutlinePolygon* poly : mf->outline) { addFloorOutlinePolygon(doc, outline, poly); }
// XMLElem* remove = doc.NewElement("remove");
// outline->InsertEndChild(remove);
// for (const FloorOutlinePolygon& poly : mf.outline.remove) { addFloorOutlinePolygon(doc, remove, poly); }
}
static void addFloorOutlinePolygon(XMLDoc& doc, XMLElem* dst, const FloorOutlinePolygon* poly) {
std::string method = toString(poly->method);
XMLElem* polygon = doc.NewElement("polygon");
polygon->SetAttribute("name", poly->name.c_str());
polygon->SetAttribute("method", method.c_str());
polygon->SetAttribute("outdoor", poly->outdoor);
dst->InsertEndChild(polygon);
for (Point2 p : poly->poly.points) {
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
polygon->InsertEndChild(point);
}
}
/** 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());
// }
for (const Meta::KeyVal& kv : meta->params) {
// <entry key="123">abc</entry>
XMLElem* subElem = doc.NewElement("entry");
subElem->SetAttribute("key", kv.key.c_str());
subElem->SetText(kv.val.c_str());
elem->InsertEndChild(subElem);
}
other->InsertEndChild(elem);
}
/** 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(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) {
XMLElem* obstacles = doc.NewElement("obstacles");
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)) {
addFloorObstacleDoor(doc, obstacles, (FloorObstacleDoor*)fo);
} else if (dynamic_cast<FloorObstacleObject*>(fo)) {
addFloorObstacleObject(doc, obstacles, (FloorObstacleObject*)fo);
}
}
floor->InsertEndChild(obstacles);
}
/** 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("x01", door->atLinePos);
oDoor->SetAttribute("width", door->width);
oDoor->SetAttribute("height", door->height);
oDoor->SetAttribute("io", door->inOut);
oDoor->SetAttribute("lr", door->leftRight);
}
// windows?
for (const FloorObstacleWallWindow* win : wall->windows) {
XMLElem* oDoor = doc.NewElement("window");
oWall->InsertEndChild(oDoor);
oDoor->SetAttribute("type", toString(win->type).c_str());
oDoor->SetAttribute("material", toString(win->material).c_str());
oDoor->SetAttribute("x01", win->atLinePos);
oDoor->SetAttribute("y", win->startsAtHeight);
oDoor->SetAttribute("width", win->width);
oDoor->SetAttribute("height", win->height);
oDoor->SetAttribute("io", win->inOut);
}
}
/** 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());
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);
obstacle->SetAttribute("thickness", line->thickness_m);
if (line->height_m != 0) {obstacle->SetAttribute("height", line->height_m);}
obstacles->InsertEndChild(obstacle);
}
/** 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);
if (circle->height != 0) {obstacle->SetAttribute("height", circle->height);}
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);
}
/** write an object-obstacle */
static void addFloorObstacleObject(XMLDoc& doc, XMLElem* obstacles, FloorObstacleObject* obj) {
XMLElem* obstacle = doc.NewElement("object");
obstacle->SetAttribute("file", obj->file.c_str());
obstacle->SetAttribute("x", obj->pos.x);
obstacle->SetAttribute("y", obj->pos.y);
obstacle->SetAttribute("z", obj->pos.z);
if (obj->rot.x != 0) {obstacle->SetAttribute("rx", obj->rot.x);}
if (obj->rot.y != 0) {obstacle->SetAttribute("ry", obj->rot.y);}
if (obj->rot.z != 0) {obstacle->SetAttribute("rz", obj->rot.z);}
if (obj->scale.x != 1) {obstacle->SetAttribute("sx", obj->scale.x);}
if (obj->scale.y != 1) {obstacle->SetAttribute("sy", obj->scale.y);}
if (obj->scale.z != 1) {obstacle->SetAttribute("sz", obj->scale.z);}
obstacles->InsertEndChild(obstacle);
}
};
}
#endif // FLOORPLANWRITER_H