51 const Boundary& orig,
const Boundary& conv,
double scale,
double rot,
bool inverse,
bool flatten):
54 myProjection(nullptr),
55 myInverseProjection(nullptr),
56 myGeoProjection(nullptr),
62 myProjectionMethod(
NONE),
63 myUseInverseProjection(inverse),
66 myConvBoundary(conv) {
69 }
else if (proj ==
"-") {
71 }
else if (proj ==
"UTM") {
73 }
else if (proj ==
"DHDN") {
75 }
else if (proj ==
"DHDN_UTM") {
81 if (myProjection ==
nullptr) {
83 myProjString = std::regex_replace(proj, std::regex(
"\\+geoidgrids[^ ]*"), std::string(
""));
84 myProjString = std::regex_replace(
myProjString, std::regex(
"\\+step \\+proj=vgridshift \\+grids[^ ]*"), std::string(
""));
90 if (myProjection ==
nullptr) {
101 GeoConvHelper::initProj(
const std::string& proj) {
102 #ifdef PROJ_VERSION_MAJOR
103 myProjection = proj_create(PJ_DEFAULT_CTX, proj.c_str());
105 myProjection = pj_init_plus(proj.c_str());
113 if (myProjection !=
nullptr) {
114 #ifdef PROJ_VERSION_MAJOR
115 proj_destroy(myProjection);
117 pj_free(myProjection);
120 if (myInverseProjection !=
nullptr) {
121 #ifdef PROJ_VERSION_MAJOR
122 proj_destroy(myInverseProjection);
124 pj_free(myInverseProjection);
127 if (myGeoProjection !=
nullptr) {
128 #ifdef PROJ_VERSION_MAJOR
129 proj_destroy(myGeoProjection);
131 pj_free(myGeoProjection);
166 if (myProjection !=
nullptr) {
167 #ifdef PROJ_VERSION_MAJOR
168 proj_destroy(myProjection);
170 pj_free(myProjection);
172 myProjection =
nullptr;
174 if (myInverseProjection !=
nullptr) {
175 #ifdef PROJ_VERSION_MAJOR
176 proj_destroy(myInverseProjection);
178 pj_free(myInverseProjection);
180 myInverseProjection =
nullptr;
182 if (myGeoProjection !=
nullptr) {
183 #ifdef PROJ_VERSION_MAJOR
184 proj_destroy(myGeoProjection);
186 pj_free(myGeoProjection);
188 myGeoProjection =
nullptr;
190 if (orig.myProjection !=
nullptr) {
191 #ifdef PROJ_VERSION_MAJOR
192 myProjection = proj_create(PJ_DEFAULT_CTX, orig.
myProjString.c_str());
197 if (orig.myInverseProjection !=
nullptr) {
198 #ifdef PROJ_VERSION_MAJOR
199 myInverseProjection = orig.myInverseProjection;
201 myInverseProjection = pj_init_plus(pj_get_def(orig.myInverseProjection, 0));
204 if (orig.myGeoProjection !=
nullptr) {
205 #ifdef PROJ_VERSION_MAJOR
206 myGeoProjection = orig.myGeoProjection;
208 myGeoProjection = pj_init_plus(pj_get_def(orig.myGeoProjection, 0));
218 std::string proj =
"!";
219 double scale = oc.
getFloat(
"proj.scale");
220 double rot = oc.
getFloat(
"proj.rotate");
222 bool inverse = oc.
exists(
"proj.inverse") && oc.
getBool(
"proj.inverse");
223 bool flatten = oc.
exists(
"flatten") && oc.
getBool(
"flatten");
225 if (oc.
getBool(
"simple-projection")) {
231 WRITE_ERROR(
TL(
"Inverse projection works only with explicit proj parameters."));
235 if (numProjections > 1) {
236 WRITE_ERROR(
TL(
"The projection method needs to be uniquely defined."));
242 }
else if (oc.
getBool(
"proj.dhdn")) {
244 }
else if (oc.
getBool(
"proj.dhdnutm")) {
258 const Boundary& conv,
double scale) {
269 oc.
addSynonyme(
"simple-projection",
"proj.simple",
true);
270 oc.
addDescription(
"simple-projection",
"Projection",
"Uses a simple method for projection");
273 oc.
addDescription(
"proj.scale",
"Projection",
"Scaling factor for input coordinates");
276 oc.
addDescription(
"proj.rotate",
"Projection",
"Rotation (clockwise degrees) for input coordinates");
280 oc.
addDescription(
"proj.utm",
"Projection",
"Determine the UTM zone (for a universal transversal mercator projection based on the WGS84 ellipsoid)");
283 oc.
addDescription(
"proj.dhdn",
"Projection",
"Determine the DHDN zone (for a transversal mercator projection based on the bessel ellipsoid, \"Gauss-Krueger\")");
286 oc.
addDescription(
"proj",
"Projection",
"Uses STR as proj.4 definition for projection");
289 oc.
addDescription(
"proj.inverse",
"Projection",
"Inverses projection");
292 oc.
addDescription(
"proj.dhdnutm",
"Projection",
"Convert from Gauss-Krueger to UTM");
316 const double y = cartesian.
y() / 111136.;
317 const double x = cartesian.
x() / 111320. / cos(
DEG2RAD(y));
322 #ifdef PROJ_VERSION_MAJOR
324 c.xy.x = cartesian.
x();
325 c.xy.y = cartesian.
y();
326 c = proj_trans(myProjection, PJ_INV, c);
327 cartesian.
set(proj_todeg(c.lp.lam), proj_todeg(c.lp.phi));
332 p = pj_inv(p, myProjection);
336 cartesian.
set((
double) p.u, (
double) p.v);
344 if (includeInBoundary) {
349 if (myProjection ==
nullptr) {
353 int zone = (int)((x - 500000.) / 1000000.);
354 if (zone < 1 || zone > 5) {
359 " +k=1 +x_0=" +
toString(zone * 1000000 + 500000) +
360 " +y_0=0 +ellps=bessel +datum=potsdam +units=m +no_defs";
361 #ifdef PROJ_VERSION_MAJOR
362 myInverseProjection = proj_create(PJ_DEFAULT_CTX,
myProjString.c_str());
363 myGeoProjection = proj_create(PJ_DEFAULT_CTX,
"+proj=latlong +datum=WGS84");
365 myInverseProjection = pj_init_plus(
myProjString.c_str());
366 myGeoProjection = pj_init_plus(
"+proj=latlong +datum=WGS84");
369 x = ((x - 500000.) / 1000000.) * 3;
373 int zone = (int)(x + 180) / 6 + 1;
375 " +ellps=WGS84 +datum=WGS84 +units=m +no_defs";
376 #ifdef PROJ_VERSION_MAJOR
377 myProjection = proj_create(PJ_DEFAULT_CTX,
myProjString.c_str());
385 int zone = (int)(x / 3);
386 if (zone < 1 || zone > 5) {
391 " +k=1 +x_0=" +
toString(zone * 1000000 + 500000) +
392 " +y_0=0 +ellps=bessel +datum=potsdam +units=m +no_defs";
393 #ifdef PROJ_VERSION_MAJOR
394 myProjection = proj_create(PJ_DEFAULT_CTX,
myProjString.c_str());
405 if (myInverseProjection !=
nullptr) {
406 #ifdef PROJ_VERSION_MAJOR
410 c = proj_trans(myInverseProjection, PJ_INV, c);
411 from.
set(proj_todeg(c.lp.lam), proj_todeg(c.lp.phi));
415 if (pj_transform(myInverseProjection, myGeoProjection, 1, 1, &x, &y,
nullptr)) {
418 from.
set(
double(x * RAD_TO_DEG),
double(y * RAD_TO_DEG));
425 if (includeInBoundary) {
444 if (x > 180.1 || x < -180.1) {
448 if (y > 90.1 || y < -90.1) {
453 if (myProjection !=
nullptr) {
454 #ifdef PROJ_VERSION_MAJOR
456 c.lp.lam = proj_torad(x);
457 c.lp.phi = proj_torad(y);
458 c = proj_trans(myProjection, PJ_FWD, c);
464 p.u = x * DEG_TO_RAD;
465 p.v = y * DEG_TO_RAD;
466 p = pj_fwd(p, myProjection);
475 x *= 111320. * cos(
DEG2RAD(y));
480 if (x > std::numeric_limits<double>::max() ||
481 y > std::numeric_limits<double>::max()) {
#define WRITE_WARNING(msg)
@ SUMO_ATTR_CONV_BOUNDARY
@ SUMO_ATTR_ORIG_BOUNDARY
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
A class that stores a 2D geometrical boundary.
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
void moveby(double x, double y, double z=0)
Moves the boundary by the given amount.
void flipY()
flips ymin and ymax
static methods for processing the coordinates conversion for the current net
static void resetLoaded()
resets loaded location elements
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
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
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 GeoConvHelper myProcessing
coordinate transformation to use for input conversion and processing
A storage for options typed value containers)
void addDescription(const std::string &name, const std::string &subtopic, const std::string &description)
Adds a description for an option.
void doRegister(const std::string &name, Option *v)
Adds an option under the given name.
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.
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 SumoXMLAttr attr, const T &val)
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.
void set(double x, double y)
set positions x and y
void sub(double dx, double dy)
Substracts the given position from this one.
double x() const
Returns the x-position.
void add(const Position &pos)
Adds the given position to this one.
void setz(double z)
set position z
void mul(double val)
Multiplies both positions with the given value.
double y() const
Returns the y-position.