年度变更建库软件5.0版本
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1205 lines
44 KiB

4 months ago
using ESRI.ArcGIS.Client.Geometry;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
namespace Kingo.Plugin.ProofManager.Common
{
public class CoordinateTrans
{
#region 四参数集合操作
/// <summary>
/// 初始化四参数
/// </summary>
/// <param name="dbHelper"></param>
public static void InitParams()
{
try
{
string selectSql = "SELECT * FROM TB_CSSZ";
DataTable dt = null;// Kingo.SanDiaoCheck.Common.CommonAPI.GetSystemTable(selectSql);
if (dt != null && dt.Rows.Count > 0)
{
ParamsEntity hcryEntity = null;
foreach (DataRow item in dt.Rows)
{
hcryEntity = new ParamsEntity();
hcryEntity.BSM = ObjectConvertOperate.ObjectToInt(item["BSM"]);
hcryEntity.XZQDM = ObjectConvertOperate.ObjectToString(item["XZQDM"]);
hcryEntity.X80OFFSET = ObjectConvertOperate.ObjectToDouble(item["X80OFFSET"]);
hcryEntity.X80ROTATE = ObjectConvertOperate.ObjectToDouble(item["X80ROTATE"]);
hcryEntity.X84OFFSET = ObjectConvertOperate.ObjectToDouble(item["X84OFFSET"]);
hcryEntity.X84ROTATE = ObjectConvertOperate.ObjectToDouble(item["X84ROTATE"]);
hcryEntity.Y80OFFSET = ObjectConvertOperate.ObjectToDouble(item["Y80OFFSET"]);
hcryEntity.Y80ROTATE = ObjectConvertOperate.ObjectToDouble(item["Y80ROTATE"]);
hcryEntity.Y84OFFSET = ObjectConvertOperate.ObjectToDouble(item["Y84OFFSET"]);
hcryEntity.Y84ROTATE = ObjectConvertOperate.ObjectToDouble(item["Y84ROTATE"]);
hcryEntity.DH = ObjectConvertOperate.ObjectToString(item["DH"]);
AddOrUpdateParams(hcryEntity);
}
}
}
catch (Exception ex)
{
}
}
/// <summary>
/// 四参数集合
/// </summary>
private static Dictionary<string, ParamsEntity> paramsEntityList = new Dictionary<string, ParamsEntity>();
/// <summary>
/// 增加或修改四参数
/// </summary>
/// <param name="paramEntity"></param>
/// <returns></returns>
public static bool AddOrUpdateParams(ParamsEntity paramEntity)
{
lock (paramsEntityList)
{
if (paramsEntityList.ContainsKey(paramEntity.XZQDM))
paramsEntityList[paramEntity.XZQDM] = paramEntity;
else
paramsEntityList.Add(paramEntity.XZQDM, paramEntity);
}
return true;
}
/// <summary>
/// 获取四参数根据行政区
/// </summary>
/// <param name="xzq"></param>
/// <returns></returns>
public static ParamsEntity GetParamsByXzq(string xzq)
{
if (string.IsNullOrWhiteSpace(xzq)) return null;
if (paramsEntityList.ContainsKey(xzq))
return paramsEntityList[xzq];
return null;
}
public static Param4 Get80To84(string xzq)
{
ParamsEntity paramsEntity = GetParamsByXzq(xzq);
Param4 param4 = null;
if (paramsEntity != null)
{
if (paramsEntity.X80OFFSET == 0 && paramsEntity.X80ROTATE == 0 && paramsEntity.Y80OFFSET == 0 && paramsEntity.Y80ROTATE == 0)
return null;
param4 = new Param4();
param4.PX = paramsEntity.X80OFFSET;
param4.PY = paramsEntity.Y80OFFSET;
param4.SX = paramsEntity.X80ROTATE;
param4.SY = paramsEntity.Y80ROTATE;
}
return param4;
}
public static Param4 Get84To80(string xzq)
{
ParamsEntity paramsEntity = GetParamsByXzq(xzq);
Param4 param4 = null;
if (paramsEntity != null)
{
if (paramsEntity.X84OFFSET == 0 && paramsEntity.X84ROTATE == 0 && paramsEntity.Y84OFFSET == 0 && paramsEntity.Y84ROTATE == 0)
return null;
param4 = new Param4();
param4.PX = paramsEntity.X84OFFSET;
param4.PY = paramsEntity.Y84OFFSET;
param4.SX = paramsEntity.X84ROTATE;
param4.SY = paramsEntity.Y84ROTATE;
}
return param4;
}
#endregion
/// <summary>
/// 计算四参数
/// </summary>
/// <param name="N">重合点个数</param>
/// <param name="oldp">重合点在旧坐标系中的坐标</param>
/// <param name="newp1">重合点的在新坐标系中的坐标</param>
/// <returns></returns>
private static double[][] Calculate4Param(int N, double[][] oldp, double[][] newp1)
{
int i, j;
double[][] coneB; //系数矩阵B
coneB = new double[2 * N][];
for (i = 0; i < 2 * N; i++)
coneB[i] = new double[4];
double[][] TconeB; //系数矩阵B的转置
TconeB = new double[4][];
for (i = 0; i < 4; i++)
TconeB[i] = new double[2 * N];
double[][] consL; //常数项矩阵L
consL = new double[2 * N][];
for (i = 0; i < 2 * N; i++)
consL[i] = new double[1];
double[][] Nbb; //法方程系数矩阵Nbb
Nbb = new double[4][];
for (i = 0; i < 4; i++)
Nbb[i] = new double[4];
double[][] DNbb; //法方程系数矩阵Nbb的逆矩阵
DNbb = new double[4][];
for (i = 0; i < 4; i++)
DNbb[i] = new double[4];
double[][] ENbb; //法方程系数矩阵Nbb的扩展矩阵
ENbb = new double[4][];
for (i = 0; i < 4; i++)
ENbb[i] = new double[8];
double[][] W; //用于表示Nbb*TconeB
W = new double[4][];
for (i = 0; i < 4; i++)
W[i] = new double[2 * N];
double[][] parameter; //平差参数
parameter = new double[4][];
for (i = 0; i < 4; i++)
parameter[i] = new double[1];
double[][] V; //平差改正数
V = new double[2 * N][];
for (i = 0; i < 2 * N; i++)
V[i] = new double[1];
double[][] result2; //用于存储系数B与平差参数parameter的乘积
result2 = new double[2 * N][];
for (i = 0; i < 2 * N; i++)
result2[i] = new double[1];
for (i = 0; i < 2 * N; i++) //写出方程系数矩阵B
{
for (j = 0; j < 4; j++)
{
coneB[i][0] = (0.5 + Math.Pow(-1, i) * 0.5);
coneB[i][1] = (0.5 - Math.Pow(-1, i) * 0.5);
coneB[i][2] = oldp[i / 2][0] * (0.5 + Math.Pow(-1, i) * 0.5) + oldp[i / 2][1] * (0.5 - Math.Pow(-1, i) * 0.5);
coneB[i][3] = oldp[i / 2][0] * (0.5 - Math.Pow(-1, i) * 0.5) + oldp[i / 2][1] * (-0.5 - Math.Pow(-1, i) * 0.5);
}
}
for (i = 0; i < 2 * N; i++) //写出常数项矩阵L
for (j = 0; j < 1; j++)
consL[i][j] = newp1[i / 2][0] * (0.5 + Math.Pow(-1, i) * 0.5) + newp1[i / 2][1] * (0.5 - Math.Pow(-1, i) * 0.5);
transform(coneB, TconeB, 2 * N, 4); //调用转置函数
multiplication(TconeB, coneB, Nbb, 4, 2 * N, 4); //调用乘法函数计算法方程系数
det(Nbb, ENbb, DNbb, 4); //调用求逆函数,计算法方程系数的逆阵
multiplication(TconeB, consL, W, 4, 2 * N, 1);//调用乘法函数,计算常数项W
multiplication(DNbb, W, parameter, 4, 4, 1); //调用乘法函数,解算转换系数a,b,c,d
return parameter;
}
/// <summary>
/// 四参数转换
/// </summary>
/// <param name="oldpoint"></param>
/// <param name="parameter"></param>
/// <param name="M"></param>
/// <returns></returns>
private static double[][] Tras4Param(double[][] oldpoint, double[][] parameter, int M)
{
int i;
double[][] newpoint; //用于存储旧坐标经转换后的新坐标
newpoint = new double[M][];
for (i = 0; i < M; i++)
{
newpoint[i] = new double[2];
}
for (i = 0; i < M; i++)
{
newpoint[i][0] = parameter[0][0] + oldpoint[i][0] * parameter[2][0] - oldpoint[i][1] * parameter[3][0];
newpoint[i][1] = parameter[1][0] + oldpoint[i][1] * parameter[2][0] + oldpoint[i][0] * parameter[3][0];
}
return newpoint;
}
//求逆函数
private static void det(double[][] p, double[][] b, double[][] c, int n)
{
int i, j, k;
double m;
//扩展为增广矩阵
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
b[i][j] = p[i][j];
}
for (j = n; j < 2 * n; j++)
{
if (i + n == j)
b[i][j] = 1;
else
b[i][j] = 0;
}
}
//将左半部分化为单位矩阵
for (i = 0; i < n; i++)
{
m = b[i][i];
for (j = i; j < n * 2; j++)
b[i][j] /= m;
for (j = i + 1; j < n; j++)
{
m = b[j][i];
for (k = i; k < n * 2; k++)
b[j][k] = b[j][k] - m * b[i][k];
}
}
for (i = n - 1; i >= 0; i--)
{
m = b[i][i];
for (j = i - 1; j >= 0; j--)
{
m = b[j][i];
for (k = i; k < n * 2; k++)
b[j][k] = b[j][k] - m * b[i][k];
}
}
for (i = 0; i < n; i++)
{
for (j = n; j < 2 * n; j++)
{
c[i][j - n] = b[i][j];
}
}
}
//转置函数
private static void transform(double[][] a, double[][] b, int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
{
b[j][i] = a[i][j];
}
}
//乘法函数
public static void multiplication(double[][] a, double[][] b, double[][] c, int m, int s, int n)
{
int i, j, k;
double sum;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
{
sum = 0.0;
for (k = 0; k < s; k++)
sum += a[i][k] * b[k][j];
c[i][j] = sum;
}
}
//矩阵加法函数
private static void add(double[][] a, double[][] b, double[][] ab, int m, int n, int sign)
{
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
ab[i][j] = a[i][j] + Math.Pow(-1, sign) * b[i][j]; //sign为偶数是表示矩阵相加,奇数表示相减
}
/// <summary>
/// 根据同位点计算平面转换四参数
/// </summary>
/// <param name="sourcePoints"></param>
/// <param name="targetPoints"></param>
/// <returns></returns>
public static Param4 Calculate4Param(MapPoint[] sourcePoints, MapPoint[] targetPoints)
{
if (sourcePoints == null || targetPoints == null || sourcePoints.Length != targetPoints.Length || sourcePoints.Length == 0)
throw new ArgumentException("参数为空或者个数不一致", "sourcePoints,targetPoints");
int n = sourcePoints.Length;
double[][] oldp1 = new double[n][];
double[][] newp1 = new double[n][];
for (int i = 0; i < n; i++)
{
oldp1[i] = new double[] { sourcePoints[i].X, sourcePoints[i].Y };
newp1[i] = new double[] { targetPoints[i].X, targetPoints[i].Y };
}
double[][] param4 = Calculate4Param(n, oldp1, newp1);
return new Param4()
{
PX = param4[0][0],
PY = param4[1][0],
SX = param4[2][0],
SY = param4[3][0]
};
}
public static MapPoint[] Tras4Param(MapPoint[] sourcePoints, Param4 param4)
{
if (sourcePoints == null || sourcePoints.Length == 0)
throw new ArgumentNullException("sourcePoints");
if (param4 == null)
throw new ArgumentNullException("param4");
double[][] parameter = new double[4][];
parameter[0] = new double[] { param4.PX };
parameter[1] = new double[] { param4.PY };
parameter[2] = new double[] { param4.SX };
parameter[3] = new double[] { param4.SY };
int m = sourcePoints.Length;
double[][] oldp = new double[m][];
for (int i = 0; i < m; i++)
{
oldp[i] = new double[] { sourcePoints[i].X, sourcePoints[i].Y };
}
double[][] newp = Tras4Param(oldp, parameter, m);
MapPoint[] targetPoints = new MapPoint[m];
for (int i = 0; i < m; i++)
{
targetPoints[i] = new MapPoint(newp[i][0], newp[i][1]);
}
return targetPoints;
}
/// <summary>
/// 平面四参数转换方法
/// </summary>
/// <param name="sourcePoint"></param>
/// <param name="param4"></param>
/// <returns></returns>
public static MapPoint Tras4Param(MapPoint sourcePoint, Param4 param4)
{
return Tras4Param(new MapPoint[] { sourcePoint }, param4)[0];
}
//高斯投影正、反算
//////3度带宽
//高斯投影由经纬度(Unit:DD)反算大地坐标(含带号,Unit:Metres)
private static void GaussProjCal(double longitude, double latitude, double a, double f, out double X, out double Y, int ProjNo = 0)
{
//int ProjNo = 0;
int ZoneWide; ////带宽
double longitude1, latitude1, longitude0, latitude0, X0, Y0, xval, yval;
double e2, ee, NN, T, C, A, M, iPI;
iPI = Math.PI / 180; ////3.1415926535898/180.0;
ZoneWide = 3; ////3度带宽
//a = 6378245.0; f = 1.0 / 298.3; //54年北京坐标系参数
//a=6378140.0; f=1/298.257; //80年西安坐标系参数
//a=6378137m;f=1/298.257223563;//WGS-84坐标系
if (ProjNo == 0)
{
ProjNo = (int)Math.Round(longitude / ZoneWide);
}
longitude0 = ProjNo * ZoneWide;
longitude0 = longitude0 * iPI;
latitude0 = 0;
longitude1 = longitude * iPI; //经度转换为弧度
latitude1 = latitude * iPI; //纬度转换为弧度
e2 = 2 * f - f * f;
ee = e2 * (1.0 - e2);
NN = a / Math.Sqrt(1.0 - e2 * Math.Sin(latitude1) * Math.Sin(latitude1));
T = Math.Tan(latitude1) * Math.Tan(latitude1);
C = ee * Math.Cos(latitude1) * Math.Cos(latitude1);
A = (longitude1 - longitude0) * Math.Cos(latitude1);
M = a * ((1 - e2 / 4 - 3 * e2 * e2 / 64 - 5 * e2 * e2 * e2 / 256) * latitude1 - (3 * e2 / 8 + 3 * e2 * e2 / 32 + 45 * e2 * e2 * e2 / 1024) * Math.Sin(2 * latitude1)
+ (15 * e2 * e2 / 256 + 45 * e2 * e2 * e2 / 1024) * Math.Sin(4 * latitude1) - (35 * e2 * e2 * e2 / 3072) * Math.Sin(6 * latitude1));
xval = NN * (A + (1 - T + C) * A * A * A / 6 + (5 - 18 * T + T * T + 72 * C - 58 * ee) * A * A * A * A * A / 120);
yval = M + NN * Math.Tan(latitude1) * (A * A / 2 + (5 - T + 9 * C + 4 * C * C) * A * A * A * A / 24
+ (61 - 58 * T + T * T + 600 * C - 330 * ee) * A * A * A * A * A * A / 720);
X0 = 1000000L * (ProjNo) + 500000L;
Y0 = 0;
xval = xval + X0; yval = yval + Y0;
X = xval;
Y = yval;
}
/// <summary>
/// 高斯投影正算
/// </summary>
/// <param name="sourcePoint"></param>
/// <param name="param"></param>
/// <returns></returns>
public static MapPoint GaussProjCal(MapPoint sourcePoint, EarthParam param, int ProjNo = 0)
{
double x, y;
GaussProjCal(sourcePoint.X, sourcePoint.Y, param.A, param.F, out x, out y, ProjNo);
return new MapPoint(x, y);
}
//高斯投影由大地坐标(Unit:Metres)反算经纬度(Unit:DD)
private static void GaussProjInvCal(double X, double Y, double a, double f, out double longitude, out double latitude, int ProjNo = 0)
{
//int ProjNo;
int ZoneWide; ////带宽
double longitude1, latitude1, longitude0, latitude0, X0, Y0, xval, yval;
double e1, e2, ee, NN, T, C, M, D, R, u, fai, iPI;
iPI = Math.PI / 180; ////3.1415926535898/180.0;
//a = 6378245.0; f = 1.0 / 298.3; //54年北京坐标系参数
//a=6378140.0; f=1/298.257; //80年西安坐标系参数
//a=6378137m;f=1/298.257223563;//WGS-84坐标系
ZoneWide = 3; ////3度带宽
if (ProjNo == 0)
{
ProjNo = (int)(X / 1000000L); //查找带号
}
longitude0 = ProjNo * ZoneWide;
longitude0 = longitude0 * iPI; //中央经线
X0 = ProjNo * 1000000L + 500000L;
Y0 = 0;
xval = X - X0; yval = Y - Y0; //带内大地坐标
e2 = 2 * f - f * f;
e1 = (1.0 - Math.Sqrt(1 - e2)) / (1.0 + Math.Sqrt(1 - e2));
ee = e2 / (1 - e2);
M = yval;
u = M / (a * (1 - e2 / 4 - 3 * e2 * e2 / 64 - 5 * e2 * e2 * e2 / 256));
fai = u + (3 * e1 / 2 - 27 * e1 * e1 * e1 / 32) * Math.Sin(2 * u) + (21 * e1 * e1 / 16 - 55 * e1 * e1 * e1 * e1 / 32) * Math.Sin(4 * u)
+ (151 * e1 * e1 * e1 / 96) * Math.Sin(6 * u) + (1097 * e1 * e1 * e1 * e1 / 512) * Math.Sin(8 * u);
C = ee * Math.Cos(fai) * Math.Cos(fai);
T = Math.Tan(fai) * Math.Tan(fai);
NN = a / Math.Sqrt(1.0 - e2 * Math.Sin(fai) * Math.Sin(fai));
R = a * (1 - e2) / Math.Sqrt((1 - e2 * Math.Sin(fai) * Math.Sin(fai)) * (1 - e2 * Math.Sin(fai) * Math.Sin(fai)) * (1 - e2 * Math.Sin(fai) * Math.Sin(fai)));
D = xval / NN;
//计算经度(Longitude) 纬度(Latitude)
longitude1 = longitude0 + (D - (1 + 2 * T + C) * D * D * D / 6 + (5 - 2 * C + 28 * T - 3 * C * C + 8 * ee + 24 * T * T) * D * D * D * D * D / 120) / Math.Cos(fai);
latitude1 = fai - (NN * Math.Tan(fai) / R) * (D * D / 2 - (5 + 3 * T + 10 * C - 4 * C * C - 9 * ee) * D * D * D * D / 24
+ (61 + 90 * T + 298 * C + 45 * T * T - 256 * ee - 3 * C * C) * D * D * D * D * D * D / 720);
//转换为度 DD
longitude = longitude1 / iPI;
latitude = latitude1 / iPI;
}
/// <summary>
/// 高斯投影反算
/// </summary>
/// <param name="sourcePoint"></param>
/// <param name="param"></param>
/// <returns></returns>
public static MapPoint GaussProjInvCal(MapPoint sourcePoint, EarthParam param, int ProjNo = 0)
{
double x, y;
GaussProjInvCal(sourcePoint.X, sourcePoint.Y, param.A, param.F, out x, out y, ProjNo);
return new MapPoint(x, y);
}
/// <summary>
/// 西安80平面坐标转84经纬度坐标
/// </summary>
/// <param name="sourcePoint"></param>
/// <param name="param"></param>
/// <returns></returns>
public static MapPoint Xian80ToWgs84(MapPoint sourcePoint, Param4 param = null, int ProjNo = 0)
{
if (sourcePoint == null)
throw new ArgumentNullException("sourcePoint");
if (param != null && param.SX != 0 && param.PX != 0)
{
MapPoint targetPoint = Tras4Param(sourcePoint, param);
return GaussProjInvCal(targetPoint, EarthParam.WGS84, ProjNo);
}
else
{
return GaussProjInvCal(sourcePoint, EarthParam.WGS84, ProjNo);
}
}
/// <summary>
/// 84经纬度坐标转西安80平面坐标
/// </summary>
/// <param name="sourcePoint"></param>
/// <param name="param"></param>
/// <returns></returns>
public static MapPoint Wgs84ToXian80(MapPoint sourcePoint, Param4 param = null, int ProjNo = 0)
{
if (sourcePoint == null)
{
throw new ArgumentNullException("sourcePoint");
}
MapPoint targetPoint = GaussProjCal(sourcePoint, EarthParam.WGS84, ProjNo);
if (param != null && param.PX != 0 && param.SX != 0)
{
return Tras4Param(targetPoint, param);
}
else
{
return targetPoint;
}
}
public static MapPoint Wgs84ToXian80(MapPoint sourcePoint, string xzqdm, int ProjNo = 0)
{
return Wgs84ToXian80(sourcePoint, Get84To80(xzqdm), ProjNo);
}
public static Envelope Xian80ToWgs84(Envelope source, Param4 param = null, int ProjNo = 0)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (ProjNo == 0)
{
MapPoint pt = source.GetCenter();
ProjNo = (int)(pt.X / 1000000L);
}
MapPoint ptLT = Xian80ToWgs84(new MapPoint(source.XMin, source.YMax), param, ProjNo);
MapPoint ptRB = Xian80ToWgs84(new MapPoint(source.XMax, source.YMin), param, ProjNo);
return new Envelope(ptLT.X, ptRB.Y, ptRB.X, ptLT.Y);
}
public static Envelope Wgs84ToXian80(Envelope source, Param4 param = null, int ProjNo = 0)
{
if (source == null)
throw new ArgumentNullException("source");
if (ProjNo == 0)
{
MapPoint pt = source.GetCenter();
ProjNo = (int)Math.Round(pt.X / 3);
}
MapPoint ptLT = Wgs84ToXian80(new MapPoint(source.XMin, source.YMax), param, ProjNo);
MapPoint ptRB = Wgs84ToXian80(new MapPoint(source.XMax, source.YMin), param, ProjNo);
return new Envelope(ptLT.X, ptRB.Y, ptRB.X, ptLT.Y);
}
/// <summary>
/// 度分秒转成度
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
public static MapPoint DFM2D(MapPoint point)
{
return new MapPoint(DFM2D(point.X), DFM2D(point.Y));
}
/// <summary>
/// 度转成度分秒
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
public static MapPoint D2DFM(MapPoint point)
{
return new MapPoint(D2DFM(point.X), D2DFM(point.Y));
}
public static double DFM2D(double dfm)
{
double d = Math.Floor(dfm);
double f = Math.Floor((dfm - d) * 100);
double m = (dfm - d - f / 100) * 10000;
return d + f / 60 + m / 3600;
}
public static double D2DFM(double degree)
{
double d = Math.Floor(degree);
double f = Math.Floor((degree - d) * 60);
double m = (degree - d - f / 60) * 3600;
return d + f / 100 + m / 10000;
}
public static int Get80PrjNo(double x)
{
if (x > 1000000 && x < 70000000)
{
return (int)x / 1000000;
}
return 0;
}
}
public class Param4 : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void PropertyChangedNotify(string propName)
{
if (this.PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
private double _PX;
public double PX
{
get { return _PX; }
set
{
_PX = value;
PropertyChangedNotify("PX");
}
}
private double _PY;
public double PY
{
get { return _PY; }
set { _PY = value; PropertyChangedNotify("PY"); }
}
private double _SX;
public double SX
{
get { return _SX; }
set { _SX = value; PropertyChangedNotify("SX"); }
}
private double _SY;
public double SY
{
get { return _SY; }
set { _SY = value; PropertyChangedNotify("SY"); }
}
public Param4 Reverse()
{
return new Param4()
{
PX = -this.PX,
PY = -this.PY,
SX = -this.SX,
SY = -this.SY
};
}
public bool IsEmpty
{
get
{
return PX == 0 && PY == 0 && SX == 0 && SY == 0;
}
}
}
public class EarthParam
{
/// <summary>
/// 长轴 eg:6378137
/// </summary>
public double A { get; set; }
/// <summary>
/// 扁心率 eg:1 / 298.257223563
/// </summary>
public double F { get; set; }
public static EarthParam WGS84 { get; private set; }
public static EarthParam XIAN80 { get; private set; }
public static EarthParam BJ54 { get; private set; }
static EarthParam()
{
WGS84 = new EarthParam() { A = 6378137, F = 1 / 298.257223563 };
XIAN80 = new EarthParam() { A = 6378140, F = 1.0 / 298.3 };
BJ54 = new EarthParam() { A = 6378245.0, F = 1 / 298.257 };
}
}
public class YPRMethod
{
public static double GetAngle(double yaw, double pitch, double roll)
{
yaw = yaw * Math.PI / 180;
pitch = pitch * Math.PI / 180;
roll = roll * Math.PI / 180;
//MapPoint pt1 = new MapPoint(0, 0, 0, 0);
//MapPoint pt2 = new MapPoint(0, 1, 0, 0);
//MapPoint pt22 = new MapPoint(0, 1, 0, 0);
//MapPoint pt3 = new MapPoint(1, 0, 0, 0);
//rotate(pt1, yaw, pitch, roll);
//rotate(pt2, yaw, pitch, roll);
//rotate2(pt22, yaw, pitch, roll);
//rotate(pt3, yaw, pitch, roll);
//MapPoint vec = get_Normal(pt1, pt2, pt3);
//if (vec.X == 0 && vec.Y == 0)
//{
// return (360 + yaw / Math.PI * 180) % 360;
//}
//double angle = Math.Atan2(vec.Y, vec.X);
//if (double.IsNaN(angle))
//{
// return angle;
//}
//else
//{
// return (360 + angle * 180 / Math.PI) % 360;
//}
MapPoint pt = RotateOL(yaw, pitch, roll);
double angle = Math.Atan2(pt.X, pt.Z);
if (double.IsNaN(angle) || angle == 0)
{
return yaw * 180 / Math.PI;
}
else
{
return -angle * 180 / Math.PI;
}
//return 0;
}
private static void rotate(MapPoint pt, double yaw, double pitch, double roll)
{
double x1 = pt.X * Math.Cos(yaw) - pt.Y * Math.Sin(yaw);
double y1 = pt.X * Math.Sin(yaw) + pt.Y * Math.Cos(yaw);
double z1 = pt.Z;
double y2 = y1 * Math.Cos(roll) - z1 * Math.Sin(roll);
double z2 = y1 * Math.Sin(roll) + z1 * Math.Cos(roll);
double x2 = x1;
pt.Z = z2 * Math.Cos(pitch) - x2 * Math.Sin(pitch);
pt.X = z2 * Math.Sin(pitch) + x2 * Math.Cos(pitch);
pt.Y = y2;
}
private static void rotate2(MapPoint pt, double yaw, double pitch, double roll)
{
double y1 = pt.Y * Math.Cos(roll) - pt.Z * Math.Sin(roll);
double z1 = pt.Y * Math.Sin(roll) + pt.Z * Math.Cos(roll);
double x1 = pt.X;
double x2 = x1 * Math.Cos(yaw) - y1 * Math.Sin(yaw);
double y2 = x1 * Math.Sin(yaw) + y1 * Math.Cos(yaw);
double z2 = z1;
pt.Z = z2 * Math.Cos(pitch) - x2 * Math.Sin(pitch);
pt.X = z2 * Math.Sin(pitch) + x2 * Math.Cos(pitch);
pt.Y = y2;
}
private static MapPoint get_Normal(MapPoint p1, MapPoint p2, MapPoint p3)
{
double a = ((p2.Y - p1.Y) * (p3.Z - p1.Z) - (p2.Z - p1.Z) * (p3.Y - p1.Y));
double b = ((p2.Z - p1.Z) * (p3.X - p1.X) - (p2.X - p1.X) * (p3.Z - p1.Z));
double c = ((p2.X - p1.X) * (p3.Y - p1.Y) - (p2.Y - p1.Y) * (p3.X - p1.X));
return new MapPoint(a, b, c, 0);
}
private static MapPoint RotateOL(double yaw, double pitch, double roll)
{
//double[][] mb = GetMaxtrixB(roll);
//double[][] mc = GetMaxtrixC(pitch);
//double[][] md = GetMaxtrixD(yaw);
double[][] ma = GetMaxtrixA(pitch, yaw, roll);
double[][] xyz = new double[3][];
xyz[0] = new double[1] { 0 };
xyz[1] = new double[1] { 1 };
xyz[2] = new double[1] { 0 };
//double[][] bc = new double[3][];
//for (int i = 0; i < 3; i++)
//{
// bc[i] = new double[3];
//}
//CoordinateTrans.multiplication(mb, mc, bc, 3, 3, 3);
//double[][] bcd = new double[3][];
//for (int i = 0; i < 3; i++)
//{
// bcd[i] = new double[3];
//}
//CoordinateTrans.multiplication(bc, md, bcd, 3, 3, 3);
double[][] xyz1 = new double[3][];
for (int i = 0; i < 3; i++)
{
xyz1[i] = new double[1];
}
CoordinateTrans.multiplication(ma, xyz, xyz1, 3, 3, 1);
return new MapPoint(xyz1[0][0], xyz1[1][0], xyz1[2][0], 0);
}
private static double[][] GetMaxtrixB(double d)
{
double[][] mxtrix = new double[3][];
mxtrix[0] = new double[] { Math.Cos(d), Math.Sin(d), 0 };
mxtrix[1] = new double[] { -Math.Sin(d), Math.Cos(d), 0 };
mxtrix[2] = new double[] { 0, 0, 1 };
return mxtrix;
}
private static double[][] GetMaxtrixC(double d)
{
double[][] mxtrix = new double[3][];
mxtrix[0] = new double[] { 1, 0, 0 };
mxtrix[1] = new double[] { 0, Math.Cos(d), Math.Sin(d) };
mxtrix[2] = new double[] { 0, -Math.Sin(d), Math.Cos(d) };
return mxtrix;
}
private static double[][] GetMaxtrixD(double d)
{
double[][] mxtrix = new double[3][];
mxtrix[0] = new double[] { Math.Cos(d), Math.Sin(d), 0 };
mxtrix[1] = new double[] { -Math.Sin(d), Math.Cos(d), 0 };
mxtrix[2] = new double[] { 0, 0, 1 };
return mxtrix;
}
private static double[][] GetMaxtrixA(double x, double y, double z)
{
double[][] mxtrix = new double[3][];
mxtrix[0] = new double[] {
Math.Cos(y)*Math.Cos(z)-Math.Sin(x)*Math.Sin(y)*Math.Sin(z),
Math.Cos(y)*Math.Sin(z)+Math.Sin(x)*Math.Sin(y)*Math.Cos(z),
-Math.Sin(y)*Math.Cos(x) };
mxtrix[1] = new double[] {
-Math.Cos(x)*Math.Sin(z),
Math.Cos(x)*Math.Cos(z),
Math.Sin(x) };
mxtrix[2] = new double[] {
Math.Sin(y)*Math.Cos(z)+Math.Sin(x)*Math.Cos(y)*Math.Sin(z),
Math.Sin(y)*Math.Sin(z)+Math.Sin(x)*Math.Cos(y)*Math.Cos(z),
Math.Cos(x)*Math.Cos(y) };
return mxtrix;
}
}
/// <summary>
/// 墨卡托与经纬度转换操作
/// </summary>
public class MercatorToLonLat
{
/// <summary>
/// 经纬度转墨卡托坐标
/// </summary>
/// <param name="lonLat"></param>
/// <returns></returns>
public static ESRI.ArcGIS.Client.Geometry.MapPoint lonLat2Mercator(ESRI.ArcGIS.Client.Geometry.MapPoint lonLat)
{
double x1 = 0, y1 = 0;
transform(lonLat.Y, lonLat.X, out y1, out x1);
lonLat = new MapPoint(x1, y1);
ESRI.ArcGIS.Client.Geometry.MapPoint mercator = new ESRI.ArcGIS.Client.Geometry.MapPoint();
double x = lonLat.X * 20037508.34 / 180;
double y = Math.Log(Math.Tan((90 + lonLat.Y) * Math.PI / 360)) / (Math.PI / 180);
y = y * 20037508.34 / 180;
mercator.X = x;
mercator.Y = y;
return mercator;
}
/// <summary>
/// 墨卡托坐标转经纬度
/// </summary>
/// <param name="mercator"></param>
/// <returns></returns>
public static ESRI.ArcGIS.Client.Geometry.MapPoint Mercator2lonLat(ESRI.ArcGIS.Client.Geometry.MapPoint mercator)
{
ESRI.ArcGIS.Client.Geometry.MapPoint lonLat = new ESRI.ArcGIS.Client.Geometry.MapPoint();
double x = mercator.X / 20037508.34 * 180;
double y = mercator.Y / 20037508.34 * 180;
y = 180 / Math.PI * (2 * Math.Atan(Math.Exp(y * Math.PI / 180)) - Math.PI / 2);
lonLat.X = x;
lonLat.Y = y;
return lonLat;
}
public static ESRI.ArcGIS.Client.Geometry.Envelope Mercator2lonLat(ESRI.ArcGIS.Client.Geometry.Envelope mercator)
{
double xMax = MercatorX2Lon(mercator.XMax);
double xMin = MercatorX2Lon(mercator.XMin);
double yMax = MercatorY2Lat(mercator.YMax);
double yMin = MercatorY2Lat(mercator.YMin);
return new Envelope()
{
XMax = xMax,
XMin = xMin,
YMax = yMax,
YMin = yMin
};
}
public static ESRI.ArcGIS.Client.Geometry.Envelope LonLat2Mercator(ESRI.ArcGIS.Client.Geometry.Envelope lonlat)
{
double xMax = Lon2Mercator(lonlat.XMax);
double xMin = Lon2Mercator(lonlat.XMin);
double yMax = Lat2Mercator(lonlat.YMax);
double yMin = Lat2Mercator(lonlat.YMin);
return new Envelope()
{
XMax = xMax,
XMin = xMin,
YMax = yMax,
YMin = yMin
};
}
private static double MercatorX2Lon(double x)
{
return x / 20037508.34 * 180;
}
private static double MercatorY2Lat(double y)
{
double lat = y / 20037508.34 * 180;
return 180 / Math.PI * (2 * Math.Atan(Math.Exp(lat * Math.PI / 180)) - Math.PI / 2);
}
private static double Lon2Mercator(double x)
{
return x * 20037508.34 / 180;
}
private static double Lat2Mercator(double y)
{
double mercatorY = Math.Log(Math.Tan((90 + y) * Math.PI / 360)) / (Math.PI / 180);
return mercatorY * 20037508.34 / 180;
}
#region 经纬度转火星坐标
const double pi = 3.14159265358979324;
//
// Krasovsky 1940
//
// a = 6378245.0, 1/f = 298.3
// b = a * (1 - f)
// ee = (a^2 - b^2) / a^2;
const double a = 6378245.0;
const double ee = 0.00669342162296594323;
//
// World Geodetic System ==> Mars Geodetic System
public static void transform(double wgLat, double wgLon, out double mgLat, out double mgLon)
{
if (outOfChina(wgLat, wgLon))
{
mgLat = wgLat;
mgLon = wgLon;
return;
}
double dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
double dLon = transformLon(wgLon - 105.0, wgLat - 35.0);
double radLat = wgLat / 180.0 * pi;
double magic = Math.Sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.Sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.Cos(radLat) * pi);
mgLat = wgLat + dLat;
mgLon = wgLon + dLon;
}
static bool outOfChina(double lat, double lon)
{
if (lon < 72.004 || lon > 137.8347)
return true;
if (lat < 0.8293 || lat > 55.8271)
return true;
return false;
}
static double transformLat(double x, double y)
{
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.Sqrt(Math.Abs(x));
ret += (20.0 * Math.Sin(6.0 * x * pi) + 20.0 * Math.Sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.Sin(y * pi) + 40.0 * Math.Sin(y / 3.0 * pi)) * 2.0 / 3.0;
ret += (160.0 * Math.Sin(y / 12.0 * pi) + 320 * Math.Sin(y * pi / 30.0)) * 2.0 / 3.0;
return ret;
}
static double transformLon(double x, double y)
{
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.Sqrt(Math.Abs(x));
ret += (20.0 * Math.Sin(6.0 * x * pi) + 20.0 * Math.Sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.Sin(x * pi) + 40.0 * Math.Sin(x / 3.0 * pi)) * 2.0 / 3.0;
ret += (150.0 * Math.Sin(x / 12.0 * pi) + 300.0 * Math.Sin(x / 30.0 * pi)) * 2.0 / 3.0;
return ret;
}
#endregion
#region 百度坐标转火星坐标
const double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
static MapPoint LonLatToBaidu(MapPoint mapPointLon)
{
MapPoint rst = new MapPoint();
double bd_lat = 0;
double bd_lon = 0;
LonLatToBaidu(mapPointLon.X, mapPointLon.Y, ref bd_lat, ref bd_lon);
rst.X = bd_lon;
rst.Y = bd_lat;
return rst;
}
static void LonLatToBaidu(double lon, double lat, ref double bd_lat, ref double bd_lon)
{
double x = lon, y = lat;
double z = Math.Sqrt(x * x + y * y) + 0.00002 * Math.Sin(y * x_pi);
double theta = Math.Atan2(y, x) + 0.000003 * Math.Cos(x * x_pi);
bd_lon = z * Math.Cos(theta) + 0.0065;
bd_lat = z * Math.Sin(theta) + 0.006;
}
static void BaiduToLonLat(double bd_lat, double bd_lon, ref double lon, ref double lat)
{
double x = bd_lon - 0.0065, y = bd_lat - 0.006;
double z = Math.Sqrt(x * x + y * y) - 0.00002 * Math.Sin(y * x_pi);
double theta = Math.Atan2(y, x) - 0.000003 * Math.Cos(x * x_pi);
lon = z * Math.Cos(theta);
lat = z * Math.Sin(theta);
}
#endregion
}
/// <summary>
/// 四参数实体
/// </summary>
public class ParamsEntity
{
/// <summary>
/// 标识码
/// </summary>
public int BSM { get; set; }
/// <summary>
/// 行政区代码
/// </summary>
public string XZQDM { get; set; }
/// <summary>
/// X平移84转80
/// </summary>
public double X84OFFSET { get; set; }
/// <summary>
/// Y平移84转80
/// </summary>
public double Y84OFFSET { get; set; }
/// <summary>
/// X旋转84转80
/// </summary>
public double X84ROTATE { get; set; }
/// <summary>
/// Y旋转84转80
/// </summary>
public double Y84ROTATE { get; set; }
/// <summary>
/// X平移80转84
/// </summary>
public double X80OFFSET { get; set; }
/// <summary>
/// Y平移80转84
/// </summary>
public double Y80OFFSET { get; set; }
/// <summary>
/// X旋转80转84
/// </summary>
public double X80ROTATE { get; set; }
/// <summary>
/// Y旋转80转84
/// </summary>
public double Y80ROTATE { get; set; }
/// <summary>
///代号
/// </summary>
public string DH { get; set; }
}
public class ObjectConvertOperate
{
/// <summary>
/// Object转string
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static string ObjectToString(object obj)
{
if (obj == null)
return "";
return obj.ToString();
}
/// <summary>
/// Object转double
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static double ObjectToDouble(object obj)
{
if (obj == null)
return 0.0;
double rst = 0.0;
double.TryParse(obj.ToString(), out rst);
return rst;
}
/// <summary>
/// Object转double
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static int ObjectToInt(object obj)
{
if (obj == null)
return 0;
int rst = 0;
int.TryParse(obj.ToString(), out rst);
return rst;
}
/// <summary>
/// Object转bool
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static bool ObjectToBool(object obj)
{
if (obj == null)
return false;
bool rst = false;
bool.TryParse(obj.ToString(), out rst);
return rst;
}
/// <summary>
/// Object转datetime
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static DateTime ObjectToDate(object obj)
{
if (obj == null)
return new DateTime();
DateTime dt = new DateTime();
DateTime.TryParse(obj.ToString(), out dt);
return dt;
}
}
public class JsonRings
{
public List<List<double[]>> rings;
public static JsonRings GetTemp()
{
JsonRings jr = new JsonRings() { rings = new List<List<double[]>>() };
for (int i = 0; i < 10; i++)
{
List<double[]> ring = new List<double[]>();
for (int j = 0; j < 10; j++)
{
ring.Add(new double[] { 1111, 1111 });
}
jr.rings.Add(ring);
}
return jr;
}
public string GetJsonString()
{
var serializer = new DataContractJsonSerializer(this.GetType());
var stream = new MemoryStream();
serializer.WriteObject(stream, this);
byte[] dataBytes = new byte[stream.Length];
stream.Position = 0;
stream.Read(dataBytes, 0, (int)stream.Length);
return Encoding.UTF8.GetString(dataBytes);
}
public static JsonRings FromJson(string json)
{
try
{
if (string.IsNullOrWhiteSpace(json)) return null;
var serializer = new DataContractJsonSerializer(typeof(JsonRings));
var mStream = new MemoryStream(Encoding.Default.GetBytes(json));
return (JsonRings)serializer.ReadObject(mStream);
}
catch
{
return null;
}
}
}
}