osgearth中文


osgearth 中文显示

1、osgearth 有关中文路径问题

转自:http://blog.sina.com.cn/s/blog_803fc5eb0100yqrc.html

osgearth打开中文路径失败,若是驱动器为gdal时,大体是由于gdal无法打开中文文件所造成的,可进行一下设置:

用的是最新的GDAL1.9,GDAL中有一个函数CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" )判断,通过判断是否是UTF8的编码,而且指定的默认值还是UTF8编码,在含有中文路径的字符串大多数的编码应该是GBK的编码,这样,系统就将GBK的编码当做UTF8的编码来进行转换,结果就是汉字全部是乱码,导致的结果就是找不到文件,所以打不开。

解决方法:

不改变GDAL源代码,在自己调用GDALRegisterAll()和OGRAllRegiser()函数后,加上下面一句即可。

CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");

包含的头文件为:cpl_conv.h

 

2、有关osgearth缓存文件命名的问题

转自:http://blog.sina.com.cn/s/blog_803fc5eb0100yqr3.html

当设置缓存文件类型为filesystem 时,进行以下设置:

<layer name="something" cacheid="something" ...>

此时,缓存文件名为"something_xxxxx"

若是在代码中,进行以下设置:

sgEarth::Drivers::GDALOptions opt;
opt.url() = filePath;
opt.maxDataLevel() = 14;
opt.tileSize()=256;
osgEarth::ImageLayerOptions layerOpt(name, opt);
layerOpt.cacheId() = "my_cache_id";
ImageLayer* layer = new osgEarth::ImageLayer(layerOpt);

 

3、中文显示

转自:http://blog.sina.com.cn/s/blog_803fc5eb01012q66.html

BOOL StringToWString(const std::string &str,std::wstring &wstr)
{    
    int nLen = (int)str.length();    
    wstr.resize(nLen,L' ');

    int nResult = MultiByteToWideChar(CP_ACP,0,(LPCSTR)str.c_str(),nLen,(LPWSTR)wstr.c_str(),nLen);

    if (nResult == 0)
    {
        return FALSE;
    }

    return TRUE;
}

std::string convertUTF16toUTF8(const wchar_t* source, unsigned sourceLength)
{
    if (sourceLength == 0)
    {
        return std::string();
    }

    int destLen = WideCharToMultiByte(CP_UTF8, 0, source, sourceLength, 0, 0, 0, 0);
    if (destLen <= 0)
    {
        OSG_WARN << "Cannot convert UTF-16 string to UTF-8." << std::endl;
        return std::string();
    }

    std::string sDest(destLen, '\0');
    destLen = WideCharToMultiByte(CP_UTF8, 0, source, sourceLength, &sDest[0], destLen, 0, 0);

    if (destLen <= 0)
    {
        OSG_WARN << "Cannot convert UTF-16 string to UTF-8." << std::endl;
        return std::string();
    }

    return sDest;
}

std::string convertUTF16toUTF8(const std::wstring& s){return convertUTF16toUTF8(s.c_str(), s.length());}

1、先从string转为wstring;
2、从wstring转为string;
即为 wstring wstr;
StringToWString(str, wstr);
string r = convertUTF16toUTF8(wstr);
osgText::Text text =  new osgText::Text();
text->setText(r,  osgText::String::ENCODING_UTF8);

 

4、osg、osgearth和qt中文显示

转自:http://blog.sina.com.cn/s/blog_6c922b4501014469.html

Q:同时导入多个模型,想鼠标点击其中的一个,使其高亮显示,并且可以单独控制该模型移动(如拖动或摆动等),怎么可以实现
A:方法有很多,例如设置颜色数组,材质,或者用着色器等
计算鼠标的偏移,相应事件中重绘模型,但是效率可能比较低
单击-射线求交,通过鼠标Drag消息计算平移,赋到上层transform结点,不就完了。
使用osg中的自带的drag拖拽器就可以完成场景模型的拖动功能。

 

Q:求教:一个模型的不同部件,如何显示鼠标所指位置模型不同部件的名称?有什么好的方法?
A:直接求交,从交集的nodepath里找
如果你的一个部件就是一个node的话,那么从交集的nodepath里就可以确定。
交集的nodepath保存了从相交的drawable开始到root的父节点链
所有部件属于同一模型,同一Node该怎么办呢?    拆!
我试过FLT文件可以通过交集测试获取模型的部件

 


Q:请问如何在漫游中能像默认操作器那样用鼠标拖拽模型?
A:拖曳的识别是通过GUIEventHandler中的DRAG事件来完成的


解决QT中文字符串在osg中显示乱码的问题
网上有很多例子,但是几乎都没有正常显示中文,经过痛苦的试验和折磨,终于解决了QT字符串在osg中的正常显示问题,下面贴出主要

代码,分享给大家。
QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK"));
 
 
QTextCodec* code = QTextCodec::codecForName("UTF-8");
 
QString qstr = QObject::tr("中国");
 
string str = code->fromUnicode(qstr).data();
       
osgText::Text* text = new osgText::Text;
       
textOne->setFont("C:/WINDOWS/Fonts/STSONG.ttf");//设置中文字体
 
text->setText(str, osgText::String::ENCODING_UTF8);


Q:关于Google earth影像坐标准不准?
http://bbs.esrichina-bj.cn/ESRI/viewthread.php?action=printable&tid=78315
http://topic.csdn.net/u/20100412/13/d81d7f70-c82c-4e71-883c-77555aee5c74.html

Q:模型的朝向
elevationManager.getPlacementMatrix(geoPoint.x(),geoPoint.y(),10.0,0.0,NULL,n_matrix,elevationInMap,resolution);
要设一个节点来专门调整模型的朝向
一开始模型太小了

 

5、OSG和osgearth显示中文

转自:http://blog.csdn.net/l_andy/article/details/44204741

做osg相关的项目有一段时间了,一直想写几篇这方面的博文,今天终于开始了。今天主要介绍一下怎么解决osg 和osgearth中显示中文的的问题,这个问题我反复遇到让我很是纠结啊。

  一、知识储备

  要想很好的理解和解决这个问题,首先要了解什么是多字节和宽字节。说实话我之前也知道这两个字节到底有什么区别,只是简单查了一下资料。这里引用了这篇博客,我感觉博主写的很有意思,通俗易懂,在这里先谢谢这位博主的奉献。http://blog.163.com/baijianguo00@126/blog/static/1375326052011018101334714/

 二、问题提出

在大致了解了什么是多字节和款字节之后,我们来看看具体的问题。osg是老外开发的源码,没办法对中文支持很差,虽然这一点儿也不能影响osg带给我们的快感,我们在使用osg中肯定会或多或少要显示中文,但是你会发现你按显示英文那样就做显示的都是乱码。比如我使用LableNode 加一个标记在地球上,如下

labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, 117.5, 39.38), "北京" , pin));

labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -100.10, 40.60), "U.S.A" , flag));

这时发现北京显示的乱码,而“U.S.A”显示是正确的,还有我们在加载矢量的shp数据时,如果是地名标记数据,显示在地球上也是乱码,还用LableControl显示中文时也是一样的。这里有两种成功的方法,一、改源码;二、转换字符,其实这两种方法本质都是在显示中文时转换字符。改源码一劳永逸但是难度大有风险而且还要重新编译,鉴于此我还是推荐第二种方法-------在程序实时地转换字符。

  三、解决方法

中文显示要用宽字节,这里提供几个转换函数。

函数一:

void unicodeToUTF8(const wstring &src, string& result)
{
int n = WideCharToMultiByte( CP_UTF8, 0, src.c_str(), -1, 0, 0, 0, 0 );
result.resize(n);
::WideCharToMultiByte( CP_UTF8, 0, src.c_str(), -1, (char*)result.c_str(), result.length(), 0, 0 );
}


函数二:
void gb2312ToUnicode(const string& src, wstring& result)
{
int n = MultiByteToWideChar( CP_ACP, 0, src.c_str(), -1, NULL, 0 );
result.resize(n);
::MultiByteToWideChar( CP_ACP, 0, src.c_str(), -1, (LPWSTR)result.c_str(), result.length());
}
当物在osg程序中显示汉字时,就如下调用上述两个函数即可,
void gb2312ToUtf8(const string& src, string& result)
{
wstring strWideChar;
gb2312ToUnicode(src, strWideChar);
unicodeToUTF8(strWideChar, result);
}
我们拿上面显示的北京标记的做例子,

Style pin;

pin.getOrCreate<IconSymbol>()->url()->setLiteral(m_PngFilepath);//指定标注图片路径

pin.getOrCreate<osgEarth::Symbology::TextSymbol>()->font()=m_FontFilepath;//指定中文字体路径
pin.getOrCreate<osgEarth::Symbology::TextSymbol>()->encoding() = osgEarth::Symbology::TextSymbol::ENCODING_UTF8;
pin.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_CENTER;
pin.getOrCreate<TextSymbol>()->fill()->color() = Color::Red;

std::string _strName;

_strName = "北京";

std::string _strWideName;

gb2312ToUtf8(_strName,_strWideName);//这时的_strWideName就是宽字节用来显示就正确了

labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, 117.5, 39.38), _strWideName , pin));

显示地名标记和LableControl中的中文都是这个方法,先转换在显示。

注明:这些方法都是在看了许多例子和博客的才解决的问题,其实我没什么创新只是整合了一下供大家参考,在这里感谢那些大牛们的无私奉献。

 
6、 解决osgEarth中文显示乱码的几种方法
转自:http://blog.csdn.net/gis_zss/article/details/45014377

方法一:

通过自己写函数转换类型。

下面这三个函数先复制过去吧。

 

void unicodeToUTF8(const std::wstring &src, std::string& result)
{
int n = WideCharToMultiByte( CP_UTF8, 0, src.c_str(), -1, 0, 0, 0, 0 );
result.resize(n);
::WideCharToMultiByte( CP_UTF8, 0, src.c_str(), -1, (char*)result.c_str(), result.length(), 0, 0 );
}

void gb2312ToUnicode(const std::string& src, std::wstring& result)
{
int n = MultiByteToWideChar( CP_ACP, 0, src.c_str(), -1, NULL, 0 );
result.resize(n);
::MultiByteToWideChar( CP_ACP, 0, src.c_str(), -1, (LPWSTR)result.c_str(), result.length());
}
void gb2312ToUtf8(const std::string& src, std::string& result)
{
std::wstring strWideChar;
gb2312ToUnicode(src, strWideChar);
unicodeToUTF8(strWideChar, result);
}

接下来把需要显示的中文进行如下转换便可以使用了。

std::string _strName;
    _strName = "你好";
    std::string _strWideName;
    gb2312ToUtf8(_strName,_strWideName)

-------------等等还是乱码。好吧的确有可能还是乱码,这里需要设置字体样式:

Style pin;

    pin.getOrCreate<IconSymbol>()->url()->setLiteral("D:/osgearth/OSGOK/data/placemark32.png");//指定标注图片路径
    pin.getOrCreate<osgEarth::Symbology::TextSymbol>()->font()="C:/Windows/Fonts/simhei.ttf";//指定中文字体路径
    pin.getOrCreate<osgEarth::Symbology::TextSymbol>()->encoding() = osgEarth::Symbology::TextSymbol::ENCODING_UTF8;
    pin.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_CENTER;
    pin.getOrCreate<TextSymbol>()->fill()->color() = Color::Red;

root->addChild( new PlaceNode(mapNode, GeoPoint(mapNode->getMapSRS(), 117.5, 39.38), _strWideName , pin));

把这个字体样式加上就可以成功显示中文了,好了吧。

方法二:

这是一种很酷炫的方法(其实跟方法二差不多啦)。

方法就是利用Qt的函数来处理中文,代码很简单,如下:

QString name="你好";
    std::string _strWideName = std::string(name.toUtf8());

--------------等等别忘记额,这种方法任然需要设置字体样式(跟方法二相同)。

 

方法三:

修改源码重新编译。好吧,这种方式一劳永逸(网上有很多重新编译的需要修改源码的案例),这里我就不多做累述。


无图无真相:

 
转自:http://blog.csdn.net/xiaopeixiaojun/article/details/49262769

摘要: 
使用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


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);

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

 

 

8、osgearth支持中文过程详解

转自:http://www.ithao123.cn/content-5600891.html

[摘要:为使osgEarth支撑中文,需对osgEarthAnnotation源码做出修改,现将进程纪录以下以供参考。 ①参考PlaceNode的组织函数发明,源码中应用了Init函数,个中须要对增加注记的CreateTextDrawable函数进] 

为使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;

修改效果如下:

 

 

9、osgEarth2.2中文标注解决办法

转自:http://blog.csdn.net/taor1/article/details/8296210

最近在osg官网上发现osgEarth升级到2.2版了,看了发布说明,增加了不少新功能,所以赶紧把源码下下来,发现确实多了不少新功能,最大的升级是在对Qt的支持、墨卡托坐标系的支持,还多了不少例子。

   但是我添加中文标注的矢量数据时,标注出现乱码的情况,经过对源码的研究,对源码进行了修改,标注的代码在AnnotationUtils类的CreateTextDrawable函数中的t->setText(string)代码,将该代码修改如下:

   Setlocale(LC_ALL,"chs");

   int wSize = text.size()*2+2;

   wchar_t* wtext=new wchar_t[wSize+1];

   memset(wtext,0,wSize+1);

   mbstowcs(wtext,text.c_str(),wSize);

   t->setText(wtext);

   delete[] wtext;

   wtext=NULL ;

 

   LabelControl中也存在类似问题,解决方法和标注一样,修改的函数为LabelControl::calcSize函数中修改即可。

 



============================================================================================
============================================================================================

 

 

显示label的代码src\osgEarthUtil\Controls.cpp的524行,修改如下。

LabelControl::calcSize(const ControlContext& cx, osg::Vec2f& out_size)

{

    if ( visible() == true )

    {

        // we have to create the drawable during the layout pass so we can calculate its size.

        LabelText* t = new LabelText();

 

#if 1

        // needs a special shader

        // todo: doesn't work. why?

        osg::Program* program = new osg::Program();

        program->addShader( new osg::Shader( osg::Shader::VERTEX, s_controlVertexShader ) );

        program->addShader( new osg::Shader( osg::Shader::FRAGMENT, s_labelControlFragmentShader ) );

        t->getOrCreateStateSet()->setAttributeAndModes( program, osg::StateAttribute::ON );

#endif

// chinese support.part1 begin 2011-11-14

        setlocale( LC_ALL, "chs" );

int requiredSize = mbstowcs(NULL, _text.c_str(), 0); 

        wchar_t* wtext = new wchar_t[requiredSize+1]; 

        mbstowcs(wtext, _text.c_str(), requiredSize+1); 

        t->setText(wtext); 

        delete [] wtext; 

        wtext = NULL; 

// chinese support. part1 end 2011-11-14

 

// chinese support.part1 begin 2011-11-14

       //t->setText( _text );

// chinese support. part1 end 2011-11-14

 

 

        // yes, object coords. screen coords won't work becuase the bounding box will be wrong.

        t->setCharacterSizeMode( osgText::Text::OBJECT_COORDS );

        t->setCharacterSize( _fontSize );

        // always align to top. layout alignment gets calculated layer in Control::calcPos().

        t->setAlignment( osgText::Text::LEFT_TOP ); 

        t->setColor( foreColor().value() );

        if ( _font.valid() )

            t->setFont( _font.get() );

 

// chinese support.part1 begin 2011-11-14

setlocale( LC_ALL,"C" ); 

// chinese support. part1 end 2011-11-14

 

        if ( haloColor().isSet() )

        {

            t->setBackdropType( osgText::Text::OUTLINE );

            t->setBackdropOffset( 0.03 );

            t->setBackdropColor( haloColor().value() );

        }

 

        osg::BoundingBox bbox = t->getTextBB();

        if ( cx._viewContextID != ~0u )

        {

            //the Text's autoTransformCache matrix puts some mojo on the bounding box

            osg::Matrix m = t->getATMatrix( cx._viewContextID );

            _bmin = osg::Vec3( bbox.xMin(), bbox.yMin(), bbox.zMin() ) * m;

            _bmax = osg::Vec3( bbox.xMax(), bbox.yMax(), bbox.zMax() ) * m;

        }

        else

        {

            _bmin = osg::Vec3( bbox.xMin(), bbox.yMin(), bbox.zMin() );

            _bmax = osg::Vec3( bbox.xMax(), bbox.yMax(), bbox.zMax() );

        }

 

        _renderSize.set(

            (_bmax.x() - _bmin.x()) + padding().x(),

            (_bmax.y() - _bmin.y()) + padding().y() );

 

        _drawable = t;

 

        out_size.set(

            margin().x() + _renderSize.x(),

            margin().y() + _renderSize.y() );

    }

    else

    {

        out_size.set(0,0);

    }

 

    //_dirty = false;

}

 

原因是读取字符串的时候就没有支持双字节的字节,如中文。


 

============================================================================================
============================================================================================

osgEarth中设置显示中文的label

CString  mss = _T("中国");
std::string ss = osgDB::convertUTF16toUTF8(mss.AllocSysString());

// set up a style to use for labels:
osgEarth::Annotation::Symbology::Style labelStyle;
labelStyle.getOrCreate<TextSymbol>()->encoding() = TextSymbol::ENCODING_UTF8;
labelStyle.getOrCreate<TextSymbol>()->font() = std::string("fonts/SimHei.ttf");

============================================================================================
 

osgearth打开中文路径失败,若是驱动器为gdal时,大体是由于gdal无法打开中文文件所造成的,可进行一下设置:

用的是最新的GDAL1.9,GDAL中有一个函数CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" )判断,通过判断是否是UTF8的编码,而且指定的默认值还是UTF8编码,在含有中文路径的字符串大多数的编码应该是GBK的编码,这样,系统就将GBK的编码当做UTF8的编码来进行转换,结果就是汉字全部是乱码,导致的结果就是找不到文件,所以打不开。

解决方法:

不改变GDAL源代码,在自己调用GDALRegisterAll()和OGRAllRegiser()函数后,加上下面一句即可。

CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");

包含的头文件为:cpl_conv.h


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM