/** * @Author: Caven * @Date: 2020-08-30 16:27:29 */ import { Cesium } from '@dc-modules/namespace' import Parse from '@dc-modules/parse/Parse' import { Transform } from '@dc-modules/transform' import { PlotUtil } from '@dc-modules/utils' const HALF_PI = Math.PI / 2 class DoubleArrowGraphics { constructor(options) { this._positions = options?.positions || [] this.headHeightFactor = 0.25 this.headWidthFactor = 0.3 this.neckHeightFactor = 0.85 this.neckWidthFactor = 0.15 } set positions(positions) { this._positions = positions } get positions() { return this._positions } get hierarchy() { return this._createHierarchy() } _getArrowPoints(pnt1, pnt2, pnt3, clockWise) { let midPnt = PlotUtil.mid(pnt1, pnt2) let len = PlotUtil.distance(midPnt, pnt3) let midPnt1 = PlotUtil.getThirdPoint(pnt3, midPnt, 0, len * 0.3, true) let midPnt2 = PlotUtil.getThirdPoint(pnt3, midPnt, 0, len * 0.5, true) midPnt1 = PlotUtil.getThirdPoint( midPnt, midPnt1, HALF_PI, len / 5, clockWise ) midPnt2 = PlotUtil.getThirdPoint( midPnt, midPnt2, HALF_PI, len / 4, clockWise ) let points = [midPnt, midPnt1, midPnt2, pnt3] // 计算箭头部分 let arrowPnts = this._getArrowHeadPoints(points) let neckLeftPoint = arrowPnts[0] let neckRightPoint = arrowPnts[4] // 计算箭身部分 let tailWidthFactor = PlotUtil.distance(pnt1, pnt2) / PlotUtil.getBaseLength(points) / 2 let bodyPnts = this._getArrowBodyPoints( points, neckLeftPoint, neckRightPoint, tailWidthFactor ) let n = bodyPnts.length let lPoints = bodyPnts.slice(0, n / 2) let rPoints = bodyPnts.slice(n / 2, n) lPoints.push(neckLeftPoint) rPoints.push(neckRightPoint) lPoints = lPoints.reverse() lPoints.push(pnt2) rPoints = rPoints.reverse() rPoints.push(pnt1) return lPoints.reverse().concat(arrowPnts, rPoints) } _getArrowHeadPoints(points) { let len = PlotUtil.getBaseLength(points) let headHeight = len * this.headHeightFactor let headPnt = points[points.length - 1] let headWidth = headHeight * this.headWidthFactor let neckWidth = headHeight * this.neckWidthFactor let neckHeight = headHeight * this.neckHeightFactor let headEndPnt = PlotUtil.getThirdPoint( points[points.length - 2], headPnt, 0, headHeight, true ) let neckEndPnt = PlotUtil.getThirdPoint( points[points.length - 2], headPnt, 0, neckHeight, true ) let headLeft = PlotUtil.getThirdPoint( headPnt, headEndPnt, HALF_PI, headWidth, false ) let headRight = PlotUtil.getThirdPoint( headPnt, headEndPnt, HALF_PI, headWidth, true ) let neckLeft = PlotUtil.getThirdPoint( headPnt, neckEndPnt, HALF_PI, neckWidth, false ) let neckRight = PlotUtil.getThirdPoint( headPnt, neckEndPnt, HALF_PI, neckWidth, true ) return [neckLeft, headLeft, headPnt, headRight, neckRight] } _getArrowBodyPoints(points, neckLeft, neckRight, tailWidthFactor) { let allLen = PlotUtil.wholeDistance(points) let len = PlotUtil.getBaseLength(points) let tailWidth = len * tailWidthFactor let neckWidth = PlotUtil.distance(neckLeft, neckRight) let widthDif = (tailWidth - neckWidth) / 2 let tempLen = 0 let leftBodyPnts = [] let rightBodyPnts = [] for (let i = 1; i < points.length - 1; i++) { let angle = PlotUtil.getAngleOfThreePoints( points[i - 1], points[i], points[i + 1] ) / 2 tempLen += PlotUtil.distance(points[i - 1], points[i]) let w = (tailWidth / 2 - (tempLen / allLen) * widthDif) / Math.sin(angle) let left = PlotUtil.getThirdPoint( points[i - 1], points[i], Math.PI - angle, w, true ) let right = PlotUtil.getThirdPoint( points[i - 1], points[i], angle, w, false ) leftBodyPnts.push(left) rightBodyPnts.push(right) } return leftBodyPnts.concat(rightBodyPnts) } _getTempPoint4(linePnt1, linePnt2, point) { let midPnt = PlotUtil.mid(linePnt1, linePnt2) let len = PlotUtil.distance(midPnt, point) let angle = PlotUtil.getAngleOfThreePoints(linePnt1, midPnt, point) let symPnt, distance1, distance2, mid if (angle < HALF_PI) { distance1 = len * Math.sin(angle) distance2 = len * Math.cos(angle) mid = PlotUtil.getThirdPoint(linePnt1, midPnt, HALF_PI, distance1, false) symPnt = PlotUtil.getThirdPoint(midPnt, mid, HALF_PI, distance2, true) } else if (angle >= HALF_PI && angle < Math.PI) { distance1 = len * Math.sin(Math.PI - angle) distance2 = len * Math.cos(Math.PI - angle) mid = PlotUtil.getThirdPoint(linePnt1, midPnt, HALF_PI, distance1, false) symPnt = PlotUtil.getThirdPoint(midPnt, mid, HALF_PI, distance2, false) } else if (angle >= Math.PI && angle < Math.PI * 1.5) { distance1 = len * Math.sin(angle - Math.PI) distance2 = len * Math.cos(angle - Math.PI) mid = PlotUtil.getThirdPoint(linePnt1, midPnt, HALF_PI, distance1, true) symPnt = PlotUtil.getThirdPoint(midPnt, mid, HALF_PI, distance2, true) } else { distance1 = len * Math.sin(Math.PI * 2 - angle) distance2 = len * Math.cos(Math.PI * 2 - angle) mid = PlotUtil.getThirdPoint(linePnt1, midPnt, HALF_PI, distance1, true) symPnt = PlotUtil.getThirdPoint(midPnt, mid, HALF_PI, distance2, false) } return symPnt } _createHierarchy() { let count = this._positions.length let tempPoint4 = undefined let connPoint = undefined let pnts = Parse.parsePolygonCoordToArray( Transform.transformCartesianArrayToWGS84Array(this._positions) )[0] let pnt1 = pnts[0] let pnt2 = pnts[1] let pnt3 = pnts[2] if (count === 3) tempPoint4 = this._getTempPoint4(pnt1, pnt2, pnt3) else tempPoint4 = pnts[3] if (count === 3 || count === 4) connPoint = PlotUtil.mid(pnt1, pnt2) else connPoint = pnts[4] let leftArrowPnts, rightArrowPnts if (PlotUtil.isClockWise(pnt1, pnt2, pnt3)) { leftArrowPnts = this._getArrowPoints(pnt1, connPoint, tempPoint4, false) rightArrowPnts = this._getArrowPoints(connPoint, pnt2, pnt3, true) } else { leftArrowPnts = this._getArrowPoints(pnt2, connPoint, pnt3, false) rightArrowPnts = this._getArrowPoints(connPoint, pnt1, tempPoint4, true) } let m = leftArrowPnts.length let t = (m - 5) / 2 let llBodyPnts = leftArrowPnts.slice(0, t) let lArrowPnts = leftArrowPnts.slice(t, t + 5) let lrBodyPnts = leftArrowPnts.slice(t + 5, m) let rlBodyPnts = rightArrowPnts.slice(0, t) let rArrowPnts = rightArrowPnts.slice(t, t + 5) let rrBodyPnts = rightArrowPnts.slice(t + 5, m) rlBodyPnts = PlotUtil.getBezierPoints(rlBodyPnts) let bodyPnts = PlotUtil.getBezierPoints( rrBodyPnts.concat(llBodyPnts.slice(1)) ) lrBodyPnts = PlotUtil.getBezierPoints(lrBodyPnts) return new Cesium.PolygonHierarchy( Transform.transformWGS84ArrayToCartesianArray( Parse.parsePositions( rlBodyPnts.concat(rArrowPnts, bodyPnts, lArrowPnts, lrBodyPnts) ) ) ) } } export default DoubleArrowGraphics