@antv/x6
Version:
JavaScript diagramming library that uses SVG and HTML for rendering.
1,088 lines • 42.9 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Path = void 0;
var util_1 = require("../util");
var line_1 = require("../line");
var point_1 = require("../point");
var curve_1 = require("../curve");
var polyline_1 = require("../polyline");
var rectangle_1 = require("../rectangle");
var geometry_1 = require("../geometry");
var close_1 = require("./close");
var lineto_1 = require("./lineto");
var moveto_1 = require("./moveto");
var curveto_1 = require("./curveto");
var normalize_1 = require("./normalize");
var Util = __importStar(require("./util"));
var Path = /** @class */ (function (_super) {
__extends(Path, _super);
function Path(args) {
var _this = _super.call(this) || this;
_this.PRECISION = 3;
_this.segments = [];
if (Array.isArray(args)) {
if (line_1.Line.isLine(args[0]) || curve_1.Curve.isCurve(args[0])) {
var previousObj_1 = null;
var arr = args;
arr.forEach(function (o, i) {
if (i === 0) {
_this.appendSegment(Path.createSegment('M', o.start));
}
if (previousObj_1 != null && !previousObj_1.end.equals(o.start)) {
_this.appendSegment(Path.createSegment('M', o.start));
}
if (line_1.Line.isLine(o)) {
_this.appendSegment(Path.createSegment('L', o.end));
}
else if (curve_1.Curve.isCurve(o)) {
_this.appendSegment(Path.createSegment('C', o.controlPoint1, o.controlPoint2, o.end));
}
previousObj_1 = o;
});
}
else {
var arr = args;
arr.forEach(function (s) {
if (s.isSegment) {
_this.appendSegment(s);
}
});
}
}
else if (args != null) {
if (line_1.Line.isLine(args)) {
_this.appendSegment(Path.createSegment('M', args.start));
_this.appendSegment(Path.createSegment('L', args.end));
}
else if (curve_1.Curve.isCurve(args)) {
_this.appendSegment(Path.createSegment('M', args.start));
_this.appendSegment(Path.createSegment('C', args.controlPoint1, args.controlPoint2, args.end));
}
else if (polyline_1.Polyline.isPolyline(args)) {
if (args.points && args.points.length) {
args.points.forEach(function (point, index) {
var segment = index === 0
? Path.createSegment('M', point)
: Path.createSegment('L', point);
_this.appendSegment(segment);
});
}
}
else if (args.isSegment) {
_this.appendSegment(args);
}
}
return _this;
}
Object.defineProperty(Path.prototype, Symbol.toStringTag, {
get: function () {
return Path.toStringTag;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Path.prototype, "start", {
get: function () {
var segments = this.segments;
var count = segments.length;
if (count === 0) {
return null;
}
for (var i = 0; i < count; i += 1) {
var segment = segments[i];
if (segment.isVisible) {
return segment.start;
}
}
// if no visible segment, return last segment end point
return segments[count - 1].end;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Path.prototype, "end", {
get: function () {
var segments = this.segments;
var count = segments.length;
if (count === 0) {
return null;
}
for (var i = count - 1; i >= 0; i -= 1) {
var segment = segments[i];
if (segment.isVisible) {
return segment.end;
}
}
// if no visible segment, return last segment end point
return segments[count - 1].end;
},
enumerable: false,
configurable: true
});
Path.prototype.moveTo = function () {
var _a;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return this.appendSegment((_a = moveto_1.MoveTo.create).call.apply(_a, __spreadArray([null], args, false)));
};
Path.prototype.lineTo = function () {
var _a;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return this.appendSegment((_a = lineto_1.LineTo.create).call.apply(_a, __spreadArray([null], args, false)));
};
Path.prototype.curveTo = function () {
var _a;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return this.appendSegment((_a = curveto_1.CurveTo.create).call.apply(_a, __spreadArray([null], args, false)));
};
Path.prototype.arcTo = function (rx, ry, xAxisRotation, largeArcFlag, sweepFlag, endX, endY) {
var start = this.end || new point_1.Point();
var points = typeof endX === 'number'
? Util.arcToCurves(start.x, start.y, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, endX, endY)
: Util.arcToCurves(start.x, start.y, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, endX.x, endX.y);
if (points != null) {
for (var i = 0, ii = points.length; i < ii; i += 6) {
this.curveTo(points[i], points[i + 1], points[i + 2], points[i + 3], points[i + 4], points[i + 5]);
}
}
return this;
};
Path.prototype.quadTo = function (x1, y1, x, y) {
var start = this.end || new point_1.Point();
var data = ['M', start.x, start.y];
if (typeof x1 === 'number') {
data.push('Q', x1, y1, x, y);
}
else {
var p = y1;
data.push("Q", x1.x, x1.y, p.x, p.y);
}
var path = Path.parse(data.join(' '));
this.appendSegment(path.segments.slice(1));
return this;
};
Path.prototype.close = function () {
return this.appendSegment(close_1.Close.create());
};
Path.prototype.drawPoints = function (points, options) {
if (options === void 0) { options = {}; }
var raw = Util.drawPoints(points, options);
var sub = Path.parse(raw);
if (sub && sub.segments) {
this.appendSegment(sub.segments);
}
};
Path.prototype.bbox = function () {
var segments = this.segments;
var count = segments.length;
if (count === 0) {
return null;
}
var bbox;
for (var i = 0; i < count; i += 1) {
var segment = segments[i];
if (segment.isVisible) {
var segmentBBox = segment.bbox();
if (segmentBBox != null) {
bbox = bbox ? bbox.union(segmentBBox) : segmentBBox;
}
}
}
if (bbox != null) {
return bbox;
}
// if the path has only invisible elements, return end point of last segment
var lastSegment = segments[count - 1];
return new rectangle_1.Rectangle(lastSegment.end.x, lastSegment.end.y, 0, 0);
};
Path.prototype.appendSegment = function (seg) {
var count = this.segments.length;
var previousSegment = count !== 0 ? this.segments[count - 1] : null;
var currentSegment;
var nextSegment = null;
if (Array.isArray(seg)) {
for (var i = 0, ii = seg.length; i < ii; i += 1) {
var segment = seg[i];
currentSegment = this.prepareSegment(segment, previousSegment, nextSegment);
this.segments.push(currentSegment);
previousSegment = currentSegment;
}
}
else if (seg != null && seg.isSegment) {
currentSegment = this.prepareSegment(seg, previousSegment, nextSegment);
this.segments.push(currentSegment);
}
return this;
};
Path.prototype.insertSegment = function (index, seg) {
var count = this.segments.length;
if (index < 0) {
index = count + index + 1; // eslint-disable-line
}
if (index > count || index < 0) {
throw new Error('Index out of range.');
}
var currentSegment;
var previousSegment = null;
var nextSegment = null;
if (count !== 0) {
if (index >= 1) {
previousSegment = this.segments[index - 1];
nextSegment = previousSegment.nextSegment;
}
else {
previousSegment = null;
nextSegment = this.segments[0];
}
}
if (!Array.isArray(seg)) {
currentSegment = this.prepareSegment(seg, previousSegment, nextSegment);
this.segments.splice(index, 0, currentSegment);
}
else {
for (var i = 0, ii = seg.length; i < ii; i += 1) {
var segment = seg[i];
currentSegment = this.prepareSegment(segment, previousSegment, nextSegment);
this.segments.splice(index + i, 0, currentSegment);
previousSegment = currentSegment;
}
}
return this;
};
Path.prototype.removeSegment = function (index) {
var idx = this.fixIndex(index);
var removedSegment = this.segments.splice(idx, 1)[0];
var previousSegment = removedSegment.previousSegment;
var nextSegment = removedSegment.nextSegment;
// link the previous and next segments together (if present)
if (previousSegment) {
previousSegment.nextSegment = nextSegment;
}
if (nextSegment) {
nextSegment.previousSegment = previousSegment;
}
if (removedSegment.isSubpathStart && nextSegment) {
this.updateSubpathStartSegment(nextSegment);
}
return removedSegment;
};
Path.prototype.replaceSegment = function (index, seg) {
var idx = this.fixIndex(index);
var currentSegment;
var replacedSegment = this.segments[idx];
var previousSegment = replacedSegment.previousSegment;
var nextSegment = replacedSegment.nextSegment;
var updateSubpathStart = replacedSegment.isSubpathStart;
if (!Array.isArray(seg)) {
currentSegment = this.prepareSegment(seg, previousSegment, nextSegment);
this.segments.splice(idx, 1, currentSegment);
if (updateSubpathStart && currentSegment.isSubpathStart) {
// already updated by `prepareSegment`
updateSubpathStart = false;
}
}
else {
this.segments.splice(index, 1);
for (var i = 0, ii = seg.length; i < ii; i += 1) {
var segment = seg[i];
currentSegment = this.prepareSegment(segment, previousSegment, nextSegment);
this.segments.splice(index + i, 0, currentSegment);
previousSegment = currentSegment;
if (updateSubpathStart && currentSegment.isSubpathStart) {
updateSubpathStart = false;
}
}
}
if (updateSubpathStart && nextSegment) {
this.updateSubpathStartSegment(nextSegment);
}
};
Path.prototype.getSegment = function (index) {
var idx = this.fixIndex(index);
return this.segments[idx];
};
Path.prototype.fixIndex = function (index) {
var length = this.segments.length;
if (length === 0) {
throw new Error('Path has no segments.');
}
var i = index;
while (i < 0) {
i = length + i;
}
if (i >= length || i < 0) {
throw new Error('Index out of range.');
}
return i;
};
Path.prototype.segmentAt = function (ratio, options) {
if (options === void 0) { options = {}; }
var index = this.segmentIndexAt(ratio, options);
if (!index) {
return null;
}
return this.getSegment(index);
};
Path.prototype.segmentAtLength = function (length, options) {
if (options === void 0) { options = {}; }
var index = this.segmentIndexAtLength(length, options);
if (!index)
return null;
return this.getSegment(index);
};
Path.prototype.segmentIndexAt = function (ratio, options) {
if (options === void 0) { options = {}; }
if (this.segments.length === 0) {
return null;
}
var rate = (0, util_1.clamp)(ratio, 0, 1);
var opt = this.getOptions(options);
var len = this.length(opt);
var length = len * rate;
return this.segmentIndexAtLength(length, opt);
};
Path.prototype.segmentIndexAtLength = function (length, options) {
if (options === void 0) { options = {}; }
var count = this.segments.length;
if (count === 0) {
return null;
}
var fromStart = true;
if (length < 0) {
fromStart = false;
length = -length; // eslint-disable-line
}
var precision = this.getPrecision(options);
var segmentSubdivisions = this.getSubdivisions(options);
var memo = 0;
var lastVisibleIndex = null;
for (var i = 0; i < count; i += 1) {
var index = fromStart ? i : count - 1 - i;
var segment = this.segments[index];
var subdivisions = segmentSubdivisions[index];
var len = segment.length({ precision: precision, subdivisions: subdivisions });
if (segment.isVisible) {
if (length <= memo + len) {
return index;
}
lastVisibleIndex = index;
}
memo += len;
}
// If length requested is higher than the length of the path, return
// last visible segment index. If no visible segment, return null.
return lastVisibleIndex;
};
Path.prototype.getSegmentSubdivisions = function (options) {
if (options === void 0) { options = {}; }
var precision = this.getPrecision(options);
var segmentSubdivisions = [];
for (var i = 0, ii = this.segments.length; i < ii; i += 1) {
var segment = this.segments[i];
var subdivisions = segment.getSubdivisions({ precision: precision });
segmentSubdivisions.push(subdivisions);
}
return segmentSubdivisions;
};
Path.prototype.updateSubpathStartSegment = function (segment) {
var previous = segment.previousSegment;
var current = segment;
while (current && !current.isSubpathStart) {
// assign previous segment's subpath start segment to this segment
if (previous != null) {
current.subpathStartSegment = previous.subpathStartSegment;
}
else {
current.subpathStartSegment = null;
}
previous = current;
current = current.nextSegment;
}
};
Path.prototype.prepareSegment = function (segment, previousSegment, nextSegment) {
segment.previousSegment = previousSegment;
segment.nextSegment = nextSegment;
if (previousSegment != null) {
previousSegment.nextSegment = segment;
}
if (nextSegment != null) {
nextSegment.previousSegment = segment;
}
var updateSubpathStart = segment;
if (segment.isSubpathStart) {
// move to
segment.subpathStartSegment = segment;
updateSubpathStart = nextSegment;
}
// assign previous segment's subpath start (or self if it is a subpath start) to subsequent segments
if (updateSubpathStart != null) {
this.updateSubpathStartSegment(updateSubpathStart);
}
return segment;
};
Path.prototype.closestPoint = function (p, options) {
if (options === void 0) { options = {}; }
var t = this.closestPointT(p, options);
if (!t) {
return null;
}
return this.pointAtT(t);
};
Path.prototype.closestPointLength = function (p, options) {
if (options === void 0) { options = {}; }
var opts = this.getOptions(options);
var t = this.closestPointT(p, opts);
if (!t) {
return 0;
}
return this.lengthAtT(t, opts);
};
Path.prototype.closestPointNormalizedLength = function (p, options) {
if (options === void 0) { options = {}; }
var opts = this.getOptions(options);
var cpLength = this.closestPointLength(p, opts);
if (cpLength === 0) {
return 0;
}
var length = this.length(opts);
if (length === 0) {
return 0;
}
return cpLength / length;
};
Path.prototype.closestPointT = function (p, options) {
if (options === void 0) { options = {}; }
if (this.segments.length === 0) {
return null;
}
var precision = this.getPrecision(options);
var segmentSubdivisions = this.getSubdivisions(options);
var closestPointT;
var minSquaredDistance = Infinity;
for (var i = 0, ii = this.segments.length; i < ii; i += 1) {
var segment = this.segments[i];
var subdivisions = segmentSubdivisions[i];
if (segment.isVisible) {
var segmentClosestPointT = segment.closestPointT(p, {
precision: precision,
subdivisions: subdivisions,
});
var segmentClosestPoint = segment.pointAtT(segmentClosestPointT);
var squaredDistance = (0, util_1.squaredLength)(segmentClosestPoint, p);
if (squaredDistance < minSquaredDistance) {
closestPointT = { segmentIndex: i, value: segmentClosestPointT };
minSquaredDistance = squaredDistance;
}
}
}
if (closestPointT) {
return closestPointT;
}
return { segmentIndex: this.segments.length - 1, value: 1 };
};
Path.prototype.closestPointTangent = function (p, options) {
if (options === void 0) { options = {}; }
if (this.segments.length === 0) {
return null;
}
var precision = this.getPrecision(options);
var segmentSubdivisions = this.getSubdivisions(options);
var closestPointTangent;
var minSquaredDistance = Infinity;
for (var i = 0, ii = this.segments.length; i < ii; i += 1) {
var segment = this.segments[i];
var subdivisions = segmentSubdivisions[i];
if (segment.isDifferentiable()) {
var segmentClosestPointT = segment.closestPointT(p, {
precision: precision,
subdivisions: subdivisions,
});
var segmentClosestPoint = segment.pointAtT(segmentClosestPointT);
var squaredDistance = (0, util_1.squaredLength)(segmentClosestPoint, p);
if (squaredDistance < minSquaredDistance) {
closestPointTangent = segment.tangentAtT(segmentClosestPointT);
minSquaredDistance = squaredDistance;
}
}
}
if (closestPointTangent) {
return closestPointTangent;
}
return null;
};
Path.prototype.containsPoint = function (p, options) {
if (options === void 0) { options = {}; }
var polylines = this.toPolylines(options);
if (!polylines) {
return false;
}
var numIntersections = 0;
for (var i = 0, ii = polylines.length; i < ii; i += 1) {
var polyline = polylines[i];
if (polyline.containsPoint(p)) {
numIntersections += 1;
}
}
// returns `true` for odd numbers of intersections (even-odd algorithm)
return numIntersections % 2 === 1;
};
Path.prototype.pointAt = function (ratio, options) {
if (options === void 0) { options = {}; }
if (this.segments.length === 0) {
return null;
}
if (ratio <= 0) {
return this.start.clone();
}
if (ratio >= 1) {
return this.end.clone();
}
var opts = this.getOptions(options);
var pathLength = this.length(opts);
var length = pathLength * ratio;
return this.pointAtLength(length, opts);
};
Path.prototype.pointAtLength = function (length, options) {
if (options === void 0) { options = {}; }
if (this.segments.length === 0) {
return null;
}
if (length === 0) {
return this.start.clone();
}
var fromStart = true;
if (length < 0) {
fromStart = false;
length = -length; // eslint-disable-line
}
var precision = this.getPrecision(options);
var segmentSubdivisions = this.getSubdivisions(options);
var lastVisibleSegment;
var memo = 0;
for (var i = 0, ii = this.segments.length; i < ii; i += 1) {
var index = fromStart ? i : ii - 1 - i;
var segment = this.segments[index];
var subdivisions = segmentSubdivisions[index];
var d = segment.length({
precision: precision,
subdivisions: subdivisions,
});
if (segment.isVisible) {
if (length <= memo + d) {
return segment.pointAtLength((fromStart ? 1 : -1) * (length - memo), {
precision: precision,
subdivisions: subdivisions,
});
}
lastVisibleSegment = segment;
}
memo += d;
}
// if length requested is higher than the length of the path,
// return last visible segment endpoint
if (lastVisibleSegment) {
return fromStart ? lastVisibleSegment.end : lastVisibleSegment.start;
}
// if no visible segment, return last segment end point
var lastSegment = this.segments[this.segments.length - 1];
return lastSegment.end.clone();
};
Path.prototype.pointAtT = function (t) {
var segments = this.segments;
var numSegments = segments.length;
if (numSegments === 0)
return null; // if segments is an empty array
var segmentIndex = t.segmentIndex;
if (segmentIndex < 0)
return segments[0].pointAtT(0);
if (segmentIndex >= numSegments) {
return segments[numSegments - 1].pointAtT(1);
}
var tValue = (0, util_1.clamp)(t.value, 0, 1);
return segments[segmentIndex].pointAtT(tValue);
};
Path.prototype.divideAt = function (ratio, options) {
if (options === void 0) { options = {}; }
if (this.segments.length === 0) {
return null;
}
var rate = (0, util_1.clamp)(ratio, 0, 1);
var opts = this.getOptions(options);
var len = this.length(opts);
var length = len * rate;
return this.divideAtLength(length, opts);
};
Path.prototype.divideAtLength = function (length, options) {
if (options === void 0) { options = {}; }
if (this.segments.length === 0) {
return null;
}
var fromStart = true;
if (length < 0) {
fromStart = false;
length = -length; // eslint-disable-line
}
var precision = this.getPrecision(options);
var segmentSubdivisions = this.getSubdivisions(options);
var memo = 0;
var divided;
var dividedSegmentIndex;
var lastValidSegment;
var lastValidSegmentIndex;
var t;
for (var i = 0, ii = this.segments.length; i < ii; i += 1) {
var index_1 = fromStart ? i : ii - 1 - i;
var segment = this.getSegment(index_1);
var subdivisions = segmentSubdivisions[index_1];
var opts = { precision: precision, subdivisions: subdivisions };
var len = segment.length(opts);
if (segment.isDifferentiable()) {
lastValidSegment = segment;
lastValidSegmentIndex = index_1;
if (length <= memo + len) {
dividedSegmentIndex = index_1;
divided = segment.divideAtLength((fromStart ? 1 : -1) * (length - memo), opts);
break;
}
}
memo += len;
}
if (!lastValidSegment) {
return null;
}
if (!divided) {
dividedSegmentIndex = lastValidSegmentIndex;
t = fromStart ? 1 : 0;
divided = lastValidSegment.divideAtT(t);
}
// create a copy of this path and replace the identified segment with its two divided parts:
var pathCopy = this.clone();
var index = dividedSegmentIndex;
pathCopy.replaceSegment(index, divided);
var divisionStartIndex = index;
var divisionMidIndex = index + 1;
var divisionEndIndex = index + 2;
// do not insert the part if it looks like a point
if (!divided[0].isDifferentiable()) {
pathCopy.removeSegment(divisionStartIndex);
divisionMidIndex -= 1;
divisionEndIndex -= 1;
}
// insert a Moveto segment to ensure secondPath will be valid:
var movetoEnd = pathCopy.getSegment(divisionMidIndex).start;
pathCopy.insertSegment(divisionMidIndex, Path.createSegment('M', movetoEnd));
divisionEndIndex += 1;
// do not insert the part if it looks like a point
if (!divided[1].isDifferentiable()) {
pathCopy.removeSegment(divisionEndIndex - 1);
divisionEndIndex -= 1;
}
// ensure that Closepath segments in secondPath will be assigned correct subpathStartSegment:
var secondPathSegmentIndexConversion = divisionEndIndex - divisionStartIndex - 1;
for (var i = divisionEndIndex, ii = pathCopy.segments.length; i < ii; i += 1) {
var originalSegment = this.getSegment(i - secondPathSegmentIndexConversion);
var segment = pathCopy.getSegment(i);
if (segment.type === 'Z' &&
!originalSegment.subpathStartSegment.end.equals(segment.subpathStartSegment.end)) {
// pathCopy segment's subpathStartSegment is different from original segment's one
// convert this Closepath segment to a Lineto and replace it in pathCopy
var convertedSegment = Path.createSegment('L', originalSegment.end);
pathCopy.replaceSegment(i, convertedSegment);
}
}
// distribute pathCopy segments into two paths and return those:
var firstPath = new Path(pathCopy.segments.slice(0, divisionMidIndex));
var secondPath = new Path(pathCopy.segments.slice(divisionMidIndex));
return [firstPath, secondPath];
};
Path.prototype.intersectsWithLine = function (line, options) {
if (options === void 0) { options = {}; }
var polylines = this.toPolylines(options);
if (polylines == null) {
return null;
}
var intersections = null;
for (var i = 0, ii = polylines.length; i < ii; i += 1) {
var polyline = polylines[i];
var intersection = line.intersect(polyline);
if (intersection) {
if (intersections == null) {
intersections = [];
}
if (Array.isArray(intersection)) {
intersections.push.apply(intersections, intersection);
}
else {
intersections.push(intersection);
}
}
}
return intersections;
};
Path.prototype.isDifferentiable = function () {
for (var i = 0, ii = this.segments.length; i < ii; i += 1) {
var segment = this.segments[i];
if (segment.isDifferentiable()) {
return true;
}
}
return false;
};
Path.prototype.isValid = function () {
var segments = this.segments;
var isValid = segments.length === 0 || segments[0].type === 'M';
return isValid;
};
Path.prototype.length = function (options) {
if (options === void 0) { options = {}; }
if (this.segments.length === 0) {
return 0;
}
var segmentSubdivisions = this.getSubdivisions(options);
var length = 0;
for (var i = 0, ii = this.segments.length; i < ii; i += 1) {
var segment = this.segments[i];
var subdivisions = segmentSubdivisions[i];
length += segment.length({ subdivisions: subdivisions });
}
return length;
};
Path.prototype.lengthAtT = function (t, options) {
if (options === void 0) { options = {}; }
var count = this.segments.length;
if (count === 0) {
return 0;
}
var segmentIndex = t.segmentIndex;
if (segmentIndex < 0) {
return 0;
}
var tValue = (0, util_1.clamp)(t.value, 0, 1);
if (segmentIndex >= count) {
segmentIndex = count - 1;
tValue = 1;
}
var precision = this.getPrecision(options);
var segmentSubdivisions = this.getSubdivisions(options);
var length = 0;
for (var i = 0; i < segmentIndex; i += 1) {
var segment_1 = this.segments[i];
var subdivisions_1 = segmentSubdivisions[i];
length += segment_1.length({ precision: precision, subdivisions: subdivisions_1 });
}
var segment = this.segments[segmentIndex];
var subdivisions = segmentSubdivisions[segmentIndex];
length += segment.lengthAtT(tValue, { precision: precision, subdivisions: subdivisions });
return length;
};
Path.prototype.tangentAt = function (ratio, options) {
if (options === void 0) { options = {}; }
if (this.segments.length === 0) {
return null;
}
var rate = (0, util_1.clamp)(ratio, 0, 1);
var opts = this.getOptions(options);
var len = this.length(opts);
var length = len * rate;
return this.tangentAtLength(length, opts);
};
Path.prototype.tangentAtLength = function (length, options) {
if (options === void 0) { options = {}; }
if (this.segments.length === 0) {
return null;
}
var fromStart = true;
if (length < 0) {
fromStart = false;
length = -length; // eslint-disable-line
}
var precision = this.getPrecision(options);
var segmentSubdivisions = this.getSubdivisions(options);
var lastValidSegment;
var memo = 0;
for (var i = 0, ii = this.segments.length; i < ii; i += 1) {
var index = fromStart ? i : ii - 1 - i;
var segment = this.segments[index];
var subdivisions = segmentSubdivisions[index];
var len = segment.length({ precision: precision, subdivisions: subdivisions });
if (segment.isDifferentiable()) {
if (length <= memo + len) {
return segment.tangentAtLength((fromStart ? 1 : -1) * (length - memo), {
precision: precision,
subdivisions: subdivisions,
});
}
lastValidSegment = segment;
}
memo += len;
}
// if length requested is higher than the length of the path, return tangent of endpoint of last valid segment
if (lastValidSegment) {
var t = fromStart ? 1 : 0;
return lastValidSegment.tangentAtT(t);
}
// if no valid segment, return null
return null;
};
Path.prototype.tangentAtT = function (t) {
var count = this.segments.length;
if (count === 0) {
return null;
}
var segmentIndex = t.segmentIndex;
if (segmentIndex < 0) {
return this.segments[0].tangentAtT(0);
}
if (segmentIndex >= count) {
return this.segments[count - 1].tangentAtT(1);
}
var tValue = (0, util_1.clamp)(t.value, 0, 1);
return this.segments[segmentIndex].tangentAtT(tValue);
};
Path.prototype.getPrecision = function (options) {
if (options === void 0) { options = {}; }
return options.precision == null ? this.PRECISION : options.precision;
};
Path.prototype.getSubdivisions = function (options) {
if (options === void 0) { options = {}; }
if (options.segmentSubdivisions == null) {
var precision = this.getPrecision(options);
return this.getSegmentSubdivisions({ precision: precision });
}
return options.segmentSubdivisions;
};
Path.prototype.getOptions = function (options) {
if (options === void 0) { options = {}; }
var precision = this.getPrecision(options);
var segmentSubdivisions = this.getSubdivisions(options);
return { precision: precision, segmentSubdivisions: segmentSubdivisions };
};
Path.prototype.toPoints = function (options) {
if (options === void 0) { options = {}; }
var segments = this.segments;
var count = segments.length;
if (count === 0) {
return null;
}
var segmentSubdivisions = this.getSubdivisions(options);
var points = [];
var partialPoints = [];
for (var i = 0; i < count; i += 1) {
var segment = segments[i];
if (segment.isVisible) {
var divisions = segmentSubdivisions[i];
if (divisions.length > 0) {
// eslint-disable-next-line no-loop-func
divisions.forEach(function (c) { return partialPoints.push(c.start); });
}
else {
partialPoints.push(segment.start);
}
}
else if (partialPoints.length > 0) {
partialPoints.push(segments[i - 1].end);
points.push(partialPoints);
partialPoints = [];
}
}
if (partialPoints.length > 0) {
partialPoints.push(this.end);
points.push(partialPoints);
}
return points;
};
Path.prototype.toPolylines = function (options) {
if (options === void 0) { options = {}; }
var points = this.toPoints(options);
if (!points) {
return null;
}
return points.map(function (arr) { return new polyline_1.Polyline(arr); });
};
Path.prototype.scale = function (sx, sy, origin) {
this.segments.forEach(function (s) { return s.scale(sx, sy, origin); });
return this;
};
Path.prototype.rotate = function (angle, origin) {
this.segments.forEach(function (segment) { return segment.rotate(angle, origin); });
return this;
};
Path.prototype.translate = function (tx, ty) {
if (typeof tx === 'number') {
this.segments.forEach(function (s) { return s.translate(tx, ty); });
}
else {
this.segments.forEach(function (s) { return s.translate(tx); });
}
return this;
};
Path.prototype.clone = function () {
var path = new Path();
this.segments.forEach(function (s) { return path.appendSegment(s.clone()); });
return path;
};
Path.prototype.equals = function (p) {
if (p == null) {
return false;
}
var segments = this.segments;
var otherSegments = p.segments;
var count = segments.length;
if (otherSegments.length !== count) {
return false;
}
for (var i = 0; i < count; i += 1) {
var a = segments[i];
var b = otherSegments[i];
if (a.type !== b.type || !a.equals(b)) {
return false;
}
}
return true;
};
Path.prototype.toJSON = function () {
return this.segments.map(function (s) { return s.toJSON(); });
};
Path.prototype.serialize = function () {
if (!this.isValid()) {
throw new Error('Invalid path segments.');
}
return this.segments.map(function (s) { return s.serialize(); }).join(' ');
};
Path.prototype.toString = function () {
return this.serialize();
};
return Path;
}(geometry_1.Geometry));
exports.Path = Path;
(function (Path) {
Path.toStringTag = "X6.Geometry." + Path.name;
function isPath(instance) {
if (instance == null) {
return false;
}
if (instance instanceof Path) {
return true;
}
var tag = instance[Symbol.toStringTag];
var path = instance;
if ((tag == null || tag === Path.toStringTag) &&
Array.isArray(path.segments) &&
typeof path.moveTo === 'function' &&
typeof path.lineTo === 'function' &&
typeof path.curveTo === 'function') {
return true;
}
return false;
}
Path.isPath = isPath;
})(Path = exports.Path || (exports.Path = {}));
exports.Path = Path;
(function (Path) {
function parse(pathData) {
if (!pathData) {
return new Path();
}
var path = new Path();
var commandRe = /(?:[a-zA-Z] *)(?:(?:-?\d+(?:\.\d+)?(?:e[-+]?\d+)? *,? *)|(?:-?\.\d+ *,? *))+|(?:[a-zA-Z] *)(?! |\d|-|\.)/g;
var commands = Path.normalize(pathData).match(commandRe);
if (commands != null) {
for (var i = 0, ii = commands.length; i < ii; i += 1) {
var command = commands[i];
var argRe = /(?:[a-zA-Z])|(?:(?:-?\d+(?:\.\d+)?(?:e[-+]?\d+)?))|(?:(?:-?\.\d+))/g;
// args = [type, coordinate1, coordinate2...]
var args = command.match(argRe);
if (args != null) {
var type = args[0];
var coords = args.slice(1).map(function (a) { return +a; });
var segment = createSegment.call.apply(createSegment, __spreadArray([null, type], coords, false));
path.appendSegment(segment);
}
}
}
return path;
}
Path.parse = parse;
function createSegment(type) {
var _a, _b, _c;
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
if (type === 'M') {
return (_a = moveto_1.MoveTo.create).call.apply(_a, __spreadArray([null], args, false));
}
if (type === 'L') {
return (_b = lineto_1.LineTo.create).call.apply(_b, __spreadArray([null], args, false));
}
if (type === 'C') {
return (_c = curveto_1.CurveTo.create).call.apply(_c, __spreadArray([null], args, false));
}
if (type === 'z' || type === 'Z') {
return close_1.Close.create();
}
throw new Error("Invalid path segment type \"" + type + "\"");
}
Path.createSegment = createSegment;
})(Path = exports.Path || (exports.Path = {}));
exports.Path = Path;
(function (Path) {
Path.normalize = normalize_1.normalizePathData;
Path.isValid = Util.isValid;
Path.drawArc = Util.drawArc;
Path.drawPoints = Util.drawPoints;
Path.arcToCurves = Util.arcToCurves;
})(Path = exports.Path || (exports.Path = {}));
exports.Path = Path;
//# sourceMappingURL=path.js.map