text: /*! JointJS v0.9.7 - JavaScript diagramming library  2016-01-18 
  
  
  This Source Code Form is subject to the terms of the Mozilla Public
  License, v. 2.0. If a copy of the MPL was not distributed with this
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
   */
  (function(root, factory) {
  
      if (typeof define === 'function' && define.amd) {
  
          // AMD. Register as an anonymous module.
          define([], factory);
  
      } else if (typeof exports === 'object') {
  
          // Node. Does not work with strict CommonJS, but
          // only CommonJS-like environments that support module.exports,
          // like Node.
          module.exports = factory();
  
      } else {
  
          // Browser globals.
          root.g = factory();
      }
  
  }(this, function() {
  
  //      Geometry library.
  //      (c) 2011-2015 client IO
  
  var g = (function() {
  
      // Declare shorthands to the most used math functions.
      var math = Math;
      var abs = math.abs;
      var cos = math.cos;
      var sin = math.sin;
      var sqrt = math.sqrt;
      var mmin = math.min;
      var mmax = math.max;
      var atan = math.atan;
      var atan2 = math.atan2;
      var acos = math.acos;
      var round = math.round;
      var floor = math.floor;
      var PI = math.PI;
      var random = math.random;
      var toDeg = function(rad) { return (180 * rad / PI) % 360; };
      var toRad = function(deg, over360) {
          over360 = over360 || false;
          deg = over360 ? deg : (deg % 360);
          return deg * PI / 180;
      };
      var snapToGrid = function(val, gridSize) { return gridSize * Math.round(val / gridSize); };
      var normalizeAngle = function(angle) { return (angle % 360) + (angle < 0 ? 360 : 0); };
  
      // Point
      // -----
  
      // Point is the most basic object consisting of x/y coordinate,.
  
      // Possible instantiations are:
  
      // * `point(10, 20)`
      // * `new point(10, 20)`
      // * `point('10 20')`
      // * `point(point(10, 20))`
      function point(x, y) {
          if (!(this instanceof point))
              return new point(x, y);
          var xy;
          if (y === undefined && Object(x) !== x) {
              xy = x.split(x.indexOf('@') === -1 ? ' ' : '@');
              this.x = parseInt(xy[0], 10);
              this.y = parseInt(xy[1], 10);
          } else if (Object(x) === x) {
              this.x = x.x;
              this.y = x.y;
          } else {
              this.x = x;
              this.y = y;
          }
      }
  
      point.prototype = {
          toString: function() {
              return this.x + '@' + this.y;
          },
          // If point lies outside rectangle `r`, return the nearest point on the boundary of rect `r`,
          // otherwise return point itself.
          // (see Squeak Smalltalk, Point>>adhereTo:)
          adhereToRect: function(r) {
              if (r.containsPoint(this)) {
                  return this;
              }
              this.x = mmin(mmax(this.x, r.x), r.x + r.width);
              this.y = mmin(mmax(this.y, r.y), r.y + r.height);
              return this;
          },
          // Compute the angle between me and `p` and the x axis.
          // (cartesian-to-polar coordinates conversion)
          // Return theta angle in degrees.
          theta: function(p) {
              p = point(p);
              // Invert the y-axis.
              var y = -(p.y - this.y);
              var x = p.x - this.x;
              // Makes sure that the comparison with zero takes rounding errors into account.
              var PRECISION = 10;
              // Note that `atan2` is not defined for `x`, `y` both equal zero.
              var rad = (y.toFixed(PRECISION) == 0 && x.toFixed(PRECISION) == 0) ? 0 : atan2(y, x);
  
              // Correction for III. and IV. quadrant.
              if (rad < 0) {
                  rad = 2 * PI + rad;
              }
              return 180 * rad / PI;
          },
          // Returns distance between me and point `p`.
          distance: function(p) {
              return line(this, p).length();
          },
          // Returns a manhattan (taxi-cab) distance between me and point `p`.
          manhattanDistance: function(p) {
              return abs(p.x - this.x) + abs(p.y - this.y);
          },
          // Offset me by the specified amount.
          offset: function(dx, dy) {
              this.x += dx || 0;
              this.y += dy || 0;
              return this;
          },
          magnitude: function() {
              return sqrt((this.x * this.x) + (this.y * this.y)) || 0.01;
          },
          update: function(x, y) {
              this.x = x || 0;
              this.y = y || 0;
              return this;
          },
          round: function(decimals) {
              this.x = decimals ? this.x.toFixed(decimals) : round(this.x);
              this.y = decimals ? this.y.toFixed(decimals) : round(this.y);
              return this;
          },
          // Scale the line segment between (0,0) and me to have a length of len.
          normalize: function(len) {
              var s = (len || 1) / this.magnitude();
              this.x = s * this.x;
              this.y = s * this.y;
              return this;
          },
          difference: function(p) {
              return point(this.x - p.x, this.y - p.y);
          },
          // Return the bearing between me and point `p`.
          bearing: function(p) {
              return line(this, p).bearing();
          },
          // Converts rectangular to polar coordinates.
          // An origin can be specified, otherwise it's 0@0.
          toPolar: function(o) {
              o = (o && point(o)) || point(0, 0);
              var x = this.x;
              var y = this.y;
              this.x = sqrt((x - o.x) * (x - o.x) + (y - o.y) * (y - o.y)); // r
              this.y = toRad(o.theta(point(x, y)));
              return this;
          },
          // Rotate point by angle around origin o.
          rotate: function(o, angle) {
              angle = (angle + 360) % 360;
              this.toPolar(o);
              this.y += toRad(angle);
              var p = point.fromPolar(this.x, this.y, o);
              this.x = p.x;
              this.y = p.y;
              return this;
          },
          // Move point on line starting from ref ending at me by
          // distance distance.
          move: function(ref, distance) {
              var theta = toRad(point(ref).theta(this));
              return this.offset(cos(theta) * distance, -sin(theta) * distance);
          },
          // Returns change in angle from my previous position (-dx, -dy) to my new position
          // relative to ref point.
          changeInAngle: function(dx, dy, ref) {
              // Revert the translation and measure the change in angle around x-axis.
              return point(this).offset(-dx, -dy).theta(ref) - this.theta(ref);
          },
          equals: function(p) {
              return this.x === p.x && this.y === p.y;
          },
          snapToGrid: function(gx, gy) {
              this.x = snapToGrid(this.x, gx);
              this.y = snapToGrid(this.y, gy || gx);
              return this;
          },
          // Returns a point that is the reflection of me with
          // the center of inversion in ref point.
          reflection: function(ref) {
              return point(ref).move(this, this.distance(ref));
          },
          clone: function() {
              return point(this);
          }
      };
      // Alternative constructor, from polar coordinates.
      // @param {number} r Distance.
      // @param {number} angle Angle in radians.
      // @param {point} [optional] o Origin.
      point.fromPolar = function(r, angle, o) {
          o = (o && point(o)) || point(0, 0);
          var x = abs(r * cos(angle));
          var y = abs(r * sin(angle));
          var deg = normalizeAngle(toDeg(angle));
  
          if (deg < 90) {
              y = -y;
          } else if (deg < 180) {
              x = -x;
              y = -y;
          } else if (deg < 270) {
              x = -x;
          }
  
          return point(o.x + x, o.y + y);
      };
  
      // Create a point with random coordinates that fall into the range `[x1, x2]` and `[y1, y2]`.
      point.random = function(x1, x2, y1, y2) {
          return point(floor(random() * (x2 - x1 + 1) + x1), floor(random() * (y2 - y1 + 1) + y1));
      };
  
      // Line.
      // -----
      function line(p1, p2) {
          if (!(this instanceof line))
              return new line(p1, p2);
          this.start = point(p1);
          this.end = point(p2);
      }
  
      line.prototype = {
          toString: function() {
              return this.start.toString() + ' ' + this.end.toString();
          },
          // @return {double} length of the line
          length: function() {
              return sqrt(this.squaredLength());
          },
          // @return {integer} length without sqrt
          // @note for applications where the exact length is not necessary (e.g. compare only)
          squaredLength: function() {
              var x0 = this.start.x;
              var y0 = this.start.y;
              var x1 = this.end.x;
              var y1 = this.end.y;
              return (x0 -= x1) * x0 + (y0 -= y1) * y0;
          },
          // @return {point} my midpoint
          midpoint: function() {
              return point((this.start.x + this.end.x) / 2,
                           (this.start.y + this.end.y) / 2);
          },
          // @return {point} Point where I'm intersecting l.
          // @see Squeak Smalltalk, LineSegment>>intersectionWith:
          intersection: function(l) {
              var pt1Dir = point(this.end.x - this.start.x, this.end.y - this.start.y);
              var pt2Dir = point(l.end.x - l.start.x, l.end.y - l.start.y);
              var det = (pt1Dir.x * pt2Dir.y) - (pt1Dir.y * pt2Dir.x);
              var deltaPt = point(l.start.x - this.start.x, l.start.y - this.start.y);
              var alpha = (deltaPt.x * pt2Dir.y) - (deltaPt.y * pt2Dir.x);
              var beta = (deltaPt.x * pt1Dir.y) - (deltaPt.y * pt1Dir.x);
  
              if (det === 0 ||
                  alpha * det < 0 ||
                  beta * det < 0) {
                  // No intersection found.
                  return null;
              }
              if (det > 0) {
                  if (alpha > det || beta > det) {
                      return null;
                  }
              } else {
                  if (alpha < det || beta < det) {
                      return null;
                  }
              }
              return point(this.start.x + (alpha * pt1Dir.x / det),
                           this.start.y + (alpha * pt1Dir.y / det));
          },
  
          // @return the bearing (cardinal direction) of the line. For example N, W, or SE.
          // @returns {String} One of the following bearings : NE, E, SE, S, SW, W, NW, N.
          bearing: function() {
  
              var lat1 = toRad(this.start.y);
              var lat2 = toRad(this.end.y);
              var lon1 = this.start.x;
              var lon2 = this.end.x;
              var dLon = toRad(lon2 - lon1);
              var y = sin(dLon) * cos(lat2);
              var x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);
              var brng = toDeg(atan2(y, x));
  
              var bearings = ['NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'N'];
  
              var index = brng - 22.5;
              if (index < 0)
                  index += 360;
              index = parseInt(index / 45);
  
              return bearings[index];
          },
  
          // @return {point} my point at 't' <0,1>
          pointAt: function(t) {
              var x = (1 - t) * this.start.x + t * this.end.x;
              var y = (1 - t) * this.start.y + t * this.end.y;
              return point(x, y);
          },
  
          // @return {number} the offset of the point `p` from the line. + if the point `p` is on the right side of the line, - if on the left and 0 if on the line.
          pointOffset: function(p) {
              // Find the sign of the determinant of vectors (start,end), where p is the query point.
              return ((this.end.x - this.start.x) * (p.y - this.start.y) - (this.end.y - this.start.y) * (p.x - this.start.x)) / 2;
          },
          clone: function() {
              return line(this);
          }
      };
  
      // Rectangle.
      // ----------
      function rect(x, y, w, h) {
          if (!(this instanceof rect))
              return new rect(x, y, w, h);
          if (y === undefined) {
              y = x.y;
              w = x.width;
              h = x.height;
              x = x.x;
          }
          this.x = x;
          this.y = y;
          this.width = w;
          this.height = h;
      }
  
      rect.prototype = {
          toString: function() {
              return this.origin().toString() + ' ' + this.corner().toString();
          },
          // @return {boolean} true if rectangles are equal.
          equals: function(r) {
              var mr = g.rect(this).normalize();
              var nr = g.rect(r).normalize();
              return mr.x === nr.x && mr.y === nr.y && mr.width === nr.width && mr.height === nr.height;
          },
          origin: function() {
              return point(this.x, this.y);
          },
          corner: function() {
              return point(this.x + this.width, this.y + this.height);
          },
          topRight: function() {
              return point(this.x + this.width, this.y);
          },
          bottomLeft: function() {
              return point(this.x, this.y + this.height);
          },
          center: function() {
              return point(this.x + this.width / 2, this.y + this.height / 2);
          },
          // @return {rect} if rectangles intersect, {null} if not.
          intersect: function(r) {
              var myOrigin = this.origin();
              var myCorner = this.corner();
              var rOrigin = r.origin();
              var rCorner = r.corner();
  
              // No intersection found
              if (rCorner.x <= myOrigin.x ||
                  rCorner.y <= myOrigin.y ||
                  rOrigin.x >= myCorner.x ||
                  rOrigin.y >= myCorner.y) return null;
  
              var x = Math.max(myOrigin.x, rOrigin.x);
              var y = Math.max(myOrigin.y, rOrigin.y);
  
              return rect(x, y, Math.min(myCorner.x, rCorner.x) - x, Math.min(myCorner.y, rCorner.y) - y);
          },
  
          // @return {rect} representing the union of both rectangles.
          union: function(r) {
              var myOrigin = this.origin();
              var myCorner = this.corner();
              var rOrigin = r.origin();
              var rCorner = r.corner();
  
              var originX = Math.min(myOrigin.x, rOrigin.x);
              var originY = Math.min(myOrigin.y, rOrigin.y);
              var cornerX = Math.max(myCorner.x, rCorner.x);
              var cornerY = Math.max(myCorner.y, rCorner.y);
  
              return rect(originX, originY, cornerX - originX, cornerY - originY);
          },
  
          // @return {string} (left|right|top|bottom) side which is nearest to point
          // @see Squeak Smalltalk, Rectangle>>sideNearestTo:
          sideNearestToPoint: function(p) {
              p = point(p);
              var distToLeft = p.x - this.x;
              var distToRight = (this.x + this.width) - p.x;
              var distToTop = p.y - this.y;
              var distToBottom = (this.y + this.height) - p.y;
              var closest = distToLeft;
              var side = 'left';
  
              if (distToRight < closest) {
                  closest = distToRight;
                  side = 'right';
              }
              if (distToTop < closest) {
                  closest = distToTop;
                  side = 'top';
              }
              if (distToBottom < closest) {
                  closest = distToBottom;
                  side = 'bottom';
              }
              return side;
          },
          // @return {bool} true if point p is insight me
          containsPoint: function(p) {
              p = point(p);
              if (p.x >= this.x && p.x <= this.x + this.width &&
                  p.y >= this.y && p.y <= this.y + this.height) {
                  return true;
              }
              return false;
          },
          // Algorithm ported from java.awt.Rectangle from OpenJDK.
          // @return {bool} true if rectangle `r` is inside me.
          containsRect: function(r) {
              var nr = rect(r).normalize();
              var W = nr.width;
              var H = nr.height;
              var X = nr.x;
              var Y = nr.y;
              var w = this.width;
              var h = this.height;
              if ((w | h | W | H) < 0) {
                  // At least one of the dimensions is negative...
                  return false;
              }
              // Note: if any dimension is zero, tests below must return false...
              var x = this.x;
              var y = this.y;
              if (X < x || Y < y) {
                  return false;
              }
              w += x;
              W += X;
              if (W <= X) {
                  // X+W overflowed or W was zero, return false if...
                  // either original w or W was zero or
                  // x+w did not overflow or
                  // the overflowed x+w is smaller than the overflowed X+W
                  if (w >= x || W > w) return false;
              } else {
                  // X+W did not overflow and W was not zero, return false if...
                  // original w was zero or
                  // x+w did not overflow and x+w is smaller than X+W
                  if (w >= x && W > w) return false;
              }
              h += y;
              H += Y;
              if (H <= Y) {
                  if (h >= y || H > h) return false;
              } else {
                  if (h >= y && H > h) return false;
              }
              return true;
          },
          // @return {point} a point on my boundary nearest to p
          // @see Squeak Smalltalk, Rectangle>>pointNearestTo:
          pointNearestToPoint: function(p) {
              p = point(p);
              if (this.containsPoint(p)) {
                  var side = this.sideNearestToPoint(p);
                  switch (side){
                      case 'right': return point(this.x + this.width, p.y);
                      case 'left': return point(this.x, p.y);
                      case 'bottom': return point(p.x, this.y + this.height);
                      case 'top': return point(p.x, this.y);
                  }
              }
              return p.adhereToRect(this);
          },
          // Find point on my boundary where line starting
          // from my center ending in point p intersects me.
          // @param {number} angle If angle is specified, intersection with rotated rectangle is computed.
          intersectionWithLineFromCenterToPoint: function(p, angle) {
              p = point(p);
              var center = point(this.x + this.width / 2, this.y + this.height / 2);
              var result;
              if (angle) p.rotate(center, angle);
  
              // (clockwise, starting from the top side)
              var sides = [
                  line(this.origin(), this.topRight()),
                  line(this.topRight(), this.corner()),
                  line(this.corner(), this.bottomLeft()),
                  line(this.bottomLeft(), this.origin())
              ];
              var connector = line(center, p);
  
              for (var i = sides.length - 1; i >= 0; --i) {
                  var intersection = sides[i].intersection(connector);
                  if (intersection !== null) {
                      result = intersection;
                      break;
                  }
              }
              if (result && angle) result.rotate(center, -angle);
              return result;
          },
          // Move and expand me.
          // @param r {rectangle} representing deltas
          moveAndExpand: function(r) {
              this.x += r.x || 0;
              this.y += r.y || 0;
              this.width += r.width || 0;
              this.height += r.height || 0;
              return this;
          },
          round: function(decimals) {
              this.x = decimals ? this.x.toFixed(decimals) : round(this.x);
              this.y = decimals ? this.y.toFixed(decimals) : round(this.y);
              this.width = decimals ? this.width.toFixed(decimals) : round(this.width);
              this.height = decimals ? this.height.toFixed(decimals) : round(this.height);
              return this;
          },
          // Normalize the rectangle; i.e., make it so that it has a non-negative width and height.
          // If width < 0 the function swaps the left and right corners,
          // and it swaps the top and bottom corners if height < 0
          // like in http://qt-project.org/doc/qt-4.8/qrectf.html#normalized
          normalize: function() {
              var newx = this.x;
              var newy = this.y;
              var newwidth = this.width;
              var newheight = this.height;
              if (this.width < 0) {
                  newx = this.x + this.width;
                  newwidth = -this.width;
              }
              if (this.height < 0) {
                  newy = this.y + this.height;
                  newheight = -this.height;
              }
              this.x = newx;
              this.y = newy;
              this.width = newwidth;
              this.height = newheight;
              return this;
          },
          // Find my bounding box when I'm rotated with the center of rotation in the center of me.
          // @return r {rectangle} representing a bounding box
          bbox: function(angle) {
              var theta = toRad(angle || 0);
              var st = abs(sin(theta));
              var ct = abs(cos(theta));
              var w = this.width * ct + this.height * st;
              var h = this.width * st + this.height * ct;
              return rect(this.x + (this.width - w) / 2, this.y + (this.height - h) / 2, w, h);
          },
          snapToGrid: function(gx, gy) {
              var origin = this.origin().snapToGrid(gx, gy);
              var corner = this.corner().snapToGrid(gx, gy);
              this.x = origin.x;
              this.y = origin.y;
              this.width = corner.x - origin.x;
              this.height = corner.y - origin.y;
              return this;
          },
          clone: function() {
              return rect(this);
          }
      };
  
      // Ellipse.
      // --------
      function ellipse(c, a, b) {
          if (!(this instanceof ellipse))
              return new ellipse(c, a, b);
          c = point(c);
          this.x = c.x;
          this.y = c.y;
          this.a = a;
          this.b = b;
      }
  
      ellipse.prototype = {
          toString: function() {
              return point(this.x, this.y).toString() + ' ' + this.a + ' ' + this.b;
          },
          bbox: function() {
              return rect(this.x - this.a, this.y - this.b, 2 * this.a, 2 * this.b);
          },
          // Find point on me where line from my center to
          // point p intersects my boundary.
          // @param {number} angle If angle is specified, intersection with rotated ellipse is computed.
          intersectionWithLineFromCenterToPoint: function(p, angle) {
              p = point(p);
              if (angle) p.rotate(point(this.x, this.y), angle);
              var dx = p.x - this.x;
              var dy = p.y - this.y;
              var result;
              if (dx === 0) {
                  result = this.bbox().pointNearestToPoint(p);
                  if (angle) return result.rotate(point(this.x, this.y), -angle);
                  return result;
              }
              var m = dy / dx;
              var mSquared = m * m;
              var aSquared = this.a * this.a;
              var bSquared = this.b * this.b;
              var x = sqrt(1 / ((1 / aSquared) + (mSquared / bSquared)));
  
              x = dx < 0 ? -x : x;
              var y = m * x;
              result = point(this.x + x, this.y + y);
              if (angle) return result.rotate(point(this.x, this.y), -angle);
              return result;
          },
          clone: function() {
              return ellipse(this);
          }
      };
  
      // Bezier curve.
      // -------------
      var bezier = {
          // Cubic Bezier curve path through points.
          // Ported from C# implementation by Oleg V. Polikarpotchkin and Peter Lee (http://www.codeproject.com/KB/graphics/BezierSpline.aspx).
          // @param {array} points Array of points through which the smooth line will go.
          // @return {array} SVG Path commands as an array
          curveThroughPoints: function(points) {
              var controlPoints = this.getCurveControlPoints(points);
              var path = ['M', points[0].x, points[0].y];
  
              for (var i = 0; i < controlPoints[0].length; i++) {
                  path.push('C', controlPoints[0][i].x, controlPoints[0][i].y, controlPoints[1][i].x, controlPoints[1][i].y, points[i + 1].x, points[i + 1].y);
              }
              return path;
          },
  
          // Get open-ended Bezier Spline Control Points.
          // @param knots Input Knot Bezier spline points (At least two points!).
          // @param firstControlPoints Output First Control points. Array of knots.length - 1 length.
          //  @param secondControlPoints Output Second Control points. Array of knots.length - 1 length.
          getCurveControlPoints: function(knots) {
              var firstControlPoints = [];
              var secondControlPoints = [];
              var n = knots.length - 1;
              var i;
  
              // Special case: Bezier curve should be a straight line.
              if (n == 1) {
                  // 3P1 = 2P0 + P3
                  firstControlPoints[0] = point((2 * knots[0].x + knots[1].x) / 3,
                                                (2 * knots[0].y + knots[1].y) / 3);
                  // P2 = 2P1 – P0
                  secondControlPoints[0] = point(2 * firstControlPoints[0].x - knots[0].x,
                                                 2 * firstControlPoints[0].y - knots[0].y);
                  return [firstControlPoints, secondControlPoints];
              }
  
              // Calculate first Bezier control points.
              // Right hand side vector.
              var rhs = [];
  
              // Set right hand side X values.
              for (i = 1; i < n - 1; i++) {
                  rhs[i] = 4 * knots[i].x + 2 * knots[i + 1].x;
              }
              rhs[0] = knots[0].x + 2 * knots[1].x;
              rhs[n - 1] = (8 * knots[n - 1].x + knots[n].x) / 2.0;
              // Get first control points X-values.
              var x = this.getFirstControlPoints(rhs);
  
              // Set right hand side Y values.
              for (i = 1; i < n - 1; ++i) {
                  rhs[i] = 4 * knots[i].y + 2 * knots[i + 1].y;
              }
              rhs[0] = knots[0].y + 2 * knots[1].y;
              rhs[n - 1] = (8 * knots[n - 1].y + knots[n].y) / 2.0;
              // Get first control points Y-values.
              var y = this.getFirstControlPoints(rhs);
  
              // Fill output arrays.
              for (i = 0; i < n; i++) {
                  // First control point.
                  firstControlPoints.push(point(x[i], y[i]));
                  // Second control point.
                  if (i < n - 1) {
                      secondControlPoints.push(point(2 * knots [i + 1].x - x[i + 1],
                                                     2 * knots[i + 1].y - y[i + 1]));
                  } else {
                      secondControlPoints.push(point((knots[n].x + x[n - 1]) / 2,
                                                     (knots[n].y + y[n - 1]) / 2));
                  }
              }
              return [firstControlPoints, secondControlPoints];
          },
  
          // Solves a tridiagonal system for one of coordinates (x or y) of first Bezier control points.
          // @param rhs Right hand side vector.
          // @return Solution vector.
          getFirstControlPoints: function(rhs) {
              var n = rhs.length;
              // `x` is a solution vector.
              var x = [];
              var tmp = [];
              var b = 2.0;
  
              x[0] = rhs[0] / b;
              // Decomposition and forward substitution.
              for (var i = 1; i < n; i++) {
                  tmp[i] = 1 / b;
                  b = (i < n - 1 ? 4.0 : 3.5) - tmp[i];
                  x[i] = (rhs[i] - x[i - 1]) / b;
              }
              for (i = 1; i < n; i++) {
                  // Backsubstitution.
                  x[n - i - 1] -= tmp[n - i] * x[n - i];
              }
              return x;
          },
  
          // Solves an inversion problem -- Given the (x, y) coordinates of a point which lies on
          // a parametric curve x = x(t)/w(t), y = y(t)/w(t), ﬁnd the parameter value t
          // which corresponds to that point.
          // @param control points (start, control start, control end, end)
          // @return a function accepts a point and returns t.
          getInversionSolver: function(p0, p1, p2, p3) {
              var pts = arguments;
              function l(i, j) {
                  // calculates a determinant 3x3
                  // [p.x  p.y  1]
                  // [pi.x pi.y 1]
                  // [pj.x pj.y 1]
                  var pi = pts[i];
                  var pj = pts[j];
                  return function(p) {
                      var w = (i % 3 ? 3 : 1) * (j % 3 ? 3 : 1);
                      var lij = p.x * (pi.y - pj.y) + p.y * (pj.x - pi.x) + pi.x * pj.y - pi.y * pj.x;
                      return w * lij;
                  };
              }
              return function solveInversion(p) {
                  var ct = 3 * l(2, 3)(p1);
                  var c1 = l(1, 3)(p0) / ct;
                  var c2 = -l(2, 3)(p0) / ct;
                  var la = c1 * l(3, 1)(p) + c2 * (l(3, 0)(p) + l(2, 1)(p)) + l(2, 0)(p);
                  var lb = c1 * l(3, 0)(p) + c2 * l(2, 0)(p) + l(1, 0)(p);
                  return lb / (lb - la);
              };
          },
  
          // Divide a Bezier curve into two at point defined by value 't' <0,1>.
          // Using deCasteljau algorithm. http://math.stackexchange.com/a/317867
          // @param control points (start, control start, control end, end)
          // @return a function accepts t and returns 2 curves each defined by 4 control points.
          getCurveDivider: function(p0, p1, p2, p3) {
              return function divideCurve(t) {
                  var l = line(p0, p1).pointAt(t);
                  var m = line(p1, p2).pointAt(t);
                  var n = line(p2, p3).pointAt(t);
                  var p = line(l, m).pointAt(t);
                  var q = line(m, n).pointAt(t);
                  var r = line(p, q).pointAt(t);
                  return [{ p0: p0, p1: l, p2: p, p3: r }, { p0: r, p1: q, p2: n, p3: p3 }];
              };
          }
      };
  
      // Scale.
      var scale = {
  
          // Return the `value` from the `domain` interval scaled to the `range` interval.
          linear: function(domain, range, value) {
  
              var domainSpan = domain[1] - domain[0];
              var rangeSpan = range[1] - range[0];
              return (((value - domain[0]) / domainSpan) * rangeSpan + range[0]) || 0;
          }
      };
  
      return {
          toDeg: toDeg,
          toRad: toRad,
          snapToGrid: snapToGrid,
          normalizeAngle: normalizeAngle,
          point: point,
          line: line,
          rect: rect,
          ellipse: ellipse,
          bezier: bezier,
          scale: scale
      };
  
  })();
  
  
      return g;
  
  }));
  