Python - 将Matplotlib图导出为KML文件

时间:2017-09-17 18:48:17

标签: python matplotlib

我必须编写下面的代码,它读取(地理)坐标(经度,纬度)的文件,从这些点中的距离矩阵计算最小生成树,并使用Matplotlib绘制生成的树。

import warnings
import numpy as np
from scipy.spatial.distance import pdist, squareform
import matplotlib.pyplot as plt
import simplekml

warnings.filterwarnings("ignore")

def minimum_spanning_tree(X, copy_X=True):
    """X are edge weights of fully connected graph"""
    if copy_X:
        X = X.copy()

    if X.shape[0] != X.shape[1]:
        raise ValueError("X needs to be square matrix of edge weights")
    n_vertices = X.shape[0]
    spanning_edges = []

    # initialize with node 0:                                                                                        
    visited_vertices = [0]                                                                                           
    num_visited = 1
    # exclude self connections:
    diag_indices = np.arange(n_vertices)
    X[diag_indices, diag_indices] = np.inf

    while num_visited != n_vertices:
        new_edge = np.argmin(X[visited_vertices], axis=None)
        # 2d encoding of new_edge from flat, get correct indices                                                     
        new_edge = divmod(new_edge, n_vertices)
        new_edge = [visited_vertices[new_edge[0]], new_edge[1]]                                                      
        # add edge to tree
        spanning_edges.append(new_edge)
        visited_vertices.append(new_edge[1])
        # remove all edges inside current tree
        X[visited_vertices, new_edge[1]] = np.inf
        X[new_edge[1], visited_vertices] = np.inf                                                                    
        num_visited += 1
    return np.vstack(spanning_edges)

def test_mst():
    P = np.loadtxt("testdata.csv", delimiter=',', skiprows=1)

    X = squareform(pdist(P))

    edge_list = minimum_spanning_tree(X)
    plt.scatter(P[:, 0], P[:, 1], c='b')

    edges = []
    for edge in edge_list:
        i, j = edge
        plt.plot([P[i, 0], P[j, 0]], [P[i, 1], P[j, 1]], c='b')
        edges.append([(P[i, 0], P[j, 0]), (P[i, 1], P[j, 1])])
    plt.show()

    # Save KML file
    kml = simplekml.Kml()
    for i in range(len(edges)):
        line = kml.newlinestring(name="Track" + str(i + 1), coords=edges[i])
        line.style.linestyle.width = 3
        line.style.linestyle.color = simplekml.Color.red
    kml.save("mst.kml")

if __name__ == "__main__":
    test_mst()

这是我的测试数据:

Longitude,Latitude
-61.05,10.4
-79.4333333333,9.15
-70.6666666667,9.5333333333
-63.1166666667,7.9166666667
-63.1166666667,10.55
-81.1833333333,7.5166666667
-56.4833333333,3.1
-60.5,3.9333333333
-81.0166666667,7.6666666667
-67.4333333333,8.9333333333
-65.9666666667,10.3166666667
-78.9333333333,8.3833333333
-72.8666666667,9.8333333333
-68.4,10.6166666667
-72.9833333333,10.6166666667

它工作正常并显示下图:

enter image description here

但是,我还想将结果树的坐标保存为KML格式,以便使用Google Earth绘制它。然后我存储传递的相同坐标以将绘图构建到元组列表中,然后将其传递给simpleKml对象。它不起作用,Google地球没有正确显示树。

因此,一般而言,我的问题是:我如何保存(以任何格式)绘图的坐标,以便能够完全按照Matplotlib显示的方式重建它?

提前感谢您提供的任何帮助。

编辑:以下是Google地球中显示的KML文件:

enter image description here

以下是应该出现的方式(此图是使用Matplotlib和Basemap创建的):

enter image description here

2 个答案:

答案 0 :(得分:1)

唯一的另一种选择是转换为.csv然后转换为xml
https://developers.google.com/kml/articles/csvtokml
不确定这是否是您正在寻找的

答案 1 :(得分:1)

查看the simplekml documentation,坐标需要以(lon,lat)对的形式给出。

所以而不是

 # edges.append([(P[i, 0], P[j, 0]), (P[i, 1], P[j, 1])])

你需要

 edges.append([(P[i, 0], P[i, 1]), (P[j, 0],P[j, 1] )])

google earth的屏幕截图:

enter image description here