Geotools结合SLD实现矢量中文标注下的乱码和可用字体解析

news2025/4/2 16:33:38

目录

前言

一、需求溯源

1、原始的SLD渲染

2、最初的效果

二、问题修复

1、还是字符编码

2、如何选择可用的字体

 3、如何查看支持的字体库

三、总结


前言

        随着地理信息系统(GIS)技术的不断发展,矢量数据的可视化和标注成为了地理信息展示的重要环节。矢量数据标注不仅能够增强地图的可读性,还能为用户提供更多直观的信息。然而,在实际应用中,矢量数据的中文标注往往面临乱码问题,尤其是在跨平台、跨系统环境下,字体的兼容性和可用性问题尤为突出。本文将探讨如何利用Geotools结合SLD(Styled Layer Descriptor)技术,解决矢量中文标注中的乱码问题,并解析可用字体,以实现高效、准确的矢量数据可视化。

        1. 矢量数据标注的重要性

        矢量数据标注是地理信息系统中不可或缺的一部分。通过标注,用户可以快速获取地理实体的名称、属性等信息,从而更好地理解地图内容。在城市规划、资源管理、环境保护等领域,矢量数据标注的应用尤为广泛。然而,随着应用场景的多样化,矢量数据标注面临着越来越多的挑战,尤其是在中文标注方面。

        2. 中文标注的乱码问题

        中文标注的乱码问题主要源于以下几个方面:

  1. 编码问题:不同系统或平台对字符编码的支持可能存在差异,导致字符无法正确显示。

  2. 字体问题:某些字体在特定系统或环境中可能不可用,或者字体本身不支持中文字符。

  3. 渲染问题:矢量数据的渲染过程可能涉及多种技术栈,不同技术栈对字体和字符的支持程度不同。

        这些问题在实际应用中可能导致标注内容无法正确显示,影响地图的可读性和用户体验。

        3. 可用字体解析

        在实际应用中,确保标注字体的可用性是解决乱码问题的关键。Geotools提供了字体解析功能,可以动态检测系统中可用的字体,并根据SLD文件中的配置选择合适的字体进行渲染。通过解析系统字体,可以确保标注内容在不同环境下的兼容性和一致性。

        本文的目标是通过Geotools和SLD技术,解决矢量中文标注中的乱码问题,并解析可用字体,以实现高效、准确的矢量数据可视化。研究方法包括:

  1. 分析矢量数据标注的常见问题:通过实际案例分析中文标注乱码的原因。

  2. 探索Geotools和SLD的结合应用:研究如何利用Geotools的字体管理和SLD的样式定义解决乱码问题。

  3. 验证解决方案的有效性:通过实验验证解决方案在不同环境下的适用性和稳定性。

一、需求溯源

        Geotools是一个开源的Java GIS工具库,广泛应用于地理信息数据的处理和可视化。SLD(Styled Layer Descriptor)是一种基于XML的标准,用于定义地理数据的样式和渲染规则。通过结合Geotools和SLD技术,可以实现对矢量数据的高效管理和可视化。在解决中文标注乱码问题时,Geotools提供了强大的字体管理和字符编码支持,而SLD则可以通过样式定义确保标注内容的正确显示。通过合理配置SLD文件,可以指定字体、颜色、大小等样式属性,从而避免因字体或编码问题导致的乱码。原来在做一个矢量文件渲染时,使用代码加载了SLD文件后,出现文字注记没有正确的加载展示的情况,虽然图形的轮廓是展示出来了,但是表示是乱码的,所以整体效果比较差。如下图:

        通过在网络上查询一些资料,讲解Geotools中如何进行SLD渲染的内容不少,讲解注记的也挺多。但是一些博主在讲解中文注记时,没有很好的进行深入,本文这里就是主要用来弥补相关信息的不足,为遇到问题的各位提供一个问题排查的思路。 

1、原始的SLD渲染

        首先我们可以使用Qgis软件来展示和编辑相关的矢量文件,在编辑预览的同时可以设置矢量数据的样式,比如渲染的边界颜色等信息。关于如何在Qgis中进行SLD样式的设置知识,这里不进行赘述,大家可以翻阅之前的系列博客进行学习。这里以一个湖南省的乡镇的面数据为例,主要讲解的一个面数据的简单标绘。在Qgis中生成的SLD文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:se="http://www.opengis.net/se" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1.0" xmlns:ogc="http://www.opengis.net/ogc">
  <NamedLayer>
    <se:Name>湖南-乡镇utf8</se:Name>
    <UserStyle>
      <se:Name>湖南-乡镇utf8</se:Name>
      <se:FeatureTypeStyle>
        <se:Rule>
          <se:Name>Single symbol</se:Name>
          <se:PolygonSymbolizer>
            <se:Fill>
              <se:SvgParameter name="fill">#f4f4f4</se:SvgParameter>
            </se:Fill>
            <se:Stroke>
              <se:SvgParameter name="stroke">#e31a1c</se:SvgParameter>
              <se:SvgParameter name="stroke-width">1</se:SvgParameter>
              <se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter>
              <se:SvgParameter name="stroke-dasharray">4 2</se:SvgParameter>
            </se:Stroke>
          </se:PolygonSymbolizer>
        </se:Rule>
        <se:Rule>
          <se:TextSymbolizer>
            <se:Label>
              <ogc:PropertyName>Name</ogc:PropertyName>
            </se:Label>
            <se:Font>
              <se:SvgParameter name="font-family">宋体</se:SvgParameter>
              <se:SvgParameter name="font-size">13</se:SvgParameter>
            </se:Font>
            <se:LabelPlacement>
              <se:PointPlacement>
                <se:AnchorPoint>
                  <se:AnchorPointX>0</se:AnchorPointX>
                  <se:AnchorPointY>0.5</se:AnchorPointY>
                </se:AnchorPoint>
              </se:PointPlacement>
            </se:LabelPlacement>
            <se:Fill>
              <se:SvgParameter name="fill">#000000</se:SvgParameter>
            </se:Fill>
            <se:VendorOption name="maxDisplacement">1</se:VendorOption>
          </se:TextSymbolizer>
        </se:Rule>
      </se:FeatureTypeStyle>
    </UserStyle>
  </NamedLayer>
</StyledLayerDescriptor>

        该SLD文件定义了一个矢量图层的样式规则,主要用于多边形数据的符号化和文本标注。文件的结构遵循OGC(Open Geospatial Consortium)的SLD规范,版本为1.1.0。 

 2.核心内容解析

2.1 命名层(NamedLayer

  • <se:Name>:定义图层的名称为“湖南-乡镇utf8”,表示该样式适用于名为“湖南-乡镇utf8”的矢量图层。

2.2 用户样式(UserStyle

  • <se:Name>:定义样式的名称为“湖南-乡镇utf8”,与命名层的名称一致。

  • <se:FeatureTypeStyle>:定义了适用于该图层的样式规则。

2.3 多边形符号化(PolygonSymbolizer

  • <se:Fill>:定义多边形的填充样式。

    • <se:SvgParameter name="fill">:填充颜色为浅灰色(#f4f4f4)。

  • <se:Stroke>:定义多边形边框的样式。

    • <se:SvgParameter name="stroke">:边框颜色为红色(#e31a1c)。

    • <se:SvgParameter name="stroke-width">:边框宽度为1像素。

    • <se:SvgParameter name="stroke-linejoin">:边框连接方式为“bevel”(斜接)。

    • <se:SvgParameter name="stroke-dasharray">:边框为虚线,虚线模式为“4 2”(4像素实线,2像素间隔)。

2.4 文本符号化(TextSymbolizer

  • <se:Label>:定义标注内容为矢量数据的“Name”字段。

  • <se:Font>:定义标注字体样式。

    • <se:SvgParameter name="font-family">:字体为“宋体”。

    • <se:SvgParameter name="font-size">:字体大小为13像素。

  • <se:LabelPlacement>:定义标注的定位方式。

    • <se:PointPlacement>:标注定位为点。

    • <se:AnchorPoint>:定义标注的锚点。

      • <se:AnchorPointX>:锚点X坐标为0。

      • <se:AnchorPointY>:锚点Y坐标为0.5。

  • <se:Fill>:定义标注文本的颜色。

    • <se:SvgParameter name="fill">:文本颜色为黑色(#000000)。

  • <se:VendorOption name="maxDisplacement">:定义标注的最大偏移量为1像素,用于避免标注重叠。

    3. 关键点分析

    3.1 多边形样式

  • 多边形填充为浅灰色,边框为红色虚线,这种样式通常用于突出显示区域边界。

  • 虚线模式“4 2”表示边框由4像素的实线和2像素的间隔交替组成。

  • 标注内容为矢量数据的“Name”字段,字体为“宋体”,大小为13像素,颜色为黑色。

  • 文件中明确指定了字体为“宋体”,这是常见的中文字体,但在某些系统或环境中可能不可用。如果字体不可用,可能会导致标注乱码。

  • 标注的锚点设置为(0, 0.5),表示标注文本的左中点对齐。

  • 最大偏移量为1像素,用于避免标注重叠。

2、最初的效果

        该SLD文件定义了一个矢量图层的样式规则,包括多边形的填充和边框样式,以及文本标注的字体、大小、颜色和定位方式。文件中特别指定了“宋体”作为标注字体,但需要注意字体的可用性问题,以避免中文标注乱码。通过合理配置SLD文件和利用Geotools的字体解析功能,可以确保标注内容在不同环境下的正确显示。正常情况,我们将这个sld文件加载到程序中对矢量数据进行渲染,你会发现问题还是出现了,在生成的图片中我们预期的乡镇名称并没有成功的加载,只是如下图所示:

        那么究竟是什么原因导致了上述的问题呢?在本文的下一个小节中会进行具体的讲解。 

二、问题修复

        本节将对上一节出现的中文标注在SLD样式渲染下无法正常展示的问题进行解决。以及讲解在中文标注下有哪些字体可以选择。导致上图中出现中文字体无法展示的原因就是字体的原因,所以在渲染时无法正常展示。跟我们常见的服务器端乱码的结果差不多。

1、还是字符编码

        首先来看下原来的字符编码是如何指定的,在之前的添加矢量图层的方法中。关键代码如下,在代码中,我们使用申明的方式直接指定了字符集编码为UTF-8:

/**
* 添加shp文件
* @param shpPath
*/
@SuppressWarnings("deprecation")
public void addShapeLayer(String shpPath, String sldPath) {
    try {
		File file = new File(shpPath);
		ShapefileDataStore shpDataStore = null;
		shpDataStore = new ShapefileDataStore(file.toURL());
		Charset charset = Charset.forName("UTF-8");
		shpDataStore.setCharset(charset);
		//xxx 加载SLD样式
		this.map.addLayer(layer);
	} catch (Exception e) {
		e.printStackTrace();
	}
}

        在创建shp文件时,通常我们会创建dbf文件用来保存属性文件。同时在属性文件中,我们会指定属性字段的字符集。 通常发生中文无法解析的情况就是设置的字符集编码不对。我们可以在QGIS或者Arcgis中来查看当前矢量文件的字符集。可以发现,真实文件的字符集是GB2312,因此基本可以断定是字符集的问题,在知晓了原理之后,就只需要设置新的字符集编码即可:

// 设置编码,这里格外要注意,否则会造成中文标注失败的情况
//Charset charset = Charset.forName("UTF-8");
Charset charset = Charset.forName("GB2312");

        重新生成,发现乡镇的名称可以正常展示,如下图所示:

 

        局部放大后给大家展示:

        可以直观的看到,中文标注正常。可以正确的展示。 

2、如何选择可用的字体

        除了字符编码可能会引起这种问题,还有一种情况是大家都能够想到的,就是操作系统的字体编码问题。如果设置的字体不是系统支持的,那肯定也是有问题,在本文的第一部分就说明了文章采用的字体是宋体,接下来我们来试试其它的字体,比如:华文行楷,sld中的样式标注部分调整为:

<se:Font>
    <se:SvgParameter name="font-family">华文行楷</se:SvgParameter>
    <se:SvgParameter name="font-size">13</se:SvgParameter>
</se:Font>

        在此运行程序,在控制台中它会报错,如下所示,表示无法加载字体库:

三月 31, 2025 11:28:18 下午 org.geotools.renderer.style.FontCache loadFromUrl
信息: null input stream, could not load the font

        在中文情况下,虽然无法加载,但是还是正常展示,如果切换成另外一种字符,如:

<se:SvgParameter name="font-family">MoolBoran</se:SvgParameter>

        此时的效果就完全是乱码了,如下图:

        所以字体的选择至关重要。 

 3、如何查看支持的字体库

        要想在程序中查看系统中支持的字体库,可以使用下面的方法,代码如下:

System.out.println("******************************");
Set<String> availableFonts = FontCache.getDefaultInstance().getAvailableFonts();
System.out.println(availableFonts.size());
for (String font : availableFonts) {
	System.out.println(font);
}

        其中FontCache类是org.geotools.renderer.style.FontCache这个类。在应用程序中输出以下信息:

         通过以上的输出就能确定当前系统环境支持哪些字体库。

三、总结

        以上就是本文的主要内容, 本文的目标是通过Geotools和SLD技术,解决矢量中文标注中的乱码问题,并解析可用字体,以实现高效、准确的矢量数据可视化。

        通过Geotools结合SLD技术,可以有效解决矢量中文标注中的乱码问题,并解析可用字体,确保标注内容的正确显示。这一解决方案不仅提高了矢量数据的可视化效果,还增强了系统的兼容性和用户体验。未来,随着GIS技术的不断发展,矢量数据标注技术也将不断创新,为地理信息的展示和应用提供更强大的支持。行文仓促,难免有许多不足之处,如有不足,在此恳请各位专家博主在评论区不吝留言指出,不胜感激。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2325715.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Python与CATIA V5的斐波那契螺旋线自动化建模技术解析

引言 斐波那契螺旋线&#xff08;Fibonacci Spiral&#xff09;作为自然界广泛存在的黄金比例曲线&#xff0c;在工业设计、产品造型、机械工程等领域具有重要应用价值。本文将以Python控制CATIA V5进行参数化建模为例&#xff0c;深入解析三维CAD环境中复杂数学曲线的自动化生…

动态规划(11.按摩师)

题目链接&#xff1a;面试题 17.16. 按摩师 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a; 状态表示&#xff1a; 对于简单的线性 dp &#xff0c;我们可以⽤「经验 题⽬要求」来定义状态表⽰&#xff1a; 以某个位置为结尾&#xff0c;巴拉巴拉&#xff1b;…

CentOS下安装Docker,Docker下安装JDK\MYSQL\REDIS\NGINX

先用VM安装好Centos8.5&#xff0c;可以选择安装迷你版&#xff0c;我安装的是UI版。 然后用MobaXterm_Portable_v23.0_cn连上去&#xff0c;互访成功就可以往下操作。 1. 修改文件&#xff1a;就是要把之前的mirror替换成现在的vault cd /etc/yum.repos.d/sed -i s/mirrorl…

demo.launch(inbrowser=True, share=True)无法生成共享网址

Gradio 的共享功能无法正常工作&#xff0c;原因是缺少一个名为 frpc_windows_amd64_v0.3 用到代码 app.demo.launch(show_errorTrue, inbrowserTrue, shareTrue) show_errorTrue&#xff1a;这个参数的作用是当应用在启动过程中出现错误时&#xff0c;会显示错误信息。这对于调…

翻译: 人工智能如何让世界变得更美好二

Basic assumptions and framework 基本假设和框架 To make this whole essay more precise and grounded, it’s helpful to specify clearly what we mean by powerful AI (i.e. the threshold at which the 5-10 year clock starts counting), as well as laying out a fram…

【vue】editor富文本输入全英文,谷歌浏览器:元素不会自动换行bug

【vue】editor富文本输入全英文&#xff0c;谷歌浏览器&#xff1a;元素不会自动换行bug 解决方案&#xff1a;给元素一个宽度 100% .editor {width: 100%; }

# OpenCV实现人脸与微笑检测:从图像到视频的实战应用

OpenCV实现人脸与微笑检测&#xff1a;从图像到视频的实战应用 在计算机视觉领域&#xff0c;人脸检测和微笑检测是两个非常有趣且实用的任务。它们广泛应用于智能监控、社交媒体分析、人机交互等多个场景。本文将通过两个代码示例&#xff0c;详细介绍如何使用OpenCV实现人脸…

Kubernetes可视化面板——KubePi(Kubernetes Visualization Panel - kubepi)

Kubernetes可视化管理面板——KubePi 在云计算和容器化的大潮下&#xff0c;Kubernetes 已成为管理容器集群的事实标准。然而&#xff0c;面对复杂的集群管理和运维工作&#xff0c;一个直观、易用的可视化工具显得至关重要。KubePi 正是为此而生——一款专为简化 Kubernetes …

【区块链安全 | 第二十三篇】单位和全局可用变量(一)

文章目录 单位和全局可用变量&#xff08;Units and Globally Available Variables&#xff09;以太单位&#xff08;Ether Units&#xff09;时间单位&#xff08;Time Units&#xff09;保留关键字 单位和全局可用变量&#xff08;Units and Globally Available Variables&am…

权重参数矩阵

目录 1. 权重参数矩阵的定义与作用 2. 权重矩阵的初始化与训练 3. 权重矩阵的解读与分析 (1) 可视化权重分布 (2) 统计指标分析 4. 权重矩阵的常见问题与优化 (1) 过拟合与欠拟合 (2) 梯度问题 (3) 权重对称性问题 5. 实际应用示例 案例1&#xff1a;全连接网络中的…

【现代深度学习技术】现代卷积神经网络06:残差网络(ResNet)

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈PyTorch深度学习 ⌋ ⌋ ⌋ 深度学习 (DL, Deep Learning) 特指基于深层神经网络模型和方法的机器学习。它是在统计机器学习、人工神经网络等算法模型基础上&#xff0c;结合当代大数据和大算力的发展而发展出来的。深度学习最重…

《异常检测——从经典算法到深度学习》30. 在线服务系统中重复故障的可操作和可解释的故障定位

《异常检测——从经典算法到深度学习》 0 概论1 基于隔离森林的异常检测算法 2 基于LOF的异常检测算法3 基于One-Class SVM的异常检测算法4 基于高斯概率密度异常检测算法5 Opprentice——异常检测经典算法最终篇6 基于重构概率的 VAE 异常检测7 基于条件VAE异常检测8 Donut: …

nut-ui下拉选的实现方式:nut-menu

nut-ui下拉选的实现方式&#xff1a;nut-menu 官方文档&#xff1a;https://nutui.jd.com/h5/vue/4x/#/zh-CN/component/menu 案例截图&#xff1a; nut-tab选项卡组件实现&#xff1a; 官方组件地址&#xff1a;https://nutui.jd.com/h5/vue/4x/#/zh-CN/component/tabs nut…

鸿蒙NEXT小游戏开发:扫雷

1. 引言 本文将介绍如何使用鸿蒙NEXT框架开发一个简单的扫雷游戏。通过本案例&#xff0c;您将学习到如何利用鸿蒙NEXT的组件化特性、状态管理以及用户交互设计来构建一个完整的游戏应用。 2. 环境准备 电脑系统&#xff1a;windows 10 工程版本&#xff1a;API 12 真机&…

LangChain4j 入门(二)

LangChain 整合 SpringBoot 下述代码均使用 阿里云百炼平台 提供的模型。 创建项目&#xff0c;引入依赖 通过 IDEA 创建 SpringBoot 项目&#xff0c;并引入 Spring Web 依赖&#xff0c;SpringBoot 推荐使用 3.x 版本。 引入 LangChain4j 和 WebFlux 依赖 <!--阿里云 D…

npm i 失败

当npm i 失败 且提示下面的错误 尝试降低npm 的版本 npm install npm6.14.15 -g

音视频基础(音视频的录制和播放原理)

文章目录 一、录制原理**1. 音视频数据解析****2. 音频处理流程****3. 视频处理流程****4. 同步控制****5. 关键技术点****总结** 二、播放原理**1. 音视频数据解析****2. 音频处理流程****3. 视频处理流程****4. 同步控制****5. 关键技术点****总结** 一、录制原理 这张图展示…

回溯(子集型):分割回文串

一、多维递归 -> 回溯 1.1&#xff1a;17. 电话号码的字母组合(力扣hot100&#xff09; 代码&#xff1a; mapping ["","", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv&qu…

2022年蓝桥杯第十三届CC++大学B组真题及代码

目录 1A&#xff1a;九进制转十进制 2B&#xff1a;顺子日期&#xff08;存在争议&#xff09; 3C&#xff1a;刷题统计 解析代码&#xff08;模拟&#xff09; 4D&#xff1a;修剪灌木 解析代码&#xff08;找规律&#xff09; 5E&#xff1a;X进制减法 解析代码1&…

1.oracle修改配置文件

1.找到oracle的安装路径 D:\app\baozi\product\11.2.0\dbhome_1\NETWORK\ADMIN &#xff0c;修改下面的两个文件。如果提示没有权限&#xff0c;可以先把这两个文件复制到桌面&#xff0c;修改完后&#xff0c;在复制回来。 2.查看自己电脑的主机名&#xff0c; 右击 - 此电脑 …