Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GeoConvHelper.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2026 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/****************************************************************************/
20// static methods for processing the coordinates conversion for the current net
21/****************************************************************************/
22#include <config.h>
23
24#include <map>
25#include <cmath>
26#include <cassert>
27#include <climits>
28#include <regex>
34#include "GeoConvHelper.h"
35
36
37// ===========================================================================
38// static member variables
39// ===========================================================================
40
45std::map<std::string, std::pair<std::string, Position> > GeoConvHelper::myLoadedPlain;
46
47// ===========================================================================
48// method definitions
49// ===========================================================================
50
51GeoConvHelper::GeoConvHelper(const std::string& proj, const Position& offset,
52 const Boundary& orig, const Boundary& conv, double scale, double rot, bool inverse, bool flatten):
53 myProjString(proj),
54#ifdef PROJ_API_FILE
55 myProjection(nullptr),
56 myInverseProjection(nullptr),
57 myGeoProjection(nullptr),
58#endif
59 myOffset(offset),
60 myGeoScale(scale),
61 mySin(sin(DEG2RAD(-rot))), // rotate clockwise
62 myCos(cos(DEG2RAD(-rot))),
63 myProjectionMethod(NONE),
64 myUseInverseProjection(inverse),
65 myFlatten(flatten),
66 myOrigBoundary(orig),
67 myConvBoundary(conv)
68{
69 // older PROJ libraries fail to construct inverse projection if this
70 // string is present
72
73 if (proj == "!") {
75 } else if (proj == "-") {
77 } else if (proj == "UTM") {
79 } else if (proj == "DHDN") {
81 } else if (proj == "DHDN_UTM") {
83#ifdef PROJ_API_FILE
84 } else {
86 initProj(myProjString);
87 if (myProjection == nullptr) {
88 // avoid error about missing datum shift file
89 myProjString = std::regex_replace(proj, std::regex("\\+geoidgrids[^ ]*"), std::string(""));
90 myProjString = std::regex_replace(myProjString, std::regex("\\+step \\+proj=vgridshift \\+grids[^ ]*"), std::string(""));
91 if (myProjString != proj) {
92 WRITE_WARNING(TL("Ignoring geoidgrids and vgridshift in projection"));
93 initProj(myProjString);
94 }
95 }
96 if (myProjection == nullptr) {
97 throw ProcessError(TL("Could not build projection!"));
98 }
99#endif
100 }
101}
102
103
104#ifdef PROJ_API_FILE
105void
106GeoConvHelper::initProj(const std::string& proj) {
107#ifdef PROJ_VERSION_MAJOR
108 myProjection = proj_create(PJ_DEFAULT_CTX, proj.c_str());
109 checkError(myProjection);
110#else
111 myProjection = pj_init_plus(proj.c_str());
112#endif
113 if (myProjection != nullptr) {
114 const PJ_TYPE type = proj_get_type(myProjection);
115 if (type != PJ_TYPE_TRANSFORMATION
116 && type != PJ_TYPE_CONCATENATED_OPERATION
117 && type != PJ_TYPE_OTHER_COORDINATE_OPERATION) {
118 // handle PROJCS WKT (i.e. from Visum) which doesn't define a transformation but only CRS
119#ifdef PROJ_VERSION_MAJOR
120 proj_destroy(myProjection);
121#else
122 pj_free(myProjection);
123#endif
124 PJ_CONTEXT *ctx = proj_context_create();
125 proj_context_use_proj4_init_rules(ctx, 1);
126 myProjection = proj_create_crs_to_crs(ctx,
127 "+proj=latlong +datum=WGS84 +type=crs",
128 proj.c_str(),
129 NULL);
130
131 //myProjection = proj_normalize_for_visualization(ctx, tmp);
132 //PJ_PROJ_INFO info = proj_pj_info(myProjection);
133 //printf("ID: %s\n", info.id);
134 //printf("Description: %s\n", info.description);
135 //printf("Definition: %s\n", info.definition);
136 //printf("Has Inverse: %s\n", info.has_inverse ? "Yes" : "No");
137 }
138 }
139}
140#endif
141
142
144#ifdef PROJ_API_FILE
145 if (myProjection != nullptr) {
146#ifdef PROJ_VERSION_MAJOR
147 proj_destroy(myProjection);
148#else
149 pj_free(myProjection);
150#endif
151 }
152 if (myInverseProjection != nullptr) {
153#ifdef PROJ_VERSION_MAJOR
154 proj_destroy(myInverseProjection);
155#else
156 pj_free(myInverseProjection);
157#endif
158 }
159 if (myGeoProjection != nullptr) {
160#ifdef PROJ_VERSION_MAJOR
161 proj_destroy(myGeoProjection);
162#else
163 pj_free(myGeoProjection);
164#endif
165 }
166#endif
167}
168
169bool
184
188 myOffset = orig.myOffset;
192 myGeoScale = orig.myGeoScale;
193 myCos = orig.myCos;
194 mySin = orig.mySin;
196 myFlatten = orig.myFlatten;
197#ifdef PROJ_API_FILE
198 if (myProjection != nullptr) {
199#ifdef PROJ_VERSION_MAJOR
200 proj_destroy(myProjection);
201#else
202 pj_free(myProjection);
203#endif
204 myProjection = nullptr;
205 }
206 if (myInverseProjection != nullptr) {
207#ifdef PROJ_VERSION_MAJOR
208 proj_destroy(myInverseProjection);
209#else
210 pj_free(myInverseProjection);
211#endif
212 myInverseProjection = nullptr;
213 }
214 if (myGeoProjection != nullptr) {
215#ifdef PROJ_VERSION_MAJOR
216 proj_destroy(myGeoProjection);
217#else
218 pj_free(myGeoProjection);
219#endif
220 myGeoProjection = nullptr;
221 }
222 if (orig.myProjection != nullptr) {
223#ifdef PROJ_VERSION_MAJOR
224 myProjection = proj_create(PJ_DEFAULT_CTX, orig.myProjString.c_str());
225#else
226 myProjection = pj_init_plus(orig.myProjString.c_str());
227#endif
228 }
229 if (orig.myInverseProjection != nullptr) {
230#ifdef PROJ_VERSION_MAJOR
231 myInverseProjection = orig.myInverseProjection;
232#else
233 myInverseProjection = pj_init_plus(pj_get_def(orig.myInverseProjection, 0));
234#endif
235 }
236 if (orig.myGeoProjection != nullptr) {
237#ifdef PROJ_VERSION_MAJOR
238 myGeoProjection = orig.myGeoProjection;
239#else
240 myGeoProjection = pj_init_plus(pj_get_def(orig.myGeoProjection, 0));
241#endif
242 }
243#endif
244 return *this;
245}
246
247
248bool
250 std::string proj = "!"; // the default
251 double scale = oc.getFloat("proj.scale");
252 double rot = oc.getFloat("proj.rotate");
253 Position offset = Position(oc.getFloat("offset.x"), oc.getFloat("offset.y"), oc.getFloat("offset.z"));
254 bool inverse = oc.exists("proj.inverse") && oc.getBool("proj.inverse");
255 bool flatten = oc.exists("flatten") && oc.getBool("flatten");
256
257 if (oc.getBool("simple-projection")) {
258 proj = "-";
259 }
260
261#ifdef PROJ_API_FILE
262 if (oc.getBool("proj.inverse") && oc.getString("proj") == "!") {
263 WRITE_ERROR(TL("Inverse projection works only with explicit proj parameters."));
264 return false;
265 }
266 unsigned numProjections = oc.getBool("simple-projection") + oc.getBool("proj.utm") + oc.getBool("proj.dhdn") + oc.getBool("proj.dhdnutm") + (oc.getString("proj").length() > 1);
267 if (numProjections > 1) {
268 WRITE_ERROR(TL("The projection method needs to be uniquely defined."));
269 return false;
270 }
271
272 if (oc.getBool("proj.utm")) {
273 proj = "UTM";
274 } else if (oc.getBool("proj.dhdn")) {
275 proj = "DHDN";
276 } else if (oc.getBool("proj.dhdnutm")) {
277 proj = "DHDN_UTM";
278 } else if (!oc.isDefault("proj")) {
279 proj = oc.getString("proj");
280 }
281#endif
282 myProcessing = GeoConvHelper(proj, offset, Boundary(), Boundary(), scale, rot, inverse, flatten);
284 return true;
285}
286
287
288void
289GeoConvHelper::init(const std::string& proj, const Position& offset, const Boundary& orig,
290 const Boundary& conv, double scale) {
291 myProcessing = GeoConvHelper(proj, offset, orig, conv, scale);
294}
295
296void
298#ifdef PROJ_API_FILE
299 if (myProjection == nullptr &&
301 const std::string origProj = myProjString;
302 // try to initialized projection based on origBoundary
304 x2cartesian(tmp, false);
305 if (myProjection == nullptr) {
306 WRITE_WARNING("Failed to intialized projection '" + origProj + "' based on origBoundary centered on '" + toString(myOrigBoundary.getCenter()) + "'");
308 }
309 }
310#endif
311}
312
313void
315 oc.addOptionSubTopic("Projection");
316
317 oc.doRegister("simple-projection", new Option_Bool(false));
318 oc.addSynonyme("simple-projection", "proj.simple", true);
319 oc.addDescription("simple-projection", "Projection", TL("Uses a simple method for projection"));
320
321 oc.doRegister("proj.scale", new Option_Float(1.0));
322 oc.addDescription("proj.scale", "Projection", TL("Scaling factor for input coordinates"));
323
324 oc.doRegister("proj.rotate", new Option_Float(0.0));
325 oc.addDescription("proj.rotate", "Projection", TL("Rotation (clockwise degrees) for input coordinates"));
326
327#ifdef PROJ_API_FILE
328 oc.doRegister("proj.utm", new Option_Bool(false));
329 oc.addDescription("proj.utm", "Projection", TL("Determine the UTM zone (for a universal transversal mercator projection based on the WGS84 ellipsoid)"));
330
331 oc.doRegister("proj.dhdn", new Option_Bool(false));
332 oc.addDescription("proj.dhdn", "Projection", "Determine the DHDN zone (for a transversal mercator projection based on the bessel ellipsoid, \"Gauss-Krueger\")");
333
334 oc.doRegister("proj", new Option_String("!"));
335 oc.addDescription("proj", "Projection", TL("Uses STR as proj.4 definition for projection"));
336
337 oc.doRegister("proj.inverse", new Option_Bool(false));
338 oc.addDescription("proj.inverse", "Projection", TL("Inverses projection"));
339
340 oc.doRegister("proj.dhdnutm", new Option_Bool(false));
341 oc.addDescription("proj.dhdnutm", "Projection", TL("Convert from Gauss-Krueger to UTM"));
342#endif // PROJ_API_FILE
343}
344
345
346bool
350
351
352bool
356
357
358void
360 cartesian.sub(getOffsetBase());
361 if (myProjectionMethod == NONE) {
362 return;
363 }
364 if (myProjectionMethod == SIMPLE) {
365 const double y = cartesian.y() / 111136.;
366 const double x = cartesian.x() / 111320. / cos(DEG2RAD(y));
367 cartesian.set(x, y);
368 return;
369 }
370#ifdef PROJ_API_FILE
371#ifdef PROJ_VERSION_MAJOR
372 PJ_COORD c = proj_coord(cartesian.x(), cartesian.y(), cartesian.z(), 0);
373 c = proj_trans(myProjection, PJ_INV, c);
374 checkError(myProjection);
375 cartesian.set(proj_todeg(c.lp.lam), proj_todeg(c.lp.phi));
376#else
377 projUV p;
378 p.u = cartesian.x();
379 p.v = cartesian.y();
380 p = pj_inv(p, myProjection);
382 p.u *= RAD_TO_DEG;
383 p.v *= RAD_TO_DEG;
384 cartesian.set((double) p.u, (double) p.v);
385#endif
386#endif
387}
388
389
390#ifdef PROJ_API_FILE
391#ifdef PROJ_VERSION_MAJOR
392bool
393GeoConvHelper::checkError(projPJ projection) const {
394 const int err_no = proj_context_errno(PJ_DEFAULT_CTX);
395 const char* err_string = "";
396 if (err_no != 0) {
397#if PROJ_VERSION_MAJOR > 7
398 err_string = proj_context_errno_string(PJ_DEFAULT_CTX, err_no);
399#else
400 err_string = proj_errno_string(err_no);
401#endif
402 }
403 if (projection == nullptr) {
404 if (err_no == 0) {
405 WRITE_WARNING(TL("Failed to create transformation, reason unknown."));
406 } else {
407 WRITE_WARNINGF(TL("Failed to create transformation, %."), err_string);
408 }
409 return false;
410 }
411 if (err_no != 0) {
412 WRITE_WARNINGF(TL("Failed to transform, %."), err_string);
413 return false;
414 }
415 return true;
416}
417#endif
418#endif
419
420
421bool
422GeoConvHelper::x2cartesian(Position& from, bool includeInBoundary) {
423 if (includeInBoundary) {
424 myOrigBoundary.add(from);
425 }
426 // init projection parameter on first use
427#ifdef PROJ_API_FILE
428 if (myProjection == nullptr) {
429 double x = from.x() * myGeoScale;
430 switch (myProjectionMethod) {
431 case DHDN_UTM: {
432 int zone = (int)((x - 500000.) / 1000000.);
433 if (zone < 1 || zone > 5) {
434 WRITE_WARNING("Attempt to initialize DHDN_UTM-projection on invalid longitude " + toString(x));
435 return false;
436 }
437 myProjString = "+proj=tmerc +lat_0=0 +lon_0=" + toString(3 * zone) +
438 " +k=1 +x_0=" + toString(zone * 1000000 + 500000) +
439 " +y_0=0 +ellps=bessel +datum=potsdam +units=m +no_defs";
440#ifdef PROJ_VERSION_MAJOR
441 myInverseProjection = proj_create(PJ_DEFAULT_CTX, myProjString.c_str());
442 checkError(myInverseProjection);
443 myGeoProjection = proj_create(PJ_DEFAULT_CTX, "+proj=latlong +datum=WGS84");
444 checkError(myGeoProjection);
445#else
446 myInverseProjection = pj_init_plus(myProjString.c_str());
447 myGeoProjection = pj_init_plus("+proj=latlong +datum=WGS84");
448#endif
449 x = ((x - 500000.) / 1000000.) * 3; // continues with UTM
450 }
452 case UTM: {
453 int zone = (int)(x + 180) / 6 + 1;
454 myProjString = "+proj=utm +zone=" + toString(zone) +
455 " +ellps=WGS84 +datum=WGS84 +units=m +no_defs";
456#ifdef PROJ_VERSION_MAJOR
457 myProjection = proj_create(PJ_DEFAULT_CTX, myProjString.c_str());
458 checkError(myProjection);
459#else
460 myProjection = pj_init_plus(myProjString.c_str());
461#endif
462 }
463 break;
464 case DHDN: {
465 int zone = (int)(x / 3);
466 if (zone < 1 || zone > 5) {
467 WRITE_WARNING("Attempt to initialize DHDN-projection on invalid longitude " + toString(x));
468 return false;
469 }
470 myProjString = "+proj=tmerc +lat_0=0 +lon_0=" + toString(3 * zone) +
471 " +k=1 +x_0=" + toString(zone * 1000000 + 500000) +
472 " +y_0=0 +ellps=bessel +datum=potsdam +units=m +no_defs";
473#ifdef PROJ_VERSION_MAJOR
474 myProjection = proj_create(PJ_DEFAULT_CTX, myProjString.c_str());
475 checkError(myProjection);
476#else
477 myProjection = pj_init_plus(myProjString.c_str());
478#endif
479 }
480 break;
481 default:
482 break;
483 }
484 }
485 if (myInverseProjection != nullptr) {
486#ifdef PROJ_VERSION_MAJOR
487 PJ_COORD c = proj_coord(from.x(), from.y(), from.z(), 0);
488 c = proj_trans(myInverseProjection, PJ_INV, c);
489 checkError(myInverseProjection);
490 from.set(proj_todeg(c.lp.lam), proj_todeg(c.lp.phi));
491#else
492 double x = from.x();
493 double y = from.y();
494 if (pj_transform(myInverseProjection, myGeoProjection, 1, 1, &x, &y, nullptr)) {
495 WRITE_WARNINGF(TL("Could not transform (%,%)"), toString(x), toString(y));
496 }
497 from.set(double(x * RAD_TO_DEG), double(y * RAD_TO_DEG));
498#endif
499 }
500#endif
501 // perform conversion
502 bool ok = x2cartesian_const(from);
503 if (ok) {
504 if (includeInBoundary) {
505 myConvBoundary.add(from);
506 }
507 }
508 return ok;
509}
510
511
512bool
514 const double x2 = from.x() * myGeoScale;
515 const double y2 = from.y() * myGeoScale;
516 double x = x2 * myCos - y2 * mySin;
517 double y = x2 * mySin + y2 * myCos;
518 if (myProjectionMethod == NONE) {
519 // do nothing
520 } else if (myUseInverseProjection) {
521 cartesian2geo(from);
522 } else {
523 if (x > 180.1 || x < -180.1) {
524 WRITE_WARNING("Invalid longitude " + toString(x));
525 return false;
526 }
527 if (y > 90.1 || y < -90.1) {
528 WRITE_WARNING("Invalid latitude " + toString(y));
529 return false;
530 }
531#ifdef PROJ_API_FILE
532 if (myProjection != nullptr) {
533#ifdef PROJ_VERSION_MAJOR
534 PJ_COORD c = proj_coord(proj_torad(x), proj_torad(y), from.z(), 0);
535 c = proj_trans(myProjection, PJ_FWD, c);
536 checkError(myProjection);
537 x = c.xy.x;
538 y = c.xy.y;
539#else
540 projUV p;
541 p.u = x * DEG_TO_RAD;
542 p.v = y * DEG_TO_RAD;
543 p = pj_fwd(p, myProjection);
545 x = p.u;
546 y = p.v;
547#endif
548 }
549#endif
550 if (myProjectionMethod == SIMPLE) {
551 // Sinusoidal projection (https://en.wikipedia.org/wiki/Sinusoidal_projection)
552 x *= 111320. * cos(DEG2RAD(y));
553 y *= 111136.;
555 }
556 }
557 if (x > std::numeric_limits<double>::max() ||
558 y > std::numeric_limits<double>::max()) {
559 return false;
560 }
561 from.set(x, y);
562 from.add(myOffset);
563 if (myFlatten) {
564 from.setz(0);
565 }
566 return true;
567}
568
569
570void
572 myOffset.add(x, y);
574}
575
576
577const Boundary&
581
582
583const Boundary&
587
588
589const Position
591 return myOffset;
592}
593
594
595const Position
597 return myOffset;
598}
599
600
601const std::string&
605
606
607void
609 if (myNumLoaded == 0) {
611 if (lefthand) {
612 myFinal.myOffset.mul(1, -1);
613 }
614 } else {
615 if (lefthand) {
617 }
619 // prefer options over loaded location
621 // let offset and boundary lead back to the original coords of the loaded data
624 // the new boundary (updated during loading)
626 }
627 if (lefthand) {
629 }
630}
631
632
633void
635 myNumLoaded++;
636 if (myNumLoaded > 1) {
637 WRITE_WARNINGF(TL("Ignoring loaded location attribute nr. % for tracking of original location"), toString(myNumLoaded));
638 } else {
639 myLoaded = loaded;
640 }
641}
642
643
644void
645GeoConvHelper::setLoadedPlain(const std::string& nodFile, const GeoConvHelper& loaded) {
646 myLoadedPlain[nodFile] = {loaded.getProjString(), loaded.getOffset()};
647}
648
649
651GeoConvHelper::getLoadedPlain(const std::string& plainFile, const std::string& suffix) {
652 std::string nodFile = StringUtils::replace(plainFile, suffix, ".nod.xml");
653 auto it = myLoadedPlain.find(nodFile);
654 if (it != myLoadedPlain.end()) {
655 return new GeoConvHelper(it->second.first, it->second.second, Boundary(), Boundary());
656 } else {
657 return nullptr;
658 }
659}
660
661
662void
667
668
669void
685
686
687/****************************************************************************/
#define DEG2RAD(x)
Definition GeomHelper.h:35
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
@ SUMO_TAG_LOCATION
@ SUMO_ATTR_CONV_BOUNDARY
@ SUMO_ATTR_NET_OFFSET
@ SUMO_ATTR_ORIG_BOUNDARY
@ SUMO_ATTR_ORIG_PROJ
int gPrecisionGeo
Definition StdDefs.cpp:29
#define FALLTHROUGH
Definition StdDefs.h:39
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
A class that stores a 2D geometrical boundary.
Definition Boundary.h:39
Position getCenter() const
Returns the center of the boundary.
Definition Boundary.cpp:109
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition Boundary.cpp:75
void moveby(double x, double y, double z=0)
Moves the boundary by the given amount.
Definition Boundary.cpp:433
void flipY()
flips ymin and ymax
Definition Boundary.cpp:372
static methods for processing the coordinates conversion for the current net
static void resetLoaded()
resets loaded location elements
static void setLoadedPlain(const std::string &nodFile, const GeoConvHelper &loaded)
registers the coordinate transformation as having been loaded from the given file
const Position getOffset() const
Returns the network offset.
static void writeLocation(OutputDevice &into)
writes the location element
Boundary myOrigBoundary
The boundary before conversion (x2cartesian)
static void addProjectionOptions(OptionsCont &oc)
Adds projection options to the given container.
bool x2cartesian(Position &from, bool includeInBoundary=true)
Converts the given coordinate into a cartesian and optionally update myConvBoundary.
GeoConvHelper & operator=(const GeoConvHelper &)
make assignment operator private
static GeoConvHelper * getLoadedPlain(const std::string &plainFile, const std::string &suffix=".edg.xml")
ProjectionMethod myProjectionMethod
Information whether no projection shall be done.
void cartesian2geo(Position &cartesian) const
Converts the given cartesian (shifted) position to its geo (lat/long) representation.
GeoConvHelper(OptionsCont &oc)
Constructor based on the stored options.
Position myOffset
The offset to apply.
void moveConvertedBy(double x, double y)
Shifts the converted boundary by the given amounts.
bool usingInverseGeoProjection() const
Returns the information whether an inverse transformation will happen.
bool operator==(const GeoConvHelper &o) const
void resolveAbstractProjection()
init projString such as 'UTM' in loaded projection
const std::string & getProjString() const
Returns the original projection definition.
const Boundary & getOrigBoundary() const
Returns the original boundary.
double mySin
The rotation to apply to geo-coordinates.
static GeoConvHelper myLoaded
coordinate transformation loaded from a location element
static GeoConvHelper myFinal
coordinate transformation to use for writing the location element and for tracking the original coord...
static void setLoaded(const GeoConvHelper &loaded)
sets the coordinate transformation loaded from a location element
double myGeoScale
The scaling to apply to geo-coordinates.
const Position getOffsetBase() const
Returns the network base.
static bool init(OptionsCont &oc)
Initialises the processing and the final instance using the given options.
bool myFlatten
whether to discard z-data
bool myUseInverseProjection
Information whether inverse projection shall be used.
Boundary myConvBoundary
The boundary after conversion (x2cartesian)
static void computeFinal(bool lefthand=false)
compute the location attributes which will be used for output based on the loaded location data,...
bool usingGeoProjection() const
Returns whether a transformation from geo to metric coordinates will be performed.
const Boundary & getConvBoundary() const
Returns the converted boundary.
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation.
~GeoConvHelper()
Destructor.
std::string myProjString
A proj options string describing the proj.4-projection to use.
static int myNumLoaded
the numer of coordinate transformations loaded from location elements
static std::map< std::string, std::pair< std::string, Position > > myLoadedPlain
the projections loaded from .nod.xml (to be re-used when loading edg.xml)
static GeoConvHelper myProcessing
coordinate transformation to use for input conversion and processing
A storage for options typed value containers)
Definition OptionsCont.h:89
void addDescription(const std::string &name, const std::string &subtopic, const std::string &description)
Adds a description for an option.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
void addSynonyme(const std::string &name1, const std::string &name2, bool isDeprecated=false)
Adds a synonyme for an options name (any order)
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
void doRegister(const std::string &name, Option *o)
Adds an option under the given name.
bool exists(const std::string &name) const
Returns the information whether the named option is known.
void addOptionSubTopic(const std::string &topic)
Adds an option subtopic.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
Static storage of an output device and its base (abstract) implementation.
void lf()
writes a line feed if applicable
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
void setPrecision(int precision=gPrecision)
Sets the precision or resets it to default.
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
void set(double x, double y)
set positions x and y
Definition Position.h:82
void sub(double dx, double dy)
Subtracts the given position from this one.
Definition Position.h:149
double x() const
Returns the x-position.
Definition Position.h:52
void add(const Position &pos)
Adds the given position to this one.
Definition Position.h:129
void setz(double z)
set position z
Definition Position.h:77
void mul(double val)
Multiplies position with the given value.
Definition Position.h:102
double z() const
Returns the z-position.
Definition Position.h:62
double y() const
Returns the y-position.
Definition Position.h:57
static std::string replace(std::string str, const std::string &what, const std::string &by)
Replaces all occurrences of the second string by the third string within the first string.
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.