为使osgEarth支持中文,需对osgEarthAnnotation源码做出改动,现将过程记录如下以供参考。
①参考PlaceNode的构造函数发现,源码中使用了Init函数,其中需要对添加注记的CreateTextDrawable函数进行重载,步骤如下:
在AnnotationUtils.h中声明重载函数:
static osg::Drawable* createTextDrawable(
const std::wstring& text, //支持宽字符
const TextSymbol* symbol,
const osg::Vec3& positionOffset );
在AnnotationUtils.cpp中定义重载函数(直接复制原createTextDrawable函数,本文只展示修改部分):
osg::Drawable* AnnotationUtils::createTextDrawable(const std::wstring& text,
const TextSymbol* symbol,
const osg::Vec3& positionOffset )
{
....
t->setText( text.c_str());
....
}
②在对AnnotationUtils修改后需要对PlaceNode做出修改。
首先需要添加宽字符变量,以与之前字符变量区分,在PlaceNode.h中添加 std::wstring _wtext;
此外对涉及文本的函数都需要重载,需要重载的函数在PlaceNode.h声明如下:
PlaceNode(
MapNode* mapNode,
const GeoPoint& position,
osg::Image* iconImage,
const std::wstring& labelText,
const Style& style =Style() );
PlaceNode(
MapNode* mapNode,
const GeoPoint& position,
const std::wstring& labelText,
const Style& style =Style() );
void initw();
重载的函数在PlaceNode.cpp中定义如下(直接复制原函数,本文只展示修改部分):
PlaceNode::PlaceNode(MapNode* mapNode,
const GeoPoint& position,
osg::Image* image,
const std::wstring& text,
const Style& style ) :
OrthoNode( mapNode, position ),
_image ( image ),
_wtext ( text ),
_style ( style ),
_geode ( 0L )
{
initw();
}
PlaceNode::PlaceNode(MapNode* mapNode,
const GeoPoint& position,
const std::wstring& text,
const Style& style ) :
OrthoNode( mapNode, position ),
_wtext ( text ),
_style ( style ),
_geode ( 0L )
{
initw();
}
void PlaceNode::initw()
{
....
if ( _wtext.empty() && _style.has() )
{
_wtext =StringToWString(_style.get()->content()->eval_r());
}
....
text = AnnotationUtils::createTextDrawable(
_wtext,
_style.get(),
osg::Vec3( (offset.x() + (s / 2.0) + 2), offset.y(), 0 ) );
}
在重写initw函数时涉及string转wstring的问题,参考网上转换方法,虽然我也不知道如何实现转换功能,但是确实成功转换了,共享如下:
首先需要在PlaceNode.h中声明函数(当然也可以声明在别的头文件中,自己知道如何调用即可):
std::wstring StringToWString(const std::string& s);
由于该函数涉及系统函数,所以需要在PlaceNode.h中包含系统头文件:
#include <windows.h>
在PlaceNode.cpp中定义函数:
std::wstring PlaceNode::StringToWString(const std::string& s)
{
std::wstring wszStr;
int nLength = MultiByteToWideChar( CP_ACP, 0, s.c_str(), -1, NULL, NULL );
wszStr.resize(nLength);
LPWSTR lpwszStr = new wchar_t[nLength];
MultiByteToWideChar( CP_ACP, 0, s.c_str(), -1, lpwszStr, nLength );
wszStr = lpwszStr;
delete [] lpwszStr;
return wszStr;
}
③所有修改完成之后需要对osgEarthAnnotation进行重新编译,将新生成的lib以及dll文件放到对应位置,此外,由于对源码做出了改动,所以需要将修改后的源码放到include文件夹中。
④编写地标添加程序,需要注意的是一定要设置字体以及字体编码,具体如何实现添加地标不做详解。
osgEarth::Style style;
osgEarth::Symbology::TextSymbol *textStyle=style.getOrCreateSymbol();
textStyle->font()="simsun.ttc";
textStyle->size()=30.0;
textStyle->encoding()=osgEarth::Symbology::TextSymbol::ENCODING_UTF8;
修改效果如下: