import * as ol from 'ol' import * as style from 'ol/style' import * as layer from 'ol/layer' import * as source from 'ol/source' import * as geom from 'ol/geom' import * as proj from 'ol/proj' import * as interaction from 'ol/interaction' import {isValue} from "@/utils/util"; import * as extent from "ol/extent"; // @ts-ignore import AIS from './AIS.svg' 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 shipActiveStyle = (color = '#9F2EFF') => { const radius = 25 const longRadius = radius * Math.SQRT2 return new style.Style({ image: new style.RegularShape({ stroke: new style.Stroke({ color, width: 2, lineDash: [ (longRadius * 3) / 10, (longRadius * 4) / 10, (longRadius * 3) / 10, 0 ] }), radius1: radius, rotation: Math.PI / (180 / 45), points: 4 }) }) } const ShipNormalStyle = ({ course = 0, speed = 0, head = null, color = '#01f200' }) => { const _style: any = [] const allRotation = Math.PI / (180 / course) const lineRadius = speed * 5 // 船速 _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: AIS, 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 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] } const E = 0.00000001 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 (map.getView().getZoom() < map.getView().getMaxZoom()) { 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 (map.getView().getZoom() < map.getView().getMaxZoom() - 1) { 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]) } }); } return callback(_style, pList) } const trackPointNormalStyle = (color) => { const _style: any = [] _style.push(new style.Style({ image: new style.Circle({ radius: 4, fill: new style.Fill({ color: color, }), stroke: new style.Stroke({ color: '#ffffff', width: 2, }), }) })) return _style } const trackPointHoverStyle = (color) => { const _style: any = [] _style.push(new style.Style({ image: new style.Circle({ radius: 6, fill: new style.Fill({ color: color, }), }) })) return _style } export default { ShipNormalStyle, shipActiveStyle, trackStyle, trackPointNormalStyle, trackPointHoverStyle }