不改源码的方式实现osgearth当中placenode的中文支持

来源:互联网 发布:做淘宝主播赚钱吗 编辑:程序博客网 时间:2024/06/13 02:38

摘要:
使用osgearth的人越来越多,开源的工程大家都喜欢。

osgearth的底层引擎是OSG,OSG中文支持良好,但osgearth里面直接舍弃了wstring,中文没法显示,让很多程序员很蛋疼。

很多情况下载osgearth当中使用中文可能仅仅是为了添加个地标。这里就针对地标做中文支持,修改源码又不是一个好的方式,这里就使用的继承的方法来实现。有兴趣的朋友拿走。

参考:http://blog.sina.com.cn/s/blog_7cdaf8b60102v21q.html

这里表示感谢!!

我封装了两个类来实现,其实一个类也可以,这里为了使继承关系保持清晰,使用了两个
下面直接粘贴代码:

类1:AnnotationUtilsEXP
头文件:AnnotationUtilsEXP.h

#ifndef ANNOTATION_UTILS_EXP_H_#define ANNOTATION_UTILS_EXP_H_#include <osgEarthAnnotation/AnnotationUtils>using namespace osgEarth;using namespace osgEarth::Symbology;using namespace osgEarth::Annotation;struct AnnotationUtilsEXP : AnnotationUtils{public:    /**         * Creates a std::wstring drawable representing a symbolized text label in         * pixel space.         */    static osg::Drawable* createTextDrawable(        const std::wstring& text,        const TextSymbol*  symbol,        const osg::Vec3&   positionOffset );};#endif

cpp文件:AnnotationUtilsEXP.cpp

#include "AnnotationUtilsEXP.h"#include <osgEarthSymbology/Color>#include <osgEarthSymbology/MeshSubdivider>#include <osgEarth/ThreadingUtils>#include <osgEarth/Registry>#include <osgEarth/VirtualProgram>#include <osgEarth/Capabilities>#include <osgText/Text>#include <osg/Depth>#include <osg/BlendFunc>#include <osg/CullFace>#include <osg/MatrixTransform>#include <osg/LightModel>using namespace osgEarth;using namespace osgEarth::Annotation;osg::Drawable* AnnotationUtilsEXP::createTextDrawable( const std::wstring& text, const TextSymbol* symbol, const osg::Vec3& positionOffset ){    osgText::Text* t = new osgText::Text();    osgText::String::Encoding text_encoding = osgText::String::ENCODING_UNDEFINED;    if ( symbol && symbol->encoding().isSet() )    {        text_encoding = AnnotationUtils::convertTextSymbolEncoding(symbol->encoding().value());    }    t->setText( text.c_str());    // osgText::Text turns on depth writing by default, even if you turned it off..    t->setEnableDepthWrites( false );    if ( symbol && symbol->layout().isSet() )    {        if(symbol->layout().value() == TextSymbol::LAYOUT_RIGHT_TO_LEFT)        {            t->setLayout(osgText::TextBase::RIGHT_TO_LEFT);        }        else if(symbol->layout().value() == TextSymbol::LAYOUT_LEFT_TO_RIGHT)        {            t->setLayout(osgText::TextBase::LEFT_TO_RIGHT);        }        else if(symbol->layout().value() == TextSymbol::LAYOUT_VERTICAL)        {            t->setLayout(osgText::TextBase::VERTICAL);        }    }    if ( symbol && symbol->pixelOffset().isSet() )    {        t->setPosition( osg::Vec3(            positionOffset.x() + symbol->pixelOffset()->x(),            positionOffset.y() + symbol->pixelOffset()->y(),            positionOffset.z() ) );    }    else    {        t->setPosition( positionOffset );    }    t->setAutoRotateToScreen( false );    t->setCharacterSizeMode( osgText::Text::OBJECT_COORDS );    t->setCharacterSize( symbol && symbol->size().isSet() ? (float)(symbol->size()->eval()) : 16.0f );    t->setColor( symbol && symbol->fill().isSet() ? symbol->fill()->color() : Color::White );    osgText::Font* font = 0L;    if ( symbol && symbol->font().isSet() )        font = osgText::readFontFile( *symbol->font() );    if ( !font )        font = Registry::instance()->getDefaultFont();    if ( font )        t->setFont( font );    if ( symbol )    {        // they're the same enum.        osgText::Text::AlignmentType at = (osgText::Text::AlignmentType)symbol->alignment().value();        t->setAlignment( at );    }    if ( symbol && symbol->halo().isSet() )    {        t->setBackdropColor( symbol->halo()->color() );        t->setBackdropType( osgText::Text::OUTLINE );        if ( symbol->haloOffset().isSet() )        {            t->setBackdropOffset( *symbol->haloOffset(), *symbol->haloOffset() );        }    }    else if ( !symbol )    {        // if no symbol at all is provided, default to using a black halo.        t->setBackdropColor( osg::Vec4(.3,.3,.3,1) );        t->setBackdropType( osgText::Text::OUTLINE );    }    // this disables the default rendering bin set by osgText::Font. Necessary if we're    // going to do decluttering.    // TODO: verify that it's still OK to share the font stateset (think so) or does it    // need to be marked DYNAMIC    if ( t->getStateSet() )        t->getStateSet()->setRenderBinToInherit();    return t;}

类2:PlaceNodeEXP
头文件:PlaceNodeEXP.h

#ifndef PLACENODE_EXP_H_#define PLACENODE_EXP_H_#include <osgEarthAnnotation/OrthoNode>#include <osgEarthSymbology/Style>using namespace osgEarth;using namespace osgEarth::Symbology;using namespace osgEarth::Annotation;class PlaceNodeEXP : public OrthoNode{public:    /**         * Constructs a std::wstring new place node         *         * @param mapNode   MapNode that helps position this annotation         * @param position  Initial location of the annotation         * @param iconImage Image of the place icon         * @param labelText Text to place next to the icon         * @param style     Optional style settings.         */    PlaceNodeEXP(        MapNode*           mapNode,        const GeoPoint&    position,        osg::Image*        iconImage,        const std::wstring& labelText,        const Style&       style =Style() );     /**         * Constructs a new place node. You can specify an icon marker by         * adding a IconSymbol to the Style.         *         * @param mapNode   MapNode that helps position this annotation         * @param position  Initial location of the annotation         * @param labelText Text to place next to the icon         * @param style     Optional style settings.         */    PlaceNodeEXP(        MapNode*           mapNode,        const GeoPoint&    position,        const std::wstring& labelText,        const Style&       style =Style() );    /**         * Image to use for the icon         */        void setIconImage(osg::Image* image);        osg::Image* getIconImage() const { return _image.get(); }        /**         * Text label content         */        void setText( const std::wstring& text );        const std::wstring& getText() const { return _text; }        /**         * Style (for text and placement)         */        void setStyle( const Style& style );        const Style& getStyle() const { return _style; }    public: // OrthoNode override        virtual void setAnnotationData( AnnotationData* data );        virtual void setDynamic( bool value );        virtual Config getConfig() const;        std::wstring  StringToWString(const std::string& s);    protected:        virtual ~PlaceNodeEXP() { }    private:        osg::ref_ptr<osg::Image>           _image;        std::wstring                        _text;        Style                              _style;        class osg::Geode*                  _geode;        osg::ref_ptr<const osgDB::Options> _dbOptions;        void init();        // required by META_Node, but this object is not cloneable        PlaceNodeEXP() { }        PlaceNodeEXP(const PlaceNodeEXP& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL) : OrthoNode(rhs, op) { }};#endif

cpp文件:PlaceNodeEXP.cpp

#include "PlaceNodeEXP.h"#include "AnnotationUtilsEXP.h"#include <osgEarthAnnotation/AnnotationRegistry>#include <osgEarthFeatures/BuildTextFilter>#include <osgEarthFeatures/LabelSource>#include <osgEarth/Utils>#include <osgEarth/Registry>#include <osgEarth/ShaderGenerator>#include <osg/Depth>#include <osgText/Text>using namespace osgEarth;using namespace osgEarth::Annotation;using namespace osgEarth::Features;using namespace osgEarth::Symbology;PlaceNodeEXP::PlaceNodeEXP(MapNode*           mapNode,    const GeoPoint&    position,    osg::Image*        image,    const std::wstring& text,    const Style&       style ) :OrthoNode( mapNode, position ),    _image   ( image ),    _text    ( text ),    _style   ( style ),    _geode   ( 0L ){    init();}PlaceNodeEXP::PlaceNodeEXP(MapNode*           mapNode,    const GeoPoint&    position,    const std::wstring& text,    const Style&       style ):OrthoNode( mapNode, position ),    _text    ( text ),    _style   ( style ),    _geode   ( 0L ){    init();}void PlaceNodeEXP::setIconImage( osg::Image* image ){    // changing the icon requires a complete rebuild.    _image = image;    init();}void PlaceNodeEXP::setText( const std::wstring& text ){    if ( !_dynamic )    {        //OE_WARN << LC << "Illegal state: cannot change a LabelNode that is not dynamic" << std::endl;        return;    }    _text = text;    for(unsigned i=0; i<_geode->getNumDrawables(); ++i)    {        osgText::Text* d = dynamic_cast<osgText::Text*>( _geode->getDrawable(i) );        if ( d )        {            TextSymbol* symbol =  _style.getOrCreate<TextSymbol>();            osgText::String::Encoding text_encoding = osgText::String::ENCODING_UNDEFINED;            if ( symbol && symbol->encoding().isSet() )            {                text_encoding = AnnotationUtils::convertTextSymbolEncoding(symbol->encoding().value());            }            d->setText( text.c_str() );            break;        }    }}void PlaceNodeEXP::setStyle( const Style& style ){    // changing the style requires a complete rebuild.    _style = style;    init();}void PlaceNodeEXP::init(){    //reset.    this->clearDecoration();    getAttachPoint()->removeChildren(0, getAttachPoint()->getNumChildren());    _geode = new osg::Geode();    osg::Drawable* text = 0L;    // If there's no explicit text, look to the text symbol for content.    if ( _text.empty() && _style.has<TextSymbol>() )    {        _text = StringToWString(_style.get<TextSymbol>()->content()->eval());    }    osg::ref_ptr<const InstanceSymbol> instance = _style.get<InstanceSymbol>();    // backwards compability, support for deprecated MarkerSymbol    if ( !instance.valid() && _style.has<MarkerSymbol>() )    {        instance = _style.get<MarkerSymbol>()->convertToInstanceSymbol();    }    const IconSymbol* icon = instance->asIcon();    if ( !_image.valid() )    {        URI imageURI;        if ( icon )        {            if ( icon->url().isSet() )            {                imageURI = URI( icon->url()->eval(), icon->url()->uriContext() );            }        }        if ( !imageURI.empty() )        {            _image = imageURI.getImage( _dbOptions.get() );        }    }    // found an image; now format it:    if ( _image.get() )    {        // Scale the icon if necessary        double scale = 1.0;        if ( icon && icon->scale().isSet() )        {            scale = icon->scale()->eval();        }        double s = scale * _image->s();        double t = scale * _image->t();        // this offset anchors the image at the bottom        osg::Vec2s offset;        if ( !icon || !icon->alignment().isSet() )        {               // default to bottom center            offset.set(0.0, t / 2.0);        }        else        {   // default to bottom center            switch (icon->alignment().value())            {            case IconSymbol::ALIGN_LEFT_TOP:                offset.set((s / 2.0), -(t / 2.0));                break;            case IconSymbol::ALIGN_LEFT_CENTER:                offset.set((s / 2.0), 0.0);                break;            case IconSymbol::ALIGN_LEFT_BOTTOM:                offset.set((s / 2.0), (t / 2.0));                break;            case IconSymbol::ALIGN_CENTER_TOP:                offset.set(0.0, -(t / 2.0));                break;            case IconSymbol::ALIGN_CENTER_CENTER:                offset.set(0.0, 0.0);                break;            case IconSymbol::ALIGN_CENTER_BOTTOM:            default:                offset.set(0.0, (t / 2.0));                break;            case IconSymbol::ALIGN_RIGHT_TOP:                offset.set(-(s / 2.0), -(t / 2.0));                break;            case IconSymbol::ALIGN_RIGHT_CENTER:                offset.set(-(s / 2.0), 0.0);                break;            case IconSymbol::ALIGN_RIGHT_BOTTOM:                offset.set(-(s / 2.0), (t / 2.0));                break;            }        }        // Apply a rotation to the marker if requested:        double heading = 0.0;        if ( icon && icon->heading().isSet() )        {            heading = osg::DegreesToRadians( icon->heading()->eval() );        }        //We must actually rotate the geometry itself and not use a MatrixTransform b/c the         //decluttering doesn't respect Transforms above the drawable.        osg::Geometry* imageGeom = AnnotationUtils::createImageGeometry( _image.get(), offset, 0, heading, scale );        if ( imageGeom )        {            _geode->addDrawable( imageGeom );        }        text = AnnotationUtilsEXP::createTextDrawable(            _text,            _style.get<TextSymbol>(),            osg::Vec3( (offset.x() + (s / 2.0) + 2), offset.y(), 0 ) );    }    else    {        text = AnnotationUtilsEXP::createTextDrawable(            _text,            _style.get<TextSymbol>(),            osg::Vec3( 0, 0, 0 ) );    }    if ( text )        _geode->addDrawable( text );    osg::StateSet* stateSet = _geode->getOrCreateStateSet();    stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1 );    getAttachPoint()->addChild( _geode );    // for clamping and occlusion culling        //OE_WARN << LC << "PlaceNode::applyStyle: " << _style.getConfig().toJSON(true) << std::endl;    applyStyle( _style );    setLightingIfNotSet( false );    // generate shaders:    Registry::shaderGenerator().run(        this,        "osgEarth.PlaceNode",        Registry::stateSetCache() );    // re-apply annotation drawable-level stuff as neccesary.    AnnotationData* ad = getAnnotationData();    if ( ad )        setAnnotationData( ad );    if ( _dynamic )        setDynamic( _dynamic );}void PlaceNodeEXP::setAnnotationData( AnnotationData* data ){    OrthoNode::setAnnotationData( data );    // override this method so we can attach the anno data to the drawables.    for(unsigned i=0; i<_geode->getNumDrawables(); ++i)    {        _geode->getDrawable(i)->setUserData( data );    }}void PlaceNodeEXP::setDynamic( bool value ){    OrthoNode::setDynamic( value );    for(unsigned i=0; i<_geode->getNumDrawables(); ++i)    {        _geode->getDrawable(i)->setDataVariance(             value ? osg::Object::DYNAMIC : osg::Object::STATIC );    }}osgEarth::Config PlaceNodeEXP::getConfig() const{    Config conf( "place" );    conf.add   ( "text",   _text.c_str() );    conf.addObj( "style",  _style );    conf.addObj( "position", getPosition() );    if ( _image.valid() ) {        if ( !_image->getFileName().empty() )            conf.add( "icon", _image->getFileName() );        else if ( !_image->getName().empty() )            conf.add( "icon", _image->getName() );    }    return conf;}std::wstring  PlaceNodeEXP::StringToWString(const std::string& s){    std::wstring val = L"";    if(NULL == s.c_str())    {        return val;    }    size_t size_of_wc;    size_t destlen = mbstowcs(0,s.c_str(),0);    if (destlen ==(size_t)(-1))    {        return val;    }    size_of_wc = destlen+1;    wchar_t * pw  = new wchar_t[size_of_wc];    mbstowcs(pw,s.c_str(),size_of_wc);    val = pw;    delete pw;    return val;}

使用示例:

double lon = 116.39;double lat = 39.90;osgEarth::Symbology::Style text_style;    osg::ref_ptr<osgEarth::Symbology::TextSymbol>textStyle=text_style.getOrCreate<TextSymbol>();    textStyle->font()="simsun.ttc";    textStyle->size()=30.0;    textStyle->encoding()=osgEarth::Symbology::TextSymbol::ENCODING_UTF8;    text_style.getOrCreate<osgEarth::Symbology::AltitudeSymbol>()->clamping() = osgEarth::Symbology::AltitudeSymbol::CLAMP_TO_TERRAIN;    text_style.getOrCreate<osgEarth::Symbology::IconSymbol>()->url()->setLiteral( "placemark32.png" );    osg::ref_ptr<PlaceNodeEXP> poi_node =         new PlaceNodeEXP(m_MapNode, osgEarth::GeoPoint::GeoPoint(m_MapNode->getMapSRS()->getGeographicSRS(), lon, lat,0), L"中国", text_style);

有任何疑问或错漏之处欢迎批评指正!

&&我是代码的搬运工&&

0 0
原创粉丝点击