예제 #1
0
    osg::Node* makePlaceNode(FilterContext&     context,
                             Feature*           feature, 
                             const Style&       style, 
                             NumericExpression& priorityExpr )
    {
        osg::Vec3d center = feature->getGeometry()->getBounds().center();

        AltitudeMode mode = ALTMODE_ABSOLUTE;        

        const AltitudeSymbol* alt = style.getSymbol<AltitudeSymbol>();
        if (alt &&
           (alt->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN || alt->clamping() == AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN) &&
           alt->technique() == AltitudeSymbol::TECHNIQUE_SCENE)
        {
            mode = ALTMODE_RELATIVE;
        }                              

        GeoPoint point(feature->getSRS(), center.x(), center.y(), center.z(), mode);        

        PlaceNode* node = new PlaceNode(0L, point, style, context.getDBOptions());

        if ( !priorityExpr.empty() )
        {
            AnnotationData* data = new AnnotationData();
            data->setPriority( feature->eval(priorityExpr, &context) );
            node->setAnnotationData( data );
        }

        return node;
    }
예제 #2
0
 virtual void onClick( AnnotationNode* node, const EventArgs& details )
 {        
     PlaceNode* place = dynamic_cast<PlaceNode*>(node);
     if (place == NULL)
     {
         OE_NOTICE << "Thanks for clicking this annotation" << std::endl;
     }
     else
     {
         OE_NOTICE << "Thanks for clicking the PlaceNode: " << place->getText() << std::endl;
     }
 }
    osg::Node* makePlaceNode(const FilterContext& context,
                             const Feature*       feature, 
                             const Style&         style, 
                             NumericExpression&   priorityExpr )
    {
        osg::Vec3d center = feature->getGeometry()->getBounds().center();
        GeoPoint point(feature->getSRS(), center.x(), center.y());

        PlaceNode* placeNode = new PlaceNode(0L, point, style, context.getDBOptions());

        if ( !priorityExpr.empty() )
        {
            AnnotationData* data = new AnnotationData();
            data->setPriority( feature->eval(priorityExpr, &context) );
            placeNode->setAnnotationData( data );
        }

        return placeNode;
    }
예제 #4
0
PlaceNode* ClusterNode::getOrCreateLabel()
{
    PlaceNode* node = 0;
    if (_labelPool.size() <= _nextLabel)
    {
        // set up a style to use for placemarks:
        Style placeStyle;
        placeStyle.getOrCreate<TextSymbol>()->declutter() = false;
        node = new PlaceNode("", placeStyle, _defaultImage.get());
        node->setMapNode(_mapNode.get());
        node->setDynamic(true);
        _labelPool.push_back(node);
    }
    else
    {
        node = _labelPool[_nextLabel].get();
    }

    ++_nextLabel;

    return node;


}
예제 #5
0
int
main(int argc, char** argv)
{
    osg::ArgumentParser arguments(&argc,argv);
    if ( arguments.read("--stencil") )
        osg::DisplaySettings::instance()->setMinimumNumStencilBits( 8 );

    //Setup a CompositeViewer
    osgViewer::CompositeViewer viewer(arguments);

    //Setup our main view that will show the loaded earth file.
    osgViewer::View* mainView = new osgViewer::View();
    mainView->getCamera()->setNearFarRatio(0.00002);
    mainView->setCameraManipulator( new EarthManipulator() );      
    mainView->setUpViewInWindow( 50, 50, 800, 800 );
    viewer.addView( mainView );
    
    //Setup a MiniMap View that will be embedded in the main view
    int miniMapWidth = 400;
    int miniMapHeight = 200;
    osgViewer::View* miniMapView = new osgViewer::View();
    miniMapView->getCamera()->setNearFarRatio(0.00002);
    miniMapView->getCamera()->setViewport( 0, 0, miniMapWidth, miniMapHeight);    
    miniMapView->setCameraManipulator( new EarthManipulator() );    
    miniMapView->getCamera()->setClearColor( osg::Vec4(0,0,0,0));
    miniMapView->getCamera()->setProjectionResizePolicy( osg::Camera::FIXED );
    miniMapView->getCamera()->setProjectionMatrixAsPerspective(30.0, double(miniMapWidth) / double(miniMapHeight), 1.0, 1000.0);
    //Share a graphics context with the main view
    miniMapView->getCamera()->setGraphicsContext( mainView->getCamera()->getGraphicsContext());        
    viewer.addView( miniMapView );
    
    // load an earth file, and support all or our example command-line options
    // and earth file <external> tags    
    osg::Node* node = MapNodeHelper().load( arguments, mainView );
    if ( node )
    {
        MapNode* mapNode = MapNode::findMapNode(node);
    
        //Set the main view's scene data to the loaded earth file
        mainView->setSceneData( node );

        //Setup a group to hold the contents of the MiniMap
        osg::Group* miniMapGroup = new osg::Group;

        MapNode* miniMapNode = makeMiniMapNode();        
        miniMapGroup->addChild( miniMapNode );
       
        //Get the main MapNode so we can do tranformations between it and our minimap
        MapNode* mainMapNode = MapNode::findMapNode( node );
                               
        //Set the scene data for the minimap
        miniMapView->setSceneData( miniMapGroup );        

        //Add a marker we can move around with the main view's eye point
        Style markerStyle;
        markerStyle.getOrCreate<IconSymbol>()->url()->setLiteral( "../data/placemark32.png" );
        PlaceNode* eyeMarker = new PlaceNode(miniMapNode, GeoPoint(miniMapNode->getMapSRS(), 0, 0), "", markerStyle);
        miniMapGroup->addChild( eyeMarker );        
        miniMapGroup->getOrCreateStateSet()->setRenderBinDetails(100, "RenderBin");

        osg::Node* bounds = 0;
  
        while (!viewer.done())
        {
            //Reset the viewport so that the camera's viewport is static and doesn't resize with window resizes
            miniMapView->getCamera()->setViewport( 0, 0, miniMapWidth, miniMapHeight);    

            //Get the eye point of the main view
            osg::Vec3d eye, up, center;
            mainView->getCamera()->getViewMatrixAsLookAt( eye, center, up );

            //Turn the eye into a geopoint and transform it to the minimap's SRS
            GeoPoint eyeGeo;
            eyeGeo.fromWorld( mainMapNode->getMapSRS(), eye );
            eyeGeo.transform( miniMapNode->getMapSRS());

            //We want the marker to be positioned at elevation 0, so zero out any elevation in the eye point
            eyeGeo.z() = 0;           
 
            //Set the position of the marker
            eyeMarker->setPosition( eyeGeo );

            if (bounds)
            {
                miniMapGroup->removeChild( bounds );
            }
            GeoExtent extent = getExtent( mainView );
            bounds = drawBounds( miniMapNode, extent );
            miniMapGroup->addChild( bounds );

            viewer.frame();
        }        
    }
    else
    {
        OE_NOTICE 
            << "\nUsage: " << argv[0] << " file.earth" << std::endl
            << MapNodeHelper().usage() << std::endl;
    }
    return 0;
}
예제 #6
0
int
main(int argc, char** argv)
{
    osg::Group* root = new osg::Group();

    // try to load an earth file.
    osg::ArgumentParser arguments(&argc,argv);

    osgViewer::Viewer viewer(arguments);

    unsigned int numObjects = 200;
    while (arguments.read("--count", numObjects)) {}

    bool declutter = false;
    if (arguments.read("--declutter")) declutter = true;
    
    // initialize the viewer:    
    viewer.setCameraManipulator( new EarthManipulator() );


    // load an earth file and parse demo arguments
    osg::Node* node = MapNodeHelper().load(arguments, &viewer);
    if ( !node )
        return usage(argv);

    // find the map node that we loaded.
    MapNode* mapNode = MapNode::findMapNode(node);
    if ( !mapNode )
        return usage(argv);

    root->addChild( node );
   
    // Make a group for 2D items, and activate the decluttering engine. Decluttering
    // will migitate overlap between elements that occupy the same screen real estate.
    osg::Group* labelGroup = new osg::Group();
    if (declutter)
    {
        Decluttering::setEnabled( labelGroup->getOrCreateStateSet(), true );
    }
    root->addChild( labelGroup );
    
    // set up a style to use for placemarks:
    Style placeStyle;
    placeStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN;

    // A lat/long SRS for specifying points.
    const SpatialReference* geoSRS = mapNode->getMapSRS()->getGeographicSRS();

    //--------------------------------------------------------------------

    //Create a bunch of placemarks around Mt Rainer so we can actually get some elevation
    {
        osg::Image* pin = osgDB::readImageFile( "../data/placemark32.png" );

        double centerLat =  46.840866;
        double centerLon = -121.769846;
        double height = 0.2;
        double width = 0.2;
        double minLat = centerLat - (height/2.0);
        double minLon = centerLon - (width/2.0);

        OE_NOTICE << "Placing " << numObjects << " placemarks" << std::endl;

        for (unsigned int i = 0; i < numObjects; i++)
        {
            double lat = minLat + height * (rand() * 1.0)/(RAND_MAX-1);
            double lon = minLon + width * (rand() * 1.0)/(RAND_MAX-1);        
            PlaceNode* place = new PlaceNode(mapNode, GeoPoint(geoSRS, lon, lat), pin, "Placemark", placeStyle);
            //Enable occlusion culling.  This will hide placemarks that are hidden behind terrain.
            //This makes use of the OcclusionCullingCallback in CullingUtils.
            place->setOcclusionCulling( true );
            labelGroup->addChild( place );
        }    
    }

    viewer.setSceneData( root );

    viewer.getCamera()->addCullCallback( new AutoClipPlaneCullCallback(mapNode) );
    viewer.addEventHandler(new osgViewer::StatsHandler());
    viewer.addEventHandler(new osgViewer::WindowSizeHandler());
    viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));

    return viewer.run();
}
예제 #7
0
void 
KML_Placemark::build( xml_node<>* node, KMLContext& cx )
{
	Style masterStyle;

	std::string styleUrl = getValue(node, "styleurl");

	if (!styleUrl.empty())
	{	// process a "stylesheet" style
		const Style* ref_style = cx._sheet->getStyle( styleUrl, false );
		if (ref_style)
		{
			masterStyle = masterStyle.combineWith(*ref_style);
		}
	}

	xml_node<>* style = node->first_node("style", 0, false);
	if ( style )
	{	// process an "inline" style
		KML_Style kmlStyle;
		kmlStyle.scan(style, cx);
		masterStyle = masterStyle.combineWith(cx._activeStyle);
	}

    // parse the geometry. the placemark must have geometry to be valid. The 
    // geometry parse may optionally specify an altitude mode as well.
    KML_Geometry geometry;
    geometry.build(node, cx, masterStyle);

    Geometry* allGeom = geometry._geom.get();
    if ( allGeom )
    {
        GeometryIterator giter( allGeom, false );
        while( giter.hasMore() )
        {
            Geometry* geom = giter.next();
            Style style = masterStyle;

            AltitudeSymbol* alt = style.get<AltitudeSymbol>();
            
            if ( geom && geom->getTotalPointCount() > 0 )
            {
                // resolve the proper altitude mode for the anchor point
                AltitudeMode altMode = ALTMODE_RELATIVE;
                if (alt && 
                    !alt->clamping().isSetTo( alt->CLAMP_TO_TERRAIN ) &&
                    !alt->clamping().isSetTo( alt->CLAMP_RELATIVE_TO_TERRAIN ) )
                {
                    altMode = ALTMODE_ABSOLUTE;
                }

                GeoPoint position(cx._srs.get(), geom->getBounds().center(), altMode);

                // check for symbols.
                ModelSymbol* model = style.get<ModelSymbol>();
                IconSymbol*  icon  = style.get<IconSymbol>();
                TextSymbol*  text  = style.get<TextSymbol>();

                // for a single point placemark, apply the default icon and text symbols
                // if none are specified in the KML.
                if (geom->getTotalPointCount() == 1)
                {
                    if (!model && !icon && cx._options->defaultIconSymbol().valid())
                    {
                        icon = cx._options->defaultIconSymbol().get();
                        style.add(icon);
                    }

                    if (!text && cx._options->defaultTextSymbol().valid())
                    {
                        text = cx._options->defaultTextSymbol().get();
                        style.add(text);
                    }
                }

                // the annotation name:
                std::string name = getValue(node, "name");

                if (!name.empty())
                {
                    OE_INFO << LC << "Placemark: " << name << std::endl;
                }

                AnnotationNode* featureNode = 0L;
                AnnotationNode* iconNode    = 0L;
                AnnotationNode* modelNode   = 0L;

                // one coordinate? It's a place marker or a label.
                if ( (model || icon || text) && geom->getTotalPointCount() == 1 )
                {
                    // if there's a model, render that - models do NOT get labels.
                    if ( model )
                    {
                        ModelNode* node = new ModelNode( cx._mapNode, style, cx._dbOptions.get() );
                        node->setPosition( position );

                        // model scale:
                        if ( cx._options->modelScale() != 1.0f )
                        {
                            float s = *cx._options->modelScale();
                            node->getPositionAttitudeTransform()->setScale(osg::Vec3d(s,s,s));
                        }

                        // model local tangent plane rotation:
                        if ( !cx._options->modelRotation()->zeroRotation() )
                        {
                            node->getPositionAttitudeTransform()->setAttitude( *cx._options->modelRotation() );
                        }

                        modelNode = node;
                    }

                    // is there a label?
                    else if ( !name.empty() )
                    {
                        if ( !text )
                        {
                            text = style.getOrCreate<TextSymbol>();
                            text->encoding() = TextSymbol::ENCODING_UTF8;
                        }
                        text->content()->setLiteral( name );
                    }

                    // is there an icon?
                    if ( icon )
                    {
                        PlaceNode* placeNode = new PlaceNode( position );
                        placeNode->setStyle(style, cx._dbOptions.get());
                        iconNode = placeNode;
                    }

                    else if ( !model && text && !name.empty() )
                    {
                        // note: models do not get labels.
                        iconNode = new LabelNode();
                        iconNode->setStyle(style);
                    }
                }

                // multiple coords? feature:
                if ( geom->getTotalPointCount() > 1 )
                {
                    // Remove symbols that we have already processed so the geometry
                    // compiler doesn't get confused.
                    if ( model )
                        style.removeSymbol( model );
                    if ( icon )
                        style.removeSymbol( icon );
                    if ( text )
                        style.removeSymbol( text );

                    Feature* feature = new Feature(geom, cx._srs.get(), style);
                    featureNode = new FeatureNode(feature );
                    featureNode->setMapNode( cx._mapNode );
                }

                if ( iconNode )
                {
                    Registry::objectIndex()->tagNode( iconNode, iconNode );
                }

                if ( modelNode )
                {
                    Registry::objectIndex()->tagNode( modelNode, modelNode );
                }

                if ( featureNode )
                {
                    Registry::objectIndex()->tagNode( featureNode, featureNode );
                }


                // assemble the results:
                if ( (iconNode || modelNode) && featureNode )
                {
                    osg::Group* group = new osg::Group();
                    group->addChild( featureNode );
                    if ( iconNode )
                        group->addChild( iconNode );
                    if ( modelNode )
                        group->addChild( modelNode );

                    cx._groupStack.top()->addChild( group );

                    if ( iconNode )
                        KML_Feature::build( node, cx, iconNode );
                    if ( modelNode )
                        KML_Feature::build( node, cx, modelNode );
                    if ( featureNode )
                        KML_Feature::build( node, cx, featureNode );
                }

                else
                {
                    if ( iconNode )
                    {
                        if ( cx._options->iconAndLabelGroup().valid() )
                        {
                            cx._options->iconAndLabelGroup()->addChild( iconNode );
                        }
                        else
                        {
                            cx._groupStack.top()->addChild( iconNode );
                        }
                        KML_Feature::build( node, cx, iconNode );
                    }
                    if ( modelNode )
                    {
                        cx._groupStack.top()->addChild( modelNode );
                        KML_Feature::build( node, cx, modelNode );
                    }
                    if ( featureNode )
                    {
                        osg::Node* child = featureNode;

                        // If this feature node is map-clamped, we most likely need a depth-offset
                        // shader to prevent z-fighting with the terrain.
                        if (alt && alt->clamping() == alt->CLAMP_TO_TERRAIN && alt->technique() == alt->TECHNIQUE_MAP)
                        {
                            DepthOffsetGroup* g = new DepthOffsetGroup();
                            g->addChild( featureNode );
                            child = g;
                        }
                
                        cx._groupStack.top()->addChild( child );
                        KML_Feature::build( node, cx, featureNode );
                    }
                }
            }
        }
    }
}
예제 #8
0
void ClusterNode::getClusters(osgUtil::CullVisitor* cv, ClusterList& out)
{
    _nextLabel = 0;

    osg::Camera* camera = cv->getCurrentCamera();

    osg::Viewport* viewport = camera->getViewport();
    if (!viewport)
    {
        return;
    }

    osg::Matrixd mvpw = camera->getViewMatrix() *
        camera->getProjectionMatrix() *
        camera->getViewport()->computeWindowMatrix();

    std::vector<TPoint> points;

    osg::NodeList validPlaces;

    buildIndex();

    for (osg::NodeList::iterator itr = _clusterIndex.begin(); itr != _clusterIndex.end(); ++itr)
    {
        osg::Group* index = static_cast<osg::Group*>(itr->get());
        if (cv->isCulled(index->getBound()))
        {
            continue;
        }

        for (unsigned int i = 0; i < index->getNumChildren(); i++)
        {
            osg::Node* node = index->getChild(i);
            osg::Vec3d world = node->getBound().center();

            if (cv->isCulled(*node))
            {
                continue;
            }

            if (!_horizon->isVisible(world))
            {
                continue;
            }

            osg::Vec3d screen = world * mvpw;

            if (screen.x() >= 0 && screen.x() <= viewport->width() &&
                screen.y() >= 0 && screen.y() <= viewport->height())
            {
                validPlaces.push_back(node);
                points.push_back(TPoint(screen.x(), screen.y()));
            }
        }
    }

    if (validPlaces.size() == 0) return;

    kdbush::KDBush<TPoint> index(points);
    std::set< unsigned int > clustered;

    for (unsigned int i = 0; i < validPlaces.size(); i++)
    {
        TPoint &screen = points[i];
        osg::Node* node = validPlaces[i].get();

        // If this thing is already part of a cluster then just continue.
        if (clustered.find(i) != clustered.end())
        {
            continue;
        }

        osg::Vec3d world = node->getBound().center();

        // Get any matching indices that are part of this cluster.
        TIds indices;

        index.range(screen.first - _radius, screen.second - _radius, screen.first + _radius, screen.second + _radius, indices);

        // Create a new cluster.
        Cluster cluster;

        unsigned int actualCount = 0;

        // Add all of the points to the cluster.
        for (unsigned int j = 0; j < indices.size(); j++)
        {
            if (clustered.find(indices[j]) == clustered.end())
            {
                if (_canClusterCallback.valid())
                {
                    bool canCluster = (*_canClusterCallback)(node, validPlaces[indices[j]].get());
                    if (!canCluster) {
                        continue;
                    }
                }
                cluster.nodes.push_back(validPlaces[indices[j]]);
                actualCount++;
                clustered.insert(indices[j]);
            }
        }

        std::stringstream buf;
        buf << actualCount << std::endl;

        PlaceNode* marker = getOrCreateLabel();
        GeoPoint markerPos;
        markerPos.fromWorld(_mapNode->getMapSRS(), world);
        marker->setPosition(markerPos);
        marker->setText(buf.str());

        cluster.marker = marker;
        out.push_back(cluster);

        clustered.insert(i);
    }
}