Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>Cubic Spline Experiments</title>
- <script type="text/javascript" src="script/extensions-0.2.1.js"></script>
- <script type="text/javascript" src="https://www.google.com/jsapi"></script>
- <script type="text/javascript" language="javascript">
- var ge; // Google Earth instance
- var w, d, e, g; // variables for window, document, documentElement, and body
- var dragInfo = null; // variable identifying the Placemark being dragged
- var designInput = null; // kmlObject holding the Placemarks
- var gex; // Google Earth Extensions instance
- var placeMarks = []; // array of Placemarks extracted from designInput
- var lineStringIndex = 0; // LineString id suffix to ensure uniqueness
- google.load("earth", "1"); // load Google Earth
- google.setOnLoadCallback(init); // identify callback method
- function init() {
- w = window; // get abbreviated names for window, document etc.
- d = document; // for use in the resize method
- e = d.documentElement;
- g = d.getElementsByTagName('body')[0];
- w.onresize = resize;
- // create the Google Earth instance, specifying callback methods
- google.earth.createInstance('viewKML', kmlViewerCreated, failureCB);
- // add buttons to fetch a KMLfile and calculate the spline curve
- addButton('Open File', fetchInput);
- addButton('Fit Spline Curve', calculateSpline);
- resize(); // resize the Google Earth instance
- }
- // resize the Google Earth instance to fill the available screen
- function resize() {
- var x = w.innerWidth || e.clientWidth || g.clientWidth;
- var y = w.innerHeight || e.clientHeight || g.clientHeight;
- var v = document.getElementById('viewKML');
- var counter = 0;
- if (v) {
- v.style.width = (x - 20) + 'px';
- v.style.height = (y - 80) + 'px';
- }
- }
- // handle the successful creation of the Google Earth instance
- function kmlViewerCreated(instance) {
- ge = instance; // short name for the Google Earth instance
- gex = new GEarthExtensions(ge); // create instance of the GE Extensions API
- // SET UP EVENT LISTENERS TO IMPLEMENT PLACEMARK DRAGGING
- // ======================================================
- // This code was copied from the Code Playground at:
- // http://code.google.com/apis/ajax/playground/?exp=earth#draggable_placemark
- // listen for mousedown on the window (look specifically for point placemarks)
- google.earth.addEventListener(ge.getWindow(), 'mousedown', function (event) {
- if (event.getTarget().getType() == 'KmlPlacemark' &&
- event.getTarget().getGeometry().getType() == 'KmlPoint') {
- var placemark = event.getTarget();
- dragInfo = {
- placemark: event.getTarget(),
- dragged: false
- };
- }
- });
- // listen for mousemove on the globe
- google.earth.addEventListener(ge.getGlobe(), 'mousemove', function (event) {
- if (dragInfo) {
- event.preventDefault();
- var point = dragInfo.placemark.getGeometry();
- point.setLatitude(event.getLatitude());
- point.setLongitude(event.getLongitude());
- dragInfo.dragged = true;
- }
- });
- // listen for mouseup on the window
- google.earth.addEventListener(ge.getWindow(), 'mouseup', function (event) {
- if (dragInfo) {
- if (dragInfo.dragged) {
- // if the placemark was dragged, prevent balloons from popping up
- event.preventDefault();
- }
- dragInfo = null;
- clearLinestrings(); // when a drag completes, remove the previous LineString
- calculateSpline(); // and recalculate the spline using the new points
- }
- });
- // END OF DRAGGABLE PLACEMARK CODE
- }
- function failureCB(errorCode) {
- alert('Failed to create Google Earth instance with error: ' + errorCode);
- }
- // get a kml file which holds a set of Placemarks
- function fetchInput() {
- // identify the kml file to load
- // =============================
- // set the URL of your own file here.
- var href = '*************************';
- // get the kml file and show its placemarks
- google.earth.fetchKml(ge, href, function (kmlObject) {
- if (kmlObject) {
- designInput = kmlObject;
- ge.getFeatures().appendChild(kmlObject);
- // if there's a view available, use it
- if (kmlObject.getAbstractView())
- ge.getView().setAbstractView(kmlObject.getAbstractView());
- }
- });
- }
- // calculate and display a cubic spline curve through the given Placemarks
- function calculateSpline() {
- // extract the Placemarks as an array
- placeMarks = getPlacemarks(designInput);
- // if Placemaraks were found
- if (placeMarks.length > 0) {
- var i = 0; // while loop index
- var j; // interpolation index
- var x = []; // array of longitudes
- var y = []; // array of latitudes
- var d = []; // array of derivatives
- // for each Placemark in the array
- while (i < placeMarks.length) {
- var point = placeMarks[i++].getGeometry(); // get the geometry
- x.push(point.getLongitude()); // extract longitude
- y.push(point.getLatitude()); // and latitude
- }
- // calculate array of derivatives
- CubicSpline.derivatives(x, y, d);
- // create a Placemark with a LineString geometry, giving it a unique id
- var lineStringPlacemark = ge.createPlacemark('SplineCurve' + lineStringIndex++);
- var lineString = ge.createLineString('');
- lineStringPlacemark.setGeometry(lineString);
- i = 0;
- // for each pair of points
- while (i < placeMarks.length) {
- // divide the difference in longitude into 100 increments
- var deltaLong = (x[i + 1] - x[i]) / 100;
- // for each intermediate point
- for (j = 0; j < 100; j++) {
- // calculate its longitude
- var lng = x[i] + (j * deltaLong);
- // interpolate the latitude
- var lat = CubicSpline.interpolate(lng, x, y, d);
- // if a valid point is derived
- if (!(isNaN(lat) || isNaN(lng))) {
- // add the point to the LineString geometry
- addToLineString(lineString, lat, lng, 0, 0, 0,1.0);
- }
- }
- i++;
- }
- // add the Placemark to Google Earth
- ge.getFeatures().appendChild(lineStringPlacemark);
- }
- else {
- alert('no placemarks found');
- }
- }
- // extract Placemarks to an array
- function getPlacemarks(input) {
- var result = []; // array of Placemarks returned to caller
- // the required objects exist
- if (input && gex) {
- // get the Placemark Folder (in the sample file they are
- // in a Folder with id set to 'PlacemarkFolder')
- var pf = getObjectById('PlacemarkFolder');
- // if the Placemark Folder is found
- if (pf) {
- // Walk fhe Folder finding the Placemarks
- gex.dom.walk({
- rootObject: pf,
- visitCallback: function () {
- if ('getType' in this && this.getType() == 'KmlPlacemark')
- result.push(this);
- }
- });
- }
- }
- // return a Placemark array to the caller
- return result;
- }
- // add a segment to a LineString
- function addToLineString(lineString, lat, lng, latOffset, lngOffset, altitude) {
- lineString.getCoordinates().
- pushLatLngAlt(lat + latOffset, lng + lngOffset, altitude);
- }
- // clear all Placemarks identified as SplineCurves
- function clearLinestrings() {
- gex.dom.walk({
- rootObject: ge,
- visitCallback: function () {
- // if the current node is a Placemark whose id begins with 'SplineCurve'
- if ('getType' in this && this.getType() == 'KmlPlacemark') {
- if (this.getId().indexOf('SplineCurve') >= 0) {
- // remove from the Feature Container
- ge.getFeatures().removeChild(this);
- }
- }
- }
- });
- }
- // find an object in the Google Earth instance with the given id
- function getObjectById(id) {
- var foundObject = null;
- // Traverse the DOM until the object is found
- gex.dom.walk({
- rootObject: ge,
- visitCallback: function () {
- if ('getId' in this && this.getId() == id) {
- foundObject = this;
- return false; // Stop the walk.
- }
- }
- });
- return foundObject;
- }
- // flexible way to add command buttons
- // (as used widely in the Code Playground)
- function addButton(caption, clickHandler) {
- var btn = document.createElement('input');
- btn.type = 'button';
- btn.value = caption;
- if (btn.attachEvent)
- btn.attachEvent('onclick', clickHandler);
- else
- btn.addEventListener('click', clickHandler, false);
- // add the button to the Sample UI
- document.getElementById('content').appendChild(btn);
- }
- function CubicSpline() { };
- CubicSpline._gaussJ = {};
- CubicSpline._gaussJ.solve = function (A, x) // in Matrix, out solutions
- {
- var m = A.length;
- for (var k = 0; k < m; k++) // column
- {
- // pivot for column
- var i_max = 0; var vali = Number.NEGATIVE_INFINITY;
- for (var i = k; i < m; i++) if (A[i][k] > vali) { i_max = i; vali = A[i][k]; }
- CubicSpline._gaussJ.swapRows(A, k, i_max);
- if (A[i_max][i] == 0) console.log("matrix is singular!");
- // for all rows below pivot
- for (var i = k + 1; i < m; i++) {
- for (var j = k + 1; j < m + 1; j++)
- A[i][j] = A[i][j] - A[k][j] * (A[i][k] / A[k][k]);
- A[i][k] = 0;
- }
- }
- for (var i = m - 1; i >= 0; i--) // rows = columns
- {
- var v = A[i][m] / A[i][i];
- x[i] = v;
- for (var j = i - 1; j >= 0; j--) // rows
- {
- A[j][m] -= A[j][i] * v;
- A[j][i] = 0;
- }
- }
- }
- CubicSpline._gaussJ.zerosMat = function (r, c) { var A = []; for (var i = 0; i < r; i++) { A.push([]); for (var j = 0; j < c; j++) A[i].push(0); } return A; }
- CubicSpline._gaussJ.printMat = function (A) { for (var i = 0; i < A.length; i++) console.log(A[i]); }
- CubicSpline._gaussJ.swapRows = function (m, k, l) { var p = m[k]; m[k] = m[l]; m[l] = p; }
- CubicSpline.derivatives = function (xs, ys, ks) // in x values, in y values, out k values
- {
- var n = xs.length - 1;
- var A = CubicSpline._gaussJ.zerosMat(n + 1, n + 2);
- for (var i = 1; i < n; i++) // rows
- {
- A[i][i - 1] = 1 / (xs[i] - xs[i - 1]);
- A[i][i] = 2 * (1 / (xs[i] - xs[i - 1]) + 1 / (xs[i + 1] - xs[i]));
- A[i][i + 1] = 1 / (xs[i + 1] - xs[i]);
- A[i][n + 1] = 3 * ((ys[i] - ys[i - 1]) / ((xs[i] - xs[i - 1]) * (xs[i] - xs[i - 1])) + (ys[i + 1] - ys[i]) / ((xs[i + 1] - xs[i]) * (xs[i + 1] - xs[i])));
- }
- A[0][0] = 2 / (xs[1] - xs[0]);
- A[0][1] = 1 / (xs[1] - xs[0]);
- A[0][n + 1] = 3 * (ys[1] - ys[0]) / ((xs[1] - xs[0]) * (xs[1] - xs[0]));
- A[n][n - 1] = 1 / (xs[n] - xs[n - 1]);
- A[n][n] = 2 / (xs[n] - xs[n - 1]);
- A[n][n + 1] = 3 * (ys[n] - ys[n - 1]) / ((xs[n] - xs[n - 1]) * (xs[n] - xs[n - 1]));
- CubicSpline._gaussJ.solve(A, ks);
- }
- CubicSpline.interpolate = function (x, xs, ys, ks) {
- var i = 1;
- while (xs[i] < x) i++;
- var t = (x - xs[i - 1]) / (xs[i] - xs[i - 1]);
- var a = ks[i - 1] * (xs[i] - xs[i - 1]) - (ys[i] - ys[i - 1]);
- var b = -ks[i] * (xs[i] - xs[i - 1]) + (ys[i] - ys[i - 1]);
- var q = (1 - t) * ys[i - 1] + t * ys[i] + t * (1 - t) * (a * (1 - t) + b * t);
- return q;
- }
- </script>
- </head>
- <body>
- <div id="content">
- <div id="viewKML"/>
- </div>
- </body>
- </html>
Add Comment
Please, Sign In to add comment