Skip to content

Instantly share code, notes, and snippets.

@carlosefonseca
Created February 12, 2013 18:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carlosefonseca/4771881 to your computer and use it in GitHub Desktop.
Save carlosefonseca/4771881 to your computer and use it in GitHub Desktop.
Given a KML with multiple point placemarks and a line at the end, compares all placemarks with the line and checks if the line contains a point that is close enough to each point. Returns a √ or an X for each placemark and the distance to the closest point on the line.
#!/usr/bin/python
# -*- coding: utf-8 -*-
import math
import sys
from bs4 import BeautifulSoup
def distance_on_unit_sphere(lat1, long1, lat2, long2):
# Convert latitude and longitude to
# spherical coordinates in radians.
degrees_to_radians = math.pi/180.0
# phi = 90 - latitude
phi1 = (90.0 - lat1)*degrees_to_radians
phi2 = (90.0 - lat2)*degrees_to_radians
# theta = longitude
theta1 = long1*degrees_to_radians
theta2 = long2*degrees_to_radians
# Compute spherical distance from spherical coordinates.
# For two locations in spherical coordinates
# (1, theta, phi) and (1, theta, phi)
# cosine( arc length ) =
# sin phi sin phi' cos(theta-theta') + cos phi cos phi'
# distance = rho * arc length
cos = (math.sin(phi1)*math.sin(phi2)*math.cos(theta1 - theta2) +
math.cos(phi1)*math.cos(phi2))
arc = math.acos( cos )
# Remember to multiply arc by the radius of the earth
# in your favorite set of units to get length.
return arc
def distance(lat1, long1, lat2, long2):
return distance_on_unit_sphere(lat1, long1, lat2, long2)*6373*1000
def readKML(path):
soup = BeautifulSoup(open(path), "xml")
doc = soup.find("Document")
line = doc.find_all("Placemark")[-1].extract().find("coordinates").string.split()
linecoords = []
for point in line:
c = point.split(",")[0:2]
linecoords.append([float(c[1]),float(c[0])])
#print linecoords
for pm in doc.find_all("Placemark"):
c = pm.find("coordinates").string.split(",")[0:2]
coords = ([float(c[1]),float(c[0])])
mindist = 99999;
for point in linecoords:
d = distance(coords[0],coords[1],point[0],point[1])
if mindist > d:
mindist = d
if mindist>5:
print u"X {0:{1}<35}".format(pm.find("name").string.strip(), " "),int(mindist)
else:
print u"√ {0:{1}<35}".format(pm.find("name").string.strip(), " "),int(mindist)
readKML(sys.argv[1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment