支持标准矢量图层的创建和展示
This commit is contained in:
@@ -38,6 +38,10 @@ public class GlobalResponseAdvice implements ResponseBodyAdvice<Object> {
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedContentType.equals(MediaType.parseMediaType("application/x-protobuf"))) {
|
||||
return body;
|
||||
}
|
||||
|
||||
if (body instanceof WVPResult) {
|
||||
return body;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,10 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -498,6 +502,20 @@ public class ChannelController {
|
||||
channelService.resetLevel();
|
||||
}
|
||||
|
||||
@Operation(summary = "为地图提供标准的mvt图层", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@GetMapping(value = "/map/tile/{z}/{x}/{y}", produces = "application/x-protobuf")
|
||||
@Parameter(name = "geoCoordSys", description = "地理坐标系, WGS84/GCJ02")
|
||||
public ResponseEntity<byte[]> getTile(@PathVariable int z, @PathVariable int x, @PathVariable int y, String geoCoordSys){
|
||||
|
||||
|
||||
try {
|
||||
byte[] mvt = channelService.getTile(z, x, y, geoCoordSys);
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.parseMediaType("application/x-protobuf"));
|
||||
headers.setContentLength(mvt.length);
|
||||
return new ResponseEntity<>(mvt, headers, HttpStatus.OK);
|
||||
} catch (Exception e) {
|
||||
log.error("构建矢量瓦片失败: z: {}, x: {}, y:{}", z, x, y, e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -673,4 +673,7 @@ public interface CommonGBChannelMapper {
|
||||
@Update("UPDATE wvp_device_channel SET map_level=null")
|
||||
int resetLevel();
|
||||
|
||||
@SelectProvider(type = ChannelProvider.class, method = "queryCameraChannelInBox")
|
||||
List<CommonGBChannel> queryCameraChannelInBox(@Param("minLon") double minLon, @Param("maxLon") double maxLon,
|
||||
@Param("minLat") double minLat, @Param("maxLat") double maxLat);
|
||||
}
|
||||
|
||||
@@ -527,10 +527,13 @@ public class ChannelProvider {
|
||||
" where data_type=#{dataType} and data_device_id=#{dataDeviceId} AND device_id=#{deviceId}";
|
||||
}
|
||||
|
||||
public String queryOnlineListsByGbDeviceId(Map<String, Object> params ){
|
||||
public String queryCameraChannelInBox(Map<String, Object> params ){
|
||||
StringBuilder sqlBuild = new StringBuilder();
|
||||
sqlBuild.append(BASE_SQL_TABLE_NAME);
|
||||
sqlBuild.append(" where wdc.channel_type = 0 AND coalesce(wdc.gb_status, wdc.status) = 'ON' AND wdc.data_type = 1 AND data_device_id = #{deviceId}");
|
||||
sqlBuild.append(" where coalesce(wdc.gb_longitude, wdc.longitude) > #{minLon} " +
|
||||
"AND coalesce(wdc.gb_longitude, wdc.longitude) <= #{maxLon} " +
|
||||
"AND coalesce(wdc.gb_latitude, wdc.latitude) > #{minLat} " +
|
||||
"AND coalesce(wdc.gb_latitude, wdc.latitude) <= #{maxLat}");
|
||||
return sqlBuild.toString();
|
||||
}
|
||||
|
||||
@@ -570,6 +573,13 @@ public class ChannelProvider {
|
||||
return sqlBuild.toString();
|
||||
}
|
||||
|
||||
public String queryOnlineListsByGbDeviceId(Map<String, Object> params ){
|
||||
StringBuilder sqlBuild = new StringBuilder();
|
||||
sqlBuild.append(BASE_SQL_TABLE_NAME);
|
||||
sqlBuild.append(" where wdc.channel_type = 0 AND coalesce(wdc.gb_status, wdc.status) = 'ON' AND wdc.data_type = 1 AND data_device_id = #{deviceId}");
|
||||
return sqlBuild.toString();
|
||||
}
|
||||
|
||||
public String queryListForSy(Map<String, Object> params ){
|
||||
StringBuilder sqlBuild = new StringBuilder();
|
||||
sqlBuild.append(BASE_SQL_FOR_CAMERA_DEVICE);
|
||||
|
||||
@@ -107,4 +107,6 @@ public interface IGbChannelService {
|
||||
|
||||
void resetLevel();
|
||||
|
||||
byte[] getTile(int z, int x, int y, String geoCoordSys);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service.impl;
|
||||
|
||||
import com.alibaba.excel.support.cglib.beans.BeanMap;
|
||||
import com.alibaba.excel.util.BeanMapUtils;
|
||||
import com.genersoft.iot.vmp.common.enums.ChannelDataType;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
@@ -14,21 +16,24 @@ import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService;
|
||||
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
||||
import com.genersoft.iot.vmp.streamPush.bean.StreamPush;
|
||||
import com.genersoft.iot.vmp.utils.Coordtransform;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import no.ecc.vectortile.VectorTileEncoder;
|
||||
import org.locationtech.jts.geom.Coordinate;
|
||||
import org.locationtech.jts.geom.GeometryFactory;
|
||||
import org.locationtech.jts.geom.Point;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@@ -52,6 +57,8 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
@Autowired
|
||||
private GroupMapper groupMapper;
|
||||
|
||||
private final GeometryFactory geometryFactory = new GeometryFactory();
|
||||
|
||||
@Override
|
||||
public CommonGBChannel queryByDeviceId(String gbDeviceId) {
|
||||
List<CommonGBChannel> commonGBChannels = commonGBChannelMapper.queryByDeviceId(gbDeviceId);
|
||||
@@ -859,4 +866,89 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
public void resetLevel() {
|
||||
commonGBChannelMapper.resetLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getTile(int z, int x, int y, String geoCoordSys) {
|
||||
double minLon = tile2lon(x, z);
|
||||
double maxLon = tile2lon(x + 1, z);
|
||||
double maxLat = tile2lat(y, z);
|
||||
double minLat = tile2lat(y + 1, z);
|
||||
|
||||
if (geoCoordSys != null) {
|
||||
if (geoCoordSys.equalsIgnoreCase("GCJ02")) {
|
||||
Double[] minPosition = Coordtransform.GCJ02ToWGS84(minLon, minLat);
|
||||
minLon = minPosition[0];
|
||||
minLat = minPosition[1];
|
||||
|
||||
Double[] maxPosition = Coordtransform.GCJ02ToWGS84(maxLon, maxLat);
|
||||
maxLon = maxPosition[0];
|
||||
maxLat = maxPosition[1];
|
||||
}
|
||||
}
|
||||
// 从数据库查询对应的数据
|
||||
List<CommonGBChannel> channelList = commonGBChannelMapper.queryCameraChannelInBox(minLon, maxLon, minLat, maxLat);
|
||||
VectorTileEncoder encoder = new VectorTileEncoder();
|
||||
if (!channelList.isEmpty()) {
|
||||
channelList.forEach(commonGBChannel -> {
|
||||
double lon = commonGBChannel.getGbLongitude();
|
||||
double lat = commonGBChannel.getGbLatitude();
|
||||
// 转换为目标坐标系
|
||||
if (geoCoordSys != null) {
|
||||
if (geoCoordSys.equalsIgnoreCase("GCJ02")) {
|
||||
Double[] minPosition = Coordtransform.WGS84ToGCJ02(lon, lat);
|
||||
lon = minPosition[0];
|
||||
lat = minPosition[1];
|
||||
}
|
||||
}
|
||||
|
||||
// 将 lon/lat 转为瓦片内像素坐标(0..256)
|
||||
double[] px = lonLatToTilePixel(lon, lat, z, x, y);
|
||||
Point pointGeom = geometryFactory.createPoint(new Coordinate(px[0], px[1]));
|
||||
|
||||
BeanMap beanMap = BeanMapUtils.create(commonGBChannel);
|
||||
|
||||
// Map<String, Object> props = new HashMap<>();
|
||||
// props.put("id", commonGBChannel.getGbId());
|
||||
// props.put("name", commonGBChannel.getGbName());
|
||||
// props.put("deviceId", commonGBChannel.getGbDeviceId());
|
||||
// props.put("status", commonGBChannel.getGbStatus());
|
||||
|
||||
encoder.addFeature("points", beanMap, pointGeom);
|
||||
});
|
||||
}
|
||||
return encoder.encode();
|
||||
}
|
||||
|
||||
/**
|
||||
* tile X/Z -> longitude (deg)
|
||||
*/
|
||||
private double tile2lon(int x, int z) {
|
||||
double n = Math.pow(2.0, z);
|
||||
return x / n * 360.0 - 180.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tile Y/Z -> latitude (deg)
|
||||
*/
|
||||
private double tile2lat(int y, int z) {
|
||||
double n = Math.pow(2.0, z);
|
||||
double latRad = Math.atan(Math.sinh(Math.PI * (1 - 2.0 * y / n)));
|
||||
return Math.toDegrees(latRad);
|
||||
}
|
||||
|
||||
/**
|
||||
* lon/lat -> pixel in tile (0..256)
|
||||
*/
|
||||
private double[] lonLatToTilePixel(double lon, double lat, int z, int tileX, int tileY) {
|
||||
double n = Math.pow(2.0, z);
|
||||
double xtile = (lon + 180.0) / 360.0 * n;
|
||||
|
||||
double latRad = Math.toRadians(lat);
|
||||
double ytile = (1.0 - Math.log(Math.tan(latRad) + 1.0 / Math.cos(latRad)) / Math.PI) / 2.0 * n;
|
||||
|
||||
double pixelX = (xtile - tileX) * 256.0;
|
||||
double pixelY = (ytile - tileY) * 256.0;
|
||||
|
||||
return new double[] { pixelX, pixelY };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user