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