UNPKG

svg-pathdata

Version:

Manipulate SVG path data (path[d] attribute content) simply and efficiently.

56 lines (49 loc) 1.85 kB
import { SVGPathData } from '../SVGPathData.js'; import { SVGPathDataTransformer } from '../index.js'; import { arePointsCollinear, type Point } from '../mathUtils.js'; import type { SVGCommand } from '../types.js'; /** * Process a path and remove collinear points * @param commands Array of SVG path commands to process (must be absolute) * @returns New array with collinear points removed */ export function REMOVE_COLLINEAR(commands: SVGCommand[]): SVGCommand[] { if (commands.length <= 2) return commands; // exit early if there are less than 3 points const results: SVGCommand[] = []; const points: Point[] = commands.map( SVGPathDataTransformer.INFO((cmd, pXAbs, pYAbs) => { // Calculate absolute coordinates and normlise HV const isRelatve = 'relative' in cmd && cmd.relative; return [ 'x' in cmd ? cmd.x + (isRelatve ? pXAbs : 0) : pXAbs, 'y' in cmd ? cmd.y + (isRelatve ? pYAbs : 0) : pYAbs, ]; }), ); let prevPoint = points[0]; results.push(commands[0]); // always keep the first point for (let i = 1; i < commands.length; i++) { const cmd = commands[i]; const nextCmd = commands[i + 1]; if ( i < commands.length - 1 && nextCmd && cmd.type & SVGPathData.LINE_COMMANDS && nextCmd.type & SVGPathData.LINE_COMMANDS ) { const nextPoint = points[i + 1]; // Check triplets of points for collinearity if (arePointsCollinear(prevPoint, points[i], nextPoint)) { // update next point if its relative if ('relative' in nextCmd && nextCmd.relative) { if ('x' in nextCmd) nextCmd.x = nextPoint[0] - prevPoint[0]; if ('y' in nextCmd) nextCmd.y = nextPoint[1] - prevPoint[1]; } continue; } } results.push(cmd); prevPoint = points[i]; } return results; }