1

I've got a bunch of CSV files containing, amongst other fields, lat and long. Each row is a point on a journey. I'm trying to create a KML that shows the journey as a linestring, but can't quite figure out how to get multiple coords into the linestring element. At the moment it's just putting in the last coords and that's all. It prints the whole set to screen, so I don't think it's my logic.

import csv
import simplekml

inputfile = csv.reader(open('foo.csv','r'))
kml=simplekml.Kml()
ls = kml.newlinestring(name="Journey path")

inputfile.next(); # skip CSV header
for row in inputfile:
        ls.coords=[(row[10],row[9])];
        print ls.coords
kml.save('fooline.kml');
CodeMonkey
  • 22,825
  • 4
  • 35
  • 75
Ben H
  • 13
  • 1
  • 5

1 Answers1

2

Problem

This line is your problem:

ls.coords=[(row[10],row[9])];

You overwrite all the coordinates in your LineString with a new list each time, only containing the current coordinates.

Semicolon isn't needed, and you should append the current coordinates to the Linestring coordinates. I couldn't find any documentation anywhere, but it seems that coords isn't a list object, but a simplekml.coordinates.Coordinates, which accepts an addcoordinates method:

ls.coords.addcoordinates([(row[10],row[9])])

To find this non-documented method, I had to call :

print([method for method in dir(ls.coords) if callable(getattr(ls.coords, method))])
# ['__class__', '__delattr__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'addcoordinates']

Here's an example with lists:

>>> coords = [(1,1)]
>>> coords = [(2,2)]
>>> coords = [(3,3)]
>>> coords
[(3, 3)]

>>> coords = []
>>> coords.append((1,1))
>>> coords.append((2,2))
>>> coords.append((3,3))
>>> coords
[(1, 1), (2, 2), (3, 3)]

and with simplekml objects:

import simplekml

kml=simplekml.Kml()
ls = kml.newlinestring(name="Journey path")

ls.coords.addcoordinates([(1,2)])
ls.coords.addcoordinates([(3,4)])
ls.coords.addcoordinates([(5,6)])
print(ls.coords)
# 1,2,0.0 3,4,0.0 5,6,0.0

Solution

import csv
import simplekml

inputfile = csv.reader(open('foo.csv','r'))
kml=simplekml.Kml()
ls = kml.newlinestring(name="Journey path")

inputfile.next()
for row in inputfile:
        ls.coords.addcoordinates([(row[10],row[9])]) #<-- IMPORTANT! Longitude first, Latitude second.
        print ls.coords
kml.save('fooline.kml');
Eric Duminil
  • 52,989
  • 9
  • 71
  • 124
  • Thanks very much the help and explanation. I've tried that but I get 'AttributeError: 'Coordinates' object has no attribute 'append''. I'm assuming that ls.coords is treating its input as a string rather than an array, despite declaring it as such with ls.coords = []? I've given it a couple of hours this morning but can't get any further. – Ben H Apr 06 '17 at 08:56
  • @BenH: `addcoordinates` is the required method. Too bad it doesn't appear anywhere in the [doc](http://simplekml.readthedocs.io/en/latest/reference.html). If you feel like it, you could contact the team working on this project. – Eric Duminil Apr 06 '17 at 12:40
  • Fantastic! That works - thanks for your help, and I think I will contact the team. – Ben H Apr 06 '17 at 14:02
  • 1
    A small note that it's `.addcoordinates([(longtidue, latitude)])` (not Lat/Long). (Just making clear in case someone else is trying the above but getting odd results like I was, until I switched Lat/Long to Long/Lat). – BruceWayne Feb 19 '18 at 16:33
  • 1
    @BruceWayne: Thanks for the comment. The fact that we usually talk about Latitude first and Longitude second oftens collides with the fact we usually write Longitude first (as x coordinate) and Latitude second (just like y). This has been the source of many bugs. – Eric Duminil Feb 19 '18 at 16:43
  • @EricDuminil - D'oh! Thanks for your comment back, I was always wondering why I kept running in to using long/lat when using python/programming instead of the lat/long I'm used to. No idea why I never realized it's as simple as that's the `x/y` coordinate way, duh. Cheers! – BruceWayne Feb 19 '18 at 16:51