Changeset 4345


Ignore:
Timestamp:
Apr 20, 2014 10:34:27 PM (10 years ago)
Author:
ldelgass
Message:

First pass at scale bar

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

Legend:

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

    r4328 r4345  
    101101    initEarthManipulator();
    102102    initMouseCoordsTool();
     103    initControls();
    103104
    104105    finalizeViewer();
     
    314315}
    315316
     317void Renderer::initControls()
     318{
     319    if (_hbox.valid())
     320        return;
     321    _hbox =
     322        new osgEarth::Util::Controls::HBox(osgEarth::Util::Controls::Control::ALIGN_RIGHT,
     323                                           osgEarth::Util::Controls::Control::ALIGN_BOTTOM,
     324                                           osgEarth::Util::Controls::Gutter(0, 2, 2, 0), 2.0f);
     325    _copyrightLabel =
     326        new osgEarth::Util::Controls::LabelControl("Map data © 2014 ACME Corp.", 12.0f);
     327    _copyrightLabel->setForeColor(osg::Vec4f(1, 1, 1, 1));
     328    _copyrightLabel->setHaloColor(osg::Vec4f(0, 0, 0, 1));
     329    _copyrightLabel->setEncoding(osgText::String::ENCODING_UTF8);
     330    _scaleLabel =
     331        new osgEarth::Util::Controls::LabelControl("- km", 12.0f);
     332    _scaleLabel->setForeColor(osg::Vec4f(1, 1, 1, 1));
     333    _scaleLabel->setHaloColor(osg::Vec4f(0, 0, 0, 1));
     334    _scaleBar =
     335        new osgEarth::Util::Controls::Frame();
     336    _scaleBar->setVertFill(true);
     337    _scaleBar->setForeColor(osg::Vec4f(0, 0, 0, 1));
     338    _scaleBar->setBackColor(osg::Vec4f(1, 1, 1, 0.6));
     339    _scaleBar->setBorderColor(osg::Vec4f(0, 0, 0 ,1));
     340    _scaleBar->setBorderWidth(1.0);
     341    _hbox->addControl(_copyrightLabel.get());
     342    _hbox->addControl(_scaleLabel.get());
     343    _hbox->addControl(_scaleBar.get());
     344    osgEarth::Util::Controls::ControlCanvas::get(_viewer.get(), true)->addControl(_hbox.get());
     345}
     346
    316347void Renderer::setGraticule(bool enable, GraticuleType type)
    317348{
     
    362393        osgEarth::Util::Controls::LabelControl *readout =
    363394            new osgEarth::Util::Controls::LabelControl("", 12.0f);
     395        readout->setForeColor(osg::Vec4f(1, 1, 1, 1));
     396        readout->setHaloColor(osg::Vec4f(0, 0, 0, 1));
    364397        osgEarth::Util::Controls::ControlCanvas::get(_viewer.get(), true)->addControl(readout);
    365398        osgEarth::Util::LatLongFormatter *formatter =
     
    425458
    426459    initMouseCoordsTool();
     460    initControls();
    427461    initEarthManipulator();
    428462   
     
    515549    _viewer->setSceneData(_sceneRoot.get());
    516550    initMouseCoordsTool();
     551    initControls();
    517552    //_viewer->setSceneData(_sceneRoot.get());
    518553    initEarthManipulator();
     
    690725    }
    691726    if (!_viewer.valid()) {
    692         ERROR("No Viewer");
     727        ERROR("No viewer");
    693728        return false;
    694729    }
     
    13181353    if (_viewer.valid() && checkNeedToDoFrame()) {
    13191354        TRACE("Enter needsRedraw=%d",  _needsRedraw ? 1 : 0);
    1320 
     1355        computeMapScale();
    13211356        osg::Timer_t startFrameTick = osg::Timer::instance()->tick();
    13221357        TRACE("Before frame()");
     
    13531388        return NULL;
    13541389}
     1390
     1391/**
     1392 * \brief Compute the scale ratio of the map based on a horizontal center line
     1393 *
     1394 * The idea here is to take 2 screen points on a horizontal line in the center
     1395 * of the screen and convert to lat/long.  The lat/long coordinates are then
     1396 * used to compute the great circle distance (assuming spherical earth) between
     1397 * the points.
     1398 *
     1399 * We could use local projected map coordinates for the distance computation,
     1400 * which would be faster; however, this would not show e.g. the change in
     1401 * scale at different latitudes
     1402 */
     1403double Renderer::computeMapScale()
     1404{
     1405    if (!_mapNode.valid() || _mapNode->getTerrain() == NULL) {
     1406        ERROR("No map");
     1407        return -1.0;
     1408    }
     1409    if (!_viewer.valid()) {
     1410        ERROR("No viewer");
     1411        return -1.0;
     1412    }
     1413
     1414    double x, y;
     1415    double pixelWidth = _windowWidth * 0.1 * 2.0;
     1416    if (pixelWidth < 10)
     1417        pixelWidth = 10;
     1418    if (pixelWidth > 150)
     1419        pixelWidth = 150;
     1420    x = (double)(_windowWidth -1)/2.0 - pixelWidth / 2.0;
     1421    y = (double)(_windowHeight-1)/2.0;
     1422
     1423    osg::Vec3d world1, world2;
     1424    if (!_mapNode->getTerrain()->getWorldCoordsUnderMouse(_viewer->asView(), x, y, world1)) {
     1425        // off map
     1426        TRACE("Off map coords: %g %g", x, y);
     1427        _scaleLabel->setText("");
     1428        _scaleBar->setWidth(0);
     1429        return -1.0;
     1430    }
     1431    x += pixelWidth;
     1432    if (!_mapNode->getTerrain()->getWorldCoordsUnderMouse(_viewer->asView(), x, y, world2)) {
     1433        // off map
     1434        TRACE("Off map coords: %g %g", x, y);
     1435        _scaleLabel->setText("");
     1436        _scaleBar->setWidth(0);
     1437        return -1.0;
     1438    }
     1439
     1440    TRACE("w1: %g %g %g w2: %g %g %g",
     1441          world1.x(), world1.y(), world1.z(),
     1442          world2.x(), world2.y(), world2.z());
     1443
     1444    double meters;
     1445    double radius = 6378137.0;
     1446    if (_mapNode->getMapSRS() &&
     1447        _mapNode->getMapSRS()->getEllipsoid()) {
     1448        radius = _mapNode->getMapSRS()->getEllipsoid()->getRadiusEquator();
     1449    }
     1450    if (!_map->isGeocentric() &&
     1451        _mapNode->getMapSRS() &&
     1452        _mapNode->getMapSRS()->isGeographic()) {
     1453        TRACE("Map is geographic");
     1454        // World cords are already lat/long
     1455        // Compute great circle distance
     1456        meters =
     1457            osgEarth::GeoMath::distance(world1, world2, _mapNode->getMapSRS());
     1458    } else if (_mapNode->getMapSRS()) {
     1459        // Get map coords in lat/long
     1460        osgEarth::GeoPoint mapPoint1, mapPoint2;
     1461        mapPoint1.fromWorld(_mapNode->getMapSRS(), world1);
     1462        mapPoint1.makeGeographic();
     1463        mapPoint2.fromWorld(_mapNode->getMapSRS(), world2);
     1464        mapPoint2.makeGeographic();
     1465        // Compute great circle distance
     1466        meters =
     1467            osgEarth::GeoMath::distance(osg::DegreesToRadians(mapPoint1.y()),
     1468                                        osg::DegreesToRadians(mapPoint1.x()),
     1469                                        osg::DegreesToRadians(mapPoint2.y()),
     1470                                        osg::DegreesToRadians(mapPoint2.x()),
     1471                                        radius);
     1472    } else {
     1473        // Assume geocentric?
     1474        ERROR("No map SRS");
     1475        _scaleLabel->setText("");
     1476        _scaleBar->setWidth(0);
     1477        return -1.0;
     1478    }
     1479
     1480    double scale = meters / pixelWidth;
     1481    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) {
     1524            _scaleLabel->setText(osgEarth::Stringify()
     1525                                 << meters / 1000.0
     1526                                 << " km");
     1527        } else {
     1528            _scaleLabel->setText(osgEarth::Stringify()
     1529                                 << meters
     1530                                 << " m");
     1531        }
     1532    }
     1533    if (_scaleBar.valid()) {
     1534        _scaleBar->setWidth(pixelWidth);
     1535    }
     1536    return scale;
     1537}
  • trunk/packages/vizservers/geovis/Renderer.h

    r4322 r4345  
    111111    }
    112112
    113     void set(const osgEarth::GeoPoint& p, osg::View *view, osgEarth::MapNode *mapNode)
    114     {
    115         TRACE("%g %g %g", p.x(), p.y(), p.z());
     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());
    116116        if (_label.valid()) {
    117117            _label->setText(osgEarth::Stringify()
    118118                            << "Lat/Long: "
    119                             <<  _formatter->format(p));
    120                             //<< ", " << p.z());
    121         }
    122         _pt = p;
     119                            <<  _formatter->format(mapCoords));
     120                            //<< ", " << mapCoords.z());
     121        }
     122        _pt = mapCoords;
    123123        _havePoint = true;
    124124    }
     
    369369                        osgEarth::GeoPoint &pt, bool invertY = true);
    370370
     371    double computeMapScale();
     372
    371373    bool getMousePoint(double *x, double *y, double *z)
    372374    {
     
    383385
    384386    void finalizeViewer();
     387   
     388    void initControls();
    385389
    386390    void initEarthManipulator();
     
    418422    osg::ref_ptr<osgEarth::Util::MouseCoordsTool> _mouseCoordsTool;
    419423    osg::ref_ptr<MouseCoordsCallback> _coordsCallback;
     424    osg::ref_ptr<osgEarth::Util::Controls::HBox> _hbox;
     425    osg::ref_ptr<osgEarth::Util::Controls::LabelControl> _copyrightLabel;
     426    osg::ref_ptr<osgEarth::Util::Controls::LabelControl> _scaleLabel;
     427    osg::ref_ptr<osgEarth::Util::Controls::Frame> _scaleBar;
    420428    osg::ref_ptr<osgEarth::Util::EarthManipulator> _manipulator;
    421429    osg::ref_ptr<osgGA::StateSetManipulator> _stateManip;
Note: See TracChangeset for help on using the changeset viewer.