Changeset 4575


Ignore:
Timestamp:
Jul 27, 2014 1:28:15 PM (7 years ago)
Author:
ldelgass
Message:

Add optional coordinate conversion for 'map coords' command, add 'screen coords'
command to project map coords to screen coords.

Location:
trunk/packages/vizservers/geovis
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/packages/vizservers/geovis/Renderer.cpp

    r4574 r4575  
    2020#include <sys/time.h>
    2121#endif
     22
     23//#define USE_OSGEARTH_TRUNK
     24#define USE_CACHE
    2225
    2326#include <osgDB/FileUtils>
     
    4245#include <osgEarth/DateTime>
    4346#include <osgEarthUtil/EarthManipulator>
    44 #if OSGEARTH_MIN_VERSION_REQUIRED(2, 5, 1)
     47#if defined(USE_OSGEARTH_TRUNK) || OSGEARTH_MIN_VERSION_REQUIRED(2, 5, 1)
    4548#include <osgEarthUtil/Sky>
    4649#else
     
    106109    bopts.url() = BASE_IMAGE;
    107110    addImageLayer("base", bopts);
     111#ifdef USE_OSGEARTH_TRUNK
     112    osgEarth::Drivers::MPTerrainEngine::MPTerrainEngineOptions mpOpt;
     113#else
    108114    osgEarth::Drivers::MPTerrainEngineOptions mpOpt;
     115#endif
    109116    // Set background layer color
    110117    mpOpt.color() = osg::Vec4(1, 1, 1, 1);
     
    409416    _hbox->addControl(_scaleLabel.get());
    410417    _hbox->addControl(_scaleBar.get());
     418#ifdef USE_OSGEARTH_TRUNK
     419    osgEarth::Util::Controls::ControlCanvas::getOrCreate(_viewer.get())->addControl(_hbox.get());
     420#else
    411421    osgEarth::Util::Controls::ControlCanvas::get(_viewer.get(), true)->addControl(_hbox.get());
     422#endif
    412423    // Install an event callback to handle scale bar updates
    413424    // Can't use an update callback since that will trigger
     
    487498            osgEarth::Util::Controls::LabelControl *readout =
    488499                _coordsCallback->getLabel();
     500#ifdef USE_OSGEARTH_TRUNK
     501            osgEarth::Util::Controls::ControlCanvas::getOrCreate(_viewer.get())->removeControl(readout);
     502#else
    489503            osgEarth::Util::Controls::ControlCanvas::get(_viewer.get(), true)->removeControl(readout);
     504#endif
    490505            _coordsCallback = NULL;
    491506        }
     
    532547    } else {
    533548        readout = new osgEarth::Util::Controls::LabelControl("", 12.0f);
     549#ifdef USE_OSGEARTH_TRUNK
     550        osgEarth::Util::Controls::ControlCanvas::getOrCreate(_viewer.get())->addControl(readout);
     551#else
    534552        osgEarth::Util::Controls::ControlCanvas::get(_viewer.get(), true)->addControl(readout);
     553#endif
    535554        readout->setForeColor(osg::Vec4f(1, 1, 1, 1));
    536555        readout->setHaloColor(osg::Vec4f(0, 0, 0, 1));
     
    667686    }
    668687
     688#ifdef USE_CACHE
    669689    setupCache();
    670690    osgEarth::Drivers::FileSystemCacheOptions cacheOpts;
    671691    cacheOpts.rootPath() = _cacheDir;
    672692    mapOpts.cache() = cacheOpts;
     693#endif
    673694
    674695    initViewer();
     
    680701    bopts.url() = BASE_IMAGE;
    681702    addImageLayer("base", bopts);
     703#ifdef USE_OSGEARTH_TRUNK
     704    osgEarth::Drivers::MPTerrainEngine::MPTerrainEngineOptions mpOpt;
     705#else
    682706    osgEarth::Drivers::MPTerrainEngineOptions mpOpt;
     707#endif
    683708    // Set background layer color
    684709    mpOpt.color() = osg::Vec4(1, 1, 1, 1);
     
    693718    if (_map->isGeocentric()) {
    694719        osgEarth::DateTime now;
    695 #if OSGEARTH_MIN_VERSION_REQUIRED(2, 5, 1)
     720#if defined(USE_OSGEARTH_TRUNK) || OSGEARTH_MIN_VERSION_REQUIRED(2, 5, 1)
    696721        TRACE("Creating SkyNode");
    697722        osgEarth::Util::SkyOptions skyOpts;
     
    890915        return osgEarth::Viewpoint();
    891916    }
     917}
     918
     919static void srsInfo(const osgEarth::SpatialReference *srs)
     920{
     921    TRACE("SRS: %s", srs->getName().c_str());
     922    TRACE("horiz: \"%s\" vert: \"%s\"", srs->getHorizInitString().c_str(), srs->getVertInitString().c_str());
     923    TRACE("geographic: %d geodetic: %d projected: %d ecef: %d mercator: %d spherical mercator: %d northpolar: %d southpolar: %d userdefined: %d contiguous: %d cube: %d ltp: %d plate_carre: %d",
     924          srs->isGeographic() ? 1 : 0,
     925          srs->isGeodetic() ? 1 : 0,
     926          srs->isProjected() ? 1 : 0,
     927          srs->isECEF() ? 1 : 0,
     928          srs->isMercator() ? 1 : 0,
     929          srs->isSphericalMercator() ? 1 : 0,
     930          srs->isNorthPolar() ? 1 : 0,
     931          srs->isSouthPolar() ? 1 : 0,
     932          srs->isUserDefined() ? 1 : 0,
     933          srs->isContiguous() ? 1 : 0,
     934          srs->isCube() ? 1 : 0,
     935          srs->isLTP() ? 1 : 0,
     936          srs->isPlateCarre() ? 1 : 0);
     937}
     938
     939bool Renderer::getWorldCoords(const osgEarth::GeoPoint& mapPt, osg::Vec3d *world)
     940{
     941    if (!_mapNode.valid() || _mapNode->getTerrain() == NULL) {
     942        ERROR("No map");
     943        return false;
     944    }
     945    TRACE("Input SRS:");
     946    srsInfo(mapPt.getSRS());
     947    TRACE("Map SRS:");
     948    srsInfo(_mapNode->getMapSRS());
     949    bool ret = mapPt.toWorld(*world, _mapNode->getTerrain());
     950    TRACE("In: %g,%g,%g Out: %g,%g,%g",
     951          mapPt.x(), mapPt.y(), mapPt.z(),
     952          world->x(), world->y(), world->z());
     953    return ret;
     954}
     955
     956bool Renderer::worldToScreen(const osg::Vec3d& world, osg::Vec3d *screen, bool invertY)
     957{
     958    if (!_viewer.valid()) {
     959        ERROR("No viewer");
     960        return false;
     961    }
     962    osg::Camera *cam = _viewer->getCamera();
     963    osg::Matrixd MVP = cam->getViewMatrix() * cam->getProjectionMatrix();
     964    // Get clip coords
     965    osg::Vec4d pt;
     966    pt = osg::Vec4d(world, 1.0) * MVP;
     967    // Clip
     968    if (pt.x() < -pt.w() ||
     969        pt.x() > pt.w() ||
     970        pt.y() < -pt.w() ||
     971        pt.y() > pt.w() ||
     972        pt.z() < -pt.w() ||
     973        pt.z() > pt.w()) {
     974        // Outside frustum
     975        TRACE("invalid pt: %g,%g,%g,%g", pt.x(), pt.y(), pt.z(), pt.w());
     976        return false;
     977    }
     978    TRACE("clip pt: %g,%g,%g,%g", pt.x(), pt.y(), pt.z(), pt.w());
     979    // Perspective divide: now NDC
     980    pt /= pt.w();
     981    const osg::Viewport *viewport = cam->getViewport();
     982#if 1
     983    screen->x() = viewport->x() + viewport->width() * 0.5 + pt.x() * viewport->width() * 0.5;
     984    screen->y() = viewport->y() + viewport->height() * 0.5 + pt.y() * viewport->height() * 0.5;
     985    //double near = 0;
     986    //double far = 1;
     987    //screen->z() = (far + near) * 0.5 + (far - near) * 0.5 * pt.z();
     988    screen->z() = 0.5 + 0.5 * pt.z();
     989#else
     990    *screen = osg::Vec3d(pt.x(), pt.y(), pt.z()) * cam->getViewport()->computeWindowMatrix();
     991#endif
     992    if (invertY) {
     993        screen->y() = viewport->height() - screen->y();
     994    }
     995    TRACE("screen: %g,%g,%g", screen->x(), screen->y(), screen->z());
     996    return true;
    892997}
    893998
  • trunk/packages/vizservers/geovis/Renderer.h

    r4382 r4575  
    339339    double computeMapScale();
    340340
     341    const osgEarth::SpatialReference *getMapSRS()
     342    {
     343        if (_mapNode.valid()) {
     344            return _mapNode->getMapSRS();
     345        } else {
     346            return NULL;
     347        }
     348    }
     349
    341350    bool getMousePoint(double *x, double *y, double *z)
    342351    {
    343352        return (_coordsCallback.valid() && _coordsCallback->report(x, y, z));
    344353    }
     354
     355    bool getWorldCoords(const osgEarth::GeoPoint& mapPt, osg::Vec3d *world);
     356
     357    bool worldToScreen(const osg::Vec3d& world, osg::Vec3d *screen,
     358                       bool invertY = true);
    345359
    346360    long getTimeout();
  • trunk/packages/vizservers/geovis/RendererCmd.cpp

    r4424 r4575  
    733733    char mesg[256];
    734734    if (g_renderer->mapMouseCoords(x, y, mapPoint)) {
     735        std::string srsInit;
     736        std::string verticalDatum;
     737        if (objc > 4) {
     738            srsInit = Tcl_GetString(objv[4]);
     739            if (objc > 5) {
     740                verticalDatum = Tcl_GetString(objv[5]);
     741            }
     742            osgEarth::SpatialReference *outSRS =
     743                osgEarth::SpatialReference::get(srsInit, verticalDatum);
     744            if (outSRS == NULL) {
     745                Tcl_AppendResult(interp, "bad SRS \"", srsInit.c_str(), "\"", (char*)NULL);
     746                return TCL_ERROR;
     747            }
     748            mapPoint = mapPoint.transform(outSRS);
     749            if (!mapPoint.isValid()) {
     750                Tcl_AppendResult(interp, "Could not transform map point to requested SRS", (char*)NULL);
     751                return TCL_ERROR;
     752            }
     753        }
    735754        // send coords to client
    736755        length = snprintf(mesg, sizeof(mesg),
    737                           "nv>map coords %g %g %g %d %d\n",
     756                          "nv>map coords %g %g %g %d %d {%s} {%s}\n",
    738757                          mapPoint.x(), mapPoint.y(), mapPoint.z(),
    739                           x, y);
     758                          x, y,
     759                          mapPoint.getSRS()->getHorizInitString().c_str(),
     760                          mapPoint.getSRS()->getVertInitString().c_str());
    740761
    741762        queueResponse(mesg, length, Response::VOLATILE);
     
    12811302                return TCL_ERROR;
    12821303            }
     1304            // Note: plate-carre generates same SRS as others, but with
     1305            // _is_plate_carre flag set
     1306            // In map profile, _is_plate_carre is forced on for
     1307            // geographic+projected SRS
    12831308            if (strcmp(profile, "geodetic") == 0 ||
    1284                 strcmp(profile, "epsg:4326") == 0 ) {
     1309                strcmp(profile, "epsg:4326") == 0 ||
     1310                strcmp(profile, "wgs84") == 0 ||
     1311                strcmp(profile, "plate-carre") == 0) {
    12851312                if (bounds[0] < -180. || bounds[0] > 180. ||
    12861313                    bounds[2] < -180. || bounds[2] > 180. ||
     
    12921319            } else if (strcmp(profile, "spherical-mercator") == 0 ||
    12931320                       strcmp(profile, "epsg:900913") == 0 ||
    1294                        strcmp(profile, "epsg:3857") == 0) {
     1321                       strcmp(profile, "epsg:3785") == 0 ||
     1322                       strcmp(profile, "epsg:3857") == 0 ||
     1323                       strcmp(profile, "epsg:102113") == 0) {
    12951324                for (int i = 0; i < 4; i++) {
    12961325                    if (bounds[i] < -20037508.34 || bounds[i] > 20037508.34) {
     
    12991328                    }
    13001329                }
    1301             }
    1302 
     1330            } else if (strcmp(profile, "epsg:32662") == 0 ||
     1331                       strcmp(profile, "epsg:32663") == 0) {
     1332                if (bounds[0] < -20037508.3428 || bounds[0] > 20037508.3428 ||
     1333                    bounds[2] < -20037508.3428 || bounds[2] > 20037508.3428 ||
     1334                    bounds[1] < -10018754.1714 || bounds[1] > 10018754.1714 ||
     1335                    bounds[3] < -10018754.1714 || bounds[3] > 10018754.1714) {
     1336                    Tcl_AppendResult(interp, "invalid bounds", (char*)NULL);
     1337                    return TCL_ERROR;
     1338                }
     1339            }
    13031340            g_renderer->resetMap(type, profile, bounds);
    13041341        } else {
     
    14561493
    14571494static CmdSpec mapOps[] = {
    1458     {"coords",   1, MapCoordsOp,          4, 4, "x y"},
     1495    {"coords",   1, MapCoordsOp,          4, 6, "x y ?srs? ?verticalDatum?"},
    14591496    {"grid",     1, MapGraticuleOp,       3, 4, "bool ?type?"},
    14601497    {"layer",    2, MapLayerOp,           3, 0, "op ?params...?"},
     
    16551692
    16561693static int
     1694ScreenCoordsOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1695               Tcl_Obj *const *objv)
     1696{
     1697    double x, y, z;
     1698    if (Tcl_GetDoubleFromObj(interp, objv[2], &x) != TCL_OK ||
     1699        Tcl_GetDoubleFromObj(interp, objv[3], &y) != TCL_OK ||
     1700        Tcl_GetDoubleFromObj(interp, objv[4], &z) != TCL_OK) {
     1701        return TCL_ERROR;
     1702    }
     1703    const osgEarth::SpatialReference *srs = NULL;
     1704    if (objc < 6) {
     1705        srs = g_renderer->getMapSRS();
     1706        if (srs == NULL) {
     1707            Tcl_AppendResult(interp, "Could not determine map SRS", (char*)NULL);
     1708            return TCL_ERROR;
     1709        }
     1710    } else {
     1711        std::string srsInit(Tcl_GetString(objv[5]));
     1712        std::string verticalDatum;
     1713        if (objc > 6) {
     1714            verticalDatum = Tcl_GetString(objv[6]);
     1715        }
     1716        srs = osgEarth::SpatialReference::get(srsInit, verticalDatum);
     1717        if (srs == NULL) {
     1718            Tcl_AppendResult(interp, "bad SRS \"", srsInit.c_str(), "\"", (char*)NULL);
     1719            return TCL_ERROR;
     1720        }
     1721    }
     1722    // ALTMODE_RELATIVE is height above terrain, ALTMODE_ABSOLUTE means
     1723    // relative to the vertical datum
     1724    osgEarth::GeoPoint mapPoint(srs, x, y, z, osgEarth::ALTMODE_ABSOLUTE);
     1725    size_t length;
     1726    char mesg[256];
     1727    osg::Vec3d world;
     1728    osg::Vec3d screen;
     1729    if (g_renderer->getWorldCoords(mapPoint, &world) &&
     1730        g_renderer->worldToScreen(world, &screen)) {
     1731        // send coords to client
     1732        length = snprintf(mesg, sizeof(mesg),
     1733                          "nv>screen coords %g %g %g %g %g %g\n",
     1734                          screen.x(), screen.y(), screen.z(),
     1735                          x, y, z);
     1736
     1737        queueResponse(mesg, length, Response::VOLATILE);
     1738    } else {
     1739        // Out of range
     1740        length = snprintf(mesg, sizeof(mesg),
     1741                          "nv>screen coords invalid %g %g %g\n", x, y, z);
     1742
     1743        queueResponse(mesg, length, Response::VOLATILE);
     1744    }
     1745    return TCL_OK;
     1746}
     1747
     1748static int
    16571749ScreenSizeOp(ClientData clientData, Tcl_Interp *interp, int objc,
    16581750             Tcl_Obj *const *objv)
     
    16711763static CmdSpec screenOps[] = {
    16721764    {"bgcolor", 1, ScreenBgColorOp, 5, 5, "r g b"},
    1673     {"size", 1, ScreenSizeOp, 4, 4, "width height"}
     1765    {"coords",  1, ScreenCoordsOp, 5, 7, "x y z ?srs? ?verticalDatum?"},
     1766    {"size",    1, ScreenSizeOp, 4, 4, "width height"}
    16741767};
    16751768static int nScreenOps = NumCmdSpecs(screenOps);
Note: See TracChangeset for help on using the changeset viewer.