Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2005-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file PCPolyContainer.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @author Melanie Knocke
19 : /// @date Mon, 05 Dec 2005
20 : ///
21 : // A storage for loaded polygons and pois
22 : /****************************************************************************/
23 : #include <config.h>
24 :
25 : #include <string>
26 : #include <algorithm>
27 : #include <map>
28 : #include <utils/common/MsgHandler.h>
29 : #include <utils/common/ToString.h>
30 : #include <utils/common/UtilExceptions.h>
31 : #include <utils/common/StringUtils.h>
32 : #include <utils/geom/GeoConvHelper.h>
33 : #include <utils/shapes/SUMOPolygon.h>
34 : #include <utils/iodevices/OutputDevice.h>
35 : #include <utils/xml/SUMOSAXAttributes.h>
36 : #include <utils/options/OptionsCont.h>
37 : #include "PCPolyContainer.h"
38 :
39 :
40 : // ===========================================================================
41 : // method definitions
42 : // ===========================================================================
43 43 : PCPolyContainer::PCPolyContainer(bool prune,
44 : const Boundary& pruningBoundary,
45 43 : const std::vector<std::string>& removeByNames)
46 43 : : myPruningBoundary(pruningBoundary), myDoPrune(prune),
47 43 : myRemoveByNames(removeByNames) {}
48 :
49 :
50 43 : PCPolyContainer::~PCPolyContainer() {
51 43 : myPolygons.clear();
52 43 : myPOIs.clear();
53 86 : }
54 :
55 :
56 : bool
57 3697 : PCPolyContainer::add(SUMOPolygon* poly, bool ignorePruning) {
58 : // check whether the polygon lies within the wished area
59 : // - if such an area was given
60 3697 : if (myDoPrune && !ignorePruning) {
61 0 : Boundary b = poly->getShape().getBoxBoundary();
62 0 : if (!b.partialWithin(myPruningBoundary)) {
63 0 : delete poly;
64 : return false;
65 : }
66 0 : }
67 : // check whether the polygon was named to be a removed one
68 3697 : if (find(myRemoveByNames.begin(), myRemoveByNames.end(), poly->getID()) != myRemoveByNames.end()) {
69 0 : delete poly;
70 0 : return false;
71 : }
72 3697 : return ShapeContainer::add(poly);
73 : }
74 :
75 :
76 : bool
77 2799 : PCPolyContainer::add(PointOfInterest* poi, bool ignorePruning) {
78 : // check whether the poi lies within the wished area
79 : // - if such an area was given
80 2799 : if (myDoPrune && !ignorePruning) {
81 7 : if (!myPruningBoundary.around(*poi)) {
82 4 : delete poi;
83 4 : return false;
84 : }
85 : }
86 : // check whether the polygon was named to be a removed one
87 2795 : if (find(myRemoveByNames.begin(), myRemoveByNames.end(), poi->getID()) != myRemoveByNames.end()) {
88 0 : delete poi;
89 0 : return false;
90 : }
91 2795 : return ShapeContainer::add(poi);
92 : }
93 :
94 :
95 : void
96 1 : PCPolyContainer::addLanePos(const std::string& poiID, const std::string& laneID, const double lanePos, const bool friendlyPos, const double lanePosLat) {
97 2 : myLanePosPois[poiID] = LanePos(laneID, lanePos, friendlyPos, lanePosLat);
98 1 : }
99 :
100 :
101 : void
102 39 : PCPolyContainer::save(const std::string& file, bool useGeo) {
103 : const GeoConvHelper& gch = GeoConvHelper::getFinal();
104 39 : if (useGeo && !gch.usingGeoProjection()) {
105 4 : WRITE_WARNING(TL("Ignoring option \"proj.plain-geo\" because no geo-conversion has been defined"));
106 : useGeo = false;
107 : }
108 39 : OutputDevice& out = OutputDevice::getDevice(file);
109 78 : out.writeXMLHeader("additional", "additional_file.xsd");
110 39 : if (useGeo) {
111 16 : out.setPrecision(gPrecisionGeo);
112 23 : } else if (gch.usingGeoProjection()) {
113 16 : GeoConvHelper::writeLocation(out);
114 : }
115 : // write polygons
116 3734 : for (auto i : myPolygons) {
117 3695 : i.second->writeXML(out, useGeo);
118 : }
119 : // write pois
120 78 : const double zOffset = OptionsCont::getOptions().getFloat("poi-layer-offset");
121 2831 : for (const auto& POI : myPOIs) {
122 2792 : std::map<std::string, LanePos>::const_iterator it = myLanePosPois.find(POI.first);
123 2792 : if (it == myLanePosPois.end()) {
124 5582 : POI.second->writeXML(out, useGeo, zOffset);
125 : } else {
126 3 : POI.second->writeXML(out, useGeo, zOffset, it->second.laneID, it->second.pos, it->second.friendlyPos, it->second.posLat);
127 : }
128 : }
129 39 : out.close();
130 39 : }
131 :
132 :
133 2 : void PCPolyContainer::writeDlrTDPHeader(OutputDevice& device, const OptionsCont& oc) {
134 : // XXX duplicate of NWWriter_DlrNavteq::writeHeader()
135 2 : device << "# Format matches Extraction version: V6.5 \n";
136 2 : std::stringstream tmp;
137 4 : oc.writeConfiguration(tmp, true, false, false);
138 2 : tmp.seekg(std::ios_base::beg);
139 : std::string line;
140 82 : while (!tmp.eof()) {
141 80 : std::getline(tmp, line);
142 80 : device << "# " << line << "\n";
143 : }
144 2 : device << "#\n";
145 2 : }
146 :
147 :
148 : void
149 1 : PCPolyContainer::saveDlrTDP(const std::string& prefix) {
150 1 : const OptionsCont& oc = OptionsCont::getOptions();
151 : const GeoConvHelper& gch = GeoConvHelper::getFinal();
152 1 : const bool haveGeo = gch.usingGeoProjection();
153 1 : const double geoScale = pow(10.0f, haveGeo ? 5 : 2); // see NIImporter_DlrNavteq::GEO_SCALE
154 : // write pois
155 1 : OutputDevice& out = OutputDevice::getDevice(prefix + "_points_of_interest.txt");
156 1 : out.setPrecision(0);
157 1 : writeDlrTDPHeader(out, oc);
158 : // write format specifier
159 1 : out << "# ID\tCITY\tTYPE\tNAME\tgeo_x\tgeo_y\n";
160 1 : int id = 0;
161 2 : for (const auto& i : myPOIs) {
162 1 : Position pos(*i.second);
163 1 : gch.cartesian2geo(pos);
164 : pos.mul(geoScale);
165 1 : out << id << "\t";
166 1 : out << "" << "\t";
167 1 : out << i.second->getShapeType() << "\t";
168 1 : out << i.first << "\t";
169 1 : out << pos.x() << "\t";
170 1 : out << pos.y() << "\t";
171 1 : id++;
172 : }
173 1 : out.close();
174 : // write polygons
175 1 : OutputDevice& out2 = OutputDevice::getDevice(prefix + "_polygons.txt");
176 1 : out2.setPrecision(0);
177 1 : writeDlrTDPHeader(out2, oc);
178 : // write format specifier
179 1 : out2 << "# ID\tCITY\tTYPE\tNAME\tgeo_x1\tgeo_y1\t[geo_x2 geo_y2 ...]\n";
180 1 : id = 0;
181 2 : for (const auto& i : myPolygons) {
182 1 : out2 << id << "\t";
183 1 : out2 << "" << "\t";
184 1 : out2 << i.second->getShapeType() << "\t";
185 1 : out2 << i.first << "\t";
186 :
187 6 : for (Position pos : i.second->getShape()) {
188 5 : gch.cartesian2geo(pos);
189 : pos.mul(geoScale);
190 5 : out2 << pos.x() << "\t";
191 5 : out2 << pos.y() << "\t";
192 : }
193 1 : id++;
194 : }
195 1 : out2.close();
196 1 : }
197 :
198 :
199 : int
200 7 : PCPolyContainer::getEnumIDFor(const std::string& key) {
201 7 : return myIDEnums[key]++;
202 : }
203 :
204 :
205 1 : PCPolyContainer::LanePos::LanePos() :
206 1 : pos(0),
207 1 : friendlyPos(false),
208 1 : posLat(0) {
209 0 : }
210 :
211 :
212 1 : PCPolyContainer::LanePos::LanePos(const std::string& _laneID, double _pos, bool _friendlyPos, double _posLat) :
213 0 : laneID(_laneID),
214 1 : pos(_pos),
215 1 : friendlyPos(_friendlyPos),
216 1 : posLat(_posLat) {
217 0 : }
218 :
219 : /****************************************************************************/
|