Draw a cubic spline curve through Google Earth Placemarks
This YouTube video demonstrates the script in action:
You might want to do this, for instance, to create a path for a Camera to follow. I thought at first I would use such a curve to define the flightpath of an animated model aircraft but I realised quite soon that aircraft don’t fly along cubic splines and I needed a different approach to that problem. That’s partly why I’ve only taken the solution this far; I may come back to it later to describe how the camera flies as it follows the aircraft.
All I’ve done is to bring together bits and pieces from the following resources:
- The Google Code Playground
- The earth api utility library
- cubic spline functions provided by Ivan Kuckir at the Faculty of Mathematics and Physics at Charles University in Prague.
Fragment 1: initialisation
In this code fragment scripts are imported, variables defined, and Google Earth loaded. Note that in the version displayed here the spline calculations are in a separate file, whereas in the source code on Pastebin I’ve dropped them into the main script; this was purely to reduce the number of file downloads you need to get started.
Two buttons are added to the screen:
- A button to fetch a KML file that holds Placemarks. This could be expanded into some sort of file-open dialogue, but I haven’t done that.
- A button to run the spline calculation.
Line 29 is the call to create an instance of the Google Earth plugin; it names the <div> element where it should be displayed and identifies the callback function if the plugin is successfully loaded.
Line 34 calls the resize() function to maximise the size of the Earth viewer.
Fragment 2: resize the screen and initialise the plugin
Line 39 defines the function to resize the Google Earth plugin so it uses most of the available space. A little room is needed beneath the plugin to show the control buttons.
Line 50 defines the callback function which is executed after the plugin is created. The variable ‘gex’ at line 51 becomes an instance of Google Earth Extensions, which is a utility library that the script uses to navigate KML objects.
This is followed by setting up event listeners to monitor the user’s mouse, detecting mousedown, mousemove, and mouseup actions. Together these allow Placemarks to be dragged to new locations. This code was mostly copied from the Google Code Playground, but the code at lines 83 and 84 are extra. The ‘clearLineStrings’ method will remove any existing spline curves from the view, while ‘calculateSpine’ recomputes and redraws the curve based on the new Placemark positions.
Fragment 3: Fetch a KML file containing Placemarks
Line 93 defines a function to fetch and display a KML file. Line 96 sets the URL of the file. The address shown here will be valid for a while but is not guaranteed so, if you want to play with this code, you will need to copy this file (available on Pastebin), or create your own.
If the file is fetched successfully, the object returned is assigned to global variable ‘designInput’. If there’s a top-level view available, either a <LookAt> or a <Camera>, the plugin viewer navigates to that view using the code at line 106.
Fragment 4: Extract Placemarks to an array
The ‘getPlacemarks’ function, at line 111, is used to find the Placemarks in the input file and copy them to an array. Line 120 makes a call to function ‘getObjectById’. This function searches the input file for a Folder node with id set to ‘PlacemarkFolder’; this is how the input file happens to be structured; you might have other Placemarks in it but this method only operates on those that you place in the ‘PlacemarkFolder’. You can change this behaviour easily enough.
If the Folder is found, the GE Extensions API is used to find all the Placemarks it contains. Each Placemark is added to array ‘result’ which is returned to the caller.
Fragment 5: Cubic Spline Part 1
When the KML file has been loaded, you click on the ‘Fit Spline Curve’ button and this action calls the ‘calculateSpline’ function. Line 142 is where ‘getPlacemarks’ is called. If Placemarks were found, the longitude and latitude of each Placemark are extracted and added to their respective arrays (x for longitude and y for latitude). Sorry about the typo at line 144; how unprofessional 🙂
At line 160, Mr. Kuckir’s cubic spline algorithm is called to calculate the required derivatives. It is beyond my ability to describe how this works, so I’m using it as a black box of tricks (see his article for more detail).
Fragment 6: Cubic Spline Part 2
With the derivatives calculated, it is possible to generate the cubic spline curve. This will be displayed as a KmlLineString, so the first thing to do is to create a Placemark to hold the LineString geometry. Notice that the Placemark is created, at line 163, giving it a unique id which begins with the string ‘SplineCurve’. This makes it easier to remove when the input Placemarks are dragged and we want to show the new curve.
The next step is to iterate through successive pairs of Placemarks. The difference between their longitudes is calculated, and that difference is divided into 100 intermediate points (line 172). For each intermediate longitude, a latitude is calculated using the ‘CubicSpline.interpolate’ function (line 181). This point on the spline curve is added to the LineString with the function call at line 187.
When all pairs of Placemarks have been processed, the resulting curve is displayed by added the LineString Placemark to the plugin’s feature list.
Fragment 7: Supporting functions
- addToLineString adds the given point to the given LineString.
- clearLineStrings navigates through the features added to the plugin instance and removes any Placemark that has an id beginning with ‘SplineCurve’.
- getObjectById searches the features in the plugin for an object with the given id.
Fragment 8: Completing the head element and defining the body element
There is one more function to describe; this is the addButton function which was copied from the Google Code Playground. It provides a way to add command buttons to an HTML page.
Finally, the body of the HTML page is defined. The div with id=’viewKML’ is the place where the Google Earth plugin is displayed.
The script has its limitations and, in many ways, it is a first crude attempt at providing a way to draw spline curves between Placemarks. You will need to take it further if you want something more general purpose. The major limitations are:
- The spline curve interpolation assumes that longitude is monotonically increasing; it calculates the latitude for a given longitude.
- The script takes no account of altitude when generating the LineString; all line segments are set to an altitude of 1.0 metres.
- No way is provided to extract the LineString coordinates.
Don’t forget, if you do download the code, I’ve commented out the URL of the KML input file and I would recommend that you create your own and place it on your own server.
Good luck, and a happy new year.
Copyright © Colin Hazlehurst, 2014