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 myRadians(true),
59#endif
60 myOffset(offset),
61 myGeoScale(scale),
62 mySin(sin(DEG2RAD(-rot))), // rotate clockwise
63 myCos(cos(DEG2RAD(-rot))),
64 myProjectionMethod(NONE),
65 myUseInverseProjection(inverse),
66 myFlatten(flatten),
67 myOrigBoundary(orig),
68 myConvBoundary(conv) {
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#if PROJ_VERSION_MAJOR > 5
111 if (myProjection != nullptr) {
112 const PJ_TYPE type = proj_get_type(myProjection);
113 if (type != PJ_TYPE_TRANSFORMATION
114 && type != PJ_TYPE_CONCATENATED_OPERATION
115 && type != PJ_TYPE_OTHER_COORDINATE_OPERATION) {
116 // handle PROJCS WKT (i.e. from Visum) which doesn't define a transformation but only CRS
117 proj_destroy(myProjection);
118 PJ_CONTEXT* ctx = proj_context_create();
119 proj_context_use_proj4_init_rules(ctx, 1);
120 myProjection = proj_create_crs_to_crs(ctx,
121 "+proj=longlat +datum=WGS84 +type=crs +no_defs",
122 proj.c_str(),
123 NULL);
124 checkError(myProjection);
125 // "modern" proj doesn't default to radians but traditional proj strings do
126 myRadians = false;
127 //auto tmp = proj_normalize_for_visualization(ctx, myProjection);
128 //PJ_PROJ_INFO info = proj_pj_info(myProjection);
129 //printf("ID init: %s\n", info.id);
130 //printf("Description: %s\n", info.description);
131 //printf("Definition: %s\n", info.definition);
132 //printf("Has Inverse: %s\n", info.has_inverse ? "Yes" : "No");
133 }
134 }
135#endif
136#else
137 myProjection = pj_init_plus(proj.c_str());
138#endif
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 initProj(myProjString);
224 }
225 if (orig.myInverseProjection != nullptr) {
226#ifdef PROJ_VERSION_MAJOR
227 myInverseProjection = orig.myInverseProjection;
228#else
229 myInverseProjection = pj_init_plus(pj_get_def(orig.myInverseProjection, 0));
230#endif
231 }
232 if (orig.myGeoProjection != nullptr) {
233#ifdef PROJ_VERSION_MAJOR
234 myGeoProjection = orig.myGeoProjection;
235#else
236 myGeoProjection = pj_init_plus(pj_get_def(orig.myGeoProjection, 0));
237#endif
238 }
239#endif
240 return *this;
241}
242
243
244bool
246 std::string proj = "!"; // the default
247 double scale = oc.getFloat("proj.scale");
248 double rot = oc.getFloat("proj.rotate");
249 Position offset = Position(oc.getFloat("offset.x"), oc.getFloat("offset.y"), oc.getFloat("offset.z"));
250 bool inverse = oc.exists("proj.inverse") && oc.getBool("proj.inverse");
251 bool flatten = oc.exists("flatten") && oc.getBool("flatten");
252
253 if (oc.getBool("simple-projection")) {
254 proj = "-";
255 }
256
257#ifdef PROJ_API_FILE
258#ifdef PROJ_VERSION_MAJOR
259#ifdef WIN32
260 if (getenv("SUMO_HOME") != nullptr) {
261 const char* paths[] = { (std::string(getenv("SUMO_HOME")) + "/data/proj").c_str() };
262 proj_context_set_search_paths(PJ_DEFAULT_CTX, 1, paths);
263 }
264#endif
265#endif
266 if (oc.getBool("proj.inverse") && oc.getString("proj") == "!") {
267 WRITE_ERROR(TL("Inverse projection works only with explicit proj parameters."));
268 return false;
269 }
270 unsigned numProjections = oc.getBool("simple-projection") + oc.getBool("proj.utm") + oc.getBool("proj.dhdn") + oc.getBool("proj.dhdnutm") + (oc.getString("proj").length() > 1);
271 if (numProjections > 1) {
272 WRITE_ERROR(TL("The projection method needs to be uniquely defined."));
273 return false;
274 }
275
276 if (oc.getBool("proj.utm")) {
277 proj = "UTM";
278 } else if (oc.getBool("proj.dhdn")) {
279 proj = "DHDN";
280 } else if (oc.getBool("proj.dhdnutm")) {
281 proj = "DHDN_UTM";
282 } else if (!oc.isDefault("proj")) {
283 proj = oc.getString("proj");
284 }
285#endif
286 myProcessing = GeoConvHelper(proj, offset, Boundary(), Boundary(), scale, rot, inverse, flatten);
288 return true;
289}
290
291
292void
293GeoConvHelper::init(const std::string& proj, const Position& offset, const Boundary& orig,
294 const Boundary& conv, double scale) {
295 myProcessing = GeoConvHelper(proj, offset, orig, conv, scale);
298}
299
300void
302#ifdef PROJ_API_FILE
303 if (myProjection == nullptr &&
305 const std::string origProj = myProjString;
306 // try to initialized projection based on origBoundary
308 x2cartesian(tmp, false);
309 if (myProjection == nullptr) {
310 WRITE_WARNING("Failed to intialized projection '" + origProj + "' based on origBoundary centered on '" + toString(myOrigBoundary.getCenter()) + "'");
312 }
313 }
314#endif
315}
316
317void
319 oc.addOptionSubTopic("Projection");
320
321 oc.doRegister("simple-projection", new Option_Bool(false));
322 oc.addSynonyme("simple-projection", "proj.simple", true);
323 oc.addDescription("simple-projection", "Projection", TL("Uses a simple method for projection"));
324
325 oc.doRegister("proj.scale", new Option_Float(1.0));
326 oc.addDescription("proj.scale", "Projection", TL("Scaling factor for input coordinates"));
327
328 oc.doRegister("proj.rotate", new Option_Float(0.0));
329 oc.addDescription("proj.rotate", "Projection", TL("Rotation (clockwise degrees) for input coordinates"));
330
331#ifdef PROJ_API_FILE
332 oc.doRegister("proj.utm", new Option_Bool(false));
333 oc.addDescription("proj.utm", "Projection", TL("Determine the UTM zone (for a universal transversal mercator projection based on the WGS84 ellipsoid)"));
334
335 oc.doRegister("proj.dhdn", new Option_Bool(false));
336 oc.addDescription("proj.dhdn", "Projection", "Determine the DHDN zone (for a transversal mercator projection based on the bessel ellipsoid, \"Gauss-Krueger\")");
337
338 oc.doRegister("proj", new Option_String("!"));
339 oc.addDescription("proj", "Projection", TL("Uses STR as proj.4 definition for projection"));
340
341 oc.doRegister("proj.inverse", new Option_Bool(false));
342 oc.addDescription("proj.inverse", "Projection", TL("Inverses projection"));
343
344 oc.doRegister("proj.dhdnutm", new Option_Bool(false));
345 oc.addDescription("proj.dhdnutm", "Projection", TL("Convert from Gauss-Krueger to UTM"));
346#endif // PROJ_API_FILE
347}
348
349
350bool
354
355
356bool
360
361
362void
364 cartesian.sub(getOffsetBase());
365 if (myProjectionMethod == NONE) {
366 return;
367 }
368 if (myProjectionMethod == SIMPLE) {
369 const double y = cartesian.y() / 111136.;
370 const double x = cartesian.x() / 111320. / cos(DEG2RAD(y));
371 cartesian.set(x, y);
372 return;
373 }
374#ifdef PROJ_API_FILE
375#ifdef PROJ_VERSION_MAJOR
376 PJ_COORD c = proj_coord(cartesian.x(), cartesian.y(), cartesian.z(), 0);
377 c = proj_trans(myProjection, PJ_INV, c);
378 checkError(myProjection);
379 if (myRadians) {
380 cartesian.set(proj_todeg(c.lp.lam), proj_todeg(c.lp.phi));
381 } else {
382 cartesian.set(c.lp.lam, c.lp.phi);
383 }
384#else
385 projUV p;
386 p.u = cartesian.x();
387 p.v = cartesian.y();
388 p = pj_inv(p, myProjection);
390 p.u *= RAD_TO_DEG;
391 p.v *= RAD_TO_DEG;
392 cartesian.set((double) p.u, (double) p.v);
393#endif
394#endif
395}
396
397
398#ifdef PROJ_API_FILE
399#ifdef PROJ_VERSION_MAJOR
400bool
401GeoConvHelper::checkError(projPJ projection) const {
402 const int err_no = proj_context_errno(PJ_DEFAULT_CTX);
403 const char* err_string = "";
404 if (err_no != 0) {
405#if PROJ_VERSION_MAJOR > 7
406 err_string = proj_context_errno_string(PJ_DEFAULT_CTX, err_no);
407#else
408 err_string = proj_errno_string(err_no);
409#endif
410 }
411 if (projection == nullptr) {
412 if (err_no == 0) {
413 WRITE_WARNING(TL("Failed to create transformation, reason unknown."));
414 } else {
415 WRITE_WARNINGF(TL("Failed to create transformation, %."), err_string);
416 }
417 return false;
418 }
419 if (err_no != 0) {
420 WRITE_WARNINGF(TL("Failed to transform, %."), err_string);
421 return false;
422 }
423 return true;
424}
425#endif
426#endif
427
428
429bool
430GeoConvHelper::x2cartesian(Position& from, bool includeInBoundary) {
431 if (includeInBoundary) {
432 myOrigBoundary.add(from);
433 }
434 // init projection parameter on first use
435#ifdef PROJ_API_FILE
436 if (myProjection == nullptr) {
437 double x = from.x() * myGeoScale;
438 switch (myProjectionMethod) {
439 case DHDN_UTM: {
440 int zone = (int)((x - 500000.) / 1000000.);
441 if (zone < 1 || zone > 5) {
442 WRITE_WARNING("Attempt to initialize DHDN_UTM-projection on invalid longitude " + toString(x));
443 return false;
444 }
445 myProjString = "+proj=tmerc +lat_0=0 +lon_0=" + toString(3 * zone) +
446 " +k=1 +x_0=" + toString(zone * 1000000 + 500000) +
447 " +y_0=0 +ellps=bessel +datum=potsdam +units=m +no_defs";
448#ifdef PROJ_VERSION_MAJOR
449 myInverseProjection = proj_create(PJ_DEFAULT_CTX, myProjString.c_str());
450 checkError(myInverseProjection);
451 myGeoProjection = proj_create(PJ_DEFAULT_CTX, "+proj=latlong +datum=WGS84");
452 checkError(myGeoProjection);
453#else
454 myInverseProjection = pj_init_plus(myProjString.c_str());
455 myGeoProjection = pj_init_plus("+proj=latlong +datum=WGS84");
456#endif
457 x = ((x - 500000.) / 1000000.) * 3; // continues with UTM
458 }
460 case UTM: {
461 int zone = (int)(x + 180) / 6 + 1;
462 myProjString = "+proj=utm +zone=" + toString(zone) +
463 " +ellps=WGS84 +datum=WGS84 +units=m +no_defs";
464#ifdef PROJ_VERSION_MAJOR
465 myProjection = proj_create(PJ_DEFAULT_CTX, myProjString.c_str());
466 checkError(myProjection);
467#else
468 myProjection = pj_init_plus(myProjString.c_str());
469#endif
470 }
471 break;
472 case DHDN: {
473 int zone = (int)(x / 3);
474 if (zone < 1 || zone > 5) {
475 WRITE_WARNING("Attempt to initialize DHDN-projection on invalid longitude " + toString(x));
476 return false;
477 }
478 myProjString = "+proj=tmerc +lat_0=0 +lon_0=" + toString(3 * zone) +
479 " +k=1 +x_0=" + toString(zone * 1000000 + 500000) +
480 " +y_0=0 +ellps=bessel +datum=potsdam +units=m +no_defs";
481#ifdef PROJ_VERSION_MAJOR
482 myProjection = proj_create(PJ_DEFAULT_CTX, myProjString.c_str());
483 checkError(myProjection);
484#else
485 myProjection = pj_init_plus(myProjString.c_str());
486#endif
487 }
488 break;
489 default:
490 break;
491 }
492 }
493 if (myInverseProjection != nullptr) {
494#ifdef PROJ_VERSION_MAJOR
495 PJ_COORD c = proj_coord(from.x(), from.y(), from.z(), 0);
496 c = proj_trans(myInverseProjection, PJ_INV, c);
497 checkError(myInverseProjection);
498 from.set(proj_todeg(c.lp.lam), proj_todeg(c.lp.phi));
499#else
500 double x = from.x();
501 double y = from.y();
502 if (pj_transform(myInverseProjection, myGeoProjection, 1, 1, &x, &y, nullptr)) {
503 WRITE_WARNINGF(TL("Could not transform (%,%)"), toString(x), toString(y));
504 }
505 from.set(double(x * RAD_TO_DEG), double(y * RAD_TO_DEG));
506#endif
507 }
508#endif
509 // perform conversion
510 bool ok = x2cartesian_const(from);
511 if (ok) {
512 if (includeInBoundary) {
513 myConvBoundary.add(from);
514 }
515 }
516 return ok;
517}
518
519
520bool
522 const double x2 = from.x() * myGeoScale;
523 const double y2 = from.y() * myGeoScale;
524 double x = x2 * myCos - y2 * mySin;
525 double y = x2 * mySin + y2 * myCos;
526 if (myProjectionMethod == NONE) {
527 // do nothing
528 } else if (myUseInverseProjection) {
529 cartesian2geo(from);
530 } else {
531 if (x > 180.1 || x < -180.1) {
532 WRITE_WARNING("Invalid longitude " + toString(x));
533 return false;
534 }
535 if (y > 90.1 || y < -90.1) {
536 WRITE_WARNING("Invalid latitude " + toString(y));
537 return false;
538 }
539#ifdef PROJ_API_FILE
540 if (myProjection != nullptr) {
541#ifdef PROJ_VERSION_MAJOR
542 PJ_COORD c = proj_coord(myRadians ? proj_torad(x) : x, myRadians ? proj_torad(y) : y, from.z(), 0);
543 c = proj_trans(myProjection, PJ_FWD, c);
544 checkError(myProjection);
545 x = c.xy.x;
546 y = c.xy.y;
547#else
548 projUV p;
549 p.u = x * DEG_TO_RAD;
550 p.v = y * DEG_TO_RAD;
551 p = pj_fwd(p, myProjection);
553 x = p.u;
554 y = p.v;
555#endif
556 }
557#endif
558 if (myProjectionMethod == SIMPLE) {
559 // Sinusoidal projection (https://en.wikipedia.org/wiki/Sinusoidal_projection)
560 x *= 111320. * cos(DEG2RAD(y));
561 y *= 111136.;
563 }
564 }
565 if (x > std::numeric_limits<double>::max() ||
566 y > std::numeric_limits<double>::max()) {
567 return false;
568 }
569 from.set(x, y);
570 from.add(myOffset);
571 if (myFlatten) {
572 from.setz(0);
573 }
574 return true;
575}
576
577
578void
580 myOffset.add(x, y);
582}
583
584
585const Boundary&
589
590
591const Boundary&
595
596
597const Position
599 return myOffset;
600}
601
602
603const Position
605 return myOffset;
606}
607
608
609const std::string&
613
614
615void
617 if (myNumLoaded == 0) {
619 if (lefthand) {
620 myFinal.myOffset.mul(1, -1);
621 }
622 } else {
623 if (lefthand) {
625 }
627 // prefer options over loaded location
629 // let offset and boundary lead back to the original coords of the loaded data
632 // the new boundary (updated during loading)
634 }
635 if (lefthand) {
637 }
638}
639
640
641void
643 myNumLoaded++;
644 if (myNumLoaded > 1) {
645 WRITE_WARNINGF(TL("Ignoring loaded location attribute nr. % for tracking of original location"), toString(myNumLoaded));
646 } else {
647 myLoaded = loaded;
648 }
649}
650
651
652void
653GeoConvHelper::setLoadedPlain(const std::string& nodFile, const GeoConvHelper& loaded) {
654 myLoadedPlain[nodFile] = {loaded.getProjString(), loaded.getOffset()};
655}
656
657
659GeoConvHelper::getLoadedPlain(const std::string& plainFile, const std::string& suffix) {
660 std::string nodFile = StringUtils::replace(plainFile, suffix, ".nod.xml");
661 auto it = myLoadedPlain.find(nodFile);
662 if (it != myLoadedPlain.end()) {
663 return new GeoConvHelper(it->second.first, it->second.second, Boundary(), Boundary());
664 } else {
665 return nullptr;
666 }
667}
668
669
670void
675
676
677void
693
694
695/****************************************************************************/
#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:49
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 & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false)
writes a named attribute
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.