如何在 python 3.7 和 Windows 10 上使用 matplotlib 绘制 .kml 文件中的数据?

问题描述 投票:0回答:1

我首先会介绍一下我的问题的背景。

我在此站点上获得了世界各地领海的.kml文件,我想不在Google Earth上显示它,而是在matplotlib.pyplot图上显示它(如果可能的话也可以使用cartopy地图)。 .kml 文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<NetworkLink>
    <name>Territorial Seas (12NM) v3</name>
    <description><![CDATA[Flanders Marine Institute (2019). Maritime Boundaries Geodatabase: Territorial Seas (12NM), version 3. Available online at <a href="http://www.marineregions.org">http://www.marineregions.org</a> https://doi.org/10.14284/387. Consulted on YYYY-MM-DD.]]></description>
    <Link>
        <href>http://geo.vliz.be/geoserver/gwc/service/kml/MarineRegions:eez_12nm.png.kml</href>
    </Link>
</NetworkLink>
</kml>

为此,我在 另一个 StackOverflow 问题上看到,使用 fastkml 读取文件是可能的。

所以这是我尝试运行的test.py代码(它来自使用指南):

from fastkml import  kml

filename = "C:\\Users\\dumasal\\Documents\\GOOGLE_EARTH\\MarineRegions-eez_12nm.kml"
with open(filename, 'rt', encoding="utf-8") as myfile:
    doc=myfile.read()
    print(doc)
    
    # Create the KML object to store the parsed result
    k = kml.KML()
    
    # Read in the KML string
    k.from_string(doc)
    print('k = ', k)
    
    ### Next we perform some simple sanity checks ###
    
    # Check that the number of features is correct
    # This corresponds to the single ``Document``
    features = list(k.features())
    print(len(features))
    
    # Check that we can access the features as a generator
    # (The two Placemarks of the Document)
    print(features[0].features())
    f2 = list(features[0].features())
    print(len(f2))
    
    # Check specifics of the first Placemark in the Document
    print(f2[0])
    print(f2[0].description)
    print(f2[0].name)
    
    # Check specifics of the second Placemark in the Document
    print(f2[1].name)
    f2[1].name = "ANOTHER NAME"
    
    # Verify that we can print back out the KML object as a string
    print(k.to_string(prettyprint=True))

当我运行它时,我收到错误:

ValueError: Unicode strings with encoding declaration are not supported. Please use bytes input or XML fragments without declaration.

我在谷歌上查找了错误,发现这个 GitHub 页面,他们说“from_string()”函数只需要字节,所以我的代码的开头可以更改为:

from fastkml import  kml

filename = "C:\\Users\\dumasal\\Documents\\GOOGLE_EARTH\\MarineRegions-eez_12nm.kml"
with open(filename, 'r') as myfile:
    doc=myfile.read().encode('UTF-8')
    print(doc)
    
    # Create the KML object to store the parsed result
    k = kml.KML()
    
    # Read in the KML string
    k.from_string(doc)
    print('k = ', k)

    ### Next we perform some simple sanity checks ###
    
    # Check that the number of features is correct
    # This corresponds to the single ``Document``
    features = list(k.features())
    print(len(features))

奇怪的是,ValueError 不再出现。但是现在我收到错误:

    print(features[0].features())
IndexError: list index out of range

这是因为我的变量 features =

[]
,我不知道为什么。

那么您能否向我解释一下为什么 features 变量为空,或者使用 python 和 matplotlib 绘制 .kml 文件的更直接方法?

非常感谢!

python matplotlib kml valueerror fastkml
1个回答
1
投票

一个问题是您拥有的 KML 文件是一个 super-overlay,它自动生成为子区域中引用为 NetworkLink 的多个 KML“文件”,并且很少有 KML python 包直接支持递归 NetworkLink。您正在使用的 fastkml 模块实现 NetworkLinks,因此内容会被跳过。

pyKML包可以解析KML文件并迭代网络链接中引用的KML图层。

您可以执行类似的操作来迭代 NetworkLink 和 KML 内容。

import requests
import re
from pykml import parser

count = 0

def walk(elt):
    global count
    for elt in elt.getchildren():
        tag = re.sub(r'^.*\}', '', elt.tag)
        if tag in ['Folder', 'Document']:
            walk(elt)
        elif tag == 'NetworkLink':
            print(tag)
            print(elt.Link.href)
            if count == 10:
                # for debugging stop after 10 links
                raise Exception("too many links")
            count += 1
            response = requests.get(elt.Link.href)
            walk(parser.fromstring(response.content))
        elif tag == 'GroundOverlay':
            print(tag)
            # do something with the ground overlay
        else:
            # other tag; e.g. Region, comment, etc
            print(">>", tag)

with open("MarineRegions-eez_12nm.kml", 'rb') as myfile:
    root = parser.parse(myfile).getroot()
walk(root)

MarineRegions KML 是一个超级叠加层,它递归地细分为更小的区域,因此尝试在所有级别绘制 GroundOverlay 将会用较小的高分辨率叠加层覆盖较大的低分辨率叠加层。您需要决定是否只需要高分辨率地面叠加层或低分辨率叠加层。例如,如果给定级别的 KML 内容没有任何 NetworkLink,则它处于最低级别。

注意 GeoServer 有两种不同类型的 super-overlays:栅格和矢量。您使用的 KML 是栅格超级叠加。您可能想检查是否有可用的矢量叠加,因为处理矢量可能比处理地面叠加图像更容易。

© www.soinside.com 2019 - 2024. All rights reserved.