123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- /* 引入Cesium */
- // import * as Cesium from 'Cesium';
- const BD_FACTOR = (3.14159265358979324 * 3000.0) / 180.0;
- const PI = 3.1415926535897932384626;
- const RADIUS = 6378245.0;
- const EE = 0.00669342162296594323;
- /**
- * 坐标转换
- */
- class CoordTransform {
- /**
- * 百度坐标系转||BD-09 To GCJ-02
- * @ignore 忽略注释,注释不生成Doc
- * @param lng
- * @param lat
- * @returns {number[]}
- */
- static BD09ToGCJ02(lng, lat) {
- let x = +lng - 0.0065
- let y = +lat - 0.006
- let z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * BD_FACTOR)
- let theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * BD_FACTOR)
- let gg_lng = z * Math.cos(theta)
- let gg_lat = z * Math.sin(theta)
- return [gg_lng, gg_lat];
- }
- /**
- * GCJ-02 To BD-09
- * @ignore 忽略注释,注释不生成Doc
- * @param lng
- * @param lat
- * @returns {number[]}
- * @constructor
- */
- static GCJ02ToBD09(lng, lat) {
- lat = +lat
- lng = +lng
- let z =
- Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * BD_FACTOR)
- let theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * BD_FACTOR)
- let bd_lng = z * Math.cos(theta) + 0.0065
- let bd_lat = z * Math.sin(theta) + 0.006
- return [bd_lng, bd_lat]
- }
- /**
- * WGS-84 To GCJ-02
- * @ignore 忽略注释,注释不生成Doc
- * @param lng
- * @param lat
- * @returns {number[]}
- */
- static WGS84ToGCJ02(lng, lat) {
- lat = +lat
- lng = +lng
- if (this.out_of_china(lng, lat)) {
- return [lng, lat]
- } else {
- let d = this.delta(lng, lat)
- return [lng + d[0], lat + d[1]]
- }
- }
- /**
- * GCJ-02 To WGS-84
- * @ignore 忽略注释,注释不生成Doc
- * @param lng
- * @param lat
- * @returns {number[]}
- * @constructor
- */
- static GCJ02ToWGS84(lng, lat) {
- lat = +lat
- lng = +lng
- if (this.out_of_china(lng, lat)) {
- return [lng, lat]
- } else {
- let d = this.delta(lng, lat)
- let mgLng = lng + d[0]
- let mgLat = lat + d[1]
- return [lng * 2 - mgLng, lat * 2 - mgLat]
- }
- }
- /**
- * @ignore 忽略注释,注释不生成Doc
- * @param lng
- * @param lat
- * @returns {number[]}
- */
- static delta(lng, lat) {
- let dLng = this.transformLng(lng - 105, lat - 35)
- let dLat = this.transformLat(lng - 105, lat - 35)
- const radLat = (lat / 180) * PI
- let magic = Math.sin(radLat)
- magic = 1 - EE * magic * magic
- const sqrtMagic = Math.sqrt(magic)
- dLng = (dLng * 180) / ((RADIUS / sqrtMagic) * Math.cos(radLat) * PI)
- dLat = (dLat * 180) / (((RADIUS * (1 - EE)) / (magic * sqrtMagic)) * PI)
- return [dLng, dLat]
- }
- /**
- * @ignore 忽略注释,注释不生成Doc
- * @param lng
- * @param lat
- * @returns {number}
- */
- static transformLng(lng, lat) {
- lat = +lat
- lng = +lng
- let ret =
- 300.0 +
- lng +
- 2.0 * lat +
- 0.1 * lng * lng +
- 0.1 * lng * lat +
- 0.1 * Math.sqrt(Math.abs(lng))
- ret +=
- ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) *
- 2.0) /
- 3.0
- ret +=
- ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) * 2.0) /
- 3.0
- ret +=
- ((150.0 * Math.sin((lng / 12.0) * PI) +
- 300.0 * Math.sin((lng / 30.0) * PI)) *
- 2.0) /
- 3.0
- return ret
- }
- /**
- * @ignore 忽略注释,注释不生成Doc
- * @param lng
- * @param lat
- * @returns {number}
- */
- static transformLat(lng, lat) {
- lat = +lat
- lng = +lng
- let ret = -100.0 +
- 2.0 * lng +
- 3.0 * lat +
- 0.2 * lat * lat +
- 0.1 * lng * lat +
- 0.2 * Math.sqrt(Math.abs(lng))
- ret +=
- ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) *
- 2.0) /
- 3.0
- ret +=
- ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) * 2.0) /
- 3.0
- ret +=
- ((160.0 * Math.sin((lat / 12.0) * PI) +
- 320 * Math.sin((lat * PI) / 30.0)) *
- 2.0) /
- 3.0
- return ret
- }
- /**
- * @ignore 忽略注释,注释不生成Doc
- * @param lng
- * @param lat
- * @returns {boolean}
- */
- static out_of_china(lng, lat) {
- lat = +lat
- lng = +lng
- return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55)
- }
- /**
- * 获取Catesian3坐标
- */
- static getCatesian3FromPX(viewer, px) {
- let picks = viewer.scene.drillPick(px);
- let cartesian = null;
- let isOn3dtiles = false,
- isOnTerrain = false;
- // drillPick
- for (let i in picks) {
- let pick = picks[i];
- if (
- (pick && pick.primitive instanceof Cesium.Cesium3DTileFeature) ||
- (pick && pick.primitive instanceof Cesium.Cesium3DTileset) ||
- (pick && pick.primitive instanceof Cesium.Model)
- ) {
- //模型上拾取
- isOn3dtiles = true;
- }
- // 3dtilset
- if (isOn3dtiles) {
- viewer.scene.pick(px); // pick
- cartesian = viewer.scene.pickPosition(px);
- if (cartesian) {
- let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
- if (cartographic.height < 0) cartographic.height = 0;
- let lon = Cesium.Math.toDegrees(cartographic.longitude),
- lat = Cesium.Math.toDegrees(cartographic.latitude),
- height = cartographic.height;
- cartesian = this.transformWGS84ToCartesian({
- lng: lon,
- lat: lat,
- alt: height,
- });
- }
- }
- }
- // 地形
- let boolTerrain = viewer.terrainProvider instanceof Cesium.EllipsoidTerrainProvider;
- // Terrain
- if (!isOn3dtiles && !boolTerrain) {
- let ray = viewer.scene.camera.getPickRay(px);
- if (!ray) return null;
- cartesian = viewer.scene.globe.pick(ray, viewer.scene);
- isOnTerrain = true;
- }
- // 地球
- if (!isOn3dtiles && !isOnTerrain && boolTerrain) {
- cartesian = viewer.scene.camera.pickEllipsoid(
- px,
- viewer.scene.globe.ellipsoid
- );
- }
- if (cartesian) {
- let position = this.transformCartesianToWGS84(cartesian);
- if (position.alt < 0) {
- cartesian = this.transformWGS84ToCartesian(position, 0.1);
- }
- return cartesian;
- }
- return false;
- }
- /**
- * 坐标转换 84转笛卡尔
- * @ignore 忽略注释,注释不生成Doc
- * @param {object} position - {lng,lat,alt} 地理坐标
- * @param {number} alt - 高度
- * @returns {object} Cartesian3 笛卡尔坐标
- */
- static transformWGS84ToCartesian(position, alt) {
- return position ?
- Cesium.Cartesian3.fromDegrees(
- position.lng || position.lon,
- position.lat,
- (position.alt = alt || position.alt),
- Cesium.Ellipsoid.WGS84
- ) :
- Cesium.Cartesian3.ZERO
- }
- /**
- * 坐标转换 笛卡尔转84
- * @ignore 忽略注释,注释不生成Doc
- * @param {object} cartesian - 笛卡尔坐标
- * @returns {object} - {lng,lat,alt} 地理坐标
- */
- static transformCartesianToWGS84(cartesian) {
- let ellipsoid = Cesium.Ellipsoid.WGS84
- let cartographic = ellipsoid.cartesianToCartographic(cartesian)
- return {
- lng: Cesium.Math.toDegrees(cartographic.longitude),
- lat: Cesium.Math.toDegrees(cartographic.latitude),
- alt: cartographic.height
- }
- }
- /**
- * 笛卡尔坐标数组转WGS84
- * @param {Array} cartesianList 笛卡尔坐标数组
- * @returns {Array} WGS84经纬度坐标数组
- */
- static Cartesian3ListToWGS84(cartesianList) {
- let ellipsoid = Cesium.Ellipsoid.WGS84;
- let result = [];
- for (let index = 0; index < cartesianList.length; index++) {
- const cartesian = cartesianList[index];
- let cartographic = ellipsoid.cartesianToCartographic(cartesian);
- result.push({
- lng: Cesium.Math.toDegrees(cartographic.longitude),
- lat: Cesium.Math.toDegrees(cartographic.latitude),
- alt: cartographic.height,
- });
- }
- return result;
- }
- /**
- * 度(十进制)转度分秒
- * @param {Number} value 十进制度
- */
- static Degrees2DMS(value) {
- let degrees = Math.floor(value); //根据“floor”的字面意思“地板”去理解;舍小数位
- let rem = (value - degrees) * 60;
- let minutes = Math.floor(rem);
- let _second = (rem - minutes) * 60;
- // let seconds = Math.ceil(_second); //根据“ceil”的字面意思“天花板”去理解;进小数位
- let seconds = Math.round(_second); //(小数点后第一位)大于五全部加,等于五正数加,小于五全不加。
- var _radians = Cesium.Math.toRadians(value); //经纬度转弧度
- var _degrees = Cesium.Math.toDegrees(value); //弧度转经纬度
- console.log(_radians)
- console.log(_degrees)
- let DMS = {
- degrees: degrees,
- minutes: minutes,
- seconds: seconds
- };
- return DMS;
- }
- /**
- * 度分秒转度(十进制)
- * @param {Object} DMS 度分秒对象
- * @param {Object} DMS.degrees 度
- * @param {Object} DMS.minutes 分
- * @param {Object} DMS.seconds 秒
- */
- static DMS2Degrees(DMS) {
- let _double = parseFloat(DMS.degrees) + parseFloat(DMS.minutes) / 60 + parseFloat(DMS.seconds) / 3600;
- return parseFloat(_double).toFixed(6);
- }
-
- /**
- * 世界坐标转换为经纬度坐标
- * @ignore 生成方法时不对外公开
- * @param {Cesium.Cartesian3} position 点
- */
- static _cartesian3ToGeo(position) {
- let g = Cesium.Ellipsoid.WGS84.cartesianToCartographic(position);
- return {
- longitude: Cesium.Math.toDegrees(g.longitude),
- latitude: Cesium.Math.toDegrees(g.latitude),
- height: g.height,
- }
- }
-
- /**
- * 弧度转度
- * @ignore
- * @param {Number} arc 弧度
- * @return {Number} 角度
- */
- static _arcToDegree(arc) {
- return arc / Math.PI * 180;
- }
-
- /**
- * 根据地形或实景或模型检测当前屏幕位置的经纬度及高度
- * @ignore
- * @param {JSON} screenPoint 屏幕坐标
- * @param {Number} screenPoint.x 屏幕坐标x
- * @param {Number} screenPoint.y 屏幕坐标y
- * @return {JSON} 位置信息{lng,lat,height}
- */
- static _getScreenClickPositionAndHeight(viewer,screenPoint) {
- this._viewer=viewer;
-
- var lng = undefined,
- lat = undefined,
- height = undefined;
-
- /* 从相机位置到 windowPosition 处的像素创建射线在世界坐标系中 */
- var ray = this._viewer.scene.camera.getPickRay(screenPoint);
- /* 找到射线与渲染的地球表面之间的交点 */
- var position = this._viewer.scene.globe.pick(ray, this._viewer.scene);
- /* 获取地理位置的制图表达 */
- var cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(position);
-
- /* 查询屏幕位置的要素 */
- var feature = this._viewer.scene.pick(screenPoint);
- if (feature == undefined) {
- lng = this._arcToDegree(cartographic.longitude);
- lat = this._arcToDegree(cartographic.latitude);
- height = cartographic.height;
- } else {
- var cartesian = this._viewer.scene.pickPosition(screenPoint);
- if (Cesium.defined(cartesian)) {
- var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
- lng = this._arcToDegree(cartographic.longitude);
- lat = this._arcToDegree(cartographic.latitude);
- height = cartographic.height;
- }
- }
- /* 返回结果 */
- return {
- lng: lng,
- lat: lat,
- height: height,
- }
- }
-
- /**
- * 屏幕位置转换为经纬度位置及空间位置
- * @ignore
- * @param {Object} viewer 三维场景
- * @param {Cesium.Cartesian2} screenPosition 屏幕位置
- * @return {JSON} 经纬度位置及空间位置
- */
- static _transfromFromScreenPoint(viewer,screenPosition) {
- /* 根据屏幕位置获取经度、纬度和高度信息 */
- let location = this._getScreenClickPositionAndHeight(viewer,screenPosition);
- /* 经纬度位置转换为三维坐标 */
- var cartesian = Cesium.Cartesian3.fromDegrees(location.lng, location.lat, location.height);
- /* 返回 */
- return {
- gLocation: location,
- sLocation: cartesian,
- }
- }
- }
- export default CoordTransform;
|