Changeset 4349


Ignore:
Timestamp:
Apr 25, 2014, 3:26:50 PM (10 years ago)
Author:
ldelgass
Message:

Improvements to coordinate display, scale bar

Location:
trunk/packages/vizservers/geovis
Files:
5 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/packages/vizservers/geovis/Makefile.in

    r4058 r4349  
    107107                RenderServer.cpp \
    108108                TGAWriter.cpp \
    109                 Trace.cpp
     109                Trace.cpp \
     110                ScaleBar.cpp \
     111                Stats.cpp
    110112
    111113ifdef USE_THREADS
     
    156158PPMWriter.o: PPMWriter.h ResponseQueue.h Trace.h
    157159ReadBuffer.o: ReadBuffer.h Trace.h
    158 Renderer.o: Renderer.h Trace.h
     160Renderer.o: Renderer.h Trace.h MouseCoordsTool.h ScaleBar.h
    159161RendererCmd.o: Renderer.h ReadBuffer.h ResponseQueue.h Trace.h CmdProc.h PPMWriter.h TGAWriter.h
    160 RenderServer.o: RenderServer.h RendererCmd.h Renderer.h ReadBuffer.h ResponseQueue.h Trace.h PPMWriter.h TGAWriter.h
     162RenderServer.o: RenderServer.h RendererCmd.h Renderer.h ReadBuffer.h ResponseQueue.h Trace.h PPMWriter.h TGAWriter.h Stats.h
    161163ResponseQueue.o: ResponseQueue.h Trace.h
     164ScaleBar.o: ScaleBar.h Trace.h
     165Stats.o: Stats.h RenderServer.h Trace.h md5.h
    162166Trace.o: Trace.h
  • trunk/packages/vizservers/geovis/RenderServer.cpp

    r4328 r4349  
    2828#include "RendererCmd.h"
    2929#include "Renderer.h"
     30#include "Stats.h"
    3031#include "PPMWriter.h"
    3132#include "TGAWriter.h"
     
    3738#endif
    3839#endif
    39 #include <md5.h>
    4040
    4141using namespace GeoVis;
     
    184184}
    185185
    186 int
    187 GeoVis::getStatsFile(Tcl_Interp *interp, Tcl_Obj *objPtr)
    188 {
    189     Tcl_DString ds;
    190     Tcl_Obj **objv;
    191     int objc;
    192     int i;
    193     char fileName[33];
    194     const char *path;
    195     md5_state_t state;
    196     md5_byte_t digest[16];
    197     char *string;
    198     int length;
    199 
    200     if ((objPtr == NULL) || (g_statsFile >= 0)) {
    201         return g_statsFile;
    202     }
    203     if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
    204         return -1;
    205     }
    206     Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("pid", 3));
    207     Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewIntObj(getpid()));
    208     string = Tcl_GetStringFromObj(objPtr, &length);
    209 
    210     md5_init(&state);
    211     md5_append(&state, (const md5_byte_t *)string, length);
    212     md5_finish(&state, digest);
    213     for (i = 0; i < 16; i++) {
    214         sprintf(fileName + i * 2, "%02x", digest[i]);
    215     }
    216     Tcl_DStringInit(&ds);
    217     Tcl_DStringAppend(&ds, STATSDIR, -1);
    218     Tcl_DStringAppend(&ds, "/", 1);
    219     Tcl_DStringAppend(&ds, fileName, 32);
    220     path = Tcl_DStringValue(&ds);
    221 
    222     g_statsFile = open(path, O_EXCL | O_CREAT | O_WRONLY, 0600);
    223     Tcl_DStringFree(&ds);
    224     if (g_statsFile < 0) {
    225         ERROR("can't open \"%s\": %s", fileName, strerror(errno));
    226         return -1;
    227     }
    228     return g_statsFile;
    229 }
    230 
    231 int
    232 GeoVis::writeToStatsFile(int f, const char *s, size_t length)
    233 {
    234     if (f >= 0) {
    235         ssize_t numWritten;
    236 
    237         numWritten = write(f, s, length);
    238         if (numWritten == (ssize_t)length) {
    239             close(dup(f));
    240         }
    241     }
    242     return 0;
    243 }
    244 
    245 static int
    246 serverStats(int code)
    247 {
    248     double start, finish;
    249     char buf[BUFSIZ];
    250     Tcl_DString ds;
    251     int result;
    252     int f;
    253 
    254     {
    255         struct timeval tv;
    256 
    257         /* Get ending time.  */
    258         gettimeofday(&tv, NULL);
    259         finish = CVT2SECS(tv);
    260         tv = g_stats.start;
    261         start = CVT2SECS(tv);
    262     }
    263     /*
    264      * Session information:
    265      *   - Name of render server
    266      *   - Process ID
    267      *   - Hostname where server is running
    268      *   - Start date of session
    269      *   - Start date of session in seconds
    270      *   - Number of data sets loaded from client
    271      *   - Number of data bytes total loaded from client
    272      *   - Number of frames returned
    273      *   - Number of bytes total returned (in frames)
    274      *   - Number of commands received
    275      *   - Total elapsed time of all commands
    276      *   - Total elapsed time of session
    277      *   - Exit code of vizserver
    278      *   - User time
    279      *   - System time
    280      *   - User time of children
    281      *   - System time of children
    282      */
    283 
    284     Tcl_DStringInit(&ds);
    285    
    286     Tcl_DStringAppendElement(&ds, "render_stop");
    287     /* renderer */
    288     Tcl_DStringAppendElement(&ds, "renderer");
    289     Tcl_DStringAppendElement(&ds, "geovis");
    290     /* pid */
    291     Tcl_DStringAppendElement(&ds, "pid");
    292     sprintf(buf, "%d", getpid());
    293     Tcl_DStringAppendElement(&ds, buf);
    294     /* host */
    295     Tcl_DStringAppendElement(&ds, "host");
    296     gethostname(buf, BUFSIZ-1);
    297     buf[BUFSIZ-1] = '\0';
    298     Tcl_DStringAppendElement(&ds, buf);
    299     /* date */
    300     Tcl_DStringAppendElement(&ds, "date");
    301     strcpy(buf, ctime(&g_stats.start.tv_sec));
    302     buf[strlen(buf) - 1] = '\0';
    303     Tcl_DStringAppendElement(&ds, buf);
    304     /* date_secs */
    305     Tcl_DStringAppendElement(&ds, "date_secs");
    306     sprintf(buf, "%ld", g_stats.start.tv_sec);
    307     Tcl_DStringAppendElement(&ds, buf);
    308     /* num_data_sets */
    309     Tcl_DStringAppendElement(&ds, "num_data_sets");
    310     sprintf(buf, "%lu", (unsigned long int)g_stats.nDataSets);
    311     Tcl_DStringAppendElement(&ds, buf);
    312     /* data_set_bytes */
    313     Tcl_DStringAppendElement(&ds, "data_set_bytes");
    314     sprintf(buf, "%lu", (unsigned long int)g_stats.nDataBytes);
    315     Tcl_DStringAppendElement(&ds, buf);
    316     /* num_frames */
    317     Tcl_DStringAppendElement(&ds, "num_frames");
    318     sprintf(buf, "%lu", (unsigned long int)g_stats.nFrames);
    319     Tcl_DStringAppendElement(&ds, buf);
    320     /* frame_bytes */
    321     Tcl_DStringAppendElement(&ds, "frame_bytes");
    322     sprintf(buf, "%lu", (unsigned long int)g_stats.nFrameBytes);
    323     Tcl_DStringAppendElement(&ds, buf);
    324     /* num_commands */
    325     Tcl_DStringAppendElement(&ds, "num_commands");
    326     sprintf(buf, "%lu", (unsigned long int)g_stats.nCommands);
    327     Tcl_DStringAppendElement(&ds, buf);
    328     /* cmd_time */
    329     Tcl_DStringAppendElement(&ds, "cmd_time");
    330     sprintf(buf, "%g", g_stats.cmdTime);
    331     Tcl_DStringAppendElement(&ds, buf);
    332     /* session_time */
    333     Tcl_DStringAppendElement(&ds, "session_time");
    334     sprintf(buf, "%g", finish - start);
    335     Tcl_DStringAppendElement(&ds, buf);
    336     /* status */
    337     Tcl_DStringAppendElement(&ds, "status");
    338     sprintf(buf, "%d", code);
    339     Tcl_DStringAppendElement(&ds, buf);
    340     {
    341         long clocksPerSec = sysconf(_SC_CLK_TCK);
    342         double clockRes = 1.0 / clocksPerSec;
    343         struct tms tms;
    344 
    345         memset(&tms, 0, sizeof(tms));
    346         times(&tms);
    347         /* utime */
    348         Tcl_DStringAppendElement(&ds, "utime");
    349         sprintf(buf, "%g", tms.tms_utime * clockRes);
    350         Tcl_DStringAppendElement(&ds, buf);
    351         /* stime */
    352         Tcl_DStringAppendElement(&ds, "stime");
    353         sprintf(buf, "%g", tms.tms_stime * clockRes);
    354         Tcl_DStringAppendElement(&ds, buf);
    355         /* cutime */
    356         Tcl_DStringAppendElement(&ds, "cutime");
    357         sprintf(buf, "%g", tms.tms_cutime * clockRes);
    358         Tcl_DStringAppendElement(&ds, buf);
    359         /* cstime */
    360         Tcl_DStringAppendElement(&ds, "cstime");
    361         sprintf(buf, "%g", tms.tms_cstime * clockRes);
    362         Tcl_DStringAppendElement(&ds, buf);
    363     }
    364     Tcl_DStringAppend(&ds, "\n", -1);
    365     f = getStatsFile(NULL, NULL);
    366     result = writeToStatsFile(f, Tcl_DStringValue(&ds),
    367                               Tcl_DStringLength(&ds));
    368     close(f);
    369     Tcl_DStringFree(&ds);
    370     return result;
    371 }
    372 
    373186static void
    374187initService()
     
    418231    TRACE("Enter");
    419232
    420     serverStats(0);
     233    serverStats(g_stats, 0);
    421234
    422235    // close log file
  • trunk/packages/vizservers/geovis/RenderServer.h

    r4308 r4349  
    11/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
    22/*
    3  * Copyright (C) 2013  HUBzero Foundation, LLC
     3 * Copyright (C) 2013-2014  HUBzero Foundation, LLC
    44 *
    55 * Author: Leif Delgass <ldelgass@purdue.edu>
     
    99#define GEOVIS_RENDERSERVER_H
    1010
     11#include <stdio.h>
    1112#include <sys/types.h>
    1213#include <sys/time.h>
     
    1819class CommandQueue;
    1920class ResponseQueue;
     21class Stats;
    2022
    2123#define GEOVIS_VERSION_STRING "0.4"
     
    2628
    2729#define CVT2SECS(x)  ((double)(x).tv_sec) + ((double)(x).tv_usec * 1.0e-6)
    28 
    29 #ifndef STATSDIR
    30 #define STATSDIR        "/var/tmp/visservers"
    31 #endif
    32 
    33 typedef struct {
    34     pid_t pid;
    35     size_t nDataSets;       /**< # of data sets received */
    36     size_t nDataBytes;      /**< # of bytes received as data sets */
    37     size_t nFrames;         /**< # of frames sent to client. */
    38     size_t nFrameBytes;     /**< # of bytes for all frames. */
    39     size_t nCommands;       /**< # of commands executed */
    40     double cmdTime;         /**< Elasped time spend executing commands. */
    41     struct timeval start;   /**< Start of elapsed time. */
    42 } Stats;
    4330
    4431extern Stats g_stats;
     
    5845extern int g_statsFile;
    5946extern int writeToStatsFile(int f, const char *s, size_t length);
    60 extern int getStatsFile(Tcl_Interp * interp, Tcl_Obj *objPtr);
     47extern int getStatsFile(const char *key = NULL);
    6148
    6249}
  • trunk/packages/vizservers/geovis/Renderer.cpp

    r4345 r4349  
    4343#include <osgEarthUtil/GeodeticGraticule>
    4444#include <osgEarthUtil/LatLongFormatter>
     45#include <osgEarthUtil/MGRSFormatter>
    4546#include <osgEarthUtil/GLSLColorFilter>
    4647#include <osgEarthUtil/VerticalScale>
     
    4950
    5051#include "Renderer.h"
     52#include "ScaleBar.h"
    5153#include "Trace.h"
    5254
     
    6264    _needsRedraw(false),
    6365    _windowWidth(500),
    64     _windowHeight(500)
     66    _windowHeight(500),
     67    _scaleBarUnits(UNITS_METERS)
    6568{
    6669    _bgColor[0] = 0;
     
    100103
    101104    initEarthManipulator();
    102     initMouseCoordsTool();
    103105    initControls();
    104106
     
    169171{
    170172    _colorMaps[id] = xfer;
    171 #if 0
    172     osgEarth::Drivers::GDALOptions opts;
    173     char *url =  Tcl_GetString(objv[4]);
    174     std::ostringstream oss;
    175     oss << "_cmap_" << id;
    176 
    177     opts.url() = url;
    178 
    179     addImageLayer(oss.str().c_str(), opts);
    180 #endif
    181173}
    182174
     
    312304        _viewer->realize();
    313305        initColorMaps();
     306        // HACK: This seems to initialize something required for properly
     307        // mapping mouse coords
     308        assert(getEventQueue() != NULL);
     309        getEventQueue()->mouseMotion(_windowWidth/2, _windowHeight/2);
    314310    }
    315311}
     
    343339    _hbox->addControl(_scaleBar.get());
    344340    osgEarth::Util::Controls::ControlCanvas::get(_viewer.get(), true)->addControl(_hbox.get());
     341    // Install an event callback to handle scale bar updates
     342    // Can't use an update callback since that will trigger
     343    // constant rendering
     344    _mapNode->setEventCallback(new MapNodeCallback(this));
    345345}
    346346
     
    383383}
    384384
    385 void Renderer::initMouseCoordsTool()
    386 {
     385void Renderer::setReadout(int x, int y)
     386{
     387    if (!_coordsCallback.valid() || !_mapNode.valid() || !_viewer.valid())
     388        return;
     389
     390    osgEarth::GeoPoint mapCoord;
     391    if (mapMouseCoords(x, y, mapCoord)) {
     392        _coordsCallback->set(mapCoord, _viewer->asView(), _mapNode);
     393    } else {
     394        _coordsCallback->reset(_viewer->asView(), _mapNode);
     395    }
     396    _needsRedraw = true;
     397}
     398
     399void Renderer::clearReadout()
     400{
     401    if (_coordsCallback.valid()) {
     402        _coordsCallback->reset(_viewer->asView(), _mapNode);
     403    }
     404    _needsRedraw = true;
     405}
     406
     407void Renderer::setCoordinateReadout(bool state, CoordinateDisplayType type,
     408                                    int precision)
     409{
     410    if (!state) {
     411        if (_mouseCoordsTool.valid() && _viewer.valid()) {
     412            _viewer->removeEventHandler(_mouseCoordsTool.get());
     413            _mouseCoordsTool = NULL;
     414        }
     415        if (_coordsCallback.valid() && _viewer.valid()) {
     416            osgEarth::Util::Controls::LabelControl *readout =
     417                _coordsCallback->getLabel();
     418            osgEarth::Util::Controls::ControlCanvas::get(_viewer.get(), true)->removeControl(readout);
     419            _coordsCallback = NULL;
     420        }
     421    } else {
     422        initMouseCoordsTool(type, precision);
     423    }
     424    _needsRedraw = true;
     425}
     426
     427osgEarth::Util::MGRSFormatter::Precision
     428Renderer::getMGRSPrecision(int precisionInMeters)
     429{
     430    switch (precisionInMeters) {
     431    case 1:
     432        return osgEarth::Util::MGRSFormatter::PRECISION_1M;
     433    case 10:
     434        return osgEarth::Util::MGRSFormatter::PRECISION_10M;
     435    case 100:
     436        return osgEarth::Util::MGRSFormatter::PRECISION_100M;
     437    case 1000:
     438        return osgEarth::Util::MGRSFormatter::PRECISION_1000M;
     439    case 10000:
     440        return osgEarth::Util::MGRSFormatter::PRECISION_10000M;
     441    case 100000:
     442        return osgEarth::Util::MGRSFormatter::PRECISION_100000M;
     443    default:
     444        ERROR("Invalid precision: %d", precisionInMeters);
     445        return osgEarth::Util::MGRSFormatter::PRECISION_1M;
     446    }
     447}
     448
     449void Renderer::initMouseCoordsTool(CoordinateDisplayType type, int precision)
     450{
     451    if (!_viewer.valid())
     452        return;
    387453    if (_mouseCoordsTool.valid()) {
    388454        _viewer->removeEventHandler(_mouseCoordsTool.get());
    389455    }
    390     _mouseCoordsTool = new osgEarth::Util::MouseCoordsTool(_mapNode.get());
    391 
    392     if (!_coordsCallback.valid()) {
    393         osgEarth::Util::Controls::LabelControl *readout =
    394             new osgEarth::Util::Controls::LabelControl("", 12.0f);
     456    _mouseCoordsTool = new MouseCoordsTool(_mapNode.get());
     457    osgEarth::Util::Controls::LabelControl *readout;
     458    if (_coordsCallback.valid()) {
     459        readout = _coordsCallback->getLabel();
     460        _coordsCallback = NULL;
     461    } else {
     462        readout = new osgEarth::Util::Controls::LabelControl("", 12.0f);
     463        osgEarth::Util::Controls::ControlCanvas::get(_viewer.get(), true)->addControl(readout);
    395464        readout->setForeColor(osg::Vec4f(1, 1, 1, 1));
    396465        readout->setHaloColor(osg::Vec4f(0, 0, 0, 1));
    397         osgEarth::Util::Controls::ControlCanvas::get(_viewer.get(), true)->addControl(readout);
    398         osgEarth::Util::LatLongFormatter *formatter =
    399             new osgEarth::Util::LatLongFormatter();
    400         formatter->setPrecision(5);
    401         _coordsCallback = new MouseCoordsCallback(readout, formatter);
    402     }
     466    }
     467
     468    osgEarth::Util::Formatter *formatter = NULL;
     469    if (type == COORDS_MGRS) {
     470        osgEarth::Util::MGRSFormatter::Precision prec =
     471            osgEarth::Util::MGRSFormatter::PRECISION_1M;
     472        if (precision > 0) {
     473            prec = getMGRSPrecision(precision);
     474        }
     475        unsigned int opts = 0u;
     476        formatter = new osgEarth::Util::MGRSFormatter(prec, NULL, opts);
     477    } else {
     478        osgEarth::Util::LatLongFormatter::AngularFormat af;
     479        unsigned int opts =  osgEarth::Util::LatLongFormatter::USE_SYMBOLS;
     480        switch (type) {
     481        case COORDS_LATLONG_DEGREES_DECIMAL_MINUTES:
     482            af = osgEarth::Util::LatLongFormatter::FORMAT_DEGREES_DECIMAL_MINUTES;
     483            break;
     484        case COORDS_LATLONG_DEGREES_MINUTES_SECONDS:
     485            af = osgEarth::Util::LatLongFormatter::FORMAT_DEGREES_MINUTES_SECONDS;
     486            break;
     487        default:
     488            af = osgEarth::Util::LatLongFormatter::FORMAT_DECIMAL_DEGREES;
     489        }
     490        osgEarth::Util::LatLongFormatter *latlong = new osgEarth::Util::LatLongFormatter(af, opts);
     491        if (precision > 0) {
     492            latlong->setPrecision(precision);
     493        }
     494        formatter = latlong;
     495    }
     496    _coordsCallback = new MouseCoordsCallback(readout, formatter);
     497
    403498    _mouseCoordsTool->addCallback(_coordsCallback.get());
    404499    _viewer->addEventHandler(_mouseCoordsTool.get());
     
    457552    _viewer->setSceneData(_sceneRoot.get());
    458553
    459     initMouseCoordsTool();
     554    if (_mouseCoordsTool.valid()) {
     555        initMouseCoordsTool();
     556    }
    460557    initControls();
    461558    initEarthManipulator();
     
    548645    }
    549646    _viewer->setSceneData(_sceneRoot.get());
    550     initMouseCoordsTool();
     647    if (_mouseCoordsTool.valid()) {
     648        initMouseCoordsTool();
     649    }
    551650    initControls();
    552651    //_viewer->setSceneData(_sceneRoot.get());
     
    10761175        }
    10771176#endif
     1177        // HACK: Without this, the mouse coordinate mapping uses the old size
     1178        // for 1 frame.
     1179        assert(_viewer->getEventQueue() != NULL);
     1180        //TRACE("Window EventQueue: %p", getEventQueue());
     1181        //TRACE("Viewer EventQueue: %p", _viewer->getEventQueue());
     1182        _viewer->getEventQueue()->windowResize(0, 0, _windowWidth, _windowHeight);
    10781183        _needsRedraw = true;
    10791184    }
     
    13441449
    13451450/**
     1451 * \brief MapNode event phase
     1452 *
     1453 * This is called by the MapNode's event callback during the event
     1454 * traversal of the viewer
     1455 */
     1456void Renderer::mapNodeUpdate()
     1457{
     1458    computeMapScale();
     1459}
     1460
     1461/**
    13461462 * \brief Cause the rendering to render a new image if needed
    13471463 *
     
    13531469    if (_viewer.valid() && checkNeedToDoFrame()) {
    13541470        TRACE("Enter needsRedraw=%d",  _needsRedraw ? 1 : 0);
    1355         computeMapScale();
    13561471        osg::Timer_t startFrameTick = osg::Timer::instance()->tick();
    13571472        TRACE("Before frame()");
     
    13871502    else
    13881503        return NULL;
     1504}
     1505
     1506void Renderer::setScaleBar(bool state)
     1507{
     1508    if (_scaleLabel.valid()) {
     1509        _scaleLabel->setVisible(state);
     1510    }
     1511    if (_scaleBar.valid()) {
     1512        _scaleBar->setVisible(state);
     1513    }
     1514    _needsRedraw = true;
     1515}
     1516
     1517void Renderer::setScaleBarUnits(ScaleBarUnits units)
     1518{
     1519    _scaleBarUnits = units;
     1520    _needsRedraw = true;
    13891521}
    13901522
     
    14031535double Renderer::computeMapScale()
    14041536{
     1537    if (!_scaleLabel.valid() || !_scaleLabel->visible()) {
     1538        return -1.0;
     1539    }
    14051540    if (!_mapNode.valid() || _mapNode->getTerrain() == NULL) {
    14061541        ERROR("No map");
     
    14791614
    14801615    double scale = meters / pixelWidth;
     1616    // 1mi = 5280 feet
     1617    //double scaleMiles = scale / 1609.344; // International mile = 1609.344m
     1618    //double scaleNauticalMiles = scale / 1852.0; // nautical mile = 1852m
     1619    //double scaleUSSurveyMiles = scale / 1609.347218694; // US survey mile = 5280 US survey feet
     1620    //double scaleUSSurveyFeet = scale * 3937.0/1200.0; // US survey foot = 1200/3937 m
    14811621    TRACE("m: %g px: %g m/px: %g", meters, pixelWidth, scale);
    1482     if (meters <= 3) {
    1483         meters = 1;
    1484     } else if (meters <= 7.5) {
    1485         meters = 5;
    1486     } else if (meters <= 15) {
    1487         meters = 10;
    1488     } else if (meters <= 35) {
    1489         meters = 20;
    1490     } else if (meters <= 75) {
    1491         meters = 50;
    1492     } else if (meters <= 150) {
    1493         meters = 100;
    1494     } else if (meters <= 350) {
    1495         meters = 200;
    1496     } else if (meters <= 750) {
    1497         meters = 500;
    1498     } else if (meters <= 1500) {
    1499         meters = 1000;
    1500     } else if (meters <= 3500) {
    1501         meters = 2000;
    1502     } else if (meters <= 7500) {
    1503         meters = 5000;
    1504     } else if (meters <= 15000) {
    1505         meters = 10000;
    1506     } else if (meters <= 35000) {
    1507         meters = 20000;
    1508     } else if (meters <= 55000) {
    1509         meters = 50000;
    1510     } else if (meters <= 150000) {
    1511         meters = 100000;
    1512     } else if (meters <= 350000) {
    1513         meters = 200000;
    1514     } else if (meters <= 750000) {
    1515         meters = 500000;
    1516     } else if (meters <= 1500000) {
    1517         meters = 1000000;
    1518     } else {
    1519         meters = 2000000;
    1520     }
    1521     pixelWidth = meters / scale;
    1522     if (_scaleLabel.valid()) {
    1523         if (meters >= 1000) {
     1622    switch (_scaleBarUnits) {
     1623    case UNITS_NAUTICAL_MILES: {
     1624        double nmi = meters / 1852.0;
     1625        scale = nmi / pixelWidth;
     1626        nmi = normalizeScaleNauticalMiles(nmi);
     1627        pixelWidth = nmi / scale;
     1628        if (_scaleLabel.valid()) {
    15241629            _scaleLabel->setText(osgEarth::Stringify()
    1525                                  << meters / 1000.0
    1526                                  << " km");
     1630                                 << nmi
     1631                                 << " nmi");
     1632        }
     1633    }
     1634        break;
     1635    case UNITS_US_SURVEY_FEET:
     1636    case UNITS_INTL_FEET: {
     1637        double feet;
     1638        if (_scaleBarUnits == UNITS_US_SURVEY_FEET) {
     1639            feet = meters * 3937.0/1200.0;
    15271640        } else {
    1528             _scaleLabel->setText(osgEarth::Stringify()
    1529                                  << meters
    1530                                  << " m");
    1531         }
     1641            feet = 5280.0 * meters / 1609.344;
     1642        }
     1643        scale = feet / pixelWidth;
     1644        feet = normalizeScaleFeet(feet);
     1645        pixelWidth = feet / scale;
     1646        if (_scaleLabel.valid()) {
     1647            if (feet >= 5280) {
     1648                _scaleLabel->setText(osgEarth::Stringify()
     1649                                     << feet / 5280.0
     1650                                     << " mi");
     1651            } else {
     1652                _scaleLabel->setText(osgEarth::Stringify()
     1653                                     << feet
     1654                                     << " ft");
     1655            }
     1656        }
     1657    }
     1658        break;
     1659    case UNITS_METERS:
     1660    default: {
     1661        meters = normalizeScaleMeters(meters);
     1662        pixelWidth = meters / scale;
     1663        if (_scaleLabel.valid()) {
     1664            if (meters >= 1000) {
     1665                _scaleLabel->setText(osgEarth::Stringify()
     1666                                     << meters / 1000.0
     1667                                     << " km");
     1668            } else {
     1669                _scaleLabel->setText(osgEarth::Stringify()
     1670                                     << meters
     1671                                     << " m");
     1672            }
     1673        }
     1674    }
     1675        break;
    15321676    }
    15331677    if (_scaleBar.valid()) {
  • trunk/packages/vizservers/geovis/Renderer.h

    r4345 r4349  
    3434#include <osgEarthUtil/Controls>
    3535#include <osgEarthUtil/Formatter>
     36#include <osgEarthUtil/MGRSFormatter>
    3637#include <osgEarthUtil/AutoClipPlaneHandler>
    3738#include <osgEarthUtil/VerticalScale>
     
    3940#include "Types.h"
    4041#include "Trace.h"
     42#include "MouseCoordsTool.h"
     43#include "ScaleBar.h"
    4144
    4245// Controls if TGA format is sent to client
     
    99102};
    100103
    101 class MouseCoordsCallback : public osgEarth::Util::MouseCoordsTool::Callback
    102 {
    103 public:
    104     MouseCoordsCallback(osgEarth::Util::Controls::LabelControl *label,
    105                         osgEarth::Util::Formatter *formatter) :
    106         osgEarth::Util::MouseCoordsTool::Callback(),
    107         _label(label),
    108         _formatter(formatter),
    109         _havePoint(false)
    110     {
    111     }
    112 
    113     void set(const osgEarth::GeoPoint& mapCoords, osg::View *view, osgEarth::MapNode *mapNode)
    114     {
    115         TRACE("%g %g %g", mapCoords.x(), mapCoords.y(), mapCoords.z());
    116         if (_label.valid()) {
    117             _label->setText(osgEarth::Stringify()
    118                             << "Lat/Long: "
    119                             <<  _formatter->format(mapCoords));
    120                             //<< ", " << mapCoords.z());
    121         }
    122         _pt = mapCoords;
    123         _havePoint = true;
    124     }
    125 
    126     void reset(osg::View *view, osgEarth::MapNode *mapNode)
    127     {
    128         TRACE("Out of range");
    129         // Out of range of map extents
    130         if (_label.valid()) {
    131             _label->setText("");
    132         }
    133         _havePoint = false;
    134     }
    135 
    136     bool report(double *x, double *y, double *z)
    137     {
    138         if (_havePoint) {
    139             *x = _pt.x();
    140             *y = _pt.y();
    141             *z = _pt.z();
    142             _havePoint = false;
    143             return true;
    144         }
    145         return false;
    146     }
    147 
    148 private:
    149     osg::observer_ptr<osgEarth::Util::Controls::LabelControl> _label;
    150     osg::ref_ptr<osgEarth::Util::Formatter> _formatter;
    151     bool _havePoint;
    152     osgEarth::GeoPoint _pt;
    153 };
    154 
    155104/**
    156105 * \brief GIS Renderer
     
    168117    };
    169118
     119    enum CoordinateDisplayType {
     120        COORDS_LATLONG_DECIMAL_DEGREES,
     121        COORDS_LATLONG_DEGREES_DECIMAL_MINUTES,
     122        COORDS_LATLONG_DEGREES_MINUTES_SECONDS,
     123        COORDS_MGRS
     124    };
     125
    170126    Renderer();
    171127    virtual ~Renderer();
     
    190146
    191147    // Map options
     148
     149    void setCoordinateReadout(bool state,
     150                              CoordinateDisplayType type = COORDS_LATLONG_DECIMAL_DEGREES,
     151                              int precision = -1);
     152
     153    void setReadout(int mouseX, int mouseY);
     154
     155    void clearReadout();
     156
     157    void setScaleBar(bool state);
     158
     159    void setScaleBarUnits(ScaleBarUnits units);
    192160
    193161    void setGraticule(bool enable, GraticuleType type = GRATICULE_GEODETIC);
     
    378346    long getTimeout();
    379347
     348    void mapNodeUpdate();
     349
    380350private:
    381351    typedef std::tr1::unordered_map<ColorMapId, osg::ref_ptr<osg::TransferFunction1D> > ColorMapHashmap;
     
    390360    void initEarthManipulator();
    391361
    392     void initMouseCoordsTool();
     362    void initMouseCoordsTool(CoordinateDisplayType type = COORDS_LATLONG_DECIMAL_DEGREES,
     363                             int precision = -1);
     364
     365    osgEarth::Util::MGRSFormatter::Precision getMGRSPrecision(int precisionInMeters);
    393366
    394367    void initColorMaps();
     
    420393    osg::ref_ptr<ScreenCaptureCallback> _captureCallback;
    421394    osg::ref_ptr<osgEarth::Util::AutoClipPlaneCullCallback> _clipPlaneCullCallback;
    422     osg::ref_ptr<osgEarth::Util::MouseCoordsTool> _mouseCoordsTool;
     395    osg::ref_ptr<MouseCoordsTool> _mouseCoordsTool;
    423396    osg::ref_ptr<MouseCoordsCallback> _coordsCallback;
    424397    osg::ref_ptr<osgEarth::Util::Controls::HBox> _hbox;
     
    426399    osg::ref_ptr<osgEarth::Util::Controls::LabelControl> _scaleLabel;
    427400    osg::ref_ptr<osgEarth::Util::Controls::Frame> _scaleBar;
     401    ScaleBarUnits _scaleBarUnits;
    428402    osg::ref_ptr<osgEarth::Util::EarthManipulator> _manipulator;
    429403    osg::ref_ptr<osgGA::StateSetManipulator> _stateManip;
     
    432406};
    433407
     408class MapNodeCallback : public osg::NodeCallback
     409{
     410public:
     411    MapNodeCallback(Renderer *renderer) :
     412        _renderer(renderer)
     413    {}
     414
     415    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
     416    {
     417        _renderer->mapNodeUpdate();
     418        traverse(node, nv);
     419    }
     420private:
     421    Renderer *_renderer;
     422};
     423
    434424}
    435425
  • trunk/packages/vizservers/geovis/RendererCmd.cpp

    r4346 r4349  
    4141#include "RenderServer.h"
    4242#include "Renderer.h"
     43#include "Stats.h"
    4344#include "PPMWriter.h"
    4445#include "TGAWriter.h"
     
    447448    static bool first = true;
    448449
    449     /* Use the initial client key value pairs as the parts for a generating
    450      * a unique file name. */
    451     int fd = GeoVis::getStatsFile(interp, objv[1]);
     450    /* Client arguments. */
     451    if (Tcl_ListObjGetElements(interp, objv[1], &numItems, &items) != TCL_OK) {
     452        return TCL_ERROR;
     453    }
     454
     455    /* First try to see if we already have an open descriptor */
     456    int fd = getStatsFile();
    452457    if (fd < 0) {
    453         Tcl_AppendResult(interp, "can't open stats file: ",
    454                          Tcl_PosixError(interp), (char *)NULL);
    455         return TCL_ERROR;
     458        /* Use the initial client key value pairs as the parts for generating
     459         * a unique file name. */
     460        fd = GeoVis::getStatsFile(Tcl_GetString(objv[1]));
     461        if (fd < 0) {
     462            Tcl_AppendResult(interp, "can't open stats file: ",
     463                             Tcl_PosixError(interp), (char *)NULL);
     464            return TCL_ERROR;
     465        }
    456466    }
    457467    listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
     
    461471        objPtr = Tcl_NewStringObj("render_start", 12);
    462472        Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
    463         /* server */
    464         objPtr = Tcl_NewStringObj("server", 6);
     473        /* renderer */
     474        objPtr = Tcl_NewStringObj("renderer", 8);
    465475        Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
    466476        objPtr = Tcl_NewStringObj("geovis", 6);
     
    470480        Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
    471481        Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewIntObj(getpid()));
    472         /* machine */
    473         objPtr = Tcl_NewStringObj("machine", 7);
     482        /* host */
     483        objPtr = Tcl_NewStringObj("host", 4);
    474484        Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
    475485        gethostname(buf, BUFSIZ-1);
     
    491501    Tcl_ListObjAppendElement(interp, listObjPtr,
    492502                             Tcl_NewLongObj(GeoVis::g_stats.start.tv_sec));
    493     /* Client arguments. */
    494     if (Tcl_ListObjGetElements(interp, objv[1], &numItems, &items) != TCL_OK) {
    495         return TCL_ERROR;
    496     }
     503    /* client items */
    497504    for (int i = 0; i < numItems; i++) {
    498505        Tcl_ListObjAppendElement(interp, listObjPtr, items[i]);
     
    11431150        return TCL_ERROR;
    11441151    }
     1152    return TCL_OK;
     1153}
     1154
     1155static int
     1156MapPositionDisplayOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1157                     Tcl_Obj *const *objv)
     1158{
     1159    bool state;
     1160    if (GetBooleanFromObj(interp, objv[2], &state) != TCL_OK) {
     1161        return TCL_ERROR;
     1162    }
     1163    Renderer::CoordinateDisplayType type = Renderer::COORDS_LATLONG_DECIMAL_DEGREES;
     1164    if (state && objc > 3) {
     1165        const char *str = Tcl_GetString(objv[3]);
     1166        if (str[0] == 'l' && strcmp(str, "latlong_decimal_degrees") == 0) {
     1167            type = Renderer::COORDS_LATLONG_DECIMAL_DEGREES;
     1168        } else if (str[0] == 'l' && strcmp(str, "latlong_degrees_decimal_minutes") == 0) {
     1169            type = Renderer::COORDS_LATLONG_DEGREES_DECIMAL_MINUTES;
     1170        } else if (str[0] == 'l' && strcmp(str, "latlong_degrees_minutes_seconds") == 0) {
     1171            type = Renderer::COORDS_LATLONG_DEGREES_MINUTES_SECONDS;
     1172        } else if (str[0] == 'm' && strcmp(str, "mgrs") == 0) {
     1173            type = Renderer::COORDS_MGRS;
     1174        } else {
     1175            Tcl_AppendResult(interp, "invalid type: \"", str,
     1176                             "\": should be 'latlong_decimal_degrees', 'latlong_degrees_decimal_minutes', 'latlong_degrees_minutes_seconds', or 'mgrs'",
     1177                             (char*)NULL);
     1178            return TCL_ERROR;
     1179        }
     1180    }
     1181    if (state && objc > 4) {
     1182        int precision;
     1183        if (Tcl_GetIntFromObj(interp, objv[4], &precision) != TCL_OK) {
     1184            return TCL_ERROR;
     1185        }
     1186        g_renderer->setCoordinateReadout(state, type, precision);
     1187    } else {
     1188        g_renderer->setCoordinateReadout(state, type);
     1189    }
     1190
    11451191    return TCL_OK;
    11461192}
     
    12251271
    12261272static int
     1273MapScaleBarOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1274              Tcl_Obj *const *objv)
     1275{
     1276    bool state;
     1277    if (GetBooleanFromObj(interp, objv[2], &state) != TCL_OK) {
     1278        return TCL_ERROR;
     1279    }
     1280    g_renderer->setScaleBar(state);
     1281    if (state && objc > 3) {
     1282        const char *unitStr = Tcl_GetString(objv[3]);
     1283        ScaleBarUnits units;
     1284        if (unitStr[0] == 'm' && strcmp(unitStr, "meters") == 0) {
     1285            units = UNITS_METERS;
     1286        } else if (unitStr[0] == 'f' && strcmp(unitStr, "feet") == 0) {
     1287            units = UNITS_INTL_FEET;
     1288        } else if (unitStr[0] == 'u' && strcmp(unitStr, "us_survey_feet") == 0) {
     1289            units = UNITS_US_SURVEY_FEET;
     1290        } else if (unitStr[0] == 'n' && strcmp(unitStr, "nautical_miles") == 0) {
     1291            units = UNITS_NAUTICAL_MILES;
     1292        } else {
     1293            Tcl_AppendResult(interp, "bad units \"", unitStr,
     1294                             "\": must be 'meters', 'feet', 'us_survey_feet' or 'nautical_miles'", (char*)NULL);
     1295            return TCL_ERROR;
     1296        }
     1297        g_renderer->setScaleBarUnits(units);
     1298    }
     1299    return TCL_OK;
     1300}
     1301
     1302static int
     1303MapSetPositionOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1304            Tcl_Obj *const *objv)
     1305{
     1306    if (objc < 3) {
     1307        g_renderer->clearReadout();
     1308    } else {
     1309        int x, y;
     1310        if (Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK ||
     1311            Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK) {
     1312            return TCL_ERROR;
     1313        }
     1314        g_renderer->setReadout(x, y);
     1315    }
     1316    return TCL_OK;
     1317}
     1318
     1319static int
    12271320MapTerrainEdgesOp(ClientData clientData, Tcl_Interp *interp, int objc,
    12281321                  Tcl_Obj *const *objv)
     
    13151408
    13161409static CmdSpec mapOps[] = {
    1317     {"coords",   1, MapCoordsOp,      4, 4, "x y"},
    1318     {"grid",     1, MapGraticuleOp,   3, 4, "bool ?type?"},
    1319     {"layer",    2, MapLayerOp,       3, 0, "op ?params...?"},
    1320     {"load",     2, MapLoadOp,        4, 5, "options"},
    1321     {"reset",    1, MapResetOp,       3, 8, "type ?profile xmin ymin xmax ymax?"},
    1322     {"terrain",  1, MapTerrainOp,     3, 0, "op ?params...?"},
     1410    {"coords",   1, MapCoordsOp,          4, 4, "x y"},
     1411    {"grid",     1, MapGraticuleOp,       3, 4, "bool ?type?"},
     1412    {"layer",    2, MapLayerOp,           3, 0, "op ?params...?"},
     1413    {"load",     2, MapLoadOp,            4, 5, "options"},
     1414    {"posdisp",  1, MapPositionDisplayOp, 3, 5, "bool ?format? ?precision?"},
     1415    {"reset",    1, MapResetOp,           3, 8, "type ?profile xmin ymin xmax ymax?"},
     1416    {"scalebar", 1, MapScaleBarOp,        3, 4, "bool ?units?"},
     1417    {"setpos",   1, MapSetPositionOp,     2, 4, "x y"},
     1418    {"terrain",  1, MapTerrainOp,         3, 0, "op ?params...?"},
    13231419};
    13241420static int nMapOps = NumCmdSpecs(mapOps);
Note: See TracChangeset for help on using the changeset viewer.