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 #include <osgEarthFeatures/LabelSource> 00020 #include <osgEarthSymbology/Expression> 00021 #include <osgEarthUtil/Controls> 00022 #include <osgEarth/Utils> 00023 #include <osgEarth/ECEF> 00024 #include <osg/ClusterCullingCallback> 00025 #include <osg/MatrixTransform> 00026 #include <osgDB/FileNameUtils> 00027 #include <set> 00028 00029 using namespace osgEarth; 00030 using namespace osgEarth::Features; 00031 using namespace osgEarth::Symbology; 00032 using namespace osgEarth::Util; 00033 00034 class OverlayLabelSource : public LabelSource 00035 { 00036 public: 00037 OverlayLabelSource( const LabelSourceOptions& options ) : 00038 LabelSource( options ) 00039 { 00040 //nop 00041 } 00042 00043 osg::Node* createNode( 00044 const FeatureList& input, 00045 const TextSymbol* text, 00046 const FilterContext& context ) 00047 { 00048 osg::Group* group = 0L; 00049 std::set<std::string> used; // to prevent dupes 00050 bool skipDupes = (text->removeDuplicateLabels() == true); 00051 00052 StringExpression contentExpr ( *text->content() ); 00053 NumericExpression priorityExpr( *text->priority() ); 00054 00055 const MapInfo& mi = context.getSession()->getMapInfo(); 00056 bool makeECEF = mi.isGeocentric(); 00057 00058 for( FeatureList::const_iterator i = input.begin(); i != input.end(); ++i ) 00059 { 00060 const Feature* feature = i->get(); 00061 if ( !feature ) 00062 continue; 00063 00064 const Geometry* geom = feature->getGeometry(); 00065 if ( !geom ) 00066 continue; 00067 00068 osg::Vec3d centroid = geom->getBounds().center(); 00069 //osg::Vec3d centroidWorld = context.toWorld(centroid); 00070 00071 if ( makeECEF ) 00072 { 00073 context.profile()->getSRS()->transformToECEF( centroid, centroid ); 00074 } 00075 00076 #if 0 00077 if ( context.isGeocentric() && geom->getComponentType() != Geometry::TYPE_POINTSET ) 00078 { 00079 // "clamp" the centroid to the ellipsoid 00080 osg::Vec3d centroidMap; 00081 mi.worldPointToMapPoint(centroidWorld, centroidMap); 00082 centroidMap.z() = 0.0; 00083 mi.mapPointToWorldPoint(centroidMap, centroidWorld); 00084 centroid = context.toLocal(centroidWorld); 00085 } 00086 #endif 00087 00088 const std::string& value = feature->eval( contentExpr ); 00089 00090 if ( !value.empty() && (!skipDupes || used.find(value) == used.end()) ) 00091 { 00092 if ( !group ) 00093 { 00094 group = new osg::Group(); 00095 } 00096 00097 double priority = feature->eval( priorityExpr ); 00098 00099 Controls::LabelControl* label = new Controls::LabelControl( value ); 00100 if ( text->fill().isSet() ) 00101 label->setForeColor( text->fill()->color() ); 00102 if ( text->halo().isSet() ) 00103 label->setHaloColor( text->halo()->color() ); 00104 if ( text->size().isSet() ) 00105 label->setFontSize( *text->size() ); 00106 if ( text->font().isSet() ) 00107 label->setFont( osgText::readFontFile(*text->font()) ); 00108 00109 Controls::ControlNode* node = new Controls::ControlNode( label, priority ); 00110 00111 osg::MatrixTransform* xform = new osg::MatrixTransform( osg::Matrixd::translate(centroid) ); 00112 xform->addChild( node ); 00113 00114 // for a geocentric map, do a simple dot product cull. 00115 if ( makeECEF ) 00116 { 00117 xform->setCullCallback( new CullNodeByHorizon(centroid, mi.getProfile()->getSRS()->getEllipsoid()) ); 00118 group->addChild( xform ); 00119 } 00120 else 00121 { 00122 group->addChild( xform ); 00123 } 00124 00125 if ( skipDupes ) 00126 used.insert( value ); 00127 } 00128 } 00129 00130 return group; 00131 } 00132 }; 00133 00134 //------------------------------------------------------------------------ 00135 00136 class OverlayLabelSourceDriver : public LabelSourceDriver 00137 { 00138 public: 00139 OverlayLabelSourceDriver() 00140 { 00141 supportsExtension( "osgearth_label_overlay", "osgEarth overlay label plugin" ); 00142 } 00143 00144 virtual const char* className() 00145 { 00146 return "osgEarth Overlay Label Plugin"; 00147 } 00148 00149 virtual ReadResult readObject(const std::string& file_name, const Options* options) const 00150 { 00151 if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name ))) 00152 return ReadResult::FILE_NOT_HANDLED; 00153 00154 return new OverlayLabelSource( getLabelSourceOptions(options) ); 00155 } 00156 }; 00157 00158 REGISTER_OSGPLUGIN(osgearth_label_overlay, OverlayLabelSourceDriver)