pchip1.js 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // Copyright 2012 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview A one dimensional monotone cubic spline interpolator.
  16. *
  17. * See http://en.wikipedia.org/wiki/Monotone_cubic_interpolation.
  18. *
  19. */
  20. goog.provide('goog.math.interpolator.Pchip1');
  21. goog.require('goog.math');
  22. goog.require('goog.math.interpolator.Spline1');
  23. /**
  24. * A one dimensional monotone cubic spline interpolator.
  25. * @extends {goog.math.interpolator.Spline1}
  26. * @constructor
  27. * @final
  28. */
  29. goog.math.interpolator.Pchip1 = function() {
  30. goog.math.interpolator.Pchip1.base(this, 'constructor');
  31. };
  32. goog.inherits(goog.math.interpolator.Pchip1, goog.math.interpolator.Spline1);
  33. /** @override */
  34. goog.math.interpolator.Pchip1.prototype.computeDerivatives = function(
  35. dx, slope) {
  36. var len = dx.length;
  37. var deriv = new Array(len + 1);
  38. for (var i = 1; i < len; ++i) {
  39. if (goog.math.sign(slope[i - 1]) * goog.math.sign(slope[i]) <= 0) {
  40. deriv[i] = 0;
  41. } else {
  42. var w1 = 2 * dx[i] + dx[i - 1];
  43. var w2 = dx[i] + 2 * dx[i - 1];
  44. deriv[i] = (w1 + w2) / (w1 / slope[i - 1] + w2 / slope[i]);
  45. }
  46. }
  47. deriv[0] =
  48. this.computeDerivativeAtBoundary_(dx[0], dx[1], slope[0], slope[1]);
  49. deriv[len] = this.computeDerivativeAtBoundary_(
  50. dx[len - 1], dx[len - 2], slope[len - 1], slope[len - 2]);
  51. return deriv;
  52. };
  53. /**
  54. * Computes the derivative of a data point at a boundary.
  55. * @param {number} dx0 The spacing of the 1st data point.
  56. * @param {number} dx1 The spacing of the 2nd data point.
  57. * @param {number} slope0 The slope of the 1st data point.
  58. * @param {number} slope1 The slope of the 2nd data point.
  59. * @return {number} The derivative at the 1st data point.
  60. * @private
  61. */
  62. goog.math.interpolator.Pchip1.prototype.computeDerivativeAtBoundary_ = function(
  63. dx0, dx1, slope0, slope1) {
  64. var deriv = ((2 * dx0 + dx1) * slope0 - dx0 * slope1) / (dx0 + dx1);
  65. if (goog.math.sign(deriv) != goog.math.sign(slope0)) {
  66. deriv = 0;
  67. } else if (
  68. goog.math.sign(slope0) != goog.math.sign(slope1) &&
  69. Math.abs(deriv) > Math.abs(3 * slope0)) {
  70. deriv = 3 * slope0;
  71. }
  72. return deriv;
  73. };