GeoConvHelper.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // static methods for processing the coordinates conversion for the current net
00008 /****************************************************************************/
00009 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00010 // Copyright 2001-2010 DLR (http://www.dlr.de/) and contributors
00011 /****************************************************************************/
00012 //
00013 //   This program is free software; you can redistribute it and/or modify
00014 //   it under the terms of the GNU General Public License as published by
00015 //   the Free Software Foundation; either version 2 of the License, or
00016 //   (at your option) any later version.
00017 //
00018 /****************************************************************************/
00019 
00020 
00021 // ===========================================================================
00022 // included modules
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 // static member variables
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 // method definitions
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     // !!! check pj_errno
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 

Generated on Wed May 5 00:06:29 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6