我使用GDAL最终目的是为了获取OSGB数据中的GPS.
首先,我们需要配置环境变量
public class GameManager : MonoBehaviour
{
private void Awake()
{
string str = Application.streamingAssetsPath + @"/Data/proj9";
str = str.Replace("/", "\\");
var abc = Environment.GetEnvironmentVariable("PROJ_LIB", EnvironmentVariableTarget.User);
if (!string.IsNullOrEmpty(abc))
{
if(abc != str)
{
Environment.SetEnvironmentVariable("PROJ_LIB", str, EnvironmentVariableTarget.User);
Debug.LogError("重新配置环境变量:" + str);
Osr.SetPROJSearchPath(str);
Gdal.SetConfigOption("PROJ_LIB", str);
}
}
else
{
Environment.SetEnvironmentVariable("PROJ_LIB", str, EnvironmentVariableTarget.User);
Debug.LogError("配置环境变量:" + str);
Osr.SetPROJSearchPath(str);
Gdal.SetConfigOption("PROJ_LIB", str);
}
Gdal.AllRegister();
}
}
其次,我们要解析OSGB数据中的 metadata.xml
/// <summary>
/// 定义对象 OSGB数据文件中的 metadata.xml
/// </summary>
public class OSGBDataXml
{
private string data;
private double x;
private double y;
public string Data { get => data; set => data = value; }
public double X { get => x; set => x = value; }
public double Y { get => y; set => y = value; }
}
/// <summary>
/// 解析OSGB的XML
/// </summary>
/// <param name="path"> metadata.xml 路径</param>
/// <returns></returns>
private OSGBDataXml XMLAnalyzed(string path)
{
XmlDocument xml = new XmlDocument(); //xml文件对象
XmlReaderSettings set = new XmlReaderSettings(); //一个读取xml设置的对象
set.IgnoreComments = true; //设置忽略xml注释文档的影响,有时候注释会影响到xml的读取
string xmlPath = path + "metadata.xml";
if (!File.Exists(xmlPath))
{
Debug.LogError("metadata.xml 不存在!");
return null;
}
XmlReader reader = XmlReader.Create(xmlPath, set); //xml读取对象
xml.Load(reader); //加载xml文件
XmlNode nodeSRS = xml.SelectSingleNode("//SRS");
XmlNode nodeSRSOrigin = xml.SelectSingleNode("//SRSOrigin");
string[] strs = nodeSRSOrigin.InnerText.Split(',');
OSGBDataXml oSGBDataXml = new OSGBDataXml();
oSGBDataXml.Data = nodeSRS.InnerText;
oSGBDataXml.X = double.Parse(strs[0]);
oSGBDataXml.Y = double.Parse(strs[1]);
//Debug.Log($"OSGBDataXml.data: {oSGBDataXml.Data} X:{oSGBDataXml.X} Y:{oSGBDataXml.Y}");
return oSGBDataXml;
}
最后,我们就要转换坐标系,就可以获得我们想要的坐标值了
/// <summary>
/// 坐标系转换
/// </summary>
/// <param name="metadata">OSGB中 metadata.xml</param>
/// <param name="epsg">目标坐标系代号</param>
public void CoordinateSystemTransformation1(OSGBDataXml metadata, int epsg = 4490)
{
//不同椭球下进行坐标转换
SpatialReference sourceSr = new SpatialReference(string.Empty);
//OSGB中metadata.xml文件,内容可能会不一样,分地方坐标系和标准坐标系
if (metadata.Data.StartsWith("EPSG"))//如果开头是EPSG 则为标准坐标系
{
int epsgValue = 4490;
int.TryParse(metadata.Data.Substring(5), out epsgValue);//需要获取坐标系代号
sourceSr.ImportFromEPSG(epsgValue);//设置代号为xxxx的坐标系
}
else//否则为地方坐标系
{
var xmlData = metadata.Data;
sourceSr.ImportFromWkt(ref xmlData);//如果是地方坐标系则不是代号,而是一段str
}
SpatialReference targetSr = new SpatialReference(string.Empty);
targetSr.ImportFromEPSG(epsg); //CGCS2000 目标坐标系
// 获取该投影坐标系统中的地理坐标系统
var targetSr1 = targetSr.CloneGeogCS();
//转换到投影坐标系
CoordinateTransformation coordinateTransformation = new CoordinateTransformation(sourceSr, targetSr1);
if (coordinateTransformation == null)
{
Debug.LogError("创建坐标转换关系失败!");
}
///转换方式为单点
double[] p = new double[3] { metadata.X, metadata.Y, 0 };
Debug.LogError("平面坐标:" + p[1] + " " + p[0]);
coordinateTransformation.TransformPoint(p);
Debug.LogError("经纬度坐标:" + p[0] + " " + p[1]);
}
转换坐标系这块,参考的这篇文章:
https://blog.csdn.net/qq_37390625/article/details/105082852
地方坐标系与标准坐标系 metadata.xml 示例(数据是假的)
标准的:
地方的: