Java对点、线、面生成栅格瓦片jpg,并渲染呈现

39 篇文章 5 订阅
19 篇文章 7 订阅

这篇博客将介绍从前端HTML页面到后端预生成栅格瓦片jpg,并提供查询接口供前端html调用呈现效果图;

1. 效果图

随机画一个多边形,以这个多边形面进行栅格瓦片生成;
在这里插入图片描述

点线面的渲染效果图如下:

多点为蓝色,线为绿色,面为红色

在这里插入图片描述
面生成为背景黑色的栅格瓦片,点线生成为背景白色的栅格瓦片效果图如下:
在这里插入图片描述

红色面的渲染效果图如下:

级别小一些只有一张图,和级别大一些多张图拼合而成,背景色可以是白色的,也可以是黑色的~;

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

蓝色点的渲染效果图如下:
在这里插入图片描述

级别大一些蓝色点的渲染效果图如下:
在这里插入图片描述

绿色线的渲染效果图如下:(1/500的分辨率认为点在线上)在这里插入图片描述
1/20分辨率距离则认为点在线上效果图,看起来线要宽一些;
在这里插入图片描述

2. 原理

2.1 面瓦片的生成

  1. 先计算多边形面的Geometry经纬度范围(外接矩形的左上角,右下角坐标);
  2. 经纬度坐标转web墨卡托坐标;
  3. 指定某一级别计算瓦片号范围;
  4. 分别遍历每一个瓦片(计算瓦片范围与多边形面是否有交集,没有交集生成一张空白图;有交集遍历每一个像素点转换为web墨卡托坐标,转换为Geometry坐标,判断点是否在多边形面上,在设置当前像素点颜色;不在给空白);
  5. 循环遍历多个级别,重复1~4步骤,即可生成多个不同级别

2.2 线瓦片的生成

  1. 先计算 多线 的Geometry经纬度范围(外接矩形的左上角,右下角坐标);
  2. 经纬度坐标转web墨卡托坐标;
  3. 指定某一级别计算瓦片号范围;
  4. 分别遍历每一个瓦片(计算瓦片范围与 线 是否有交集,没有交集生成一张空白图;有交集遍历每一个像素点转换为web墨卡托坐标,转换为Geometry 点坐标, 判断点是否在线上 ,在设置当前像素点颜色;不在给空白);
  5. 循环遍历多个级别,重复1~4步骤,即可生成多个不同级别

判断点是否在线上需要注意,可参考谷歌js提供的算法,isPointOnSegment 计算距离允许误差在分辨率范围内,则标识在线上;

2.3 多点瓦片的生成

  1. 先计算 多点 的Geometry经纬度范围(外接矩形的左上角,右下角坐标);
  2. 经纬度坐标转web墨卡托坐标;
  3. 指定某一级别计算瓦片号范围;
  4. 分别遍历每一个瓦片(计算瓦片范围与 多点 是否有交集,没有交集生成一张空白图;有交集 求瓦片范围与多点的交集点,然后遍历交集点,判断点是否在线上 ,在设置当前像素点颜色;不在给空白);
  5. 循环遍历多个级别,重复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);
        }
    }
}

参考

  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序媛一枚~

您的鼓励是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值