Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

Every Google Earth user is going mad about path and distance: you can get Path or Distance but not both.
This little snipset help you to get path AND distance.

  1. Create your path as usual with Google Earth
  2. Save it as a .kml file (not .kmz)
  3. Run the this script

The current version is KML 2.2

Code Block
 /**
 * Compute distance in Google Earth KML path file from a path
 * @author Marc DEXET ( marcdexet [at] gmail [dot] org )
*/
class Point {
    def lat
    def lon
    public Point(){}

    public Point(String gps) {
        def xyz = gps.tokenize(',');
        lat = Double.parseDouble( xyz[1] )
        lon = Double.parseDouble( xyz[0] )
    }
    public String toString() {
        return "LAT: ${lat} LON: ${lon}"
    }

    public static double distance(Point p0, Point p1) {
        return Haversine.compute(p0, p1)
    }
}

/**
 * List of Points
 */
class PointList {
    def points
    def distance
    def partiels = []

    public PointList( List points ) {
        this.points = points
        compute()
    }

    void compute() {
        def nbPointList = points.size()
        distance = 0;
        partiels = []
        for( idx in 1..(nbPointList-1) ) {
            def p0 = points[(idx-1)]
            def p1 = points[idx]
            def dist = Point.distance(p0,p1)
            partiels << dist
            distance = distance+dist
        }
    }

}
/**
 * Haversine algorithmus
 * (thanks to http://www.movable-type.co.uk/scripts/latlong.html)
 */
class Haversine {
    static double R = 6371

    static double compute(Point p1, Point p2) {
        def dLat = Math.toRadians(p2.lat-p1.lat);
        def dLon = Math.toRadians(p2.lon-p1.lon);
        def a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                Math.cos( Math.toRadians(p1.lat) ) *
                Math.cos( Math.toRadians(p2.lat) ) * Math.sin(dLon/2) * Math.sin(dLon/2);
        def c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
        def d = R * c;
        return d
    }

}

class KmlParser {
    static ns = new groovy.xml.Namespace("http://earth.google.com/kml/2.2", 'ns')
    List parse( Object input ) {
            def kml = new groovy.util.XmlParser().parse( input );
            def coords = kml[ ns.Document ][ ns.Placemark ][ ns.LineString ][ ns.coordinates ].text()
            def myList = coords.tokenize();
            def points = []
            myList.each{ gestring -> points << new Point(gestring) }
            return points;
    }
}

// Application

def kmlParser = new KmlParser()
def points = kmlParser.parse( args[0] )
def PointList pointList = new PointList( points )
def partiels = pointList.partiels;
def distance = pointList.distance;

java.text.DecimalFormat f = new java.text.DecimalFormat( "0.000" );
java.text.DecimalFormat n = new java.text.DecimalFormat( "00" );
println "Distance totale: ${f.format(distance)} km"
partiels.eachWithIndex { d, i ->
    println "${n.format(i)}) ${f.format(d)} km"
}

Archives

KML 2.1

Code Block
/**
 * Compute distance in Google Earth KML path file from a path
 * @author Marc DEXET ( marcdexet [at] gmail [dot] org )
*/
class Point {
    def lat
    def lon
    public Point(){}

    public Point(String gps) {
        def xyz = gps.tokenize(',');
        lat = Double.parseDouble( xyz[1] )
        lon = Double.parseDouble( xyz[0] )
    }
    public String toString() {
        return "LAT: ${lat} LON: ${lon}"
    }

    public static double distance(Point p0, Point p1) {
        return Haversine.compute(p0, p1)
    }
}

/**
 * List of Points
 */
class PointList {
    def points
    def distance
    def partiels = []

    public PointList( List points ) {
        this.points = points
        compute()
    }

    void compute() {
        def nbPointList = points.size()
        distance = 0;
        partiels = []
        for( idx in 1..(nbPointList-1) ) {
            def p0 = points[(idx-1)]
            def p1 = points[idx]
            def dist = Point.distance(p0,p1)
            partiels << dist
            distance = distance+dist
        }
    }

}
/**
 * Haversine algorithmus
 * (thanks to http://www.movable-type.co.uk/scripts/latlong.html)
 */
class Haversine {
    static double R = 6371

    static double compute(Point p1, Point p2) {
        def dLat = Math.toRadians(p2.lat-p1.lat);
        def dLon = Math.toRadians(p2.lon-p1.lon);
        def a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                Math.cos( Math.toRadians(p1.lat) ) *
                Math.cos( Math.toRadians(p2.lat) ) * Math.sin(dLon/2) * Math.sin(dLon/2);
        def c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
        def d = R * c;
        return d
    }

}

class KmlParser {
    static ns = new groovy.xml.Namespace("http://earth.google.com/kml/2.1", 'ns')

    List parse( Object input ) {
            def kml = new groovy.util.XmlParser().parse( input );
            def coords = kml[ ns.Document ][ ns.Placemark ][ ns.LineString ][ ns.coordinates ].value[0]
            def myList = coords.tokenize();
            def points = []
            myList.each{ gestring -> points << new Point(gestring) }
            return points;
    }
}

// Application

def kmlParser = new KmlParser()
def points = kmlParser.parse( args[0] )
def PointList pointList = new PointList( points )
def partiels = pointList.partiels;
def distance = pointList.distance;

java.text.DecimalFormat f = new java.text.DecimalFormat( "0.000" );
java.text.DecimalFormat n = new java.text.DecimalFormat( "00" );
println "Distance totale: ${f.format(distance)} km"
partiels.eachWithIndex { d, i ->
    println "${n.format(i)}) ${f.format(d)} km"
}