在JavaFx中使用StyledLayerDescriptor(SLD)1.0和1.1版本进行地图美化实践

news2024/11/14 14:00:06

目录

前言

一、最开始的初始世界

1、默认的样式

二、注册事件让地图实现交互

1、绑定事件及注册处理逻辑

三、地图美化,让地图生动起来

1、POM.xml中引入相应的依赖

2、GeoTools加载不同版本的SLD问题

 3、加载1.1.0版本的SLD

四、总结


前言

        俗话说,人靠衣装马靠鞍。在GIS的世界中同样如此,一幅精美的地图,除了时空地理数据本身的内容和质量外,使用美化样式就是如虎添翼,给地图增加了吸引力。制作精良的地图,绝对离不开它的化妆师,即StyledLayerDescriptor(以下简称SLD)。SLD是OGC关于地图样式的规范,牵涉到OGC的制图标准,其实可以有很多内容可以讲。如果熟悉Web开发的同学,一定对CSS或者LESS很熟悉,你可以把SLD当成地图界的CSS。在Web2.0的界面中,我们的界面做得如此精美,其实就是CSS设计得好,包括合理的配色,文字的大小,布局的协调性等等。

        本文结合之前做的一个JavaFX案例讲解,首先分析了原来可视化效果的不足,包括地图没有进行美化、不支持鼠标的缩放和拖动、不支持文本标注的展示等等。本文将重点讲解如何在JavaFx中进行地图美化的开发,同时对JavaFX进行扩展,支持地图的缩放等操作。在讲解SLD时,不仅讲解如何创建模式样式,同时讲解在Geotools中,如何加载SLD1.0.0的版本和SLD1.1.0的版本,通过实例代码的形式给大家展示如何如正确的解析并展示矢量数据。如果您也在学习SLD的相关知识,不妨来这篇博客指导一二。通过本文,相信您可以更加了解GeoTools,对SLD的常规用法掌握更加透彻。

一、最开始的初始世界

        还记得最开始的初始世界吗?全球的空间数据展示出来,地图是黑白的。没有明显的填充颜色。并不像上面的地图表现的那么亮眼(大家也可以看到填充了颜色的全球世界还是非常美丽的)。用一张照片给大家看下最开始的样子。

        除了它的样式不太好看,其实它还有很多缺点,比如地图不能拖动,不能使用鼠标的滚轮进行放大和缩小。不能按照各个大洲来展示国家信息(比如使用不同的颜色来进行标记),并且在地图上还能进行国家名称的标注,在小层级的时候可以不用展示,只有地图放大到指定层级才会展示。 

1、默认的样式

        不知道大家还有没有印象,在前面的地图界面展示中,我们使用的都是自带的最简单的样式。可以看看下面的代码:

private void initMap() {
	try {
		FileDataStore store = FileDataStoreFinder
		.getDataStore(this.getClass().getClassLoader().getResource("maps/countries.shp"));
		SimpleFeatureSource featureSource = store.getFeatureSource();
		map = new MapContent();
		map.setTitle("Quickstart");
		Style style = SLD.createSimpleStyle(featureSource.getSchema());
		FeatureLayer layer = new FeatureLayer(featureSource, style);
		map.addLayer(layer);
		map.getViewport().setScreenArea(new Rectangle((int) canvas.getWidth(), (int) canvas.getHeight()));
	} catch (IOException e) {
		e.printStackTrace();
	}
}

        在这里,Style style = SLD.createSimpleStyle(featureSource.getSchema());这里的样式是根据空间数据的不同类型自动生成的。下面是这个类的源码(部分):

        可以看到,这里其实是通过要素的类型,比如线对象、面对象、点对象等进行样式的生成,而这里的颜色其实也是设置得非常粗狂,直接就是fillColor = Color.BLACK,都是黑色信息。 关于如何调整样式,这个下文再进行深入讲解。

二、注册事件让地图实现交互

        在初版的功能展示当中,地图是没有办法进行事件交互的,只有一个静态的界面的展示。这一小节,我们来讲解一下如何进行地图事件的注册,让地图和鼠标的交互绑定起来,实现缩放和拖拽的功能。

1、绑定事件及注册处理逻辑

        不管是桌面应用还是Web的应用,如何支持外设设备的接入和响应他们的指令。通常都是与一个事件模型分不开的,很多动作的触发都是使用事件机制来驱动。在JavaFx当中进行地图控制和缩放控制也是采用事件模式来实现的。在进行地图绘制的时候,注册以下的时间,关键代码如下所示:

/*
*initial for mouse event 
*/
private void initEvent() {
/*
* setting the original coordinate
*/
canvas.addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {

	@Override
	public void handle(MouseEvent e) {
		baseDrageX = e.getSceneX();
		baseDrageY = e.getSceneY();
		e.consume();
	}
});
/*
* translate according to the mouse drag
*/
canvas.addEventHandler(MouseEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
	@Override
	public void handle(MouseEvent e) {
		double difX = e.getSceneX() - baseDrageX;
		double difY = e.getSceneY() - baseDrageY;
		baseDrageX = e.getSceneX();
		baseDrageY = e.getSceneY();
		DirectPosition2D newPos = new DirectPosition2D(difX, difY);
		DirectPosition2D result = new DirectPosition2D();
		map.getViewport().getScreenToWorld().transform(newPos, result);
		ReferencedEnvelope env = new ReferencedEnvelope(map.getViewport().getBounds());
		env.translate(env.getMinimum(0) - result.x, env.getMaximum(1) - result.y);
			doSetDisplayArea(env);
			e.consume();
		}
	});
/*
* double clicks to restore to original map
*/
canvas.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
	@Override
	public void handle(MouseEvent t) {
		if (t.getClickCount() > 1) {
			doSetDisplayArea(map.getMaxBounds());
		}
		t.consume();
	}
});
/*
 * scroll for zoom in and out
*/
canvas.addEventHandler(ScrollEvent.SCROLL, new EventHandler<ScrollEvent>() {

	@Override
	public void handle(ScrollEvent e) {
		ReferencedEnvelope envelope = map.getViewport().getBounds();
		double percent = e.getDeltaY() / canvas.getWidth();
		double width = envelope.getWidth();
		double height = envelope.getHeight();
		double deltaW = width * percent;
		double deltaH = height * percent;
		envelope.expandBy(deltaW, deltaH);
		doSetDisplayArea(envelope);
			e.consume();
		}
	});
}

        在加上以上的功能后,地图可以实现缩放和拖动了。基本达到我们控制的目标。

三、地图美化,让地图生动起来

        这里说的美化底图,其实也是比较有限的美化哈。个人的配色和搭配也是一般般。这里用生动一词想表达的是通过SLD可以让地图美观,希望大家在使用的时候发挥主观能动性,能实现真正的美化地图的外观。本节将主要讲解如何自己实现加载SLD1.0.0和SLD1.1.0两个版本的样式。很多博客没有讲清楚如何正确的加载样式,这里给各位朋友讲清楚。

1、POM.xml中引入相应的依赖

        在我们的案例中,我们使用的GeoTools的相关组件,与一般的展示不一样,这里我们要引入一些处理样式的组件。在下面的Pom.xml中定义好依赖的资源包。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.ldj.tutorial</groupId>
	<artifactId>geotools-fx</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<geotools.version>28.2</geotools.version>
		<fxgraphics2d.version>1.3</fxgraphics2d.version>
	</properties>
	<repositories>
		<!--从22.x后geotools由OSGeo管理-->
        <repository>
            <id>osgeo</id>
            <name>OSGeo Release Repository</name>
            <url>https://repo.osgeo.org/repository/release/</url>
            <snapshots><enabled>false</enabled></snapshots>
            <releases><enabled>true</enabled></releases>
        </repository>
        <repository>
            <id>osgeo-snapshot</id>
            <name>OSGeo Snapshot Repository</name>
            <url>https://repo.osgeo.org/repository/snapshot/</url>
            <snapshots><enabled>true</enabled></snapshots>
            <releases><enabled>false</enabled></releases>
        </repository>
        <repository>
            <id>GeoSolutions</id>
            <url>http://maven.geo-solutions.it/</url>
        </repository>
	</repositories>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.geotools</groupId>
			<artifactId>gt-shapefile</artifactId>
			<version>${geotools.version}</version>
		</dependency>
		<dependency>
			<groupId>org.geotools</groupId>
			<artifactId>gt-swing</artifactId>
			<version>${geotools.version}</version>
		</dependency>
		<dependency>
			<groupId>org.geotools</groupId>
			<artifactId>gt-main</artifactId>
			<version>${geotools.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.geotools.xsd/gt-xsd-sld -->
		<dependency>
		    <groupId>org.geotools.xsd</groupId>
		    <artifactId>gt-xsd-sld</artifactId>
		    <version>${geotools.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.geotools.xsd/gt-xsd-core -->
		<dependency>
		    <groupId>org.geotools.xsd</groupId>
		    <artifactId>gt-xsd-core</artifactId>
		   	<version>${geotools.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.geotools/gt-xml -->
		<dependency>
		    <groupId>org.geotools</groupId>
		    <artifactId>gt-xml</artifactId>
		    <version>${geotools.version}</version>
		</dependency>
		<dependency>
			<groupId>org.jfree</groupId>
			<artifactId>fxgraphics2d</artifactId>
			<version>1.3</version>
		</dependency>
	</dependencies>
</project>

2、GeoTools加载不同版本的SLD问题

        关于SLD的原文说明可以看如下的介绍,SLD - Introduction,

Geospatial data (vector and raster) have no intrinsic visual component. In order to see data, it must be styled. Styling specifies color, thickness, and other visible attributes used to render data on a map. A WMS provides a set of style options for each data set; however these are preconfigured by the server, and the user cannot create, inspect, modify a style. The Styled Layer Descriptor (SLD) is a standard that enables an application to configure in an XML document how to properly portray layers and legends in a WMS. It uses Symbology Ending (SE) to specify styling of features and coverages. The SLD Profile of WMS enhances a WMS with additional operations to support styling of features from WFS and coverages from WCS.

History

Version number

Release date

Summary of Changes

1.1

2007-06-29

“1.0 specification was split into SE and SLD, more functionality was added”

1.0

2002-09-19

 可以看到SLD也有两个版本,2002年9月19发布第一个版本。在时隔五年之后发布了1.1.0版本。这两个差别的xml语法定法差别很大,同时比如在GeoServer中一些版本对1.1.0支持得不够友好。下面给出一个1.0.0的SLD样式定义文件:

<?xml version="1.0" encoding="UTF-8"?>
<StyledLayerDescriptor version="1.0.0"
    xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd"
    xmlns="http://www.opengis.net/sld"
    xmlns:ogc="http://www.opengis.net/ogc"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <NamedLayer>
    <Name>countries</Name>
    <UserStyle>
      <Title>Simple Polygon</Title>
      <FeatureTypeStyle>
        <Rule>
          <PolygonSymbolizer>
            <Fill>
              <CssParameter name="fill">#21e91e</CssParameter>
            </Fill>
            <Stroke>
              <!-- <CssParameter name="stroke">#0000FF</CssParameter> -->
              <CssParameter name="stroke">#3f51b5</CssParameter>
              <CssParameter name="stroke-width">1</CssParameter>
            </Stroke>
          </PolygonSymbolizer>
        </Rule>
      </FeatureTypeStyle>
    </UserStyle>
   </NamedLayer>
</StyledLayerDescriptor>

        在这里我们设置了边框颜色和填充颜色,让全球世界范围看起来好看了一丢丢,主功能如下:

        在设置了颜色之后,世界变得艳丽了许多,也明亮了许多。

 3、加载1.1.0版本的SLD

        上面的1.0版本的SLD是通过官方提供的样式进行生成的,比较简单。大家知道,如果大家使用的是QGIS的话,一定会用到里面的样式和标绘功能,使用QGIS进行地图标绘完成之后,可以将标绘的样式导出为SLD,可以部分直接放在GeoServer中使用。也可以放到JavaFx程序中进行使用。我使用的QGIS3.X的版本,其生成的SLD都是1.1版本的。因此我们需要实现兼容两种不同版本的SLD。

public Style createStyleFromSld(String uri)
	throws XPathExpressionException, IOException, SAXException, ParserConfigurationException {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		Document xmlDocument = db.parse(uri);

		XPath xPath = XPathFactory.newInstance().newXPath();
		String version = xPath.compile("/StyledLayerDescriptor/@version").evaluate(xmlDocument);
		Configuration sldConf;
		if (version != null && version.startsWith("1.1")) {
			sldConf = new org.geotools.sld.v1_1.SLDConfiguration();
		} else {
			sldConf = new org.geotools.sld.SLDConfiguration();
		}
		StyledLayerDescriptor sld = (StyledLayerDescriptor) new org.geotools.xsd.DOMParser(sldConf, xmlDocument)
				.parse();
		NamedLayer l = (NamedLayer) sld.getStyledLayers()[0];
		Style style = l.getStyles()[0];
		return style;
	}

        然后我们使用QGIS进行标绘后,将样式导出为SLD,在JavaFx中加载这个导出的SLD样式文件。为了实现页面的刷新,我们需要定义个后台线程,有变化后通过线程来更新JavaFx组件。线程的核心代码如下:

private static final double PAINT_HZ = 50.0;

private void initPaintThread() {
	ScheduledService<Boolean> svc = new ScheduledService<Boolean>() {
		protected Task<Boolean> createTask() {
			return new Task<Boolean>() {
				protected Boolean call() {
					Platform.runLater(() -> {
						drawMap(gc);
					});
					return true;
				}
			};
		}
	};
	svc.setPeriod(Duration.millis(1000.0 / PAINT_HZ));
	svc.start();
}

        在1.1.0版本的SLD中,我们将按照不同的大洲进行分类,比如亚洲和非洲的颜色就不一样,同时定义了国家标注的大小层级。这里直接给出实例文件,关于SLD的样式文件内容,以后可以专门进行讲解。

<?xml version="1.0" encoding="UTF-8"?>
<StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:se="http://www.opengis.net/se" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc">
  <NamedLayer>
    <se:Name>countries</se:Name>
    <UserStyle>
      <se:Name>countries</se:Name>
      <se:FeatureTypeStyle>
        <se:Rule>
          <se:Name>Africa</se:Name>
          <se:Description>
            <se:Title>Africa</se:Title>
          </se:Description>
          <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
            <ogc:PropertyIsEqualTo>
              <ogc:PropertyName>CONTINENT</ogc:PropertyName>
              <ogc:Literal>Africa</ogc:Literal>
            </ogc:PropertyIsEqualTo>
          </ogc:Filter>
          <se:PolygonSymbolizer>
            <se:Fill>
              <se:SvgParameter name="fill">#df77c5</se:SvgParameter>
            </se:Fill>
            <se:Stroke>
              <se:SvgParameter name="stroke">#232323</se:SvgParameter>
              <se:SvgParameter name="stroke-width">1</se:SvgParameter>
              <se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter>
            </se:Stroke>
          </se:PolygonSymbolizer>
        </se:Rule>
        <se:Rule>
          <se:Name>Antartica</se:Name>
          <se:Description>
            <se:Title>Antartica</se:Title>
          </se:Description>
          <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
            <ogc:PropertyIsEqualTo>
              <ogc:PropertyName>CONTINENT</ogc:PropertyName>
              <ogc:Literal>Antartica</ogc:Literal>
            </ogc:PropertyIsEqualTo>
          </ogc:Filter>
          <se:PolygonSymbolizer>
            <se:Fill>
              <se:SvgParameter name="fill">#91cb5a</se:SvgParameter>
            </se:Fill>
            <se:Stroke>
              <se:SvgParameter name="stroke">#232323</se:SvgParameter>
              <se:SvgParameter name="stroke-width">1</se:SvgParameter>
              <se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter>
            </se:Stroke>
          </se:PolygonSymbolizer>
        </se:Rule>
        <se:Rule>
          <se:Name>Asia</se:Name>
          <se:Description>
            <se:Title>Asia</se:Title>
          </se:Description>
          <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
            <ogc:PropertyIsEqualTo>
              <ogc:PropertyName>CONTINENT</ogc:PropertyName>
              <ogc:Literal>Asia</ogc:Literal>
            </ogc:PropertyIsEqualTo>
          </ogc:Filter>
          <se:PolygonSymbolizer>
            <se:Fill>
              <se:SvgParameter name="fill">#cf413e</se:SvgParameter>
            </se:Fill>
            <se:Stroke>
              <se:SvgParameter name="stroke">#232323</se:SvgParameter>
              <se:SvgParameter name="stroke-width">1</se:SvgParameter>
              <se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter>
            </se:Stroke>
          </se:PolygonSymbolizer>
        </se:Rule>
        <se:Rule>
          <se:Name>Europe</se:Name>
          <se:Description>
            <se:Title>Europe</se:Title>
          </se:Description>
          <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
            <ogc:PropertyIsEqualTo>
              <ogc:PropertyName>CONTINENT</ogc:PropertyName>
              <ogc:Literal>Europe</ogc:Literal>
            </ogc:PropertyIsEqualTo>
          </ogc:Filter>
          <se:PolygonSymbolizer>
            <se:Fill>
              <se:SvgParameter name="fill">#6aedef</se:SvgParameter>
            </se:Fill>
            <se:Stroke>
              <se:SvgParameter name="stroke">#232323</se:SvgParameter>
              <se:SvgParameter name="stroke-width">1</se:SvgParameter>
              <se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter>
            </se:Stroke>
          </se:PolygonSymbolizer>
        </se:Rule>
        <se:Rule>
          <se:Name>North America</se:Name>
          <se:Description>
            <se:Title>North America</se:Title>
          </se:Description>
          <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
            <ogc:PropertyIsEqualTo>
              <ogc:PropertyName>CONTINENT</ogc:PropertyName>
              <ogc:Literal>North America</ogc:Literal>
            </ogc:PropertyIsEqualTo>
          </ogc:Filter>
          <se:PolygonSymbolizer>
            <se:Fill>
              <se:SvgParameter name="fill">#4c71e8</se:SvgParameter>
            </se:Fill>
            <se:Stroke>
              <se:SvgParameter name="stroke">#232323</se:SvgParameter>
              <se:SvgParameter name="stroke-width">1</se:SvgParameter>
              <se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter>
            </se:Stroke>
          </se:PolygonSymbolizer>
        </se:Rule>
        <se:Rule>
          <se:Name>Oceania</se:Name>
          <se:Description>
            <se:Title>Oceania</se:Title>
          </se:Description>
          <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
            <ogc:PropertyIsEqualTo>
              <ogc:PropertyName>CONTINENT</ogc:PropertyName>
              <ogc:Literal>Oceania</ogc:Literal>
            </ogc:PropertyIsEqualTo>
          </ogc:Filter>
          <se:PolygonSymbolizer>
            <se:Fill>
              <se:SvgParameter name="fill">#dec05e</se:SvgParameter>
            </se:Fill>
            <se:Stroke>
              <se:SvgParameter name="stroke">#232323</se:SvgParameter>
              <se:SvgParameter name="stroke-width">1</se:SvgParameter>
              <se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter>
            </se:Stroke>
          </se:PolygonSymbolizer>
        </se:Rule>
        <se:Rule>
          <se:Name>South America</se:Name>
          <se:Description>
            <se:Title>South America</se:Title>
          </se:Description>
          <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
            <ogc:PropertyIsEqualTo>
              <ogc:PropertyName>CONTINENT</ogc:PropertyName>
              <ogc:Literal>South America</ogc:Literal>
            </ogc:PropertyIsEqualTo>
          </ogc:Filter>
          <se:PolygonSymbolizer>
            <se:Fill>
              <se:SvgParameter name="fill">#39c960</se:SvgParameter>
            </se:Fill>
            <se:Stroke>
              <se:SvgParameter name="stroke">#232323</se:SvgParameter>
              <se:SvgParameter name="stroke-width">1</se:SvgParameter>
              <se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter>
            </se:Stroke>
          </se:PolygonSymbolizer>
        </se:Rule>
        <se:Rule>
          <se:Name></se:Name>
          <se:Description>
            <se:Title>CONTINENT is ''</se:Title>
          </se:Description>
          <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
            <ogc:Or>
              <ogc:PropertyIsEqualTo>
                <ogc:PropertyName>CONTINENT</ogc:PropertyName>
                <ogc:Literal></ogc:Literal>
              </ogc:PropertyIsEqualTo>
              <ogc:PropertyIsNull>
                <ogc:PropertyName>CONTINENT</ogc:PropertyName>
              </ogc:PropertyIsNull>
            </ogc:Or>
          </ogc:Filter>
          <se:PolygonSymbolizer>
            <se:Fill>
              <se:SvgParameter name="fill">#7a2aca</se:SvgParameter>
            </se:Fill>
            <se:Stroke>
              <se:SvgParameter name="stroke">#232323</se:SvgParameter>
              <se:SvgParameter name="stroke-width">1</se:SvgParameter>
              <se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter>
            </se:Stroke>
          </se:PolygonSymbolizer>
        </se:Rule>
        <se:Rule>
          <se:MinScaleDenominator>25000</se:MinScaleDenominator>
          <se:MaxScaleDenominator>124672208</se:MaxScaleDenominator>
          <se:TextSymbolizer>
            <se:Label>
              <ogc:PropertyName>NAME</ogc:PropertyName>
            </se:Label>
            <se:Font>
              <se:SvgParameter name="font-family">SimSun</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>

        经过以上的定义,基本实现我们刚开始的业务需求。实现的功能界面效果如下:

四、总结

        以上就是本文的主要内容,本文结合之前做的一个JavaFX案例讲解,首先分析了原来可视化效果的不足,包括地图没有进行美化、不支持鼠标的缩放和拖动、不支持文本标注的展示等等。本文将重点讲解如何在JavaFx中进行地图美化的开发,同时对JavaFX进行扩展,支持地图的缩放等操作。在讲解SLD时,不仅讲解如何创建模式样式,同时讲解在Geotools中,如何加载SLD1.0.0的版本和SLD1.1.0的版本,通过实例代码的形式给大家展示如何如正确的解析并展示矢量数据。行文仓促,定有不足之处,欢迎各位专家朋友在评论区留下真知灼见,不胜感激。

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

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

相关文章

超简单理解LSTM和GRU模型

目录 参考资料 RNN在反向传播时容易遭受梯度消失的问题&#xff0c;而梯度是用于更新神经网络权重的关键因子&#xff0c;梯度消失描述的是梯度在时间序列反向传播中逐渐减小的情况。 若梯度过小&#xff0c;它对于网络的学习贡献甚微。结果是&#xff0c;在RNN中&#xff0c;梯…

成功的秘诀:客户推荐推动 SaaS 成功的4个原因

在竞争激烈的SaaS市场中&#xff0c;脱颖而出并非易事。客户推荐合作伙伴关系正是这样一种强大的营销渠道&#xff0c;它利用口碑传播的力量&#xff0c;将满意的客户转变为品牌倡导者&#xff0c;从而显著提升品牌信誉和市场影响力。 您的 SaaS 品牌应该接受客户推荐营销的4 …

进 程

1.进程&#xff1a;进行中的程序。 微观串行&#xff0c;宏观并行。 程序的一次执行过程 进程是程序的一个实例 一个程序可以对应一个或多个进程。 2.为什么需要进程&#xff1f; 3.进程的组成部分&#xff1a; 进程 pcb 块 栈|堆|bss|data|text 其中&#xff1a; 家族…

车载测试与分析的利器之CANoe

连接汽车神经网络的专家 CANoe不仅是一款强大的总线分析工具&#xff0c;它还集成了仿真、标定和诊断功能&#xff0c;为汽车工程师提供了全方位的车载网络解决方案。从基础的信号监测到复杂的网络交互测试&#xff0c;CANoe凭借其灵活性和高效性&#xff0c;成为了车载测试工程…

浏览器后门:保护影子 IT 的新前线

浏览器扩展是网络犯罪分子的主要目标。这不仅仅是消费者的问题&#xff0c;也是企业对抗影子 IT 的新领域。 最终&#xff0c;扩展权限越多&#xff0c;攻击面就越大。研究表明&#xff0c;平均每个企业的生态系统中都有近 1500 个浏览器扩展程序 - 即使是一个不良插件也可能导…

线上o2o商城小程序源码系统 带完整的安装代码包以及搭建部署教程

系统概述 在数字化时代&#xff0c;线上线下融合&#xff08;O2O&#xff09;的商业模式已成为推动零售业发展的新引擎。为了满足商家快速构建高效、便捷、用户友好的电商平台需求&#xff0c;我们精心研发了一款线上O2O商城小程序源码系统。该系统不仅配备了完整的安装代码包…

面向对象编程-多态

一、多态的引入 1、先看一个问题 2、使用传统的方法类解决 class Food:nameNonedef __init__(self,name):self.namenameclass Fish(Food):passclass Bone(Food):passclass Animal:nameNonedef __init__(self,name):self.namenameclass Cat(Animal):passclass Dog(Animal):pas…

STM32F103-固件库开发-keil一些警告解决-中断机制-NVIC-简单按钮电灯流程及其代码;

1、固件库和HAL库 固件库&#xff08;Standard Peripheral Library&#xff0c;通常被称为SPL&#xff09;和HAL库&#xff08;Hardware Abstraction Layer&#xff0c;硬件抽象层&#xff09;都是STMicroelectronics&#xff08;ST&#xff09;为STM32系列微控制器提供的软件…

腾讯云AI代码助手:智能编程的新篇章,大家的代码开发伙伴

文章目录 一、前言二、开发环境介绍三、腾讯云AI代码助手使用实例1、案例一&#xff1a;代码补全2、案例二&#xff1a;代码注释和解释等3、案例三&#xff1a;与AI对话实现需求 四、获得的帮助与提升五、建议六、结语 一、前言 随着人工智能技术的飞速发展&#xff0c;其在各…

SWIPT综述

TS PS Hybrid TSPS ρ 和 α 的最优值以及确定继电器的最优位置可以最小化系统的 OP。 SWIPT CoR with non-linear EH, the hybrid protocol performs better than TSR as well as PSR protocols in terms OP. 波束成形&#xff1a;多天线 SWIPT CoR NETWORKS 多天线系统在 5…

自制神之嘴: fish-speech 容器镜像 (文本转语音 AI 大模型)

穷, 没有 N 卡 ! 穷, 没有 N 卡 ! 穷, 没有 N 卡 !! (重要的事情说 3 遍. ) 最近发现了一个很新的 AI (神经网络) 文本转语音大模型: https://speech.fish.audio/ fish-speech 可以根据输入的文本, 生成高质量的人类说话声音, 效果挺好的. fish-speech 官方已经提供了容器 (d…

2.3 不同数据库管理系统的比较与应用场景

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; 工&#x1f497;重&#x1f497;hao&#x1f497;&#xff1a;野老杂谈 ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题.…

[LitCTF 2024]浏览器也能套娃?

题目有标志SSRF SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下&#xff0c;SSRF攻击的目标是从外网无法访问的内部系统。&#xff08;正是因为它是由服务端发起的&#xff0c;所以它能够请求到与它相…

背包九讲(灵魂版)

文章目录 背包九讲[题库 - AcWing](https://www.acwing.com/problem/search/1/?search_content背包九讲&show_algorithm_tags0)01背包朴素代码一维优化代码 完全背包朴素代码一维优化代码 多重背包I 模板题代码 多重背包 II 二进制优化代码 多重背包 III 单调队列优化代码…

[算法题]01 矩阵

题目链接: 01 矩阵 多源BFS类型题, 即给定多个起点, 判断从哪个起点走到终点距离最短, 一般解题思路为将所有起点看成一个"起点", 由此"起点"做bfs得到题解, 实际代码编写将所有起点都入队列, 每次都对所有起点做一层扩展. 题解思路: 从1往0处走寻找最短…

kali-linux 常用命令大集合(目录、文件查看与编辑,登录、电源、帮助等相关命令详解)

目录 目录查看-ls 帮助命令 帮助命令&#xff1a;whatis 帮助命令&#xff1a;help 帮助命令&#xff1a;man 帮助命令&#xff1a;info 登录命令 登录命令&#xff1a;login 登录命令&#xff1a;last 登录命令&#xff1a;exit 切换用户&#xff1a;su/sudo 命令-…

嵌入式学习day17(顺序表)

大纲 线性表是最基本、最简单、也是最常用的一种数据结构&#xff0c;可以存储逻辑关系为线性的数据。线性表&#xff08;linear list&#xff09;是数据结构的一种&#xff0c;一个线性表是n个具有相同特性的数据元素的有限序列。 分类&#xff1a; 顺序表、单向链表、单向循环…

WhatsApp代理地址:如何成功连接WhatsApp?

所有外贸人都非常需要通过WhatsApp与客户沟通&#xff0c;简直是搞钱“生命线”&#xff01;但是&#xff0c;很多老板在后台抱怨说自己一直登不进去&#xff0c;99.99%是你网络问题。很多外贸人找的代理IP来路不明或者滥竽充数&#xff0c;要和很多人一起共用IP或者IP地址总是…

【PGCCC】使用 Postgres 递归 CTE 进行图形检索

您是否知道可以将 Postgres 用作某些用例的图形数据库&#xff1f; 假设您有如下图表&#xff1a; 我们可以在 NetworkX 中构建此图&#xff1a; 1import networkx as nx23G nx.Graph()45G.add_edges_from([6 ("A", "B"),7 ("A", "…

HAproxy 七层负载均衡调度器详解及配置

HAproxy 七层负载均衡 负载均衡技术 负载均衡&#xff08;Load Balance&#xff09;&#xff1a;一种服务&#xff0c;或基于硬件设备实现的高可用的反向代理技术&#xff0c;是指将特定的业务流量分摊给一个或多个后端的特定服务器或设备&#xff0c;实现高并发处理业务流量…