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); } }
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; }
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(); 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::ref_ptr<osg::Image> pin = osgDB::readRefImageFile( "../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("Placemark", placeStyle, pin.get()); place->setMapNode(mapNode); place->setPosition(GeoPoint(geoSRS, lon, lat)); //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(); }