zhouyuexiang 1 год назад
Родитель
Сommit
2f366cac1a

+ 61 - 2
.gitignore

@@ -1,2 +1,61 @@
-/.idea/
-/log/
+######################################################################
+# Build Tools
+
+.gradle
+/build/
+!gradle/wrapper/gradle-wrapper.jar
+
+target/
+!.mvn/wrapper/maven-wrapper.jar
+
+######################################################################
+# IDE
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+### 通用 ###
+*.class
+rebel.xml
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
+
+nbproject/private/
+build/*
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+
+######################################################################
+# Others
+*.log
+*.xml.versionsBackup
+*.swp
+
+!*/build/*.java
+!*/build/*.html
+!*/build/*.xml

+ 5 - 8
cql-service/pom.xml

@@ -14,16 +14,12 @@
     <dependencies>
 
         <dependency>
-            <groupId>com.alibaba</groupId>
-            <artifactId>fastjson</artifactId>
-            <version>1.2.60</version>
+            <groupId>cn.com.taiji</groupId>
+            <artifactId>tile-service</artifactId>
+            <version>1.0</version>
         </dependency>
 
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-            <version>1.18.20</version>
-        </dependency>
+
 
         <dependency>
             <groupId>cn.hutool</groupId>
@@ -39,6 +35,7 @@
             <artifactId>spring-boot-starter-web</artifactId>
         </dependency>
 
+
         <dependency>
             <groupId>org.geotools</groupId>
             <artifactId>gt-main</artifactId>

+ 2 - 2
cql-service/src/main/java/cn/com/taiji/cql/service/impl/TileServiceImpl.java

@@ -4,6 +4,7 @@ import cn.com.taiji.cql.model.GeoDataSource;
 import cn.com.taiji.cql.model.GeoRequestParam;
 import cn.com.taiji.cql.service.IECqlService;
 import cn.com.taiji.cql.service.ITileService;
+import cn.com.taiji.tile.util.TileUtils;
 import com.alibaba.fastjson.JSONObject;
 import lombok.extern.slf4j.Slf4j;
 import org.geotools.jdbc.JDBCDataStoreFactory;
@@ -71,10 +72,9 @@ public class TileServiceImpl implements ITileService {
             List<Map<String, Object>> cqlDataList = ecqlService.cqlQuery(cqlDsParams,filterCql);
 
             if(cqlDataList.size() >0){
-
                 //3根据空间地理数据生成图层二进制数据
-
                 System.out.println("返回的数据:"+cqlDataList.toString());
+                return TileUtils.getTile(cqlDataList, requestParam.getBbox());
 
             }else{
 


+ 31 - 1
pom.xml

@@ -9,12 +9,14 @@
     <version>1.0</version>
     <modules>
         <module>cql-service</module>
+        <module>tile-service</module>
     </modules>
     <packaging>pom</packaging>
 
     <properties>
         <spring-boot-dependencies.version>2.5.5</spring-boot-dependencies.version>
         <geotools.version>30.0</geotools.version>
+        <lombok.version>1.18.28</lombok.version>
     </properties>
 
     <dependencyManagement>
@@ -37,6 +39,11 @@
                 <artifactId>gt-main</artifactId>
                 <version>${geotools.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.projectlombok</groupId>
+                <artifactId>lombok</artifactId>
+                <version>${lombok.version}</version>
+            </dependency>
         </dependencies>
 
     </dependencyManagement>
@@ -52,7 +59,30 @@
         </pluginManagement>
     </build>
 
-
+    <repositories>
+        <repository>
+            <id>osgeo</id>
+            <name>OSGeo Release Repository</name>
+            <url>https://repo.osgeo.org/repository/release/</url>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+        </repository>
+        <repository>
+            <id>osgeo-snapshot</id>
+            <name>OSGeo Snapshot Repository</name>
+            <url>https://repo.osgeo.org/repository/snapshot/</url>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+        </repository>
+    </repositories>
 
 
 </project>

+ 91 - 0
tile-service/pom.xml

@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>cn.com.taiji</groupId>
+        <artifactId>ecql-service</artifactId>
+        <version>1.0</version>
+    </parent>
+
+    <artifactId>tile-service</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.geotools</groupId>
+            <artifactId>gt-shapefile</artifactId>
+            <version>${geotools.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.geotools</groupId>
+            <artifactId>gt-epsg-hsql</artifactId>
+            <version>${geotools.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.geotools</groupId>
+            <artifactId>gt-swing</artifactId>
+            <version>${geotools.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.geotools</groupId>
+            <artifactId>gt-geotiff</artifactId>
+            <version>${geotools.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.geotools</groupId>
+            <artifactId>gt-image</artifactId>
+            <version>${geotools.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.geotools</groupId>
+            <artifactId>gt-wms</artifactId>
+            <version>${geotools.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.geotools</groupId>
+            <artifactId>gt-wmts</artifactId>
+            <version>${geotools.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.geotools</groupId>
+            <artifactId>gt-elasticsearch</artifactId>
+            <version>${geotools.version}</version>
+        </dependency>
+
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.60</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <!-- 数据库相关  -->
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.7.30</version>
+        </dependency>
+
+
+    </dependencies>
+
+
+
+
+</project>

+ 76 - 0
tile-service/src/main/java/cn/com/taiji/tile/model/AggsResult.java

@@ -0,0 +1,76 @@
+
+package cn.com.taiji.tile.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+import java.util.Map;
+
+@JsonIgnoreProperties(
+        ignoreUnknown = true
+)
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class AggsResult {
+    @JsonProperty("centroid")
+    private Centroid centroid;
+    @JsonProperty("large-grid")
+    private LargeGrid largeGrid;
+    @JsonProperty("total")
+    private Total total;
+    private Map<String, Object> group;
+    private String count;
+    private String lat;
+    private String lon;
+
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class Buckets {
+        @JsonProperty("key")
+        private String key;
+        @JsonProperty("doc_count")
+        private long docCount;
+    }
+
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class LargeGrid {
+        @JsonProperty("buckets")
+        private List<Buckets> buckets;
+    }
+
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class Total {
+        @JsonProperty("doc_count")
+        private long total;
+    }
+
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class CentroidLocation {
+        @JsonProperty("lat")
+        private String lat;
+        @JsonProperty("lon")
+        private String lon;
+    }
+
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class Centroid {
+        @JsonProperty("count")
+        private String count;
+        @JsonProperty("location")
+        private CentroidLocation location;
+    }
+}

+ 31 - 0
tile-service/src/main/java/cn/com/taiji/tile/model/POI.java

@@ -0,0 +1,31 @@
+package cn.com.taiji.tile.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author zzyx
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class POI {
+    private String id;
+    private double lon;
+    private double lat;
+    private String shape;
+    private String pcolor;
+    private String name;
+    private String layername;
+    private boolean showTitle;
+    private String markerPath;
+    private String markerFilePath;
+    private String markerFileName;
+    private int markerWidth;
+    private int markerHeigth;
+
+    public boolean isShowTitle() {
+        return this.showTitle;
+    }
+}

+ 129 - 0
tile-service/src/main/java/cn/com/taiji/tile/model/Point.java

@@ -0,0 +1,129 @@
+package cn.com.taiji.tile.model;
+
+import lombok.Data;
+
+@Data
+public class Point {
+    private double x;
+    private double y;
+    private double z;
+
+    public Point(double x, double y, boolean round) {
+        this.x = round ? Math.round(x) : x;
+        this.y = round ? Math.round(y) : y;
+    }
+
+    public Point(double x, double y) {
+        this(x, y, false);
+    }
+
+    public Point(double x, double y, double z) {
+        this(x, y, false);
+        this.z = z;
+    }
+
+    public Point(Point p) {
+        this(p.x, p.y);
+    }
+
+
+    public Point(int[] p) {
+        this(p[0], p[1]);
+    }
+
+
+    public Point clone() {
+        return new Point(this.x, this.y);
+    }
+
+    public Point add(Point point) {
+        return clone()._add(new Point(point));
+    }
+
+
+    private Point _add(Point point) {
+        this.x += point.x;
+        this.y += point.y;
+        return this;
+    }
+
+    public Point subtract(Point point) {
+        return clone()._subtract(point);
+    }
+
+    Point _subtract(Point point) {
+        this.x -= point.x;
+        this.y -= point.y;
+        return this;
+    }
+
+    public Point divideBy(double num) {
+        return clone()._divideBy(num);
+    }
+
+    private Point _divideBy(double num) {
+        this.x /= num;
+        this.y /= num;
+        return this;
+    }
+
+    public Point multiplyBy(double num) {
+        return clone()._multiplyBy(num);
+    }
+
+    private Point _multiplyBy(double num) {
+        this.x *= num;
+        this.y *= num;
+        return this;
+    }
+
+    public Point scaleBy(Point point) {
+        return new Point(this.x * point.x, this.y * point.y);
+    }
+
+    public Point unscaleBy(Point point) {
+        return new Point(this.x / point.x, this.y / point.y);
+    }
+
+    public Point round() {
+        return clone()._round();
+    }
+
+    Point _round() {
+        this.x = Math.round(this.x);
+        this.y = Math.round(this.y);
+        return this;
+    }
+
+    public Point floor() {
+        return clone()._floor();
+    }
+
+    private Point _floor() {
+        this.x = Math.floor(this.x);
+        this.y = Math.floor(this.y);
+        return this;
+    }
+
+
+    public Point ceil() {
+        return clone()._ceil();
+    }
+
+    private Point _ceil() {
+        this.x = Math.ceil(this.x);
+        this.y = Math.ceil(this.y);
+        return this;
+    }
+
+
+    public double distanceTo(Point point) {
+        double x = point.x - this.x;
+        double y = point.y - this.y;
+        return Math.sqrt(x * x + y * y);
+    }
+
+    public boolean contains(Point point) {
+        return (Math.abs(point.x) <= Math.abs(this.x) && Math.abs(point.y) <= Math.abs(this.y));
+    }
+}

+ 434 - 0
tile-service/src/main/java/cn/com/taiji/tile/util/GeoUtils.java

@@ -0,0 +1,434 @@
+package cn.com.taiji.tile.util;
+
+import com.github.davidmoten.geo.GeoHash;
+import com.github.davidmoten.geo.LatLong;
+import org.geotools.referencing.GeodeticCalculator;
+import org.geotools.referencing.datum.DefaultEllipsoid;
+import org.geotools.util.logging.Logging;
+import org.locationtech.jts.geom.*;
+import org.locationtech.jts.io.ParseException;
+import org.locationtech.jts.io.WKTReader;
+
+import java.awt.geom.Point2D;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class GeoUtils {
+    private static final Logger LOGGER = Logging.getLogger(GeoUtils.class);
+    private static final Pattern GEO_POINT_PATTERN = Pattern.compile("\\s*([-+]?\\d*\\.?\\d*)[^-+\\d.]+([-+]?\\d*\\.?\\d*)\\s*");
+    private static final Pattern GEO_HASH_PATTERN = Pattern.compile("[0123456789bcdefghjkmnpqrstuvwxyz]+");
+    private static final Pattern ELASTIC_DISTANCE_PATTERN = Pattern.compile("([0-9]+(\\.[0-9]+)?)([a-zA-Z]*)");
+    private static final double CIRCLE_INTERPOLATION_INTERVAL = 500.0;
+    private static final int MAX_CIRCLE_POINTS = 500;
+    private static final int MIN_CIRCLE_POINTS = 40;
+    private static final double MIN_CIRCLE_RADIUS_M = 0.001;
+    private final GeodeticCalculator geodeticCalculator;
+    private static final Pattern WKT_PATTERN = Pattern.compile("POINT.*|LINESTRING.*|POLYGON.*|MULTIPOINT.*|MULTILINESTRING.*|MULTIPOLYGON.*|GEOMETRYCOLLECTION.*");
+    private final GeometryFactory geometryFactory = new GeometryFactory();
+    private final WKTReader wktReader;
+    private static String s;
+    static final Map<String, Double> UNITS_MAP = new HashMap<String, Double>() {
+        private static final long serialVersionUID = 1L;
+
+        {
+            this.put("millimeter", 0.001);
+            this.put("mm", 0.001);
+            this.put("cm", 0.01);
+            this.put("m", 1.0);
+            this.put("kilometers", 1000.0);
+            this.put("kilometer", 1000.0);
+            this.put("km", 1000.0);
+            this.put("in", 0.0254);
+            this.put("ft", 0.3048);
+            this.put("feet", 0.3048);
+            this.put("yd", 0.9144);
+            this.put("mi", 1609.344);
+            this.put("miles", 1609.344);
+            this.put("NM", 1852.0);
+            this.put("nmi", 1852.0);
+        }
+    };
+    private static GeoUtils _this;
+
+    private GeoUtils() {
+        this.geodeticCalculator = new GeodeticCalculator(DefaultEllipsoid.WGS84);
+        this.wktReader = new WKTReader();
+    }
+
+    public static GeoUtils getGeoUtils() {
+        if (_this == null) {
+            _this = new GeoUtils();
+        }
+
+        return _this;
+    }
+
+    public Point createPoint(double x, double y) {
+        return this.geometryFactory.createPoint(new Coordinate(x, y));
+    }
+
+    public Geometry createGeometry(Object obj) {
+        Object geometry;
+        double x;
+        double y;
+        if (obj instanceof String) {
+            String ms = obj + "";
+            if (ms.length() > 65536) {
+                ms = ms.substring(0, 65536);
+            }
+
+            Matcher listMatcher = GEO_POINT_PATTERN.matcher(ms);
+            if (listMatcher.matches()) {
+                x = Double.valueOf(listMatcher.group(1));
+                y = Double.valueOf(listMatcher.group(2));
+                geometry = this.geometryFactory.createPoint(new Coordinate(y, x));
+            } else if (GEO_HASH_PATTERN.matcher(ms).matches()) {
+                LatLong latLon = GeoHash.decodeHash(ms);
+                Coordinate geoPoint = new Coordinate(latLon.getLon(), latLon.getLat());
+                y = geoPoint.y;
+                double lon = geoPoint.x;
+                geometry = this.geometryFactory.createPoint(new Coordinate(lon, y));
+            } else if (WKT_PATTERN.matcher(ms).matches()) {
+                Geometry geom;
+                try {
+                    geom = this.wktReader.read((String)obj);
+                } catch (ParseException var13) {
+                    geom = null;
+                }
+
+                geometry = geom;
+            } else {
+                geometry = null;
+            }
+        } else if (obj instanceof List && ((List)obj).size() == 2) {
+            List<?> values = (List)obj;
+            if (Number.class.isAssignableFrom(values.get(0).getClass())) {
+                x = ((Number)values.get(0)).doubleValue();
+                y = ((Number)values.get(1)).doubleValue();
+                geometry = this.geometryFactory.createPoint(new Coordinate(x, y));
+            } else if (values.get(0) instanceof String) {
+                x = Double.valueOf((String)values.get(0));
+                y = Double.valueOf((String)values.get(1));
+                geometry = this.geometryFactory.createPoint(new Coordinate(x, y));
+            } else {
+                geometry = null;
+            }
+        } else if (obj instanceof Map) {
+            geometry = this.createGeometry((Map)obj);
+        } else {
+            geometry = null;
+        }
+
+        return (Geometry)geometry;
+    }
+
+    public Geometry createGeometry(String geometryType, Coordinate[][] coordinates, String radius) {
+        switch (geometryType.toUpperCase()) {
+            case "MULTIPOLYGON":
+                Polygon[] polygons = new Polygon[coordinates.length];
+
+                for(int i = 0; i < coordinates.length; ++i) {
+                    polygons[i] = this.geometryFactory.createPolygon(coordinates[i]);
+                }
+
+                return this.geometryFactory.createMultiPolygon(polygons);
+            case "ENVELOPE":
+                Envelope envelope = new Envelope(coordinates[0][0], coordinates[0][1]);
+                return this.geometryFactory.toGeometry(envelope);
+            case "POINT":
+                return this.geometryFactory.createPoint(coordinates[0][0]);
+            case "POLYGON":
+                return this.geometryFactory.createPolygon(coordinates[0]);
+            case "MULTILINESTRING":
+                LineString[] lineStrings = new LineString[coordinates.length];
+
+                for(int i = 0; i < coordinates.length; ++i) {
+                    lineStrings[i] = this.geometryFactory.createLineString(coordinates[i]);
+                }
+
+                return this.geometryFactory.createMultiLineString(lineStrings);
+            case "LINESTRING":
+                return this.geometryFactory.createLineString(coordinates[0]);
+            case "MULTIPOINT":
+                this.geometryFactory.createMultiPointFromCoords(coordinates[0]);
+            case "CIRCLE":
+                return this.createCircle(coordinates[0][0], radius);
+            default:
+                return null;
+        }
+    }
+
+    public Geometry createGeometry(Map<String, Object> properties) {
+        Object geometry;
+        List list;
+        Coordinate[] coords;
+        Coordinate coordinate;
+        int i;
+        switch (String.valueOf(properties.get("type")).toUpperCase()) {
+            case "POINT":
+                list = (List)properties.get("coordinates");
+                coordinate = this.createCoordinate(list);
+                geometry = this.geometryFactory.createPoint(coordinate);
+                break;
+            case "LINESTRING":
+                list = (List)properties.get("coordinates");
+                coords = this.createCoordinates(list);
+                geometry = this.geometryFactory.createLineString(coords);
+                break;
+            case "POLYGON":
+                list = (List)properties.get("coordinates");
+                geometry = this.createPolygon(list);
+                break;
+            case "MULTIPOINT":
+                list = (List)properties.get("coordinates");
+                coords = this.createCoordinates(list);
+                geometry = this.geometryFactory.createMultiPointFromCoords(coords);
+                break;
+            case "MULTILINESTRING":
+                list = (List)properties.get("coordinates");
+                LineString[] lineStrings = new LineString[list.size()];
+
+                for(i = 0; i < list.size(); ++i) {
+                    Coordinate[] coordinates = this.createCoordinates((List)list.get(i));
+                    lineStrings[i] = this.geometryFactory.createLineString(coordinates);
+                }
+
+                geometry = this.geometryFactory.createMultiLineString(lineStrings);
+                break;
+            case "MULTIPOLYGON":
+                list = (List)properties.get("coordinates");
+                Polygon[] polygons = new Polygon[list.size()];
+
+                for(i = 0; i < list.size(); ++i) {
+                    polygons[i] = this.createPolygon((List)list.get(i));
+                }
+
+                geometry = this.geometryFactory.createMultiPolygon(polygons);
+                break;
+            case "GEOMETRYCOLLECTION":
+                list = (List)properties.get("geometries");
+                Geometry[] geometries = new Geometry[list.size()];
+
+                for(i = 0; i < geometries.length; ++i) {
+                    geometries[i] = this.createGeometry((Map)list.get(i));
+                }
+
+                geometry = this.geometryFactory.createGeometryCollection(geometries);
+                break;
+            case "ENVELOPE":
+                list = (List)properties.get("coordinates");
+                coords = this.createCoordinates(list);
+                Envelope envelope = new Envelope(coords[0], coords[1]);
+                geometry = this.geometryFactory.toGeometry(envelope);
+                break;
+            case "CIRCLE":
+                list = (List)properties.get("coordinates");
+                String radius = (String)properties.get("radius");
+                coordinate = this.createCoordinate(list);
+                geometry = this.createCircle(coordinate, radius);
+                break;
+            default:
+                Object latObj = properties.get("lat");
+                Object lonObj = properties.get("lon");
+                if (latObj != null && lonObj != null) {
+                    Double lat;
+                    if (latObj instanceof Number) {
+                        lat = ((Number)latObj).doubleValue();
+                    } else if (latObj instanceof String) {
+                        lat = new Double((String)latObj);
+                    } else {
+                        lat = null;
+                    }
+
+                    Double lon;
+                    if (lonObj instanceof Number) {
+                        lon = ((Number)lonObj).doubleValue();
+                    } else if (lonObj instanceof String) {
+                        lon = new Double((String)lonObj);
+                    } else {
+                        lon = null;
+                    }
+
+                    if (lat != null && lon != null) {
+                        geometry = this.geometryFactory.createPoint(new Coordinate(lon, lat));
+                    } else {
+                        geometry = null;
+                    }
+                } else {
+                    geometry = null;
+                }
+        }
+
+        return (Geometry)geometry;
+    }
+
+    private Polygon createPolygon(List<List<Object>> posList) {
+        Coordinate[] shellCoordinates = this.createCoordinates((List)posList.get(0));
+        LinearRing shell = this.geometryFactory.createLinearRing(shellCoordinates);
+        LinearRing[] holes = new LinearRing[posList.size() - 1];
+
+        for(int i = 1; i < posList.size(); ++i) {
+            Coordinate[] coordinates = this.createCoordinates((List)posList.get(i));
+            holes[i - 1] = this.geometryFactory.createLinearRing(coordinates);
+        }
+
+        return this.geometryFactory.createPolygon(shell, holes);
+    }
+
+    private Coordinate[] createCoordinates(List<List<Object>> posList) {
+        Coordinate[] coordinates = new Coordinate[posList.size()];
+
+        for(int i = 0; i < posList.size(); ++i) {
+            coordinates[i] = this.createCoordinate((List)posList.get(i));
+        }
+
+        return coordinates;
+    }
+
+    private Coordinate createCoordinate(List<Object> posList) {
+        if (posList == null) {
+            return null;
+        } else {
+            double x;
+            double y;
+            if (Number.class.isAssignableFrom(posList.get(0).getClass())) {
+                x = ((Number)posList.get(0)).doubleValue();
+                y = ((Number)posList.get(1)).doubleValue();
+            } else {
+                x = Double.valueOf(posList.get(0).toString());
+                y = Double.valueOf(posList.get(1).toString());
+            }
+
+            return new Coordinate(x, y);
+        }
+    }
+
+    public List<Object> readField(Map<String, Object> source, String name) {
+        List<String> keys = Arrays.asList(name.split("\\."));
+        List<Object> values = new ArrayList();
+        if (!keys.isEmpty()) {
+            Object entry = source.get(keys.get(0));
+            if (entry == null) {
+                this.readField(source.get(name), new ArrayList(), values);
+            } else {
+                this.readField(entry, keys.subList(1, keys.size()), values);
+            }
+        }
+
+        List<Object> result;
+        if (!values.isEmpty()) {
+            result = values;
+        } else {
+            result = null;
+        }
+
+        return result;
+    }
+
+    private void readField(Object entry, List<String> keys, List<Object> values) {
+        if (entry != null && List.class.isAssignableFrom(entry.getClass())) {
+            Iterator var6 = ((List)entry).iterator();
+
+            while(var6.hasNext()) {
+                Object object = var6.next();
+                this.readField(object, keys, values);
+            }
+        } else if (entry != null && !keys.isEmpty() && Map.class.isAssignableFrom(entry.getClass())) {
+            Object nextEntry = ((Map)entry).get(keys.get(0));
+            List<String> newKeys = keys.subList(1, keys.size());
+            this.readField(nextEntry, newKeys, values);
+        } else if (entry != null) {
+            values.add(entry);
+        }
+
+    }
+
+    public static boolean isGeoPointFeature(Map<String, Object> map) {
+        boolean result = false;
+        if (map.size() == 2 && map.containsKey("coordinates")) {
+            try {
+                result = "geo_point".equals(((Map)map.get("coordinates")).get("type"));
+            } catch (Exception var3) {
+            }
+        }
+
+        return result;
+    }
+
+    public static String urlDecode(String value) {
+        try {
+            value = URLDecoder.decode(value, StandardCharsets.UTF_8.toString());
+        } catch (UnsupportedEncodingException var2) {
+            LOGGER.warning("Unable to encode value(s): " + var2);
+        }
+
+        return value;
+    }
+
+    private Geometry createCircle(Coordinate centreCoord, String radius) {
+        if (centreCoord == null) {
+            return null;
+        } else {
+            double radM;
+            try {
+                radM = convertToMeters(radius);
+            } catch (Exception var15) {
+                return null;
+            }
+
+            if (radM < 0.001) {
+                return null;
+            } else {
+                double circumferance = radM * 2.0 * Math.PI;
+                int numPoints = (int)(circumferance / 500.0);
+                numPoints = Math.max(40, numPoints);
+                numPoints = Math.min(500, numPoints);
+                double angularIncrement = 360.0 / (double)numPoints;
+                this.geodeticCalculator.setStartingGeographicPoint(centreCoord.x, centreCoord.y);
+                Coordinate[] linearRingCoords = new Coordinate[numPoints + 1];
+                double angle = 0.0;
+
+                for(int i = 0; i < numPoints; ++i) {
+                    this.geodeticCalculator.setDirection(angle, radM);
+                    Point2D point2D = this.geodeticCalculator.getDestinationGeographicPoint();
+                    linearRingCoords[i] = new Coordinate(point2D.getX(), point2D.getY());
+                    angle += angularIncrement;
+                }
+
+                linearRingCoords[numPoints] = linearRingCoords[0];
+                LinearRing linearRing = this.geometryFactory.createLinearRing(linearRingCoords);
+                return this.geometryFactory.createPolygon(linearRing);
+            }
+        }
+    }
+
+    static double convertToMeters(String distanceWithUnit) throws IllegalArgumentException {
+        if (distanceWithUnit != null && !distanceWithUnit.isEmpty()) {
+            Matcher matcher = ELASTIC_DISTANCE_PATTERN.matcher(distanceWithUnit);
+            if (matcher.matches()) {
+                double distance = Double.valueOf(matcher.group(1));
+                String unit = matcher.group(3);
+                Double conversion = (Double)UNITS_MAP.get(unit);
+                if (conversion == null) {
+                    if (unit != null && !unit.isEmpty()) {
+                        throw new IllegalArgumentException("Illegal unit: " + unit);
+                    }
+
+                    conversion = 1.0;
+                }
+
+                return distance * conversion;
+            } else {
+                throw new IllegalArgumentException("Distance string argument has incorrect format");
+            }
+        } else {
+            throw new IllegalArgumentException("Null of zero length distance string argument");
+        }
+    }
+
+}

+ 46 - 0
tile-service/src/main/java/cn/com/taiji/tile/util/HotImageTile.java

@@ -0,0 +1,46 @@
+package cn.com.taiji.tile.util;
+
+import cn.com.taiji.tile.model.POI;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+
+public class HotImageTile {
+
+    public byte[] setHotImage(List<POI> poiList, String bboxStr) {
+        double[] matrix = new double[65536];
+        double[] bbox = new double[4];
+        if (StringUtils.isNotBlank(bboxStr)) {
+            String[] split = bboxStr.split(",");
+            for (int i = 0; i < split.length; i++) {
+                bbox[i] = Double.parseDouble(split[i]);
+            }
+        }
+        for (POI poi : poiList) {
+            int[] pxy = TileUtils.toPixelXY(poi.getLon(), poi.getLat(), bbox[0], bbox[1], bbox[2], bbox[3]);
+            HotImageTileUtils.press(matrix, pxy[0], pxy[1], 1);
+        }
+        double presure = 0.0D;
+        BufferedImage image = new BufferedImage(256, 256, 2);
+        for (int x = 0; x < 256; x++) {
+            for (int y = 0; y < 256; y++) {
+                presure = matrix[x * 256 + y];
+                if (presure > 0.0D) {
+                    image.setRGB(x, y, HotImageTileUtils.toRGB(presure).getRGB());
+                }
+            }
+        }
+        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        try {
+            ImageIO.write(image, "png", buffer);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return buffer.toByteArray();
+    }
+}

+ 109 - 0
tile-service/src/main/java/cn/com/taiji/tile/util/HotImageTileUtils.java

@@ -0,0 +1,109 @@
+package cn.com.taiji.tile.util;
+
+import java.awt.*;
+import java.awt.image.*;
+import java.util.Map;
+import java.util.TreeMap;
+
+
+public class HotImageTileUtils {
+    private static final Color rbg0_5 = new Color(0, 180, 0, 20);
+    private static final Color rbg5_10 = new Color(0, 200, 0, 40);
+    private static final Color rbg10_25 = new Color(50, 255, 0, 80);
+    private static final Color rbg25_50 = new Color(0, 255, 0, 160);
+    private static final Color rbg50_100 = new Color(255, 255, 0, 185);
+    private static final Color rbg100_125 = new Color(255, 213, 0, 200);
+    private static final Color rbg125_150 = new Color(255, 171, 0, 215);
+    private static final Color rbg125_150_2 = new Color(255, 129, 0, 225);
+    private static final Color rbg150_175 = new Color(255, 87, 0, 235);
+    private static final Color rbg175_200 = new Color(255, 42, 0, 245);
+    private static final Color rbg200_ = new Color(255, 0, 0, 255);
+    private static final RGBTable pressures = new RGBTable(64);
+    private static final RGBTable pressuresColor = new RGBTable(5);
+    private static final TreeMap<Double, Color> colors = new TreeMap<>();
+
+    static {
+        colors.put(Double.valueOf("0.0D"), new Color(0, 0, 0, 0));
+        colors.put(Double.valueOf("0.1D"), rbg0_5);
+        colors.put(Double.valueOf("3.0D"), rbg5_10);
+        colors.put(Double.valueOf("15.0D"), rbg10_25);
+        colors.put(Double.valueOf("25.0D"), rbg25_50);
+        colors.put(Double.valueOf("35.0D"), rbg50_100);
+        colors.put(Double.valueOf("55.0D"), rbg100_125);
+        colors.put(Double.valueOf("85.0D"), rbg125_150);
+        colors.put(Double.valueOf("125.0D"), rbg125_150_2);
+        colors.put(Double.valueOf("135.0D"), rbg150_175);
+        colors.put(Double.valueOf("145.0D"), rbg175_200);
+        colors.put(Double.valueOf("150.0D"), rbg200_);
+    }
+
+    public static boolean gradual = false;
+
+    public static void press(double[] matrix, int px, int py, int w) {
+        for (int dx = -64; dx <= 64; dx++) {
+            for (int dy = -64; dy <= 64; dy++) {
+                int x = px + dx, y = py + dy;
+                if (0 <= x && x < 256 && 0 <= y && y < 256) {
+                    matrix[x * 256 + y] = matrix[x * 256 + y] + w * pressures.getPressure(dx, dy);
+                }
+            }
+        }
+    }
+
+
+    public static Color toRGB(double presure) {
+        Map.Entry<Double, Color> floor = colors.floorEntry(Double.valueOf(presure));
+        Map.Entry<Double, Color> ceiling = colors.ceilingEntry(Double.valueOf(presure));
+        if (floor == null) {
+            return ceiling.getValue();
+        }
+        if (ceiling == null) {
+            return floor.getValue();
+        }
+        if (floor.getKey().equals(ceiling.getKey())) {
+            return floor.getValue();
+        }
+        float factor = (float) ((presure - ((Double) floor.getKey()).doubleValue()) / (((Double) ceiling.getKey()).doubleValue() - ((Double) floor.getKey()).doubleValue()));
+        return mix(factor, floor.getValue(), ceiling.getValue());
+    }
+
+
+    private static Color mix(float factor, Color color1, Color color2) {
+        int r = (int) (color1.getRed() * (1.0F - factor) + color2.getRed() * factor);
+        int g = (int) (color1.getGreen() * (1.0F - factor) + color2.getGreen() * factor);
+        int b = (int) (color1.getBlue() * (1.0F - factor) + color2.getBlue() * factor);
+        int a = (int) (color1.getAlpha() * (1.0F - factor) + color2.getAlpha() * factor);
+        return new Color(r, g, b, a);
+    }
+
+
+    private static BufferedImage blur(BufferedImage source, int radius) {
+        BufferedImage img = new BufferedImage(source.getWidth() + radius * 2, source.getHeight() + radius * 2, 3);
+        Graphics2D g2 = (Graphics2D) img.getGraphics();
+        g2.setColor(new Color(0, 0, 0, 0));
+        g2.fillRect(0, 0, source.getWidth() + radius * 2, source.getHeight() + radius * 2);
+        g2.drawImage(source, radius, radius, (ImageObserver) null);
+        g2.dispose();
+        int square = radius * radius;
+        float sum = 0.0F;
+        float[] matrix = new float[square];
+        int i;
+        for (i = 0; i < square; i++) {
+            int dx = i % radius - radius / 2;
+            int dy = i / radius - radius / 2;
+            matrix[i] = (float) (radius - Math.sqrt((dx * dx + dy * dy)));
+            sum += matrix[i];
+        }
+        for (i = 0; i < square; i++) {
+            matrix[i] = matrix[i] / sum;
+        }
+        BufferedImageOp op = new ConvolveOp(new Kernel(radius, radius, matrix), 0, null);
+        BufferedImage res = op.filter(img, null);
+        BufferedImage out = new BufferedImage(source.getWidth(), source.getHeight(), 6);
+        Graphics2D g3 = (Graphics2D) out.getGraphics();
+        g3.drawImage(res, -radius, -radius, (ImageObserver) null);
+        g3.dispose();
+        return out;
+    }
+
+}

+ 42 - 0
tile-service/src/main/java/cn/com/taiji/tile/util/RGBTable.java

@@ -0,0 +1,42 @@
+ package cn.com.taiji.tile.util;
+ 
+ public class RGBTable {
+   final int distance;
+   final int d2;
+   double[] table;
+   
+   public RGBTable(int distance) {
+    this.distance = distance;
+  this.d2 = this.distance * this.distance;
+     this.table = new double[(2 * distance + 1) * (2 * distance + 1)];
+     initPressureTable();
+   }
+   
+   private void initPressureTable() {
+     for (int dx = -this.distance; dx <= this.distance; dx++) {
+       for (int dy = -this.distance; dy <= this.distance; dy++) {
+         this.table[toIndex(dx, dy)] = pressure(dx, dy);
+       }
+     } 
+   }
+ 
+   
+   public double getPressure(int dx, int dy) {
+     if (-this.distance <= dx && dx <= this.distance && -this.distance <= dy && dy <= this.distance) {
+       if (dx * dx + dy * dy <= this.d2){
+         return this.table[toIndex(dx, dy)];
+       }
+       return 0.0D;
+     } 
+     return 0.0D;
+   }
+   
+   private int toIndex(int dx, int dy) {
+    return (dx + this.distance) * (2 * this.distance + 1) + dy + this.distance;
+   }
+   
+   private double pressure(double dx, double dy) {
+     double dis = Math.sqrt(dx * dx + dy * dy);
+     return 1.0D / (dis + 1.0D);
+   }
+ }

+ 35 - 0
tile-service/src/main/java/cn/com/taiji/tile/util/ResourceUtil.java

@@ -0,0 +1,35 @@
+package cn.com.taiji.tile.util;
+
+import org.springframework.util.ResourceUtils;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+
+public class ResourceUtil
+        extends ResourceUtils {
+    public static InputStream getResourceInputStream(String classpathName) {
+        URL myUrl = null;
+        try {
+            myUrl = ResourceUtils.getURL("classpath:" + classpathName);
+            if (myUrl == null) {
+                myUrl = ResourceUtils.class.getResource("classpath:" + classpathName);
+            }
+            if (myUrl == null) {
+                myUrl = ResourceUtils.getURL(classpathName);
+            }
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        if (myUrl != null) {
+            try {
+                return myUrl.openStream();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return null;
+    }
+}

+ 134 - 0
tile-service/src/main/java/cn/com/taiji/tile/util/TileUtils.java

@@ -0,0 +1,134 @@
+package cn.com.taiji.tile.util;
+
+import cn.com.taiji.tile.model.POI;
+import cn.com.taiji.tile.model.Point;
+import org.apache.commons.lang3.StringUtils;
+import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.io.ParseException;
+import org.locationtech.jts.io.WKTReader;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * @author zzyx 2023/12/5
+ */
+public class TileUtils {
+
+    public static byte[] getTile(List<Map<String,Object>> maps, String bboxStr){
+        List<POI> list = convert(maps);
+        return setColorTile(list,bboxStr);
+    }
+
+    public static List<POI> convert(List<Map<String, Object>> maps) {
+        List<POI> pois = new ArrayList<>();
+        for (Map<String, Object> map : maps) {
+            POI poi = new POI();
+            poi.setId((String) map.get("id"));
+            poi.setName((String) map.get("name"));
+            poi.setShape((String) map.get("shape"));
+            poi.setLat((Double) map.get("lat"));
+            poi.setLon((Double) map.get("lon"));
+            poi.setPcolor((String)map.get("pcolor"));
+            pois.add(poi);
+        }
+        return pois;
+    }
+
+
+    public static BufferedImage scaleWidthHeight(BufferedImage image, int width, int height) {
+        BufferedImage i2 = new BufferedImage(width, height, 2);
+        i2.getGraphics().drawImage(image.getScaledInstance(width, height, 4), 0, 0, null);
+        return i2;
+    }
+
+    public static boolean ins(Point point1, Point point2) {
+        double distance = point1.distanceTo(point2);
+        double markerMusure = 12.0D;
+        return (markerMusure >= distance);
+    }
+
+
+    public static byte[] setColorTile(List<POI> poiList, String bboxStr) {
+        BufferedImage image = new BufferedImage(256, 256, 2);
+        String[] split = bboxStr.split(",");
+        // 接受前端传递的bbox 进行解析
+        double[] bbox = new double[split.length];
+        for (int i = 0; i < split.length; i++) {
+            bbox[i] = Double.parseDouble(split[i]);
+        }
+        Graphics2D g = (Graphics2D) image.getGraphics();
+        g.setColor(Color.GREEN);
+        for (POI poi : poiList) {
+            int[] pxy = TileUtils.toPixelXY(poi.getLon(), poi.getLat(), bbox[0], bbox[1], bbox[2], bbox[3]);
+            g.drawArc(pxy[0], pxy[1], 6, 6, 0, 360);
+            g.fillArc(pxy[0], pxy[1], 6, 6, 0, 360);
+            TileUtils.drawShapeToTile(poi, g, bbox, 1);
+        }
+        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        try {
+            ImageIO.write(image, "png", buffer);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return buffer.toByteArray();
+    }
+
+    public static void drawShapeToTile(POI poi, Graphics2D graphics, double[] bbox, int lineSize) {
+        Geometry shape = GeoUtils.getGeoUtils().createGeometry(poi.getShape());
+        if (shape != null && shape.getCoordinates() != null && (shape.getCoordinates()).length > 1 &&
+                StringUtils.isNotBlank(poi.getPcolor()) && StringUtils.indexOf(poi.getPcolor(), "rgb(") >= 0) {
+            String[] rgb = StringUtils.substring(poi.getPcolor(), poi.getPcolor().indexOf("rgb(") + 4, poi.getPcolor().length() - 1).split(",");
+            Color color = new Color(Integer.parseInt(rgb[0].trim()), Integer.parseInt(rgb[1].trim()), Integer.parseInt(rgb[2].trim()));
+            graphics.setColor(color);
+            if (StringUtils.equals(shape.getGeometryType(), "Polygon") ||
+                    StringUtils.equals(shape.getGeometryType(), "LinearRing") ||
+                    StringUtils.equals(shape.getGeometryType(), "LineString") ||
+                    StringUtils.equals(shape.getGeometryType(), "MultiLineString")) {
+                int[] xpoint = new int[(shape.getCoordinates()).length];
+                int[] ypoint = new int[(shape.getCoordinates()).length];
+                for (int i = 0; i < (shape.getCoordinates()).length; i++) {
+                    Coordinate c = shape.getCoordinates()[i];
+                    int[] pxy = toPixelXY(c.getX(), c.getY(), bbox[0], bbox[1], bbox[2], bbox[3]);
+                    xpoint[i] = pxy[0];
+                    ypoint[i] = pxy[1];
+                }
+                if (lineSize <= 0) {
+                    lineSize = 1;
+                }
+                graphics.setStroke(new BasicStroke(lineSize));
+                //抗锯齿
+                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+                if (StringUtils.equals(shape.getGeometryType(), "Polygon")) {
+                    //fill 是将设置的颜色全部填充
+                    graphics.fill(new Polygon(xpoint, ypoint, shape.getCoordinates().length));
+//                    graphics.drawPolygon(xpoint, ypoint, (shape.getCoordinates()).length);
+                } else if (StringUtils.equalsAny(shape.getGeometryType(), "LinearRing", "MultiLineString", "LineString")) {
+                    graphics.drawPolyline(xpoint, ypoint, (shape.getCoordinates()).length);
+                }
+            }
+        }
+    }
+
+    public byte[] newHotImageTileWithPoiList(List<POI> poiList, String bbox) {
+        HotImageTile tile = new HotImageTile();
+        return tile.setHotImage(poiList, bbox);
+    }
+
+
+    public static int[] toPixelXY(double x, double y, double minX, double minY, double maxX, double maxY) {
+        int dx = (int) (256.0D * (x - minX) / (maxX - minX));
+        int dy = 256 - (int) (256.0D * (y - minY) / (maxY - minY));
+        return new int[]{dx, dy};
+    }
+
+}