import * as style from 'ol/style' import * as geom from 'ol/geom' import * as extent from "ol/extent"; import MapWarningIconRed from "@/assets/images/web/map-warning-icon-red.svg"; import MapWarningIconYellow from "@/assets/images/web/map-warning-icon-yellow.svg"; import MapWarningIconBlue from "@/assets/images/web/map-warning-icon-blue.svg"; import AIS from './ship-type/AIS.svg' import AIS_BEIDOU from './ship-type/AIS_BEIDOU.svg' import AIS_BEIDOU_RADAR from './ship-type/AIS_BEIDOU_RADAR.svg' import AIS_RADAR from './ship-type/AIS_RADAR.svg' import BEIDOU from './ship-type/BEIDOU.svg' import BEIDOU_RADAR from './ship-type/BEIDOU_RADAR.svg' import OTHER from './ship-type/OTHER.svg' import RADAR from './ship-type/RADAR.svg' import FIXED from './ship-type/FIXED.svg' const shipIcon = { AIS, AIS_BEIDOU, AIS_BEIDOU_RADAR, AIS_RADAR, BEIDOU, BEIDOU_RADAR, OTHER, RADAR, FIXED } const speedStyle = (lineRadius, rotation) => { return new style.Style({ image: new style.RegularShape({ stroke: new style.Stroke({ color: '#000000', width: 1 }), displacement: [0, lineRadius], radius: lineRadius, rotation, points: 2 }) }) } const headingStyle = (lineRadius, headAngle, rotation) => { const headRadius = 6 return new style.Style({ image: new style.RegularShape({ stroke: new style.Stroke({ color: '#ee1919', width: 1 }), displacement: [ headRadius * Math.sin(headAngle / 180 * Math.PI), (lineRadius * 2) + headRadius * Math.cos(headAngle / 180 * Math.PI) ], //这是偏移量 radius: headRadius, rotation, angle: Math.PI / (180 / headAngle), //这是角度计算出的地图上显示的角度 points: 2 }) }) } const ShipNormalStyle = ({course = 0, speed = 0, head = null, color = '#01f200', mergeType = 'OTHER'}) => { const _style: any = [] const allRotation = Math.PI / (180 / course) let lineRadius = 0 if (speed > 0) { if (speed <= 5) { lineRadius = 2 } else if (speed <= 10) { lineRadius = 6 } else if (speed <= 20) { lineRadius = 18 } else if (speed > 20) { lineRadius = 30 } } // 船速 _style.push(speedStyle(lineRadius, allRotation)) if (head) { const headAngle = head + (360 - course) // 船首向 _style.push(headingStyle(lineRadius, headAngle, allRotation)) } _style.push(new style.Style({ image: new style.Icon({ color: color, src: shipIcon[mergeType], rotation: allRotation, scale: 1 }), })) return _style } const trackStyle = (feature, resolution, map, color, callback) => { const geometry = feature.getGeometry(); const length = geometry.getLength();//获取线段长度 const radio = (200 * resolution) / length; const dradio = 1;//投影坐标系,如3857等,在EPSG:4326下可以设置dradio=10000 const _style = [ new style.Style({ stroke: new style.Stroke({ color: color, width: 2, }) }) ]; const radius = 10 const longRadius = radius * Math.SQRT2; const flag = map.getView().getZoom() < map.getView().getMaxZoom() - 1 const E = 0.00000001 const judgeIs = (p1, p2, p3) => { const k1 = (ps, pe) => { return (pe[1] - ps[1]) / (pe[0] - ps[0]) } const k2 = (ps, pe) => { return (pe[0] - ps[0]) / (pe[1] - ps[0]) } const a = (ps, pe) => { return Math.abs(k1(p1, ps) - k1(p1, pe)) <= E && Math.abs(k1(p1, ps) - k1(p1, pe)) >= -E } const d = (ps, pe) => { return Math.abs(k2(p1, ps) - k2(p1, pe)) <= E && Math.abs(k2(p1, ps) - k2(p1, pe)) >= -E } const s = (p) => { return p3[0] === p[0] && p3[1] === p[1] } return s(p1) || s(p2) || a(p2, p3) || d(p2, p3) } for (let i = 0; i <= 1; i += radio) { const arrowLocation = geometry.getCoordinateAt(i); if (extent.containsCoordinate(map.getView().calculateExtent(map.getSize()), arrowLocation)) { geometry.forEachSegment((start, end) => { if (!judgeIs(start, end, arrowLocation)) { return } let rotation = 0; const dx = end[0] - start[0]; const dy = end[1] - start[1]; rotation = Math.atan2(dy, dx); const pushStyle = (position) => { _style.push(new style.Style({ geometry: new geom.Point(position), image: new style.RegularShape({ stroke: new style.Stroke({ color, width: 2, lineDash: [ longRadius - (4 * (radius / 10)), longRadius + (5.5 * (radius / 10)), longRadius, 0 ] }), radius: radius / Math.SQRT2, rotation: -rotation, angle: Math.PI / (180 / 90), points: 4 }) })); } if (flag) { const dx1 = end[0] - arrowLocation[0]; const dy1 = end[1] - arrowLocation[1]; const dx2 = arrowLocation[0] - start[0]; const dy2 = arrowLocation[1] - start[1]; if (dx1 != dx2 && dy1 != dy2) { if (Math.abs(dradio * dx1 * dy2 - dradio * dx2 * dy1) < 0.001) { pushStyle(arrowLocation) } } } else { if (Math.sqrt(Math.pow(start[0] - end[0], 2) + Math.pow(start[1] - end[1], 2)) > resolution * 100) { pushStyle([(start[0] + end[0]) / 2, (start[1] + end[1]) / 2]) } } }); } } const trackPointList = feature.get('trackPointList') const pList: any = [] let trackPointListIndex = 0 let lC = 0 pList.push(trackPointList[0]) if (flag) { geometry.forEachSegment((start, end) => { trackPointListIndex++ const l = new geom.LineString([start,end]) lC += l.getLength() if (extent.containsCoordinate(map.getView().calculateExtent(map.getSize()), end) && lC > 200 * resolution) { pList.push(trackPointList[trackPointListIndex]) lC = 0 } }); } else { geometry.forEachSegment((start, end) => { trackPointListIndex++ const l = new geom.LineString([start,end]) if (extent.containsCoordinate(map.getView().calculateExtent(map.getSize()), end)) { pList.push(trackPointList[trackPointListIndex]) } }); } const arr: any = [] const num = 100 const step = Math.ceil(_style.length / num) for (let i = 0; i < _style.length; i += step) { arr.push(_style[i]) } return callback([..._style, ...arr], pList) } const trackPointNormalStyle = (color) => { const _style: any = [] _style.push(new style.Style({ image: new style.Circle({ radius: 3, fill: new style.Fill({ color: color, }), stroke: new style.Stroke({ color: '#ffffff', width: 1, }), }) })) return _style } const warningStyle = (level) => { let icon = MapWarningIconBlue; switch (warningStyle) { case 1: {icon = MapWarningIconRed} break; case 2: {icon = MapWarningIconYellow} break; case 3: {icon = MapWarningIconBlue} break; } return new style.Style({ image: new style.Icon({ src: icon, scale: 2, anchor: [0.5, 0], anchorOrigin: 'bottom-left', anchorXUnits: 'fraction', // 定位点的单位 anchorYUnits: 'fraction', }), }) } export default { ShipNormalStyle, trackStyle, trackPointNormalStyle, warningStyle, }