osgEarth 2.1.1
|
00001 /* -*-c++-*- */ 00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph 00003 * Copyright 2008-2010 Pelican Mapping 00004 * http://osgearth.org 00005 * 00006 * osgEarth is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> 00018 */ 00019 00020 #include <osg/Notify> 00021 #include <osgGA/GUIEventHandler> 00022 #include <osgViewer/Viewer> 00023 #include <osgGA/StateSetManipulator> 00024 #include <osgViewer/ViewerEventHandlers> 00025 #include <osgEarthUtil/EarthManipulator> 00026 #include <osgEarthUtil/Controls> 00027 #include <osgEarthDrivers/feature_ogr/OGRFeatureOptions> 00028 #include <osgEarthFeatures/FeatureSource> 00029 #include <osgEarth/Utils> 00030 00031 #define LC "[osgearth_labels] " 00032 00033 using namespace osgEarth::Util::Controls; 00034 using namespace osgEarth::Drivers; 00035 using namespace osgEarth::Features; 00036 using namespace osgEarth::Symbology; 00037 00038 osg::Group* createLabels( Map* ); 00039 00040 std::string g_featureFile, g_labelAttr, g_priorityAttr; 00041 bool g_removeDupes = true; 00042 00047 int main(int argc, char** argv) 00048 { 00049 osg::ArgumentParser arguments(&argc,argv); 00050 00051 if ( arguments.read( "--help" ) || argc < 2 ) 00052 { 00053 OE_NOTICE << LC << std::endl << std::endl 00054 00055 << "osgearth_labels <earthfile>" << std::endl 00056 << " --features <filename> : name of shapefile containing feature labels" << std::endl 00057 << " --label-attr <attribute> : attribute containing label text" << std::endl 00058 << " --priority-attr <attribute> : attribute containing priority value" << std::endl 00059 << " --show-duplicates : draws duplicate labels (usually won't)" << std::endl; 00060 00061 return 0; 00062 } 00063 00064 if ( !arguments.read( "--features", g_featureFile ) ) 00065 g_featureFile = "../data/world.shp"; 00066 00067 if ( !arguments.read( "--label-attr", g_labelAttr ) ) 00068 g_labelAttr = "cntry_name"; 00069 00070 if ( !arguments.read( "--priority-attr", g_priorityAttr ) ) 00071 g_priorityAttr = "cntry_pop"; 00072 00073 if ( arguments.read( "--show-duplicates" ) ) 00074 g_removeDupes = false; 00075 00076 osgViewer::Viewer viewer(arguments); 00077 00078 osg::Group* root = new osg::Group(); 00079 osg::Node* node = osgDB::readNodeFiles( arguments ); 00080 if ( node ) 00081 root->addChild( node ); 00082 00083 MapNode* mapNode = MapNode::findMapNode(node); 00084 if ( mapNode ) 00085 { 00086 viewer.setSceneData( root ); 00087 viewer.setCameraManipulator( new osgEarth::Util::EarthManipulator ); 00088 00089 //root->addChild( new ControlCanvas( &viewer ) ); 00090 00091 // load up some labels. 00092 root->addChild( createLabels(mapNode->getMap()) ); 00093 } 00094 00095 // add some stock OSG handlers: 00096 viewer.addEventHandler(new osgViewer::StatsHandler()); 00097 viewer.addEventHandler(new osgViewer::WindowSizeHandler()); 00098 viewer.addEventHandler(new osgViewer::ThreadingHandler()); 00099 viewer.addEventHandler(new osgViewer::LODScaleHandler()); 00100 viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet())); 00101 viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage())); 00102 00103 return viewer.run(); 00104 } 00105 00106 osg::Group* 00107 createLabels( Map* map ) 00108 { 00109 osg::ref_ptr<osg::Group> labels = new osg::Group(); 00110 00111 // first, open up the source shapefile 00112 OGRFeatureOptions fo; 00113 fo.url() = g_featureFile; 00114 00115 osg::ref_ptr<FeatureSource> features = FeatureSourceFactory::create( fo ); 00116 if ( !features.valid() ) 00117 { 00118 OE_WARN << LC << "Unable to load features!" << std::endl; 00119 return 0L; 00120 } 00121 00122 features->initialize( "" ); 00123 const FeatureProfile* featureProfile = features->getFeatureProfile(); 00124 if ( !featureProfile || !featureProfile->getSRS() ) 00125 { 00126 OE_WARN << LC << "Feature data has no spatial reference!" << std::endl; 00127 return 0L; 00128 } 00129 00130 osg::ref_ptr<FeatureCursor> cursor = features->createFeatureCursor(); 00131 if ( !cursor.valid() ) 00132 { 00133 OE_WARN << LC << "Failed to query the feature source!" << std::endl; 00134 return 0L; 00135 } 00136 00137 //SceneControlBin* priorityBin = canvas->getSceneControls(); 00138 00139 unsigned count = 0; 00140 00141 std::set<std::string> antiDupeSet; 00142 00143 while( cursor->hasMore() ) 00144 { 00145 Feature* feature = cursor->nextFeature(); 00146 Geometry* geom = feature->getGeometry(); 00147 00148 if ( !geom ) 00149 continue; 00150 00151 // we will display the country name: 00152 std::string text = feature->getString( g_labelAttr ); 00153 if ( text.empty() ) 00154 continue; 00155 00156 // and use the population to prioritize labels: 00157 float population = feature->getDouble(g_priorityAttr, 0.0); 00158 00159 // remove duplicate labels: 00160 if ( g_removeDupes ) 00161 { 00162 if ( antiDupeSet.find(text) != antiDupeSet.end() ) 00163 continue; 00164 antiDupeSet.insert(text); 00165 } 00166 00167 // calculate the world location of the label: 00168 osg::Vec3d centerPoint = geom->getBounds().center(); 00169 00170 osg::Vec3d mapPoint; 00171 if ( !map->toMapPoint( centerPoint, featureProfile->getSRS(), mapPoint ) ) 00172 continue; 00173 00174 osg::Vec3d worldPoint; 00175 if ( !map->mapPointToWorldPoint( mapPoint, worldPoint ) ) 00176 continue; 00177 00178 // create the label and place it: 00179 osg::MatrixTransform* xform = new osg::MatrixTransform( osg::Matrix::translate(worldPoint) ); 00180 xform->setCullCallback( new CullNodeByNormal(worldPoint) ); 00181 xform->addChild( new ControlNode(new LabelControl(text)) ); 00182 labels->addChild( xform ); 00183 00184 ++count; 00185 00186 //OE_NOTICE << LC << "Added: " << text << std::endl; 00187 } 00188 00189 OE_NOTICE << LC << "Found " << count << " features. " << std::endl; 00190 00191 return labels.release(); 00192 } 00193