Esempio n. 1
0
/**
 * Main application.
 * Creates some simulated track data and runs the simulation.
 */
int
main(int argc, char** argv)
{
    osg::ArgumentParser arguments(&argc,argv);

    // initialize a viewer.
    osgViewer::Viewer viewer( arguments );
    viewer.setCameraManipulator( new EarthManipulator );

    // load a map from an earth file.
    osg::Node* earth = MapNodeHelper().load(arguments, &viewer);
    MapNode* mapNode = MapNode::findMapNode(earth);
    if ( !mapNode )
        return usage("Missing required .earth file" );

    // count on the cmd line?
    arguments.read("--count", g_numTracks);
    
    osg::Group* root = new osg::Group();
    root->addChild( earth );
    viewer.setSceneData( root );

    // build a track field schema.
    TrackNodeFieldSchema schema;
    createFieldSchema( schema );

    // create some track nodes.
    TrackSims trackSims;
    osg::Group* tracks = new osg::Group();
    createTrackNodes( mapNode, tracks, schema, trackSims );
    root->addChild( tracks );

    // Set up the automatic decluttering. setEnabled() activates decluttering for
    // all drawables under that state set. We are also activating priority-based
    // sorting, which looks at the AnnotationData::priority field for each drawable.
    // (By default, objects are sorted by disatnce-to-camera.) Finally, we customize 
    // a couple of the decluttering options to get the animation effects we want.
    g_dcOptions = Decluttering::getOptions();
    g_dcOptions.inAnimationTime()  = 1.0f;
    g_dcOptions.outAnimationTime() = 1.0f;
    g_dcOptions.sortByPriority()   = true;
    Decluttering::setOptions( g_dcOptions );

    // attach the simulator to the viewer.
    viewer.addUpdateOperation( new TrackSimUpdate(trackSims) );
    viewer.setRunFrameScheme( viewer.CONTINUOUS );

    // configure a UI for controlling the demo
    createControls( &viewer );
    
    viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
    viewer.run();
}
void
Decluttering::setOptions( const DeclutteringOptions& options )
{
    // pull our prototype
    osgEarthAnnotationDeclutterRenderBin* bin = dynamic_cast<osgEarthAnnotationDeclutterRenderBin*>(
        osgUtil::RenderBin::getRenderBinPrototype( OSGEARTH_DECLUTTER_BIN ) );

    if ( bin )
    {
        // activate priority-sorting through the options.
        if ( options.sortByPriority().isSetTo( true ) &&
             bin->_context->_options.sortByPriority() == false )
        {
            Decluttering::setSortFunctor(new DeclutterByPriority());
        }
        
        // communicate the new options on the shared context.
        bin->_context->_options = options;
    }
}
    /**
     * Creates a complete set of positioned label nodes from a feature list.
     */
    osg::Node* createNode(
        const FeatureList&   input,
        const Style&         style,
        const FilterContext& context )
    {
        const TextSymbol* text = style.get<TextSymbol>();
        if ( !text )
            return 0L;

        osg::Group* group = new osg::Group();
        Decluttering::setEnabled( group->getOrCreateStateSet(), true );
        if ( text->priority().isSet() )
        {
            DeclutteringOptions dco = Decluttering::getOptions();
            dco.sortByPriority() = text->priority().isSet();
            Decluttering::setOptions( dco );
        }    
        
        StringExpression  contentExpr ( *text->content() );
        NumericExpression priorityExpr( *text->priority() );

        if ( text->removeDuplicateLabels() == true )
        {
            // in remove-duplicates mode, make a list of unique features, selecting
            // the one with the largest area as the one we'll use for labeling.

            typedef std::pair<double, osg::ref_ptr<const Feature> > Entry;
            typedef std::map<std::string, Entry>                    EntryMap;

            EntryMap used;
    
            for( FeatureList::const_iterator i = input.begin(); i != input.end(); ++i )
            {
                Feature* feature = i->get();
                if ( feature && feature->getGeometry() )
                {
                    const std::string& value = feature->eval( contentExpr );
                    if ( !value.empty() )
                    {
                        double area = feature->getGeometry()->getBounds().area2d();
                        if ( used.find(value) == used.end() )
                        {
                            used[value] = Entry(area, feature);
                        }
                        else 
                        {
                            Entry& biggest = used[value];
                            if ( area > biggest.first )
                            {
                                biggest.first = area;
                                biggest.second = feature;
                            }
                        }
                    }
                }
            }

            for( EntryMap::iterator i = used.begin(); i != used.end(); ++i )
            {
                const std::string& value = i->first;
                const Feature* feature = i->second.second.get();
                group->addChild( makeLabelNode(context, feature, value, text, priorityExpr) );
            }
        }

        else
        {
            for( FeatureList::const_iterator i = input.begin(); i != input.end(); ++i )
            {
                const Feature* feature = i->get();
                if ( !feature )
                    continue;

                const Geometry* geom = feature->getGeometry();
                if ( !geom )
                    continue;

                const std::string& value = feature->eval( contentExpr, &context );
                if ( value.empty() )
                    continue;

                group->addChild( makeLabelNode(context, feature, value, text, priorityExpr) );
            }
        }

#if 0 // good idea but needs work.
        DepthOffsetGroup* dog = new DepthOffsetGroup();
        dog->setMinimumOffset( 500.0 );
        dog->addChild( group );
        return dog;
#endif
        return group;
    }
Esempio n. 4
0
/** creates some UI controls for adjusting the decluttering parameters. */
void
createControls( osgViewer::View* view )
{
    ControlCanvas* canvas = ControlCanvas::getOrCreate(view);
    
    // title bar
    VBox* vbox = canvas->addControl(new VBox(Control::ALIGN_NONE, Control::ALIGN_BOTTOM, 2, 1 ));
    vbox->setBackColor( Color(Color::Black, 0.5) );
    vbox->addControl( new LabelControl("osgEarth Tracks Demo", Color::Yellow) );
    
    // checkbox that toggles decluttering of tracks
    struct ToggleDecluttering : public ControlEventHandler {
        void onValueChanged( Control* c, bool on ) {
            Decluttering::setEnabled( on );
        }
    };
    HBox* dcToggle = vbox->addControl( new HBox() );
    dcToggle->addControl( new CheckBoxControl(true, new ToggleDecluttering()) );
    dcToggle->addControl( new LabelControl("Declutter") );

    // checkbox that toggles the coordinate display
    struct ToggleCoords : public ControlEventHandler {
        void onValueChanged( Control* c, bool on ) {
            g_showCoords = on;
        }
    };
    HBox* coordsToggle = vbox->addControl( new HBox() );
    coordsToggle->addControl( new CheckBoxControl(true, new ToggleCoords()) );
    coordsToggle->addControl( new LabelControl("Show locations") );

    // grid for the slider controls so they look nice
    Grid* grid = vbox->addControl( new Grid() );
    grid->setHorizFill( true );
    grid->setChildHorizAlign( Control::ALIGN_LEFT );
    grid->setChildSpacing( 6 );

    unsigned r=0;

    // event handler for changing decluttering options
    struct ChangeFloatOption : public ControlEventHandler {
        optional<float>& _param;
        LabelControl* _label;
        ChangeFloatOption( optional<float>& param, LabelControl* label ) : _param(param), _label(label) { }
        void onValueChanged( Control* c, float value ) {
            _param = value;
            _label->setText( Stringify() << std::fixed << std::setprecision(1) << value );
            Decluttering::setOptions( g_dcOptions );
        }
    };

    grid->setControl( 0, r, new LabelControl("Sim loop duration:") );
    LabelControl* speedLabel = grid->setControl( 2, r, new LabelControl(Stringify() << std::fixed << std::setprecision(1) << *g_duration) );
    HSliderControl* speedSlider = grid->setControl( 1, r, new HSliderControl( 
        600.0, 30.0, *g_duration, new ChangeFloatOption(g_duration, speedLabel) ) );
    speedSlider->setHorizFill( true, 200 );

    grid->setControl( 0, ++r, new LabelControl("Min scale:") );
    LabelControl* minAnimationScaleLabel = grid->setControl( 2, r, new LabelControl(Stringify() << std::fixed << std::setprecision(1) << *g_dcOptions.minAnimationScale()) );
    grid->setControl( 1, r, new HSliderControl( 
        0.0, 1.0, *g_dcOptions.minAnimationScale(), new ChangeFloatOption(g_dcOptions.minAnimationScale(), minAnimationScaleLabel) ) );

    grid->setControl( 0, ++r, new LabelControl("Min alpha:") );
    LabelControl* alphaLabel = grid->setControl( 2, r, new LabelControl(Stringify() << std::fixed << std::setprecision(1) << *g_dcOptions.minAnimationAlpha()) );
    grid->setControl( 1, r, new HSliderControl( 
        0.0, 1.0, *g_dcOptions.minAnimationAlpha(), new ChangeFloatOption(g_dcOptions.minAnimationAlpha(), alphaLabel) ) );

    grid->setControl( 0, ++r, new LabelControl("Activate time (s):") );
    LabelControl* actLabel = grid->setControl( 2, r, new LabelControl(Stringify() << std::fixed << std::setprecision(1) << *g_dcOptions.inAnimationTime()) );
    grid->setControl( 1, r, new HSliderControl( 
        0.0, 2.0, *g_dcOptions.inAnimationTime(), new ChangeFloatOption(g_dcOptions.inAnimationTime(), actLabel) ) );

    grid->setControl( 0, ++r, new LabelControl("Deactivate time (s):") );
    LabelControl* deactLabel = grid->setControl( 2, r, new LabelControl(Stringify() << std::fixed << std::setprecision(1) << *g_dcOptions.outAnimationTime()) );
    grid->setControl( 1, r, new HSliderControl( 
        0.0, 2.0, *g_dcOptions.outAnimationTime(), new ChangeFloatOption(g_dcOptions.outAnimationTime(), deactLabel) ) );
}