运营区
This commit is contained in:
parent
77139780fb
commit
97e5a2e782
|
@ -15,8 +15,56 @@
|
|||
common通用工具
|
||||
</description>
|
||||
|
||||
<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>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.geotools/gt-geojson -->
|
||||
<dependency>
|
||||
<groupId>org.geotools</groupId>
|
||||
<artifactId>gt-geojson</artifactId>
|
||||
<version>24.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.geotools/gt-epsg-hsql -->
|
||||
<dependency>
|
||||
<groupId>org.geotools</groupId>
|
||||
<artifactId>gt-epsg-hsql</artifactId>
|
||||
<version>24.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.geotools/gt-shapefile -->
|
||||
<dependency>
|
||||
<groupId>org.geotools</groupId>
|
||||
<artifactId>gt-shapefile</artifactId>
|
||||
<version>24.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.geotools/gt-swing -->
|
||||
<dependency>
|
||||
<groupId>org.geotools</groupId>
|
||||
<artifactId>gt-swing</artifactId>
|
||||
<version>24.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.geotools.jdbc/gt-jdbc-postgis -->
|
||||
<dependency>
|
||||
<groupId>org.geotools.jdbc</groupId>
|
||||
<artifactId>gt-jdbc-postgis</artifactId>
|
||||
<version>24.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
|
@ -193,4 +241,5 @@
|
|||
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,375 @@
|
|||
package com.ruoyi.common.utils.map;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.geotools.data.DataUtilities;
|
||||
import org.geotools.data.collection.ListFeatureCollection;
|
||||
import org.geotools.feature.FeatureCollection;
|
||||
import org.geotools.feature.simple.SimpleFeatureBuilder;
|
||||
import org.geotools.geojson.feature.FeatureJSON;
|
||||
import org.geotools.geojson.geom.GeometryJSON;
|
||||
import org.geotools.geometry.jts.JTS;
|
||||
import org.geotools.referencing.CRS;
|
||||
import org.geotools.referencing.crs.DefaultGeographicCRS;
|
||||
import org.locationtech.jts.geom.*;
|
||||
import org.locationtech.jts.geom.Point;
|
||||
import org.locationtech.jts.io.WKTReader;
|
||||
import org.locationtech.jts.io.WKTWriter;
|
||||
import org.opengis.feature.simple.SimpleFeature;
|
||||
import org.opengis.feature.simple.SimpleFeatureType;
|
||||
import org.opengis.referencing.operation.MathTransform;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* GeoUtils.
|
||||
*
|
||||
* @author qiuzhenzhao
|
||||
* @date 2024/04/19
|
||||
*/
|
||||
@Slf4j
|
||||
@UtilityClass
|
||||
public class GeoUtils {
|
||||
private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory();
|
||||
private static final String AUTO = "AUTO:42001,%s,%s";
|
||||
private static final WKTWriter WKT_WRITER = new WKTWriter();
|
||||
private static final WKTReader WKT_READER = new WKTReader();
|
||||
private static final GeometryJSON GEOMETRY_JSON = new GeometryJSON(15);
|
||||
private final static FeatureJSON FEATURE_JSON = new FeatureJSON(GEOMETRY_JSON);
|
||||
|
||||
private static final double EARTH_RADIUS = 6371000; // 地球半径,单位:米
|
||||
|
||||
/**
|
||||
* 合并多边形 Geographic
|
||||
* */
|
||||
public Geometry union(Collection<Geometry> geometries) {
|
||||
return GEOMETRY_FACTORY.buildGeometry(geometries).union();
|
||||
}
|
||||
|
||||
/**
|
||||
* geometry转geojson
|
||||
* */
|
||||
@SneakyThrows
|
||||
public String geoJson(Geometry geometry) {
|
||||
SimpleFeatureType type = DataUtilities.createType("Link", "geometry:" + geometry.getGeometryType());
|
||||
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(type);
|
||||
featureBuilder.add(geometry);
|
||||
SimpleFeature feature = featureBuilder.buildFeature(null);
|
||||
FeatureCollection<?, ?> featureCollection = new ListFeatureCollection(type, Collections.singletonList(feature));
|
||||
return FEATURE_JSON.toString(featureCollection);
|
||||
}
|
||||
|
||||
/**
|
||||
* 定的geometry对象转换为GeoJSON格式,并将其写入到指定的file中
|
||||
* */
|
||||
@SneakyThrows
|
||||
public void geoJson(Geometry geometry, File file) {
|
||||
SimpleFeatureType type = DataUtilities.createType("Link", "geometry:" + geometry.getGeometryType());
|
||||
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(type);
|
||||
featureBuilder.add(geometry);
|
||||
SimpleFeature feature = featureBuilder.buildFeature(null);
|
||||
FeatureCollection<?, ?> featureCollection = new ListFeatureCollection(type, Collections.singletonList(feature));
|
||||
FEATURE_JSON.writeFeatureCollection(featureCollection, FileUtils.openOutputStream(file));
|
||||
}
|
||||
/**
|
||||
* wkt转Geometry对象
|
||||
* wkt格式:POLYGON((x1 y1,x2 y2,x3 y3,x4 y4,x1 y1))
|
||||
* */
|
||||
public Geometry fromWkt(String wkt) {
|
||||
if (StringUtils.isBlank(wkt)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return WKT_READER.read(wkt);
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* json转Geometry对象
|
||||
* 格式:[[120.356267,26.941506],[120.357168,26.941262],[120.35697,26.940564]]
|
||||
* */
|
||||
public Geometry toGeometry(String json) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
// 将json转成二位数组并形成闭合
|
||||
double[][] coordinates = transform(json);
|
||||
log.info("coordinates:{}", JSON.toJSONString(coordinates));
|
||||
// 构建坐标数组
|
||||
Coordinate[] points = new Coordinate[coordinates.length];
|
||||
for (int i = 0; i < coordinates.length; i++) {
|
||||
double lon = coordinates[i][0];
|
||||
double lat = coordinates[i][1];
|
||||
points[i] = new Coordinate(lon, lat);
|
||||
}
|
||||
// 创建LinearRing对象
|
||||
LinearRing linearRing = GEOMETRY_FACTORY.createLinearRing(points);
|
||||
// 创建Polygon对象
|
||||
Polygon polygon = GEOMETRY_FACTORY.createPolygon(linearRing);
|
||||
return polygon;
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* json转Geometry对象 直线
|
||||
* 格式:[[120.356267,26.941506],[120.357168,26.941262],[120.35697,26.940564]]
|
||||
* */
|
||||
public Geometry toGeometryByLinearRing(String json) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
// 将json转成二位数组
|
||||
double[][] coordinates = transform(json);
|
||||
log.info("coordinates:{}", JSON.toJSONString(coordinates));
|
||||
// 构建坐标数组
|
||||
Coordinate[] points = new Coordinate[coordinates.length];
|
||||
for (int i = 0; i < coordinates.length; i++) {
|
||||
double lon = coordinates[i][0];
|
||||
double lat = coordinates[i][1];
|
||||
points[i] = new Coordinate(lon, lat);
|
||||
}
|
||||
// 创建LineString对象
|
||||
LineString lineString = GEOMETRY_FACTORY.createLineString(points);
|
||||
return lineString;
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将json转成二位数组
|
||||
* */
|
||||
public double[][] transform(String json) {
|
||||
// 使用 Jackson 库解析 JSON 字符串为二维数组
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
double[][] coordinates;
|
||||
try {
|
||||
coordinates = objectMapper.readValue(json, double[][].class);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
// 添加闭合多边形的最后一个点
|
||||
int numPoints = coordinates.length;
|
||||
double[][] closedCoordinates = new double[numPoints + 1][2];
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
closedCoordinates[i] = coordinates[i];
|
||||
}
|
||||
closedCoordinates[numPoints] = coordinates[0]; // 将第一个点复制到最后一个点
|
||||
return closedCoordinates;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Geometry对象转wkt
|
||||
* */
|
||||
public String wkt(Geometry geometry) {
|
||||
if (geometry == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return WKT_WRITER.write(geometry);
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* JSON转Geometry
|
||||
* */
|
||||
public Geometry fromJson(String json) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return GEOMETRY_JSON.read(json);
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 计算Geometry的面积
|
||||
* */
|
||||
@SneakyThrows
|
||||
public Double calcArea(Geometry geometry) {
|
||||
Point centroid = geometry.getCentroid();
|
||||
MathTransform mathTransform = CRS.findMathTransform(DefaultGeographicCRS.WGS84,
|
||||
CRS.decode(String.format(AUTO, centroid.getX(), centroid.getY())));
|
||||
Geometry transform = JTS.transform(geometry, mathTransform);
|
||||
return transform.getArea();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断经纬度是否在多边形区域内
|
||||
* */
|
||||
public boolean isInCircle(String longitude, String latitude,Geometry polygon){
|
||||
/**创建一个点*/
|
||||
GeometryFactory geometryFactory = new GeometryFactory();
|
||||
Coordinate coordinate = new Coordinate(Double.parseDouble(longitude), Double.parseDouble(latitude));
|
||||
Point point = geometryFactory.createPoint(coordinate);
|
||||
return polygon.contains(point);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断一个点是否在一个圆形区域内(考虑误差距离)
|
||||
* */
|
||||
public static boolean isInPolygonWithTolerance(String longitude, String latitude, Geometry polygon, double tolerance) {
|
||||
double lon = Double.parseDouble(longitude);
|
||||
double lat = Double.parseDouble(latitude);
|
||||
|
||||
GeometryFactory geometryFactory = new GeometryFactory();
|
||||
Coordinate coordinate = new Coordinate(lon, lat);
|
||||
Point point = geometryFactory.createPoint(coordinate);
|
||||
|
||||
if (polygon.contains(point)) {
|
||||
return true;
|
||||
} else {
|
||||
// 获取多边形的外边界
|
||||
Coordinate[] coordinates = polygon.getCoordinates();
|
||||
for (Coordinate coord : coordinates) {
|
||||
double distance = calculateDistance(lat, lon, coord.y, coord.x);
|
||||
// log.info("距离----distance:{}",distance);
|
||||
if (distance <= tolerance) {
|
||||
// log.info("最小距离----distance:{}",distance);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断一个点是否在一个缩短后的圆形区域内
|
||||
* */
|
||||
public static boolean isInPolygonWithShorten(String longitude, String latitude, Geometry polygon, double shortenDistance) {
|
||||
double lon = Double.parseDouble(longitude);
|
||||
double lat = Double.parseDouble(latitude);
|
||||
|
||||
GeometryFactory geometryFactory = new GeometryFactory();
|
||||
Coordinate coordinate = new Coordinate(lon, lat);
|
||||
Point point = geometryFactory.createPoint(coordinate);
|
||||
|
||||
if (polygon.contains(point)) {
|
||||
// 获取多边形的外边界
|
||||
Coordinate[] coordinates = polygon.getCoordinates();
|
||||
for (Coordinate coord : coordinates) {
|
||||
double distance = calculateDistance(lat, lon, coord.y, coord.x);
|
||||
// log.info("距离----distance:{}",distance);
|
||||
if (shortenDistance >= distance) {
|
||||
// log.info("最小距离----distance:{}",distance);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 将角度转换为弧度
|
||||
private static double deg2rad(double deg) {
|
||||
return deg * (Math.PI / 180);
|
||||
}
|
||||
|
||||
// 使用 Haversine 公式计算两点间的距离
|
||||
public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
|
||||
double dLat = deg2rad(lat2 - lat1);
|
||||
double dLon = deg2rad(lon1 - lon2); // 修正此处为 (lon1 - lon2)
|
||||
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
||||
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
|
||||
Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
||||
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
return EARTH_RADIUS * c;
|
||||
}
|
||||
|
||||
public static double[][] parseJsonTrack(String jsonString) {
|
||||
JSONArray jsonArray = JSONArray.parseArray(jsonString);
|
||||
double[][] track = new double[jsonArray.size()][2];
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
JSONArray coord = jsonArray.getJSONArray(i);
|
||||
track[i][0] = coord.getDouble(0);
|
||||
track[i][1] = coord.getDouble(1);
|
||||
}
|
||||
return track;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算一段轨迹的总距离
|
||||
* */
|
||||
public static double calculateTotalDistance(double[][] track) {
|
||||
double totalDistance = 0;
|
||||
for (int i = 0; i < track.length - 1; i++) {
|
||||
totalDistance += haversineDistance(track[i], track[i + 1]);
|
||||
}
|
||||
return totalDistance;
|
||||
}
|
||||
|
||||
public static double haversineDistance(double[] coord1, double[] coord2) {
|
||||
double lat1 = deg2rad(coord1[1]);
|
||||
double lon1 = deg2rad(coord1[0]);
|
||||
double lat2 = deg2rad(coord2[1]);
|
||||
double lon2 = deg2rad(coord2[0]);
|
||||
|
||||
double dLat = lat2 - lat1;
|
||||
double dLon = lon2 - lon1;
|
||||
|
||||
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
||||
Math.cos(lat1) * Math.cos(lat2) *
|
||||
Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
||||
|
||||
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
|
||||
return EARTH_RADIUS * c; // 距离(米)
|
||||
}
|
||||
|
||||
/**
|
||||
* 判获取到最近一个运营区
|
||||
* */
|
||||
public static boolean getNearestOperatingArea (String longitude, String latitude, List<Geometry> polygon) {
|
||||
double lon = Double.parseDouble(longitude);
|
||||
double lat = Double.parseDouble(latitude);
|
||||
|
||||
GeometryFactory geometryFactory = new GeometryFactory();
|
||||
Coordinate coordinate = new Coordinate(lon, lat);
|
||||
Point point = geometryFactory.createPoint(coordinate);
|
||||
|
||||
for (Geometry geometry : polygon) {
|
||||
if (geometry.contains(point)) {
|
||||
return true;
|
||||
}else{
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算给定点到多边形的最短距离
|
||||
* */
|
||||
public double calculateMinDistanceToPolygon(Geometry polygon, double lon, double lat) {
|
||||
Coordinate coord = new Coordinate(lon, lat);
|
||||
Point point = new GeometryFactory().createPoint(coord);
|
||||
return polygon.distance(point); // 返回给定点到多边形的最短距离
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,823 @@
|
|||
package com.ruoyi.common.utils.map;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 坐标系转换
|
||||
* @author Mr.Li
|
||||
* @date 2023-08-02
|
||||
*/
|
||||
@Slf4j
|
||||
public class GpsCoordinateUtils {
|
||||
|
||||
private static final double PI = 3.1415926535897932384626433832795;
|
||||
private static final double A = 6378245.0;
|
||||
private static final double EE = 0.00669342162296594323;
|
||||
|
||||
/**
|
||||
* 地球坐标系 WGS-84 to 火星坐标系 GCJ-02
|
||||
*
|
||||
* @param latitude 纬度
|
||||
* @param longitude 经度
|
||||
* @return [纬度, 经度]
|
||||
*/
|
||||
public static double[] calWGS84toGCJ02(double latitude, double longitude) {
|
||||
Point dev = calDev(latitude, longitude);
|
||||
double retLat = latitude + dev.getLatitude();
|
||||
double retLon = longitude + dev.getLongitude();
|
||||
return new double[]{retLat, retLon};
|
||||
}
|
||||
|
||||
/**
|
||||
* 地球坐标系 WGS-84 to 百度坐标系 BD-09
|
||||
*
|
||||
* @param latitude 纬度
|
||||
* @param longitude 经度
|
||||
* @return [纬度, 经度]
|
||||
*/
|
||||
public static double[] calWGS84toBD09(double latitude, double longitude) {
|
||||
Point dev = calDev(latitude, longitude);
|
||||
double retLat = latitude + dev.getLatitude();
|
||||
double retLon = longitude + dev.getLongitude();
|
||||
return calGCJ02toBD09(retLat, retLon);
|
||||
}
|
||||
|
||||
/**
|
||||
* 火星坐标系 GCJ-02 to 地球坐标系 WGS-84
|
||||
*
|
||||
* @param latitude 纬度
|
||||
* @param longitude 经度
|
||||
* @return [纬度, 经度]
|
||||
*/
|
||||
public static double[] calGCJ02toWGS84(double latitude, double longitude) {
|
||||
Point dev = calDev(latitude, longitude);
|
||||
double retLat = latitude - dev.getLatitude();
|
||||
double retLon = longitude - dev.getLongitude();
|
||||
dev = calDev(retLat, retLon);
|
||||
retLat = latitude - dev.getLatitude();
|
||||
retLon = longitude - dev.getLongitude();
|
||||
return new double[]{retLat, retLon};
|
||||
}
|
||||
|
||||
/**
|
||||
* 百度坐标系 BD-09 to 地球坐标系 WGS-84
|
||||
*
|
||||
* @param latitude 纬度
|
||||
* @param longitude 经度
|
||||
* @return [纬度, 经度]
|
||||
*/
|
||||
public static double[] calBD09toWGS84(double latitude, double longitude) {
|
||||
double[] gcj = calBD09toGCJ02(latitude, longitude);
|
||||
return calGCJ02toWGS84(gcj[0], gcj[1]);
|
||||
}
|
||||
|
||||
private static Point calDev(double latitude, double longitude) {
|
||||
if (isOutOfChina(latitude, longitude, false)) {
|
||||
return new Point(latitude, latitude);
|
||||
}
|
||||
double dLat = calLat(longitude - 105.0, latitude - 35.0);
|
||||
double dLon = calLon(longitude - 105.0, latitude - 35.0);
|
||||
double radLat = latitude / 180.0 * PI;
|
||||
double magic = Math.sin(radLat);
|
||||
magic = 1 - EE * magic * magic;
|
||||
double sqrtMagic = Math.sqrt(magic);
|
||||
dLat = (dLat * 180.0) / ((A * (1 - EE)) / (magic * sqrtMagic) * PI);
|
||||
dLon = (dLon * 180.0) / (A / sqrtMagic * Math.cos(radLat) * PI);
|
||||
return new Point(dLat, dLon);
|
||||
}
|
||||
|
||||
private static double calLat(double x, double y) {
|
||||
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
|
||||
ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
|
||||
ret += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0;
|
||||
ret += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static double calLon(double x, double y) {
|
||||
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
|
||||
ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
|
||||
ret += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0;
|
||||
ret += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0 * PI)) * 2.0 / 3.0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 火星坐标系 GCJ-02 to 百度坐标系 BD-09
|
||||
*
|
||||
* @param latitude 纬度
|
||||
* @param longitude 经度
|
||||
* @return [纬度, 经度]
|
||||
*/
|
||||
public static double[] calGCJ02toBD09(double latitude, double longitude) {
|
||||
double x = longitude, y = latitude;
|
||||
double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * PI);
|
||||
double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * PI);
|
||||
double retLat = z * Math.sin(theta) + 0.006;
|
||||
double retLon = z * Math.cos(theta) + 0.0065;
|
||||
return new double[]{retLat, retLon};
|
||||
}
|
||||
|
||||
/**
|
||||
* 百度坐标系 BD-09 to 火星坐标系 GCJ-02
|
||||
*
|
||||
* @param latitude 纬度
|
||||
* @param longitude 经度
|
||||
* @return [纬度, 经度]
|
||||
*/
|
||||
public static double[] calBD09toGCJ02(double latitude, double longitude) {
|
||||
double x = longitude - 0.0065, y = latitude - 0.006;
|
||||
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * PI);
|
||||
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * PI);
|
||||
double retLat = z * Math.sin(theta);
|
||||
double retLon = z * Math.cos(theta);
|
||||
return new double[]{retLat, retLon};
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断坐标是否在国内
|
||||
*
|
||||
* @param latitude
|
||||
* @param longitude
|
||||
* @param precision 是否精确判断范围
|
||||
* @return true 在国外,false 在国内
|
||||
*/
|
||||
public static boolean isOutOfChina(double latitude, double longitude, boolean precision) {
|
||||
if (precision) {
|
||||
return CHINA_POLYGON.stream().noneMatch(point -> pointInPolygon(point, latitude, longitude));
|
||||
} else {
|
||||
if (longitude < 72.004 || longitude > 137.8347) {
|
||||
return true;
|
||||
}
|
||||
if (latitude < 0.8293 || latitude > 55.8271) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查坐标点是否在多边形区域内
|
||||
*
|
||||
* @param polygon 多边形
|
||||
* @param latitude 纬度
|
||||
* @param longitude 经度
|
||||
* @return true 在多边形区域内,false 在多边形区域外
|
||||
*/
|
||||
private static boolean pointInPolygon(Point[] polygon, double latitude, double longitude) {
|
||||
int i, j = polygon.length - 1;
|
||||
boolean oddNodes = false;
|
||||
for (i = 0; i < polygon.length; i++) {
|
||||
if ((polygon[i].getLatitude() < latitude && polygon[j].getLatitude() >= latitude
|
||||
|| polygon[j].getLatitude() < latitude && polygon[i].getLatitude() >= latitude)
|
||||
&& (polygon[i].getLongitude() <= longitude || polygon[j].getLongitude() <= longitude)) {
|
||||
if (polygon[i].getLongitude()
|
||||
+ (latitude - polygon[i].getLatitude()) / (polygon[j].getLatitude() - polygon[i].getLatitude())
|
||||
* (polygon[j].getLongitude() - polygon[i].getLongitude())
|
||||
< longitude) {
|
||||
oddNodes = !oddNodes;
|
||||
}
|
||||
}
|
||||
j = i;
|
||||
}
|
||||
return oddNodes;
|
||||
}
|
||||
|
||||
static class Point {
|
||||
private double longitude;
|
||||
private double latitude;
|
||||
|
||||
Point(double latitude, double longitude) {
|
||||
this.longitude = longitude;
|
||||
this.latitude = latitude;
|
||||
}
|
||||
|
||||
public double getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public void setLongitude(double longitude) {
|
||||
this.longitude = longitude;
|
||||
}
|
||||
|
||||
public double getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
public void setLatitude(double latitude) {
|
||||
this.latitude = latitude;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return longitude + "," + latitude;
|
||||
}
|
||||
}
|
||||
|
||||
//region 中国行政边界的WGS84坐标数据
|
||||
/**
|
||||
* 大陆边境线
|
||||
*/
|
||||
private static final Point[] MAINLAND = new Point[]{
|
||||
new Point(27.32083, 88.91693),
|
||||
new Point(27.54243, 88.76464),
|
||||
new Point(28.00805, 88.83575),
|
||||
new Point(28.1168, 88.62435),
|
||||
new Point(27.86605, 88.14279),
|
||||
new Point(27.82305, 87.19275),
|
||||
new Point(28.11166, 86.69527),
|
||||
new Point(27.90888, 86.45137),
|
||||
new Point(28.15805, 86.19769),
|
||||
new Point(27.88625, 86.0054),
|
||||
new Point(28.27916, 85.72137),
|
||||
new Point(28.30666, 85.11095),
|
||||
new Point(28.59104, 85.19518),
|
||||
new Point(28.54444, 84.84665),
|
||||
new Point(28.73402, 84.48623),
|
||||
new Point(29.26097, 84.11651),
|
||||
new Point(29.18902, 83.5479),
|
||||
new Point(29.63166, 83.19109),
|
||||
new Point(30.06923, 82.17525),
|
||||
new Point(30.33444, 82.11123),
|
||||
new Point(30.385, 81.42623),
|
||||
new Point(30.01194, 81.23221),
|
||||
new Point(30.20435, 81.02536),
|
||||
new Point(30.57552, 80.207),
|
||||
new Point(30.73374, 80.25423),
|
||||
new Point(30.96583, 79.86304),
|
||||
new Point(30.95708, 79.55429),
|
||||
new Point(31.43729, 79.08082),
|
||||
new Point(31.30895, 78.76825),
|
||||
new Point(31.96847, 78.77075),
|
||||
new Point(32.24304, 78.47594),
|
||||
new Point(32.5561, 78.40595),
|
||||
new Point(32.63902, 78.74623),
|
||||
new Point(32.35083, 78.9711),
|
||||
new Point(32.75666, 79.52874),
|
||||
new Point(33.09944, 79.37511),
|
||||
new Point(33.42863, 78.93623),
|
||||
new Point(33.52041, 78.81387),
|
||||
new Point(34.06833, 78.73581),
|
||||
new Point(34.35001, 78.98535),
|
||||
new Point(34.6118, 78.33707),
|
||||
new Point(35.28069, 78.02305),
|
||||
new Point(35.49902, 78.0718),
|
||||
new Point(35.50133, 77.82393),
|
||||
new Point(35.6125, 76.89526),
|
||||
new Point(35.90665, 76.55304),
|
||||
new Point(35.81458, 76.18061),
|
||||
new Point(36.07082, 75.92887),
|
||||
new Point(36.23751, 76.04166),
|
||||
new Point(36.66343, 75.85984),
|
||||
new Point(36.73169, 75.45179),
|
||||
new Point(36.91156, 75.39902),
|
||||
new Point(36.99719, 75.14787),
|
||||
new Point(37.02782, 74.56543),
|
||||
new Point(37.17, 74.39089),
|
||||
new Point(37.23733, 74.91574),
|
||||
new Point(37.40659, 75.18748),
|
||||
new Point(37.65243, 74.9036),
|
||||
new Point(38.47256, 74.85442),
|
||||
new Point(38.67438, 74.35471),
|
||||
new Point(38.61271, 73.81401),
|
||||
new Point(38.88653, 73.70818),
|
||||
new Point(38.97256, 73.85235),
|
||||
new Point(39.23569, 73.62005),
|
||||
new Point(39.45483, 73.65569),
|
||||
new Point(39.59965, 73.95471),
|
||||
new Point(39.76896, 73.8429),
|
||||
new Point(40.04202, 73.99096),
|
||||
new Point(40.32792, 74.88089),
|
||||
new Point(40.51723, 74.8588),
|
||||
new Point(40.45042, 75.23394),
|
||||
new Point(40.64452, 75.58284),
|
||||
new Point(40.298, 75.70374),
|
||||
new Point(40.35324, 76.3344),
|
||||
new Point(41.01258, 76.87067),
|
||||
new Point(41.04079, 78.08083),
|
||||
new Point(41.39286, 78.39554),
|
||||
new Point(42.03954, 80.24513),
|
||||
new Point(42.19622, 80.23402),
|
||||
new Point(42.63245, 80.15804),
|
||||
new Point(42.81565, 80.25796),
|
||||
new Point(42.88545, 80.57226),
|
||||
new Point(43.02906, 80.38405),
|
||||
new Point(43.1683, 80.81526),
|
||||
new Point(44.11378, 80.36887),
|
||||
new Point(44.6358, 80.38499),
|
||||
new Point(44.73408, 80.51589),
|
||||
new Point(44.90282, 79.87106),
|
||||
new Point(45.3497, 81.67928),
|
||||
new Point(45.15748, 81.94803),
|
||||
new Point(45.13303, 82.56638),
|
||||
new Point(45.43581, 82.64624),
|
||||
new Point(45.5831, 82.32179),
|
||||
new Point(47.20061, 83.03443),
|
||||
new Point(46.97332, 83.93026),
|
||||
new Point(46.99361, 84.67804),
|
||||
new Point(46.8277, 84.80318),
|
||||
new Point(47.0591, 85.52257),
|
||||
new Point(47.26221, 85.70139),
|
||||
new Point(47.93721, 85.53707),
|
||||
new Point(48.39333, 85.76596),
|
||||
new Point(48.54277, 86.59791),
|
||||
new Point(49.1102, 86.87602),
|
||||
new Point(49.09262, 87.34821),
|
||||
new Point(49.17295, 87.8407),
|
||||
new Point(48.98304, 87.89291),
|
||||
new Point(48.88103, 87.7611),
|
||||
new Point(48.73499, 88.05942),
|
||||
new Point(48.56541, 87.99194),
|
||||
new Point(48.40582, 88.51679),
|
||||
new Point(48.21193, 88.61179),
|
||||
new Point(47.99374, 89.08514),
|
||||
new Point(47.88791, 90.07096),
|
||||
new Point(46.95221, 90.9136),
|
||||
new Point(46.57735, 91.07027),
|
||||
new Point(46.29694, 90.92151),
|
||||
new Point(46.01735, 91.02651),
|
||||
new Point(45.57972, 90.68193),
|
||||
new Point(45.25305, 90.89694),
|
||||
new Point(45.07729, 91.56088),
|
||||
new Point(44.95721, 93.5547),
|
||||
new Point(44.35499, 94.71735),
|
||||
new Point(44.29416, 95.41061),
|
||||
new Point(44.01937, 95.34109),
|
||||
new Point(43.99311, 95.53339),
|
||||
new Point(43.28388, 95.87901),
|
||||
new Point(42.73499, 96.38206),
|
||||
new Point(42.79583, 97.1654),
|
||||
new Point(42.57194, 99.51012),
|
||||
new Point(42.67707, 100.8425),
|
||||
new Point(42.50972, 101.8147),
|
||||
new Point(42.23333, 102.0772),
|
||||
new Point(41.88721, 103.4164),
|
||||
new Point(41.87721, 104.5267),
|
||||
new Point(41.67068, 104.5237),
|
||||
new Point(41.58666, 105.0065),
|
||||
new Point(42.46624, 107.4758),
|
||||
new Point(42.42999, 109.3107),
|
||||
new Point(42.64576, 110.1064),
|
||||
new Point(43.31694, 110.9897),
|
||||
new Point(43.69221, 111.9583),
|
||||
new Point(44.37527, 111.4214),
|
||||
new Point(45.04944, 111.873),
|
||||
new Point(45.08055, 112.4272),
|
||||
new Point(44.8461, 112.853),
|
||||
new Point(44.74527, 113.638),
|
||||
new Point(45.38943, 114.5453),
|
||||
new Point(45.4586, 115.7019),
|
||||
new Point(45.72193, 116.2104),
|
||||
new Point(46.29583, 116.5855),
|
||||
new Point(46.41888, 117.3755),
|
||||
new Point(46.57069, 117.425),
|
||||
new Point(46.53645, 117.8455),
|
||||
new Point(46.73638, 118.3147),
|
||||
new Point(46.59895, 119.7068),
|
||||
new Point(46.71513, 119.9315),
|
||||
new Point(46.90221, 119.9225),
|
||||
new Point(47.66499, 119.125),
|
||||
new Point(47.99475, 118.5393),
|
||||
new Point(48.01125, 117.8046),
|
||||
new Point(47.65741, 117.3827),
|
||||
new Point(47.88805, 116.8747),
|
||||
new Point(47.87819, 116.2624),
|
||||
new Point(47.69186, 115.9231),
|
||||
new Point(47.91749, 115.5944),
|
||||
new Point(48.14353, 115.5491),
|
||||
new Point(48.25249, 115.8358),
|
||||
new Point(48.52055, 115.8111),
|
||||
new Point(49.83047, 116.7114),
|
||||
new Point(49.52058, 117.8747),
|
||||
new Point(49.92263, 118.5746),
|
||||
new Point(50.09631, 119.321),
|
||||
new Point(50.33028, 119.36),
|
||||
new Point(50.39027, 119.1386),
|
||||
new Point(51.62083, 120.0641),
|
||||
new Point(52.115, 120.7767),
|
||||
new Point(52.34423, 120.6259),
|
||||
new Point(52.54267, 120.7122),
|
||||
new Point(52.58805, 120.0819),
|
||||
new Point(52.76819, 120.0314),
|
||||
new Point(53.26374, 120.8307),
|
||||
new Point(53.54361, 123.6147),
|
||||
new Point(53.18832, 124.4933),
|
||||
new Point(53.05027, 125.62),
|
||||
new Point(52.8752, 125.6573),
|
||||
new Point(52.75722, 126.0968),
|
||||
new Point(52.5761, 125.9943),
|
||||
new Point(52.12694, 126.555),
|
||||
new Point(51.99437, 126.4412),
|
||||
new Point(51.38138, 126.9139),
|
||||
new Point(51.26555, 126.8176),
|
||||
new Point(51.31923, 126.9689),
|
||||
new Point(51.05825, 126.9331),
|
||||
new Point(50.74138, 127.2919),
|
||||
new Point(50.31472, 127.334),
|
||||
new Point(50.20856, 127.5861),
|
||||
new Point(49.80588, 127.515),
|
||||
new Point(49.58665, 127.838),
|
||||
new Point(49.58443, 128.7119),
|
||||
new Point(49.34676, 129.1118),
|
||||
new Point(49.4158, 129.4902),
|
||||
new Point(48.86464, 130.2246),
|
||||
new Point(48.86041, 130.674),
|
||||
new Point(48.60576, 130.5236),
|
||||
new Point(48.3268, 130.824),
|
||||
new Point(48.10839, 130.6598),
|
||||
new Point(47.68721, 130.9922),
|
||||
new Point(47.71027, 132.5211),
|
||||
new Point(48.09888, 133.0827),
|
||||
new Point(48.06888, 133.4843),
|
||||
new Point(48.39112, 134.4153),
|
||||
new Point(48.26713, 134.7408),
|
||||
new Point(47.99207, 134.5576),
|
||||
new Point(47.70027, 134.7608),
|
||||
new Point(47.32333, 134.1825),
|
||||
new Point(46.64017, 133.9977),
|
||||
new Point(46.47888, 133.8472),
|
||||
new Point(46.25363, 133.9016),
|
||||
new Point(45.82347, 133.4761),
|
||||
new Point(45.62458, 133.4702),
|
||||
new Point(45.45083, 133.1491),
|
||||
new Point(45.05694, 133.0253),
|
||||
new Point(45.34582, 131.8684),
|
||||
new Point(44.97388, 131.4691),
|
||||
new Point(44.83649, 130.953),
|
||||
new Point(44.05193, 131.298),
|
||||
new Point(43.53624, 131.1912),
|
||||
new Point(43.38958, 131.3104),
|
||||
new Point(42.91645, 131.1285),
|
||||
new Point(42.74485, 130.4327),
|
||||
new Point(42.42186, 130.6044),
|
||||
new Point(42.71416, 130.2468),
|
||||
new Point(42.88794, 130.2514),
|
||||
new Point(43.00457, 129.9046),
|
||||
new Point(42.43582, 129.6955),
|
||||
new Point(42.44624, 129.3493),
|
||||
new Point(42.02736, 128.9269),
|
||||
new Point(42.00124, 128.0566),
|
||||
new Point(41.58284, 128.3002),
|
||||
new Point(41.38124, 128.1529),
|
||||
new Point(41.47249, 127.2708),
|
||||
new Point(41.79222, 126.9047),
|
||||
new Point(41.61176, 126.5661),
|
||||
new Point(40.89694, 126.0118),
|
||||
new Point(40.47037, 124.8851),
|
||||
new Point(40.09362, 124.3736),
|
||||
new Point(39.82777, 124.128),
|
||||
new Point(39.8143, 123.2422),
|
||||
new Point(39.67388, 123.2167),
|
||||
new Point(38.99638, 121.648),
|
||||
new Point(38.8611, 121.6982),
|
||||
new Point(38.71909, 121.1873),
|
||||
new Point(38.91221, 121.0887),
|
||||
new Point(39.09013, 121.6794),
|
||||
new Point(39.2186, 121.5994),
|
||||
new Point(39.35166, 121.7511),
|
||||
new Point(39.52847, 121.2283),
|
||||
new Point(39.62322, 121.533),
|
||||
new Point(39.81138, 121.4683),
|
||||
new Point(40.00305, 121.881),
|
||||
new Point(40.50562, 122.2987),
|
||||
new Point(40.73874, 122.0521),
|
||||
new Point(40.92194, 121.1775),
|
||||
new Point(40.1961, 120.4468),
|
||||
new Point(39.87242, 119.5264),
|
||||
new Point(39.15693, 118.9715),
|
||||
new Point(39.04083, 118.3273),
|
||||
new Point(39.19846, 117.889),
|
||||
new Point(38.67555, 117.5364),
|
||||
new Point(38.38666, 117.6722),
|
||||
new Point(38.16721, 118.0281),
|
||||
new Point(38.1529, 118.8378),
|
||||
new Point(37.87832, 119.0355),
|
||||
new Point(37.30054, 118.9566),
|
||||
new Point(37.14361, 119.2328),
|
||||
new Point(37.15138, 119.7672),
|
||||
new Point(37.35228, 119.8529),
|
||||
new Point(37.83499, 120.7371),
|
||||
new Point(37.42458, 121.58),
|
||||
new Point(37.55256, 122.1282),
|
||||
new Point(37.41833, 122.1814),
|
||||
new Point(37.39624, 122.5586),
|
||||
new Point(37.20999, 122.5972),
|
||||
new Point(37.02583, 122.4005),
|
||||
new Point(37.01978, 122.5392),
|
||||
new Point(36.89361, 122.5047),
|
||||
new Point(36.84298, 122.1923),
|
||||
new Point(37.00027, 121.9566),
|
||||
new Point(36.75889, 121.5944),
|
||||
new Point(36.61666, 120.7764),
|
||||
new Point(36.52638, 120.96),
|
||||
new Point(36.37582, 120.8753),
|
||||
new Point(36.42277, 120.7062),
|
||||
new Point(36.14075, 120.6956),
|
||||
new Point(36.0419, 120.3436),
|
||||
new Point(36.26345, 120.3078),
|
||||
new Point(36.19998, 120.0889),
|
||||
new Point(35.95943, 120.2378),
|
||||
new Point(35.57893, 119.6475),
|
||||
new Point(34.88499, 119.1761),
|
||||
new Point(34.31145, 120.2487),
|
||||
new Point(32.97499, 120.8858),
|
||||
new Point(32.63889, 120.8375),
|
||||
new Point(32.42958, 121.3348),
|
||||
new Point(32.11333, 121.4412),
|
||||
new Point(32.02166, 121.7066),
|
||||
new Point(31.67833, 121.8275),
|
||||
new Point(31.86639, 120.9444),
|
||||
new Point(32.09361, 120.6019),
|
||||
new Point(31.94555, 120.099),
|
||||
new Point(32.30638, 119.8267),
|
||||
new Point(32.26277, 119.6317),
|
||||
new Point(31.90388, 120.1364),
|
||||
new Point(31.98833, 120.7026),
|
||||
new Point(31.81944, 120.7196),
|
||||
new Point(31.30889, 121.6681),
|
||||
new Point(30.97986, 121.8828),
|
||||
new Point(30.85305, 121.8469),
|
||||
new Point(30.56889, 120.9915),
|
||||
new Point(30.33555, 120.8144),
|
||||
new Point(30.39298, 120.4586),
|
||||
new Point(30.19694, 120.15),
|
||||
new Point(30.31027, 120.5082),
|
||||
new Point(30.06465, 120.7916),
|
||||
new Point(30.30458, 121.2808),
|
||||
new Point(29.96305, 121.6778),
|
||||
new Point(29.88211, 122.1196),
|
||||
new Point(29.51167, 121.4483),
|
||||
new Point(29.58916, 121.9744),
|
||||
new Point(29.19527, 121.9336),
|
||||
new Point(29.18388, 121.8119),
|
||||
new Point(29.37236, 121.7969),
|
||||
new Point(29.19729, 121.7444),
|
||||
new Point(29.29111, 121.5611),
|
||||
new Point(29.1634, 121.4135),
|
||||
new Point(29.02194, 121.6914),
|
||||
new Point(28.9359, 121.4908),
|
||||
new Point(28.72798, 121.6113),
|
||||
new Point(28.84215, 121.1464),
|
||||
new Point(28.66993, 121.4844),
|
||||
new Point(28.34722, 121.6417),
|
||||
new Point(28.13889, 121.3419),
|
||||
new Point(28.38277, 121.1651),
|
||||
new Point(27.98222, 120.9353),
|
||||
new Point(28.07944, 120.5908),
|
||||
new Point(27.87229, 120.84),
|
||||
new Point(27.59319, 120.5812),
|
||||
new Point(27.45083, 120.6655),
|
||||
new Point(27.20777, 120.5075),
|
||||
new Point(27.28278, 120.1896),
|
||||
new Point(27.14764, 120.4211),
|
||||
new Point(26.89805, 120.0332),
|
||||
new Point(26.64465, 120.128),
|
||||
new Point(26.51778, 119.8603),
|
||||
new Point(26.78823, 120.0733),
|
||||
new Point(26.64888, 119.8668),
|
||||
new Point(26.79611, 119.7879),
|
||||
new Point(26.75625, 119.5503),
|
||||
new Point(26.44222, 119.8204),
|
||||
new Point(26.47388, 119.5775),
|
||||
new Point(26.33861, 119.658),
|
||||
new Point(26.36777, 119.9489),
|
||||
new Point(25.99694, 119.4253),
|
||||
new Point(26.14041, 119.0975),
|
||||
new Point(25.93788, 119.354),
|
||||
new Point(25.99069, 119.7058),
|
||||
new Point(25.67996, 119.5807),
|
||||
new Point(25.68222, 119.4522),
|
||||
new Point(25.35333, 119.6454),
|
||||
new Point(25.60649, 119.3149),
|
||||
new Point(25.42097, 119.1053),
|
||||
new Point(25.25319, 119.3526),
|
||||
new Point(25.17208, 119.2726),
|
||||
new Point(25.2426, 118.8749),
|
||||
new Point(24.97194, 118.9866),
|
||||
new Point(24.88291, 118.5729),
|
||||
new Point(24.75673, 118.7631),
|
||||
new Point(24.52861, 118.5953),
|
||||
new Point(24.53638, 118.2397),
|
||||
new Point(24.68194, 118.1688),
|
||||
new Point(24.44024, 118.0199),
|
||||
new Point(24.46019, 117.7947),
|
||||
new Point(24.25875, 118.1237),
|
||||
new Point(23.62437, 117.1957),
|
||||
new Point(23.65919, 116.9179),
|
||||
new Point(23.355, 116.7603),
|
||||
new Point(23.42024, 116.5322),
|
||||
new Point(23.23666, 116.7871),
|
||||
new Point(23.21083, 116.5139),
|
||||
new Point(22.93902, 116.4817),
|
||||
new Point(22.73916, 115.7978),
|
||||
new Point(22.88416, 115.6403),
|
||||
new Point(22.65889, 115.5367),
|
||||
new Point(22.80833, 115.1614),
|
||||
new Point(22.70277, 114.8889),
|
||||
new Point(22.53305, 114.8722),
|
||||
new Point(22.64027, 114.718),
|
||||
new Point(22.81402, 114.7782),
|
||||
new Point(22.69972, 114.5208),
|
||||
new Point(22.50423, 114.6136),
|
||||
new Point(22.55004, 114.2223),
|
||||
new Point(22.42993, 114.3885),
|
||||
new Point(22.26056, 114.2961),
|
||||
new Point(22.36736, 113.9056),
|
||||
new Point(22.50874, 114.0337),
|
||||
new Point(22.47444, 113.8608),
|
||||
new Point(22.83458, 113.606),
|
||||
new Point(23.05027, 113.5253),
|
||||
new Point(23.11724, 113.8219),
|
||||
new Point(23.05083, 113.4793),
|
||||
new Point(22.87986, 113.3629),
|
||||
new Point(22.54944, 113.5648),
|
||||
new Point(22.18701, 113.5527),
|
||||
new Point(22.56701, 113.1687),
|
||||
new Point(22.17965, 113.3868),
|
||||
new Point(22.04069, 113.2226),
|
||||
new Point(22.20485, 113.0848),
|
||||
new Point(21.8693, 112.94),
|
||||
new Point(21.96472, 112.824),
|
||||
new Point(21.70139, 112.2819),
|
||||
new Point(21.91611, 111.8921),
|
||||
new Point(21.75139, 111.9669),
|
||||
new Point(21.77819, 111.6762),
|
||||
new Point(21.61264, 111.7832),
|
||||
new Point(21.5268, 111.644),
|
||||
new Point(21.52528, 111.0285),
|
||||
new Point(21.21138, 110.5328),
|
||||
new Point(21.37322, 110.3944),
|
||||
new Point(20.84381, 110.1594),
|
||||
new Point(20.84083, 110.3755),
|
||||
new Point(20.64, 110.3239),
|
||||
new Point(20.48618, 110.5274),
|
||||
new Point(20.24611, 110.2789),
|
||||
new Point(20.2336, 109.9244),
|
||||
new Point(20.4318, 110.0069),
|
||||
new Point(20.92416, 109.6629),
|
||||
new Point(21.44694, 109.9411),
|
||||
new Point(21.50569, 109.6605),
|
||||
new Point(21.72333, 109.5733),
|
||||
new Point(21.49499, 109.5344),
|
||||
new Point(21.39666, 109.1428),
|
||||
new Point(21.58305, 109.1375),
|
||||
new Point(21.61611, 108.911),
|
||||
new Point(21.79889, 108.8702),
|
||||
new Point(21.59888, 108.7403),
|
||||
new Point(21.93562, 108.4692),
|
||||
new Point(21.59014, 108.5125),
|
||||
new Point(21.68999, 108.3336),
|
||||
new Point(21.51444, 108.2447),
|
||||
new Point(21.54241, 107.99),
|
||||
new Point(21.66694, 107.7831),
|
||||
new Point(21.60526, 107.3627),
|
||||
new Point(22.03083, 106.6933),
|
||||
new Point(22.45682, 106.5517),
|
||||
new Point(22.76389, 106.7875),
|
||||
new Point(22.86694, 106.7029),
|
||||
new Point(22.91253, 105.8771),
|
||||
new Point(23.32416, 105.3587),
|
||||
new Point(23.18027, 104.9075),
|
||||
new Point(22.81805, 104.7319),
|
||||
new Point(22.6875, 104.3747),
|
||||
new Point(22.79812, 104.1113),
|
||||
new Point(22.50387, 103.9687),
|
||||
new Point(22.78287, 103.6538),
|
||||
new Point(22.58436, 103.5224),
|
||||
new Point(22.79451, 103.3337),
|
||||
new Point(22.43652, 103.0304),
|
||||
new Point(22.77187, 102.4744),
|
||||
new Point(22.39629, 102.1407),
|
||||
new Point(22.49777, 101.7415),
|
||||
new Point(22.20916, 101.5744),
|
||||
new Point(21.83444, 101.7653),
|
||||
new Point(21.14451, 101.786),
|
||||
new Point(21.17687, 101.2919),
|
||||
new Point(21.57264, 101.1482),
|
||||
new Point(21.76903, 101.099),
|
||||
new Point(21.47694, 100.6397),
|
||||
new Point(21.43546, 100.2057),
|
||||
new Point(21.72555, 99.97763),
|
||||
new Point(22.05018, 99.95741),
|
||||
new Point(22.15592, 99.16785),
|
||||
new Point(22.93659, 99.56484),
|
||||
new Point(23.08204, 99.5113),
|
||||
new Point(23.18916, 98.92747),
|
||||
new Point(23.97076, 98.67991),
|
||||
new Point(24.16007, 98.89073),
|
||||
new Point(23.92999, 97.54762),
|
||||
new Point(24.26055, 97.7593),
|
||||
new Point(24.47666, 97.54305),
|
||||
new Point(24.73992, 97.55255),
|
||||
new Point(25.61527, 98.19109),
|
||||
new Point(25.56944, 98.36137),
|
||||
new Point(25.85597, 98.7104),
|
||||
new Point(26.12527, 98.56944),
|
||||
new Point(26.18472, 98.73109),
|
||||
new Point(26.79166, 98.77777),
|
||||
new Point(27.52972, 98.69699),
|
||||
new Point(27.6725, 98.45888),
|
||||
new Point(27.54014, 98.31992),
|
||||
new Point(28.14889, 98.14499),
|
||||
new Point(28.54652, 97.55887),
|
||||
new Point(28.22277, 97.34888),
|
||||
new Point(28.46749, 96.65387),
|
||||
new Point(28.35111, 96.40193),
|
||||
new Point(28.525, 96.34027),
|
||||
new Point(28.79569, 96.61373),
|
||||
new Point(29.05666, 96.47083),
|
||||
new Point(28.90138, 96.17532),
|
||||
new Point(29.05972, 96.14888),
|
||||
new Point(29.25757, 96.39172),
|
||||
new Point(29.46444, 96.08315),
|
||||
new Point(29.03527, 95.38777),
|
||||
new Point(29.33346, 94.64751),
|
||||
new Point(29.07348, 94.23456),
|
||||
new Point(28.6692, 93.96172),
|
||||
new Point(28.61876, 93.35194),
|
||||
new Point(28.3193, 93.22205),
|
||||
new Point(28.1419, 92.71044),
|
||||
new Point(27.86194, 92.54498),
|
||||
new Point(27.76472, 91.65776),
|
||||
new Point(27.945, 91.66277),
|
||||
new Point(28.08111, 91.30138),
|
||||
new Point(27.96999, 91.08693),
|
||||
new Point(28.07958, 90.3765),
|
||||
new Point(28.24257, 90.38898),
|
||||
new Point(28.32369, 89.99819),
|
||||
new Point(28.05777, 89.48749),
|
||||
new Point(27.32083, 88.91693)
|
||||
};
|
||||
|
||||
/**
|
||||
* 台湾区域
|
||||
*/
|
||||
private static final Point[] TAIWAN = new Point[]{
|
||||
new Point(25.13474, 121.4441),
|
||||
new Point(25.28361, 121.5632),
|
||||
new Point(25.00722, 122.0004),
|
||||
new Point(24.85028, 121.8182),
|
||||
new Point(24.47638, 121.8397),
|
||||
new Point(23.0875, 121.3556),
|
||||
new Point(21.92791, 120.7196),
|
||||
new Point(22.31277, 120.6103),
|
||||
new Point(22.54044, 120.3071),
|
||||
new Point(23.04437, 120.0539),
|
||||
new Point(23.61708, 120.1112),
|
||||
new Point(25.00166, 121.0017),
|
||||
new Point(25.13474, 121.4441)
|
||||
};
|
||||
|
||||
/**
|
||||
* 海南区域
|
||||
*/
|
||||
private static final Point[] HAINAN = new Point[]{
|
||||
new Point(19.52888, 110.855),
|
||||
new Point(19.16761, 110.4832),
|
||||
new Point(18.80083, 110.5255),
|
||||
new Point(18.3852, 110.0503),
|
||||
new Point(18.39152, 109.7594),
|
||||
new Point(18.19777, 109.7036),
|
||||
new Point(18.50562, 108.6871),
|
||||
new Point(19.28028, 108.6283),
|
||||
new Point(19.76, 109.2939),
|
||||
new Point(19.7236, 109.1653),
|
||||
new Point(19.89972, 109.2572),
|
||||
new Point(19.82861, 109.4658),
|
||||
new Point(19.99389, 109.6108),
|
||||
new Point(20.13361, 110.6655),
|
||||
new Point(19.97861, 110.9425),
|
||||
new Point(19.63829, 111.0215),
|
||||
new Point(19.52888, 110.855)
|
||||
};
|
||||
|
||||
/**
|
||||
* 崇明县
|
||||
*/
|
||||
private static final Point[] CHONGMING = new Point[]{
|
||||
new Point(31.80054, 121.2039),
|
||||
new Point(31.49972, 121.8736),
|
||||
new Point(31.53111, 121.5464),
|
||||
new Point(31.80054, 121.2039)
|
||||
};
|
||||
//endregion
|
||||
|
||||
/**
|
||||
* 中国行政边界的WGS84坐标数据,
|
||||
* 光线投射算法 (Ray casting algorithm) 获得,
|
||||
* 沿海、国界周边地区可能会有误差,更高精度需要调整坐标点
|
||||
*/
|
||||
private static final List<Point[]> CHINA_POLYGON = new ArrayList<>();
|
||||
|
||||
static {
|
||||
CHINA_POLYGON.add(MAINLAND);
|
||||
CHINA_POLYGON.add(TAIWAN);
|
||||
CHINA_POLYGON.add(HAINAN);
|
||||
CHINA_POLYGON.add(CHONGMING);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
package com.ruoyi.common.utils.map;
|
||||
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MapUtils {
|
||||
public static final class MapU {
|
||||
public static final double EARTH_RADIUS = 6378.137;
|
||||
public static final int N_2 = 2;
|
||||
public static final int N_1000 = 1000;
|
||||
public static final double N_180 = 180.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断一个点是否在圆形区域内
|
||||
* @param pointLon 判断点经度
|
||||
* @param pointLat 判断点维度
|
||||
* @param centerLon 圆心经度
|
||||
* @param centerLat 圆心维度
|
||||
* @param radius 半径
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean isInCircle(double pointLon, double pointLat, double centerLon, double centerLat, double radius) {
|
||||
|
||||
return getDistance(pointLon, pointLat, centerLon, centerLat) < radius;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断是否在多边形区域内
|
||||
*
|
||||
* @param pointLon 要判断的点的经度
|
||||
* @param pointLat 要判断的点的维度
|
||||
* @param lon 区域各顶点的经度数组
|
||||
* @param lat 区域各顶点的维度数组
|
||||
* @return
|
||||
*/
|
||||
public static boolean isInPolygon(double pointLon, double pointLat, double[] lon, double[] lat) {
|
||||
// 将要判断的横纵坐标组成一个点
|
||||
Point2D.Double point = new Point2D.Double(pointLon, pointLat);
|
||||
// 将区域各顶点的横纵坐标放到一个点集合里面
|
||||
List<Point2D.Double> pointList = new ArrayList<>();
|
||||
double polygonPoint_x, polygonPoint_y;
|
||||
for (int i = 0; i < lon.length; i++) {
|
||||
polygonPoint_x = lon[i];
|
||||
polygonPoint_y = lat[i];
|
||||
Point2D.Double polygonPoint = new Point2D.Double(polygonPoint_x, polygonPoint_y);
|
||||
pointList.add(polygonPoint);
|
||||
}
|
||||
return areaCheck(point, pointList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否在多边形区域内
|
||||
*
|
||||
* @param point 要判断的点
|
||||
* @param polygon 区域点集合
|
||||
* @return
|
||||
*/
|
||||
public static boolean areaCheck(Point2D.Double point, List<Point2D.Double> polygon) {
|
||||
java.awt.geom.GeneralPath generalPath = new java.awt.geom.GeneralPath();
|
||||
Point2D.Double first = polygon.get(0);
|
||||
// 通过移动到指定坐标(以双精度指定),将一个点添加到路径中
|
||||
generalPath.moveTo(first.x, first.y);
|
||||
polygon.remove(0);
|
||||
for (Point2D.Double d : polygon) {
|
||||
// 通过绘制一条从当前坐标到新指定坐标(以双精度指定)的直线,将一个点添加到路径中。
|
||||
generalPath.lineTo(d.x, d.y);
|
||||
}
|
||||
// 将几何多边形封闭
|
||||
generalPath.lineTo(first.x, first.y);
|
||||
generalPath.closePath();
|
||||
// 测试指定的 Point2D 是否在 Shape 的边界内。
|
||||
return generalPath.contains(point);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个点间的距离
|
||||
*
|
||||
* @param lonA1 A1点的经度
|
||||
* @param latA1 A1点的纬度
|
||||
* @param lonA2 A2点的经度
|
||||
* @param latA2 A2点的纬度
|
||||
* @return
|
||||
*/
|
||||
public static double getDistance(double lonA1, double latA1, double lonA2, double latA2) {
|
||||
// 单位(米)
|
||||
double lon1 = lonA1 * Math.PI / MapU.N_180;
|
||||
double lat1 = latA1 * Math.PI / MapU.N_180;
|
||||
double lon2 = lonA2 * Math.PI / MapU.N_180;
|
||||
double lat2 = latA2 * Math.PI / MapU.N_180;
|
||||
double dlon = lon2 - lon1;
|
||||
double dlat = lat2 - lat1;
|
||||
double a = Math.pow(Math.sin(dlat / MapU.N_2), MapU.N_2) +
|
||||
Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(dlon / MapU.N_2), MapU.N_2);
|
||||
double c = MapU.N_2 * Math.asin(Math.sqrt(a));
|
||||
return c * MapU.EARTH_RADIUS * MapU.N_1000;
|
||||
}
|
||||
|
||||
public static boolean isPtInPoly(double ALon , double ALat , Point[] ps) {
|
||||
int iSum, iCount, iIndex;
|
||||
double dLon1 = 0, dLon2 = 0, dLat1 = 0, dLat2 = 0, dLon;
|
||||
if (ps.length < 3) {
|
||||
return false;
|
||||
}
|
||||
iSum = 0;
|
||||
iCount = ps.length;
|
||||
for (iIndex = 0; iIndex<iCount;iIndex++) {
|
||||
if (iIndex == iCount - 1) {
|
||||
dLon1 = ps[iIndex].getX();
|
||||
dLat1 = ps[iIndex].getY();
|
||||
dLon2 = ps[0].getX();
|
||||
dLat2 = ps[0].getY();
|
||||
} else {
|
||||
dLon1 = ps[iIndex].getX();
|
||||
dLat1 = ps[iIndex].getY();
|
||||
dLon2 = ps[iIndex + 1].getX();
|
||||
dLat2 = ps[iIndex + 1].getY();
|
||||
}
|
||||
// 以下语句判断A点是否在边的两端点的水平平行线之间,在则可能有交点,开始判断交点是否在左射线上
|
||||
if (((ALat >= dLat1) && (ALat < dLat2)) || ((ALat >= dLat2) && (ALat < dLat1))) {
|
||||
if (Math.abs(dLat1 - dLat2) > 0) {
|
||||
//得到 A点向左射线与边的交点的x坐标:
|
||||
dLon = dLon1 - ((dLon1 - dLon2) * (dLat1 - ALat) ) / (dLat1 - dLat2);
|
||||
// 如果交点在A点左侧(说明是做射线与 边的交点),则射线与边的全部交点数加一:
|
||||
if (dLon < ALon) {
|
||||
iSum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((iSum % 2) != 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
//114.331951,30.64091#114.341049,30.610185#114.331436,30.588058#114.312038,30.56393#114.293498,30.558609#114.267922,30.563784#114.231185,30.57945#114.212303,30.601616#114.235649,30.626878#114.280624,30.646818#
|
||||
Map[] map=new Map[]{};
|
||||
Point[] ps = new Point[] { new Point(114.309914,30.599556),//114.309914,30.599556
|
||||
new Point(114.295688,30.592879),//114.295688,30.592879
|
||||
new Point(114.292812,30.587726), //114.292812,30.587726
|
||||
new Point(114.292812,30.587726), //114.292812,30.587726
|
||||
new Point(114.30058,30.580318),//114.30058,30.580318
|
||||
new Point(114.303606,30.586959),//114.303606,30.586959
|
||||
new Point(114.304534,30.594751),//114.304534,30.594751
|
||||
new Point(114.30838,30.590131),//114.30838,30.590131
|
||||
new Point(114.308651,30.584182),//114.308651,30.584182
|
||||
new Point(114.304495,30.584015),//114.304495,30.584015
|
||||
new Point(114.301301,30.578759),//114.301301,30.578759
|
||||
new Point(114.309437,30.578528),//114.309437,30.578528
|
||||
new Point(114.323282,30.592786)};//114.323282,30.592786
|
||||
Point n1 = new Point(114.303217,30.583553);
|
||||
Point n2 = new Point(114.307336,30.597592);
|
||||
Point n3 = new Point(114.286565,30.590056);
|
||||
Point y1 = new Point(114.227342,30.587987);
|
||||
Point y2 = new Point(120.1866 , 30.2672);
|
||||
Point y4 = new Point(120.1869 , 30.2718);
|
||||
System.out.println( "n1:" + isPtInPoly(n1.getX() , n1.getY() , ps));
|
||||
System.out.println( "n2:" + isPtInPoly(n2.getX() , n2.getY() , ps));
|
||||
System.out.println( "n3:" + isPtInPoly(n3.getX() , n3.getY() , ps));
|
||||
System.out.println( "y1:" + isPtInPoly(y1.getX() , y1.getY() , ps));
|
||||
System.out.println( "y2:" + isPtInPoly(y2.getX() , y2.getY() , ps));
|
||||
System.out.println( "y4:" + isPtInPoly(y4.getX() , y4.getY() , ps));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.ruoyi.common.utils.map;
|
||||
|
||||
public class Point {
|
||||
private Double x;
|
||||
private Double y;
|
||||
|
||||
public Point (Double x , Double y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
public Double getX() {
|
||||
return x;
|
||||
}
|
||||
public void setX(Double x) {
|
||||
this.x = x;
|
||||
}
|
||||
public Double getY() {
|
||||
return y;
|
||||
}
|
||||
public void setY(Double y) {
|
||||
this.y = y;
|
||||
}
|
||||
}
|
|
@ -2,8 +2,12 @@ package com.ruoyi.bst.area.domain;
|
|||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import com.ruoyi.common.core.validate.ValidGroup;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
@ -27,6 +31,8 @@ public class Area extends BaseEntity
|
|||
|
||||
@Excel(name = "区域名称")
|
||||
@ApiModelProperty("区域名称")
|
||||
@NotBlank(message = "区域名称不能为空", groups = {ValidGroup.Create.class})
|
||||
@Size(max = 50, message = "区域名称不能超过50个字符")
|
||||
private String name;
|
||||
|
||||
@Excel(name = "边界值")
|
||||
|
|
|
@ -14,4 +14,12 @@ public class AreaVO extends Area {
|
|||
@ApiModelProperty("创建人名称")
|
||||
private String createName;
|
||||
|
||||
@ApiModelProperty("停车区数量")
|
||||
private Integer parkingAreaCount;
|
||||
|
||||
@ApiModelProperty("禁停区数量")
|
||||
private Integer noParkingAreaCount;
|
||||
|
||||
@ApiModelProperty("禁行区数量")
|
||||
private Integer noRideAreaCount;
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="userId != null">#{userId},</if>
|
||||
<if test="name != null and name != ''">#{name},</if>
|
||||
<if test="boundary != null">#{boundary},</if>
|
||||
<if test="boundary != null">ST_GeomFromText(#{boundary}),</if>
|
||||
<if test="boundaryStr != null">#{boundaryStr},</if>
|
||||
<if test="longitude != null">#{longitude},</if>
|
||||
<if test="latitude != null">#{latitude},</if>
|
||||
|
@ -169,7 +169,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<sql id="updateColumns">
|
||||
<if test="data.userId != null">user_id = #{data.userId},</if>
|
||||
<if test="data.name != null and data.name != ''">name = #{data.name},</if>
|
||||
<if test="data.boundary != null">boundary = #{data.boundary},</if>
|
||||
<if test="data.boundary != null">boundary = ST_GeomFromText(#{data.boundary}),</if>
|
||||
<if test="data.boundaryStr != null">boundary_str = #{data.boundaryStr},</if>
|
||||
<if test="data.longitude != null">longitude = #{data.longitude},</if>
|
||||
<if test="data.latitude != null">latitude = #{data.latitude},</if>
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package com.ruoyi.bst.area.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.ruoyi.bst.area.domain.AreaVO;
|
||||
|
||||
public interface AreaAssembler {
|
||||
|
||||
/**
|
||||
* 组装子区域数量
|
||||
*/
|
||||
void assembleSubAreaCount(List<AreaVO> list);
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package com.ruoyi.bst.area.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.ruoyi.bst.area.domain.AreaVO;
|
||||
import com.ruoyi.bst.area.service.AreaAssembler;
|
||||
import com.ruoyi.bst.areaSub.domain.AreaSubQuery;
|
||||
import com.ruoyi.bst.areaSub.domain.enums.AreaSubType;
|
||||
import com.ruoyi.bst.areaSub.domain.vo.AreaSubCountTypeByAreaVO;
|
||||
import com.ruoyi.bst.areaSub.service.AreaSubDashboard;
|
||||
import com.ruoyi.common.utils.collection.CollectionUtils;
|
||||
|
||||
@Service
|
||||
public class AreaAssemblerImpl implements AreaAssembler {
|
||||
|
||||
@Autowired
|
||||
private AreaSubDashboard areaSubDashboard;
|
||||
|
||||
@Override
|
||||
public void assembleSubAreaCount(List<AreaVO> list) {
|
||||
if (CollectionUtils.isEmptyElement(list)) {
|
||||
return;
|
||||
}
|
||||
|
||||
AreaSubQuery query = new AreaSubQuery();
|
||||
query.setAreaIds(CollectionUtils.map(list, AreaVO::getId));
|
||||
List<AreaSubCountTypeByAreaVO> countList = areaSubDashboard.selectTypeCountGroupByAreaId(query);
|
||||
|
||||
for (AreaVO area : list) {
|
||||
|
||||
// 停车区
|
||||
AreaSubCountTypeByAreaVO parkingAreaCount = countList.stream()
|
||||
.filter(item -> Objects.equals(item.getAreaId(), area.getId()) && AreaSubType.PARKING.getCode().equals(item.getType()))
|
||||
.findFirst().orElse(null);
|
||||
if (parkingAreaCount != null) {
|
||||
area.setParkingAreaCount(parkingAreaCount.getCount());
|
||||
} else {
|
||||
area.setParkingAreaCount(0);
|
||||
}
|
||||
|
||||
// 禁停区
|
||||
AreaSubCountTypeByAreaVO noParkingAreaCount = countList.stream()
|
||||
.filter(item -> Objects.equals(item.getAreaId(), area.getId()) && AreaSubType.NO_PARKING.getCode().equals(item.getType()))
|
||||
.findFirst().orElse(null);
|
||||
if (noParkingAreaCount != null) {
|
||||
area.setNoParkingAreaCount(noParkingAreaCount.getCount());
|
||||
} else {
|
||||
area.setNoParkingAreaCount(0);
|
||||
}
|
||||
|
||||
// 禁行区
|
||||
AreaSubCountTypeByAreaVO noRideAreaCount = countList.stream()
|
||||
.filter(item -> Objects.equals(item.getAreaId(), area.getId()) && AreaSubType.NO_RIDE.getCode().equals(item.getType()))
|
||||
.findFirst().orElse(null);
|
||||
if (noRideAreaCount != null) {
|
||||
area.setNoRideAreaCount(noRideAreaCount.getCount());
|
||||
} else {
|
||||
area.setNoRideAreaCount(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -2,6 +2,9 @@ package com.ruoyi.bst.area.service.impl;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.ruoyi.common.utils.map.GeoUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.locationtech.jts.geom.Geometry;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
@ -19,6 +22,7 @@ import com.ruoyi.common.utils.DateUtils;
|
|||
* @date 2025-03-14
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AreaServiceImpl implements AreaService
|
||||
{
|
||||
@Autowired
|
||||
|
@ -57,6 +61,11 @@ public class AreaServiceImpl implements AreaService
|
|||
@Override
|
||||
public int insertArea(Area area)
|
||||
{
|
||||
// 将边界值转Geometry对象
|
||||
if (area.getBoundaryStr() != null) {
|
||||
Geometry geometry = GeoUtils.toGeometry(area.getBoundaryStr());
|
||||
area.setBoundary(GeoUtils.wkt(geometry));
|
||||
}
|
||||
area.setCreateTime(DateUtils.getNowDate());
|
||||
return areaMapper.insertArea(area);
|
||||
}
|
||||
|
@ -70,6 +79,11 @@ public class AreaServiceImpl implements AreaService
|
|||
@Override
|
||||
public int updateArea(Area area)
|
||||
{
|
||||
// 将边界值转Geometry对象
|
||||
if (area.getBoundaryStr() != null) {
|
||||
Geometry geometry = GeoUtils.toGeometry(area.getBoundaryStr());
|
||||
area.setBoundary(GeoUtils.wkt(geometry));
|
||||
}
|
||||
return areaMapper.updateArea(area);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package com.ruoyi.bst.areaSub.domain;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
|
@ -7,4 +10,8 @@ import lombok.EqualsAndHashCode;
|
|||
@EqualsAndHashCode(callSuper = true)
|
||||
public class AreaSubQuery extends AreaSubVO {
|
||||
|
||||
@ApiModelProperty(value = "区域ID列表")
|
||||
private List<Long> areaIds;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package com.ruoyi.bst.areaSub.domain.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum AreaSubType {
|
||||
|
||||
PARKING("1", "停车区"),
|
||||
NO_PARKING("2", "禁停区"),
|
||||
NO_RIDE("3", "禁行区");
|
||||
|
||||
|
||||
private String code;
|
||||
|
||||
private String name;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.ruoyi.bst.areaSub.domain.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AreaSubCountTypeByAreaVO {
|
||||
|
||||
@ApiModelProperty("区域ID")
|
||||
private Long areaId;
|
||||
|
||||
@ApiModelProperty("类型")
|
||||
private String type;
|
||||
|
||||
@ApiModelProperty("数量")
|
||||
private Integer count;
|
||||
|
||||
}
|
|
@ -1,11 +1,14 @@
|
|||
package com.ruoyi.bst.areaSub.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.ruoyi.bst.areaSub.domain.AreaSub;
|
||||
import com.ruoyi.bst.areaSub.domain.AreaSubVO;
|
||||
import com.ruoyi.bst.areaSub.domain.AreaSubQuery;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import com.ruoyi.bst.areaSub.domain.AreaSub;
|
||||
import com.ruoyi.bst.areaSub.domain.AreaSubQuery;
|
||||
import com.ruoyi.bst.areaSub.domain.AreaSubVO;
|
||||
import com.ruoyi.bst.areaSub.domain.vo.AreaSubCountTypeByAreaVO;
|
||||
|
||||
/**
|
||||
* 子区域Mapper接口
|
||||
*
|
||||
|
@ -38,16 +41,6 @@ public interface AreaSubMapper
|
|||
*/
|
||||
int insertAreaSub(AreaSub areaSub);
|
||||
|
||||
/**
|
||||
* 批量新增子区域
|
||||
*/
|
||||
int batchInsert(@Param("list") List<? extends AreaSub> list);
|
||||
|
||||
/**
|
||||
* 批量修改子区域
|
||||
*/
|
||||
int batchUpdate(@Param("list") List<? extends AreaSub> list);
|
||||
|
||||
/**
|
||||
* 修改子区域
|
||||
*
|
||||
|
@ -71,4 +64,6 @@ public interface AreaSubMapper
|
|||
* @return 结果
|
||||
*/
|
||||
public int deleteAreaSubByIds(Long[] ids);
|
||||
|
||||
List<AreaSubCountTypeByAreaVO> selectTypeCountGroupByAreaId(@Param("query") AreaSubQuery query);
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="name != null">#{name},</if>
|
||||
<if test="type != null">#{type},</if>
|
||||
<if test="areaId != null">#{areaId},</if>
|
||||
<if test="boundary != null">#{boundary},</if>
|
||||
<if test="boundary != null">ST_GeomFromText(#{boundary}),</if>
|
||||
<if test="boundaryStr != null">#{boundaryStr},</if>
|
||||
<if test="error != null">#{error},</if>
|
||||
<if test="longitude != null">#{longitude},</if>
|
||||
|
@ -91,183 +91,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
</trim>
|
||||
</insert>
|
||||
|
||||
<insert id="batchInsert" parameterType="AreaSub" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into bst_area_sub
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
name,
|
||||
type,
|
||||
area_id,
|
||||
boundary,
|
||||
boundary_str,
|
||||
error,
|
||||
longitude,
|
||||
latitude,
|
||||
create_time,
|
||||
picture,
|
||||
remark,
|
||||
status,
|
||||
</trim>
|
||||
values
|
||||
<foreach collection="list" item="i" separator=",">
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="i.name != null ">#{i.name},</if>
|
||||
<if test="i.name == null ">default,</if>
|
||||
<if test="i.type != null ">#{i.type},</if>
|
||||
<if test="i.type == null ">default,</if>
|
||||
<if test="i.areaId != null ">#{i.areaId},</if>
|
||||
<if test="i.areaId == null ">default,</if>
|
||||
<if test="i.boundary != null ">#{i.boundary},</if>
|
||||
<if test="i.boundary == null ">default,</if>
|
||||
<if test="i.boundaryStr != null ">#{i.boundaryStr},</if>
|
||||
<if test="i.boundaryStr == null ">default,</if>
|
||||
<if test="i.error != null ">#{i.error},</if>
|
||||
<if test="i.error == null ">default,</if>
|
||||
<if test="i.longitude != null ">#{i.longitude},</if>
|
||||
<if test="i.longitude == null ">default,</if>
|
||||
<if test="i.latitude != null ">#{i.latitude},</if>
|
||||
<if test="i.latitude == null ">default,</if>
|
||||
<if test="i.createTime != null ">#{i.createTime},</if>
|
||||
<if test="i.createTime == null ">default,</if>
|
||||
<if test="i.picture != null ">#{i.picture},</if>
|
||||
<if test="i.picture == null ">default,</if>
|
||||
<if test="i.remark != null ">#{i.remark},</if>
|
||||
<if test="i.remark == null ">default,</if>
|
||||
<if test="i.status != null and i.status != ''">#{i.status},</if>
|
||||
<if test="i.status == null or i.status == ''">default,</if>
|
||||
</trim>
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<update id="batchUpdate">
|
||||
update bst_area_sub
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<foreach open="name = CASE id" collection="list" item="item" close="END,">
|
||||
<choose>
|
||||
<when test="item.name != null ">
|
||||
WHEN #{item.id} THEN #{item.name}
|
||||
</when>
|
||||
<otherwise>
|
||||
WHEN #{item.id} THEN `name`
|
||||
</otherwise>
|
||||
</choose>
|
||||
</foreach>
|
||||
<foreach open="type = CASE id" collection="list" item="item" close="END,">
|
||||
<choose>
|
||||
<when test="item.type != null ">
|
||||
WHEN #{item.id} THEN #{item.type}
|
||||
</when>
|
||||
<otherwise>
|
||||
WHEN #{item.id} THEN `type`
|
||||
</otherwise>
|
||||
</choose>
|
||||
</foreach>
|
||||
<foreach open="area_id = CASE id" collection="list" item="item" close="END,">
|
||||
<choose>
|
||||
<when test="item.areaId != null ">
|
||||
WHEN #{item.id} THEN #{item.areaId}
|
||||
</when>
|
||||
<otherwise>
|
||||
WHEN #{item.id} THEN `area_id`
|
||||
</otherwise>
|
||||
</choose>
|
||||
</foreach>
|
||||
<foreach open="boundary = CASE id" collection="list" item="item" close="END,">
|
||||
<choose>
|
||||
<when test="item.boundary != null ">
|
||||
WHEN #{item.id} THEN #{item.boundary}
|
||||
</when>
|
||||
<otherwise>
|
||||
WHEN #{item.id} THEN `boundary`
|
||||
</otherwise>
|
||||
</choose>
|
||||
</foreach>
|
||||
<foreach open="boundary_str = CASE id" collection="list" item="item" close="END,">
|
||||
<choose>
|
||||
<when test="item.boundaryStr != null ">
|
||||
WHEN #{item.id} THEN #{item.boundaryStr}
|
||||
</when>
|
||||
<otherwise>
|
||||
WHEN #{item.id} THEN `boundary_str`
|
||||
</otherwise>
|
||||
</choose>
|
||||
</foreach>
|
||||
<foreach open="error = CASE id" collection="list" item="item" close="END,">
|
||||
<choose>
|
||||
<when test="item.error != null ">
|
||||
WHEN #{item.id} THEN #{item.error}
|
||||
</when>
|
||||
<otherwise>
|
||||
WHEN #{item.id} THEN `error`
|
||||
</otherwise>
|
||||
</choose>
|
||||
</foreach>
|
||||
<foreach open="longitude = CASE id" collection="list" item="item" close="END,">
|
||||
<choose>
|
||||
<when test="item.longitude != null ">
|
||||
WHEN #{item.id} THEN #{item.longitude}
|
||||
</when>
|
||||
<otherwise>
|
||||
WHEN #{item.id} THEN `longitude`
|
||||
</otherwise>
|
||||
</choose>
|
||||
</foreach>
|
||||
<foreach open="latitude = CASE id" collection="list" item="item" close="END,">
|
||||
<choose>
|
||||
<when test="item.latitude != null ">
|
||||
WHEN #{item.id} THEN #{item.latitude}
|
||||
</when>
|
||||
<otherwise>
|
||||
WHEN #{item.id} THEN `latitude`
|
||||
</otherwise>
|
||||
</choose>
|
||||
</foreach>
|
||||
<foreach open="create_time = CASE id" collection="list" item="item" close="END,">
|
||||
<choose>
|
||||
<when test="item.createTime != null ">
|
||||
WHEN #{item.id} THEN #{item.createTime}
|
||||
</when>
|
||||
<otherwise>
|
||||
WHEN #{item.id} THEN `create_time`
|
||||
</otherwise>
|
||||
</choose>
|
||||
</foreach>
|
||||
<foreach open="picture = CASE id" collection="list" item="item" close="END,">
|
||||
<choose>
|
||||
<when test="item.picture != null ">
|
||||
WHEN #{item.id} THEN #{item.picture}
|
||||
</when>
|
||||
<otherwise>
|
||||
WHEN #{item.id} THEN `picture`
|
||||
</otherwise>
|
||||
</choose>
|
||||
</foreach>
|
||||
<foreach open="remark = CASE id" collection="list" item="item" close="END,">
|
||||
<choose>
|
||||
<when test="item.remark != null ">
|
||||
WHEN #{item.id} THEN #{item.remark}
|
||||
</when>
|
||||
<otherwise>
|
||||
WHEN #{item.id} THEN `remark`
|
||||
</otherwise>
|
||||
</choose>
|
||||
</foreach>
|
||||
<foreach open="status = CASE id" collection="list" item="item" close="END,">
|
||||
<choose>
|
||||
<when test="item.status != null and item.status != ''">
|
||||
WHEN #{item.id} THEN #{item.status}
|
||||
</when>
|
||||
<otherwise>
|
||||
WHEN #{item.id} THEN `status`
|
||||
</otherwise>
|
||||
</choose>
|
||||
</foreach>
|
||||
</trim>
|
||||
where id in
|
||||
<foreach item="item" collection="list" open="(" separator="," close=")">
|
||||
#{item.id}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<update id="updateAreaSub" parameterType="AreaSub">
|
||||
update bst_area_sub
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
|
@ -280,7 +103,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="data.name != null">name = #{data.name},</if>
|
||||
<if test="data.type != null">type = #{data.type},</if>
|
||||
<if test="data.areaId != null">area_id = #{data.areaId},</if>
|
||||
<if test="data.boundary != null">boundary = #{data.boundary},</if>
|
||||
<if test="data.boundary != null">boundary = ST_GeomFromText(#{data.boundary}),</if>
|
||||
<if test="data.boundaryStr != null">boundary_str = #{data.boundaryStr},</if>
|
||||
<if test="data.error != null">error = #{data.error},</if>
|
||||
<if test="data.longitude != null">longitude = #{data.longitude},</if>
|
||||
|
@ -301,4 +124,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
<!-- selectTypeCountGroupByAreaId -->
|
||||
|
||||
<select id="selectTypeCountGroupByAreaId" resultType="AreaSubCountTypeByAreaVO">
|
||||
select
|
||||
bas.area_id,
|
||||
bas.type,
|
||||
count(bas.id) as `count`
|
||||
from bst_area_sub bas
|
||||
<where>
|
||||
<include refid="searchCondition"/>
|
||||
</where>
|
||||
group by bas.area_id, bas.type
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package com.ruoyi.bst.areaSub.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.ruoyi.bst.areaSub.domain.AreaSubQuery;
|
||||
import com.ruoyi.bst.areaSub.domain.vo.AreaSubCountTypeByAreaVO;
|
||||
|
||||
public interface AreaSubDashboard {
|
||||
|
||||
/**
|
||||
* 根据区域id查询类型统计
|
||||
*/
|
||||
List<AreaSubCountTypeByAreaVO> selectTypeCountGroupByAreaId(AreaSubQuery query);
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.ruoyi.bst.areaSub.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.ruoyi.bst.areaSub.domain.AreaSubQuery;
|
||||
import com.ruoyi.bst.areaSub.domain.vo.AreaSubCountTypeByAreaVO;
|
||||
import com.ruoyi.bst.areaSub.mapper.AreaSubMapper;
|
||||
import com.ruoyi.bst.areaSub.service.AreaSubDashboard;
|
||||
|
||||
@Service
|
||||
public class AreaSubDashboardImpl implements AreaSubDashboard {
|
||||
|
||||
@Autowired
|
||||
private AreaSubMapper areaSubMapper;
|
||||
|
||||
|
||||
@Override
|
||||
public List<AreaSubCountTypeByAreaVO> selectTypeCountGroupByAreaId(AreaSubQuery query) {
|
||||
return areaSubMapper.selectTypeCountGroupByAreaId(query);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -3,6 +3,8 @@ package com.ruoyi.bst.areaSub.service.impl;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.ruoyi.common.utils.map.GeoUtils;
|
||||
import org.locationtech.jts.geom.Geometry;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
@ -59,6 +61,11 @@ public class AreaSubServiceImpl implements AreaSubService
|
|||
public int insertAreaSub(AreaSub areaSub)
|
||||
{
|
||||
areaSub.setCreateTime(DateUtils.getNowDate());
|
||||
// 将边界值转Geometry对象
|
||||
if (areaSub.getBoundaryStr() != null) {
|
||||
Geometry geometry = GeoUtils.toGeometry(areaSub.getBoundaryStr());
|
||||
areaSub.setBoundary(GeoUtils.wkt(geometry));
|
||||
}
|
||||
return areaSubMapper.insertAreaSub(areaSub);
|
||||
}
|
||||
|
||||
|
@ -71,6 +78,11 @@ public class AreaSubServiceImpl implements AreaSubService
|
|||
@Override
|
||||
public int updateAreaSub(AreaSub areaSub)
|
||||
{
|
||||
// 将边界值转Geometry对象
|
||||
if (areaSub.getBoundaryStr() != null) {
|
||||
Geometry geometry = GeoUtils.toGeometry(areaSub.getBoundaryStr());
|
||||
areaSub.setBoundary(GeoUtils.wkt(geometry));
|
||||
}
|
||||
return areaSubMapper.updateAreaSub(areaSub);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.springframework.web.bind.annotation.RestController;
|
|||
import com.ruoyi.bst.area.domain.Area;
|
||||
import com.ruoyi.bst.area.domain.AreaQuery;
|
||||
import com.ruoyi.bst.area.domain.AreaVO;
|
||||
import com.ruoyi.bst.area.service.AreaAssembler;
|
||||
import com.ruoyi.bst.area.service.AreaService;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
|
@ -41,6 +42,9 @@ public class AreaController extends BaseController
|
|||
@Autowired
|
||||
private AreaService areaService;
|
||||
|
||||
@Autowired
|
||||
private AreaAssembler areaAssembler;
|
||||
|
||||
/**
|
||||
* 查询运营区列表
|
||||
*/
|
||||
|
@ -51,6 +55,7 @@ public class AreaController extends BaseController
|
|||
startPage();
|
||||
startOrderBy();
|
||||
List<AreaVO> list = areaService.selectAreaList(query);
|
||||
areaAssembler.assembleSubAreaCount(list);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
|
@ -85,6 +90,7 @@ public class AreaController extends BaseController
|
|||
@PostMapping
|
||||
public AjaxResult add(@RequestBody @Validated(ValidGroup.Create.class) Area area)
|
||||
{
|
||||
area.setCreateId(getUserId());
|
||||
return toAjax(areaService.insertArea(area));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user