123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510 |
- // 三、曲线
- // DrawCurve
- /*
- 绘制曲线
- */
- class DrawCurve {
- constructor(arg) {
- this.viewer = arg.viewer;
- this.Cesium = arg.Cesium;
- this.floatingPoint = null;//标识点
- this._curveline = null; //活动曲线
- this._curvelineLast = null; //最后一条曲线
- this._positions = []; //活动点
- this._entities_point = []; //脏数据
- this._entities_line = []; //脏数据
- this._curvelineData = null; //用于构造曲线数据
- this.DrawStartEvent = new Cesium.Event(); //开始绘制事件
- this.DrawEndEvent = new Cesium.Event(); //结束绘制事件
- this.ZERO_TOLERANCE = 0.0001;
- this.FITTING_COUNT = 100;
- this.t = 0.3;
-
- /* 通用参数集合 */
- this._param = {
- id: "DrawStraightArrow",
- polygonColor: 'rgba(0,255,0,0.5)', //面填充颜色
- outlineColor: 'rgba(255, 255, 255, 1)', //边框颜色
- outlineWidth: 1, //边框宽度
- }
-
- /* 创建面材质 */
- this.polygonMaterial = Cesium.Color.fromCssColorString(this._param.polygonColor);
- /* 创建线材质 */
- // this.outlineMaterial = new Cesium.PolylineDashMaterialProperty({//曲线
- // dashLength: 16,
- // color: Cesium.Color.fromCssColorString(this._param.outlineColor)
- // });
- this.outlineMaterial = Cesium.Color.fromCssColorString(this._param.outlineColor);
- }
- //返回最后活动曲线
- get curveline() {
- return this._curvelineLast;
- }
- //返回线数据用于加载线
- getData() {
- return this._curvelineData;
- }
- //加载曲线
- addload(data) {
- var $this = this;
- let pnts = []
- for (let p = 0; p < data.length; p++) {
- pnts.push($this.lonLatToMercator(data[p]))
- }
- let CurvePoints = $this.getCurvePoints(pnts)
- let point = [];
- for (let i = 0; i < CurvePoints.length; i++) {
- point.push($this.LatlngTocartesian($this.WebMercator2lonLat(CurvePoints[i])))
- }
- var polyline = this.viewer.entities.add({
- Type: 'DrawCurve',
- Position: data,
- id: data.id || $this.objId,
- polyline: {
- positions: point,
- show: true,
- material: $this.Cesium.Color.YELLOW,
- width: 3,
- clampToGround: true
- }
- });
- return polyline;
- }
- // 修改编辑调用计算
- computePosition(data) {
- let pnts = [];
- let position = [];
- for (let p = 0; p < data.length; p++) {
- position.push(this.cartesianToLatlng(data[p]));
- pnts.push(this.lonLatToMercator(this.cartesianToLatlng(data[p])))
- }
- this._curvelineData = position;
- let CurvePoints = this.getCurvePoints(pnts)
- let point = [];
- for (let i = 0; i < CurvePoints.length; i++) {
- point.push(this.LatlngTocartesian(this.WebMercator2lonLat(CurvePoints[i])))
- }
- return point;
- }
- //开始创建
- startCreate(drawType) {
- this.drawType = drawType
- var $this = this;
- this.handler = new this.Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
- this.handler.setInputAction(function (evt) { //单机开始绘制
- //屏幕坐标转地形上坐标
- var cartesian = $this.getCatesian3FromPX(evt.position);
- if ($this._positions.length == 0) {
- $this._positions.push(cartesian.clone());
- $this.floatingPoint = $this.createPoint(cartesian);
- $this.createPoint(cartesian);// 绘制点
- }
- $this._positions.push(cartesian);
- }, $this.Cesium.ScreenSpaceEventType.LEFT_CLICK);
- this.handler.setInputAction(function (evt) { //移动时绘制线
- if ($this._positions.length < 3) return;
- var cartesian = $this.getCatesian3FromPX(evt.endPosition);
- if (!$this.Cesium.defined($this._curveline)) {
- $this._curveline = $this.createCurveline();
- }
- $this.floatingPoint.position.setValue(cartesian);
- if ($this._curveline) {
- $this._positions.pop();
- $this._positions.push(cartesian);
- }
- }, $this.Cesium.ScreenSpaceEventType.MOUSE_MOVE);
- this.handler.setInputAction(function (evt) {
- if (!$this._curveline) return;
- var cartesian = $this.getCatesian3FromPX(evt.position);
- $this._positions.pop();
- $this._positions.push(cartesian);
- $this.createPoint(cartesian);// 绘制点
- $this._curvelineData = $this._positions.concat();
- $this.viewer.entities.remove($this._curveline); //移除
- $this._curveline = null;
- $this._positions = [];
- $this.floatingPoint.position.setValue(cartesian);
- let lnglatArr = [];
- for (var i = 0; i < $this._curvelineData.length; i++) {
- var lnglat = $this.cartesianToLatlng($this._curvelineData[i]);
- lnglatArr.push(lnglat)
- }
- $this._curvelineData = lnglatArr;
- var line = $this.addload($this._curvelineData); //加载曲线
- $this._entities_line.push(line);
- $this._curvelineLast = line;
- $this.clearPoint()
- $this.destroy()
- }, $this.Cesium.ScreenSpaceEventType.RIGHT_CLICK);
- }
- //创建点
- createPoint(cartesian) {
- var $this = this;
- var point = this.viewer.entities.add({
- position: cartesian,
- point: {
- pixelSize: 10,
- color: $this.Cesium.Color.RED,
- heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
- }
- });
- $this._entities_point.push(point);
- return point;
- }
- //创建曲线
- createCurveline() {
- var $this = this;
- var polyline = this.viewer.entities.add({
- polyline: {
- //使用cesium的peoperty
- positions: new $this.Cesium.CallbackProperty(function () {
- let pnts = []
- for (let p = 0; p < $this._positions.length; p++) {
- pnts.push($this.lonLatToMercator($this.cartesianToLatlng($this._positions[p])))
- }
- let CurvePoints = $this.getCurvePoints(pnts)
- let point = [];
- for (let i = 0; i < CurvePoints.length; i++) {
- point.push($this.LatlngTocartesian($this.WebMercator2lonLat(CurvePoints[i])))
- }
- return point;
- }, false),
- show: true,
- material: $this.Cesium.Color.YELLOW,
- width: 3,
- clampToGround: true
- }
- });
- $this._entities_line.push(polyline);
- return polyline;
- }
- clearPoint() {
- this.DrawEndEvent.raiseEvent(this._curvelineLast, this._curvelineData, this.drawType);
- for (var i = 0; i < this._entities_point.length; i++) {
- this.viewer.entities.remove(this._entities_point[i]);
- }
- this._entities_point = []; //脏数据
- }
- //销毁
- destroy() {
- if (this.handler) {
- this.handler.destroy();
- this.handler = null;
- }
- }
- //清空实体对象
- clear() {
- for (var i = 0; i < this._entities_point.length; i++) {
- this.viewer.entities.remove(this._entities_point[i]);
- }
- for (var i = 0; i < this._entities_line.length; i++) {
- this.viewer.entities.remove(this._entities_line[i]);
- }
- this.floatingPoint = null;//标识点
- this._curveline = null; //活动曲线
- this._curvelineLast = null; //最后一条曲线
- this._positions = []; //活动点
- this._entities_point = []; //脏数据
- this._entities_line = []; //脏数据
- this._curvelineData = null; //用于构造曲线数据
- }
- getCatesian3FromPX(px) {
- var cartesian;
- var ray = this.viewer.camera.getPickRay(px);
- if (!ray) return null;
- cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
- return cartesian;
- }
- cartesianToLatlng(cartesian) {
- var latlng = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian);
- var lat = this.Cesium.Math.toDegrees(latlng.latitude);
- var lng = this.Cesium.Math.toDegrees(latlng.longitude);
- return [lng, lat];
- }
- LatlngTocartesian(latlng) {
- let cartesian3 = this.Cesium.Cartesian3.fromDegrees(latlng[0], latlng[1]);
- return cartesian3
- }
- /**
- * 经纬度坐标转墨卡托坐标
- */
- // 墨卡托坐标系:展开地球,赤道作为x轴,向东为x轴正方,本初子午线作为y轴,向北为y轴正方向。
- // 数字20037508.34是地球赤道周长的一半:地球半径6378137米,赤道周长2*PI*r = 2 * 20037508.3427892,墨卡托坐标x轴区间[-20037508.3427892,20037508.3427892]
- lonLatToMercator(Latlng) {
- var E = Latlng[0];
- var N = Latlng[1];
- var x = E * 20037508.34 / 180;
- var y = Math.log(Math.tan((90 + N) * Math.PI / 360)) / (Math.PI / 180);
- y = y * 20037508.34 / 180;
- return [x, y]
- }
- /**
- * 墨卡托坐标转经纬度坐标转
- */
- WebMercator2lonLat(mercator) {
- let x = mercator[0] / 20037508.34 * 180;
- let ly = mercator[1] / 20037508.34 * 180;
- let y = 180 / Math.PI * (2 * Math.atan(Math.exp(ly * Math.PI / 180)) - Math.PI / 2)
- return [x, y];
- }
- /**
- * 插值曲线点
- * @param t
- * @param controlPoints
- * @returns {null}
- */
- getCurvePoints( controlPoints) {
- let leftControl = this.getLeftMostControlPoint(controlPoints, this.t)
- let [pnt1, pnt2, pnt3, normals, points] = [null, null, null, [leftControl], []]
- for (let i = 0; i < controlPoints.length - 2; i++) {
- [pnt1, pnt2, pnt3] = [controlPoints[i], controlPoints[i + 1], controlPoints[i + 2]]
- let normalPoints = this.getBisectorNormals(this.t, pnt1, pnt2, pnt3)
- normals = normals.concat(normalPoints)
- }
- let rightControl = this.getRightMostControlPoint(controlPoints, this.t)
- if (rightControl) {
- normals.push(rightControl)
- }
- for (let i = 0; i < controlPoints.length - 1; i++) {
- pnt1 = controlPoints[i]
- pnt2 = controlPoints[i + 1]
- points.push(pnt1)
- for (let t = 0; t < this.FITTING_COUNT; t++) {
- let pnt = this.getCubicValue(t / this.FITTING_COUNT, pnt1, normals[i * 2], normals[i * 2 + 1], pnt2)
- points.push(pnt)
- }
- points.push(pnt2)
- }
- return points
- }
- /**
- * 获取左边控制点
- * @param controlPoints
- * @returns {[*,*]}
- */
- getLeftMostControlPoint(controlPoints, t) {
- let [pnt1, pnt2, pnt3, controlX, controlY] = [controlPoints[0], controlPoints[1], controlPoints[2], null, null]
- let pnts = this.getBisectorNormals(0, pnt1, pnt2, pnt3)
- let normalRight = pnts[0]
- let normal = this.getNormal(pnt1, pnt2, pnt3)
- let dist = Math.sqrt(normal[0] * normal[0] + normal[1] * normal[1])
- if (dist > this.ZERO_TOLERANCE) {
- let mid = this.Mid(pnt1, pnt2)
- let pX = pnt1[0] - mid[0]
- let pY = pnt1[1] - mid[1]
- let d1 = this.MathDistance(pnt1, pnt2)
- let n = 2.0 / d1
- let nX = -n * pY
- let nY = n * pX
- let a11 = nX * nX - nY * nY
- let a12 = 2 * nX * nY
- let a22 = nY * nY - nX * nX
- let dX = normalRight[0] - mid[0]
- let dY = normalRight[1] - mid[1]
- controlX = mid[0] + a11 * dX + a12 * dY
- controlY = mid[1] + a12 * dX + a22 * dY
- } else {
- controlX = pnt1[0] + t * (pnt2[0] - pnt1[0])
- controlY = pnt1[1] + t * (pnt2[1] - pnt1[1])
- }
- return [controlX, controlY]
- }
- /**
- * getBisectorNormals
- * @param t
- * @param pnt1
- * @param pnt2
- * @param pnt3
- * @returns {[*,*]}
- */
- getBisectorNormals(t, pnt1, pnt2, pnt3) {
- let normal = this.getNormal(pnt1, pnt2, pnt3)
- let [bisectorNormalRight, bisectorNormalLeft, dt, x, y] = [null, null, null, null, null]
- let dist = Math.sqrt(normal[0] * normal[0] + normal[1] * normal[1])
- let uX = normal[0] / dist
- let uY = normal[1] / dist
- let d1 = this.MathDistance(pnt1, pnt2)
- let d2 = this.MathDistance(pnt2, pnt3)
- if (dist > this.ZERO_TOLERANCE) {
- if (this.isClockWise(pnt1, pnt2, pnt3)) {
- dt = t * d1
- x = pnt2[0] - dt * uY
- y = pnt2[1] + dt * uX
- bisectorNormalRight = [x, y]
- dt = t * d2
- x = pnt2[0] + dt * uY
- y = pnt2[1] - dt * uX
- bisectorNormalLeft = [x, y]
- } else {
- dt = t * d1
- x = pnt2[0] + dt * uY
- y = pnt2[1] - dt * uX
- bisectorNormalRight = [x, y]
- dt = t * d2
- x = pnt2[0] - dt * uY
- y = pnt2[1] + dt * uX
- bisectorNormalLeft = [x, y]
- }
- } else {
- x = pnt2[0] + t * (pnt1[0] - pnt2[0])
- y = pnt2[1] + t * (pnt1[1] - pnt2[1])
- bisectorNormalRight = [x, y]
- x = pnt2[0] + t * (pnt3[0] - pnt2[0])
- y = pnt2[1] + t * (pnt3[1] - pnt2[1])
- bisectorNormalLeft = [x, y]
- }
- return [bisectorNormalRight, bisectorNormalLeft]
- }
- /**
- * 获取默认三点的内切圆
- * @param pnt1
- * @param pnt2
- * @param pnt3
- * @returns {[*,*]}
- */
- getNormal(pnt1, pnt2, pnt3) {
- let dX1 = pnt1[0] - pnt2[0]
- let dY1 = pnt1[1] - pnt2[1]
- let d1 = Math.sqrt(dX1 * dX1 + dY1 * dY1)
- dX1 /= d1
- dY1 /= d1
- let dX2 = pnt3[0] - pnt2[0]
- let dY2 = pnt3[1] - pnt2[1]
- let d2 = Math.sqrt(dX2 * dX2 + dY2 * dY2)
- dX2 /= d2
- dY2 /= d2
- let uX = dX1 + dX2
- let uY = dY1 + dY2
- return [uX, uY]
- }
- /**
- * 判断是否是顺时针
- * @param pnt1
- * @param pnt2
- * @param pnt3
- * @returns {boolean}
- */
- isClockWise(pnt1, pnt2, pnt3) {
- return ((pnt3[1] - pnt1[1]) * (pnt2[0] - pnt1[0]) > (pnt2[1] - pnt1[1]) * (pnt3[0] - pnt1[0]))
- }
- /**
- * 求取两个坐标的中间值
- * @param point1
- * @param point2
- * @returns {[*,*]}
- * @constructor
- */
- Mid(point1, point2) {
- return [(point1[0] + point2[0]) / 2, (point1[1] + point2[1]) / 2]
- }
- /**
- * 计算两个坐标之间的距离
- * @ignore
- * @param pnt1
- * @param pnt2
- * @returns {number}
- * @constructor
- */
- MathDistance(pnt1, pnt2) {
- return (Math.sqrt(Math.pow((pnt1[0] - pnt2[0]), 2) + Math.pow((pnt1[1] - pnt2[1]), 2)))
- }
- /**
- * 获取右边控制点
- * @param controlPoints
- * @param t
- * @returns {[*,*]}
- */
- getRightMostControlPoint(controlPoints, t) {
- let count = controlPoints.length
- let pnt1 = controlPoints[count - 3]
- let pnt2 = controlPoints[count - 2]
- let pnt3 = controlPoints[count - 1]
- let pnts = this.getBisectorNormals(0, pnt1, pnt2, pnt3)
- let normalLeft = pnts[1]
- let normal = this.getNormal(pnt1, pnt2, pnt3)
- let dist = Math.sqrt(normal[0] * normal[0] + normal[1] * normal[1])
- let [controlX, controlY] = [null, null]
- if (dist > this.ZERO_TOLERANCE) {
- let mid = this.Mid(pnt2, pnt3)
- let pX = pnt3[0] - mid[0]
- let pY = pnt3[1] - mid[1]
- let d1 = this.MathDistance(pnt2, pnt3)
- let n = 2.0 / d1
- let nX = -n * pY
- let nY = n * pX
- let a11 = nX * nX - nY * nY
- let a12 = 2 * nX * nY
- let a22 = nY * nY - nX * nX
- let dX = normalLeft[0] - mid[0]
- let dY = normalLeft[1] - mid[1]
- controlX = mid[0] + a11 * dX + a12 * dY
- controlY = mid[1] + a12 * dX + a22 * dY
- } else {
- controlX = pnt3[0] + t * (pnt2[0] - pnt3[0])
- controlY = pnt3[1] + t * (pnt2[1] - pnt3[1])
- }
- return [controlX, controlY]
- }
- /**
- * 获取立方值
- * @param t
- * @param startPnt
- * @param cPnt1
- * @param cPnt2
- * @param endPnt
- * @returns {[*,*]}
- */
- getCubicValue(t, startPnt, cPnt1, cPnt2, endPnt) {
- t = Math.max(Math.min(t, 1), 0)
- let [tp, t2] = [(1 - t), (t * t)]
- let t3 = t2 * t
- let tp2 = tp * tp
- let tp3 = tp2 * tp
- let x = (tp3 * startPnt[0]) + (3 * tp2 * t * cPnt1[0]) + (3 * tp * t2 * cPnt2[0]) + (t3 * endPnt[0])
- let y = (tp3 * startPnt[1]) + (3 * tp2 * t * cPnt1[1]) + (3 * tp * t2 * cPnt2[1]) + (t3 * endPnt[1])
- return [x, y]
- }
- }
- export default DrawCurve
|