123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- goog.provide('goog.math.Bezier');
- goog.require('goog.math');
- goog.require('goog.math.Coordinate');
- goog.math.Bezier = function(x0, y0, x1, y1, x2, y2, x3, y3) {
-
- this.x0 = x0;
-
- this.y0 = y0;
-
- this.x1 = x1;
-
- this.y1 = y1;
-
- this.x2 = x2;
-
- this.y2 = y2;
-
- this.x3 = x3;
-
- this.y3 = y3;
- };
- goog.math.Bezier.KAPPA = 4 * (Math.sqrt(2) - 1) / 3;
- goog.math.Bezier.prototype.clone = function() {
- return new goog.math.Bezier(
- this.x0, this.y0, this.x1, this.y1, this.x2, this.y2, this.x3, this.y3);
- };
- goog.math.Bezier.prototype.equals = function(other) {
- return this.x0 == other.x0 && this.y0 == other.y0 && this.x1 == other.x1 &&
- this.y1 == other.y1 && this.x2 == other.x2 && this.y2 == other.y2 &&
- this.x3 == other.x3 && this.y3 == other.y3;
- };
- goog.math.Bezier.prototype.flip = function() {
- var temp = this.x0;
- this.x0 = this.x3;
- this.x3 = temp;
- temp = this.y0;
- this.y0 = this.y3;
- this.y3 = temp;
- temp = this.x1;
- this.x1 = this.x2;
- this.x2 = temp;
- temp = this.y1;
- this.y1 = this.y2;
- this.y2 = temp;
- };
- goog.math.Bezier.prototype.getPointX = function(t) {
-
- if (t == 0) {
- return this.x0;
- } else if (t == 1) {
- return this.x3;
- }
-
- var ix0 = goog.math.lerp(this.x0, this.x1, t);
- var ix1 = goog.math.lerp(this.x1, this.x2, t);
- var ix2 = goog.math.lerp(this.x2, this.x3, t);
-
- ix0 = goog.math.lerp(ix0, ix1, t);
- ix1 = goog.math.lerp(ix1, ix2, t);
-
- return goog.math.lerp(ix0, ix1, t);
- };
- goog.math.Bezier.prototype.getPointY = function(t) {
-
- if (t == 0) {
- return this.y0;
- } else if (t == 1) {
- return this.y3;
- }
-
- var iy0 = goog.math.lerp(this.y0, this.y1, t);
- var iy1 = goog.math.lerp(this.y1, this.y2, t);
- var iy2 = goog.math.lerp(this.y2, this.y3, t);
-
- iy0 = goog.math.lerp(iy0, iy1, t);
- iy1 = goog.math.lerp(iy1, iy2, t);
-
- return goog.math.lerp(iy0, iy1, t);
- };
- goog.math.Bezier.prototype.getPoint = function(t) {
- return new goog.math.Coordinate(this.getPointX(t), this.getPointY(t));
- };
- goog.math.Bezier.prototype.subdivideLeft = function(t) {
- if (t == 1) {
- return;
- }
-
- var ix0 = goog.math.lerp(this.x0, this.x1, t);
- var iy0 = goog.math.lerp(this.y0, this.y1, t);
- var ix1 = goog.math.lerp(this.x1, this.x2, t);
- var iy1 = goog.math.lerp(this.y1, this.y2, t);
- var ix2 = goog.math.lerp(this.x2, this.x3, t);
- var iy2 = goog.math.lerp(this.y2, this.y3, t);
-
- this.x1 = ix0;
- this.y1 = iy0;
-
- ix0 = goog.math.lerp(ix0, ix1, t);
- iy0 = goog.math.lerp(iy0, iy1, t);
- ix1 = goog.math.lerp(ix1, ix2, t);
- iy1 = goog.math.lerp(iy1, iy2, t);
-
- this.x2 = ix0;
- this.y2 = iy0;
-
- this.x3 = goog.math.lerp(ix0, ix1, t);
- this.y3 = goog.math.lerp(iy0, iy1, t);
- };
- goog.math.Bezier.prototype.subdivideRight = function(t) {
- this.flip();
- this.subdivideLeft(1 - t);
- this.flip();
- };
- goog.math.Bezier.prototype.subdivide = function(s, t) {
- this.subdivideRight(s);
- this.subdivideLeft((t - s) / (1 - s));
- };
- goog.math.Bezier.prototype.solvePositionFromXValue = function(xVal) {
-
- var epsilon = 1e-6;
-
- var t = (xVal - this.x0) / (this.x3 - this.x0);
- if (t <= 0) {
- return 0;
- } else if (t >= 1) {
- return 1;
- }
-
- var tMin = 0;
- var tMax = 1;
- var value = 0;
- for (var i = 0; i < 8; i++) {
- value = this.getPointX(t);
- var derivative = (this.getPointX(t + epsilon) - value) / epsilon;
- if (Math.abs(value - xVal) < epsilon) {
- return t;
- } else if (Math.abs(derivative) < epsilon) {
- break;
- } else {
- if (value < xVal) {
- tMin = t;
- } else {
- tMax = t;
- }
- t -= (value - xVal) / derivative;
- }
- }
-
-
-
- for (var i = 0; Math.abs(value - xVal) > epsilon && i < 8; i++) {
- if (value < xVal) {
- tMin = t;
- t = (t + tMax) / 2;
- } else {
- tMax = t;
- t = (t + tMin) / 2;
- }
- value = this.getPointX(t);
- }
- return t;
- };
- goog.math.Bezier.prototype.solveYValueFromXValue = function(xVal) {
- return this.getPointY(this.solvePositionFromXValue(xVal));
- };
|