spline.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. /**
  4. * BezierSpline
  5. * https://github.com/leszekr/bezier-spline-js
  6. *
  7. * @private
  8. * @copyright
  9. * Copyright (c) 2013 Leszek Rybicki
  10. *
  11. * Permission is hereby granted, free of charge, to any person obtaining a copy
  12. * of this software and associated documentation files (the "Software"), to deal
  13. * in the Software without restriction, including without limitation the rights
  14. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15. * copies of the Software, and to permit persons to whom the Software is
  16. * furnished to do so, subject to the following conditions:
  17. *
  18. * The above copyright notice and this permission notice shall be included in all
  19. * copies or substantial portions of the Software.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  24. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  26. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  27. * SOFTWARE.
  28. */
  29. var Spline = /** @class */ (function () {
  30. function Spline(options) {
  31. this.points = options.points || [];
  32. this.duration = options.duration || 10000;
  33. this.sharpness = options.sharpness || 0.85;
  34. this.centers = [];
  35. this.controls = [];
  36. this.stepLength = options.stepLength || 60;
  37. this.length = this.points.length;
  38. this.delay = 0;
  39. // this is to ensure compatibility with the 2d version
  40. for (var i = 0; i < this.length; i++) {
  41. this.points[i].z = this.points[i].z || 0;
  42. }
  43. for (var i = 0; i < this.length - 1; i++) {
  44. var p1 = this.points[i];
  45. var p2 = this.points[i + 1];
  46. this.centers.push({
  47. x: (p1.x + p2.x) / 2,
  48. y: (p1.y + p2.y) / 2,
  49. z: (p1.z + p2.z) / 2,
  50. });
  51. }
  52. this.controls.push([this.points[0], this.points[0]]);
  53. for (var i = 0; i < this.centers.length - 1; i++) {
  54. var dx = this.points[i + 1].x - (this.centers[i].x + this.centers[i + 1].x) / 2;
  55. var dy = this.points[i + 1].y - (this.centers[i].y + this.centers[i + 1].y) / 2;
  56. var dz = this.points[i + 1].z - (this.centers[i].y + this.centers[i + 1].z) / 2;
  57. this.controls.push([
  58. {
  59. x: (1.0 - this.sharpness) * this.points[i + 1].x +
  60. this.sharpness * (this.centers[i].x + dx),
  61. y: (1.0 - this.sharpness) * this.points[i + 1].y +
  62. this.sharpness * (this.centers[i].y + dy),
  63. z: (1.0 - this.sharpness) * this.points[i + 1].z +
  64. this.sharpness * (this.centers[i].z + dz),
  65. },
  66. {
  67. x: (1.0 - this.sharpness) * this.points[i + 1].x +
  68. this.sharpness * (this.centers[i + 1].x + dx),
  69. y: (1.0 - this.sharpness) * this.points[i + 1].y +
  70. this.sharpness * (this.centers[i + 1].y + dy),
  71. z: (1.0 - this.sharpness) * this.points[i + 1].z +
  72. this.sharpness * (this.centers[i + 1].z + dz),
  73. },
  74. ]);
  75. }
  76. this.controls.push([
  77. this.points[this.length - 1],
  78. this.points[this.length - 1],
  79. ]);
  80. this.steps = this.cacheSteps(this.stepLength);
  81. return this;
  82. }
  83. /**
  84. * Caches an array of equidistant (more or less) points on the curve.
  85. */
  86. Spline.prototype.cacheSteps = function (mindist) {
  87. var steps = [];
  88. var laststep = this.pos(0);
  89. steps.push(0);
  90. for (var t = 0; t < this.duration; t += 10) {
  91. var step = this.pos(t);
  92. var dist = Math.sqrt((step.x - laststep.x) * (step.x - laststep.x) +
  93. (step.y - laststep.y) * (step.y - laststep.y) +
  94. (step.z - laststep.z) * (step.z - laststep.z));
  95. if (dist > mindist) {
  96. steps.push(t);
  97. laststep = step;
  98. }
  99. }
  100. return steps;
  101. };
  102. /**
  103. * returns angle and speed in the given point in the curve
  104. */
  105. Spline.prototype.vector = function (t) {
  106. var p1 = this.pos(t + 10);
  107. var p2 = this.pos(t - 10);
  108. return {
  109. angle: (180 * Math.atan2(p1.y - p2.y, p1.x - p2.x)) / 3.14,
  110. speed: Math.sqrt((p2.x - p1.x) * (p2.x - p1.x) +
  111. (p2.y - p1.y) * (p2.y - p1.y) +
  112. (p2.z - p1.z) * (p2.z - p1.z)),
  113. };
  114. };
  115. /**
  116. * Gets the position of the point, given time.
  117. *
  118. * WARNING: The speed is not constant. The time it takes between control points is constant.
  119. *
  120. * For constant speed, use Spline.steps[i];
  121. */
  122. Spline.prototype.pos = function (time) {
  123. var t = time - this.delay;
  124. if (t < 0) {
  125. t = 0;
  126. }
  127. if (t > this.duration) {
  128. t = this.duration - 1;
  129. }
  130. // t = t-this.delay;
  131. var t2 = t / this.duration;
  132. if (t2 >= 1) {
  133. return this.points[this.length - 1];
  134. }
  135. var n = Math.floor((this.points.length - 1) * t2);
  136. var t1 = (this.length - 1) * t2 - n;
  137. return bezier(t1, this.points[n], this.controls[n][1], this.controls[n + 1][0], this.points[n + 1]);
  138. };
  139. return Spline;
  140. }());
  141. exports.default = Spline;
  142. function bezier(t, p1, c1, c2, p2) {
  143. var b = B(t);
  144. var pos = {
  145. x: p2.x * b[0] + c2.x * b[1] + c1.x * b[2] + p1.x * b[3],
  146. y: p2.y * b[0] + c2.y * b[1] + c1.y * b[2] + p1.y * b[3],
  147. z: p2.z * b[0] + c2.z * b[1] + c1.z * b[2] + p1.z * b[3],
  148. };
  149. return pos;
  150. }
  151. function B(t) {
  152. var t2 = t * t;
  153. var t3 = t2 * t;
  154. return [
  155. t3,
  156. 3 * t2 * (1 - t),
  157. 3 * t * (1 - t) * (1 - t),
  158. (1 - t) * (1 - t) * (1 - t),
  159. ];
  160. }