text: "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  var tslib_1 = require("tslib");
  var cubic_1 = require("@antv/g-math/lib/cubic");
  var util_1 = require("@antv/util");
  var base_1 = require("./base");
  var path_2_absolute_1 = require("@antv/path-util/lib/path-2-absolute");
  var path_2_segments_1 = require("@antv/path-util/lib/path-2-segments");
  var draw_1 = require("../util/draw");
  var point_in_path_1 = require("../util/in-path/point-in-path");
  var polygon_1 = require("../util/in-path/polygon");
  var path_1 = require("../util/path");
  var ArrowUtil = require("../util/arrow");
  // 是否在多个多边形内部
  function isInPolygons(polygons, x, y) {
      var isHit = false;
      for (var i = 0; i < polygons.length; i++) {
          var points = polygons[i];
          isHit = polygon_1.default(points, x, y);
          if (isHit) {
              break;
          }
      }
      return isHit;
  }
  var Path = /** @class */ (function (_super) {
      tslib_1.__extends(Path, _super);
      function Path() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      Path.prototype.getDefaultAttrs = function () {
          var attrs = _super.prototype.getDefaultAttrs.call(this);
          return tslib_1.__assign(tslib_1.__assign({}, attrs), { startArrow: false, endArrow: false });
      };
      Path.prototype.initAttrs = function (attrs) {
          this._setPathArr(attrs.path);
          this.setArrow();
      };
      // 更新属性时，检测是否更改了 path
      Path.prototype.onAttrChange = function (name, value, originValue) {
          _super.prototype.onAttrChange.call(this, name, value, originValue);
          if (name === 'path') {
              this._setPathArr(value);
          }
          // 由于箭头的绘制依赖于 line 的诸多 attrs，因此这里不再对每个 attr 进行判断，attr 每次变化都会影响箭头的更新
          this.setArrow();
      };
      // 将 path 转换成绝对路径
      Path.prototype._setPathArr = function (path) {
          // 转换 path 的格式
          this.attrs.path = path_2_absolute_1.default(path);
          var hasArc = path_1.default.hasArc(path);
          // 为了加速 path 的绘制、拾取和计算，这个地方可以缓存很多东西
          // 这些缓存都是第一次需要时计算和存储，虽然增加了复杂度，但是频繁调用的方法，性能有很大提升
          this.set('hasArc', hasArc);
          this.set('paramsCache', {}); // 清理缓存
          this.set('segments', null); // 延迟生成 path，在动画场景下可能不会有拾取
          this.set('curve', null);
          this.set('tCache', null);
          this.set('totalLength', null);
      };
      Path.prototype.getSegments = function () {
          var segments = this.get('segements');
          if (!segments) {
              segments = path_2_segments_1.default(this.attr('path'));
              this.set('segments', segments);
          }
          return segments;
      };
      Path.prototype.setArrow = function () {
          var attrs = this.attr();
          var startArrow = attrs.startArrow, endArrow = attrs.endArrow;
          if (startArrow) {
              var tangent = this.getStartTangent();
              ArrowUtil.addStartArrow(this, attrs, tangent[0][0], tangent[0][1], tangent[1][0], tangent[1][1]);
          }
          if (endArrow) {
              var tangent = this.getEndTangent();
              ArrowUtil.addEndArrow(this, attrs, tangent[0][0], tangent[0][1], tangent[1][0], tangent[1][1]);
          }
      };
      Path.prototype.isInStrokeOrPath = function (x, y, isStroke, isFill, lineWidth) {
          var segments = this.getSegments();
          var hasArc = this.get('hasArc');
          var isHit = false;
          if (isStroke) {
              isHit = path_1.default.isPointInStroke(segments, lineWidth, x, y);
          }
          if (!isHit && isFill) {
              if (hasArc) {
                  // 存在曲线时，暂时使用 canvas 的 api 计算，后续可以进行多边形切割
                  isHit = point_in_path_1.default(this, x, y);
              }
              else {
                  var path = this.attr('path');
                  var extractResutl = path_1.default.extractPolygons(path);
                  // 提取出来的多边形包含闭合的和非闭合的，在这里统一按照多边形处理
                  isHit = isInPolygons(extractResutl.polygons, x, y) || isInPolygons(extractResutl.polylines, x, y);
              }
          }
          return isHit;
      };
      Path.prototype.createPath = function (context) {
          var attrs = this.attr();
          var paramsCache = this.get('paramsCache'); // 由于计算圆弧的参数成本很大，所以要缓存
          draw_1.drawPath(this, context, attrs, paramsCache);
      };
      Path.prototype.afterDrawPath = function (context) {
          var startArrowShape = this.get('startArrowShape');
          var endArrowShape = this.get('endArrowShape');
          if (startArrowShape) {
              startArrowShape.draw(context);
          }
          if (endArrowShape) {
              endArrowShape.draw(context);
          }
      };
      /**
       * Get total length of path
       * @return {number} length
       */
      Path.prototype.getTotalLength = function () {
          var totalLength = this.get('totalLength');
          if (!util_1.isNil(totalLength)) {
              return totalLength;
          }
          this._calculateCurve();
          this._setTcache();
          return this.get('totalLength');
      };
      /**
       * Get point according to ratio
       * @param {number} ratio
       * @return {Point} point
       */
      Path.prototype.getPoint = function (ratio) {
          var tCache = this.get('tCache');
          if (!tCache) {
              this._calculateCurve();
              this._setTcache();
              tCache = this.get('tCache');
          }
          var subt;
          var index;
          var curve = this.get('curve');
          if (!tCache || tCache.length === 0) {
              if (curve) {
                  return {
                      x: curve[0][1],
                      y: curve[0][2],
                  };
              }
              return null;
          }
          util_1.each(tCache, function (v, i) {
              if (ratio >= v[0] && ratio <= v[1]) {
                  subt = (ratio - v[0]) / (v[1] - v[0]);
                  index = i;
              }
          });
          var seg = curve[index];
          if (util_1.isNil(seg) || util_1.isNil(index)) {
              return null;
          }
          var l = seg.length;
          var nextSeg = curve[index + 1];
          return cubic_1.default.pointAt(seg[l - 2], seg[l - 1], nextSeg[1], nextSeg[2], nextSeg[3], nextSeg[4], nextSeg[5], nextSeg[6], subt);
      };
      Path.prototype._calculateCurve = function () {
          var path = this.attr().path;
          this.set('curve', path_1.default.pathToCurve(path));
      };
      Path.prototype._setTcache = function () {
          var totalLength = 0;
          var tempLength = 0;
          // 每段 curve 对应起止点的长度比例列表，形如: [[0, 0.25], [0.25, 0.6]. [0.6, 0.9], [0.9, 1]]
          var tCache = [];
          var segmentT;
          var segmentL;
          var segmentN;
          var l;
          var curve = this.get('curve');
          if (!curve) {
              return;
          }
          util_1.each(curve, function (segment, i) {
              segmentN = curve[i + 1];
              l = segment.length;
              if (segmentN) {
                  totalLength +=
                      cubic_1.default.length(segment[l - 2], segment[l - 1], segmentN[1], segmentN[2], segmentN[3], segmentN[4], segmentN[5], segmentN[6]) || 0;
              }
          });
          this.set('totalLength', totalLength);
          if (totalLength === 0) {
              this.set('tCache', []);
              return;
          }
          util_1.each(curve, function (segment, i) {
              segmentN = curve[i + 1];
              l = segment.length;
              if (segmentN) {
                  segmentT = [];
                  segmentT[0] = tempLength / totalLength;
                  segmentL = cubic_1.default.length(segment[l - 2], segment[l - 1], segmentN[1], segmentN[2], segmentN[3], segmentN[4], segmentN[5], segmentN[6]);
                  // 当 path 不连续时，segmentL 可能为空，为空时需要作为 0 处理
                  tempLength += segmentL || 0;
                  segmentT[1] = tempLength / totalLength;
                  tCache.push(segmentT);
              }
          });
          this.set('tCache', tCache);
      };
      /**
       * Get start tangent vector
       * @return {Array}
       */
      Path.prototype.getStartTangent = function () {
          var segments = this.getSegments();
          var result;
          if (segments.length > 1) {
              var startPoint = segments[0].currentPoint;
              var endPoint = segments[1].currentPoint;
              var tangent = segments[1].startTangent;
              result = [];
              if (tangent) {
                  result.push([startPoint[0] - tangent[0], startPoint[1] - tangent[1]]);
                  result.push([startPoint[0], startPoint[1]]);
              }
              else {
                  result.push([endPoint[0], endPoint[1]]);
                  result.push([startPoint[0], startPoint[1]]);
              }
          }
          return result;
      };
      /**
       * Get end tangent vector
       * @return {Array}
       */
      Path.prototype.getEndTangent = function () {
          var segments = this.getSegments();
          var length = segments.length;
          var result;
          if (length > 1) {
              var startPoint = segments[length - 2].currentPoint;
              var endPoint = segments[length - 1].currentPoint;
              var tangent = segments[length - 1].endTangent;
              result = [];
              if (tangent) {
                  result.push([endPoint[0] - tangent[0], endPoint[1] - tangent[1]]);
                  result.push([endPoint[0], endPoint[1]]);
              }
              else {
                  result.push([startPoint[0], startPoint[1]]);
                  result.push([endPoint[0], endPoint[1]]);
              }
          }
          return result;
      };
      return Path;
  }(base_1.default));
  exports.default = Path;
  //# sourceMappingURL=path.js.map