Java对点、线、面生成栅格瓦片jpg,并渲染呈现
这篇博客将介绍从前端HTML页面到后端预生成栅格瓦片jpg,并提供查询接口供前端html调用呈现效果图;
1. 效果图
随机画一个多边形,以这个多边形面进行栅格瓦片生成;
点线面的渲染效果图如下:
多点为蓝色,线为绿色,面为红色
面生成为背景黑色的栅格瓦片,点线生成为背景白色的栅格瓦片效果图如下:
红色面的渲染效果图如下:
级别小一些只有一张图,和级别大一些多张图拼合而成,背景色可以是白色的,也可以是黑色的~;
蓝色点的渲染效果图如下:
级别大一些蓝色点的渲染效果图如下:
绿色线的渲染效果图如下:(1/500的分辨率认为点在线上)
1/20分辨率距离则认为点在线上效果图,看起来线要宽一些;
2. 原理
2.1 面瓦片的生成
- 先计算多边形面的Geometry经纬度范围(外接矩形的左上角,右下角坐标);
- 经纬度坐标转web墨卡托坐标;
- 指定某一级别计算瓦片号范围;
- 分别遍历每一个瓦片(计算瓦片范围与多边形面是否有交集,没有交集生成一张空白图;有交集遍历每一个像素点转换为web墨卡托坐标,转换为Geometry坐标,判断点是否在多边形面上,在设置当前像素点颜色;不在给空白);
- 循环遍历多个级别,重复1~4步骤,即可生成多个不同级别
2.2 线瓦片的生成
- 先计算 多线 的Geometry经纬度范围(外接矩形的左上角,右下角坐标);
- 经纬度坐标转web墨卡托坐标;
- 指定某一级别计算瓦片号范围;
- 分别遍历每一个瓦片(计算瓦片范围与 线 是否有交集,没有交集生成一张空白图;有交集遍历每一个像素点转换为web墨卡托坐标,转换为Geometry 点坐标, 判断点是否在线上 ,在设置当前像素点颜色;不在给空白);
- 循环遍历多个级别,重复1~4步骤,即可生成多个不同级别
判断点是否在线上需要注意,可参考谷歌js提供的算法,isPointOnSegment 计算距离允许误差在分辨率范围内,则标识在线上;
2.3 多点瓦片的生成
- 先计算 多点 的Geometry经纬度范围(外接矩形的左上角,右下角坐标);
- 经纬度坐标转web墨卡托坐标;
- 指定某一级别计算瓦片号范围;
- 分别遍历每一个瓦片(计算瓦片范围与 多点 是否有交集,没有交集生成一张空白图;有交集 求瓦片范围与多点的交集点,然后遍历交集点,判断点是否在线上 ,在设置当前像素点颜色;不在给空白);
- 循环遍历多个级别,重复1~4步骤,即可生成多个不同级别
3. 源码
package com.demo.utils;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
import com.vividsolutions.jts.util.GeometricShapeFactory;
import java.util.List;
/*************************************
*Class Name: JtsUtils
*Description: <jtsutils工具类>
*@author: Seminar
*@create: 2023/3/31
*@since 1.0.0
*************************************/
public class JtsUtils {
static GeometryFactory factory = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING), 4326);
public static Point createPoint(Coordinate pt) {
return factory.createPoint(pt);
}
public static double distance(Point p1, Point p2) {
return distance(p1.getCoordinate(), p2.getCoordinate());
}
public static double distance(Coordinate p1, Coordinate p2) {
double lat1 = Math.toRadians(p1.y);
double lon1 = Math.toRadians(p1.x);
double lat2 = Math.toRadians(p2.y);
double lon2 = Math.toRadians(p2.x);
double vLon = Math.abs(lon1 - lon2);
double vLat = Math.abs(lat1 - lat2);
double h = haverSin(vLat) + Math.cos(lat1) * Math.cos(lat2) * haverSin(vLon);
double distance = 1.2756274E7 * Math.asin(Math.sqrt(h));
return distance;
}
private static double haverSin(double theta) {
double v = Math.sin(theta / 2.0);
return v * v;
}
public static double distance(LineString line) {
Coordinate[] coors = line.getCoordinates();
return distance(coors);
}
public static double distance(Coordinate[] coors) {
double lineDist = 0.0;
for(int i = 1; i < coors.length; ++i) {
Coordinate coor1 = coors[i - 1];
Coordinate coor2 = coors[i];
if (coor1.x == coor2.x && coor1.y == coor2.y) {
lineDist += 0.0;
} else {
lineDist += distance(coor1, coor2);
}
}
return lineDist;
}
public static double distance(List<Coordinate> coors) {
double lineDist = 0.0;
for(int i = 1; i < coors.size(); ++i) {
Coordinate coor1 = (Coordinate)coors.get(i - 1);
Coordinate coor2 = (Coordinate)coors.get(i);
if (coor1.x == coor2.x && coor1.y == coor2.y) {
lineDist += 0.0;
} else {
lineDist += distance(coor1, coor2);
}
}
return lineDist;
}
public static Geometry createGeometryByWKT(String wkt) throws ParseException {
WKTReader reader = new WKTReader(factory);
Geometry geometry = reader.read(wkt);
return geometry;
}
public static LineString createLineStringByWKT(String wkt) throws ParseException {
WKTReader reader = new WKTReader(factory);
LineString line = (LineString)reader.read(wkt);
return line;
}
public static Point createPointByWKT(String pointWkt) {
WKTReader reader = new WKTReader(factory);
Point point = null;
try {
point = (Point)reader.read(pointWkt);
} catch (ParseException var4) {
var4.printStackTrace();
}
return point;
}
public static Polygon createPolygonByWKT(String polygonWkt) {
WKTReader reader = new WKTReader(factory);
Polygon polygon = null;
try {
polygon = (Polygon)reader.read(polygonWkt);
} catch (ParseException var4) {
var4.printStackTrace();
}
return polygon;
}
public static Geometry createCircle(double x, double y, double radius) {
GeometricShapeFactory shapeFactory = new GeometricShapeFactory();
shapeFactory.setNumPoints(128);
shapeFactory.setCentre(new Coordinate(x, y));
shapeFactory.setSize(radius * 2.0);
return shapeFactory.createCircle();
}
}
package com.demo.model.render;
import lombok.Data;
/**
* 瓦片类,(单位:块)
* 地图瓦片坐标系(Tile Coordinates)单位。
* 瓦片坐标系以左上角为原点(0, 0),到右下角(2 ^ 图像级别 - 1, 2 ^ 图像级别 - 1)
*/
@Data
public class Tile {
/**
* 横向瓦片数
*/
long x;
/**
* 纵向瓦片数
*/
long y;
/**
* 级别
*/
int z;
public Tile() {
}
/**
* 根据给定参数构造Tile的新实例
*
* @param x 横向瓦片数
* @param y 纵向瓦片数
*/
public Tile(long x, long y) {
this.x = x;
this.y = y;
}
/**
* 根据给定参数构造Tile的新实例
*
* @param x 横向瓦片数
* @param y 纵向瓦片数
* @param z 级别
*/
public Tile(long x, long y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public String toString() {
return "Tile(" + x + "," + y + "," + z + ")";
}
}
package com.demo.model.render;
import lombok.Data;
/**
* 屏幕像素坐标类(单位:像素)
* 像素坐标系(Pixel Coordinates)单位
* 以左上角为原点(0,0),向右向下为正方向
*/
@Data
public class Pixel {
/**
* 横向像素
*/
long x;
/**
* 纵向像素
*/
long y;
/**
* 根据给定参数构造Pixel的新实例
*
* @param x 横向像素
* @param y 纵向像素
*/
public Pixel(long x, long y) {
this.x = x;
this.y = y;
}
}
package com.demo.process;
import com.demo.model.render.Pixel;
import com.demo.model.render.Tile;
import com.demo.util.JtsUtils;
import com.demo.util.MercatorTransform;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import static java.lang.Math.max;
import static java.lang.Math.min;
/*************************************
*Class Name: Geoms2JpgTile
*Description: <多点、线、面生成瓦片>
*@author: Seminar
*@create: 2021/7/19
*@since 1.0.0
*************************************/
@Slf4j
public class Geoms2JpgTile {
private GeometryFactory gf = new GeometryFactory();
static MercatorTransform mercatorTransform = new MercatorTransform();
public static int WIDTH = 256;
public static int HEIGHT = 256;
public static int BACKCOLOR_WHITE = ((255 << 16) | ((255 << 8) | 255));
public static int BACKCOLOR_BLACK = ((0 << 16) | ((0 << 8) | 0));
// 多边形几何
String polygon;
// 线几何
String lineString;
// 多边几何
String multiPoint;
/**
* 初始化wkt
*/
public void initWkt() {
this.polygon = "POLYGON ((116.42486572265626 39.99500778093748, 116.51962280273439 39.886557705928475, 116.44546508789064 39.78110197709871, 116.31637573242189 39.818029898770206, 116.27655029296876 39.93817189499188, 116.42486572265626 39.99500778093748))";
this.lineString = "LINESTRING (117.18292236328126 40.16208338164619, 119.01489257812501 39.48284540453334)";
this.multiPoint = "MULTIPOINT ((115.48690795898439 40.12639098502455), (115.80139160156251 40.148438503139076), (115.83847045898439 39.9665957444875), (115.90850830078126 39.854937988531276), " +
"(115.98403930664062 39.816975090490004), (115.84808349609376 39.769491963709), (115.60638427734376 39.707186656826565), (115.44708251953126 39.82119422647455), " +
"(115.32348632812501 39.961332959837826), (115.36605834960939 40.09593265290902), (115.59951782226564 39.940277770390324), (115.74371337890626 39.842286020743394), " +
"(115.58715820312501 39.79271003204449), (115.76019287109376 39.7631584037253), (115.87280273437501 39.67759833072648), (115.96481323242189 40.18307014852534), " +
"(115.69152832031251 40.2155868104582), (115.63934326171876 40.073868105094846), (115.43060302734376 39.56547053068436), (115.66955566406251 39.470125122358176), " +
"(115.83709716796875 39.55911824217187), (115.91949462890626 39.44679856427205), (115.54046630859376 39.42346418978385), (115.07354736328125 39.63319206567459), " +
"(115.11474609375 40.092781012494065), (115.19439697265626 40.287906612507406), (114.98291015625001 39.83385008019448), (114.97467041015626 39.47224533091451), " +
"(115.27130126953126 39.38101803294523), (115.59265136718751 39.34067026099156))";
}
/**
* 面jpg瓦片生成
*
* @param zoom
* @throws IOException
* @throws ParseException
*/
public void polygon2Tile(String wkt, int zoom) throws IOException, ParseException {
Geometry geom = wkt2Geo(wkt);
Geometry envelope = geom.getEnvelope();
double lonMin = min(envelope.getCoordinates()[0].x, envelope.getCoordinates()[2].x);
double lonMax = max(envelope.getCoordinates()[0].x, envelope.getCoordinates()[2].x);
double latMin = min(envelope.getCoordinates()[0].y, envelope.getCoordinates()[2].y);
double latMax = max(envelope.getCoordinates()[0].y, envelope.getCoordinates()[2].y);
Tile t1 = latLng2Tile(lonMin, latMin, zoom);
Tile t2 = latLng2Tile(lonMax, latMax, zoom);
long tilexMin = min(t1.getX(), t2.getX());
long tileyMin = min(t1.getY(), t2.getY());
long tilexMax = max(t1.getX(), t2.getX());
long tileyMax = max(t1.getY(), t2.getY());
if (!new File("D:\\learn1\\geojson-demo\\jpg\\" + zoom).exists()) {
FileUtils.forceMkdir(new File("D:\\learn1\\geojson-demo\\jpg\\" + zoom));
}
log.info("zoom: {}, jpgNum: {}", zoom, (tilexMax - tilexMin + 1) * (tileyMax - tileyMin + 1));
for (long x = tilexMin; x <= tilexMax; x++) {
for (long y = tileyMin; y <= tileyMax; y++) {
log.info("x: {},y: {}", x, y);
Tile tile = new Tile(x, y, zoom);
Envelope enve = mercatorTransform.tile2Envelope(tile);
Geometry grid = gf.toGeometry(enve);
boolean intersects = grid.intersects(geom);
if (intersects) {
// 生成栅格瓦片jpg
Geometry inter = grid.intersection(geom);
double tempLatMin = enve.getMinY();
double tempLatMax = enve.getMaxY(); // 纬度
double tempLonMin = enve.getMinX(); // 经度
double tempLonMax = enve.getMaxX();
// 经纬度转像素坐标
Pixel p1 = mercatorTransform.geographic2Pixel(new Coordinate(tempLonMin, tempLatMin), zoom);
Pixel p2 = mercatorTransform.geographic2Pixel(new Coordinate(tempLonMax, tempLatMax), zoom);
long minX = min(p1.getX(), p2.getX());
long minY = min(p1.getY(), p2.getY());
long maxX = max(p1.getX(), p2.getX());
long maxY = max(p1.getY(), p2.getY());
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
// 生成默认图片
for (int h = 0; h < HEIGHT; h++) {
for (int w = 0; w < WIDTH; w++) {
// 可修改,黑色背景或者白色背景
image.setRGB(w, h, BACKCOLOR_BLACK);
}
}
//图像输出
// 填充面的像素
for (long x1 = minX; x1 <= maxX; x1++) {
for (long y1 = minY; y1 <= maxY; y1++) {
// 判断轨迹点是否位于面上
// 像素坐标转web墨卡托转Geom经纬度坐标
Coordinate coordinate = mercatorTransform.pixel2Geographic(new Pixel(x1, y1), zoom);
Point point = JtsUtils.createPoint(coordinate);
if (inter.contains(point)) {
int pw = (int) (x1 - 256 * x);
int ph = (int) (y1 - 256 * y);
int rgb = ((255 << 16) | ((0 << 8) | 0));
if (pw > 0 && pw < 256 && (ph > 0 && ph < 256)) {
image.setRGB(pw, ph, rgb);
}
}
}
}
//图像输出
ImageIO.write(image, "jpg", new File("D:\\learn1\\geojson-demo\\jpg\\" + zoom + "\\" + x + "_" + y + ".jpg"));
} /*else {
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
//单色通道提取
for (int h = 0; h < HEIGHT; h++) {
for (int w = 0; w < WIDTH; w++) {
image.setRGB(w, h, BACKCOLOR_BLACK);
}
}
//图像输出
ImageIO.write(image, "jpg", new File("D:\\learn1\\geojson-demo\\jpg\\" + zoom + "\\" + x + "_" + y + ".jpg"));
log.error("{} {} no datas", x, y);
}*/
}
}
}
/**
* 线生成jpg瓦片
*
* @param wkt wkt几何
* @param zoom 瓦片级别
* @throws IOException
* @throws ParseException
*/
public void lineString2Tile(String wkt, int zoom) throws IOException, ParseException {
Geometry geom = wkt2Geo(wkt);
Geometry envelope = geom.getEnvelope();
// 计算最大最小边界框经纬度
double lonMin = min(envelope.getCoordinates()[0].x, envelope.getCoordinates()[2].x);
double lonMax = max(envelope.getCoordinates()[0].x, envelope.getCoordinates()[2].x);
double latMin = min(envelope.getCoordinates()[0].y, envelope.getCoordinates()[2].y);
double latMax = max(envelope.getCoordinates()[0].y, envelope.getCoordinates()[2].y);
// 经纬度转web墨卡托坐标,转像素坐标,并计算瓦片号
Tile t1 = latLng2Tile(lonMin, latMin, zoom);
Tile t2 = latLng2Tile(lonMax, latMax, zoom);
// 计算x,y最大最小瓦片号
long tilexMin = min(t1.getX(), t2.getX());
long tileyMin = min(t1.getY(), t2.getY());
long tilexMax = max(t1.getX(), t2.getX());
long tileyMax = max(t1.getY(), t2.getY());
if (!new File("D:\\learn1\\geojson-demo\\jpg\\" + zoom).exists()) {
FileUtils.forceMkdir(new File("D:\\learn1\\geojson-demo\\jpg\\" + zoom));
}
log.info("zoom: {}, jpgNum: {}", zoom, (tilexMax - tilexMin + 1) * (tileyMax - tileyMin + 1));
for (long x = tilexMin; x <= tilexMax; x++) {
for (long y = tileyMin; y <= tileyMax; y++) {
Tile tile = new Tile(x, y, zoom);
Envelope enve = mercatorTransform.tile2Envelope(tile);
Geometry grid = gf.toGeometry(enve);
boolean intersects = grid.intersects(geom);
if (intersects) {
// 生成栅格瓦片jpg
double tempLatMin = enve.getMinY();
double tempLatMax = enve.getMaxY();
double tempLonMin = enve.getMinX(); // 经度
double tempLonMax = enve.getMaxX(); // 纬度
// 经纬度转像素坐标
Pixel p1 = mercatorTransform.geographic2Pixel(new Coordinate(tempLonMin, tempLatMin), zoom);
Pixel p2 = mercatorTransform.geographic2Pixel(new Coordinate(tempLonMax, tempLatMax), zoom);
long minX = min(p1.getX(), p2.getX());
long minY = min(p1.getY(), p2.getY());
long maxX = max(p1.getX(), p2.getX());
long maxY = max(p1.getY(), p2.getY());
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
// 生成默认图片
for (int h = 0; h < HEIGHT; h++) {
for (int w = 0; w < WIDTH; w++) {
// 可修改,黑色背景或者白色背景
image.setRGB(w, h, BACKCOLOR_WHITE);
}
}
//图像输出
// 填充线的像素
for (long x1 = minX; x1 <= maxX; x1++) {
for (long y1 = minY; y1 <= maxY; y1++) {
// 像素坐标转web墨卡托转Geom经纬度坐标
Coordinate coordinate = mercatorTransform.pixel2Geographic(new Pixel(x1, y1), zoom);
Point point = gf.createPoint(coordinate);
// 判断点是否在线上 geom.intersects(point)、point.within(geom) 这俩方法都不管用,以1/500分辨率当作误差范围
if (isPointOnSegment(point, gf.createPoint(geom.getCoordinates()[0]),
gf.createPoint(geom.getCoordinates()[1]), mercatorTransform.zoomToResolution(zoom) / 500)) {
// log.info("{}", JSON.toJSONString(point.getCoordinate()));
int pw = (int) (x1 - 256 * x);
int ph = (int) (y1 - 256 * y);
int rgb = ((0 << 16) | ((255 << 8) | 0)); // 绿色填充
if (pw > 0 && pw < 256 && (ph > 0 && ph < 256)) {
image.setRGB(pw, ph, rgb);
}
}
}
}
//图像输出
ImageIO.write(image, "jpg", new File("D:\\learn1\\geojson-demo\\jpg\\" + zoom + "\\" + x + "_" + y + ".jpg"));
} /*else {
// 构建默认图片
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
for (int h = 0; h < HEIGHT; h++) {
for (int w = 0; w < WIDTH; w++) {
// 可修改,黑色背景或者白色背景
image.setRGB(w, h, BACKCOLOR_WHITE);
}
}
//图像输出
ImageIO.write(image, "jpg", new File("D:\\learn1\\geojson-demo\\jpg\\" + zoom + "\\" + x + "_" + y + ".jpg"));
log.error("{} {} no datas", x, y);
}*/
}
}
}
/**
* 点生成栅格jpg瓦片
*
* @param zoom 瓦片级别
* @throws IOException
* @throws ParseException
*/
public void points2Tile(String wkt, int zoom) throws IOException, ParseException {
Geometry geom = wkt2Geo(wkt);
Geometry envelope = geom.getEnvelope();
// 计算最大最小边界框经纬度
double lonMin = min(envelope.getCoordinates()[0].x, envelope.getCoordinates()[2].x);
double lonMax = max(envelope.getCoordinates()[0].x, envelope.getCoordinates()[2].x);
double latMin = min(envelope.getCoordinates()[0].y, envelope.getCoordinates()[2].y);
double latMax = max(envelope.getCoordinates()[0].y, envelope.getCoordinates()[2].y);
// 经纬度转web墨卡托坐标,转像素坐标,并计算瓦片号
Tile t1 = latLng2Tile(lonMin, latMin, zoom);
Tile t2 = latLng2Tile(lonMax, latMax, zoom);
// 计算x,y最大最小瓦片号
long tilexMin = min(t1.getX(), t2.getX());
long tileyMin = min(t1.getY(), t2.getY());
long tilexMax = max(t1.getX(), t2.getX());
long tileyMax = max(t1.getY(), t2.getY());
if (!new File("D:\\learn1\\geojson-demo\\jpg\\" + zoom).exists()) {
FileUtils.forceMkdir(new File("D:\\learn1\\geojson-demo\\jpg\\" + zoom));
}
log.info("zoom: {}, jpgNum: {}", zoom, (tilexMax - tilexMin + 1) * (tileyMax - tileyMin + 1));
for (long x = tilexMin; x <= tilexMax; x++) {
for (long y = tileyMin; y <= tileyMax; y++) {
log.info("x: {},y: {}", x, y);
Tile tile = new Tile(x, y, zoom);
Envelope enve = mercatorTransform.tile2Envelope(tile);
Geometry grid = gf.toGeometry(enve);
boolean intersects = grid.intersects(geom);
// 生成栅格瓦片jpg
if (intersects) {
Geometry inter = grid.intersection(geom); // 点与瓦片的交集
// 构建默认图片
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
for (int h = 0; h < HEIGHT; h++) {
for (int w = 0; w < WIDTH; w++) {
// 可修改,黑色背景或者白色背景
image.setRGB(w, h, BACKCOLOR_WHITE);
}
}
//图像输出
// 填充点的像素
Coordinate[] intersectionPoints = inter.getCoordinates();
for (Coordinate coor : intersectionPoints) {
// 经纬度转像素坐标
Pixel pixel = mercatorTransform.geographic2Pixel(coor, zoom);
int pw = (int) (pixel.getX() - 256 * x);
int ph = (int) (pixel.getY() - 256 * y);
int rgb = ((0 << 16) | ((0 << 8) | 255)); // 蓝色填充
if (pw > 0 && pw < 256 && (ph > 0 && ph < 256)) {
image.setRGB(pw, ph, rgb);
}
}
//图像输出
ImageIO.write(image, "jpg", new File("D:\\learn1\\geojson-demo\\jpg\\" + zoom + "\\" + x + "_" + y + ".jpg"));
} /*else {
// 构建默认图片
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
for (int h = 0; h < HEIGHT; h++) {
for (int w = 0; w < WIDTH; w++) {
// 可修改,黑色背景或者白色背景
image.setRGB(w, h, BACKCOLOR_WHITE);
}
}
//图像输出
ImageIO.write(image, "jpg", new File("D:\\learn1\\geojson-demo\\jpg\\" + zoom + "\\" + x + "_" + y + ".jpg"));
log.error("{} {} no datas", x, y);
}*/
}
}
}
/**
* 判断点是否在线上
*
* @param a 点A
* @param start 线起点start
* @param end 线终点end
* @param resolution 误差范围m
* @return
*/
public boolean isPointOnSegment(Point a, Point start, Point end, double resolution) {
boolean flag = false;
double startAdis = JtsUtils.distance(a, start);
double endADis = JtsUtils.distance(a, end);
double dis = JtsUtils.distance(start, end);
if (startAdis + endADis >= dis - resolution && startAdis + endADis <= dis + resolution) {
return true;
}
return flag;
}
/**
* 计算经纬度所在瓦片号
*
* @param lon 经度
* @param lat 纬度
* @param zoom 瓦片级别
* @return
*/
public static Tile latLng2Tile(double lon, double lat, int zoom) {
// 经纬度转墨卡托
Coordinate mkt = mercatorTransform.geographic2Mercator(new Coordinate(lon, lat));
// 墨卡托转像素
Pixel pixel = mercatorTransform.mercator2Pixel(mkt, zoom);
// 像素坐标所在瓦片
Tile atTile = mercatorTransform.pixelAtTile(pixel);
atTile.setZ(zoom);
return atTile;
}
/**
* wkt 转geometry
*
* @param wkt
* @return
* @throws ParseException
*/
public Geometry wkt2Geo(String wkt) throws ParseException {
WKTReader reader = new WKTReader(gf);
Geometry geom = reader.read(wkt);
return geom;
}
public static void main(String[] args) throws IOException, ParseException {
Geoms2JpgTile geoms2JpgTile = new Geoms2JpgTile();
geoms2JpgTile.initWkt();
for (int i = 9; i <= 17; i++) {
if (i > 14) {
continue;
}
geoms2JpgTile.polygon2Tile(geoms2JpgTile.polygon, i);
geoms2JpgTile.lineString2Tile(geoms2JpgTile.lineString, i);
geoms2JpgTile.points2Tile(geoms2JpgTile.multiPoint, i);
}
}
}
参考