mirror of
https://gitee.com/pan648540858/wvp-GB28181-pro.git
synced 2026-05-23 21:47:49 +08:00
完善地图的抽稀展示、执行和保存
This commit is contained in:
parent
984d2d56ee
commit
5d471ded1a
@ -0,0 +1,33 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class VectorTileSource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 抽稀的图层数据
|
||||||
|
*/
|
||||||
|
private Map<String, byte[]> vectorTileMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 抽稀的原始数据
|
||||||
|
*/
|
||||||
|
private List<CommonGBChannel> channelList = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间, 大于6小时后删除
|
||||||
|
*/
|
||||||
|
private long time;
|
||||||
|
|
||||||
|
public VectorTileSource() {
|
||||||
|
this.time = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,9 +8,9 @@ import com.genersoft.iot.vmp.gb28181.bean.*;
|
|||||||
import com.genersoft.iot.vmp.gb28181.controller.bean.*;
|
import com.genersoft.iot.vmp.gb28181.controller.bean.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IGbChannelPlayService;
|
import com.genersoft.iot.vmp.gb28181.service.IGbChannelPlayService;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
|
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.VectorTileUtils;
|
||||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||||
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
|
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
|
||||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||||
import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
|
import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
|
||||||
@ -23,6 +23,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
@ -45,7 +46,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
public class ChannelController {
|
public class ChannelController {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
private RedisTemplate<Object, Object> redisTemplate;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IGbChannelService channelService;
|
private IGbChannelService channelService;
|
||||||
@ -490,12 +491,6 @@ public class ChannelController {
|
|||||||
return channelService.queryListForMap(query, online, hasRecordPlan, channelType);
|
return channelService.queryListForMap(query, online, hasRecordPlan, channelType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "为地图保存抽稀结果", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
|
||||||
@PostMapping("/map/save-level")
|
|
||||||
public void saveLevel(@RequestBody List<ChannelForThin> channels){
|
|
||||||
channelService.saveLevel(channels);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "为地图去除抽稀结果", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
@Operation(summary = "为地图去除抽稀结果", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
@PostMapping("/map/reset-level")
|
@PostMapping("/map/reset-level")
|
||||||
public void resetLevel(){
|
public void resetLevel(){
|
||||||
@ -515,14 +510,14 @@ public class ChannelController {
|
|||||||
@Parameter(name = "id", description = "抽稀ID", required = true)
|
@Parameter(name = "id", description = "抽稀ID", required = true)
|
||||||
@GetMapping("/map/thin/clear")
|
@GetMapping("/map/thin/clear")
|
||||||
public void clearThin(String id){
|
public void clearThin(String id){
|
||||||
|
VectorTileUtils.INSTANCE.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "保存的抽稀结果", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
@Operation(summary = "保存的抽稀结果", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
@Parameter(name = "id", description = "抽稀ID", required = true)
|
@Parameter(name = "id", description = "抽稀ID", required = true)
|
||||||
@GetMapping("/map/thin/save")
|
@GetMapping("/map/thin/save")
|
||||||
public void saveThin(String id){
|
public void saveThin(String id){
|
||||||
|
channelService.saveThin(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "获取抽稀执行的进度", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
@Operation(summary = "获取抽稀执行的进度", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
@ -541,6 +536,10 @@ public class ChannelController {
|
|||||||
byte[] mvt = channelService.getTile(z, x, y, geoCoordSys);
|
byte[] mvt = channelService.getTile(z, x, y, geoCoordSys);
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.setContentType(MediaType.parseMediaType("application/x-protobuf"));
|
headers.setContentType(MediaType.parseMediaType("application/x-protobuf"));
|
||||||
|
if (mvt == null) {
|
||||||
|
headers.setContentLength(0);
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
|
||||||
|
}
|
||||||
headers.setContentLength(mvt.length);
|
headers.setContentLength(mvt.length);
|
||||||
return new ResponseEntity<>(mvt, headers, HttpStatus.OK);
|
return new ResponseEntity<>(mvt, headers, HttpStatus.OK);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -556,16 +555,20 @@ public class ChannelController {
|
|||||||
public ResponseEntity<byte[]> getThinTile(@PathVariable int z, @PathVariable int x, @PathVariable int y,
|
public ResponseEntity<byte[]> getThinTile(@PathVariable int z, @PathVariable int x, @PathVariable int y,
|
||||||
String geoCoordSys, @RequestParam(required = false) String thinId){
|
String geoCoordSys, @RequestParam(required = false) String thinId){
|
||||||
|
|
||||||
try {
|
if (ObjectUtils.isEmpty(thinId)) {
|
||||||
byte[] mvt = channelService.getTile(z, x, y, geoCoordSys);
|
thinId = "DEFAULT";
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
String catchKey = z + "_" + x + "_" + y + "_" + geoCoordSys.toUpperCase();
|
||||||
|
byte[] mvt = VectorTileUtils.INSTANCE.getVectorTile(thinId, catchKey);
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.parseMediaType("application/x-protobuf"));
|
||||||
|
if (mvt == null) {
|
||||||
|
headers.setContentLength(0);
|
||||||
|
return ResponseEntity.status(HttpStatus.OK).body(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
headers.setContentLength(mvt.length);
|
||||||
|
return new ResponseEntity<>(mvt, headers, HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -341,9 +341,13 @@ public class DeviceQuery {
|
|||||||
}else if (channelSyncStatus.getErrorMsg() != null) {
|
}else if (channelSyncStatus.getErrorMsg() != null) {
|
||||||
wvpResult.setCode(ErrorCode.ERROR100.getCode());
|
wvpResult.setCode(ErrorCode.ERROR100.getCode());
|
||||||
wvpResult.setMsg(channelSyncStatus.getErrorMsg());
|
wvpResult.setMsg(channelSyncStatus.getErrorMsg());
|
||||||
}else if (channelSyncStatus.getTotal() == null || channelSyncStatus.getTotal() == 0){
|
}else if (channelSyncStatus.getTotal() == null){
|
||||||
wvpResult.setCode(ErrorCode.SUCCESS.getCode());
|
wvpResult.setCode(ErrorCode.SUCCESS.getCode());
|
||||||
wvpResult.setMsg("等待通道信息...");
|
wvpResult.setMsg("等待通道信息...");
|
||||||
|
}else if (channelSyncStatus.getTotal() == 0){
|
||||||
|
wvpResult.setCode(ErrorCode.SUCCESS.getCode());
|
||||||
|
wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
|
||||||
|
wvpResult.setData(channelSyncStatus);
|
||||||
}else {
|
}else {
|
||||||
wvpResult.setCode(ErrorCode.SUCCESS.getCode());
|
wvpResult.setCode(ErrorCode.SUCCESS.getCode());
|
||||||
wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
|
wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
|
||||||
|
|||||||
@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.gb28181.dao;
|
|||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.controller.bean.Extent;
|
import com.genersoft.iot.vmp.gb28181.controller.bean.Extent;
|
||||||
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelForThin;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.dao.provider.ChannelProvider;
|
import com.genersoft.iot.vmp.gb28181.dao.provider.ChannelProvider;
|
||||||
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
||||||
import com.genersoft.iot.vmp.streamPush.bean.StreamPush;
|
import com.genersoft.iot.vmp.streamPush.bean.StreamPush;
|
||||||
@ -660,7 +659,7 @@ public interface CommonGBChannelMapper {
|
|||||||
"WHERE id = #{item.gbId}" +
|
"WHERE id = #{item.gbId}" +
|
||||||
"</foreach> " +
|
"</foreach> " +
|
||||||
"</script>")
|
"</script>")
|
||||||
void saveLevel(List<ChannelForThin> channels);
|
void saveLevel(List<CommonGBChannel> channels);
|
||||||
|
|
||||||
@SelectProvider(type = ChannelProvider.class, method = "queryCameraChannelByIds")
|
@SelectProvider(type = ChannelProvider.class, method = "queryCameraChannelByIds")
|
||||||
List<CameraChannel> queryCameraChannelByIds(List<CommonGBChannel> channelList);
|
List<CameraChannel> queryCameraChannelByIds(List<CommonGBChannel> channelList);
|
||||||
@ -691,6 +690,11 @@ public interface CommonGBChannelMapper {
|
|||||||
List<CommonGBChannel> queryAllWithPosition();
|
List<CommonGBChannel> queryAllWithPosition();
|
||||||
|
|
||||||
@SelectProvider(type = ChannelProvider.class, method = "queryListInExtent")
|
@SelectProvider(type = ChannelProvider.class, method = "queryListInExtent")
|
||||||
List<CommonGBChannel> queryListInExtent(Extent extent);
|
List<CommonGBChannel> queryListInExtent(@Param("minLng") double minLng, @Param("maxLng") double maxLng,
|
||||||
|
@Param("minLat") double minLat, @Param("maxLat") double maxLat);
|
||||||
|
|
||||||
|
@SelectProvider(type = ChannelProvider.class, method = "queryListOutExtent")
|
||||||
|
List<CommonGBChannel> queryListOutExtent(@Param("minLng") double minLng, @Param("maxLng") double maxLng,
|
||||||
|
@Param("minLat") double minLat, @Param("maxLat") double maxLat);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -919,4 +919,16 @@ public class ChannelProvider {
|
|||||||
return sqlBuild.toString();
|
return sqlBuild.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String queryListOutExtent(Map<String, Object> params ){
|
||||||
|
StringBuilder sqlBuild = new StringBuilder();
|
||||||
|
sqlBuild.append(BASE_SQL);
|
||||||
|
sqlBuild.append(" where channel_type = 0 AND ( " +
|
||||||
|
"coalesce(gb_longitude, longitude) <= #{minLng} " +
|
||||||
|
"or coalesce(gb_longitude, longitude) > #{maxLng} " +
|
||||||
|
"or coalesce(gb_latitude, latitude) <= #{minLat} " +
|
||||||
|
"or coalesce(gb_latitude, latitude) > #{maxLat}" +
|
||||||
|
")");
|
||||||
|
return sqlBuild.toString();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.gb28181.service;
|
|||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.controller.bean.Extent;
|
import com.genersoft.iot.vmp.gb28181.controller.bean.Extent;
|
||||||
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelForThin;
|
|
||||||
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
||||||
import com.genersoft.iot.vmp.streamPush.bean.StreamPush;
|
import com.genersoft.iot.vmp.streamPush.bean.StreamPush;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
@ -103,8 +102,6 @@ public interface IGbChannelService {
|
|||||||
|
|
||||||
List<CommonGBChannel> queryListForMap(String query, Boolean online, Boolean hasRecordPlan, Integer channelType);
|
List<CommonGBChannel> queryListForMap(String query, Boolean online, Boolean hasRecordPlan, Integer channelType);
|
||||||
|
|
||||||
void saveLevel(List<ChannelForThin> channels);
|
|
||||||
|
|
||||||
CommonGBChannel queryCommonChannelByDeviceChannel(DeviceChannel channel);
|
CommonGBChannel queryCommonChannelByDeviceChannel(DeviceChannel channel);
|
||||||
|
|
||||||
void resetLevel();
|
void resetLevel();
|
||||||
@ -114,4 +111,6 @@ public interface IGbChannelService {
|
|||||||
String drawThin(Map<Integer, Double> zoomParam, Extent extent, String geoCoordSys);
|
String drawThin(Map<Integer, Double> zoomParam, Extent extent, String geoCoordSys);
|
||||||
|
|
||||||
DrawThinProcess thinProgress(String id);
|
DrawThinProcess thinProgress(String id);
|
||||||
|
|
||||||
|
void saveThin(String id);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,6 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
|
|||||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.controller.bean.Extent;
|
import com.genersoft.iot.vmp.gb28181.controller.bean.Extent;
|
||||||
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelForThin;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.dao.CommonGBChannelMapper;
|
import com.genersoft.iot.vmp.gb28181.dao.CommonGBChannelMapper;
|
||||||
import com.genersoft.iot.vmp.gb28181.dao.GroupMapper;
|
import com.genersoft.iot.vmp.gb28181.dao.GroupMapper;
|
||||||
import com.genersoft.iot.vmp.gb28181.dao.PlatformChannelMapper;
|
import com.genersoft.iot.vmp.gb28181.dao.PlatformChannelMapper;
|
||||||
@ -867,23 +866,6 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
|||||||
return commonGBChannelMapper.queryList(query, online, hasRecordPlan, channelType, null, null);
|
return commonGBChannelMapper.queryList(query, online, hasRecordPlan, channelType, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public void saveLevel(List<ChannelForThin> channels) {
|
|
||||||
int limitCount = 1000;
|
|
||||||
if (channels.size() > limitCount) {
|
|
||||||
for (int i = 0; i < channels.size(); i += limitCount) {
|
|
||||||
int toIndex = i + limitCount;
|
|
||||||
if (i + limitCount > channels.size()) {
|
|
||||||
toIndex = channels.size();
|
|
||||||
}
|
|
||||||
commonGBChannelMapper.saveLevel(channels.subList(i, toIndex));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
commonGBChannelMapper.saveLevel(channels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommonGBChannel queryCommonChannelByDeviceChannel(DeviceChannel channel) {
|
public CommonGBChannel queryCommonChannelByDeviceChannel(DeviceChannel channel) {
|
||||||
return commonGBChannelMapper.queryCommonChannelByDeviceChannel(channel);
|
return commonGBChannelMapper.queryCommonChannelByDeviceChannel(channel);
|
||||||
@ -896,10 +878,10 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] getTile(int z, int x, int y, String geoCoordSys) {
|
public byte[] getTile(int z, int x, int y, String geoCoordSys) {
|
||||||
double minLon = tile2lon(x, z);
|
double minLon = TileUtils.tile2lon(x, z);
|
||||||
double maxLon = tile2lon(x + 1, z);
|
double maxLon = TileUtils.tile2lon(x + 1, z);
|
||||||
double maxLat = tile2lat(y, z);
|
double maxLat = TileUtils.tile2lat(y, z);
|
||||||
double minLat = tile2lat(y + 1, z);
|
double minLat = TileUtils.tile2lat(y + 1, z);
|
||||||
|
|
||||||
if (geoCoordSys != null) {
|
if (geoCoordSys != null) {
|
||||||
if (geoCoordSys.equalsIgnoreCase("GCJ02")) {
|
if (geoCoordSys.equalsIgnoreCase("GCJ02")) {
|
||||||
@ -929,7 +911,7 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 将 lon/lat 转为瓦片内像素坐标(0..256)
|
// 将 lon/lat 转为瓦片内像素坐标(0..256)
|
||||||
double[] px = lonLatToTilePixel(lon, lat, z, x, y);
|
double[] px = TileUtils.lonLatToTilePixel(lon, lat, z, x, y);
|
||||||
Point pointGeom = geometryFactory.createPoint(new Coordinate(px[0], px[1]));
|
Point pointGeom = geometryFactory.createPoint(new Coordinate(px[0], px[1]));
|
||||||
|
|
||||||
BeanMap beanMap = BeanMapUtils.create(commonGBChannel);
|
BeanMap beanMap = BeanMapUtils.create(commonGBChannel);
|
||||||
@ -939,53 +921,20 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
|||||||
return encoder.encode();
|
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 };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String drawThin(Map<Integer, Double> zoomParam, Extent extent, String geoCoordSys) {
|
public String drawThin(Map<Integer, Double> zoomParam, Extent extent, String geoCoordSys) {
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
|
|
||||||
String id = UUID.randomUUID().toString();
|
String id = UUID.randomUUID().toString();
|
||||||
List<CommonGBChannel> channelList;
|
List<CommonGBChannel> channelListInExtent;
|
||||||
if (extent == null) {
|
if (extent == null) {
|
||||||
log.info("[抽稀] ID: {}, 未设置范围,从数据库读取摄像头的范围", id);
|
log.info("[抽稀] ID: {}, 未设置范围,从数据库读取摄像头的范围", id);
|
||||||
extent = commonGBChannelMapper.queryExtent();
|
extent = commonGBChannelMapper.queryExtent();
|
||||||
channelList = commonGBChannelMapper.queryAllWithPosition();
|
channelListInExtent = commonGBChannelMapper.queryAllWithPosition();
|
||||||
|
|
||||||
}else {
|
}else {
|
||||||
if (geoCoordSys != null && geoCoordSys.equalsIgnoreCase("GCJ02")) {
|
if (geoCoordSys != null && geoCoordSys.equalsIgnoreCase("GCJ02")) {
|
||||||
Double[] maxPosition = Coordtransform.GCJ02ToWGS84(extent.getMaxLng(), extent.getMaxLng());
|
Double[] maxPosition = Coordtransform.GCJ02ToWGS84(extent.getMaxLng(), extent.getMaxLat());
|
||||||
Double[] minPosition = Coordtransform.GCJ02ToWGS84(extent.getMinLng(), extent.getMinLat());
|
Double[] minPosition = Coordtransform.GCJ02ToWGS84(extent.getMinLng(), extent.getMinLat());
|
||||||
|
|
||||||
extent.setMaxLng(maxPosition[0]);
|
extent.setMaxLng(maxPosition[0]);
|
||||||
@ -995,9 +944,9 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
|||||||
extent.setMinLat(minPosition[1]);
|
extent.setMinLat(minPosition[1]);
|
||||||
}
|
}
|
||||||
// 获取数据源
|
// 获取数据源
|
||||||
channelList = commonGBChannelMapper.queryListInExtent(extent);
|
channelListInExtent = commonGBChannelMapper.queryListInExtent(extent.getMinLng(), extent.getMaxLng(), extent.getMinLat(), extent.getMaxLat());
|
||||||
}
|
}
|
||||||
Assert.isTrue(!channelList.isEmpty(), "通道数据为空");
|
Assert.isTrue(!channelListInExtent.isEmpty(), "通道数据为空");
|
||||||
|
|
||||||
log.info("[开始抽稀] ID: {}, 范围,[{}, {}, {}, {}]", id, extent.getMinLng(), extent.getMinLat(), extent.getMaxLng(), extent.getMaxLat());
|
log.info("[开始抽稀] ID: {}, 范围,[{}, {}, {}, {}]", id, extent.getMinLng(), extent.getMinLat(), extent.getMaxLng(), extent.getMaxLat());
|
||||||
|
|
||||||
@ -1013,62 +962,82 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
|||||||
Map<Integer, CommonGBChannel> useCameraMap = new HashMap<>();
|
Map<Integer, CommonGBChannel> useCameraMap = new HashMap<>();
|
||||||
AtomicReference<Double> process = new AtomicReference<>((double) 0);
|
AtomicReference<Double> process = new AtomicReference<>((double) 0);
|
||||||
for (Integer zoom : zoomParam.keySet()) {
|
for (Integer zoom : zoomParam.keySet()) {
|
||||||
Double diff = zoomParam.get(zoom);
|
|
||||||
// 对这个层级展开抽稀
|
|
||||||
log.info("[抽稀] ID:{},当前层级: {}, 坐标间隔: {}", id, zoom, diff);
|
|
||||||
Map<String, CommonGBChannel> useCameraMapForZoom = new HashMap<>();
|
Map<String, CommonGBChannel> useCameraMapForZoom = new HashMap<>();
|
||||||
Map<String, CommonGBChannel> cameraMapForZoom = new HashMap<>();
|
Map<String, CommonGBChannel> cameraMapForZoom = new HashMap<>();
|
||||||
// 更新上级图层的数据到当前层级,确保当前层级展示时考虑到之前层级的数据
|
|
||||||
for (CommonGBChannel channel : useCameraMap.values()) {
|
if (Objects.equals(zoom, Collections.max(zoomParam.keySet()))) {
|
||||||
int lngGrid = (int)(channel.getGbLongitude() / diff);
|
// 最大层级不进行抽稀, 将未进行抽稀的数据直接存储到这个层级
|
||||||
int latGrid = (int)(channel.getGbLatitude() / diff);
|
for (CommonGBChannel channel : channelListInExtent) {
|
||||||
String gridKey = latGrid + ":" + lngGrid;
|
if (!useCameraMap.containsKey(channel.getGbId())) {
|
||||||
useCameraMapForZoom.put(gridKey, channel);
|
// 这个的key跟后面的不一致是因为无需抽稀, 直接存储原始数据
|
||||||
}
|
cameraMapForZoom.put(channel.getGbId() + "", channel);
|
||||||
// 对数据开始执行抽稀
|
}
|
||||||
for (CommonGBChannel channel : channelList) {
|
|
||||||
if (useCameraMap.containsKey(channel.getGbId())) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
int lngGrid = (int)(channel.getGbLongitude() / diff);
|
}else {
|
||||||
int latGrid = (int)(channel.getGbLatitude() / diff);
|
Double diff = zoomParam.get(zoom);
|
||||||
// 数据网格Id
|
// 对这个层级展开抽稀
|
||||||
String gridKey = latGrid + ":" + lngGrid;
|
log.info("[抽稀] ID:{},当前层级: {}, 坐标间隔: {}", id, zoom, diff);
|
||||||
if (useCameraMapForZoom.containsKey(gridKey)) {
|
|
||||||
continue;
|
// 更新上级图层的数据到当前层级,确保当前层级展示时考虑到之前层级的数据
|
||||||
|
for (CommonGBChannel channel : useCameraMap.values()) {
|
||||||
|
int lngGrid = (int)(channel.getGbLongitude() / diff);
|
||||||
|
int latGrid = (int)(channel.getGbLatitude() / diff);
|
||||||
|
String gridKey = latGrid + ":" + lngGrid;
|
||||||
|
useCameraMapForZoom.put(gridKey, channel);
|
||||||
}
|
}
|
||||||
if (cameraMapForZoom.containsKey(gridKey)) {
|
|
||||||
CommonGBChannel oldChannel = cameraMapForZoom.get(gridKey);
|
// 对数据开始执行抽稀
|
||||||
// 如果一个网格存在多个数据,则选择最接近中心点的, 目前只选择了经度方向作为参考
|
for (CommonGBChannel channel : channelListInExtent) {
|
||||||
if (channel.getGbLongitude() % diff < oldChannel.getGbLongitude() % diff) {
|
// 已经分配再其他层级的,本层级不再使用
|
||||||
|
if (useCameraMap.containsKey(channel.getGbId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int lngGrid = (int)(channel.getGbLongitude() / diff);
|
||||||
|
int latGrid = (int)(channel.getGbLatitude() / diff);
|
||||||
|
// 数据网格Id
|
||||||
|
String gridKey = latGrid + ":" + lngGrid;
|
||||||
|
if (useCameraMapForZoom.containsKey(gridKey)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cameraMapForZoom.containsKey(gridKey)) {
|
||||||
|
CommonGBChannel oldChannel = cameraMapForZoom.get(gridKey);
|
||||||
|
// 如果一个网格存在多个数据,则选择最接近中心点的, 目前只选择了经度方向作为参考
|
||||||
|
if (channel.getGbLongitude() % diff < oldChannel.getGbLongitude() % diff) {
|
||||||
|
channel.setMapLevel(zoom);
|
||||||
|
cameraMapForZoom.put(gridKey, channel);
|
||||||
|
useCameraMap.put(channel.getGbId(), channel);
|
||||||
|
useCameraMap.remove(oldChannel.getGbId());
|
||||||
|
oldChannel.setMapLevel(null);
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
channel.setMapLevel(zoom);
|
||||||
cameraMapForZoom.put(gridKey, channel);
|
cameraMapForZoom.put(gridKey, channel);
|
||||||
useCameraMap.put(channel.getGbId(), channel);
|
useCameraMap.put(channel.getGbId(), channel);
|
||||||
useCameraMap.remove(oldChannel.getGbId());
|
|
||||||
}
|
}
|
||||||
}else {
|
|
||||||
cameraMapForZoom.put(gridKey, channel);
|
|
||||||
useCameraMap.put(channel.getGbId(), channel);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 存储
|
// 存储
|
||||||
zoomCameraMap.put(zoom, cameraMapForZoom.values());
|
zoomCameraMap.put(zoom, cameraMapForZoom.values());
|
||||||
process.updateAndGet(v -> (v + 0.5 / zoomParam.size()));
|
process.updateAndGet(v -> (v + 0.5 / zoomParam.size()));
|
||||||
saveProcess(id, process.get(), "抽稀图层: " + zoom);
|
saveProcess(id, process.get(), "抽稀图层: " + zoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 抽稀完成, 对数据生成mvt矢量瓦片
|
// 抽稀完成, 对数据生成mvt矢量瓦片
|
||||||
zoomCameraMap.forEach((key, value) -> {
|
List<CommonGBChannel> beforeData = new ArrayList<>();
|
||||||
|
for (Integer key : zoomCameraMap.keySet()) {
|
||||||
|
beforeData.addAll(zoomCameraMap.get(key));
|
||||||
log.info("[抽稀-生成mvt矢量瓦片] ID:{},当前层级: {}", id, key);
|
log.info("[抽稀-生成mvt矢量瓦片] ID:{},当前层级: {}", id, key);
|
||||||
// 按照 z/x/y 数据组织数据, 矢量数据暂时保存在内存中
|
// 按照 z/x/y 数据组织数据, 矢量数据暂时保存在内存中
|
||||||
// 按照范围生成 x y范围,
|
// 按照范围生成 x y范围,
|
||||||
List<TileUtils.TileCoord> tileCoords = TileUtils.tilesForBoxAtZoom(finalExtent, key);
|
saveTile(id, key, "WGS84", beforeData);
|
||||||
for (TileUtils.TileCoord tileCoord : tileCoords) {
|
saveTile(id, key, "GCJ02", beforeData);
|
||||||
saveTile(id, tileCoord.z, tileCoord.x, tileCoord.y, "WGS84", value);
|
process.updateAndGet(v -> (v + 0.5 / zoomParam.size()));
|
||||||
saveTile(id, tileCoord.z, tileCoord.x, tileCoord.y, "GCJ02", value);
|
saveProcess(id, process.get(), "生成mvt矢量瓦片: " + key);
|
||||||
process.updateAndGet(v -> (v + 0.5 / zoomParam.size() / tileCoords.size()));
|
}
|
||||||
saveProcess(id, process.get(), "发布矢量瓦片: " + key);
|
// 记录原始数据,未保存做准备
|
||||||
}
|
VectorTileUtils.INSTANCE.addSource(id, new ArrayList<>(useCameraMap.values()));
|
||||||
});
|
|
||||||
log.info("[抽稀完成] ID:{}, 耗时: {}ms", id, (System.currentTimeMillis() - time));
|
log.info("[抽稀完成] ID:{}, 耗时: {}ms", id, (System.currentTimeMillis() - time));
|
||||||
saveProcess(id, 1, "抽稀完成");
|
saveProcess(id, 1, "抽稀完成");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -1080,8 +1049,8 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveTile(String id, int z, int x, int y, String geoCoordSys, Collection<CommonGBChannel> commonGBChannelList ) {
|
private void saveTile(String id, int z, String geoCoordSys, Collection<CommonGBChannel> commonGBChannelList ) {
|
||||||
VectorTileEncoder encoder = new VectorTileEncoder();
|
Map<String, VectorTileEncoder> encoderMap = new HashMap<>();
|
||||||
commonGBChannelList.forEach(commonGBChannel -> {
|
commonGBChannelList.forEach(commonGBChannel -> {
|
||||||
double lon = commonGBChannel.getGbLongitude();
|
double lon = commonGBChannel.getGbLongitude();
|
||||||
double lat = commonGBChannel.getGbLatitude();
|
double lat = commonGBChannel.getGbLatitude();
|
||||||
@ -1090,18 +1059,24 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
|||||||
lon = minPosition[0];
|
lon = minPosition[0];
|
||||||
lat = minPosition[1];
|
lat = minPosition[1];
|
||||||
}
|
}
|
||||||
|
double[] doubles = TileUtils.lonLatToTileXY(lon, lat, z);
|
||||||
|
int x = (int) doubles[0];
|
||||||
|
int y = (int) doubles[1];
|
||||||
|
String key = z + "_" + x + "_" + y + "_" + geoCoordSys;
|
||||||
|
VectorTileEncoder encoder =encoderMap.get(key);
|
||||||
|
if (encoder == null) {
|
||||||
|
encoder = new VectorTileEncoder();
|
||||||
|
encoderMap.put(key, encoder);
|
||||||
|
}
|
||||||
// 将 lon/lat 转为瓦片内像素坐标(0..256)
|
// 将 lon/lat 转为瓦片内像素坐标(0..256)
|
||||||
double[] px = lonLatToTilePixel(lon, lat, z, x, y);
|
double[] px = TileUtils.lonLatToTilePixel(lon, lat, z, x, y);
|
||||||
Point pointGeom = geometryFactory.createPoint(new Coordinate(px[0], px[1]));
|
Point pointGeom = geometryFactory.createPoint(new Coordinate(px[0], px[1]));
|
||||||
|
|
||||||
BeanMap beanMap = BeanMapUtils.create(commonGBChannel);
|
BeanMap beanMap = BeanMapUtils.create(commonGBChannel);
|
||||||
encoder.addFeature("points", beanMap, pointGeom);
|
encoder.addFeature("points", beanMap, pointGeom);
|
||||||
});
|
});
|
||||||
|
encoderMap.forEach((key, encoder) -> {
|
||||||
byte[] encode = encoder.encode();
|
VectorTileUtils.INSTANCE.addVectorTile(id, key, encoder.encode());
|
||||||
String catchKey = id + "_" + z + "_" + x + "_" + y + "_" + geoCoordSys;
|
});
|
||||||
VectorTileUtils.INSTANCE.addVectorTile(catchKey, encode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveProcess(String id, double process, String msg) {
|
private void saveProcess(String id, double process, String msg) {
|
||||||
@ -1115,4 +1090,26 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
|||||||
String key = VideoManagerConstants.DRAW_THIN_PROCESS_PREFIX + id;
|
String key = VideoManagerConstants.DRAW_THIN_PROCESS_PREFIX + id;
|
||||||
return (DrawThinProcess) redisTemplate.opsForValue().get(key);
|
return (DrawThinProcess) redisTemplate.opsForValue().get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void saveThin(String id) {
|
||||||
|
commonGBChannelMapper.resetLevel();
|
||||||
|
VectorTileUtils.INSTANCE.save(id);
|
||||||
|
List<CommonGBChannel> channelList = VectorTileUtils.INSTANCE.getChannelList(id);
|
||||||
|
if (channelList != null && !channelList.isEmpty()) {
|
||||||
|
int limitCount = 1000;
|
||||||
|
if (channelList.size() > limitCount) {
|
||||||
|
for (int i = 0; i < channelList.size(); i += limitCount) {
|
||||||
|
int toIndex = i + limitCount;
|
||||||
|
if (i + limitCount > channelList.size()) {
|
||||||
|
toIndex = channelList.size();
|
||||||
|
}
|
||||||
|
commonGBChannelMapper.saveLevel(channelList.subList(i, toIndex));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
commonGBChannelMapper.saveLevel(channelList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,6 +42,7 @@ import javax.sip.header.WWWAuthenticateHeader;
|
|||||||
import javax.sip.message.Request;
|
import javax.sip.message.Request;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -218,16 +219,18 @@ public class SIPCommanderForPlatform implements ISIPCommanderForPlatform {
|
|||||||
if (index > channels.size()) {
|
if (index > channels.size()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
List<CommonGBChannel> deviceChannels;
|
String catalogXml;
|
||||||
if (index + parentPlatform.getCatalogGroup() < channels.size()) {
|
if (channels.isEmpty()) {
|
||||||
deviceChannels = channels.subList(index, index + parentPlatform.getCatalogGroup());
|
catalogXml = getCatalogXml(Collections.emptyList(), sn, parentPlatform, 0);
|
||||||
}else {
|
}else {
|
||||||
deviceChannels = channels.subList(index, channels.size());
|
List<CommonGBChannel> subChannelList;
|
||||||
|
if (index + parentPlatform.getCatalogGroup() < channels.size()) {
|
||||||
|
subChannelList = channels.subList(index, index + parentPlatform.getCatalogGroup());
|
||||||
|
}else {
|
||||||
|
subChannelList = channels.subList(index, channels.size());
|
||||||
|
}
|
||||||
|
catalogXml = getCatalogXml(subChannelList, sn, parentPlatform, channels.size());
|
||||||
}
|
}
|
||||||
if(deviceChannels.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String catalogXml = getCatalogXml(deviceChannels, sn, parentPlatform, channels.size());
|
|
||||||
// callid
|
// callid
|
||||||
CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());
|
CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import javax.sip.SipException;
|
|||||||
import javax.sip.header.FromHeader;
|
import javax.sip.header.FromHeader;
|
||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -75,7 +76,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
|
|||||||
cmderFroPlatform.catalogQuery(channelList, platform, sn, fromHeader.getTag());
|
cmderFroPlatform.catalogQuery(channelList, platform, sn, fromHeader.getTag());
|
||||||
}else {
|
}else {
|
||||||
// 回复无通道
|
// 回复无通道
|
||||||
cmderFroPlatform.catalogQuery(null, platform, sn, fromHeader.getTag(), 0);
|
cmderFroPlatform.catalogQuery(Collections.emptyList(), platform, sn, fromHeader.getTag());
|
||||||
}
|
}
|
||||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||||
log.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
|
log.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import javax.sip.SipException;
|
|||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
@ -114,13 +115,19 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
|
|||||||
Element deviceListElement = rootElement.element("DeviceList");
|
Element deviceListElement = rootElement.element("DeviceList");
|
||||||
Element sumNumElement = rootElement.element("SumNum");
|
Element sumNumElement = rootElement.element("SumNum");
|
||||||
Element snElement = rootElement.element("SN");
|
Element snElement = rootElement.element("SN");
|
||||||
|
|
||||||
|
sn = Integer.parseInt(snElement.getText());
|
||||||
int sumNum = Integer.parseInt(sumNumElement.getText());
|
int sumNum = Integer.parseInt(sumNumElement.getText());
|
||||||
|
|
||||||
if (sumNum == 0) {
|
if (sumNum == 0) {
|
||||||
log.info("[收到通道]设备:{}的: 0个", take.getDevice().getDeviceId());
|
log.info("[收到通道]设备:{}的: 0个", take.getDevice().getDeviceId());
|
||||||
// 数据已经完整接收
|
// 数据已经完整接收
|
||||||
deviceChannelService.cleanChannelsForDevice(take.getDevice().getId());
|
deviceChannelService.cleanChannelsForDevice(take.getDevice().getId());
|
||||||
|
// 推送空数据,不然无法及时结束
|
||||||
|
catalogDataCatch.put(take.getDevice().getDeviceId(), sn, 0, take.getDevice(),
|
||||||
|
Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
|
||||||
catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), sn, null);
|
catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), sn, null);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
|
Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
|
||||||
if (deviceListIterator != null) {
|
if (deviceListIterator != null) {
|
||||||
@ -167,7 +174,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
|
|||||||
}
|
}
|
||||||
channelList.add(channel);
|
channelList.add(channel);
|
||||||
}
|
}
|
||||||
sn = Integer.parseInt(snElement.getText());
|
|
||||||
catalogDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, take.getDevice(),
|
catalogDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, take.getDevice(),
|
||||||
channelList, regionList, groupList);
|
channelList, regionList, groupList);
|
||||||
log.info("[收到通道]设备: {} -> {}个,{}/{}", take.getDevice().getDeviceId(), channelList.size(), catalogDataCatch.size(take.getDevice().getDeviceId(), sn), sumNum);
|
log.info("[收到通道]设备: {} -> {}个,{}/{}", take.getDevice().getDeviceId(), channelList.size(), catalogDataCatch.size(take.getDevice().getDeviceId(), sn), sumNum);
|
||||||
@ -177,15 +184,17 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
|
|||||||
log.warn("[收到通道] 发现未处理的异常, \r\n{}", evt.getRequest());
|
log.warn("[收到通道] 发现未处理的异常, \r\n{}", evt.getRequest());
|
||||||
log.error("[收到通道] 异常内容: ", e);
|
log.error("[收到通道] 异常内容: ", e);
|
||||||
} finally {
|
} finally {
|
||||||
if (catalogDataCatch.size(take.getDevice().getDeviceId(), sn) == catalogDataCatch.sumNum(take.getDevice().getDeviceId(), sn)) {
|
String deviceId = take.getDevice().getDeviceId();
|
||||||
|
if (catalogDataCatch.size(deviceId, sn) > 0
|
||||||
|
&& catalogDataCatch.size(deviceId, sn) == catalogDataCatch.sumNum(deviceId, sn)) {
|
||||||
// 数据已经完整接收, 此时可能存在某个设备离线变上线的情况,但是考虑到性能,此处不做处理,
|
// 数据已经完整接收, 此时可能存在某个设备离线变上线的情况,但是考虑到性能,此处不做处理,
|
||||||
// 目前支持设备通道上线通知时和设备上线时向上级通知
|
// 目前支持设备通道上线通知时和设备上线时向上级通知
|
||||||
boolean resetChannelsResult = saveData(take.getDevice(), sn);
|
boolean resetChannelsResult = saveData(take.getDevice(), sn);
|
||||||
if (!resetChannelsResult) {
|
if (!resetChannelsResult) {
|
||||||
String errorMsg = "接收成功,写入失败,共" + catalogDataCatch.sumNum(take.getDevice().getDeviceId(), sn) + "条,已接收" + catalogDataCatch.getDeviceChannelList(take.getDevice().getDeviceId(), sn).size() + "条";
|
String errorMsg = "接收成功,写入失败,共" + catalogDataCatch.sumNum(deviceId, sn) + "条,已接收" + catalogDataCatch.getDeviceChannelList(take.getDevice().getDeviceId(), sn).size() + "条";
|
||||||
catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), sn, errorMsg);
|
catalogDataCatch.setChannelSyncEnd(deviceId, sn, errorMsg);
|
||||||
} else {
|
} else {
|
||||||
catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), sn, null);
|
catalogDataCatch.setChannelSyncEnd(deviceId, sn, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -187,8 +187,16 @@ public class SipUtils {
|
|||||||
remotePort = request.getTopmostViaHeader().getRPort();
|
remotePort = request.getTopmostViaHeader().getRPort();
|
||||||
// 解析本地地址替代
|
// 解析本地地址替代
|
||||||
if (ObjectUtils.isEmpty(remoteAddress) || remotePort == -1) {
|
if (ObjectUtils.isEmpty(remoteAddress) || remotePort == -1) {
|
||||||
remoteAddress = request.getPeerPacketSourceAddress().getHostAddress();
|
if (request.getPeerPacketSourceAddress() != null) {
|
||||||
remotePort = request.getPeerPacketSourcePort();
|
remoteAddress = request.getPeerPacketSourceAddress().getHostAddress();
|
||||||
|
}else {
|
||||||
|
remoteAddress = request.getRemoteAddress().getHostAddress();
|
||||||
|
}
|
||||||
|
if( request.getPeerPacketSourcePort() > 0) {
|
||||||
|
remotePort = request.getPeerPacketSourcePort();
|
||||||
|
}else {
|
||||||
|
remotePort = request.getRemotePort();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,19 +1,66 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.utils;
|
package com.genersoft.iot.vmp.gb28181.utils;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.VectorTileSource;
|
||||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public enum VectorTileUtils {
|
public enum VectorTileUtils {
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
private Map<String, byte[]> vectorTileMap = new ConcurrentReferenceHashMap<>();
|
private Map<String, VectorTileSource> vectorTileMap = new ConcurrentReferenceHashMap<>();
|
||||||
|
|
||||||
public void addVectorTile(String key, byte[] content) {
|
public void addVectorTile(String id, String key, byte[] content) {
|
||||||
vectorTileMap.put(key, content);
|
VectorTileSource vectorTileSource = vectorTileMap.get(id);
|
||||||
|
if (vectorTileSource == null) {
|
||||||
|
vectorTileSource = new VectorTileSource();
|
||||||
|
vectorTileMap.put(id, vectorTileSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
vectorTileSource.getVectorTileMap().put(key, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getVectorTile(String key) {
|
public byte[] getVectorTile(String id, String key) {
|
||||||
return vectorTileMap.get(key);
|
if (!vectorTileMap.containsKey(id)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return vectorTileMap.get(id).getVectorTileMap().get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addSource(String id, List<CommonGBChannel> channelList) {
|
||||||
|
VectorTileSource vectorTileSource = vectorTileMap.get(id);
|
||||||
|
if (vectorTileSource == null) {
|
||||||
|
vectorTileSource = new VectorTileSource();
|
||||||
|
vectorTileMap.put(id, vectorTileSource);
|
||||||
|
}
|
||||||
|
vectorTileMap.get(id).getChannelList().addAll(channelList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void remove(String id) {
|
||||||
|
vectorTileMap.remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CommonGBChannel> getChannelList(String id) {
|
||||||
|
if (!vectorTileMap.containsKey(id)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return vectorTileMap.get(id).getChannelList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(String id) {
|
||||||
|
if (!vectorTileMap.containsKey(id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
VectorTileSource vectorTileSource = vectorTileMap.get(id);
|
||||||
|
if (vectorTileSource == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vectorTileMap.remove(id);
|
||||||
|
vectorTileMap.put("DEFAULT", vectorTileSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -113,10 +113,48 @@ public class TileUtils {
|
|||||||
|
|
||||||
public static class TileCoord {
|
public static class TileCoord {
|
||||||
public final int x, y, z;
|
public final int x, y, z;
|
||||||
public TileCoord(int x, int y, int z) { this.x = x; this.y = y; this.z = z; }
|
public TileCoord(int x, int y, int z) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "{" + "z=" + z + ", x=" + x + ", y=" + y + '}';
|
return "{" + "z=" + z + ", x=" + x + ", y=" + y + '}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tile X/Z -> longitude (deg)
|
||||||
|
*/
|
||||||
|
public static 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)
|
||||||
|
*/
|
||||||
|
public static 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)
|
||||||
|
*/
|
||||||
|
public static 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 };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -265,8 +265,12 @@ public class CameraChannelController {
|
|||||||
}
|
}
|
||||||
CameraStreamContent cameraStreamContent = new CameraStreamContent(streamInfo);
|
CameraStreamContent cameraStreamContent = new CameraStreamContent(streamInfo);
|
||||||
cameraStreamContent.setName(channel.getGbName());
|
cameraStreamContent.setName(channel.getGbName());
|
||||||
cameraStreamContent.setControlType(
|
if (channel.getGbPtzType() != null) {
|
||||||
(channel.getGbPtzType() == 1 || channel.getGbPtzType() == 4 || channel.getGbPtzType() == 5) ? 1 : 0);
|
cameraStreamContent.setControlType(
|
||||||
|
(channel.getGbPtzType() == 1 || channel.getGbPtzType() == 4 || channel.getGbPtzType() == 5) ? 1 : 0);
|
||||||
|
}else {
|
||||||
|
cameraStreamContent.setControlType(0);
|
||||||
|
}
|
||||||
|
|
||||||
wvpResult.setData(cameraStreamContent);
|
wvpResult.setData(cameraStreamContent);
|
||||||
}else {
|
}else {
|
||||||
|
|||||||
@ -96,7 +96,7 @@
|
|||||||
<span v-if="!scope.row.gbLongitude || !scope.row.gbLatitude">无</span>
|
<span v-if="!scope.row.gbLongitude || !scope.row.gbLatitude">无</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="ptzType" label="云台类型" min-width="100">
|
<el-table-column prop="ptzType" label="摄像头类型" min-width="100">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<div>{{ scope.row.ptzTypeText }}</div>
|
<div>{{ scope.row.ptzTypeText }}</div>
|
||||||
</template>
|
</template>
|
||||||
@ -222,7 +222,7 @@ export default {
|
|||||||
},
|
},
|
||||||
经度: 'gbLongitude',
|
经度: 'gbLongitude',
|
||||||
纬度: 'gbLatitude',
|
纬度: 'gbLatitude',
|
||||||
云台类型: 'ptzTypeText',
|
摄像头类型: 'ptzTypeText',
|
||||||
状态: {
|
状态: {
|
||||||
field: 'gbStatus',
|
field: 'gbStatus',
|
||||||
callback: (value) => {
|
callback: (value) => {
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import VectorTileLayer from 'ol/layer/VectorTile.js'
|
|||||||
import VectorTileSource from 'ol/source/VectorTile.js'
|
import VectorTileSource from 'ol/source/VectorTile.js'
|
||||||
import WebGLVectorLayer from 'ol/layer/WebGLVector'
|
import WebGLVectorLayer from 'ol/layer/WebGLVector'
|
||||||
import Style from 'ol/style/Style'
|
import Style from 'ol/style/Style'
|
||||||
|
import Circle from 'ol/style/Circle'
|
||||||
import Stroke from 'ol/style/Stroke'
|
import Stroke from 'ol/style/Stroke'
|
||||||
import Icon from 'ol/style/Icon'
|
import Icon from 'ol/style/Icon'
|
||||||
import View from 'ol/View'
|
import View from 'ol/View'
|
||||||
@ -159,7 +160,7 @@ export default {
|
|||||||
style: function(feature) {
|
style: function(feature) {
|
||||||
let status = feature.properties_.gbStatus
|
let status = feature.properties_.gbStatus
|
||||||
if (layer.get('hideFeatures').includes(feature.properties_.gbId)) {
|
if (layer.get('hideFeatures').includes(feature.properties_.gbId)) {
|
||||||
return new Style()
|
return
|
||||||
}
|
}
|
||||||
if (status === 'ON') {
|
if (status === 'ON') {
|
||||||
return new Style({
|
return new Style({
|
||||||
|
|||||||
@ -97,7 +97,7 @@
|
|||||||
<span v-if="!scope.row.longitude || !scope.row.latitude">无</span>
|
<span v-if="!scope.row.longitude || !scope.row.latitude">无</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="ptzType" label="云台类型" min-width="100">
|
<el-table-column prop="ptzType" label="摄像头类型" min-width="100">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<div>{{ scope.row.ptzTypeText }}</div>
|
<div>{{ scope.row.ptzTypeText }}</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
<el-descriptions-item label="设备归属" >{{channel.owner}}</el-descriptions-item>
|
<el-descriptions-item label="设备归属" >{{channel.owner}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="行政区域" >{{channel.civilCode}}</el-descriptions-item>
|
<el-descriptions-item label="行政区域" >{{channel.civilCode}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="安装地址" >{{channel.address}}</el-descriptions-item>
|
<el-descriptions-item label="安装地址" >{{channel.address}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="云台类型" >{{channel.ptzTypeText}}</el-descriptions-item>
|
<el-descriptions-item label="摄像头类型" >{{channel.ptzTypeText}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="经纬度" >{{channel.longitude}},{{channel.latitude}}</el-descriptions-item>
|
<el-descriptions-item label="经纬度" >{{channel.longitude}},{{channel.latitude}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="状态">
|
<el-descriptions-item label="状态">
|
||||||
<el-tag size="small" v-if="channel.status === 1">在线</el-tag>
|
<el-tag size="small" v-if="channel.status === 1">在线</el-tag>
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
<el-table-column prop="parentName" label="设备名称" min-width="180"/>
|
<el-table-column prop="parentName" label="设备名称" min-width="180"/>
|
||||||
<el-table-column prop="deviceId" label="通道编号" min-width="180"/>
|
<el-table-column prop="deviceId" label="通道编号" min-width="180"/>
|
||||||
<el-table-column prop="name" label="通道名称" min-width="180"/>
|
<el-table-column prop="name" label="通道名称" min-width="180"/>
|
||||||
<el-table-column prop="ptzType" label="云台类型" min-width="100">
|
<el-table-column prop="ptzType" label="摄像头类型" min-width="100">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<div>{{ scope.row.ptzTypeText }}</div>
|
<div>{{ scope.row.ptzTypeText }}</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
style="text-align: center"
|
style="text-align: center"
|
||||||
@close="close()"
|
@close="close()"
|
||||||
>
|
>
|
||||||
<el-progress type="circle" :percentage="percentage" />
|
<el-progress type="circle" :percentage="percentage" :status="syncStatus"/>
|
||||||
<div style="text-align: center">
|
<div style="text-align: center">
|
||||||
{{ msg }}
|
{{ msg }}
|
||||||
</div>
|
</div>
|
||||||
@ -30,7 +30,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
endCallBack: null,
|
endCallBack: null,
|
||||||
syncStatus: null,
|
syncStatus: '',
|
||||||
percentage: 0,
|
percentage: 0,
|
||||||
showDialog: false,
|
showDialog: false,
|
||||||
isLoging: false,
|
isLoging: false,
|
||||||
@ -51,17 +51,23 @@ export default {
|
|||||||
this.msg = ''
|
this.msg = ''
|
||||||
this.percentage = 0
|
this.percentage = 0
|
||||||
this.syncFlag = false
|
this.syncFlag = false
|
||||||
this.syncStatus = null
|
this.syncStatus = ''
|
||||||
this.endCallBack = endCallBack
|
this.endCallBack = endCallBack
|
||||||
this.getProgress()
|
this.getProgress()
|
||||||
},
|
},
|
||||||
getProgress() {
|
getProgress() {
|
||||||
this.$store.dispatch('commonChanel/thinProgress', this.drawThinId)
|
this.$store.dispatch('commonChanel/thinProgress', this.drawThinId)
|
||||||
.then(({ data }) => {
|
.then((data) => {
|
||||||
|
console.log(data)
|
||||||
this.syncFlag = true
|
this.syncFlag = true
|
||||||
this.percentage = data.process * 100
|
this.percentage = data.process * 100
|
||||||
this.msg = data.msg
|
this.msg = data.msg
|
||||||
console.log('drawThinId: ' + data.drawThinId)
|
console.log('drawThinId: ' + data.drawThinId)
|
||||||
|
if (data.process >= 1) {
|
||||||
|
this.syncStatus = 'success'
|
||||||
|
this.close()
|
||||||
|
return
|
||||||
|
}
|
||||||
this.timer = setTimeout(this.getProgress, 300)
|
this.timer = setTimeout(this.getProgress, 300)
|
||||||
|
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
@ -74,10 +80,11 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
close: function() {
|
close: function() {
|
||||||
|
window.clearTimeout(this.timer)
|
||||||
|
this.showDialog = false
|
||||||
if (this.endCallBack) {
|
if (this.endCallBack) {
|
||||||
this.endCallBack()
|
this.endCallBack()
|
||||||
}
|
}
|
||||||
window.clearTimeout(this.timer)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,11 +5,6 @@
|
|||||||
<MapComponent ref="mapComponent" @loaded="initChannelLayer" @coordinateSystemChange="initChannelLayer" @zoomChange="zoomChange"></MapComponent>
|
<MapComponent ref="mapComponent" @loaded="initChannelLayer" @coordinateSystemChange="initChannelLayer" @zoomChange="zoomChange"></MapComponent>
|
||||||
</div>
|
</div>
|
||||||
<div class="map-tool-box-bottom-right">
|
<div class="map-tool-box-bottom-right">
|
||||||
<div class="map-tool-btn-group">
|
|
||||||
<div class="el-dropdown-link map-tool-btn" @click="addVectorTileLayer">
|
|
||||||
<i class="iconfont icon-mti-jutai"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="map-tool-btn-group" v-if="mapTileList.length > 0">
|
<div class="map-tool-btn-group" v-if="mapTileList.length > 0">
|
||||||
<el-dropdown placement="top" @command="changeLayerType">
|
<el-dropdown placement="top" @command="changeLayerType">
|
||||||
<div class="el-dropdown-link map-tool-btn">
|
<div class="el-dropdown-link map-tool-btn">
|
||||||
@ -66,12 +61,12 @@
|
|||||||
<div v-show="showDrawThin" class="map-tool-draw-thin">
|
<div v-show="showDrawThin" class="map-tool-draw-thin">
|
||||||
<div class="map-tool-draw-thin-density">
|
<div class="map-tool-draw-thin-density">
|
||||||
<span style="line-height: 36px; font-size: 15px">间隔: </span>
|
<span style="line-height: 36px; font-size: 15px">间隔: </span>
|
||||||
<el-slider v-model="diffPixels" show-input :min="10" :max="200" input-size="mini" ></el-slider>
|
<el-slider v-model="diffPixels" show-input :min="1" :max="200" input-size="mini" ></el-slider>
|
||||||
<div style="margin-left: 10px; line-height: 38px;">
|
<div style="margin-left: 10px; line-height: 38px;">
|
||||||
<el-button :loading="quicklyDrawThinLoading" @click="quicklyDrawThin" size="mini">快速抽稀</el-button>
|
<el-button :loading="quicklyDrawThinLoading" @click="quicklyDrawThin" size="mini">快速抽稀</el-button>
|
||||||
<el-button :loading="boxDrawThinLoading" size="mini" @click="boxDrawThin" >局部抽稀</el-button>
|
<el-button :loading="boxDrawThinLoading" size="mini" @click="boxDrawThin" >局部抽稀</el-button>
|
||||||
<el-button size="mini" @click="resetDrawThinData()">数据还原</el-button>
|
<el-button size="mini" @click="resetDrawThinData()">数据还原</el-button>
|
||||||
<el-button :loading="saveDrawThinLoading" type="primary" :disabled="!layerGroupSource" size="mini" @click="saveDrawThin()">保存</el-button>
|
<el-button :loading="saveDrawThinLoading" type="primary" :disabled="drawThinId === null" size="mini" @click="saveDrawThin()">保存</el-button>
|
||||||
<el-button type="warning" size="mini" @click="showDrawThinBox(false)">取消</el-button>
|
<el-button type="warning" size="mini" @click="showDrawThinBox(false)">取消</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -165,7 +160,7 @@ export default {
|
|||||||
longitudeStr: 'longitude',
|
longitudeStr: 'longitude',
|
||||||
latitudeStr: 'latitude',
|
latitudeStr: 'latitude',
|
||||||
mapTileList: [],
|
mapTileList: [],
|
||||||
diffPixels: 60,
|
diffPixels: 30,
|
||||||
zoomValue: 10,
|
zoomValue: 10,
|
||||||
showDrawThin: false,
|
showDrawThin: false,
|
||||||
quicklyDrawThinLoading: false,
|
quicklyDrawThinLoading: false,
|
||||||
@ -174,7 +169,6 @@ export default {
|
|||||||
drawThinLayer: null,
|
drawThinLayer: null,
|
||||||
saveDrawThinLoading: false,
|
saveDrawThinLoading: false,
|
||||||
layerType: 0,
|
layerType: 0,
|
||||||
layerGroupSource: null
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@ -316,6 +310,7 @@ export default {
|
|||||||
this.layerType = index
|
this.layerType = index
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
this.$refs.mapComponent.removeLayer(channelTileLayer)
|
this.$refs.mapComponent.removeLayer(channelTileLayer)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let geoCoordSys = this.$refs.mapComponent.getCoordSys()
|
let geoCoordSys = this.$refs.mapComponent.getCoordSys()
|
||||||
@ -326,10 +321,8 @@ export default {
|
|||||||
tileUrl = baseApi + `/api/common/channel/map/tile/{z}/{x}/{y}?geoCoordSys=${geoCoordSys}&accessToken=${this.$store.getters.token}`
|
tileUrl = baseApi + `/api/common/channel/map/tile/{z}/{x}/{y}?geoCoordSys=${geoCoordSys}&accessToken=${this.$store.getters.token}`
|
||||||
}else if (index === 2) {
|
}else if (index === 2) {
|
||||||
tileUrl = baseApi + `/api/common/channel/map/thin/tile/{z}/{x}/{y}?geoCoordSys=${geoCoordSys}&accessToken=${this.$store.getters.token}`
|
tileUrl = baseApi + `/api/common/channel/map/thin/tile/{z}/{x}/{y}?geoCoordSys=${geoCoordSys}&accessToken=${this.$store.getters.token}`
|
||||||
}else {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
channelTileLayer = this.$refs.mapComponent.addVectorTileLayer(tileUrl. this.clientEvent)
|
channelTileLayer = this.$refs.mapComponent.addVectorTileLayer(tileUrl, this.clientEvent)
|
||||||
},
|
},
|
||||||
closeInfoBox: function () {
|
closeInfoBox: function () {
|
||||||
if (this.infoBoxId !== null) {
|
if (this.infoBoxId !== null) {
|
||||||
@ -480,8 +473,6 @@ export default {
|
|||||||
this.drawThinLayer = null
|
this.drawThinLayer = null
|
||||||
}
|
}
|
||||||
this.quicklyDrawThinLoading = true
|
this.quicklyDrawThinLoading = true
|
||||||
console.log(222)
|
|
||||||
console.log(this.getDrawThinParam())
|
|
||||||
// 获取每一个图层的抽稀参数
|
// 获取每一个图层的抽稀参数
|
||||||
this.$store.dispatch('commonChanel/drawThin', {
|
this.$store.dispatch('commonChanel/drawThin', {
|
||||||
zoomParam: this.getDrawThinParam()
|
zoomParam: this.getDrawThinParam()
|
||||||
@ -504,12 +495,16 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
showDrawThinLayer(thinId) {
|
showDrawThinLayer(thinId) {
|
||||||
|
if (this.drawThinLayer) {
|
||||||
|
this.$refs.mapComponent.removeLayer(this.drawThinLayer)
|
||||||
|
this.drawThinLayer = null
|
||||||
|
}
|
||||||
// 展示抽稀结果
|
// 展示抽稀结果
|
||||||
let geoCoordSys = this.$refs.mapComponent.getCoordSys()
|
let geoCoordSys = this.$refs.mapComponent.getCoordSys()
|
||||||
const baseUrl = window.baseUrl ? window.baseUrl : ''
|
const baseUrl = window.baseUrl ? window.baseUrl : ''
|
||||||
let baseApi = ((process.env.NODE_ENV === 'development') ? process.env.VUE_APP_BASE_API : baseUrl)
|
let baseApi = ((process.env.NODE_ENV === 'development') ? process.env.VUE_APP_BASE_API : baseUrl)
|
||||||
let tileUrl = baseApi + `/api/common/channel/map/thin/tile/{z}/{x}/{y}?geoCoordSys=${geoCoordSys}&thinId=${thinId}&accessToken=${this.$store.getters.token}`
|
let tileUrl = baseApi + `/api/common/channel/map/thin/tile/{z}/{x}/{y}?geoCoordSys=${geoCoordSys}&thinId=${thinId}&accessToken=${this.$store.getters.token}`
|
||||||
this.drawThinLayer = this.$refs.mapComponent.addVectorTileLayer(tileUrl, null)
|
this.drawThinLayer = this.$refs.mapComponent.addVectorTileLayer(tileUrl, this.clientEvent)
|
||||||
},
|
},
|
||||||
boxDrawThin: function (){
|
boxDrawThin: function (){
|
||||||
this.$message.warning({
|
this.$message.warning({
|
||||||
@ -534,7 +529,13 @@ export default {
|
|||||||
// 获取每一个图层的抽稀参数
|
// 获取每一个图层的抽稀参数
|
||||||
this.$store.dispatch('commonChanel/drawThin', {
|
this.$store.dispatch('commonChanel/drawThin', {
|
||||||
zoomParam: this.getDrawThinParam(),
|
zoomParam: this.getDrawThinParam(),
|
||||||
extent: extent
|
extent: {
|
||||||
|
minLng: extent[0],
|
||||||
|
minLat: extent[1],
|
||||||
|
maxLng: extent[2],
|
||||||
|
maxLat: extent[3]
|
||||||
|
},
|
||||||
|
geoCoordSys: 'GCJ02'
|
||||||
})
|
})
|
||||||
.then(drawThinId => {
|
.then(drawThinId => {
|
||||||
// 显示抽稀进度
|
// 显示抽稀进度
|
||||||
@ -559,7 +560,7 @@ export default {
|
|||||||
let zoomExtent = this.$refs.mapComponent.getZoomExtent()
|
let zoomExtent = this.$refs.mapComponent.getZoomExtent()
|
||||||
let zoomMap = {}
|
let zoomMap = {}
|
||||||
let zoom = zoomExtent[0]
|
let zoom = zoomExtent[0]
|
||||||
while (zoom < zoomExtent[1]) {
|
while (zoom <= zoomExtent[1]) {
|
||||||
// 计算经纬度差值
|
// 计算经纬度差值
|
||||||
let diff = this.$refs.mapComponent.computeDiff(this.diffPixels, zoom)
|
let diff = this.$refs.mapComponent.computeDiff(this.diffPixels, zoom)
|
||||||
if (diff && diff > 0) {
|
if (diff && diff > 0) {
|
||||||
@ -569,96 +570,7 @@ export default {
|
|||||||
}
|
}
|
||||||
return zoomMap
|
return zoomMap
|
||||||
},
|
},
|
||||||
drawThin: function (cameraListInExtent){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
try {
|
|
||||||
let layerGroupSource = new Map()
|
|
||||||
// 获取全部层级
|
|
||||||
let zoomExtent = this.$refs.mapComponent.getZoomExtent()
|
|
||||||
let zoom = zoomExtent[0]
|
|
||||||
let zoomCameraMap = new Map()
|
|
||||||
let useCameraMap = new Map()
|
|
||||||
|
|
||||||
while (zoom < zoomExtent[1]) {
|
|
||||||
// 计算经纬度差值
|
|
||||||
let diff = this.$refs.mapComponent.computeDiff(this.diffPixels, zoom)
|
|
||||||
let cameraMapForZoom = new Map()
|
|
||||||
let useCameraMapForZoom = new Map()
|
|
||||||
let useCameraList = Array.from(useCameraMap.values())
|
|
||||||
for (let i = 0; i < useCameraList.length; i++) {
|
|
||||||
let value = useCameraList[i]
|
|
||||||
let lngGrid = Math.trunc(value.gbLongitude / diff)
|
|
||||||
let latGrid = Math.trunc(value.gbLatitude / diff)
|
|
||||||
let gridKey = latGrid + ':' + lngGrid
|
|
||||||
useCameraMapForZoom.set(gridKey, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < cameraListInExtent.length; i++) {
|
|
||||||
let value = cameraListInExtent[i]
|
|
||||||
if (useCameraMap.has(value.gbId) || !value.gbLongitude || !value.gbLatitude) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
let lngGrid = Math.trunc(value.gbLongitude / diff)
|
|
||||||
let latGrid = Math.trunc(value.gbLatitude / diff)
|
|
||||||
let gridKey = latGrid + ':' + lngGrid
|
|
||||||
if (useCameraMapForZoom.has(gridKey)) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (cameraMapForZoom.has(gridKey)) {
|
|
||||||
let oldValue = cameraMapForZoom.get(gridKey)
|
|
||||||
if (value.gbLongitude % diff < oldValue.gbLongitude % diff) {
|
|
||||||
cameraMapForZoom.set(gridKey, value)
|
|
||||||
useCameraMap.set(value.gbId, value)
|
|
||||||
useCameraMap.delete(oldValue.gbId)
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
cameraMapForZoom.set(gridKey, value)
|
|
||||||
useCameraMap.set(value.gbId, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let cameraArray = Array.from(cameraMapForZoom.values())
|
|
||||||
zoomCameraMap.set(zoom, cameraArray)
|
|
||||||
let layerSource = this.createZoomLayerSource(cameraArray)
|
|
||||||
layerGroupSource.set(zoom - 1, layerSource)
|
|
||||||
zoom += 1
|
|
||||||
}
|
|
||||||
let cameraArray = []
|
|
||||||
for (let i = 0; i < cameraListInExtent.length; i++) {
|
|
||||||
let value = cameraListInExtent[i]
|
|
||||||
if (useCameraMap.has(value.gbId) || !value.gbLongitude || !value.gbLatitude) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cameraArray.push(value)
|
|
||||||
}
|
|
||||||
let layerSource = this.createZoomLayerSource(cameraArray)
|
|
||||||
layerGroupSource.set(zoomExtent[1] - 1, layerSource)
|
|
||||||
|
|
||||||
resolve(layerGroupSource)
|
|
||||||
}catch (error) {
|
|
||||||
reject(error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
createZoomLayerSource(cameraArray) {
|
|
||||||
let dataArray = []
|
|
||||||
for (let i = 0; i < cameraArray.length; i++) {
|
|
||||||
let item = cameraArray[i]
|
|
||||||
let position = [item.gbLongitude, item.gbLatitude]
|
|
||||||
dataArray.push({
|
|
||||||
id: item.gbId,
|
|
||||||
position: position,
|
|
||||||
data: item,
|
|
||||||
status: item.gbStatus,
|
|
||||||
image: {
|
|
||||||
anchor: [0.5, 1],
|
|
||||||
src: this.getImageByChannel(item)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return dataArray
|
|
||||||
},
|
|
||||||
saveDrawThin: function(){
|
saveDrawThin: function(){
|
||||||
if (!this.drawThinId) {
|
if (!this.drawThinId) {
|
||||||
return
|
return
|
||||||
@ -669,7 +581,7 @@ export default {
|
|||||||
showClose: true,
|
showClose: true,
|
||||||
message: '保存成功'
|
message: '保存成功'
|
||||||
})
|
})
|
||||||
this.showDrawThin = false
|
this.showDrawThinBox(false)
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.saveDrawThinLoading = false
|
this.saveDrawThinLoading = false
|
||||||
@ -689,30 +601,6 @@ export default {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
|
||||||
addVectorTileLayer() {
|
|
||||||
let geoCoordSys = this.$refs.mapComponent.getCoordSys()
|
|
||||||
const baseUrl = window.baseUrl ? window.baseUrl : ''
|
|
||||||
let tileUrl = ((process.env.NODE_ENV === 'development') ? process.env.VUE_APP_BASE_API : baseUrl)
|
|
||||||
+ `/api/common/channel/map/tile/{z}/{x}/{y}?geoCoordSys=${geoCoordSys}&accessToken=${this.$store.getters.token}`
|
|
||||||
|
|
||||||
let clientEvent = data => {
|
|
||||||
this.closeInfoBox()
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.showChannelInfo(data[0])
|
|
||||||
// if (data[0].edit) {
|
|
||||||
// this.showEditInfo(data[0])
|
|
||||||
// }else {
|
|
||||||
// this.showChannelInfo(data[0])
|
|
||||||
// }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let tileEvent = error => {
|
|
||||||
console.log(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
let tileLayer = this.$refs.mapComponent.addVectorTileLayer(tileUrl, clientEvent, tileEvent)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user