DrawCurveFlag.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. // DrawCurveFlag
  2. /*
  3. 绘制曲线旗标
  4. */
  5. class DrawCurveFlag {
  6. constructor(arg) {
  7. this.viewer = arg.viewer;
  8. this.Cesium = arg.Cesium;
  9. this.identificationPoint = null; //标识点位
  10. this.CurveFlag = null;
  11. this.CurveFlagLast = null; // 曲线旗标数据
  12. this.positions = []; // 经纬度
  13. this.entitiesPoint = []; // 实体点位
  14. this.entitiesCurveFlag = [];
  15. this.CurveFlagData = null;
  16. this.DrawStartEvent = new Cesium.Event(); //开始绘制事件
  17. this.DrawEndEvent = new Cesium.Event(); //结束绘制事件
  18. /* 通用参数集合 */
  19. this._param = {
  20. id: "DrawStraightArrow",
  21. polygonColor: 'rgba(0,255,0,0.5)', //面填充颜色
  22. outlineColor: 'rgba(255, 255, 255, 1)', //边框颜色
  23. outlineWidth: 1, //边框宽度
  24. }
  25. /* 创建面材质 */
  26. this.polygonMaterial = Cesium.Color.fromCssColorString(this._param.polygonColor);
  27. /* 创建线材质 */
  28. // this.outlineMaterial = new Cesium.PolylineDashMaterialProperty({//曲线
  29. // dashLength: 16,
  30. // color: Cesium.Color.fromCssColorString(this._param.outlineColor)
  31. // });
  32. this.outlineMaterial = Cesium.Color.fromCssColorString(this._param.outlineColor);
  33. }
  34. //返回曲线旗标数据
  35. getData() {
  36. return this.CurveFlagData;
  37. }
  38. // 修改编辑调用计算
  39. computePosition(data){
  40. //计算面
  41. let $this = this
  42. var lnglatArr = [];
  43. for (var i = 0; i < data.length; i++) {
  44. var lnglat = $this.cartesianToLatlng(data[i]);
  45. lnglatArr.push(lnglat)
  46. }
  47. // 取第一个
  48. let startPoint = lnglatArr[0]
  49. // 取最后一个
  50. let endPoint =lnglatArr[lnglatArr.length - 1]
  51. // 上曲线起始点
  52. let point1 = startPoint
  53. // 上曲线第一控制点
  54. let point2 = [(endPoint[0] - startPoint[0]) / 4 + startPoint[0], (endPoint[1] - startPoint[1]) / 8 + startPoint[1]]
  55. // 上曲线第二个点
  56. let point3 = [(startPoint[0] + endPoint[0]) / 2, startPoint[1]]
  57. // 上曲线第二控制点
  58. let point4 = [(endPoint[0] - startPoint[0]) * 3 / 4 + startPoint[0], -(endPoint[1] - startPoint[1]) / 8 + startPoint[1]]
  59. // 上曲线结束点
  60. let point5 = [endPoint[0], startPoint[1]]
  61. // 下曲线结束点
  62. let point6 = [endPoint[0], (startPoint[1] + endPoint[1]) / 2]
  63. // 下曲线第二控制点
  64. let point7 = [(endPoint[0] - startPoint[0]) * 3 / 4 + startPoint[0], (endPoint[1] - startPoint[1]) * 3 / 8 + startPoint[1]]
  65. // 下曲线第二个点
  66. let point8 = [(startPoint[0] + endPoint[0]) / 2, (startPoint[1] + endPoint[1]) / 2]
  67. // 下曲线第一控制点
  68. let point9 = [(endPoint[0] - startPoint[0]) / 4 + startPoint[0], (endPoint[1] - startPoint[1]) * 5 / 8 + startPoint[1]]
  69. // 下曲线起始点
  70. let point10 = [startPoint[0], (startPoint[1] + endPoint[1]) / 2]
  71. // 旗杆底部点
  72. let point11 = [startPoint[0], endPoint[1]]
  73. // 计算上曲线
  74. let curve1 = $this.getBezierPoints([point1, point2, point3, point4, point5])
  75. // 计算下曲线
  76. let curve2 = $this.getBezierPoints([point6, point7, point8, point9, point10])
  77. // 面合并
  78. let componentspolygon = [];
  79. componentspolygon = curve1.concat(curve2)
  80. let PolygonHierarchy = new $this.Cesium.PolygonHierarchy(componentspolygon)
  81. // 线边合并
  82. let componentspolyline = [];
  83. componentspolyline = curve1.concat(curve2)
  84. componentspolyline.push($this.LatlngTocartesian(point1))
  85. componentspolyline.push($this.LatlngTocartesian(point11))
  86. $this.CurveFlagData = lnglatArr;
  87. return [PolygonHierarchy,componentspolyline];
  88. }
  89. //加载
  90. addload(data) {
  91. var $this = this;
  92. if (data.length < 2) return;
  93. // 取第一个
  94. let startPoint = data[0]
  95. // 取最后一个
  96. let endPoint =data[data.length - 1]
  97. // 上曲线起始点
  98. let point1 = startPoint
  99. // 上曲线第一控制点
  100. let point2 = [(endPoint[0] - startPoint[0]) / 4 + startPoint[0], (endPoint[1] - startPoint[1]) / 8 + startPoint[1]]
  101. // 上曲线第二个点
  102. let point3 = [(startPoint[0] + endPoint[0]) / 2, startPoint[1]]
  103. // 上曲线第二控制点
  104. let point4 = [(endPoint[0] - startPoint[0]) * 3 / 4 + startPoint[0], -(endPoint[1] - startPoint[1]) / 8 + startPoint[1]]
  105. // 上曲线结束点
  106. let point5 = [endPoint[0], startPoint[1]]
  107. // 下曲线结束点
  108. let point6 = [endPoint[0], (startPoint[1] + endPoint[1]) / 2]
  109. // 下曲线第二控制点
  110. let point7 = [(endPoint[0] - startPoint[0]) * 3 / 4 + startPoint[0], (endPoint[1] - startPoint[1]) * 3 / 8 + startPoint[1]]
  111. // 下曲线第二个点
  112. let point8 = [(startPoint[0] + endPoint[0]) / 2, (startPoint[1] + endPoint[1]) / 2]
  113. // 下曲线第一控制点
  114. let point9 = [(endPoint[0] - startPoint[0]) / 4 + startPoint[0], (endPoint[1] - startPoint[1]) * 5 / 8 + startPoint[1]]
  115. // 下曲线起始点
  116. let point10 = [startPoint[0], (startPoint[1] + endPoint[1]) / 2]
  117. // 旗杆底部点
  118. let point11 = [startPoint[0], endPoint[1]]
  119. // 计算上曲线
  120. let curve1 = $this.getBezierPoints([point1, point2, point3, point4, point5])
  121. // 计算下曲线
  122. let curve2 = $this.getBezierPoints([point6, point7, point8, point9, point10])
  123. // 合并
  124. let componentspolygon = [];
  125. componentspolygon = curve1.concat(curve2)
  126. let componentspolyline = [];
  127. componentspolyline = curve1.concat(curve2)
  128. componentspolyline.push($this.LatlngTocartesian(point1))
  129. componentspolyline.push($this.LatlngTocartesian(point11))
  130. var shape = this.viewer.entities.add({
  131. Type:'DrawCurveFlag',
  132. Position:data,
  133. id:data.id || $this.objId,
  134. polygon: {
  135. hierarchy: new $this.Cesium.PolygonHierarchy(componentspolygon),
  136. extrudedHeight: 1,
  137. material: $this.Cesium.Color.RED,
  138. },
  139. polyline: {
  140. //使用cesium的peoperty
  141. positions: componentspolyline,
  142. show: true,
  143. material: $this.Cesium.Color.YELLOW,
  144. width: 5,
  145. clampToGround: true
  146. }
  147. });
  148. $this.entitiesCurveFlag.push(shape);
  149. return shape;
  150. }
  151. //开始创建
  152. startCreate(drawType) {
  153. this.drawType = drawType;
  154. var $this = this;
  155. this.handler = new this.Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
  156. this.handler.setInputAction(function (evt) { //单机开始绘制
  157. //屏幕坐标转地形上坐标
  158. var cartesian = $this.getCatesian3FromPX(evt.position);
  159. if ($this.positions.length == 0) {
  160. $this.positions.push(cartesian.clone());
  161. $this.identificationPoint = $this.createPoint(cartesian);
  162. $this.createPoint(cartesian);// 绘制点
  163. $this.positions.push(cartesian);
  164. }
  165. // if ($this.positions.length == 2) {
  166. // $this.positions.push(cartesian);
  167. // }
  168. }, $this.Cesium.ScreenSpaceEventType.LEFT_CLICK);
  169. this.handler.setInputAction(function (evt) { //移动时绘制线
  170. if ($this.positions.length < 2) return;
  171. var cartesian = $this.getCatesian3FromPX(evt.endPosition);
  172. if (!$this.Cesium.defined($this.CurveFlag)) {
  173. $this.CurveFlag = $this.createCurveFlag();
  174. }
  175. $this.identificationPoint.position.setValue(cartesian);
  176. if ($this.CurveFlag) {
  177. $this.positions.pop();
  178. $this.positions.push(cartesian);
  179. }
  180. }, $this.Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  181. this.handler.setInputAction(function (evt) {
  182. if (!$this.CurveFlag) return;
  183. var cartesian = $this.getCatesian3FromPX(evt.position);
  184. $this.positions.pop();
  185. $this.positions.push(cartesian);
  186. $this.createPoint(cartesian);// 绘制点
  187. $this.CurveFlagData = $this.positions.concat();
  188. $this.viewer.entities.remove($this.CurveFlag); //移除
  189. $this.CurveFlag = null;
  190. $this.positions = [];
  191. $this.identificationPoint.position.setValue(cartesian);
  192. var lnglatArr = [];
  193. for (var i = 0; i < $this.CurveFlagData.length; i++) {
  194. var lnglat = $this.cartesianToLatlng($this.CurveFlagData[i]);
  195. lnglatArr.push(lnglat)
  196. }
  197. $this.CurveFlagData = lnglatArr;
  198. var CurveFlag = $this.addload([$this.CurveFlagData[0],$this.CurveFlagData[$this.CurveFlagData.length -1 ]]); //加载
  199. $this.entitiesCurveFlag.push(CurveFlag);
  200. $this.CurveFlagLast = CurveFlag;
  201. $this.clearPoint();
  202. $this.destroy()
  203. }, $this.Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  204. }
  205. //创建点
  206. createPoint(cartesian) {
  207. var $this = this;
  208. var point = this.viewer.entities.add({
  209. position: cartesian,
  210. point: {
  211. pixelSize: 10,
  212. color: $this.Cesium.Color.RED,
  213. heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
  214. }
  215. });
  216. $this.entitiesPoint.push(point);
  217. return point;
  218. }
  219. //创建曲线旗标
  220. createCurveFlag() {
  221. var $this = this;
  222. var polygon = this.viewer.entities.add({
  223. polygon: {
  224. hierarchy: new $this.Cesium.CallbackProperty(function () {
  225. if($this.positions.length < 2) return
  226. let lonlat = [];
  227. let components = [];
  228. let length = $this.positions.length
  229. for (let i=0; i<length; i++){
  230. lonlat.push($this.cartesianToLatlng($this.positions[i]))
  231. }
  232. // 取第一个
  233. let startPoint = lonlat[0]
  234. // 取最后一个
  235. let endPoint =lonlat[lonlat.length - 1]
  236. // 上曲线起始点
  237. let point1 = startPoint
  238. // 上曲线第一控制点
  239. let point2 = [(endPoint[0] - startPoint[0]) / 4 + startPoint[0], (endPoint[1] - startPoint[1]) / 8 + startPoint[1]]
  240. // 上曲线第二个点
  241. let point3 = [(startPoint[0] + endPoint[0]) / 2, startPoint[1]]
  242. // 上曲线第二控制点
  243. let point4 = [(endPoint[0] - startPoint[0]) * 3 / 4 + startPoint[0], -(endPoint[1] - startPoint[1]) / 8 + startPoint[1]]
  244. // 上曲线结束点
  245. let point5 = [endPoint[0], startPoint[1]]
  246. // 下曲线结束点
  247. let point6 = [endPoint[0], (startPoint[1] + endPoint[1]) / 2]
  248. // 下曲线第二控制点
  249. let point7 = [(endPoint[0] - startPoint[0]) * 3 / 4 + startPoint[0], (endPoint[1] - startPoint[1]) * 3 / 8 + startPoint[1]]
  250. // 下曲线第二个点
  251. let point8 = [(startPoint[0] + endPoint[0]) / 2, (startPoint[1] + endPoint[1]) / 2]
  252. // 下曲线第一控制点
  253. let point9 = [(endPoint[0] - startPoint[0]) / 4 + startPoint[0], (endPoint[1] - startPoint[1]) * 5 / 8 + startPoint[1]]
  254. // 下曲线起始点
  255. let point10 = [startPoint[0], (startPoint[1] + endPoint[1]) / 2]
  256. // 旗杆底部点
  257. let point11 = [startPoint[0], endPoint[1]]
  258. // 计算上曲线
  259. let curve1 = $this.getBezierPoints([point1, point2, point3, point4, point5])
  260. // 计算下曲线
  261. let curve2 = $this.getBezierPoints([point6, point7, point8, point9, point10])
  262. // 合并
  263. components = curve1.concat(curve2)
  264. // components.push(point11)
  265. // let components = $this.Cesium.Cartesian3.fromDegreesArray([...point0, ...point1, ...point2, ...point0])
  266. return new $this.Cesium.PolygonHierarchy(components);
  267. }, false),
  268. extrudedHeight: 1,
  269. material: $this.Cesium.Color.RED,
  270. },
  271. polyline: {
  272. //使用cesium的peoperty
  273. positions: new $this.Cesium.CallbackProperty(function () {
  274. if($this.positions.length < 2) return
  275. let lonlat = [];
  276. let components = [];
  277. let length = $this.positions.length
  278. for (let i=0; i<length; i++){
  279. lonlat.push($this.cartesianToLatlng($this.positions[i]))
  280. }
  281. // 取第一个
  282. let startPoint = lonlat[0]
  283. // 取最后一个
  284. let endPoint =lonlat[lonlat.length - 1]
  285. // 上曲线起始点
  286. let point1 = startPoint
  287. // 上曲线第一控制点
  288. let point2 = [(endPoint[0] - startPoint[0]) / 4 + startPoint[0], (endPoint[1] - startPoint[1]) / 8 + startPoint[1]]
  289. // 上曲线第二个点
  290. let point3 = [(startPoint[0] + endPoint[0]) / 2, startPoint[1]]
  291. // 上曲线第二控制点
  292. let point4 = [(endPoint[0] - startPoint[0]) * 3 / 4 + startPoint[0], -(endPoint[1] - startPoint[1]) / 8 + startPoint[1]]
  293. // 上曲线结束点
  294. let point5 = [endPoint[0], startPoint[1]]
  295. // 下曲线结束点
  296. let point6 = [endPoint[0], (startPoint[1] + endPoint[1]) / 2]
  297. // 下曲线第二控制点
  298. let point7 = [(endPoint[0] - startPoint[0]) * 3 / 4 + startPoint[0], (endPoint[1] - startPoint[1]) * 3 / 8 + startPoint[1]]
  299. // 下曲线第二个点
  300. let point8 = [(startPoint[0] + endPoint[0]) / 2, (startPoint[1] + endPoint[1]) / 2]
  301. // 下曲线第一控制点
  302. let point9 = [(endPoint[0] - startPoint[0]) / 4 + startPoint[0], (endPoint[1] - startPoint[1]) * 5 / 8 + startPoint[1]]
  303. // 下曲线起始点
  304. let point10 = [startPoint[0], (startPoint[1] + endPoint[1]) / 2]
  305. // 旗杆底部点
  306. let point11 = [startPoint[0], endPoint[1]]
  307. // 计算上曲线
  308. let curve1 = $this.getBezierPoints([point1, point2, point3, point4, point5])
  309. // 计算下曲线
  310. let curve2 = $this.getBezierPoints([point6, point7, point8, point9, point10])
  311. // 合并
  312. components = curve1.concat(curve2)
  313. components.push($this.LatlngTocartesian(point1))
  314. components.push($this.LatlngTocartesian(point11))
  315. return components
  316. }, false),
  317. show: true,
  318. material: $this.Cesium.Color.YELLOW,
  319. width: 5,
  320. clampToGround: true
  321. }
  322. });
  323. $this.entitiesCurveFlag.push(polygon);
  324. return polygon;
  325. }
  326. cartesianToLatlng(cartesian) {
  327. var latlng = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian);
  328. var lat = this.Cesium.Math.toDegrees(latlng.latitude);
  329. var lng = this.Cesium.Math.toDegrees(latlng.longitude);
  330. return [lng, lat];
  331. }
  332. LatlngTocartesian(latlng) {
  333. let cartesian3 = this.Cesium.Cartesian3.fromDegrees(latlng[0], latlng[1]);
  334. return cartesian3
  335. }
  336. clearPoint() {
  337. this.DrawEndEvent.raiseEvent(this.CurveFlagLast, [this.CurveFlagData[0],this.CurveFlagData[this.CurveFlagData.length -1 ]], this.drawType);
  338. for (var i = 0; i < this.entitiesPoint.length; i++) {
  339. this.viewer.entities.remove(this.entitiesPoint[i]);
  340. }
  341. this.entitiesPoint = []; //脏数据
  342. }
  343. //销毁
  344. destroy() {
  345. if (this.handler) {
  346. this.handler.destroy();
  347. this.handler = null;
  348. }
  349. }
  350. //清空实体对象
  351. clear() {
  352. for (var i = 0; i < this.entitiesPoint.length; i++) {
  353. this.viewer.entities.remove(this.entitiesPoint[i]);
  354. }
  355. for (var i = 0; i < this.entitiesCurveFlag.length; i++) {
  356. this.viewer.entities.remove(this.entitiesCurveFlag[i]);
  357. }
  358. this.identificationPoint = null; //标识点位
  359. this.CurveFlag = null;
  360. this.CurveFlagLast = null; // 曲线旗标数据
  361. this.positions = []; // 经纬度
  362. this.entitiesPoint = []; // 实体点位
  363. this.entitiesCurveFlag = [];
  364. this.CurveFlagData = null;
  365. }
  366. getCatesian3FromPX(px) {
  367. var cartesian;
  368. var ray = this.viewer.camera.getPickRay(px);
  369. if (!ray) return null;
  370. cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
  371. return cartesian;
  372. }
  373. // 贝塞尔曲线
  374. getBezierPoints (points) {
  375. let $this = this
  376. if (points.length <= 2) {
  377. return points
  378. } else {
  379. let bezierPoints = []
  380. let n = points.length - 1
  381. for (let t = 0; t <= 1; t += 0.01) {
  382. let [x, y] = [0, 0]
  383. for (let index = 0; index <= n; index++) {
  384. let factor = $this.getBinomialFactor(n, index)
  385. let a = Math.pow(t, index)
  386. let b = Math.pow((1 - t), (n - index))
  387. x += factor * a * b * points[index][0]
  388. y += factor * a * b * points[index][1]
  389. }
  390. bezierPoints.push($this.LatlngTocartesian([x, y]))
  391. }
  392. bezierPoints.push($this.LatlngTocartesian(points[n]))
  393. return bezierPoints
  394. }
  395. }
  396. /**
  397. * 获取二项分布
  398. * @param n
  399. * @param index
  400. * @returns {number}
  401. */
  402. getBinomialFactor(n, index) {
  403. return (this.getFactorial(n) / (this.getFactorial(index) * this.getFactorial(n - index)))
  404. }
  405. /**
  406. * 获取阶乘数据
  407. * @param n
  408. * @returns {number}
  409. */
  410. getFactorial (n) {
  411. let result = 1
  412. switch (n) {
  413. case (n <= 1):
  414. result = 1
  415. break
  416. case (n === 2):
  417. result = 2
  418. break
  419. case (n === 3):
  420. result = 6
  421. break
  422. case (n === 24):
  423. result = 24
  424. break
  425. case (n === 5):
  426. result = 120
  427. break
  428. default:
  429. for (let i = 1; i <= n; i++) {
  430. result *= i
  431. }
  432. break
  433. }
  434. return result
  435. }
  436. }
  437. export default DrawCurveFlag