123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599 |
- import {
- createTooltip
- } from "../../../common/common.js";
- import {
- isRuntimeApp,
- isRuntimeWeb,
- createOperationMainDom,
- showTooltipMessage
- } from "../../../common/RuntimeEnvironment.js";
- // 闭合曲面
- class DrawClosedCurve {
- constructor(arg) {
- this.viewer = arg.viewer;
- this.Cesium = arg.Cesium;
- this.floatingPoint = null; //标识点
- this._ClosedCurve = null; //活动闭合曲面
- this._ClosedCurveLast = null; //最后一个闭合曲面
- this._positions = []; //活动点
- this._entities_point = []; //脏数据
- this._entities_ClosedCurve = []; //脏数据
- this._ClosedCurveData = null; //用于构造闭合曲面数据
- this.ZERO_TOLERANCE = 0.0001;
- this.FITTING_COUNT = 100;
- this.t = 0.3
- this.objId = Number((new Date()).getTime() + "" + Number(Math.random() * 1000).toFixed(0));
- this.DrawStartEvent = new Cesium.Event(); //开始绘制事件
- this.DrawEndEvent = new Cesium.Event(); //结束绘制事件
- this._tooltip = createTooltip(this.viewer.container);
- /* 通用参数集合 */
- 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 ClosedCurve() {
- return this._ClosedCurveLast;
- }
- //返回闭合曲面数据用于加载闭合曲面
- getData() {
- return this._ClosedCurveData;
- }
- // 修改编辑调用计算
- computePosition(data) {
- let $this = this;
- if (data.length < 2) return
- let pnts = []
- for (let p = 0; p < data.length; p++) {
- pnts.push($this.cartesianToLatlng(data[p]))
- }
- this._ClosedCurveData = Array.from(pnts);
- pnts.push(pnts[0], pnts[1])
- let [normals, pList] = [
- [],
- []
- ]
- for (let i = 0; i < pnts.length - 2; i++) {
- let normalPoints = $this.getBisectorNormals($this.t, pnts[i], pnts[i + 1], pnts[i + 2])
- normals = normals.concat(normalPoints)
- }
- let count = normals.length
- normals = [normals[count - 1]].concat(normals.slice(0, count - 1))
- for (let i = 0; i < pnts.length - 2; i++) {
- let pnt1 = pnts[i]
- let pnt2 = pnts[i + 1]
- pList.push($this.LatlngTocartesian(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)
- pList.push($this.LatlngTocartesian(pnt))
- }
- pList.push($this.LatlngTocartesian(pnt2))
- }
- let PolygonHierarchy = new $this.Cesium.PolygonHierarchy(pList);
- return {
- PolygonHierarchy,
- pList
- }
- }
- //加载闭合曲面
- addload(data) {
- let $this = this
- if (data.length < 2) return
- let pnts = Array.from(data);
- pnts.push(pnts[0], pnts[1])
- let [normals, pList] = [
- [],
- []
- ]
- for (let i = 0; i < pnts.length - 2; i++) {
- let normalPoints = $this.getBisectorNormals($this.t, pnts[i], pnts[i + 1], pnts[i + 2])
- normals = normals.concat(normalPoints)
- }
- let count = normals.length
- normals = [normals[count - 1]].concat(normals.slice(0, count - 1))
- for (let i = 0; i < pnts.length - 2; i++) {
- let pnt1 = pnts[i]
- let pnt2 = pnts[i + 1]
- pList.push($this.LatlngTocartesian(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)
- pList.push($this.LatlngTocartesian(pnt))
- }
- pList.push($this.LatlngTocartesian(pnt2))
- }
- console.log(data, pnts)
- var arrowEntity = $this.viewer.entities.add({
- Type: 'DrawClosedCurve',
- Position: data,
- id: data.id || $this.objId,
- polygon: {
- hierarchy: new $this.Cesium.PolygonHierarchy(pList),
- show: true,
- fill: true,
- clampToGround: true,
- material: $this.polygonMaterial
- },
- polyline: {
- positions: pList,
- show: true,
- material: new Cesium.PolylineDashMaterialProperty({
- color: Cesium.Color.YELLOW,
- }),
- width: 3,
- clampToGround: true
- }
- });
- return arrowEntity;
- }
- //开始创建
- startCreate(drawType) {
- if (isRuntimeApp()) {
- showTooltipMessage("点击开始绘制");
- }
- var $this = this;
- this.drawType = drawType;
- this.handler = new this.Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
- //单击开始绘制
- this.handler.setInputAction(function(evt) {
- if (isRuntimeApp()) {
- //屏幕坐标转地形上坐标
- var cartesian = $this.getCatesian3FromPX(evt.position);
- if (!cartesian) {
- return;
- }
- $this.createPoint(cartesian); // 绘制点
- $this._positions.push(cartesian);
- if ($this._positions.length > 2) {
- showTooltipMessage("点击添加点,点击完成按钮,结束绘制");
- if ($this._positions.length === 3) {
-
- if (!$this.Cesium.defined($this._ClosedCurve)) {
- $this._ClosedCurve = $this.createClosedCurve();
- //创建按钮
- createOperationMainDom();
- //隐藏回退按钮
- document.getElementById("btnDrawBackout").style.display = 'none';
- //完成绘制
- document.getElementById("btnDrawComplete").onclick = () => {
- $this._ClosedCurveData = $this._positions.concat();
- $this.viewer.entities.remove($this._ClosedCurve); //移除
- $this._ClosedCurve = null;
- $this._positions = [];
- var lnglatArr = [];
- for (var i = 0; i < $this._ClosedCurveData.length; i++) {
- var lnglat = $this.cartesianToLatlng($this._ClosedCurveData[i]);
- lnglatArr.push(lnglat)
- }
- $this._ClosedCurveData = lnglatArr;
- var ClosedCurve = $this.addload(lnglatArr); //加载
- $this._entities_ClosedCurve.push(ClosedCurve);
- $this._ClosedCurveLast = ClosedCurve;
- $this.clearPoint();
- $this.destroy();
- let buttonDiv = document.getElementById("drawButtonDiv");
- if (buttonDiv) {
- //从页面移除
- document.body.removeChild(buttonDiv);
- }
- }
- }
- }
- } else {
- showTooltipMessage("点击添加点");
- }
- } else {
- console.log('监听鼠标事件', '单击')
- /* 锁定点击事件 以免和双击事件冲突 */
- clearTimeout($this._timer);
- $this._timer = setTimeout(function() {
- //屏幕坐标转地形上坐标
- var cartesian = $this.getCatesian3FromPX(evt.position);
- if ($this._positions.length == 0) {
- $this.floatingPoint = $this.createPoint(cartesian);
- }
- $this._positions.push(cartesian);
- $this.createPoint(cartesian);
- }, 200);
- }
- }, $this.Cesium.ScreenSpaceEventType.LEFT_CLICK);
- //移动时绘制面
- this.handler.setInputAction(function(evt) {
- /* 如果运行环境是App 则禁止使用鼠标移动事件 */
- if (isRuntimeApp()) return;
- if ($this._positions.length == 0) {
- $this._tooltip.showAt(evt.endPosition, "点击开始绘制");
- } else {
- $this._tooltip.showAt(evt.endPosition, "点击添加点");
- }
- if ($this._positions.length < 2) return;
- $this._tooltip.showAt(evt.endPosition, "点击添加点,双击结束绘制");
- var cartesian = $this.getCatesian3FromPX(evt.endPosition);
- if ($this._positions.length == 2) {
- $this._positions.push(cartesian);
- }
- $this._positions.pop();
- $this._positions.push(cartesian);
- if (!$this.Cesium.defined($this._ClosedCurve)) {
- $this._ClosedCurve = $this.createClosedCurve();
- }
- }, $this.Cesium.ScreenSpaceEventType.MOUSE_MOVE);
- //右击停止采集改为双击结束
- this.handler.setInputAction(function(evt) {
- // if (!$this._ClosedCurve) return;
- // var cartesian = $this.getCatesian3FromPX(evt.position);
- // $this._positions.pop();
- // $this._positions.push(cartesian);
- // $this._ClosedCurveData = $this._positions.concat();
- // $this.viewer.entities.remove($this._ClosedCurve); //移除
- // $this._ClosedCurve = null;
- // $this._positions = [];
- // $this.floatingPoint.position.setValue(cartesian);
- // var lnglatArr = [];
- // for (var i = 0; i < $this._ClosedCurveData.length; i++) {
- // var lnglat = $this.cartesianToLatlng($this._ClosedCurveData[i]);
- // lnglatArr.push(lnglat)
- // }
- // $this._ClosedCurveData = lnglatArr;
- // var ClosedCurve = $this.addload(lnglatArr); //加载
- // $this._entities_ClosedCurve.push(ClosedCurve);
- // $this._ClosedCurveLast = ClosedCurve;
- // $this.clearPoint();
- // $this.destroy()
- }, $this.Cesium.ScreenSpaceEventType.RIGHT_CLICK);
- //双击结束
- this.handler.setInputAction(function(evt) {
- /* 如果运行环境是App 则禁止使用鼠标双击事件 */
- if (isRuntimeApp()) return;
- console.log('监听鼠标事件', '双击')
- /* 解除锁定 */
- clearTimeout($this._timer);
- if (!$this._ClosedCurve) return;
- var cartesian = $this.getCatesian3FromPX(evt.position);
- $this._positions.pop();
- $this._positions.push(cartesian);
- $this._ClosedCurveData = $this._positions.concat();
- $this.viewer.entities.remove($this._ClosedCurve); //移除
- $this._ClosedCurve = null;
- $this._positions = [];
- $this.floatingPoint.position.setValue(cartesian);
- var lnglatArr = [];
- for (var i = 0; i < $this._ClosedCurveData.length; i++) {
- var lnglat = $this.cartesianToLatlng($this._ClosedCurveData[i]);
- lnglatArr.push(lnglat)
- }
- $this._ClosedCurveData = lnglatArr;
- var ClosedCurve = $this.addload(lnglatArr); //加载
- $this._entities_ClosedCurve.push(ClosedCurve);
- $this._ClosedCurveLast = ClosedCurve;
- $this.clearPoint();
- $this.destroy();
- $this._tooltip.setVisible(false);
- }, $this.Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
- }
- //创建直线闭合曲面
- createClosedCurve() {
- // console.log(this._positions)
- var $this = this;
- $this.pLists = ''
- var arrowEntity = $this.viewer.entities.add({
- polygon: {
- hierarchy: new $this.Cesium.CallbackProperty(
- function() {
- if ($this._positions.length < 2) return
- let pnts = []
- for (let p = 0; p < $this._positions.length; p++) {
- pnts.push($this.cartesianToLatlng($this._positions[p]))
- }
- pnts.push(pnts[0], pnts[1])
- let [normals, pList] = [
- [],
- []
- ]
- for (let i = 0; i < pnts.length - 2; i++) {
- let normalPoints = $this.getBisectorNormals($this.t, pnts[i], pnts[i + 1], pnts[i + 2])
- normals = normals.concat(normalPoints)
- }
- let count = normals.length
- normals = [normals[count - 1]].concat(normals.slice(0, count - 1))
- for (let i = 0; i < pnts.length - 2; i++) {
- let pnt1 = pnts[i]
- let pnt2 = pnts[i + 1]
- pList.push($this.LatlngTocartesian(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)
- pList.push($this.LatlngTocartesian(pnt))
- }
- pList.push($this.LatlngTocartesian(pnt2))
- }
- $this.pLists = pList
- return new $this.Cesium.PolygonHierarchy(pList);
- }, false),
- show: true,
- fill: true,
- clampToGround: true,
- material: $this.polygonMaterial
- },
- polyline: {
- positions: new $this.Cesium.CallbackProperty(
- function() {
- return $this.pLists
- }, false
- ),
- show: true,
- material: new Cesium.PolylineDashMaterialProperty({
- color: Cesium.Color.YELLOW,
- }),
- width: 3,
- clampToGround: true
- }
- })
- $this._entities_ClosedCurve.push(arrowEntity);
- return arrowEntity
- }
- //创建点
- 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;
- }
- /**
- * 世界坐标转经纬度
- */
- 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];
- }
- //销毁
- destroy() {
- if (this.handler) {
- this.handler.destroy();
- this.handler = null;
- }
- }
- clearPoint() {
- this.DrawEndEvent.raiseEvent(this._ClosedCurveLast, this._ClosedCurveData);
- for (var i = 0; i < this._entities_point.length; i++) {
- this.viewer.entities.remove(this._entities_point[i]);
- }
- this._entities_point = []; //脏数据
- }
- //清空实体对象
- 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_ClosedCurve.length; i++) {
- this.viewer.entities.remove(this._entities_ClosedCurve[i]);
- }
- this.floatingPoint = null; //标识点
- this._ClosedCurve = null; //活动闭合曲面
- this._ClosedCurveLast = null; //最后一个闭合曲面
- this._positions = []; //活动点
- this._entities_point = []; //脏数据
- this._entities_ClosedCurve = []; //脏数据
- this._ClosedCurveData = 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;
- }
- // 求取闭合曲面坐标函数/
- //闭合曲面配置函数
- /**
- * getBisectorNormals
- * @param t
- * @param pnt1
- * @param pnt2
- * @param pnt3
- * @returns {[*,*]}
- */
- getBisectorNormals(t, pnt1, pnt2, pnt3) {
- let $this = this
- 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]
- }
- /**
- * 计算两个坐标之间的距离
- * @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 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 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 DrawClosedCurve
|