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的编码来进行转换,结果就是汉字全部是乱码,导致的结果就是找不到文件,所以打不开。
解决方法:
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);
要设一个节点来专门调整模型的朝向
一开始模型太小了
转自: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中的中文都是这个方法,先转换在显示。
注明:这些方法都是在看了许多例子和博客的才解决的问题,其实我没什么创新只是整合了一下供大家参考,在这里感谢那些大牛们的无私奉献。
方法一:
通过自己写函数转换类型。
下面这三个函数先复制过去吧。
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());
--------------等等别忘记额,这种方法任然需要设置字体样式(跟方法二相同)。
方法三:
修改源码重新编译。好吧,这种方式一劳永逸(网上有很多重新编译的需要修改源码的案例),这里我就不多做累述。
无图无真相:
摘要:
使用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