"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (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; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Path = void 0; const util_1 = require("../util"); const PathUtil = __importStar(require("./util")); const line_1 = require("../line"); const point_1 = require("../point"); const curve_1 = require("../curve"); const polyline_1 = require("../polyline"); const rectangle_1 = require("../rectangle"); const geometry_1 = require("../geometry"); const close_1 = require("./close"); const lineto_1 = require("./lineto"); const moveto_1 = require("./moveto"); const curveto_1 = require("./curveto"); const normalize_1 = require("./normalize"); class Path extends geometry_1.Geometry { constructor(args) { super(); this.PRECISION = 3; this.segments = []; if (Array.isArray(args)) { if (line_1.Line.isLine(args[0]) || curve_1.Curve.isCurve(args[0])) { let previousObj = null; const arr = args; arr.forEach((o, i) => { if (i === 0) { this.appendSegment(Path.createSegment('M', o.start)); } if (previousObj != null && !previousObj.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 = o; }); } else { const arr = args; arr.forEach((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((point, index) => { const segment = index === 0 ? Path.createSegment('M', point) : Path.createSegment('L', point); this.appendSegment(segment); }); } } else if (args.isSegment) { this.appendSegment(args); } } } get start() { const segments = this.segments; const count = segments.length; if (count === 0) { return null; } for (let i = 0; i < count; i += 1) { const segment = segments[i]; if (segment.isVisible) { return segment.start; } } // if no visible segment, return last segment end point return segments[count - 1].end; } get end() { const segments = this.segments; const count = segments.length; if (count === 0) { return null; } for (let i = count - 1; i >= 0; i -= 1) { const segment = segments[i]; if (segment.isVisible) { return segment.end; } } // if no visible segment, return last segment end point return segments[count - 1].end; } moveTo(...args) { return this.appendSegment(moveto_1.MoveTo.create.call(null, ...args)); } lineTo(...args) { return this.appendSegment(lineto_1.LineTo.create.call(null, ...args)); } curveTo(...args) { return this.appendSegment(curveto_1.CurveTo.create.call(null, ...args)); } arcTo(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, endX, endY) { const start = this.end || new point_1.Point(); const points = typeof endX === 'number' ? PathUtil.arcToCurves(start.x, start.y, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, endX, endY) : PathUtil.arcToCurves(start.x, start.y, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, endX.x, endX.y); if (points != null) { for (let 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; } quadTo(x1, y1, x, y) { const start = this.end || new point_1.Point(); const data = ['M', start.x, start.y]; if (typeof x1 === 'number') { data.push('Q', x1, y1, x, y); } else { const p = y1; data.push(`Q`, x1.x, x1.y, p.x, p.y); } const path = Path.parse(data.join(' ')); this.appendSegment(path.segments.slice(1)); return this; } close() { return this.appendSegment(close_1.Close.create()); } drawPoints(points, options = {}) { const raw = PathUtil.drawPoints(points, options); const sub = Path.parse(raw); if (sub && sub.segments) { this.appendSegment(sub.segments); } } bbox() { const segments = this.segments; const count = segments.length; if (count === 0) { return null; } let bbox; for (let i = 0; i < count; i += 1) { const segment = segments[i]; if (segment.isVisible) { const 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 const lastSegment = segments[count - 1]; return new rectangle_1.Rectangle(lastSegment.end.x, lastSegment.end.y, 0, 0); } appendSegment(seg) { const count = this.segments.length; let previousSegment = count !== 0 ? this.segments[count - 1] : null; let currentSegment; const nextSegment = null; if (Array.isArray(seg)) { for (let i = 0, ii = seg.length; i < ii; i += 1) { const 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; } insertSegment(index, seg) { const 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.'); } let currentSegment; let previousSegment = null; let 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 (let i = 0, ii = seg.length; i < ii; i += 1) { const segment = seg[i]; currentSegment = this.prepareSegment(segment, previousSegment, nextSegment); this.segments.splice(index + i, 0, currentSegment); previousSegment = currentSegment; } } return this; } removeSegment(index) { const idx = this.fixIndex(index); const removedSegment = this.segments.splice(idx, 1)[0]; const previousSegment = removedSegment.previousSegment; const 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; } replaceSegment(index, seg) { const idx = this.fixIndex(index); let currentSegment; const replacedSegment = this.segments[idx]; let previousSegment = replacedSegment.previousSegment; const nextSegment = replacedSegment.nextSegment; let 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 (let i = 0, ii = seg.length; i < ii; i += 1) { const 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); } } getSegment(index) { const idx = this.fixIndex(index); return this.segments[idx]; } fixIndex(index) { const length = this.segments.length; if (length === 0) { throw new Error('Path has no segments.'); } let i = index; while (i < 0) { i = length + i; } if (i >= length || i < 0) { throw new Error('Index out of range.'); } return i; } segmentAt(ratio, options = {}) { const index = this.segmentIndexAt(ratio, options); if (!index) { return null; } return this.getSegment(index); } segmentAtLength(length, options = {}) { const index = this.segmentIndexAtLength(length, options); if (!index) return null; return this.getSegment(index); } segmentIndexAt(ratio, options = {}) { if (this.segments.length === 0) { return null; } const rate = util_1.GeometryUtil.clamp(ratio, 0, 1); const opt = this.getOptions(options); const len = this.length(opt); const length = len * rate; return this.segmentIndexAtLength(length, opt); } segmentIndexAtLength(length, options = {}) { const count = this.segments.length; if (count === 0) { return null; } let fromStart = true; if (length < 0) { fromStart = false; length = -length; // eslint-disable-line } const precision = this.getPrecision(options); const segmentSubdivisions = this.getSubdivisions(options); let memo = 0; let lastVisibleIndex = null; for (let i = 0; i < count; i += 1) { const index = fromStart ? i : count - 1 - i; const segment = this.segments[index]; const subdivisions = segmentSubdivisions[index]; const len = segment.length({ precision, 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; } getSegmentSubdivisions(options = {}) { const precision = this.getPrecision(options); const segmentSubdivisions = []; for (let i = 0, ii = this.segments.length; i < ii; i += 1) { const segment = this.segments[i]; const subdivisions = segment.getSubdivisions({ precision }); segmentSubdivisions.push(subdivisions); } return segmentSubdivisions; } updateSubpathStartSegment(segment) { let previous = segment.previousSegment; let 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; } } prepareSegment(segment, previousSegment, nextSegment) { segment.previousSegment = previousSegment; segment.nextSegment = nextSegment; if (previousSegment != null) { previousSegment.nextSegment = segment; } if (nextSegment != null) { nextSegment.previousSegment = segment; } let 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; } closestPoint(p, options = {}) { const t = this.closestPointT(p, options); if (!t) { return null; } return this.pointAtT(t); } closestPointLength(p, options = {}) { const opts = this.getOptions(options); const t = this.closestPointT(p, opts); if (!t) { return 0; } return this.lengthAtT(t, opts); } closestPointNormalizedLength(p, options = {}) { const opts = this.getOptions(options); const cpLength = this.closestPointLength(p, opts); if (cpLength === 0) { return 0; } const length = this.length(opts); if (length === 0) { return 0; } return cpLength / length; } closestPointT(p, options = {}) { if (this.segments.length === 0) { return null; } const precision = this.getPrecision(options); const segmentSubdivisions = this.getSubdivisions(options); let closestPointT; let minSquaredDistance = Infinity; for (let i = 0, ii = this.segments.length; i < ii; i += 1) { const segment = this.segments[i]; const subdivisions = segmentSubdivisions[i]; if (segment.isVisible) { const segmentClosestPointT = segment.closestPointT(p, { precision, subdivisions, }); const segmentClosestPoint = segment.pointAtT(segmentClosestPointT); const squaredDistance = util_1.GeometryUtil.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 }; } closestPointTangent(p, options = {}) { if (this.segments.length === 0) { return null; } const precision = this.getPrecision(options); const segmentSubdivisions = this.getSubdivisions(options); let closestPointTangent; let minSquaredDistance = Infinity; for (let i = 0, ii = this.segments.length; i < ii; i += 1) { const segment = this.segments[i]; const subdivisions = segmentSubdivisions[i]; if (segment.isDifferentiable()) { const segmentClosestPointT = segment.closestPointT(p, { precision, subdivisions, }); const segmentClosestPoint = segment.pointAtT(segmentClosestPointT); const squaredDistance = util_1.GeometryUtil.squaredLength(segmentClosestPoint, p); if (squaredDistance < minSquaredDistance) { closestPointTangent = segment.tangentAtT(segmentClosestPointT); minSquaredDistance = squaredDistance; } } } if (closestPointTangent) { return closestPointTangent; } return null; } containsPoint(p, options = {}) { const polylines = this.toPolylines(options); if (!polylines) { return false; } let numIntersections = 0; for (let i = 0, ii = polylines.length; i < ii; i += 1) { const polyline = polylines[i]; if (polyline.containsPoint(p)) { numIntersections += 1; } } // returns `true` for odd numbers of intersections (even-odd algorithm) return numIntersections % 2 === 1; } pointAt(ratio, options = {}) { if (this.segments.length === 0) { return null; } if (ratio <= 0) { return this.start.clone(); } if (ratio >= 1) { return this.end.clone(); } const opts = this.getOptions(options); const pathLength = this.length(opts); const length = pathLength * ratio; return this.pointAtLength(length, opts); } pointAtLength(length, options = {}) { if (this.segments.length === 0) { return null; } if (length === 0) { return this.start.clone(); } let fromStart = true; if (length < 0) { fromStart = false; length = -length; // eslint-disable-line } const precision = this.getPrecision(options); const segmentSubdivisions = this.getSubdivisions(options); let lastVisibleSegment; let memo = 0; for (let i = 0, ii = this.segments.length; i < ii; i += 1) { const index = fromStart ? i : ii - 1 - i; const segment = this.segments[index]; const subdivisions = segmentSubdivisions[index]; const d = segment.length({ precision, subdivisions, }); if (segment.isVisible) { if (length <= memo + d) { return segment.pointAtLength((fromStart ? 1 : -1) * (length - memo), { precision, 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 const lastSegment = this.segments[this.segments.length - 1]; return lastSegment.end.clone(); } pointAtT(t) { const segments = this.segments; const numSegments = segments.length; if (numSegments === 0) return null; // if segments is an empty array const segmentIndex = t.segmentIndex; if (segmentIndex < 0) return segments[0].pointAtT(0); if (segmentIndex >= numSegments) { return segments[numSegments - 1].pointAtT(1); } const tValue = util_1.GeometryUtil.clamp(t.value, 0, 1); return segments[segmentIndex].pointAtT(tValue); } divideAt(ratio, options = {}) { if (this.segments.length === 0) { return null; } const rate = util_1.GeometryUtil.clamp(ratio, 0, 1); const opts = this.getOptions(options); const len = this.length(opts); const length = len * rate; return this.divideAtLength(length, opts); } divideAtLength(length, options = {}) { if (this.segments.length === 0) { return null; } let fromStart = true; if (length < 0) { fromStart = false; length = -length; // eslint-disable-line } const precision = this.getPrecision(options); const segmentSubdivisions = this.getSubdivisions(options); let memo = 0; let divided; let dividedSegmentIndex; let lastValidSegment; let lastValidSegmentIndex; let t; for (let i = 0, ii = this.segments.length; i < ii; i += 1) { const index = fromStart ? i : ii - 1 - i; const segment = this.getSegment(index); const subdivisions = segmentSubdivisions[index]; const opts = { precision, subdivisions }; const len = segment.length(opts); if (segment.isDifferentiable()) { lastValidSegment = segment; lastValidSegmentIndex = index; if (length <= memo + len) { dividedSegmentIndex = index; 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: const pathCopy = this.clone(); const index = dividedSegmentIndex; pathCopy.replaceSegment(index, divided); const divisionStartIndex = index; let divisionMidIndex = index + 1; let 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: const 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: const secondPathSegmentIndexConversion = divisionEndIndex - divisionStartIndex - 1; for (let i = divisionEndIndex, ii = pathCopy.segments.length; i < ii; i += 1) { const originalSegment = this.getSegment(i - secondPathSegmentIndexConversion); const 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 const convertedSegment = Path.createSegment('L', originalSegment.end); pathCopy.replaceSegment(i, convertedSegment); } } // distribute pathCopy segments into two paths and return those: const firstPath = new Path(pathCopy.segments.slice(0, divisionMidIndex)); const secondPath = new Path(pathCopy.segments.slice(divisionMidIndex)); return [firstPath, secondPath]; } intersectsWithLine(line, options = {}) { const polylines = this.toPolylines(options); if (polylines == null) { return null; } let intersections = null; for (let i = 0, ii = polylines.length; i < ii; i += 1) { const polyline = polylines[i]; const intersection = line.intersect(polyline); if (intersection) { if (intersections == null) { intersections = []; } if (Array.isArray(intersection)) { intersections.push(...intersection); } else { intersections.push(intersection); } } } return intersections; } isDifferentiable() { for (let i = 0, ii = this.segments.length; i < ii; i += 1) { const segment = this.segments[i]; if (segment.isDifferentiable()) { return true; } } return false; } isValid() { const segments = this.segments; const isValid = segments.length === 0 || segments[0].type === 'M'; return isValid; } length(options = {}) { if (this.segments.length === 0) { return 0; } const segmentSubdivisions = this.getSubdivisions(options); let length = 0; for (let i = 0, ii = this.segments.length; i < ii; i += 1) { const segment = this.segments[i]; const subdivisions = segmentSubdivisions[i]; length += segment.length({ subdivisions }); } return length; } lengthAtT(t, options = {}) { const count = this.segments.length; if (count === 0) { return 0; } let segmentIndex = t.segmentIndex; if (segmentIndex < 0) { return 0; } let tValue = util_1.GeometryUtil.clamp(t.value, 0, 1); if (segmentIndex >= count) { segmentIndex = count - 1; tValue = 1; } const precision = this.getPrecision(options); const segmentSubdivisions = this.getSubdivisions(options); let length = 0; for (let i = 0; i < segmentIndex; i += 1) { const segment = this.segments[i]; const subdivisions = segmentSubdivisions[i]; length += segment.length({ precision, subdivisions }); } const segment = this.segments[segmentIndex]; const subdivisions = segmentSubdivisions[segmentIndex]; length += segment.lengthAtT(tValue, { precision, subdivisions }); return length; } tangentAt(ratio, options = {}) { if (this.segments.length === 0) { return null; } const rate = util_1.GeometryUtil.clamp(ratio, 0, 1); const opts = this.getOptions(options); const len = this.length(opts); const length = len * rate; return this.tangentAtLength(length, opts); } tangentAtLength(length, options = {}) { if (this.segments.length === 0) { return null; } let fromStart = true; if (length < 0) { fromStart = false; length = -length; // eslint-disable-line } const precision = this.getPrecision(options); const segmentSubdivisions = this.getSubdivisions(options); let lastValidSegment; let memo = 0; for (let i = 0, ii = this.segments.length; i < ii; i += 1) { const index = fromStart ? i : ii - 1 - i; const segment = this.segments[index]; const subdivisions = segmentSubdivisions[index]; const len = segment.length({ precision, subdivisions }); if (segment.isDifferentiable()) { if (length <= memo + len) { return segment.tangentAtLength((fromStart ? 1 : -1) * (length - memo), { precision, 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) { const t = fromStart ? 1 : 0; return lastValidSegment.tangentAtT(t); } // if no valid segment, return null return null; } tangentAtT(t) { const count = this.segments.length; if (count === 0) { return null; } const segmentIndex = t.segmentIndex; if (segmentIndex < 0) { return this.segments[0].tangentAtT(0); } if (segmentIndex >= count) { return this.segments[count - 1].tangentAtT(1); } const tValue = util_1.GeometryUtil.clamp(t.value, 0, 1); return this.segments[segmentIndex].tangentAtT(tValue); } getPrecision(options = {}) { return options.precision == null ? this.PRECISION : options.precision; } getSubdivisions(options = {}) { if (options.segmentSubdivisions == null) { const precision = this.getPrecision(options); return this.getSegmentSubdivisions({ precision }); } return options.segmentSubdivisions; } getOptions(options = {}) { const precision = this.getPrecision(options); const segmentSubdivisions = this.getSubdivisions(options); return { precision, segmentSubdivisions }; } toPoints(options = {}) { const segments = this.segments; const count = segments.length; if (count === 0) { return null; } const segmentSubdivisions = this.getSubdivisions(options); const points = []; let partialPoints = []; for (let i = 0; i < count; i += 1) { const segment = segments[i]; if (segment.isVisible) { const divisions = segmentSubdivisions[i]; if (divisions.length > 0) { // eslint-disable-next-line no-loop-func divisions.forEach((c) => 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; } toPolylines(options = {}) { const points = this.toPoints(options); if (!points) { return null; } return points.map((arr) => new polyline_1.Polyline(arr)); } scale(sx, sy, origin) { this.segments.forEach((s) => s.scale(sx, sy, origin)); return this; } rotate(angle, origin) { this.segments.forEach((segment) => segment.rotate(angle, origin)); return this; } translate(tx, ty) { if (typeof tx === 'number') { this.segments.forEach((s) => s.translate(tx, ty)); } else { this.segments.forEach((s) => s.translate(tx)); } return this; } clone() { const path = new Path(); this.segments.forEach((s) => path.appendSegment(s.clone())); return path; } equals(p) { if (p == null) { return false; } const segments = this.segments; const otherSegments = p.segments; const count = segments.length; if (otherSegments.length !== count) { return false; } for (let i = 0; i < count; i += 1) { const a = segments[i]; const b = otherSegments[i]; if (a.type !== b.type || !a.equals(b)) { return false; } } return true; } toJSON() { return this.segments.map((s) => s.toJSON()); } serialize() { if (!this.isValid()) { throw new Error('Invalid path segments.'); } return this.segments.map((s) => s.serialize()).join(' '); } toString() { return this.serialize(); } } exports.Path = Path; (function (Path) { function isPath(instance) { return instance != null && instance instanceof Path; } Path.isPath = isPath; })(Path = exports.Path || (exports.Path = {})); (function (Path) { function parse(pathData) { if (!pathData) { return new Path(); } const path = new Path(); const commandRe = /(?:[a-zA-Z] *)(?:(?:-?\d+(?:\.\d+)?(?:e[-+]?\d+)? *,? *)|(?:-?\.\d+ *,? *))+|(?:[a-zA-Z] *)(?! |\d|-|\.)/g; const commands = Path.normalize(pathData).match(commandRe); if (commands != null) { for (let i = 0, ii = commands.length; i < ii; i += 1) { const command = commands[i]; const argRe = /(?:[a-zA-Z])|(?:(?:-?\d+(?:\.\d+)?(?:e[-+]?\d+)?))|(?:(?:-?\.\d+))/g; const args = command.match(argRe); // [type, coordinate1, coordinate2...] if (args != null) { const type = args[0]; const coords = args.slice(1).map((a) => +a); const segment = createSegment.call(null, type, ...coords); path.appendSegment(segment); } } } return path; } Path.parse = parse; function createSegment(type, ...args) { if (type === 'M') { return moveto_1.MoveTo.create.call(null, ...args); } if (type === 'L') { return lineto_1.LineTo.create.call(null, ...args); } if (type === 'C') { return curveto_1.CurveTo.create.call(null, ...args); } 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 = {})); (function (Path) { Path.normalize = normalize_1.normalizePathData; Path.isValid = PathUtil.isValid; Path.drawArc = PathUtil.drawArc; Path.drawPoints = PathUtil.drawPoints; Path.arcToCurves = PathUtil.arcToCurves; })(Path = exports.Path || (exports.Path = {})); //# sourceMappingURL=path.js.map