GeoConvHelper.cpp
Go to the documentation of this file.00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef _MSC_VER
00025 #include <windows_config.h>
00026 #else
00027 #include <config.h>
00028 #endif
00029
00030 #include <map>
00031 #include <cmath>
00032 #include "GeoConvHelper.h"
00033 #include <utils/common/MsgHandler.h>
00034 #include <utils/common/ToString.h>
00035 #include <utils/geom/GeomHelper.h>
00036 #include <utils/options/OptionsCont.h>
00037
00038 #ifdef HAVE_PROJ
00039 #include <proj_api.h>
00040 #endif
00041
00042 #ifdef CHECK_MEMORY_LEAKS
00043 #include <foreign/nvwa/debug_new.h>
00044 #endif // CHECK_MEMORY_LEAKS
00045
00046
00047
00048
00049
00050 std::string GeoConvHelper::myProjString = "!";
00051 #ifdef HAVE_PROJ
00052 projPJ GeoConvHelper::myProjection = 0;
00053 #endif
00054 Position2D GeoConvHelper::myOffset;
00055 double GeoConvHelper::myGeoScale = 1.f;
00056 GeoConvHelper::ProjectionMethod GeoConvHelper::myProjectionMethod = NONE;
00057 bool GeoConvHelper::myUseInverseProjection = false;
00058 bool GeoConvHelper::myBaseFound = false;
00059 double GeoConvHelper::myBaseX = 0;
00060 double GeoConvHelper::myBaseY = 0;
00061 Boundary GeoConvHelper::myOrigBoundary;
00062 Boundary GeoConvHelper::myConvBoundary;
00063
00064
00065
00066
00067
00068 void
00069 GeoConvHelper::addProjectionOptions(OptionsCont &oc) {
00070 oc.addOptionSubTopic("Projection");
00071
00072 oc.doRegister("proj.simple", new Option_Bool(false));
00073 oc.addDescription("proj.simple", "Projection", "Uses a simple method for projection");
00074
00075 oc.doRegister("proj.shift", new Option_Integer(0));
00076 oc.addDescription("proj.shift", "Projection", "Number of places to shift decimal point to right in geo-coordinates");
00077
00078 #ifdef HAVE_PROJ
00079 oc.doRegister("proj.utm", new Option_Bool(false));
00080 oc.addDescription("proj.utm", "Projection", "Determine the UTM zone (for a universal transversal mercator projection based on the WGS84 ellipsoid)");
00081
00082 oc.doRegister("proj.dhdn", new Option_Bool(false));
00083 oc.addDescription("proj.dhdn", "Projection", "Determine the DHDN zone (for a transversal mercator projection based on the bessel ellipsoid)");
00084
00085 oc.doRegister("proj", new Option_String("!"));
00086 oc.addDescription("proj", "Projection", "Uses STR as proj.4 definition for projection");
00087
00088 oc.doRegister("proj.inverse", new Option_Bool(false));
00089 oc.addDescription("proj.inverse", "Projection", "Inverses projection");
00090 #endif
00091 }
00092
00093
00094 bool
00095 GeoConvHelper::init(OptionsCont &oc) {
00096 #ifdef HAVE_PROJ
00097 if (oc.getBool("proj.inverse") && oc.getString("proj") == "!") {
00098 MsgHandler::getErrorInstance()->inform("Inverse projection works only with explicit proj parameters.");
00099 return false;
00100 }
00101 unsigned numProjections = oc.getBool("proj.simple") + oc.getBool("proj.utm") + oc.getBool("proj.dhdn") + (oc.getString("proj").length() > 1);
00102 if (numProjections > 1) {
00103 MsgHandler::getErrorInstance()->inform("The projection method needs to be uniquely defined.");
00104 return false;
00105 }
00106 #endif
00107 myOffset = Position2D(oc.getFloat("x-offset-to-apply"), oc.getFloat("y-offset-to-apply"));
00108 if (oc.getBool("proj.simple")) {
00109 return init("-", oc.getInt("proj.shift"));
00110 }
00111 bool ret = true;
00112 #ifdef HAVE_PROJ
00113 if (oc.getBool("proj.utm")) {
00114 myProjectionMethod = UTM;
00115 ret = init(".", oc.getInt("proj.shift"));
00116 } else if (oc.getBool("proj.dhdn")) {
00117 myProjectionMethod = DHDN;
00118 ret = init(".", oc.getInt("proj.shift"));
00119 } else {
00120 ret = init(oc.getString("proj"), oc.getInt("proj.shift"), oc.getBool("proj.inverse"));
00121 }
00122 #endif
00123 if (!oc.exists("disable-normalize-node-positions") || oc.getBool("disable-normalize-node-positions") || !oc.isDefault("x-offset-to-apply") || !oc.isDefault("y-offset-to-apply")) {
00124 myBaseFound = true;
00125 }
00126 return ret;
00127 }
00128
00129
00130 bool
00131 GeoConvHelper::init(const std::string &proj,
00132 const int shift,
00133 bool inverse) {
00134 myProjString = proj;
00135 myGeoScale = pow(10, (double)-shift);
00136 myUseInverseProjection = inverse;
00137 close();
00138 myBaseFound = false;
00139 myOrigBoundary.reset();
00140 myConvBoundary.reset();
00141 if (proj=="!") {
00142 myProjectionMethod = NONE;
00143 return true;
00144 }
00145 if (proj=="-") {
00146 myProjectionMethod = SIMPLE;
00147 return true;
00148 }
00149 if (proj==".") {
00150 return true;
00151 }
00152 #ifdef HAVE_PROJ
00153 myProjection = pj_init_plus(proj.c_str());
00154
00155 if (myProjection != 0) {
00156 myProjectionMethod = PROJ;
00157 return true;
00158 }
00159 #endif
00160 return false;
00161 }
00162
00163
00164 bool
00165 GeoConvHelper::init(const std::string &proj,
00166 const Position2D &offset,
00167 const Boundary &orig,
00168 const Boundary &conv) {
00169 bool ret = init(proj);
00170 myOffset = offset;
00171 myOrigBoundary.add(orig);
00172 myConvBoundary.add(conv);
00173 return ret;
00174 }
00175
00176
00177 void
00178 GeoConvHelper::close() {
00179 #ifdef HAVE_PROJ
00180 if (myProjection != 0) {
00181 pj_free(myProjection);
00182 }
00183 myProjection = 0;
00184 #endif
00185 }
00186
00187
00188 bool
00189 GeoConvHelper::usingGeoProjection() {
00190 return myProjectionMethod != NONE;
00191 }
00192
00193
00194 bool
00195 GeoConvHelper::usingInverseGeoProjection() {
00196 return myUseInverseProjection;
00197 }
00198
00199
00200 void
00201 GeoConvHelper::cartesian2geo(Position2D &cartesian) {
00202 cartesian.sub(myOffset);
00203 if (myProjectionMethod == NONE) {
00204 return;
00205 }
00206 #ifdef HAVE_PROJ
00207 projUV p;
00208 p.u = cartesian.x();
00209 p.v = cartesian.y();
00210 p = pj_inv(p, myProjection);
00212 p.u *= RAD_TO_DEG;
00213 p.v *= RAD_TO_DEG;
00214 cartesian.set((SUMOReal) p.u, (SUMOReal) p.v);
00215 #endif
00216 }
00217
00218
00219 bool
00220 GeoConvHelper::x2cartesian(Position2D &from, bool includeInBoundary, double x, double y) {
00221 myOrigBoundary.add(from);
00222 if (x == -1 && y == -1) {
00223 x = from.x();
00224 y = from.y();
00225 }
00226 if (myProjectionMethod == NONE) {
00227 from.add(myOffset);
00228 } else if (myUseInverseProjection) {
00229 cartesian2geo(from);
00230 } else {
00231 x *= myGeoScale;
00232 y *= myGeoScale;
00233 if (x > 180.1 || x < -180.1 || y > 90.1 || y < -90.1) {
00234 return false;
00235 }
00236 #ifdef HAVE_PROJ
00237 if (myProjection==0) {
00238 if (myProjectionMethod == UTM) {
00239 int zone = (int)(x + 180) / 6 + 1;
00240 myProjString = "+proj=utm +zone=" + toString(zone) +
00241 " +ellps=WGS84 +datum=WGS84 +units=m +no_defs";
00242 myProjection = pj_init_plus(myProjString.c_str());
00244 }
00245 if (myProjectionMethod == DHDN) {
00246 int zone = (int)(x / 3);
00247 if (zone < 1 || zone > 5) {
00248 return false;
00249 }
00250 myProjString = "+proj=tmerc +lat_0=0 +lon_0=" + toString(3*zone) +
00251 " +k=1 +x_0=" + toString(zone * 1000000 + 500000) +
00252 " +y_0=0 +ellps=bessel +datum=potsdam +units=m +no_defs";
00253 myProjection = pj_init_plus(myProjString.c_str());
00255 }
00256 }
00257 if (myProjection!=0) {
00258 projUV p;
00259 p.u = x * DEG_TO_RAD;
00260 p.v = y * DEG_TO_RAD;
00261 p = pj_fwd(p, myProjection);
00263 x = p.u;
00264 y = p.v;
00265 }
00266 #endif
00267 if (myProjectionMethod == SIMPLE) {
00268 double ys = y;
00269 if (!myBaseFound) {
00270 myBaseX = x;
00271 myBaseY = y;
00272 myBaseFound = true;
00273 }
00274 x -= myBaseX;
00275 y -= myBaseY;
00276 x *= 111320. * cos(ys*PI/180.0);
00277 y *= 111136.;
00278 from.set((SUMOReal)x, (SUMOReal)y);
00280 from.add(myOffset);
00281 }
00282 }
00283 if (myProjectionMethod != SIMPLE) {
00284 if (!myBaseFound) {
00285 if (x > 100000 || y > 100000) {
00286 myBaseX = x;
00287 myBaseY = y;
00288 }
00289 myBaseFound = true;
00290 }
00291 if (myBaseFound) {
00292 x -= myBaseX;
00293 y -= myBaseY;
00294 }
00295 from.set((SUMOReal)x, (SUMOReal)y);
00296 from.add(myOffset);
00297 }
00298 if (includeInBoundary) {
00299 myConvBoundary.add(from);
00300 }
00301 return true;
00302 }
00303
00304
00305 void
00306 GeoConvHelper::moveConvertedBy(SUMOReal x, SUMOReal y) {
00307 myOffset.add(x, y);
00308 myConvBoundary.moveby(x, y);
00309 }
00310
00311
00312 const Boundary &
00313 GeoConvHelper::getOrigBoundary() {
00314 return myOrigBoundary;
00315 }
00316
00317
00318 const Boundary &
00319 GeoConvHelper::getConvBoundary() {
00320 return myConvBoundary;
00321 }
00322
00323
00324 const Position2D
00325 GeoConvHelper::getOffsetBase() {
00326 return Position2D(myOffset.x()-myBaseX, myOffset.y()-myBaseY);
00327 }
00328
00329
00330 const std::string &
00331 GeoConvHelper::getProjString() {
00332 return myProjString;
00333 }
00334
00335
00336
00337
00338