不改源码的方式实现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
- 不改源码的方式实现osgearth当中placenode的中文支持
- OSGEarth支持中文方法
- osg、osgearth支持中文
- osgEarth支持中文过程详解
- Mybatis Generator的model生成中文注释,支持oracle和mysql(通过修改源码的方式来实现)
- html5当中支持的视频格式
- C4D当中的对齐方式
- TMS套件当中TAdvMemo对多字节文字(MultiByte)-中文支持的修正
- 解决osgEarth中文显示乱码的几种方法
- osgEarth加载谷歌卫星地图的源码案例
- osgearth访问几种数据的几种方式
- osgearth访问几种数据的几种方式
- osgearth访问几种数据的几种方式
- Silverlight 4当中的剪贴簿支持
- Python当中的正则表达式支持!
- OsgEarth的tile
- OSGEarth的测量分析
- Mybatis的xml修改后自动刷新(不改源码)
- cocos2d-x sqlite的读取和相关操作
- Swift基础篇——数组
- Swift基础篇——字典
- Swift基础篇——字符串
- Swift基础篇——函数
- 不改源码的方式实现osgearth当中placenode的中文支持
- 每天学点儿树莓派(三)——使用IDE提高效率
- Swift基础篇——构造函数
- Swift基础篇——setter和getter的使用
- LeetCode OJ 123 Best Time to Buy and Sell Stock III
- Swift基础篇——闭包
- Unity中HideInInspector和SerializeField
- Swift基础篇——懒加载
- Eclipse 常用快捷键