From ffe35810b4b38652bbb9f890f57555337e7da0c8 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Tue, 24 May 2016 07:01:41 -0700 Subject: [PATCH] Maker.js 0.8.0 and Bezier-js (#9408) * Added definitions for Bezier.Js * updates for maker.js and bezier.js * removed copyright * deleted bezierjs * Added definitions for Bezier.Js * updates for maker.js and bezier.js * deleted bezierjs * changed name to DefinitelyTyped * update tests for 0.8.0 * rename to bezier-js * add pdfkit reference * public clockwise --- bezier-js/bezier-js-tests.ts | 95 +++++ bezier-js/bezier-js.d.ts | 197 +++++++++++ maker.js/makerjs-tests.ts | 11 +- maker.js/makerjs.d.ts | 661 +++++++++++++++++++++++++++++------ 4 files changed, 849 insertions(+), 115 deletions(-) create mode 100644 bezier-js/bezier-js-tests.ts create mode 100644 bezier-js/bezier-js.d.ts diff --git a/bezier-js/bezier-js-tests.ts b/bezier-js/bezier-js-tests.ts new file mode 100644 index 0000000000..1814d67dc0 --- /dev/null +++ b/bezier-js/bezier-js-tests.ts @@ -0,0 +1,95 @@ +/// + +function test() { + + var bezierjs: typeof BezierJs; + + var bezier = new bezierjs.Bezier([1,2,3,4]); + var cap = new bezierjs.BezierCap([]); + var point: BezierJs.Point = { x: 0, y: 0 }; + var utils = bezier.getUtils(); + var line: BezierJs.Line = { p1: { x:0, y: 0}, p2: {x:1, y: 1}}; + var abc: BezierJs.ABC = { A: null, B: null, C: null }; + var arc: BezierJs.Arc = { e: 0, s: 0, x: 0, y: 0, r: 1 }; + var bbox: BezierJs.BBox = bezier.bbox(); + var closest: BezierJs.Closest = { mdist: 1, mpos: 0 }; + var inflection: BezierJs.Inflection = { values: null, x: [0], y: [0], z:[0] }; + var minmax: BezierJs.MinMax = { min: 0, max: 0 }; + var offset: BezierJs.Offset = { x: 0, y: 0, c: point, n: point }; + var pair: BezierJs.Pair = { left: bezier, right: bezier }; + var poly: BezierJs.PolyBezier = bezier.outline(1); + var projection: BezierJs.Projection = { x: 0, y: 0, t: 9, d: 4 }; + var shape: BezierJs.Shape = { startcap: cap, endcap: cap, forward: bezier, back: bezier, bbox: bbox }; + var split: BezierJs.Split = { left: bezier, right: bezier, span: [point] }; + + bezier.arcs(); + bezier.clockwise; + bezier.compute(.5); + bezier.computedirection(); + bezier.curveintersects([bezier], [bezier]); + bezier.derivative(0); + bezier.get(1); + bezier.getLUT()[0].x; + bezier.hull(0); + bezier.inflections().values; + bezier.intersects(bezier); + bezier.length(); + bezier.lineIntersects(line); + bezier.normal(0); + bezier.offset(1,2); + bezier.on(point, 0); + bezier.order = 5; + bezier.outlineshapes(1,3); + bezier.overlaps(bezier); + bezier.point(9); + bezier.project(point); + bezier.raise(); + bezier.reduce(); + bezier.scale(4); + bezier.selfintersects(); + bezier.simple(); + bezier.split(0, 1); + bezier.toSVG(); + bezier.update(); + + cap.virtual = true; + + poly.addCurve(bezier); + poly.bbox(); + poly.curve(7); + poly.curves[0]._3d; + poly.length(); + poly.offset(9).points[0].y; + poly.points[0]; + + utils.abcratio(0, 1); + utils.align([point], line); + utils.angle(point, point, point); + utils.approximately(5, 7, .001); + utils.arcfn(1, function(){}); + utils.bboxoverlap(bbox, bbox); + utils.between(0, 0, 1); + utils.closest([point], point); + utils.copy({}); + utils.dist(point, point); + utils.droots([9]); + utils.expandbox(bbox, bbox); + utils.findbbox([bezier]); + utils.getccenter(point, point, point); + utils.getminmax(bezier, 'x', [0]); + utils.length(function(){}); + utils.lerp(1, point, point); + utils.lli(offset, offset); + utils.lli4(point, point, point, point); + utils.lli8(0, 0, 0, 0, 0, 0, 0, 0); + utils.makeline(point, point); + utils.makeshape(bezier, bezier); + utils.map(0, 0, 0, 0, 0); + utils.pairiteration(bezier, bezier); + utils.pointsToString([point]); + utils.projectionratio(0, 0); + utils.roots([point], line); + utils.round(.999, .001); + utils.shapeintersections(shape, bbox, shape, bbox); + +} \ No newline at end of file diff --git a/bezier-js/bezier-js.d.ts b/bezier-js/bezier-js.d.ts new file mode 100644 index 0000000000..7d54a19d95 --- /dev/null +++ b/bezier-js/bezier-js.d.ts @@ -0,0 +1,197 @@ +// Type definitions for Bezier.js +// Project: https://github.com/Pomax/bezierjs +// Definitions by: Dan Marshall +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +declare module BezierJs { + interface Point { + x: number; + y: number; + z?: number; + } + interface Projection extends Point { + t?: number; + d?: number; + } + interface Inflection { + x: number[]; + y: number[]; + z?: number[]; + values: number[]; + } + interface Offset extends Point { + c: Point; + n: Point; + } + interface Pair { + left: Bezier; + right: Bezier; + } + interface Split extends Pair { + span: Point[]; + _t1?: number; + _t2?: number; + } + interface MinMax { + min: number; + mid?: number; + max: number; + size?: number; + } + interface BBox { + x: MinMax; + y: MinMax; + z?: MinMax; + } + interface Line { + p1: Point; + p2: Point; + } + interface Arc extends Point { + e: number; + r: number; + s: number; + } + interface Shape { + startcap: BezierCap; + forward: Bezier; + back: Bezier; + endcap: BezierCap; + bbox: BBox; + } + interface ABC { + A: Point; + B: Point; + C: Point; + } + interface Closest { + mdist: number; + mpos: number; + } + /** + * Bezier curve constructor. The constructor argument can be one of three things: + * + * 1. array/4 of {x:..., y:..., z:...}, z optional + * 2. numerical array/8 ordered x1,y1,x2,y2,x3,y3,x4,y4 + * 3. numerical array/12 ordered x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4 + * + */ + class Bezier { + clockwise: boolean; + private _linear; + _3d: boolean; + _t1: number; + _t2: number; + _lut: Point[]; + dpoints: Point[][]; + order: number; + points: Point[]; + dims: string[]; + dimlen: number; + constructor(points: Point[]); + constructor(coords: number[]); + constructor(n1: number, n2: number, n3: number, n4: number, n5: number, n6: number, n7: number, n8: number); + constructor(p1: Point, p2: Point, p3: Point, p4?: Point); + static fromSVG(svgString: string): Bezier; + static getABC(n: number, S: Point, B: Point, E: Point, t: number): ABC; + static quadraticFromPoints(p1: Point, p2: Point, p3: Point, t: number): Bezier; + static cubicFromPoints(S: Point, B: Point, E: Point, t: number, d1: number): Bezier; + static getUtils(): typeof utils; + getUtils(): typeof utils; + valueOf(): string; + toString(): string; + toSVG(): string; + update(): void; + computedirection(): void; + length(): number; + getLUT(steps?: number): Point[]; + on(point: Point, error: number): number; + project(point: Point): Projection; + get(t: number): Point; + point(idx: number): Point; + compute(t: number): Point; + raise(): Bezier; + derivative(t: number): Point; + inflections(): number[]; + normal(t: number): Point; + private __normal2(t); + private __normal3(t); + private __normal(t); + hull(t: number): Point[]; + split(t1: number, t2?: number): Bezier | Split; + extrema(): Inflection; + bbox(): BBox; + overlaps(curve: Bezier): boolean; + offset(t: number, d?: number): Offset | Bezier[]; + simple(): boolean; + reduce(): any[]; + scale(d: Function): Bezier; + scale(d: number): Bezier; + outline(d1: number, d2?: number, d3?: number, d4?: number): PolyBezier; + outlineshapes(d1: number, d2: number): Shape[]; + intersects(curve: Bezier): string[] | number[]; + intersects(curve: Line): string[] | number[]; + lineIntersects(line: Line): number[]; + selfintersects(): string[]; + curveintersects(c1: Bezier[], c2: Bezier[]): string[]; + arcs(errorThreshold?: number): Arc[]; + private _error(pc, np1, s, e); + private _iterate(errorThreshold, circles); + } + class BezierCap extends Bezier { + virtual: boolean; + } +} +declare module BezierJs.utils { + var Tvalues: number[]; + var Cvalues: number[]; + function arcfn(t: number, derivativeFn: Function): number; + function between(v: number, m: number, M: number): boolean; + function approximately(a: number, b: number, precision?: number): boolean; + function length(derivativeFn: Function): number; + function map(v: number, ds: number, de: number, ts: number, te: number): number; + function lerp(r: number, v1: Point, v2: Point): Point; + function pointToString(p: Point): string; + function pointsToString(points: Point[]): string; + function copy(obj: Object): any; + function angle(o: Point, v1: Point, v2: Point): number; + function round(v: number, d: number): number; + function dist(p1: Point, p2: Point): number; + function closest(LUT: Point[], point: Point): Closest; + function abcratio(t: number, n: number): number; + function projectionratio(t: number, n: number): number; + function lli8(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number): Point; + function lli4(p1: Point, p2: Point, p3: Point, p4: Point): Point; + function lli(v1: Offset, v2: Offset): Point; + function makeline(p1: Point, p2: Point): Bezier; + function findbbox(sections: Bezier[]): BBox; + function shapeintersections(s1: Shape, bbox1: BBox, s2: Shape, bbox2: BBox): string[][] | number[][]; + function makeshape(forward: Bezier, back: Bezier): Shape; + function getminmax(curve: Bezier, d: string, list: number[]): MinMax; + function align(points: Point[], line: Line): Point[]; + function roots(points: Point[], line: Line): number[]; + function droots(p: number[]): number[]; + function inflections(points: Point[]): number[]; + function bboxoverlap(b1: BBox, b2: BBox): boolean; + function expandbox(bbox: BBox, _bbox: BBox): void; + function pairiteration(c1: Bezier, c2: Bezier): string[]; + function getccenter(p1: Point, p2: Point, p3: Point): Arc; +} +declare module BezierJs { + /** + * Poly Bezier + * @param {[type]} curves [description] + */ + class PolyBezier { + curves: Bezier[]; + private _3d; + points: Point[]; + constructor(curves: Bezier[]); + valueOf(): string; + toString(): string; + addCurve(curve: Bezier): void; + length(): number; + curve(idx: number): Bezier; + bbox(): BBox; + offset(d: number): PolyBezier; + } +} diff --git a/maker.js/makerjs-tests.ts b/maker.js/makerjs-tests.ts index e314f09669..ef32f885ff 100644 --- a/maker.js/makerjs-tests.ts +++ b/maker.js/makerjs-tests.ts @@ -25,11 +25,11 @@ function test() { } function testAngle() { - makerjs.angle.areEqual(12, 13); makerjs.angle.mirror(45, true, false); makerjs.angle.noRevolutions(90); makerjs.angle.ofArcEnd(paths.arc); makerjs.angle.ofArcMiddle(paths.arc); + makerjs.angle.ofArcSpan(paths.arc); makerjs.angle.ofLineInDegrees(paths.line); makerjs.angle.ofPointInDegrees([0,0], [1,1]); makerjs.angle.ofPointInRadians([0,0], [1,1]); @@ -67,7 +67,9 @@ function test() { } function testMeasure() { - makerjs.measure.arcAngle(paths.arc); + makerjs.measure.isPointEqual(p1, p2); + makerjs.measure.isPathEqual(paths.line, paths.circle, 4); + makerjs.measure.isAngleEqual(12, 13); makerjs.measure.isArcConcaveTowardsPoint(paths.arc, [0,0]); makerjs.measure.isBetween(7, 8, 9, false); makerjs.measure.isBetweenArcAngles(7, paths.arc, false); @@ -119,7 +121,6 @@ function test() { } function testPath() { - makerjs.path.areEqual(paths.line, paths.circle, 4); makerjs.path.breakAtPoint(paths.arc, [0,0]).type; makerjs.path.dogbone(paths.line, paths.line, 7); makerjs.path.fillet(paths.arc, paths.line, 4); @@ -129,7 +130,6 @@ function test() { makerjs.path.moveRelative(paths.circle, [0,0]); makerjs.path.rotate(paths.line, 5, [0,0]); makerjs.path.scale(paths.arc, 8); - makerjs.path.slopeIntersectionPoint(paths.line, paths.line); } function testPaths() { @@ -156,8 +156,6 @@ function test() { function testPoint() { makerjs.point.add(p1, p2); - makerjs.point.areEqual(p1, p2); - makerjs.point.areEqualRounded(p1, p2); makerjs.point.average(p1, p2); makerjs.point.clone(p1); makerjs.point.closest([0,0], [p1, p2]); @@ -170,7 +168,6 @@ function test() { makerjs.point.rotate(p1, 5, p2); makerjs.point.rounded(p1); makerjs.point.scale(p2, 8); - makerjs.point.serialize(p1); makerjs.point.subtract(p2, p1); makerjs.point.zero(); } diff --git a/maker.js/makerjs.d.ts b/maker.js/makerjs.d.ts index fdfade36da..28db25f854 100644 --- a/maker.js/makerjs.d.ts +++ b/maker.js/makerjs.d.ts @@ -2,6 +2,7 @@ // Project: https://github.com/Microsoft/maker.js // Definitions by: Dan Marshall // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +/// /** * Root module for Maker.js. * @@ -37,6 +38,13 @@ declare namespace MakerJs { * @param accuracy Optional exemplar of number of decimal places. */ function round(n: number, accuracy?: number): number; + /** + * Create a string representation of a route array. + * + * @param route Array of strings which are segments of a route. + * @returns String of the flattened array. + */ + function createRouteKey(route: string[]): string; /** * Clone an object. * @@ -89,6 +97,12 @@ declare namespace MakerJs { */ high: IPoint; } + /** + * A map of measurements. + */ + interface IMeasureMap { + [key: string]: IMeasure; + } /** * A line, curved line or other simple two dimensional shape. */ @@ -181,7 +195,6 @@ declare namespace MakerJs { function isPathArc(item: any): boolean; /** * A map of functions which accept a path as a parameter. - * @private */ interface IPathFunctionMap { /** @@ -191,7 +204,6 @@ declare namespace MakerJs { } /** * A map of functions which accept a path and an origin point as parameters. - * @private */ interface IPathOriginFunctionMap { /** @@ -213,10 +225,31 @@ declare namespace MakerJs { Circle: string; Arc: string; }; + /** + * Slope and y-intercept of a line. + */ + interface ISlope { + /** + * Boolean to see if line has slope or is vertical. + */ + hasSlope: boolean; + /** + * Optional value of non-vertical slope. + */ + slope?: number; + /** + * Line used to calculate this slope. + */ + line: IPathLine; + /** + * Optional value of y when x = 0. + */ + yIntercept?: number; + } /** * Options to pass to path.intersection() */ - interface IPathIntersectionOptions { + interface IPathIntersectionBaseOptions { /** * Optional boolean to only return deep intersections, i.e. not on an end point or tangent. */ @@ -226,6 +259,19 @@ declare namespace MakerJs { */ out_AreOverlapped?: boolean; } + /** + * Options to pass to path.intersection() + */ + interface IPathIntersectionOptions extends IPathIntersectionBaseOptions { + /** + * Optional boolean to only return deep intersections, i.e. not on an end point or tangent. + */ + path1Offset?: IPoint; + /** + * Optional output variable which will be set to true if the paths are overlapped. + */ + path2Offset?: IPoint; + } /** * An intersection of two paths. */ @@ -268,6 +314,14 @@ declare namespace MakerJs { * Point which is known to be outside of the model. */ farPoint?: IPoint; + /** + * Cached measurements for model A. + */ + measureA?: measure.Atlas; + /** + * Cached measurements for model B. + */ + measureB?: measure.Atlas; } /** * Options to pass to model.findLoops. @@ -278,6 +332,19 @@ declare namespace MakerJs { */ removeFromOriginal?: boolean; } + /** + * Options to pass to model.simplify() + */ + interface ISimplifyOptions { + /** + * Optional + */ + pointMatchingDistance?: number; + /** + * Optional + */ + scalarMatchingDistance?: number; + } /** * A path that may be indicated to "flow" in either direction between its endpoints. */ @@ -370,11 +437,104 @@ declare namespace MakerJs { pathId: string; } /** - * Path and its reference id within a model + * A route to either a path or a model, and the absolute offset of it. */ - interface IRefPathInModel extends IRefPathIdInModel { + interface IRouteOffset { + layer: string; + offset: IPoint; + route: string[]; + routeKey: string; + } + /** + * A path reference in a walk. + */ + interface IWalkPath extends IRefPathIdInModel, IRouteOffset { pathContext: IPath; } + /** + * Callback signature for path in model.walk(). + */ + interface IWalkPathCallback { + (context: IWalkPath): void; + } + /** + * A link in a chain, with direction of flow. + */ + interface IChainLink { + /** + * Reference to the path. + */ + walkedPath: IWalkPath; + /** + * Path flows forwards or reverse. + */ + reversed: boolean; + /** + * The endpoints of the path, in absolute coords. + */ + endPoints: IPoint[]; + } + /** + * A chain of paths which connect end to end. + */ + interface IChain { + /** + * The links in this chain. + */ + links: IChainLink[]; + /** + * Flag if this chain forms a loop end to end. + */ + endless?: boolean; + } + /** + * Callback to model.findChains() with resulting array of chains and unchained paths. + */ + interface IChainCallback { + (chains: IChain[], loose: IWalkPath[], layer: string): void; + } + /** + * Options to pass to model.findLoops. + */ + interface IFindChainsOptions extends IPointMatchOptions { + /** + * Flag to separate chains by layers. + */ + byLayers?: boolean; + } + /** + * Reference to a model within a model. + */ + interface IRefModelInModel { + parentModel: IModel; + childId: string; + childModel: IModel; + } + /** + * A model reference in a walk. + */ + interface IWalkModel extends IRefModelInModel, IRouteOffset { + } + /** + * Callback signature for model.walk(). + */ + interface IWalkModelCallback { + (context: IWalkModel): void; + } + /** + * Callback signature for model.walk(), which may return false to halt any further walking. + */ + interface IWalkModelCancellableCallback { + (context: IWalkModel): boolean; + } + /** + * Options to pass to model.walk(). + */ + interface IWalkOptions { + onPath?: IWalkPathCallback; + beforeChildWalk?: IWalkModelCancellableCallback; + afterChildWalk?: IWalkModelCallback; + } /** * Describes a parameter and its limits. */ @@ -425,14 +585,6 @@ declare namespace MakerJs { } } declare namespace MakerJs.angle { - /** - * Find out if two angles are equal. - * - * @param a First angle. - * @param b Second angle. - * @returns true if angles are the same, false if they are not - */ - function areEqual(angle1: number, angle2: number, accuracy?: number): boolean; /** * Ensures an angle is not greater than 360 * @@ -469,6 +621,13 @@ declare namespace MakerJs.angle { * @returns Middle angle of arc. */ function ofArcMiddle(arc: IPathArc, ratio?: number): number; + /** + * Total angle of an arc between its start and end angles. + * + * @param arc The arc to measure. + * @returns Angle of arc. + */ + function ofArcSpan(arc: IPathArc): number; /** * Angle of a line path. * @@ -512,23 +671,6 @@ declare namespace MakerJs.point { * @returns A new point object. */ function add(a: IPoint, b: IPoint, subtract?: boolean): IPoint; - /** - * Find out if two points are equal. - * - * @param a First point. - * @param b Second point. - * @returns true if points are the same, false if they are not - */ - function areEqual(a: IPoint, b: IPoint, withinDistance?: number): boolean; - /** - * Find out if two points are equal after rounding. - * - * @param a First point. - * @param b Second point. - * @param accuracy Optional exemplar of number of decimal places. - * @returns true if points are the same, false if they are not - */ - function areEqualRounded(a: IPoint, b: IPoint, accuracy?: number): boolean; /** * Get the average of two points. * @@ -580,7 +722,16 @@ declare namespace MakerJs.point { * @param pathContext The path object. * @returns Array with 2 elements: [0] is the point object corresponding to the origin, [1] is the point object corresponding to the end. */ - function fromPathEnds(pathContext: IPath): IPoint[]; + function fromPathEnds(pathContext: IPath, pathOffset?: IPoint): IPoint[]; + /** + * Calculates the intersection of slopes of two lines. + * + * @param lineA First line to use for slope. + * @param lineB Second line to use for slope. + * @param options Optional IPathIntersectionOptions. + * @returns point of intersection of the two slopes, or null if the slopes did not intersect. + */ + function fromSlopeIntersection(lineA: IPathLine, lineB: IPathLine, options?: IPathIntersectionBaseOptions): IPoint; /** * Get the middle point of a path. * @@ -623,14 +774,6 @@ declare namespace MakerJs.point { * @returns A new point. */ function scale(pointToScale: IPoint, scaleValue: number): IPoint; - /** - * Get a string representation of a point. - * - * @param pointContext The point to serialize. - * @param accuracy Optional exemplar of number of decimal places. - * @returns String representing the point. - */ - function serialize(pointContext: IPoint, accuracy?: number): string; /** * Subtract a point from another point, and return the result as a new point. Shortcut to Add(a, b, subtract = true). * @@ -649,13 +792,12 @@ declare namespace MakerJs.point { } declare namespace MakerJs.path { /** - * Find out if two paths are equal. + * Create a clone of a path. This is faster than cloneObject. * - * @param a First path. - * @param b Second path. - * @returns true if paths are the same, false if they are not + * @param pathToClone The path to clone. + * @returns Cloned path. */ - function areEqual(path1: IPath, path2: IPath, withinPointDistance?: number): boolean; + function clone(pathToClone: IPath): IPath; /** * Create a clone of a path, mirrored on either or both x and y axes. * @@ -679,9 +821,18 @@ declare namespace MakerJs.path { * * @param pathToMove The path to move. * @param delta The x & y adjustments as a point object. + * @param subtract Optional boolean to subtract instead of add. * @returns The original path (for chaining). */ - function moveRelative(pathToMove: IPath, delta: IPoint): IPath; + function moveRelative(pathToMove: IPath, delta: IPoint, subtract?: boolean): IPath; + /** + * Move some paths relatively during a task execution, then unmove them. + * + * @param pathsToMove The paths to move. + * @param deltas The x & y adjustments as a point object array. + * @param task The function to call while the paths are temporarily moved. + */ + function moveTemporary(pathsToMove: IPath[], deltas: IPoint[], task: Function): void; /** * Rotate a path. * @@ -715,11 +866,6 @@ declare namespace MakerJs.path { declare namespace MakerJs.paths { /** * Class for arc path. - * - * @param origin The center point of the arc. - * @param radius The radius of the arc. - * @param startAngle The start angle of the arc. - * @param endAngle The end angle of the arc. */ class Arc implements IPathArc { origin: IPoint; @@ -727,19 +873,71 @@ declare namespace MakerJs.paths { startAngle: number; endAngle: number; type: string; + /** + * Class for arc path, created from origin point, radius, start angle, and end angle. + * + * @param origin The center point of the arc. + * @param radius The radius of the arc. + * @param startAngle The start angle of the arc. + * @param endAngle The end angle of the arc. + */ constructor(origin: IPoint, radius: number, startAngle: number, endAngle: number); + /** + * Class for arc path, created from 2 points, radius, large Arc flag, and clockwise flag. + * + * @param pointA First end point of the arc. + * @param pointB Second end point of the arc. + * @param radius The radius of the arc. + * @param largeArc Boolean flag to indicate clockwise direction. + * @param clockwise Boolean flag to indicate clockwise direction. + */ + constructor(pointA: IPoint, pointB: IPoint, radius: number, largeArc: boolean, clockwise: boolean); + /** + * Class for arc path, created from 2 points and optional boolean flag indicating clockwise. + * + * @param pointA First end point of the arc. + * @param pointB Second end point of the arc. + * @param clockwise Boolean flag to indicate clockwise direction. + */ + constructor(pointA: IPoint, pointB: IPoint, clockwise?: boolean); + /** + * Class for arc path, created from 3 points. + * + * @param pointA First end point of the arc. + * @param pointB Middle point on the arc. + * @param pointC Second end point of the arc. + */ + constructor(pointA: IPoint, pointB: IPoint, pointC: IPoint); } /** * Class for circle path. - * - * @param origin The center point of the circle. - * @param radius The radius of the circle. */ class Circle implements IPathCircle { + type: string; origin: IPoint; radius: number; - type: string; + /** + * Class for circle path, created from origin point and radius. + * + * @param origin The center point of the circle. + * @param radius The radius of the circle. + */ constructor(origin: IPoint, radius: number); + /** + * Class for circle path, created from 2 points. + * + * @param pointA First point on the circle. + * @param pointB Second point on the circle. + */ + constructor(pointA: IPoint, pointB: IPoint); + /** + * Class for circle path, created from 3 points. + * + * @param pointA First point on the circle. + * @param pointB Second point on the circle. + * @param pointC Third point on the circle. + */ + constructor(pointA: IPoint, pointB: IPoint, pointC: IPoint); } /** * Class for line path. @@ -832,6 +1030,14 @@ declare namespace MakerJs.model { * @returns The original model (for chaining). */ function moveRelative(modelToMove: IModel, delta: IPoint): IModel; + /** + * Prefix the ids of paths in a model. + * + * @param modelToPrefix The model to prefix. + * @param prefix The prefix to prepend on paths ids. + * @returns The original model (for chaining). + */ + function prefixPathIds(modelToPrefix: IModel, prefix: string): IModel; /** * Rotate a model. * @@ -865,6 +1071,15 @@ declare namespace MakerJs.model { * @param callback Callback for each path. */ function walkPaths(modelContext: IModel, callback: IModelPathCallback): void; + /** + * Recursively walk through all paths for a given model. + * + * @param modelContext The model to walk. + * @param pathCallback Callback for each path. + * @param modelCallbackBeforeWalk Callback for each model prior to recursion, which can cancel the recursion if it returns false. + * @param modelCallbackAfterWalk Callback for each model after recursion. + */ + function walk(modelContext: IModel, options: IWalkOptions): void; } declare namespace MakerJs.model { /** @@ -875,7 +1090,7 @@ declare namespace MakerJs.model { * @param farPoint Optional point of reference which is outside the bounds of the modelContext. * @returns Boolean true if the path is inside of the modelContext. */ - function isPathInsideModel(pathContext: IPath, modelContext: IModel, farPoint?: IPoint): boolean; + function isPathInsideModel(pathContext: IPath, modelContext: IModel, pathOffset?: IPoint, farPoint?: IPoint, measureAtlas?: measure.Atlas): boolean; /** * Break a model's paths everywhere they intersect with another path. * @@ -884,7 +1099,7 @@ declare namespace MakerJs.model { */ function breakPathsAtIntersections(modelToBreak: IModel, modelToIntersect?: IModel): void; /** - * Combine 2 models. The models should be originated, and every path within each model should be part of a loop. + * Combine 2 models. * * @param modelA First model to combine. * @param modelB Second model to combine. @@ -896,6 +1111,106 @@ declare namespace MakerJs.model { * @param farPoint Optional point of reference which is outside the bounds of both models. */ function combine(modelA: IModel, modelB: IModel, includeAInsideB?: boolean, includeAOutsideB?: boolean, includeBInsideA?: boolean, includeBOutsideA?: boolean, options?: ICombineOptions): void; + /** + * Combine 2 models, resulting in a intersection. + * + * @param modelA First model to combine. + * @param modelB Second model to combine. + */ + function combineIntersection(modelA: IModel, modelB: IModel): void; + /** + * Combine 2 models, resulting in a subtraction of B from A. + * + * @param modelA First model to combine. + * @param modelB Second model to combine. + */ + function combineSubtraction(modelA: IModel, modelB: IModel): void; + /** + * Combine 2 models, resulting in a union. + * + * @param modelA First model to combine. + * @param modelB Second model to combine. + */ + function combineUnion(modelA: IModel, modelB: IModel): void; +} +declare namespace MakerJs { + /** + * Compare keys to see if they are equal. + */ + interface ICollectionKeyComparer { + (a: K, b: K): boolean; + } + /** + * A collection for items that share a common key. + */ + interface ICollection { + key: K; + items: T[]; + } + /** + * Collects items that share a common key. + */ + class Collector { + private comparer; + collections: ICollection[]; + constructor(comparer?: ICollectionKeyComparer); + addItemToCollection(key: K, item: T): void; + findCollection(key: K, action?: (index: number) => void): T[]; + removeCollection(key: K): boolean; + removeItemFromCollection(key: K, item: T): boolean; + getCollectionsOfMultiple(cb: (key: K, items: T[]) => void): void; + } +} +declare namespace MakerJs.model { + /** + * Simplify a model's paths by reducing redundancy: combine multiple overlapping paths into a single path. The model must be originated. + * + * @param modelContext The originated model to search for similar paths. + * @param options Optional options object. + * @returns The simplified model (for chaining). + */ + function simplify(modelToSimplify: IModel, options?: ISimplifyOptions): IModel; +} +declare namespace MakerJs.path { + /** + * Expand path by creating a model which surrounds it. + * + * @param pathToExpand Path to expand. + * @param expansion Distance to expand. + * @param isolateCaps Optional flag to put the end caps into a separate model named "caps". + * @returns Model which surrounds the path. + */ + function expand(pathToExpand: IPath, expansion: number, isolateCaps?: boolean): IModel; + /** + * Represent an arc using straight lines. + * + * @param arc Arc to straighten. + * @param bevel Optional flag to bevel the angle to prevent it from being too sharp. + * @param prefix Optional prefix to apply to path ids. + * @returns Model of straight lines with same endpoints as the arc. + */ + function straighten(arc: IPathArc, bevel?: boolean, prefix?: string): IModel; +} +declare namespace MakerJs.model { + /** + * Expand all paths in a model, then combine the resulting expansions. + * + * @param modelToExpand Model to expand. + * @param distance Distance to expand. + * @param joints Number of points at a joint between paths. Use 0 for round joints, 1 for pointed joints, 2 for beveled joints. + * @returns Model which surrounds the paths of the original model. + */ + function expandPaths(modelToExpand: IModel, distance: number, joints?: number, combineOptions?: ICombineOptions): IModel; + /** + * Outline a model by a specified distance. Useful for accommodating for kerf. + * + * @param modelToOutline Model to outline. + * @param distance Distance to outline. + * @param joints Number of points at a joint between paths. Use 0 for round joints, 1 for pointed joints, 2 for beveled joints. + * @param inside Optional boolean to draw lines inside the model instead of outside. + * @returns Model which surrounds the paths outside of the original model. + */ + function outline(modelToOutline: IModel, distance: number, joints?: number, inside?: boolean): IModel; } declare namespace MakerJs.units { /** @@ -909,12 +1224,48 @@ declare namespace MakerJs.units { } declare namespace MakerJs.measure { /** - * Total angle of an arc between its start and end angles. + * Find out if two angles are equal. * - * @param arc The arc to measure. - * @returns Angle of arc. + * @param angleA First angle. + * @param angleB Second angle. + * @returns true if angles are the same, false if they are not */ - function arcAngle(arc: IPathArc): number; + function isAngleEqual(angleA: number, angleB: number, accuracy?: number): boolean; + /** + * Find out if two paths are equal. + * + * @param pathA First path. + * @param pathB Second path. + * @returns true if paths are the same, false if they are not + */ + function isPathEqual(pathA: IPath, pathB: IPath, withinPointDistance?: number, pathAOffset?: IPoint, pathBOffset?: IPoint): boolean; + /** + * Find out if two points are equal. + * + * @param a First point. + * @param b Second point. + * @returns true if points are the same, false if they are not + */ + function isPointEqual(a: IPoint, b: IPoint, withinDistance?: number): boolean; + /** + * Check for slope equality. + * + * @param slopeA The ISlope to test. + * @param slopeB The ISlope to check for equality. + * @returns Boolean true if slopes are equal. + */ + function isSlopeEqual(slopeA: ISlope, slopeB: ISlope): boolean; +} +declare namespace MakerJs.measure { + /** + * Increase a measurement by an additional measurement. + * + * @param baseMeasure The measurement to increase. + * @param addMeasure The additional measurement. + * @param addOffset Optional offset point of the additional measurement. + * @returns The increased original measurement (for chaining). + */ + function increase(baseMeasure: IMeasure, addMeasure: IMeasure): IMeasure; /** * Check for arc being concave or convex towards a given point. * @@ -923,16 +1274,25 @@ declare namespace MakerJs.measure { * @returns Boolean true if arc is concave towards point. */ function isArcConcaveTowardsPoint(arc: IPathArc, towardsPoint: IPoint): boolean; + /** + * Check for arc overlapping another arc. + * + * @param arcA The arc to test. + * @param arcB The arc to check for overlap. + * @param excludeTangents Boolean to exclude exact endpoints and only look for deep overlaps. + * @returns Boolean true if arc1 is overlapped with arcB. + */ + function isArcOverlapping(arcA: IPathArc, arcB: IPathArc, excludeTangents: boolean): boolean; /** * Check if a given number is between two given limits. * * @param valueInQuestion The number to test. - * @param limit1 First limit. - * @param limit2 Second limit. + * @param limitA First limit. + * @param limitB Second limit. * @param exclusive Flag to exclude equaling the limits. * @returns Boolean true if value is between (or equal to) the limits. */ - function isBetween(valueInQuestion: number, limit1: number, limit2: number, exclusive: boolean): boolean; + function isBetween(valueInQuestion: number, limitA: number, limitB: number, exclusive: boolean): boolean; /** * Check if a given angle is between an arc's start and end angles. * @@ -951,6 +1311,27 @@ declare namespace MakerJs.measure { * @returns Boolean true if point is between (or equal to) the line's origin and end points. */ function isBetweenPoints(pointInQuestion: IPoint, line: IPathLine, exclusive: boolean): boolean; + /** + * Check for line overlapping another line. + * + * @param lineA The line to test. + * @param lineB The line to check for overlap. + * @param excludeTangents Boolean to exclude exact endpoints and only look for deep overlaps. + * @returns Boolean true if line1 is overlapped with lineB. + */ + function isLineOverlapping(lineA: IPathLine, lineB: IPathLine, excludeTangents: boolean): boolean; + /** + * Check for measurement overlapping another measurement. + * + * @param measureA The measurement to test. + * @param measureB The measurement to check for overlap. + * @returns Boolean true if measure1 is overlapped with measureB. + */ + function isMeasurementOverlapping(measureA: IMeasure, measureB: IMeasure): boolean; + /** + * Gets the slope of a line. + */ + function lineSlope(line: IPathLine): ISlope; /** * Calculates the distance between two points. * @@ -965,7 +1346,7 @@ declare namespace MakerJs.measure { * @param pathToMeasure The path to measure. * @returns object with low and high points. */ - function pathExtents(pathToMeasure: IPath): IMeasure; + function pathExtents(pathToMeasure: IPath, addOffset?: IPoint): IMeasure; /** * Measures the length of a path. * @@ -977,9 +1358,38 @@ declare namespace MakerJs.measure { * Measures the smallest rectangle which contains a model. * * @param modelToMeasure The model to measure. + * @param atlas Optional atlas to save measurements. * @returns object with low and high points. */ - function modelExtents(modelToMeasure: IModel): IMeasure; + function modelExtents(modelToMeasure: IModel, atlas?: measure.Atlas): IMeasure; + /** + * A list of maps of measurements. + * + * @param modelToMeasure The model to measure. + * @param atlas Optional atlas to save measurements. + * @returns object with low and high points. + */ + class Atlas { + modelContext: IModel; + /** + * Flag that models have been measured. + */ + modelsMeasured: boolean; + /** + * Map of model measurements, mapped by routeKey. + */ + modelMap: IMeasureMap; + /** + * Map of path measurements, mapped by routeKey. + */ + pathMap: IMeasureMap; + /** + * Constructor. + * @param modelContext The model to measure. + */ + constructor(modelContext: IModel); + measureModels(): void; + } } declare namespace MakerJs.exporter { /** @@ -1050,12 +1460,12 @@ declare namespace MakerJs.solvers { /** * Solves for the angle of a triangle when you know lengths of 3 sides. * - * @param length1 Length of side of triangle, opposite of the angle you are trying to find. - * @param length2 Length of any other side of the triangle. - * @param length3 Length of the remaining side of the triangle. + * @param lengthA Length of side of triangle, opposite of the angle you are trying to find. + * @param lengthB Length of any other side of the triangle. + * @param lengthC Length of the remaining side of the triangle. * @returns Angle opposite of the side represented by the first parameter. */ - function solveTriangleSSS(length1: number, length2: number, length3: number): number; + function solveTriangleSSS(lengthA: number, lengthB: number, lengthC: number): number; /** * Solves for the length of a side of a triangle when you know length of one side and 2 angles. * @@ -1076,33 +1486,24 @@ declare namespace MakerJs.path { * @returns IPathIntersection object, with points(s) of intersection (and angles, when a path is an arc or circle); or null if the paths did not intersect. */ function intersection(path1: IPath, path2: IPath, options?: IPathIntersectionOptions): IPathIntersection; - /** - * Calculates the intersection of slopes of two lines. - * - * @param line1 First line to use for slope. - * @param line2 Second line to use for slope. - * @param options Optional IPathIntersectionOptions. - * @returns point of intersection of the two slopes, or null if the slopes did not intersect. - */ - function slopeIntersectionPoint(line1: IPathLine, line2: IPathLine, options?: IPathIntersectionOptions): IPoint; } declare namespace MakerJs.path { /** * Adds a round corner to the outside angle between 2 lines. The lines must meet at one point. * - * @param line1 First line to fillet, which will be modified to fit the fillet. - * @param line2 Second line to fillet, which will be modified to fit the fillet. + * @param lineA First line to fillet, which will be modified to fit the fillet. + * @param lineB Second line to fillet, which will be modified to fit the fillet. * @returns Arc path object of the new fillet. */ - function dogbone(line1: IPathLine, line2: IPathLine, filletRadius: number, options?: IPointMatchOptions): IPathArc; + function dogbone(lineA: IPathLine, lineB: IPathLine, filletRadius: number, options?: IPointMatchOptions): IPathArc; /** * Adds a round corner to the inside angle between 2 paths. The paths must meet at one point. * - * @param path1 First path to fillet, which will be modified to fit the fillet. - * @param path2 Second path to fillet, which will be modified to fit the fillet. + * @param pathA First path to fillet, which will be modified to fit the fillet. + * @param pathB Second path to fillet, which will be modified to fit the fillet. * @returns Arc path object of the new fillet. */ - function fillet(path1: IPath, path2: IPath, filletRadius: number, options?: IPointMatchOptions): IPathArc; + function fillet(pathA: IPath, pathB: IPath, filletRadius: number, options?: IPointMatchOptions): IPathArc; } declare namespace MakerJs.kit { /** @@ -1123,22 +1524,15 @@ declare namespace MakerJs.kit { } declare namespace MakerJs.model { /** - * @private + * Find paths that have common endpoints and form chains. + * + * @param modelContext The model to search for chains. + * @param options Optional options object. + * @returns A list of chains. */ - interface IPointMappedItem { - averagePoint: IPoint; - item: T; - } - /** - * @private - */ - class PointMap { - matchingDistance: number; - list: IPointMappedItem[]; - constructor(matchingDistance?: number); - add(pointToAdd: IPoint, item: T): void; - find(pointToFind: IPoint, saveAverage: boolean): T; - } + function findChains(modelContext: IModel, callback: IChainCallback, options?: IFindChainsOptions): void; +} +declare namespace MakerJs.model { /** * Find paths that have common endpoints and form loops. * @@ -1153,7 +1547,14 @@ declare namespace MakerJs.model { * @param loopToDetach The model to search for loops. */ function detachLoop(loopToDetach: IModel): void; - function removeDeadEnds(modelContext: IModel, pointMatchingDistance?: number): void; + /** + * Remove paths from a model which have endpoints that do not connect to other paths. + * + * @param modelContext The model to search for dead ends. + * @param options Optional options object. + * @returns The input model (for chaining). + */ + function removeDeadEnds(modelContext: IModel, pointMatchingDistance?: number): IModel; } declare namespace MakerJs.exporter { /** @@ -1249,6 +1650,37 @@ declare namespace MakerJs.exporter { } } declare namespace MakerJs.exporter { + /** + * Injects drawing into a PDFKit document. + * + * @param modelToExport Model object to export. + * @param options Export options object. + * @returns String of PDF file contents. + */ + function toPDF(doc: PDFKit.PDFDocument, modelToExport: IModel, options?: IPDFRenderOptions): void; + /** + * PDF rendering options. + */ + interface IPDFRenderOptions extends IExportOptions { + /** + * Rendered reference origin. + */ + origin?: IPoint; + /** + * SVG color of the rendered paths. + */ + stroke?: string; + } +} +declare namespace MakerJs.exporter { + /** + * Convert a chain to SVG path data. + */ + function chainToSVGPathData(chain: IChain, offset: IPoint): string; + /** + * Convert a path to SVG path data. + */ + function pathToSVGPathData(pathToExport: IPath, offset: IPoint, offset2: IPoint): string; function toSVG(modelToExport: IModel, options?: ISVGRenderOptions): string; function toSVG(pathsToExport: IPath[], options?: ISVGRenderOptions): string; function toSVG(pathToExport: IPath, options?: ISVGRenderOptions): string; @@ -1273,6 +1705,10 @@ declare namespace MakerJs.exporter { * Optional attributes to add to the root svg tag. */ svgAttrs?: IXmlTagAttrs; + /** + * SVG fill color. + */ + fill?: string; /** * SVG font size and font size units. */ @@ -1314,9 +1750,11 @@ declare namespace MakerJs.models { } } declare namespace MakerJs.models { - class Polygon extends ConnectTheDots { - constructor(numberOfSides: number, radius: number, firstCornerAngleInDegrees?: number); - static getPoints(numberOfSides: number, radius: number, firstCornerAngleInDegrees?: number): IPoint[]; + class Polygon implements IModel { + paths: IPathMap; + constructor(numberOfSides: number, radius: number, firstCornerAngleInDegrees?: number, circumscribed?: boolean); + static circumscribedRadius(radius: number, angleInRadians: number): number; + static getPoints(numberOfSides: number, radius: number, firstCornerAngleInDegrees?: number, circumscribed?: boolean): IPoint[]; } } declare namespace MakerJs.models { @@ -1344,19 +1782,24 @@ declare namespace MakerJs.models { } } declare namespace MakerJs.models { - class Oval extends RoundRectangle { + class Oval implements IModel { + paths: IPathMap; constructor(width: number, height: number); } } declare namespace MakerJs.models { class OvalArc implements IModel { paths: IPathMap; - constructor(startAngle: number, endAngle: number, sweepRadius: number, slotRadius: number, selfIntersect?: boolean); + models: IModelMap; + constructor(startAngle: number, endAngle: number, sweepRadius: number, slotRadius: number, selfIntersect?: boolean, isolateCaps?: boolean); } } declare namespace MakerJs.models { - class Rectangle extends ConnectTheDots { + class Rectangle implements IModel { + paths: IPathMap; + origin: IPoint; constructor(width: number, height: number); + constructor(measurement: IMeasure); } } declare namespace MakerJs.models { @@ -1375,11 +1818,13 @@ declare namespace MakerJs.models { class Slot implements IModel { paths: IPathMap; origin: IPoint; - constructor(origin: IPoint, endPoint: IPoint, radius: number); + models: IModelMap; + constructor(origin: IPoint, endPoint: IPoint, radius: number, isolateCaps?: boolean); } } declare namespace MakerJs.models { - class Square extends Rectangle { + class Square implements IModel { + paths: IPathMap; constructor(side: number); } }