Reputation: 1587
I have to code below, which reads a file of (geographic) coordinates (longitudes, latitudes), computes a minimum spanning tree from a distance matrix among these points and plots the resulting tree using 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()
And here is my test data:
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
It works fine and shows the plot below:
However, I also want to save the coordinates of the resulting tree into a KML format for plotting it using Google Earth. I am then storing the same coordinates passed to construct the plot into a list of tuples, which I then pass to a simpleKml object. It does not work and the tree is not correctly displyed by Google Earth.
So, in general terms, my question is: how could I save (in whatever format) the coordinates of the plot, in order to be able to reconstruct it exactly as it is displayed by Matplotlib?
Thanks in advance for any assistance you can provide.
EDIT: Below is the KML file as it appears in Google Earth:
And here is how it should appear (this plot was created using Matplotlib and Basemap):
Upvotes: 2
Views: 2932
Reputation: 339795
Looking at the simplekml documentation, coordinates need to be given as pairs of (lon,lat)
.
So instead of
# edges.append([(P[i, 0], P[j, 0]), (P[i, 1], P[j, 1])])
you need
edges.append([(P[i, 0], P[i, 1]), (P[j, 0],P[j, 1] )])
Screenshot of google earth:
Upvotes: 1
Reputation: 346
The only other option would be to convert to a .csv then an xml
https://developers.google.com/kml/articles/csvtokml
Not sure if this was what you are looking for
Upvotes: 1