diff --git a/designs/examples/src/index.mjs b/designs/examples/src/index.mjs index 50cdfa2a04f..4ea67245a19 100644 --- a/designs/examples/src/index.mjs +++ b/designs/examples/src/index.mjs @@ -27,6 +27,8 @@ import { path_reverse, path_shiftalong, path_shiftfractionalong, + path_smurve, + path_smurve_, path_split, path_start, path_translate, @@ -153,6 +155,8 @@ const Examples = new Design({ path_reverse, path_shiftalong, path_shiftfractionalong, + path_smurve, + path_smurve_, path_split, path_start, path_translate, @@ -272,6 +276,8 @@ export { path_reverse, path_shiftalong, path_shiftfractionalong, + path_smurve, + path_smurve_, path_split, path_start, path_translate, diff --git a/designs/examples/src/path.mjs b/designs/examples/src/path.mjs index 3ced231626f..f4f7fda1afb 100644 --- a/designs/examples/src/path.mjs +++ b/designs/examples/src/path.mjs @@ -571,6 +571,47 @@ export const path_shiftfractionalong = { }, } +export const path_smurve = { + name: 'examples.path_smurve', + draft: ({ Point, points, Path, paths, part }) => { + points.from = new Point(10, 20) + points.cp1 = new Point(40, 10) + points.cp2 = new Point(60, 30) + points.to = new Point(90, 20) + points.scp2 = new Point(140, 30) + points.sto = new Point(170, 20) + + paths.line = new Path() + .move(points.from) + .curve(points.cp1, points.cp2, points.to) + .smurve(points.scp2, points.sto) + .attr('data-text', 'Path.smurve()') + .attr('data-text-class', 'text-sm center fill-note') + + return box(part, 180, 40) + }, +} + +export const path_smurve_ = { + name: 'examples.path_smurve_', + draft: ({ Point, points, Path, paths, part }) => { + points.from = new Point(10, 20) + points.cp1 = new Point(40, 10) + points.cp2 = new Point(60, 30) + points.to = new Point(90, 20) + points.sto = new Point(170, 20) + + paths.line = new Path() + .move(points.from) + .curve(points.cp1, points.cp2, points.to) + .smurve_(points.sto) + .attr('data-text', 'Path.smurve_()') + .attr('data-text-class', 'text-sm center fill-note') + + return box(part, 180, 40) + }, +} + export const path_split = { name: 'examples.path_split', draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => { diff --git a/packages/core/src/path.mjs b/packages/core/src/path.mjs index 3c65f5d02c3..3689e6ae188 100644 --- a/packages/core/src/path.mjs +++ b/packages/core/src/path.mjs @@ -665,6 +665,43 @@ Path.prototype.shiftFractionAlong = function (fraction, stepsPerMm = 10) { return this.shiftAlong(this.length() * fraction, stepsPerMm) } +/** + * Adds a smooth curve operation via cp2 to Point to + * + * @param {Point} cp2 - The end control Point + * @param {Point} to - The end point + * @return {Path} this - The Path instance + */ +Path.prototype.smurve = function (cp2, to) { + if (to instanceof Point !== true) + this.log.warning('Called `Path.smurve(cp2, to)` but `to` is not a `Point` object') + if (cp2 instanceof Point !== true) + this.log.warning('Called `Path.smurve(cp2, to)` but `cp2` is not a `Point` object') + // Retrieve cp1 from previous operation + const prevOp = this.ops.slice(-1).pop() + const cp1 = prevOp.cp2.rotate(180, prevOp.to) + this.ops.push({ type: 'curve', cp1, cp2, to }) + + return this +} + +/** + * Adds a smooth curve operation without cp to Point to + * + * @return {Path} this - The Path instance + */ +Path.prototype.smurve_ = function (to) { + if (to instanceof Point !== true) + this.log.warning('Called `Path.smurve_(to)` but `to` is not a `Point` object') + // Retrieve cp1 from previous operation + const prevOp = this.ops.slice(-1).pop() + const cp1 = prevOp.cp2.rotate(180, prevOp.to) + const cp2 = to + this.ops.push({ type: 'curve', cp1, cp2, to }) + + return this +} + /** * Splits path on point, and retuns both halves as Path instances * diff --git a/packages/core/tests/path.test.mjs b/packages/core/tests/path.test.mjs index 5ab947e0772..708fbc71bbb 100644 --- a/packages/core/tests/path.test.mjs +++ b/packages/core/tests/path.test.mjs @@ -4,6 +4,35 @@ import { round, Path, Point, Design } from '../src/index.mjs' const expect = chai.expect describe('Path', () => { + it('Should draw a smurve', () => { + const part = { + name: 'test', + draft: ({ Point, points, Path, paths, part }) => { + points.from = new Point(10, 20) + points.cp1 = new Point(40, 0) + points.cp2 = new Point(60, 30) + points.to = new Point(90, 20) + points.scp2 = new Point(30, 55) + points.sto = new Point(10, 50) + + paths.test = new Path() + .move(points.from) + .curve(points.cp1, points.cp2, points.to) + .smurve(points.scp2, points.sto) + console.log(paths.test, 'in draft') + + return part + }, + } + const design = new Design({ parts: [part] }) + const pattern = new design() + pattern.draft().render() + + console.log(pattern.parts[0].test.paths) + console.log(pattern.stores[0].logs) + //expect(pattern.parts[0].test.paths.test.bottomRight.x).to.equal(-10) + }) + it('Should offset a line', () => { const part = { name: 'test',