第11章 - 样式与符号化
第11章 - 样式与符号化
11.1 SLD 样式概述
11.1.1 SLD 规范
SLD(Styled Layer Descriptor)是 OGC 制定的样式描述规范,用于定义地图要素的可视化样式。
┌─────────────────────────────────────────────────────────────────────┐
│ SLD 结构层次 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ StyledLayerDescriptor │
│ │ │
│ └── NamedLayer / UserLayer │
│ │ │
│ └── UserStyle │
│ │ │
│ └── FeatureTypeStyle │
│ │ │
│ └── Rule │
│ ├── Filter (可选) │
│ ├── MinScaleDenominator │
│ ├── MaxScaleDenominator │
│ └── Symbolizer │
│ ├── PointSymbolizer │
│ ├── LineSymbolizer │
│ ├── PolygonSymbolizer │
│ ├── TextSymbolizer │
│ └── RasterSymbolizer │
│ │
└─────────────────────────────────────────────────────────────────────┘
11.1.2 样式工厂
import org.geotools.api.style.*;
import org.geotools.factory.CommonFactoryFinder;
public class StyleFactoryExample {
// 获取样式工厂
private static final StyleFactory sf = CommonFactoryFinder.getStyleFactory();
private static final FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
public static void main(String[] args) {
System.out.println("StyleFactory: " + sf.getClass().getSimpleName());
System.out.println("FilterFactory: " + ff.getClass().getSimpleName());
}
}
11.2 创建点样式
11.2.1 简单点样式
public class PointStyleExample {
private static final StyleFactory sf = CommonFactoryFinder.getStyleFactory();
private static final FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
// 创建简单圆点样式
public static Style createSimplePointStyle() {
// 创建标记
Mark mark = sf.createMark();
mark.setWellKnownName(ff.literal("circle"));
mark.setFill(sf.createFill(ff.literal(Color.RED)));
mark.setStroke(sf.createStroke(ff.literal(Color.BLACK), ff.literal(1)));
// 创建图形
Graphic graphic = sf.createDefaultGraphic();
graphic.graphicalSymbols().clear();
graphic.graphicalSymbols().add(mark);
graphic.setSize(ff.literal(10));
// 创建点符号化器
PointSymbolizer pointSymbolizer = sf.createPointSymbolizer();
pointSymbolizer.setGraphic(graphic);
// 创建规则
Rule rule = sf.createRule();
rule.symbolizers().add(pointSymbolizer);
// 创建要素类型样式
FeatureTypeStyle fts = sf.createFeatureTypeStyle();
fts.rules().add(rule);
// 创建样式
Style style = sf.createStyle();
style.featureTypeStyles().add(fts);
return style;
}
// 使用不同形状
public static Style createShapedPointStyle(String shape, Color fillColor, int size) {
// 可用形状: circle, square, triangle, star, cross, x
Mark mark = sf.createMark();
mark.setWellKnownName(ff.literal(shape));
mark.setFill(sf.createFill(ff.literal(fillColor)));
mark.setStroke(sf.createStroke(ff.literal(Color.BLACK), ff.literal(1)));
Graphic graphic = sf.createDefaultGraphic();
graphic.graphicalSymbols().clear();
graphic.graphicalSymbols().add(mark);
graphic.setSize(ff.literal(size));
PointSymbolizer ps = sf.createPointSymbolizer();
ps.setGraphic(graphic);
return createStyle(ps);
}
// 使用图标
public static Style createIconPointStyle(String iconPath) throws Exception {
ExternalGraphic externalGraphic = sf.createExternalGraphic(
new URL("file:" + iconPath), "image/png");
Graphic graphic = sf.createDefaultGraphic();
graphic.graphicalSymbols().clear();
graphic.graphicalSymbols().add(externalGraphic);
graphic.setSize(ff.literal(32));
PointSymbolizer ps = sf.createPointSymbolizer();
ps.setGraphic(graphic);
return createStyle(ps);
}
private static Style createStyle(Symbolizer symbolizer) {
Rule rule = sf.createRule();
rule.symbolizers().add(symbolizer);
FeatureTypeStyle fts = sf.createFeatureTypeStyle();
fts.rules().add(rule);
Style style = sf.createStyle();
style.featureTypeStyles().add(fts);
return style;
}
}
11.3 创建线样式
11.3.1 线符号化器
public class LineStyleExample {
private static final StyleFactory sf = CommonFactoryFinder.getStyleFactory();
private static final FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
// 简单线样式
public static Style createSimpleLineStyle(Color color, double width) {
Stroke stroke = sf.createStroke(
ff.literal(color),
ff.literal(width)
);
LineSymbolizer lineSymbolizer = sf.createLineSymbolizer();
lineSymbolizer.setStroke(stroke);
return createStyle(lineSymbolizer);
}
// 虚线样式
public static Style createDashedLineStyle(Color color, double width,
float[] dashArray) {
Stroke stroke = sf.createStroke(
ff.literal(color),
ff.literal(width),
ff.literal(1.0f), // 不透明度
ff.literal("round"), // 线帽
ff.literal("round"), // 连接
dashArray,
ff.literal(0.0f), // 虚线偏移
null,
null
);
LineSymbolizer lineSymbolizer = sf.createLineSymbolizer();
lineSymbolizer.setStroke(stroke);
return createStyle(lineSymbolizer);
}
// 道路样式(双层)
public static Style createRoadStyle(Color casing, Color fill,
double casingWidth, double fillWidth) {
// 外层(边框)
Stroke casingStroke = sf.createStroke(
ff.literal(casing),
ff.literal(casingWidth)
);
LineSymbolizer casingLine = sf.createLineSymbolizer();
casingLine.setStroke(casingStroke);
// 内层(填充)
Stroke fillStroke = sf.createStroke(
ff.literal(fill),
ff.literal(fillWidth)
);
LineSymbolizer fillLine = sf.createLineSymbolizer();
fillLine.setStroke(fillStroke);
Rule rule = sf.createRule();
rule.symbolizers().add(casingLine); // 先绘制边框
rule.symbolizers().add(fillLine); // 后绘制填充
FeatureTypeStyle fts = sf.createFeatureTypeStyle();
fts.rules().add(rule);
Style style = sf.createStyle();
style.featureTypeStyles().add(fts);
return style;
}
private static Style createStyle(Symbolizer symbolizer) {
Rule rule = sf.createRule();
rule.symbolizers().add(symbolizer);
FeatureTypeStyle fts = sf.createFeatureTypeStyle();
fts.rules().add(rule);
Style style = sf.createStyle();
style.featureTypeStyles().add(fts);
return style;
}
}
11.4 创建面样式
11.4.1 多边形符号化器
public class PolygonStyleExample {
private static final StyleFactory sf = CommonFactoryFinder.getStyleFactory();
private static final FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
// 简单面样式
public static Style createSimplePolygonStyle(Color strokeColor, Color fillColor) {
Stroke stroke = sf.createStroke(
ff.literal(strokeColor),
ff.literal(1)
);
Fill fill = sf.createFill(ff.literal(fillColor));
PolygonSymbolizer polygonSymbolizer = sf.createPolygonSymbolizer();
polygonSymbolizer.setStroke(stroke);
polygonSymbolizer.setFill(fill);
return createStyle(polygonSymbolizer);
}
// 带透明度的样式
public static Style createTransparentPolygonStyle(Color strokeColor,
Color fillColor, double opacity) {
Stroke stroke = sf.createStroke(
ff.literal(strokeColor),
ff.literal(1)
);
Fill fill = sf.createFill(
ff.literal(fillColor),
ff.literal(opacity)
);
PolygonSymbolizer ps = sf.createPolygonSymbolizer();
ps.setStroke(stroke);
ps.setFill(fill);
return createStyle(ps);
}
// 填充图案样式
public static Style createPatternFillStyle(String pattern, Color color) {
// 支持的图案: shape://times, shape://plus, etc.
Mark mark = sf.createMark();
mark.setWellKnownName(ff.literal(pattern));
mark.setStroke(sf.createStroke(ff.literal(color), ff.literal(1)));
Graphic graphic = sf.createDefaultGraphic();
graphic.graphicalSymbols().clear();
graphic.graphicalSymbols().add(mark);
graphic.setSize(ff.literal(8));
Fill fill = sf.createFill(ff.literal(Color.WHITE));
fill.setGraphicFill(graphic);
Stroke stroke = sf.createStroke(ff.literal(color), ff.literal(1));
PolygonSymbolizer ps = sf.createPolygonSymbolizer();
ps.setStroke(stroke);
ps.setFill(fill);
return createStyle(ps);
}
private static Style createStyle(Symbolizer symbolizer) {
Rule rule = sf.createRule();
rule.symbolizers().add(symbolizer);
FeatureTypeStyle fts = sf.createFeatureTypeStyle();
fts.rules().add(rule);
Style style = sf.createStyle();
style.featureTypeStyles().add(fts);
return style;
}
}
11.5 文本标注
11.5.1 TextSymbolizer
public class TextStyleExample {
private static final StyleFactory sf = CommonFactoryFinder.getStyleFactory();
private static final FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
// 简单标注
public static Style createSimpleLabelStyle(String attribute) {
// 字体
Font font = sf.createFont(
ff.literal("宋体"),
ff.literal("normal"),
ff.literal("normal"),
ff.literal(12)
);
// 标注位置
AnchorPoint anchor = sf.createAnchorPoint(
ff.literal(0.5), // X 锚点
ff.literal(0.5) // Y 锚点
);
Displacement displacement = sf.createDisplacement(
ff.literal(0),
ff.literal(5) // Y 偏移
);
PointPlacement placement = sf.createPointPlacement(anchor, displacement,
ff.literal(0)); // 旋转角度
// 创建文本符号化器
TextSymbolizer textSymbolizer = sf.createTextSymbolizer();
textSymbolizer.setLabel(ff.property(attribute));
textSymbolizer.setFont(font);
textSymbolizer.setLabelPlacement(placement);
// 设置 Halo(光晕效果)
Halo halo = sf.createHalo(
sf.createFill(ff.literal(Color.WHITE)),
ff.literal(2)
);
textSymbolizer.setHalo(halo);
// 设置颜色
textSymbolizer.setFill(sf.createFill(ff.literal(Color.BLACK)));
return createStyle(textSymbolizer);
}
// 沿线标注
public static Style createLineLabelStyle(String attribute) {
Font font = sf.createFont(
ff.literal("Arial"),
ff.literal("normal"),
ff.literal("normal"),
ff.literal(10)
);
// 沿线放置
LinePlacement linePlacement = sf.createLinePlacement(ff.literal(5));
linePlacement.setRepeated(true);
linePlacement.setGap(ff.literal(100));
TextSymbolizer textSymbolizer = sf.createTextSymbolizer();
textSymbolizer.setLabel(ff.property(attribute));
textSymbolizer.setFont(font);
textSymbolizer.setLabelPlacement(linePlacement);
textSymbolizer.setFill(sf.createFill(ff.literal(Color.BLUE)));
return createStyle(textSymbolizer);
}
// 组合样式(点+标注)
public static Style createPointWithLabelStyle(String labelAttribute) {
// 点样式
Mark mark = sf.createMark();
mark.setWellKnownName(ff.literal("circle"));
mark.setFill(sf.createFill(ff.literal(Color.RED)));
Graphic graphic = sf.createDefaultGraphic();
graphic.graphicalSymbols().clear();
graphic.graphicalSymbols().add(mark);
graphic.setSize(ff.literal(6));
PointSymbolizer pointSymbolizer = sf.createPointSymbolizer();
pointSymbolizer.setGraphic(graphic);
// 标注样式
Font font = sf.createFont(
ff.literal("宋体"),
ff.literal("normal"),
ff.literal("normal"),
ff.literal(12)
);
PointPlacement placement = sf.createPointPlacement(
sf.createAnchorPoint(ff.literal(0.5), ff.literal(0)),
sf.createDisplacement(ff.literal(0), ff.literal(10)),
ff.literal(0)
);
TextSymbolizer textSymbolizer = sf.createTextSymbolizer();
textSymbolizer.setLabel(ff.property(labelAttribute));
textSymbolizer.setFont(font);
textSymbolizer.setLabelPlacement(placement);
textSymbolizer.setFill(sf.createFill(ff.literal(Color.BLACK)));
Rule rule = sf.createRule();
rule.symbolizers().add(pointSymbolizer);
rule.symbolizers().add(textSymbolizer);
FeatureTypeStyle fts = sf.createFeatureTypeStyle();
fts.rules().add(rule);
Style style = sf.createStyle();
style.featureTypeStyles().add(fts);
return style;
}
private static Style createStyle(Symbolizer symbolizer) {
Rule rule = sf.createRule();
rule.symbolizers().add(symbolizer);
FeatureTypeStyle fts = sf.createFeatureTypeStyle();
fts.rules().add(rule);
Style style = sf.createStyle();
style.featureTypeStyles().add(fts);
return style;
}
}
11.6 分类样式
11.6.1 按属性分类
public class ClassifiedStyleExample {
private static final StyleFactory sf = CommonFactoryFinder.getStyleFactory();
private static final FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
// 分类渲染
public static Style createClassifiedStyle(String attribute,
Map<Object, Color> classification) {
FeatureTypeStyle fts = sf.createFeatureTypeStyle();
for (Map.Entry<Object, Color> entry : classification.entrySet()) {
// 创建过滤器
Filter filter = ff.equals(ff.property(attribute), ff.literal(entry.getKey()));
// 创建样式
Fill fill = sf.createFill(ff.literal(entry.getValue()));
Stroke stroke = sf.createStroke(ff.literal(Color.BLACK), ff.literal(1));
PolygonSymbolizer ps = sf.createPolygonSymbolizer();
ps.setFill(fill);
ps.setStroke(stroke);
Rule rule = sf.createRule();
rule.setFilter(filter);
rule.symbolizers().add(ps);
rule.setName(entry.getKey().toString());
fts.rules().add(rule);
}
Style style = sf.createStyle();
style.featureTypeStyles().add(fts);
return style;
}
// 数值范围分类
public static Style createRangeStyle(String attribute,
double[] breaks, Color[] colors) {
FeatureTypeStyle fts = sf.createFeatureTypeStyle();
for (int i = 0; i < breaks.length - 1; i++) {
Filter filter = ff.and(
ff.greaterOrEqual(ff.property(attribute), ff.literal(breaks[i])),
ff.less(ff.property(attribute), ff.literal(breaks[i + 1]))
);
Fill fill = sf.createFill(ff.literal(colors[i]));
Stroke stroke = sf.createStroke(ff.literal(Color.GRAY), ff.literal(0.5));
PolygonSymbolizer ps = sf.createPolygonSymbolizer();
ps.setFill(fill);
ps.setStroke(stroke);
Rule rule = sf.createRule();
rule.setFilter(filter);
rule.symbolizers().add(ps);
rule.setName(String.format("%.0f - %.0f", breaks[i], breaks[i + 1]));
fts.rules().add(rule);
}
Style style = sf.createStyle();
style.featureTypeStyles().add(fts);
return style;
}
}
11.7 SLD 文件操作
11.7.1 读取 SLD
import org.geotools.xml.styling.SLDParser;
public class SLDFileOperations {
// 从文件读取
public static Style loadFromFile(String path) throws Exception {
StyleFactory sf = CommonFactoryFinder.getStyleFactory();
SLDParser parser = new SLDParser(sf, new File(path));
Style[] styles = parser.readXML();
return styles.length > 0 ? styles[0] : null;
}
// 从 URL 读取
public static Style loadFromURL(String url) throws Exception {
StyleFactory sf = CommonFactoryFinder.getStyleFactory();
SLDParser parser = new SLDParser(sf, new URL(url));
Style[] styles = parser.readXML();
return styles.length > 0 ? styles[0] : null;
}
// 从字符串读取
public static Style loadFromString(String sld) throws Exception {
StyleFactory sf = CommonFactoryFinder.getStyleFactory();
SLDParser parser = new SLDParser(sf, new StringReader(sld));
Style[] styles = parser.readXML();
return styles.length > 0 ? styles[0] : null;
}
}
11.7.2 保存 SLD
import org.geotools.xml.styling.SLDTransformer;
public class SLDExport {
// 导出为 SLD 字符串
public static String exportToString(Style style) throws Exception {
SLDTransformer transformer = new SLDTransformer();
transformer.setIndentation(2);
return transformer.transform(style);
}
// 导出到文件
public static void exportToFile(Style style, String path) throws Exception {
String sld = exportToString(style);
try (FileWriter writer = new FileWriter(path)) {
writer.write(sld);
}
}
}
11.8 SLD 工具类
11.8.1 快速创建样式
import org.geotools.styling.SLD;
public class SLDUtilityExample {
public static void quickStyles() {
// 快速创建点样式
Style pointStyle = SLD.createPointStyle("circle", Color.RED, Color.BLACK,
0.5f, 10);
// 快速创建线样式
Style lineStyle = SLD.createLineStyle(Color.BLUE, 2);
// 快速创建面样式
Style polygonStyle = SLD.createPolygonStyle(Color.BLACK, Color.YELLOW, 0.5f);
// 从要素类型创建默认样式
// Style defaultStyle = SLD.createSimpleStyle(featureType);
}
}
11.9 本章小结
本章详细介绍了 GeoTools 的样式系统:
-
SLD 规范
- 结构层次
- 样式工厂
-
符号化器
- PointSymbolizer
- LineSymbolizer
- PolygonSymbolizer
- TextSymbolizer
-
分类样式
- 属性分类
- 数值范围
-
SLD 文件
- 读取和保存
- SLD 工具类
关键要点
- 使用 StyleFactory 创建样式
- 符号化器定义具体的可视化效果
- Rule 可以包含过滤器实现分类渲染
- SLD 文件可以持久化样式配置

浙公网安备 33010602011771号