#include <config.h>
#include <string>
#include <algorithm>
#include <map>
#include <utils/common/MsgHandler.h>
#include <utils/common/ToString.h>
#include <utils/common/UtilExceptions.h>
#include <utils/common/StringUtils.h>
#include <utils/geom/GeoConvHelper.h>
#include <utils/shapes/SUMOPolygon.h>
#include <utils/iodevices/OutputDevice.h>
#include <utils/xml/SUMOSAXAttributes.h>
#include <utils/options/OptionsCont.h>
#include "PCPolyContainer.h"
PCPolyContainer::PCPolyContainer(bool prune,
const Boundary& pruningBoundary,
const std::vector<std::string>& removeByNames)
: myPruningBoundary(pruningBoundary), myDoPrune(prune),
myRemoveByNames(removeByNames) {}
PCPolyContainer::~PCPolyContainer() {
myPolygons.clear();
myPOIs.clear();
}
bool
PCPolyContainer::add(SUMOPolygon* poly, bool ignorePruning) {
if (myDoPrune && !ignorePruning) {
Boundary b = poly->getShape().getBoxBoundary();
if (!b.partialWithin(myPruningBoundary)) {
delete poly;
return false;
}
}
if (find(myRemoveByNames.begin(), myRemoveByNames.end(), poly->getID()) != myRemoveByNames.end()) {
delete poly;
return false;
}
return ShapeContainer::add(poly);
}
bool
PCPolyContainer::add(PointOfInterest* poi, bool ignorePruning) {
if (myDoPrune && !ignorePruning) {
if (!myPruningBoundary.around(*poi)) {
delete poi;
return false;
}
}
if (find(myRemoveByNames.begin(), myRemoveByNames.end(), poi->getID()) != myRemoveByNames.end()) {
delete poi;
return false;
}
return ShapeContainer::add(poi);
}
void
PCPolyContainer::addLanePos(const std::string& poiID, const std::string& laneID, const double lanePos, const bool friendlyPos, const double lanePosLat) {
myLanePosPois[poiID] = LanePos(laneID, lanePos, friendlyPos, lanePosLat);
}
void
PCPolyContainer::save(const std::string& file, bool useGeo) {
const GeoConvHelper& gch = GeoConvHelper::getFinal();
if (useGeo && !gch.usingGeoProjection()) {
WRITE_WARNING(TL("Ignoring option \"proj.plain-geo\" because no geo-conversion has been defined"));
useGeo = false;
}
OutputDevice& out = OutputDevice::getDevice(file);
out.writeXMLHeader("additional", "additional_file.xsd");
if (useGeo) {
out.setPrecision(gPrecisionGeo);
} else if (gch.usingGeoProjection()) {
GeoConvHelper::writeLocation(out);
}
for (auto i : myPolygons) {
i.second->writeXML(out, useGeo);
}
const double zOffset = OptionsCont::getOptions().getFloat("poi-layer-offset");
for (const auto& POI : myPOIs) {
std::map<std::string, LanePos>::const_iterator it = myLanePosPois.find(POI.first);
if (it == myLanePosPois.end()) {
POI.second->writeXML(out, useGeo, zOffset);
} else {
POI.second->writeXML(out, useGeo, zOffset, it->second.laneID, it->second.pos, it->second.friendlyPos, it->second.posLat);
}
}
out.close();
}
void PCPolyContainer::writeDlrTDPHeader(OutputDevice& device, const OptionsCont& oc) {
device << "# Format matches Extraction version: V6.5 \n";
std::stringstream tmp;
oc.writeConfiguration(tmp, true, false, false);
tmp.seekg(std::ios_base::beg);
std::string line;
while (!tmp.eof()) {
std::getline(tmp, line);
device << "# " << line << "\n";
}
device << "#\n";
}
void
PCPolyContainer::saveDlrTDP(const std::string& prefix) {
const OptionsCont& oc = OptionsCont::getOptions();
const GeoConvHelper& gch = GeoConvHelper::getFinal();
const bool haveGeo = gch.usingGeoProjection();
const double geoScale = pow(10.0f, haveGeo ? 5 : 2);
OutputDevice& out = OutputDevice::getDevice(prefix + "_points_of_interest.txt");
out.setPrecision(0);
writeDlrTDPHeader(out, oc);
out << "# ID\tCITY\tTYPE\tNAME\tgeo_x\tgeo_y\n";
int id = 0;
for (const auto& i : myPOIs) {
Position pos(*i.second);
gch.cartesian2geo(pos);
pos.mul(geoScale);
out << id << "\t";
out << "" << "\t";
out << i.second->getShapeType() << "\t";
out << i.first << "\t";
out << pos.x() << "\t";
out << pos.y() << "\t";
id++;
}
out.close();
OutputDevice& out2 = OutputDevice::getDevice(prefix + "_polygons.txt");
out2.setPrecision(0);
writeDlrTDPHeader(out2, oc);
out2 << "# ID\tCITY\tTYPE\tNAME\tgeo_x1\tgeo_y1\t[geo_x2 geo_y2 ...]\n";
id = 0;
for (const auto& i : myPolygons) {
out2 << id << "\t";
out2 << "" << "\t";
out2 << i.second->getShapeType() << "\t";
out2 << i.first << "\t";
for (Position pos : i.second->getShape()) {
gch.cartesian2geo(pos);
pos.mul(geoScale);
out2 << pos.x() << "\t";
out2 << pos.y() << "\t";
}
id++;
}
out2.close();
}
int
PCPolyContainer::getEnumIDFor(const std::string& key) {
return myIDEnums[key]++;
}
PCPolyContainer::LanePos::LanePos() :
pos(0),
friendlyPos(false),
posLat(0) {
}
PCPolyContainer::LanePos::LanePos(const std::string& _laneID, double _pos, bool _friendlyPos, double _posLat) :
laneID(_laneID),
pos(_pos),
friendlyPos(_friendlyPos),
posLat(_posLat) {
}