一、样式概述
样式(Style)犹如一盒蜡笔,使我们把地图绘制的更好看。实际上,制图的重点是使用地图进行交流,选择要包含的信息,严格删除偏离主题的信息等等。有时候,制图必须遵守制图标准,例如线条必须有多粗,水用什么颜色表示。所以制图标准可以为我们省去大量的时间去发挥创造力去展现地理要素信息。
样式化层描述符 (SLD) 标准,该文档为我们以 Java 对象的形式捕获的样式定义了一个很好的数据结构。它的核心是两件事:
1、Style Layer Descriptor 样式图层描述符
涵盖“图层”的定义或要素内容的表示形式。
2、Symbology Encoding 符号系统编码
涵盖描绘或如何绘制特征
二、控制渲染的过程
这是使用 GeoTools(或开放标准)制作地图的核心。
你可以想象一个大漏斗把所有的要素同时抛向你的地图。这就像那些分类硬币的机器一样,机器的早期阶段会选择一个特征;一旦我们确定了什么样的功能,我们将使用该功能来控制实际绘制到不同的位图。最后,我们将收集所有不同的位图(并在上面贴上一些标签)以生成最终图像。
渲染发生在以下阶段:
内容选择:选择和过滤
绘本:实物图
组成:把所有东西放在一起
第一道防线是FeatureTypeStyle,它利用一个约束来选择要使用的FeatureType。如果您不介意的话,可以将Feature名称以通配符的形式使用FeatureType,因为他们都继承了Feature。
接下来再看Rules。规则实际上使用过滤器对将要绘制的内容执行严格的检查。除了使用filter来检查要素属性之外,规则还能够检查地图的当前比例。最后,还有一个其他规则来捕获剩余的几何特征。
既然规则已经为我们选择了要使用的Feature,我们就可以开始在描绘步骤中进行绘制了。渲染器将遍历一个符号列表(对于规则)并绘制结果。符号只是一个按顺序绘制的指令列表。符号器使用表达式来定义宽度和颜色-允许您在逐个特征的基础上动态生成外观!
唯一未按顺序绘制的符号是TextSymbolizer为下一步收集文本标签。
最后在构图步骤 - 将在描绘过程中绘制的所有内容并将它们压缩成最终图像。最后,文本标签绘制到所有图层的顶部(注意避免重叠任何文本)。
三、Style Layer Descriptor
样式图层描述符 API 将输入地图定义为要显示的一系列图层。
上面引用的许多元素我们都在WMS中运行,在日常使用中并不常用。也就是说,如果你让一个用户管理风格,你会让他们提供名称和标题,并组织正在发生的事情。
使用三个初始类捕获地图的样式:
StyledLayerDescriptor 表示整个地图的样式信息
NamedLayer定义FeatureTypeConstraints测试样式是否适用于您的数据,以及Style
Style定义features或Rasters将如何被绘制
四、Symbology Encoding
Symbology Encoding实现与 SLD 略有不同,因为它只关注如何孤立地绘制一层内容(而不是整个地图)。
Symbology Encoding的关键概念包括:
FeatureTypeStyle
:捕获绘制特定feature的配方(侧重于如何以类似于 CSS 的方式绘制特征)
Rule
:用于选择要绘制的features,使用符号器列表来控制实际的绘制过程。
Symbolizer
:定义如何使用填充、描边、标记和字体信息描绘所选要素。
1、Rule
1、Rule.symbolizers()
提供对 List<Symbolizer>
的直接访问
2、直接修改Symbolizer
列表
rule.clear();
rule.symbolizers().add( pointSymbolizer );
2、Symbolizer
定义如何以像素为单位渲染几何体;从特征中选择几何,然后使用此处提供的信息进行绘图。
- PointSymbolizer:用于绘制点位置,实际绘制的图形称为标记,可以选择使用一些众所周知的标记(圆形、正方形等)或您自己的外部图形,例如 PNG 图标。
- LineSymbolizer:用于控制线条(或边)的绘制方式。
- PolygonSymbolizer:用于控制实体形状的绘制方式。
- TextSymbolizer:用于控制贴标系统;标签由
TextSymbolizers
生成并放入渲染引擎中,该引擎检测重叠,根据您定义的优先级进行排序,并决定最终的标签位置。 - RasterSymbolizer:用于使用完整的“颜色映射表”控制来控制栅格数据的渲染。
五、SLD创建
SLD的创建包括SLD的手动创建和sld文件加载。
1、SLD一般创建流程
StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory();
XXXSymbolizer sym = styleFactory.createXXXSymbolizer(stroke, null);
Rule rule = styleFactory.createRule();
rule.symbolizers().add(sym);
FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle(new Rule[]{rule});
Style style = styleFactory.createStyle();
style.featureTypeStyles().add(fts);
2、创建点样式
点要素一般是一个圆圈,这个圆圈主要有外轮廓线和内部填充组成。所以我们引入了Graphic和Mark对象。具体的创建步骤如下图:
StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory();
Graphic gr = styleFactory.createDefaultGraphic();
//这里可以创建不同形状的
MarkMark mark = styleFactory.getCircleMark();
//设置圆圈的边界
mark.setStroke(styleFactory.createStroke(filterFactory.literal(Color.BLUE), filterFactory.literal(1)));
//选择圆圈填充的样式
mark.setFill(styleFactory.createFill(filterFactory.literal(Color.CYAN)));
gr.graphicalSymbols().clear();
gr.graphicalSymbols().add(mark);
gr.setSize(filterFactory.literal(5));
PointSymbolizer sym = styleFactory.createPointSymbolizer(gr, null);
3、创建线样式
作为一个线要素,他需要知道线型(实线、虚线或者其他线性)、线宽、线的颜色。在GeoTools中,使用Stroke定义线样式。
StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory();
Stroke stroke = styleFactory.createStroke(filterFactory.literal(Color.BLUE), filterFactory.literal(1));
4、创建面样式
对于一个面,他是有两部分组成,一部分是边界,这里我们用Stroke表示,另外一部分是填充,我们使用Fill表示。
StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory();
Stroke stroke = styleFactory.createStroke(filterFactory.literal(Color.BLUE),filterFactory.literal(1),filterFactory.literal(0.5));
Fill fill = styleFactory.createFill(filterFactory.literal(Color.CYAN), filterFactory.literal(0.5));
PolygonSymbolizer sym = styleFactory.createPolygonSymbolizer(stroke, fill, null);
5、创建文字样式
TextSymbolizer textSymbolizer = styleFactory.createTextSymbolizer();
textSymbolizer.setLabel(filterFactory.property("attrName"));
6、过滤器
SLD过滤器在实际用处极为广泛。比如一个线状地物的shape图层,里面有河流、铁路、公路,公路又分为国道、省道、县道等等。如果在地图上全部绘制一种样式,不仅不美观,辨识度也非常低。所以,我们这里引入过滤器,通过shape图层特定字段展现不同的样式。使用样式过滤器也很简单。
FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
StyleFactory sf = CommonFactoryFinder.getStyleFactory();
Rule selectedRule = createRule(SELECTED_COLOUR, SELECTED_COLOUR);
selectedRule.setFilter(ff.id(IDs));
Rule otherRule = createRule(LINE_COLOUR, FILL_COLOUR);
otherRule.setElseFilter(true);
FeatureTypeStyle fts = sf.createFeatureTypeStyle();
fts.rules().add(selectedRule);
fts.rules().add(otherRule);