private Cartographic3 fromCartesian(Cartesian3 cartesian3, Ellipsoid ellipsoid) { Cartesian3Service cartesian3Service = new Cartesian3Service(); var cartesianToCartographicN = new Cartesian3(); var cartesianToCartographicP = new Cartesian3(); var cartesianToCartographicH = new Cartesian3(); Cartesian3 oneOverRadii = ellipsoid.OneOverRadii; Cartesian3 oneOverRadiiSquared = ellipsoid.OneOverRadiiSquared; double centerToleranceSquared = ellipsoid.CenterToleranceSquared; Cartesian3 p = scaleToGeodeticSurface(cartesian3, ellipsoid, cartesian3Service); if (p == null) { return(null); } cartesianToCartographicN = cartesian3Service.MultiplyComponents(p, oneOverRadiiSquared); cartesianToCartographicN = cartesian3Service.Normalize(cartesianToCartographicN); cartesianToCartographicH = cartesian3Service.Subtract(cartesian3, p); var longitude = Math.Atan2(cartesianToCartographicN.Y, cartesianToCartographicN.X); var latitude = Math.Asin(cartesianToCartographicN.Z); var height = Math.Sign(cartesian3Service.Dot(cartesianToCartographicH, cartesian3)) * cartesian3Service.Magnitude(cartesianToCartographicH); Cartographic3 result = new Cartographic3(); result.Longitude = longitude; result.Latitude = latitude; result.Height = height; return(result); }
/// <summary> /// 源坐标转目标坐标 /// </summary> /// <param name="sourceCoordinate"></param> /// <returns></returns> public ICoordinate3 SourceToTarget(ICoordinate3 sourceCoordinate) { if (sourceCoordinate == null) { return(null); } Cartesian3 cartesian3 = null; Cartographic3 cartographic3 = null; Projection projection = null; // ------------------------ // 第一步:源坐标转换为地理坐标 // ------------------------ switch (sourceCoordinateType) { case CoordinateType.Cartographic: // 如果源是地理坐标,则不需要处理 cartographic3 = new Cartographic3(sourceCoordinate.XAxis, sourceCoordinate.YAxis, sourceCoordinate.ZAxis); break; case CoordinateType.Cartesian: // 如果源是笛卡尔坐标 // 处理方法: // 1.高斯反算,转为地理坐标 cartesian3 = new Cartesian3(sourceCoordinate.XAxis, sourceCoordinate.YAxis, sourceCoordinate.ZAxis); GaussKrugerTransformation gauss_source_1 = new GaussKrugerTransformation(sourceEllipsoid); cartographic3 = gauss_source_1.GaussKrugerReverse(cartesian3, sourceCenterMeridian); break; case CoordinateType.Projection: // 如果源是投影坐标 // 处理方法: // 1.投影坐标转笛卡尔坐标 // 2.高斯反算,转为地理坐标 GaussKrugerTransformation gauss_source_2 = new GaussKrugerTransformation(sourceEllipsoid); projection = new Projection(sourceCoordinate.XAxis, sourceCoordinate.YAxis, sourceCoordinate.ZAxis); cartesian3 = gauss_source_2.ProjectionToCartesian(projection); cartographic3 = gauss_source_2.GaussKrugerReverse(cartesian3, sourceCenterMeridian); break; default: break; } // ------------------------ // 第二步:地理坐标转换为笛卡尔空间坐标 // ------------------------ Cartesian3Service cartesian3Service = new Cartesian3Service(); cartesian3 = cartesian3Service.Cartographic3ToCartesian3(cartographic3, sourceEllipsoid); // ------------------------ // 第三步:通过七参数模型,对笛卡尔空间坐标进行转换,转换后同样是笛卡尔空间坐标 // ------------------------ BursaWolfTransformation bursaWolfTransformation = new BursaWolfTransformation(sevenParams); cartesian3 = bursaWolfTransformation.Transform(cartesian3); // ------------------------ // 第四步:笛卡尔空间坐标转换为地理坐标 // ------------------------ Cartographic3Service cartographic3Service = new Cartographic3Service(); cartographic3 = cartographic3Service.Cartesian3ToCartographic3(cartesian3, targetEllipsoid); // ------------------------ // 第五步:地理坐标转换为目标坐标 // ------------------------ ICoordinate3 result = null; switch (targetCoordinateType) { case CoordinateType.Cartographic: // 如果目标是地理坐标,则不需要处理 result = cartographic3.Clone(); break; case CoordinateType.Cartesian: // 如果目标是笛卡尔坐标 // 处理方法: // 1.高斯正算,转为笛卡尔坐标系 GaussKrugerTransformation gauss_target_1 = new GaussKrugerTransformation(targetEllipsoid); cartesian3 = gauss_target_1.GaussKrugerForward(cartographic3, targetCenterMeridian); result = cartesian3.Clone(); break; case CoordinateType.Projection: // 如果目标是投影坐标 // 处理方法: // 1.高斯正算,转为笛卡尔坐标系 // 2.笛卡尔坐标转投影坐标 GaussKrugerTransformation gauss_target_2 = new GaussKrugerTransformation(targetEllipsoid); cartesian3 = gauss_target_2.GaussKrugerForward(cartographic3, targetCenterMeridian); projection = gauss_target_2.CartesianToProjection(cartesian3); result = projection.Clone(); break; default: break; } return(result); }
private Cartesian3 scaleToGeodeticSurface(Cartesian3 cartesian3, Ellipsoid ellipsoid, Cartesian3Service cartesian3Service) { Cartesian3 oneOverRadii = ellipsoid.OneOverRadii; Cartesian3 oneOverRadiiSquared = ellipsoid.OneOverRadiiSquared; double centerToleranceSquared = ellipsoid.CenterToleranceSquared; var positionX = cartesian3.X; var positionY = cartesian3.Y; var positionZ = cartesian3.Z; var oneOverRadiiX = oneOverRadii.X; var oneOverRadiiY = oneOverRadii.Y; var oneOverRadiiZ = oneOverRadii.Z; var x2 = positionX * positionX * oneOverRadiiX * oneOverRadiiX; var y2 = positionY * positionY * oneOverRadiiY * oneOverRadiiY; var z2 = positionZ * positionZ * oneOverRadiiZ * oneOverRadiiZ; // Compute the squared ellipsoid norm. var squaredNorm = x2 + y2 + z2; var ratio = Math.Sqrt(1.0 / squaredNorm); // As an initial approximation, assume that the radial intersection is the projection point. var intersection = cartesian3Service.MultiplyByScalar(cartesian3, ratio); // If the position is near the center, the iteration will not converge. if (squaredNorm < centerToleranceSquared) { return(double.IsInfinity(ratio) ? null : intersection); } var oneOverRadiiSquaredX = oneOverRadiiSquared.X; var oneOverRadiiSquaredY = oneOverRadiiSquared.Y; var oneOverRadiiSquaredZ = oneOverRadiiSquared.Z; // Use the gradient at the intersection point in place of the true unit normal. // The difference in magnitude will be absorbed in the multiplier. var gradient = new Cartesian3(); gradient.X = intersection.X * oneOverRadiiSquaredX * 2.0; gradient.Y = intersection.Y * oneOverRadiiSquaredY * 2.0; gradient.Z = intersection.Z * oneOverRadiiSquaredZ * 2.0; // Compute the initial guess at the normal vector multiplier, lambda. var lambda = (1.0 - ratio) * cartesian3Service.Magnitude(cartesian3) / (0.5 * cartesian3Service.Magnitude(gradient)); var correction = 0.0; double func; double denominator; double xMultiplier; double yMultiplier; double zMultiplier; double xMultiplier2; double yMultiplier2; double zMultiplier2; double xMultiplier3; double yMultiplier3; double zMultiplier3; do { lambda -= correction; xMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquaredX); yMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquaredY); zMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquaredZ); xMultiplier2 = xMultiplier * xMultiplier; yMultiplier2 = yMultiplier * yMultiplier; zMultiplier2 = zMultiplier * zMultiplier; xMultiplier3 = xMultiplier2 * xMultiplier; yMultiplier3 = yMultiplier2 * yMultiplier; zMultiplier3 = zMultiplier2 * zMultiplier; func = x2 * xMultiplier2 + y2 * yMultiplier2 + z2 * zMultiplier2 - 1.0; // "denominator" here refers to the use of this expression in the velocity and acceleration // computations in the sections to follow. denominator = x2 * xMultiplier3 * oneOverRadiiSquaredX + y2 * yMultiplier3 * oneOverRadiiSquaredY + z2 * zMultiplier3 * oneOverRadiiSquaredZ; var derivative = -2.0 * denominator; correction = func / derivative; } while (Math.Abs(func) > 0.000000000001); Cartesian3 result = new Cartesian3(); result.X = positionX * xMultiplier; result.Y = positionY * yMultiplier; result.Z = positionZ * zMultiplier; return(result); }
/// <summary> /// 目标坐标转源坐标(批量) /// </summary> /// <param name="targetCoordinates"></param> /// <returns></returns> public List <ICoordinate3> TargetToSourceBatch(IEnumerable <ICoordinate3> targetCoordinates) { if (targetCoordinates == null || targetCoordinates.Count() == 0) { return(null); } List <ICoordinate3> result = new List <ICoordinate3>(); // 局部变量 Cartesian3 cartesian3 = null; Cartographic3 cartographic3 = null; Projection projection = null; // 高斯转换 GaussKrugerTransformation gauss_source = new GaussKrugerTransformation(sourceEllipsoid); GaussKrugerTransformation gauss_target = new GaussKrugerTransformation(targetEllipsoid); // 布尔萨转换(参数反转) BursaWolfTransformation bursaWolfTransformation = new BursaWolfTransformation(sevenParams.Reverse()); // 笛卡尔组表转换 Cartesian3Service cartesian3Service = new Cartesian3Service(); // 地理坐标转换 Cartographic3Service cartographic3Service = new Cartographic3Service(); // 遍历集合中的坐标 foreach (ICoordinate3 targetCoordinate in targetCoordinates) { // ------------------------ // 第一步:目标坐标转换为地理坐标 // ------------------------ switch (targetCoordinateType) { case CoordinateType.Cartographic: // 如果目标是地理坐标,则不需要处理 cartographic3 = new Cartographic3(targetCoordinate.XAxis, targetCoordinate.YAxis, targetCoordinate.ZAxis); break; case CoordinateType.Cartesian: // 如果目标是笛卡尔坐标 // 处理方法: // 1.高斯反算,转为地理坐标 cartesian3 = new Cartesian3(targetCoordinate.XAxis, targetCoordinate.YAxis, targetCoordinate.ZAxis); cartographic3 = gauss_target.GaussKrugerReverse(cartesian3, targetCenterMeridian); break; case CoordinateType.Projection: // 如果目标是投影坐标 // 处理方法: // 1.投影坐标转笛卡尔坐标 // 2.高斯反算,转为地理坐标 projection = new Projection(targetCoordinate.XAxis, targetCoordinate.YAxis, targetCoordinate.ZAxis); cartesian3 = gauss_target.ProjectionToCartesian(projection); cartographic3 = gauss_target.GaussKrugerReverse(cartesian3, targetCenterMeridian); break; default: break; } // ------------------------ // 第二步:地理坐标转换为笛卡尔空间坐标 // ------------------------ cartesian3 = cartesian3Service.Cartographic3ToCartesian3(cartographic3, targetEllipsoid); // ------------------------ // 第三步:通过七参数模型,对笛卡尔空间坐标进行转换,转换后同样是笛卡尔空间坐标(这里需要反转参数) // ------------------------ cartesian3 = bursaWolfTransformation.Transform(cartesian3); // ------------------------ // 第四步:笛卡尔空间坐标转换为地理坐标 // ------------------------ cartographic3 = cartographic3Service.Cartesian3ToCartographic3(cartesian3, sourceEllipsoid); // ------------------------ // 第五步:地理坐标转换为源坐标 // ------------------------ ICoordinate3 subResult = null; switch (sourceCoordinateType) { case CoordinateType.Cartographic: // 如果源是地理坐标,则不需要处理 subResult = cartographic3.Clone(); break; case CoordinateType.Cartesian: // 如果源是笛卡尔坐标 // 处理方法: // 1.高斯正算,转为笛卡尔坐标系 GaussKrugerTransformation gauss_source_1 = new GaussKrugerTransformation(sourceEllipsoid); cartesian3 = gauss_source_1.GaussKrugerForward(cartographic3, sourceCenterMeridian); subResult = cartesian3.Clone(); break; case CoordinateType.Projection: // 如果源是投影坐标 // 处理方法: // 1.高斯正算,转为笛卡尔坐标系 // 2.笛卡尔坐标转投影坐标 GaussKrugerTransformation gauss_source_2 = new GaussKrugerTransformation(sourceEllipsoid); cartesian3 = gauss_source_2.GaussKrugerForward(cartographic3, sourceCenterMeridian); projection = gauss_source_2.CartesianToProjection(cartesian3); subResult = projection.Clone(); break; default: break; } result.Add(subResult); } return(result); }