osgEarth中文显示乱码

系列文章目录

文章目录

前言

在 OpenSceneGraph 3.6.5 和 osgEarth 3.2 中,文本渲染统一使用 UTF‑8 编码。如果传入的字符串不是 UTF‑8(例如 Windows 下的 GBK/ANSI),就会出现乱码。要显示中文,必须保证传入的 std::string 是 UTF‑8,并且指定一个支持中文的字体文件(如 simsun.ttc、msyh.ttc)。否则会出现显示中文乱码的情况

一、osgEarth中文乱码的原因是什么?

在 osgEarth 三维地图中出现中文乱码,核心原因是文本编码转换错误或显示端编码不匹配,具体可分为以下几点:

1.源文件编码与 Qt 字符串处理不匹配若项目源文件(如.cpp)使用 GBK 编码(非 UTF-8),在 Qt 中直接定义中文字符串(如QString text = "中文标签")时,Qt 会默认将其按源文件编码(GBK)解析为 Unicode 字符。但由于编码解析错误,QString内部可能存储的是乱码的 Unicode 数据,后续转换为 UTF-8 时自然会出现乱码。

2.osgEarth 文本显示编码未明确指定osgEarth 的TextSymbol默认编码可能不支持 UTF-8,若未显式设置encoding()为ENCODING_UTF8,即使传入的字符串是正确的 UTF-8 格式,osgEarth 也可能用其他编码(如 ASCII)解析,导致中文无法识别。

3.缺少中文字体支持若 osgEarth 使用的字体不包含中文字符集(如默认的英文字体),即使编码正确,中文也会显示为方块或空白(本质是 "无法渲染" 而非 "乱码",但常被归为同类问题)。

二、解决方法

解决方法总结

针对上述原因,代码中采用了以下解决方案,可彻底解决中文乱码问题:

修复源文件编码导致的字符串乱码若源文件为 GBK 编码,需先将错误解析的QString还原为正确的 Unicode 字符串,再转换为 UTF-8:

用QTextCodec::codecForName("GBK")获取 GBK 编码器;

通过fromUnicode(text)提取原始 GBK 字节(还原源文件编码的字节流);

用toUnicode(gbkBytes)重新解析为正确的 Unicode 字符串;

最终通过toStdString()转换为 UTF-8 格式的std::string,供 osgEarth 使用。

显式指定 osgEarth 文本编码为 UTF-8在TextSymbol中明确设置编码,确保 osgEarth 用 UTF-8 解析文本:

cpp

运行

osgEarth::TextSymbol* ts = style.getOrCreateSymbolosgEarth::TextSymbol();

ts->encoding() = osgEarth::TextSymbol::ENCODING_UTF8; // 强制UTF-8编码

确保使用支持中文的字体(补充建议)代码中注释了字体路径设置,实际使用时需指定包含中文字符的字体(如 "微软雅黑""黑体" 等):

cpp

运行

QString fontPath = QCoreApplication::applicationDirPath() + "/fonts/simhei.ttf"; // 黑体字体

ts->font() = fontPath.toStdString(); // 关联字体文件

通过以上步骤,可确保中文从 "字符串定义" 到 "osgEarth 渲染" 的全流程编码一致,彻底解决乱码问题。

cpp 复制代码
osg::ref_ptr<osgEarth::PlaceNode> AmainWidget::createLabel(const QString& text, double lon, double lat)
{
	const osgEarth::SpatialReference* wgs84 = osgEarth::SpatialReference::get("wgs84");
	osgEarth::GeoPoint geoPoint(wgs84, lon, lat, 0.0, osgEarth::ALTMODE_RELATIVE);


	// 调试输出(保留,用于验证编码)
	qDebug() << QString::fromLocal8Bit("[QString原始内容]:") << text;
	qDebug() << QString::fromLocal8Bit("[QString长度]:") << text.length();
	QByteArray utf8Bytes = text.toUtf8();
	qDebug() << QString::fromLocal8Bit("[UTF-8字节数]:") << utf8Bytes.size();
	qDebug() << QString::fromLocal8Bit("[UTF-8十六进制]:") << utf8Bytes.toHex();


	// 修正:正确的编码转换逻辑(解决QByteArray::toUtf8()错误)
	std::string utf8Text;

	// 情况1:若原始QString因源文件GBK编码导致内部乱码(常见于非UTF-8源文件)
	QTextCodec* gbkCodec = QTextCodec::codecForName("GBK");
	if (gbkCodec) {
		// 步骤1:将GBK编码的字节(错误解析的QString)还原为正确的Unicode QString
		// (原理:假设text内部是GBK字节误解析为Unicode,先提取GBK字节,再重新解析为Unicode)
		QByteArray gbkBytes = gbkCodec->fromUnicode(text); // 提取GBK字节
		QString correctText = gbkCodec->toUnicode(gbkBytes); // 用GBK重新解析为正确的QString

		// 步骤2:将正确的QString转为UTF-8的std::string
		utf8Text = correctText.toStdString(); // 用toUtf8()而非toLocal8Bit()
	}
	else {
		// 情况2:正常情况,直接转换
		utf8Text = text.toUtf8().toStdString();
	}


	// 验证转换结果
	qDebug() << QString::fromLocal8Bit("[转换后std::string]:") << QString::fromUtf8(utf8Text.c_str());


	// 创建 PlaceNode 及样式设置(保持不变)
	osg::ref_ptr<osgEarth::PlaceNode> placeNode = new osgEarth::PlaceNode(geoPoint, utf8Text);
	osgEarth::Style style;
	osgEarth::TextSymbol* ts = style.getOrCreateSymbol<osgEarth::TextSymbol>();
	ts->size() = osgEarth::NumericExpression("18");
	ts->fill()->color() = osgEarth::Color::Yellow;
	ts->halo()->color() = osgEarth::Color::Black;
	ts->alignment() = osgEarth::TextSymbol::ALIGN_CENTER_CENTER;
	QString fontPath = QCoreApplication::applicationDirPath() + "/fonts/simhei.ttf";
	ts->font() = fontPath.toStdString(); // 确保字体文件存在
	ts->encoding() = osgEarth::TextSymbol::ENCODING_UTF8; // 明确UTF-8编码

	placeNode->setStyle(style);

	return placeNode;
}

三、结果

相关推荐
CHPCWWHSU15 天前
osg中文字的使用
osg·osgtext·text3d
CHPCWWHSU2 个月前
osg中相机矩阵到vsg相机矩阵的转换
opengl·osg·投影矩阵·vulkan·vsg
daqinzl3 个月前
Ubuntu 24.04 解决 firefox 中文界面乱码
ubuntu·中文乱码·firefox
Pafey3 个月前
VS2022 + Qt5.9 中文乱码/项目设置utf-8编码
c++·qt·中文乱码
WALL-EC4 个月前
Qt工具栏中图标槽函数没有响应的问题分析
开发语言·qt·osgearth
幽迷狂4 个月前
AFSIM入门教程03.03:更新所有依赖库版本
c++·qt·仿真·osgearth·osg·军事·afsim
星火撩猿8 个月前
如何配置osg编译使支持png图标加载显示
osgearth·osg·地图图标添加
真就死难8 个月前
ArcGIS、ArcMap查看.shp文件时属性表中文乱码
arcgis·中文乱码
xiyangxiaoguo8 个月前
使用OpenSceneGraph (osg)实现一个星系漫游
osg