java - 使用geotools开发wms服务时如何将地图图像输出到浏览器?
问题描述
我正在使用 geotools 开发 wms 服务。我创建了一个地图图层并将其添加到MapContent
. 然后我开发了一个 GetMap 服务。我在浏览器上显示地图成功,但地图位置总是错误。像这样:
请求参数为:
SERVICE: WMS
VERSION: 1.1.0
REQUEST: GetMap
FORMAT: image/png
TRANSPARENT: true
LAYERS: layer
SRS: EPSG:4326
STYLES:
WIDTH: 997
HEIGHT: 499
BBOX: 63.2958984375,3.1494140625,150.9228515625,47.0068359375
响应预览如下:
我想在正确的位置显示点。
这是我处理 GetMap 请求的代码:
double x1, y1, x2, y2;
String[] BBOX = request.getParameter("BBOX").split(",");
x1 = Double.parseDouble(BBOX[0]);
y1 = Double.parseDouble(BBOX[1]);
x2 = Double.parseDouble(BBOX[2]);
y2 = Double.parseDouble(BBOX[3]);
int width = Integer.parseInt(request.getParameter("WIDTH")),
height = Integer.parseInt(request.getParameter("HEIGHT"));
CoordinateReferenceSystem crs = CRS.decode(request.getParameter("SRS"));
ReferencedEnvelope mapArea = new ReferencedEnvelope(x1, y1, x2, y2, crs);//I think some wrong here,but I try to modify many times,it is not work
response.setContentType("image/png");
ServletOutputStream out = response.getOutputStream();
WMSRequest wmsRequest = new WMSRequest();
wmsRequest.getGetMap();
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics graphics = bi.getGraphics();
Rectangle rectangle = new Rectangle(0, 0, width, height);
MapViewport mv = new MapViewport();
mv.setBounds(mapArea);
mv.setCoordinateReferenceSystem(crs);
mv.setScreenArea(rectangle);
mapContent.setViewport(mv);
//AffineTransform atf = geometryManage.getRenderingTransform(width, height, mv.getBounds());
StreamingRenderer sr = new StreamingRenderer();
sr.setMapContent(mapContent);
sr.paint((Graphics2D) graphics, rectangle, mapArea);
ImageIO.write(bi, "png", out);
out.close();
解决方案
我解决它。错误就在这里:</p>
ReferencedEnvelope mapArea = new ReferencedEnvelope(x1, y1, x2, y2, crs);
我用这个语句来选择地图的显示区域。但是参数的顺序是错误的。
请求中的 BBOX 有 4 个参数,顺序为 [longitude,latitude,longitude,latitude],在 CRS WGS 84 中,经度定义为y,纬度定义为x。但是 ReferencedEnvelope 构造函数是:
ReferencedEnvelope(double x1, double x2, double y1, double y2, CoordinateReferenceSystem crs)
ReferencedEnvelope的更多细节:ReferencedEnvelope的文档
所以我改变了代码:
double x1, y1, x2, y2;
y1 = Double.parseDouble(BBOX[0]);
x1 = Double.parseDouble(BBOX[1]);
y2 = Double.parseDouble(BBOX[2]);
x2 = Double.parseDouble(BBOX[3]);
ReferencedEnvelope mapArea = new ReferencedEnvelope(x1, x2, y1, y2, crs);
然后就可以了。
不同的坐标系有不同的坐标序列,我们可以通过打印它的文字信息来查看,比如
GEOGCS["WGS84(DD)",
DATUM["WGS84",
SPHEROID["WGS84", 6378137.0, 298.257223563]],
PRIMEM["Greenwich", 0.0],
UNIT["degree", 0.017453292519943295],
AXIS["Geodetic longitude", EAST],
AXIS["Geodetic latitude", NORTH]]
首先定义经度,然后
GEOGCS["WGS 84",
DATUM["World Geodetic System 1984",
SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]],
AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]],
UNIT["degree", 0.017453292519943295],
AXIS["Geodetic latitude", NORTH],
AXIS["Geodetic longitude", EAST],
AUTHORITY["EPSG","4326"]]
先定义纬度
推荐阅读
- java - Java Parallel Stream AnyMatch 的 Parallel Stream 的一个字段
- branch.io - 如何从 Branch Analytics 中获取 UserId - Branch.IO
- python - 用星号(*)Python转换的短路算法
- python - 为什么 python 中的舍入数字给出不同的答案
- intellij-idea - IntelliJ 捆绑的 jdk 路径
- r - R:如何为数据框中的子集行申请循环
- c++ - 处理除以零
导致意外行为 - reactjs - 如何使 React.Children.map 与 Typescript 一起使用?
- python - 通过 Snakemake 进行符号链接(自动生成)目录
- python - 我使用熊猫附加到 DataFrame 的数据(数字)