您的位置:首页 > 房产 > 家装 > 地图美化器之多种方式生成SLD样式文件

地图美化器之多种方式生成SLD样式文件

2024/10/6 8:37:08 来源:https://blog.csdn.net/yelangkingwuzuhu/article/details/142070670  浏览:    关键词:地图美化器之多种方式生成SLD样式文件

目录

前言

一、编程式生成

1、简单样式创建

二、模板生成

1、模板示例

三、外部桌面工具生成

1、SLDEditor

2、QGIS和UDig

四、GeoServer生成

1、GeoServer的样式管理器

五、总结


前言

        在Web的世界中,我们用Style的css或者less来进行页面的装饰。在地理信息的世界中,我们可以采用SLD文件来进行地图美化。跟css一样,我们可以采用多种方式来创建SLD文件,既可以使用记事本、文本编辑器等传统文本工具来进行编写,也可以采用VsCode等现代的编辑器来进行设置。

        与CSS一致,生成SLD文件的方式也有很多种。比如有代码生成法、模板生成法、外部工具创建法等等。本文即重点讲解在开发过程中,如何使用多方式来生成SLD样式文件。文章首先介绍Java中来使用代码进行编程式生成,然后介绍如何基于SLD的模板文件进行生成,其次介绍基于桌面生成工具SLDEditor和QQis来进行样式生成,最后介绍如何利用GeoServer来进行样式生成。通过不同的SLD创建方式,让您掌握不同的样式生成方式。希望本文对学习SLD的同学有所帮助。

一、编程式生成

        编程式生成具体是指使用编码的方式来创建SLD样式,以Java为例,我们使用GeoTools这个项目来进行样式的创建。这里其实可以分两种情况,第一种,使用默认的样式,比如最简单的样式,只要区分点、线、面等不同的空间数据类型等。第二种是在简单的样式上面进行扩展,进行丰富的样式信息的创建。下面分两种模式来进行说明。

1、简单样式创建

        简单的样式创建,即是最简单的生成模式,即不会进行过多的样式控制。在进行样式表达时,仅仅考虑空间对象的类型,如点、线、面。然后根据不同的空间对象类型来创建最简单的样式。在之前的GeoTools的系列教程中,我们即采用过这种实现模式。

        第一步、创建简单样式,关键代码如下所示:

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());通过SLD对象来创建默认样式。我们可以来看一下SLD具体是如何创建默认样式。

        第二步、具体样式生成。我们通过debug跟踪代码,见如下关键代码:

/*** Create a minimal style to render features of type {@code type}.** @param type the feature type* @return a new Style instance*/
public static Style createSimpleStyle(FeatureType type) {return createSimpleStyle(type, Color.BLACK);
}

          可以看到,这里需要传入空间对象的类型,也就是FeatureType,对应前面我们所说的点、线、面等不同的类型。根据不同类型的对象来进行相应样式的创建。

public static Style createSimpleStyle(FeatureType type, Color color) {GeometryDescriptor desc = type.getGeometryDescriptor();Class<?> clazz = desc.getType().getBinding();Color fillColor = null;if (Polygon.class.isAssignableFrom(clazz) || MultiPolygon.class.isAssignableFrom(clazz)) {if (color.equals(Color.BLACK)) {fillColor = null;} else {fillColor = color;}return createPolygonStyle(color, fillColor, 0.5f);} else if (LineString.class.isAssignableFrom(clazz)|| MultiLineString.class.isAssignableFrom(clazz)) {return createLineStyle(color, 1.0f);} else if (Point.class.isAssignableFrom(clazz)|| MultiPoint.class.isAssignableFrom(clazz)) {if (color.equals(Color.BLACK)) {fillColor = null;} else {fillColor = color;}return createPointStyle("Circle", color, fillColor, 0.5f, 3.0f);}throw new UnsupportedOperationException("No style method for " + clazz.getName());}

        如果是Polygon面数据,可以看到面数据的默认样式创建代码如下:

/*** Create a polygon style with the given colors and opacity.** @param outlineColor color of polygon outlines* @param fillColor color for the fill* @param opacity proportional opacity (0 to 1)* @return a new Style instance*/
public static Style createPolygonStyle(Color outlineColor, Color fillColor, float opacity) {Stroke stroke = sf.createStroke(ff.literal(outlineColor), ff.literal(1.0f));Fill fill = Fill.NULL;if (fillColor != null) {fill = sf.createFill(ff.literal(fillColor), ff.literal(opacity));}return wrapSymbolizers(sf.createPolygonSymbolizer(stroke, fill, null));
}
/*** Wrap one or more symbolizers into a Rule / FeatureTypeStyle / Style** @param symbolizers one or more symbolizer objects* @return a new Style instance or null if no symbolizers are provided*/public static Style wrapSymbolizers(Symbolizer... symbolizers) {if (symbolizers == null || symbolizers.length == 0) {return null;}Rule rule = sf.createRule();for (Symbolizer sym : symbolizers) {rule.symbolizers().add(sym);}FeatureTypeStyle fts = sf.createFeatureTypeStyle(rule);Style style = sf.createStyle();style.featureTypeStyles().add(fts);return style;}

        可以在上述的代码中看到,面数据主要是设置填充的信息等。这都是比较简单,尤其是凸显边界。下面来看一下线数据的默认样式信息:

/*** Create a line style with given color and line width** @param lineColor color of lines* @param width width of lines* @return a new Style instance*/
public static Style createLineStyle(Color lineColor, float width) {Stroke stroke = sf.createStroke(ff.literal(lineColor), ff.literal(width));return wrapSymbolizers(sf.createLineSymbolizer(stroke, null));
}/*** Wrap one or more symbolizers into a Rule / FeatureTypeStyle / Style** @param symbolizers one or more symbolizer objects* @return a new Style instance or null if no symbolizers are provided*/
public static Style wrapSymbolizers(Symbolizer... symbolizers) {if (symbolizers == null || symbolizers.length == 0) {return null;}Rule rule = sf.createRule();for (Symbolizer sym : symbolizers) {rule.symbolizers().add(sym);}FeatureTypeStyle fts = sf.createFeatureTypeStyle(rule);Style style = sf.createStyle();style.featureTypeStyles().add(fts);return style;
}

        最后来看一下点数据的默认样式信息如下关键代码所示:

/*** Create a point style, optionally with text labels** @param wellKnownName one of: Circle, Square, Cross, X, Triangle or Star* @param lineColor color for the point symbol outline* @param fillColor color for the point symbol fill* @param opacity a value between 0 and 1 for the opacity of the fill* @param size size of the point symbol* @param labelField name of the feature field (attribute) to use for labelling; mauy be {@code*     null} for no labels* @param labelFont GeoTools Font object to use for labelling; if {@code null} and {@code*     labelField} is not {@code null} the default font will be used* @return a new Style instance*/public static Style createPointStyle(String wellKnownName,Color lineColor,Color fillColor,float opacity,float size,String labelField,Font labelFont) {Stroke stroke = sf.createStroke(ff.literal(lineColor), ff.literal(1.0f));Fill fill = Fill.NULL;if (fillColor != null) {fill = sf.createFill(ff.literal(fillColor), ff.literal(opacity));}Mark mark =sf.createMark(ff.literal(wellKnownName), stroke, fill, ff.literal(size), ff.literal(0));Graphic graphic = sf.createDefaultGraphic();graphic.graphicalSymbols().clear();graphic.graphicalSymbols().add(mark);graphic.setSize(ff.literal(size));PointSymbolizer pointSym = sf.createPointSymbolizer(graphic, null);if (labelField == null) {return wrapSymbolizers(pointSym);} else {Font font = (labelFont == null ? sf.getDefaultFont() : labelFont);Fill labelFill = sf.createFill(ff.literal(Color.BLACK));AnchorPoint anchor = sf.createAnchorPoint(ff.literal(0.5), ff.literal(0.0));Displacement disp = sf.createDisplacement(ff.literal(0), ff.literal(5));LabelPlacement placement = sf.createPointPlacement(anchor, disp, ff.literal(0));TextSymbolizer textSym =sf.createTextSymbolizer(labelFill,new Font[] {font},null,ff.property(labelField),placement,null);return wrapSymbolizers(pointSym, textSym);}}

        在代码中可以看到传入的默认样式是:

if (color.equals(Color.BLACK)) {fillColor = null;
} else {fillColor = color;
}
return createPointStyle("Circle", color, fillColor, 0.5f, 3.0f);

        以上就是默认的简单样式创建的代码说明。当然,使用默认的简单样式创建方式比较简单,直接调用GeoTools的相关API即可,后面的关于如何生成点、线、面的样式属于扩展问题。与简单样式生成的方式不一样的是,我们可以在实际运用过程中使用更复杂的API来进行更复杂也更酷炫的样式生成

二、模板生成

        模板生成方法与编程式生成有所区别,模板生成顾名思义就是按照一定的模板来进行生成。而模板的寻找有很多地方,我们可以在互联网上寻找公开的模板,将模板拷贝到工程中,当成默认的样式库进行使用。

1、模板示例

        网上有很多分享SLD模板的网站,大家可以发挥自己的聪明才智来开发自己的SLD模板库。这里分享几个公开的模板。第一个是发表在知乎上的常用SLD模板常用SLD模版,打开网站后可以看到如下信息:

         在这个网站中可以看到很多常见的模板库,比如点数据的、线数据的、面数据的、道路的、铁路的、DEM的等等。

<?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>person_point_heat</Name><UserStyle><Title>person_point_heat</Title><Abstract>A heatmap </Abstract><FeatureTypeStyle><Transformation><ogc:Function name="gs:Heatmap"><ogc:Function name="parameter"><ogc:Literal>data</ogc:Literal></ogc:Function><ogc:Function name="parameter"><ogc:Literal>weightAttr</ogc:Literal><ogc:Literal>count</ogc:Literal></ogc:Function><ogc:Function name="parameter"><ogc:Literal>radiusPixels</ogc:Literal><ogc:Function name="env"><ogc:Literal>radius</ogc:Literal><ogc:Literal>60</ogc:Literal></ogc:Function></ogc:Function><ogc:Function name="parameter"><ogc:Literal>pixelsPerCell</ogc:Literal><ogc:Literal>2</ogc:Literal></ogc:Function><ogc:Function name="parameter"><ogc:Literal>outputBBOX</ogc:Literal><ogc:Function name="env"><ogc:Literal>wms_bbox</ogc:Literal></ogc:Function></ogc:Function><ogc:Function name="parameter"><ogc:Literal>outputWidth</ogc:Literal><ogc:Function name="env"><ogc:Literal>wms_width</ogc:Literal></ogc:Function></ogc:Function><ogc:Function name="parameter"><ogc:Literal>outputHeight</ogc:Literal><ogc:Function name="env"><ogc:Literal>wms_height</ogc:Literal></ogc:Function></ogc:Function></ogc:Function></Transformation><Rule><RasterSymbolizer><!-- specify geometry attribute to pass validation --><Geometry><ogc:PropertyName>geometry</ogc:PropertyName></Geometry><Opacity>1</Opacity><ColorMap type="ramp" ><ColorMapEntry color="#FFFFFF" quantity="0" opacity="0" label="低" /><ColorMapEntry color="#7F95E6" quantity="0.1" opacity="0.5" label="" /><ColorMapEntry color="#7DFC3F" quantity="0.3" opacity="0.5" label="" /><ColorMapEntry color="#F6FD01" quantity="0.4" opacity="0.5" label="" /><ColorMapEntry color="#EF8C07" quantity="0.5" opacity="0.5" label="" /><ColorMapEntry color="#FE0409" quantity="0.7" opacity="0.5" label="" /><ColorMapEntry color="#FE0409" quantity="1" opacity="0.5" label="高" /></ColorMap></RasterSymbolizer></Rule></FeatureTypeStyle></UserStyle></NamedLayer></StyledLayerDescriptor>

        还有对应的铁路路线图SLD样式图等,

         除了在知乎上这个分享的公开的模板,关于路网(公路和铁路的数据模板)在CSDN上有一个老师也进行了分享,分享两个线+标注的SLD样式。

        大家可以将上面分享的模板样式拷贝到自己的样式中,在这个模板样式的基础上进行微调,修改成符合我们项目需要的SLD文件,然后进行样式发布,最后再制作成地图。 

三、外部桌面工具生成

        模板生成不能解决自己项目定制化的问题,因此需要我们自己来根据实际情况进行正式标绘,制作完全符合自己要求的样式信息。本小节将重点介绍几种采用外部桌面工具的方式进行生成的方式。包括SLDEdtitor、Qgis等桌面客户端软件。

1、SLDEditor

        SLDEditor是一款使用Java开发的桌面端应用程序,专门是为了在桌面端进行样式绘制的软件。使用Java进行开发,因此可以运行在不同的操作的系统中,比如Linux、Windows等不同的操作系统中。下载好SLDEditor后,打开我们的应用程序,可以看到如下的程序界面。

         这款软件主要还是用来进行配图的,在上方的tab页中可以进行方便的切换,进行样式的设置。同时可以在map视图中及时预览这些效果。

        在这里可以快速的进行样式的配置,可以添加不同的Filter,也可以添加layer图层。配置好之后,也可以直接在SLD页面看到具体的xml格式的样式结果。

         可以直接将上面的XML格式的SLD样式文件进行数据配图就可以发布出来就好。

2、QGIS和UDig

        除了前面介绍过的SLDEditor,我们还可以选择Qgis和UDig,  其中,Qgis是一款对比Arcgis的桌面软件,功能也是非常的强大。另外一个UDig是一款Java开发的桌面软件。关于在QGIS中如何进行标注,相信大家非常熟悉了,在之前的博客中也进行了详细的解释,大家可以看一下QGis的标绘配置界面。

        UDig也是一款用的比较多的系统,感兴趣的同学大家可以自己研究一下。 篇幅有限,这里不再赘述。

四、GeoServer生成

        与前面的各种生成方式相比,GeoServer其实并没有样式的生成能力。但是其自带了很多的样式模板,我们可以把GeoServer来进行模板的生成,站在GeoServer的肩膀上,看得更远。

1、GeoServer的样式管理器

        在服务器上启动GeoServer之后,我们可以打开GeoServer的管理界面,在管理窗口中可以看到相关的启动界面。

        在这个界面中就可以看到GeoServer自带的和我们上传的样式文件。我们可以点击样式名称标题就可以进入看到不同的样式信息。

        在这个界面中,可以看到在GeoServer中也自带了简单的样式生成器,帮助我们来轻松的构造SLD样式文件,方便操作。 

五、总结

        以上就是本文的主要内容,本文即重点讲解在开发过程中,如何使用多方式来生成SLD样式文件。文章首先介绍Java中来使用代码进行编程式生成,然后介绍如何基于SLD的模板文件进行生成,其次介绍基于桌面生成工具SLDEditor和QQis来进行样式生成,最后介绍如何利用GeoServer来进行样式生成。通过不同的SLD创建方式,让您掌握不同的样式生成方式。希望本文对学习SLD的同学有所帮助。行文仓促,定有许多不足支持,针对不足之处,还请各位专家朋友在评论区中留言指出,不甚感激。

        博文编写过程中,参考以下内容,在此表示感谢:

        1、常用SLD模版。

        2、分享两个线+标注的SLD样式。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com