【.net core】.KMZ文件解压为.KML文件并解析为GEOJSON坐标数据集。附KML处理多线(LineString)闭环问题

发布于:2025-06-06 ⋅ 阅读:(19) ⋅ 点赞:(0)

通过使用ZipFile解压KMZ文件,获取其中的KML文件,并解析KML文件,输出解析后的坐标数据集。

KML文件:地理信息的标准格式

解析后的坐标数据集输出格式(GEOJSON坐标数据集):[[[经度,纬度],[经度,纬度]]]

解析类

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.IO;
using System.Xml;
using System.Linq;


namespace WaterCloud.Code
{
    public static class KMZHelper
    {
        /// <summary>
        /// 解压 KMZ 文件到指定目录。
        /// </summary>
        /// <param name="kmzFilePath">kmz文件地址</param>
        /// <param name="extractDirectory">解压路径</param>
        /// <returns></returns>
        public static PlotCoordinateClass HandleKMZ(string kmzFilePath, string extractDirectory)
        {
            PlotCoordinateClass plotCoordinate = new PlotCoordinateClass();
            try
            {
                if (!File.Exists(kmzFilePath))
                {
                    Console.WriteLine($"错误: 文件 '{kmzFilePath}' 不存在。");
                    LogHelper.WriteWithTime($"错误: 文件 '{kmzFilePath}' 不存在。");
                    plotCoordinate.message = $"错误: 文件 '{kmzFilePath}' 不存在。";
                    plotCoordinate.code = 1;
                    return plotCoordinate;
                }

                if (string.IsNullOrWhiteSpace(extractDirectory))
                {
                    // 使用临时目录
                    extractDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
                    Console.WriteLine($"使用临时目录: {extractDirectory}");
                    LogHelper.WriteWithTime($"使用临时目录: {extractDirectory}");
                }

                // 确保目录存在
                Directory.CreateDirectory(extractDirectory);

                // 解压 KMZ 文件
                ExtractKMZFile(kmzFilePath, extractDirectory);
                Console.WriteLine("KMZ 文件解压完成。");
                LogHelper.WriteWithTime($"KMZ 文件解压完成。");

                // 查找并读取 KML 文件
                string[] kmlFiles = Directory.GetFiles(extractDirectory, "*.kml", SearchOption.AllDirectories);

                if (kmlFiles.Length == 0)
                {
                    Console.WriteLine("警告: 在解压文件中未找到 KML 文件。");
                    LogHelper.WriteWithTime("警告: 在解压文件中未找到 KML 文件。");
                    plotCoordinate.message = ("警告: 在解压文件中未找到 KML 文件。");
                    plotCoordinate.code = 1;
                    return plotCoordinate;
                }

                Console.WriteLine($"找到 {kmlFiles.Length} 个 KML 文件:");
                LogHelper.WriteWithTime($"找到 {kmlFiles.Length} 个 KML 文件:");
                // 处理第一个 KML 文件
                plotCoordinate = KMLHelper.HandleKML(kmlFiles[0]);

                Console.WriteLine("\n处理完成。");
                LogHelper.WriteWithTime("\n处理完成。");
                return plotCoordinate;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"发生错误: {ex.Message}");
                LogHelper.WriteWithTime($"发生错误: {ex.Message}");
                plotCoordinate.message = $"发生错误: {ex.Message}";
                plotCoordinate.code = 1;
                return plotCoordinate;
            }
        }
        /// <summary>
        /// 解压 KMZ 文件到指定目录。
        /// </summary>
        /// <param name="kmzFilePath">kmz文件地址</param>
        /// <param name="extractDirectory">解压路径</param>
        public static void ExtractKMZFile(string kmzFilePath, string extractDirectory)
        {
            try
            {
                using (ZipArchive archive = ZipFile.OpenRead(kmzFilePath))
                {
                    foreach (ZipArchiveEntry entry in archive.Entries)
                    {
                        string entryPath = Path.Combine(extractDirectory, entry.FullName);
                        string entryDirectory = Path.GetDirectoryName(entryPath);

                        // 确保目录存在
                        if (!Directory.Exists(entryDirectory))
                        {
                            Directory.CreateDirectory(entryDirectory);
                        }

                        // 跳过目录条目
                        if (entry.Length == 0)
                        {
                            continue;
                        }

                        // 提取文件
                        entry.ExtractToFile(entryPath, true);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"解压错误: {ex.Message}");
                throw;
            }
        }
        /// <summary>
        /// 截断字符串,如果长度超过指定最大长度则添加省略号。
        /// </summary>
        /// <param name="value"></param>
        /// <param name="maxLength"></param>
        /// <returns></returns>
        public static string TruncateString(string value, int maxLength)
        {
            if (string.IsNullOrEmpty(value))
            {
                return value;
            }

            return value.Length <= maxLength
                ? value
                : value.Substring(0, maxLength) + "...";
        }
    }
    public static class KMLHelper
    {
        /// <summary>
        /// 解析 KML 文件并提取坐标信息。
        /// </summary>
        /// <param name="kmlFilePath">kml文件地址</param>
        /// <returns></returns>
        public static PlotCoordinateClass HandleKML(string kmlFilePath)
        {
            PlotCoordinateClass plotCoordinate = new PlotCoordinateClass();
            try
            {

                if (!File.Exists(kmlFilePath))
                {
                    Console.WriteLine($"错误: 文件 '{kmlFilePath}' 不存在。");
                    LogHelper.WriteWithTime($"错误: 文件 '{kmlFilePath}' 不存在。");
                    plotCoordinate.message = ($"错误: 文件 '{kmlFilePath}' 不存在。");
                    plotCoordinate.code = 1;
                    return plotCoordinate;
                }

                // 加载 KML 文件
                XmlDocument kmlDoc = new XmlDocument();
                kmlDoc.Load(kmlFilePath);

                // 创建命名空间管理器,处理 KML 命名空间
                XmlNamespaceManager nsmgr = new XmlNamespaceManager(kmlDoc.NameTable);
                nsmgr.AddNamespace("kml", "http://www.opengis.net/kml/2.2");

                // 解析基本信息
                List<PlotCoordinateClass> plotCoordinates =  ParseKmlDocument(kmlDoc, nsmgr);
                if (plotCoordinates != null && plotCoordinates.Count > 0) {
                    // 取最大的坐标点数作为结果,如果有多个则取最大的一个
                    plotCoordinate = plotCoordinates.OrderByDescending(a => a.PlotCoordinateCount).First();
                }
                Console.WriteLine("\n解析完成。");
                LogHelper.WriteWithTime("\n解析完成。");
                return plotCoordinate;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"发生错误: {ex.Message}");
                LogHelper.WriteWithTime($"发生错误: {ex.Message}");
                plotCoordinate.message = ($"发生错误: {ex.Message}");
                plotCoordinate.code = 1;
                return plotCoordinate;
            }
        }

        static List<PlotCoordinateClass> ParseKmlDocument(XmlDocument kmlDoc, XmlNamespaceManager nsmgr)
        {
            List<PlotCoordinateClass> plotCoordinates = new List<PlotCoordinateClass>();
            // 获取文档名称
            XmlNode documentNode = kmlDoc.SelectSingleNode("//kml:Document", nsmgr);
            if (documentNode != null)
            {
                XmlNode nameNode = documentNode.SelectSingleNode("kml:name", nsmgr);
                if (nameNode != null)
                {
                    Console.WriteLine($"文档名称: {nameNode.InnerText}");
                }

                // 解析文件夹
                plotCoordinates =ParseFolders(documentNode, nsmgr);

                // 解析地点标记
                //plotCoordinates = ParsePlacemarks(documentNode, nsmgr);
            }
            return plotCoordinates;
        }
        /// <summary>
        /// 解析文件夹及其子节点(地点标记和嵌套的文件夹)
        /// </summary>
        /// <param name="parentNode"></param>
        /// <param name="nsmgr"></param>
        /// <returns></returns>
        static List<PlotCoordinateClass> ParseFolders(XmlNode parentNode, XmlNamespaceManager nsmgr)
        {
            List<PlotCoordinateClass> plotCoordinates = new List<PlotCoordinateClass>();
            XmlNodeList folderNodes = parentNode.SelectNodes("kml:Folder", nsmgr);
            if (folderNodes != null && folderNodes.Count > 0)
            {
                Console.WriteLine("\n发现 {0} 个文件夹:", folderNodes.Count);

                foreach (XmlNode folderNode in folderNodes)
                {
                    XmlNode nameNode = folderNode.SelectSingleNode("kml:name", nsmgr);
                    string folderName = nameNode != null ? nameNode.InnerText : "[未命名文件夹]";
                    Console.WriteLine($"  - 文件夹: {folderName}");

                    // 递归解析文件夹中的地点标记
                    List<PlotCoordinateClass> result =  ParsePlacemarks(folderNode, nsmgr);
                    plotCoordinates.AddRange(result);

                    // 递归解析子文件夹
                    plotCoordinates.AddRange(ParseFolders(folderNode, nsmgr));
                }
            }
            return plotCoordinates;
        }
        /// <summary>
        /// 解析地点标记(点、线、多边形)
        /// </summary>
        /// <param name="parentNode"></param>
        /// <param name="nsmgr"></param>
        /// <returns></returns>
        static List<PlotCoordinateClass> ParsePlacemarks(XmlNode parentNode, XmlNamespaceManager nsmgr)
        {
            List<PlotCoordinateClass> plotCoordinateClasses = new List<PlotCoordinateClass>();
            
            XmlNodeList placemarkNodes = parentNode.SelectNodes("kml:Placemark", nsmgr);
            if (placemarkNodes != null && placemarkNodes.Count > 0)
            {
                Console.WriteLine("\n发现 {0} 个地点标记:", placemarkNodes.Count);

                foreach (XmlNode placemarkNode in placemarkNodes)
                {
                    PlotCoordinateClass plotCoordinate = null;
                    // 获取地点标记名称
                    XmlNode nameNode = placemarkNode.SelectSingleNode("kml:name", nsmgr);
                    string placemarkName = nameNode != null ? nameNode.InnerText : "[未命名地点]";
                    Console.WriteLine($"  - 地点: {placemarkName}");

                    // 解析点
                    XmlNode pointNode = placemarkNode.SelectSingleNode("kml:c", nsmgr);
                    if (pointNode != null)
                    {
                        ParsePoint(pointNode, nsmgr);
                    }



                    // 解析多边形
                    XmlNode MultiGeometryNode = placemarkNode.SelectSingleNode("kml:MultiGeometry", nsmgr);

                    if (MultiGeometryNode != null)
                    {
                        XmlNode polygonNode = MultiGeometryNode.SelectSingleNode("kml:Polygon", nsmgr);
                        if (polygonNode != null)
                        {
                            plotCoordinate =  ParsePolygon(polygonNode, nsmgr);
                            if (plotCoordinate != null) plotCoordinateClasses.Add(plotCoordinate);
                        }
                        // 解析线
                        XmlNodeList lineStringNodes = MultiGeometryNode.SelectNodes("kml:LineString", nsmgr);
                        if (lineStringNodes != null && lineStringNodes.Count > 0)
                        {
                            List< PlotCoordinateClass > tempList = new List<PlotCoordinateClass>();
                            //获取所有线串节点数据
                            foreach (XmlNode node in lineStringNodes) {
                                plotCoordinate = ParseLineString(node, nsmgr);
                                if (plotCoordinate != null) tempList.Add(plotCoordinate);
                            }
                            //闭合多边形区域,将多个线串整合为一个闭合的多边形区域,并添加处理结果到返回集合中。
                            plotCoordinateClasses.Add(ClosePolygon(tempList));
                        }
                    
                    }
                }
            }
            return plotCoordinateClasses;
        }
        /// <summary>
        /// 点处理方法
        /// </summary>
        /// <param name="pointNode"></param>
        /// <param name="nsmgr"></param>
        static void ParsePoint(XmlNode pointNode, XmlNamespaceManager nsmgr)
        {
            XmlNode coordinatesNode = pointNode.SelectSingleNode("kml:coordinates", nsmgr);
            if (coordinatesNode != null && !string.IsNullOrWhiteSpace(coordinatesNode.InnerText))
            {
                string[] coords = coordinatesNode.InnerText.Trim().Split(',');
                if (coords.Length >= 2)
                {
                    double longitude = double.Parse(coords[0]);
                    double latitude = double.Parse(coords[1]);
                    double? altitude = coords.Length > 2 ? (double?)double.Parse(coords[2]) : null;

                    Console.WriteLine($"    点坐标: 经度={longitude}, 纬度={latitude}{(altitude.HasValue ? $", 高度={altitude.Value}" : "")}");
                }
            }
        }
        /// <summary>
        /// 线处理方法
        /// </summary>
        /// <param name="lineStringNode"></param>
        /// <param name="nsmgr"></param>
        /// <returns></returns>
        private static PlotCoordinateClass ParseLineString(XmlNode lineStringNode, XmlNamespaceManager nsmgr)
        {
            PlotCoordinateClass plotCoordinate = null;
            XmlNode coordinatesNode = lineStringNode.SelectSingleNode("kml:coordinates", nsmgr);
            if (coordinatesNode != null && !string.IsNullOrWhiteSpace(coordinatesNode.InnerText))
            {
                plotCoordinate = GetPlotCoordinate(coordinatesNode.InnerText);
                //string[] pointStrings = coordinatesNode.InnerText.Trim().Split(new[] { ' ', '\t', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
                //Console.WriteLine($"    线串: {pointStrings.Length} 个点");
            }
            return plotCoordinate;
        }
        /// <summary>
        /// 多线闭环处理方法,将多个线串整合为一个闭合的多边形区域
        /// </summary>
        /// <param name="plotCoordinateClasses">多线集合</param>
        /// <returns></returns>
        private static PlotCoordinateClass ClosePolygon(List<PlotCoordinateClass> plotCoordinateClasses)
        {
            PlotCoordinateClass plotCoordinate = new PlotCoordinateClass();
            //plotCoordinateClasses中的PlotCoordinates数据格式为[[[经度,纬度],[经度,纬度]]],需要将这些数据整合载入到一个List中
            List<List<List<double>>> plotCoordinates = new List<List<List<double>>>();
            if (plotCoordinateClasses != null && plotCoordinateClasses.Count > 0) {
                if (plotCoordinateClasses.Count == 1) {
                    //如果只有一个区域,则直接返回第一个区域数据
                    plotCoordinate = plotCoordinateClasses.First();
                }
                else {
                    //处理多区域数据,将多个区域整合为一个区域
                    foreach (PlotCoordinateClass item in plotCoordinateClasses)
                    {
                        List<List<List<double>>> temp = JsonConvert.DeserializeObject<List<List<List<double>>>>(item.PlotCoordinates);
                        if (temp != null && temp.Count > 0) {
                            plotCoordinates.Add(temp.First());
                        }
                    }
                    //调用序列化坐标数据方法获取处理结果
                    List<List<List<double>>> result = SerializePlotCoordinate(plotCoordinates, plotCoordinates.First());
                    if(result != null && result.Count > 0) {
                        //创建新的坐标数据集合并将序列化结果赋值给新的坐标数据
                        List<List<List<double>>> newCoordinates = new List<List<List<double>>>();
                        List<List<double>> newNodes = new  List<List<double>>();
                        foreach (List<List<double>> item in result) {
                            foreach (List<double> node in item) {
                                newNodes.Add(node);
                            }
                        }
                        newCoordinates.Add(newNodes);
                        //将处理后的坐标数据赋值给PlotCoordinate对象
                        plotCoordinate.PlotCoordinates = JsonConvert.SerializeObject(newCoordinates);
                        plotCoordinate.CententCoordinate = JsonConvert.SerializeObject(newCoordinates.First().First());
                        plotCoordinate.PlotCoordinateCount = newCoordinates.First().Count;
                        plotCoordinate.code = 0;
                        plotCoordinate.message = "处理成功";
                    }
                }

            }
            return plotCoordinate;
        }
        /// <summary>
        /// 递归序列化区域坐标数据
        /// </summary>
        /// <param name="plotCoordinates">坐标数据集合,格式为"[[[经度,纬度],[经度,纬度]],[[经度,纬度],[经度,纬度]]]"</param>
        /// <param name="coordinates">初始依据坐标数据集,根据该参数处理后续节点内容</param>
        /// <returns></returns>
        private static List<List<List<double>>> SerializePlotCoordinate(List<List<List<double>>> plotCoordinates, List<List<double>> coordinates) {
            List<List<List<double>>> result = new List<List<List<double>>>();
            //将传入的坐标数据添加到结果中
            result.Add(coordinates);
            
            List<List<double>> nextCoordinates = new List<List<double>>();
            int deleteIndex = -1;//数据集删除索引
            //遍历传入的坐标数据集,判断当前传入坐标数据的后一个数据
            List<double> coordinatesLastNode = coordinates.Last();
            for (int i = 0; i < plotCoordinates.Count; i++) {
                List < List<double> > temp = plotCoordinates[i];
                temp = temp.Distinct().ToList();
                List<double> tempLastNode = temp.Last();
                List<double> tempFirstNode = temp.First();
                if (coordinatesLastNode.First().Equals(tempFirstNode.First())
                    && coordinatesLastNode.Last().Equals(tempFirstNode.Last()))
                {
                    //说明当前遍历数据temp的第一个节点与coordinates的最后一个节点相同,直接将temp的第一个节点删除,并将剩余数据添加到nextCoordinates中
                    temp.RemoveAt(0);
                    nextCoordinates.AddRange(temp);
                    deleteIndex = i;//获取删除索引
                    break;
                }
                else if (coordinatesLastNode.First().Equals(tempLastNode.First())
                    && coordinatesLastNode.Last().Equals(tempLastNode.Last()))
                {
                    //说明当前遍历数据temp的最后一个节点与coordinates的最后一个节点相同,需要将temp翻转后,删除第一个节点,并将剩余数据添加到nextCoordinates中
                    temp.Reverse();
                    temp.RemoveAt(0);
                    nextCoordinates.AddRange(temp);
                    deleteIndex = i;//获取删除索引
                    break;
                }
                else {
                    //未匹配的情况,跳出当前循环,遍历下一个节点
                    continue;
                }
            }
            
            if (deleteIndex != -1) { 
                //如果存在删除索引,则从数据集中删除该节点
                plotCoordinates.RemoveAt(deleteIndex);
                
            }
            
            if (plotCoordinates != null && plotCoordinates.Count > 0)
            {
                //如果数据集不为空,则继续递归调用该方法
                result.AddRange(SerializePlotCoordinate(plotCoordinates, nextCoordinates));
            }
            else {
                //如果数据集为空,则将nextCoordinates添加到结果中
                result.Add(nextCoordinates);
            }

            return result;
        }
        /// <summary>
        /// 区域处理方法
        /// </summary>
        /// <param name="polygonNode"></param>
        /// <param name="nsmgr"></param>
        /// <returns></returns>
        private static PlotCoordinateClass ParsePolygon(XmlNode polygonNode, XmlNamespaceManager nsmgr)
        {
            PlotCoordinateClass plotCoordinate = null;
            XmlNode outerBoundaryNode = polygonNode.SelectSingleNode("kml:outerBoundaryIs", nsmgr);
            if (outerBoundaryNode != null)
            {
                XmlNode linearRingNode = outerBoundaryNode.SelectSingleNode("kml:LinearRing", nsmgr);
                if (linearRingNode != null)
                {
                    XmlNode coordinatesNode = linearRingNode.SelectSingleNode("kml:coordinates", nsmgr);
                    if (coordinatesNode != null && !string.IsNullOrWhiteSpace(coordinatesNode.InnerText))
                    {
                        //string[] pointStrings = coordinatesNode.InnerText.Trim().Split(new[] { '0',' ', '\t', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
                        //获取区域坐标集合
                        plotCoordinate = GetPlotCoordinate(coordinatesNode.InnerText);
                    }
                }
            }

            // 解析内圈(洞)
            XmlNodeList innerBoundaryNodes = polygonNode.SelectNodes("kml:innerBoundaryIs", nsmgr);
            if (innerBoundaryNodes != null && innerBoundaryNodes.Count > 0)
            {
                Console.WriteLine($"    多边形内圈: {innerBoundaryNodes.Count} 个");
                foreach (XmlNode innerBoundaryNode in innerBoundaryNodes)
                {
                    XmlNode linearRingNode = innerBoundaryNode.SelectSingleNode("kml:LinearRing", nsmgr);
                    if (linearRingNode != null)
                    {
                        XmlNode coordinatesNode = linearRingNode.SelectSingleNode("kml:coordinates", nsmgr);
                        if (coordinatesNode != null && !string.IsNullOrWhiteSpace(coordinatesNode.InnerText))
                        {
                            plotCoordinate = GetPlotCoordinate(coordinatesNode.InnerText);
                            string[] pointStrings = coordinatesNode.InnerText.Trim().Split(new[] { ' ', '\t', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
                            Console.WriteLine($"      内圈: {pointStrings.Length} 个点");
                        }
                    }
                }
            }
            return plotCoordinate;
        }
        /// <summary>
        /// 获取区域坐标
        /// </summary>
        /// <param name="InnerText"></param>
        /// <returns></returns>
        private static PlotCoordinateClass GetPlotCoordinate(string InnerText)
        {
            PlotCoordinateClass plotCoordinate = new PlotCoordinateClass();
            List<string> coordinates = InnerText.Trim().Split(",0").ToList();
            if (coordinates != null && coordinates.Count > 0)
            {
                coordinates = coordinates.Where(a => !string.IsNullOrEmpty(a)).ToList();
                coordinates.ForEach(a =>
                {
                    a = a.Trim();
                });
            }
            plotCoordinate.code = 0;
            List<List<List<double>>> PlotCoordinates = GetCoordinatesList(coordinates);
            if ((PlotCoordinates != null && PlotCoordinates.Count > 0) &&
                (PlotCoordinates[0] != null && PlotCoordinates[0].Count > 0)
                )
            {
                plotCoordinate.PlotCoordinates = JsonConvert.SerializeObject(PlotCoordinates);
                plotCoordinate.CententCoordinate = JsonConvert.SerializeObject(PlotCoordinates[0][0]);
                plotCoordinate.PlotCoordinateCount = PlotCoordinates[0].Count;
                plotCoordinate.code = 0;
                plotCoordinate.message = "数据获取成功";
            }
            else
            {
                plotCoordinate.code = 1;
                plotCoordinate.message = "数据获取失败";
            }

            return plotCoordinate;
        }
        /// <summary>
        /// 获取坐标集合
        /// </summary>
        /// <param name="coordinates"></param>
        /// <returns></returns>
        private static List<List<List<double>>> GetCoordinatesList(List<string> coordinates)
        {
            List<List<List<double>>> result = new List<List<List<double>>>();
            List<List<double>> secondList = new List<List<double>>();
            foreach (string item in coordinates)
            {
                //List<double> ints = item.Split(",").Select(a => Math.Round(a.ToDouble(), 6)).ToList();
                List<double> ints = item.Split(",").Select(a => a.ToDouble()).ToList();
                if (ints != null && ints.Count > 1) {
                    var gcjCoord = WGS84ToGCJ02Helper.Wgs84ToGcj02(ints[0], ints[1]);
                    ints[0] = gcjCoord.lng;
                    ints[1] = gcjCoord.lat;
                    secondList.Add(ints);
                }
            }
            result.Add(secondList);
            return result;
        }
    }
    /// <summary>
    /// 区域坐标类
    /// </summary>
    public class PlotCoordinateClass
    {
        /// <summary>
        /// 地块坐标集合,格式为"[[[经度,纬度],[经度,纬度]]]"
        /// </summary>
        public string PlotCoordinates { get; set; }
        /// <summary>
        /// 地块中心坐标,格式为"[经度,纬度]"
        /// </summary>
        public string CententCoordinate { get; set; }
        /// <summary>
        /// 区域坐标数量
        /// </summary>
        public int PlotCoordinateCount { get; set; }
        /// <summary>
        /// 解析状态码,0为成功,1为失败。默认为0
        /// </summary>
        public int code { get; set; }
        /// <summary>
        /// 解析状态信息,默认为"成功"。失败时为具体错误描述。
        /// </summary>
        public string message { get; set; }
    }


}

调用

PlotCoordinateClass plotCoordinate = null;
//调用解压KMZ文件并解析解压后的KML文件并返回结果
plotCoordinate = KMZHelper.HandleKMZ("/your/kmzFile/path",
   "/your/kmzFile/extractDirectory");
//调用解析KML文件并返回解析结果
plotCoordinate = KMLHelper.HandleKML("/your/kmlFile/path");


网站公告

今日签到

点亮在社区的每一天
去签到