From 0320641370121043116a5f5e2019c6d272237ec5 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Fri, 8 Apr 2016 20:38:21 -0700 Subject: [PATCH 1/6] refactoring - moved angle, point, and measure functions to proper namespaces. --- src/core/angle.ts | 27 +++++------ src/core/break.ts | 4 +- src/core/combine.ts | 6 +-- src/core/equal.ts | 103 ++++++++++++++++++++++++++++++++++++++++++ src/core/expand.ts | 2 +- src/core/fillet.ts | 8 ++-- src/core/intersect.ts | 75 +----------------------------- src/core/maker.ts | 9 ++++ src/core/measure.ts | 48 ++++++++------------ src/core/path.ts | 46 ------------------- src/core/paths.ts | 2 +- src/core/point.ts | 74 ++++++++++++++++++------------ src/core/simplify.ts | 4 +- src/core/svg.ts | 2 +- target/tsconfig.json | 1 + tsconfig.json | 1 + 16 files changed, 207 insertions(+), 205 deletions(-) create mode 100644 src/core/equal.ts diff --git a/src/core/angle.ts b/src/core/angle.ts index 556951f5d..d60348e12 100644 --- a/src/core/angle.ts +++ b/src/core/angle.ts @@ -1,19 +1,5 @@ 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 - */ - export function areEqual(angle1: number, angle2: number, accuracy: number = .0001) { - var a1 = noRevolutions(angle1); - var a2 = noRevolutions(angle2); - var d = noRevolutions(round(a2 - a1, accuracy)); - return d == 0; - } - /** * Ensures an angle is not greater than 360 * @@ -69,7 +55,18 @@ namespace MakerJs.angle { * @returns Middle angle of arc. */ export function ofArcMiddle(arc: IPathArc, ratio = .5): number { - return arc.startAngle + measure.arcAngle(arc) * ratio; + return arc.startAngle + ofArcSpan(arc) * ratio; + } + + /** + * Total angle of an arc between its start and end angles. + * + * @param arc The arc to measure. + * @returns Angle of arc. + */ + export function ofArcSpan(arc: IPathArc): number { + var endAngle = angle.ofArcEnd(arc); + return endAngle - arc.startAngle; } /** diff --git a/src/core/break.ts b/src/core/break.ts index 44bdf787b..138eb2269 100644 --- a/src/core/break.ts +++ b/src/core/break.ts @@ -16,7 +16,7 @@ var angleAtBreakPoint = angle.ofPointInDegrees(arc.origin, pointOfBreak); - if (angle.areEqual(angleAtBreakPoint, arc.startAngle) || angle.areEqual(angleAtBreakPoint, arc.endAngle)) { + if (measure.isAngleEqual(angleAtBreakPoint, arc.startAngle) || measure.isAngleEqual(angleAtBreakPoint, arc.endAngle)) { return null; } @@ -61,7 +61,7 @@ breakPathFunctionMap[pathType.Line] = function (line: IPathLine, pointOfBreak: IPoint): IPath { - if (point.areEqual(line.origin, pointOfBreak) || point.areEqual(line.end, pointOfBreak)) { + if (measure.isPointEqual(line.origin, pointOfBreak) || measure.isPointEqual(line.end, pointOfBreak)) { return null; } diff --git a/src/core/combine.ts b/src/core/combine.ts index f9692ba10..2402436a4 100644 --- a/src/core/combine.ts +++ b/src/core/combine.ts @@ -27,7 +27,7 @@ */ function breakAlongForeignPath(segments: ICrossedPathSegment[], overlappedSegments: ICrossedPathSegment[], foreignPath: IPath) { - if (path.areEqual(segments[0].path, foreignPath, .0001)) { + if (measure.isPathEqual(segments[0].path, foreignPath, .0001)) { segments[0].overlapped = true; segments[0].duplicate = true; @@ -102,7 +102,7 @@ function addUniquePoint(pointToAdd: IPoint) { for (var i = 0; i < pointArray.length; i++) { - if (point.areEqual(pointArray[i], pointToAdd, .000000001)) { + if (measure.isPointEqual(pointArray[i], pointToAdd, .000000001)) { return; } } @@ -261,7 +261,7 @@ function checkForEqualOverlaps(crossedPathsA: ICrossedPathSegment[], crossedPathsB: ICrossedPathSegment[], pointMatchingDistance: number) { function compareSegments(segment1: ICrossedPathSegment, segment2: ICrossedPathSegment) { - if (path.areEqual(segment1.path, segment2.path, pointMatchingDistance)) { + if (measure.isPathEqual(segment1.path, segment2.path, pointMatchingDistance)) { segment1.duplicate = segment2.duplicate = true; } } diff --git a/src/core/equal.ts b/src/core/equal.ts new file mode 100644 index 000000000..48f604239 --- /dev/null +++ b/src/core/equal.ts @@ -0,0 +1,103 @@ +namespace MakerJs.measure { + + /** + * 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 + */ + export function isAngleEqual(angle1: number, angle2: number, accuracy: number = .0001) { + var a1 = angle.noRevolutions(angle1); + var a2 = angle.noRevolutions(angle2); + var d = angle.noRevolutions(round(a2 - a1, accuracy)); + return d == 0; + } + + /** + * @private + */ + interface IPathAreEqualMap { + [type: string]: (path1: IPath, path2: IPath, withinPointDistance?: number) => boolean; + } + + /** + * @private + */ + var pathAreEqualMap: IPathAreEqualMap = {}; + + pathAreEqualMap[pathType.Line] = function (line1: IPathLine, line2: IPathLine, withinPointDistance?: number): boolean { + return (isPointEqual(line1.origin, line2.origin, withinPointDistance) && isPointEqual(line1.end, line2.end, withinPointDistance)) + || (isPointEqual(line1.origin, line2.end, withinPointDistance) && isPointEqual(line1.end, line2.origin, withinPointDistance)); + }; + + pathAreEqualMap[pathType.Circle] = function (circle1: IPathCircle, circle2: IPathCircle, withinPointDistance): boolean { + return isPointEqual(circle1.origin, circle2.origin, withinPointDistance) && circle1.radius == circle2.radius; + }; + + pathAreEqualMap[pathType.Arc] = function (arc1: IPathArc, arc2: IPathArc, withinPointDistance): boolean { + return pathAreEqualMap[pathType.Circle](arc1, arc2, withinPointDistance) && isAngleEqual(arc1.startAngle, arc2.startAngle) && isAngleEqual(arc1.endAngle, arc2.endAngle); + }; + + /** + * Find out if two paths are equal. + * + * @param a First path. + * @param b Second path. + * @returns true if paths are the same, false if they are not + */ + export function isPathEqual(path1: IPath, path2: IPath, withinPointDistance?: number): boolean { + + var result = false; + + if (path1.type == path2.type) { + var fn = pathAreEqualMap[path1.type]; + if (fn) { + result = fn(path1, path2, withinPointDistance); + } + } + + return result; + } + + /** + * 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 + */ + export function isPointEqual(a: IPoint, b: IPoint, withinDistance?: number): boolean { + if (!withinDistance) { + return a[0] == b[0] && a[1] == b[1]; + } else { + var distance = measure.pointDistance(a, b); + return distance <= withinDistance; + } + } + + /** + * Check for slope equality. + * + * @param slope1 The ISlope to test. + * @param slope2 The ISlope to check for equality. + * @returns Boolean true if slopes are equal. + */ + export function isSlopeEqual(slope1: ISlope, slope2: ISlope): boolean { + + if (!slope1.hasSlope && !slope2.hasSlope) { + + //lines are both vertical, see if x are the same + return round(slope1.line.origin[0] - slope2.line.origin[0]) == 0; + } + + if (slope1.hasSlope && slope2.hasSlope && (round(slope1.slope - slope2.slope, .00001) == 0)) { + + //lines are parallel, but not vertical, see if y-intercept is the same + return round(slope1.yIntercept - slope2.yIntercept, .00001) == 0; + } + + return false; + } + +} \ No newline at end of file diff --git a/src/core/expand.ts b/src/core/expand.ts index abbf8a584..2dbcc6d4d 100644 --- a/src/core/expand.ts +++ b/src/core/expand.ts @@ -46,7 +46,7 @@ */ export function straighten(arc: IPathArc, bevel?: boolean): IModel { - var arcSpan = measure.arcAngle(arc); + var arcSpan = angle.ofArcSpan(arc); var joints = 1; if (arcSpan >= 270) { diff --git a/src/core/fillet.ts b/src/core/fillet.ts index 489cb42dc..995bba345 100644 --- a/src/core/fillet.ts +++ b/src/core/fillet.ts @@ -78,7 +78,7 @@ namespace MakerJs.path { } function check(i1: number, i2: number) { - if (point.areEqual(path1Properties[i1].point, path2Properties[i2].point, .0001)) { + if (measure.isPointEqual(path1Properties[i1].point, path2Properties[i2].point, .0001)) { result = [ makeMatch(path1, path1Properties, i1), makeMatch(path2, path2Properties, i2) @@ -108,7 +108,7 @@ namespace MakerJs.path { properties[i].shardPoint = circleIntersection.intersectionPoints[0]; - if (point.areEqual(properties[i].point, circleIntersection.intersectionPoints[0], .0001)) { + if (measure.isPointEqual(properties[i].point, circleIntersection.intersectionPoints[0], .0001)) { if (circleIntersection.intersectionPoints.length > 1) { properties[i].shardPoint = circleIntersection.intersectionPoints[1]; } else { @@ -201,7 +201,7 @@ namespace MakerJs.path { path.moveRelative(guideLine, filletCenter); //get the intersection point of the slopes of the context line and the perpendicular line. This is where the fillet meets the line. - var intersectionPoint = slopeIntersectionPoint(line, guideLine); + var intersectionPoint = point.fromSlopeIntersection(line, guideLine); if (intersectionPoint) { result = { filletAngle: angle.ofPointInDegrees(filletCenter, intersectionPoint), @@ -410,7 +410,7 @@ namespace MakerJs.path { if (round(results[0].filletAngle - results[1].filletAngle) == 0) return null; var filletArc = new paths.Arc(center, filletRadius, results[0].filletAngle, results[1].filletAngle); - var filletSpan = measure.arcAngle(filletArc); + var filletSpan = angle.ofArcSpan(filletArc); //the algorithm is only valid for fillet less than 180 degrees if (filletSpan == 180) { diff --git a/src/core/intersect.ts b/src/core/intersect.ts index fde079706..3eda0463a 100644 --- a/src/core/intersect.ts +++ b/src/core/intersect.ts @@ -126,7 +126,7 @@ namespace MakerJs.path { }; map[pathType.Line][pathType.Line] = function (line1: IPathLine, line2: IPathLine, options: IPathIntersectionOptions) { - var intersectionPoint = slopeIntersectionPoint(line1, line2, options); + var intersectionPoint = point.fromSlopeIntersection(line1, line2, options); if (intersectionPoint) { //we have the point of intersection of endless lines, now check to see if the point is between both segemnts @@ -214,77 +214,6 @@ namespace MakerJs.path { return anglesWithinArc; } - /** - * Gets the slope of a line. - */ - export function getSlope(line: IPathLine): ISlope { - var dx = line.end[0] - line.origin[0]; - if (round(dx) == 0) { - return { - line: line, - hasSlope: false - }; - } - - var dy = line.end[1] - line.origin[1]; - - var slope = dy / dx; - var yIntercept = line.origin[1] - slope * line.origin[0]; - - return { - line: line, - hasSlope: true, - slope: slope, - yIntercept: yIntercept - }; - } - - /** - * @private - */ - function verticalIntersectionPoint(verticalLine: IPathLine, nonVerticalSlope: ISlope): IPoint { - var x = verticalLine.origin[0]; - var y = nonVerticalSlope.slope * x + nonVerticalSlope.yIntercept; - return [x, y]; - } - - /** - * 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. - */ - export function slopeIntersectionPoint(line1: IPathLine, line2: IPathLine, options: IPathIntersectionOptions = {}): IPoint { - - var slope1 = getSlope(line1); - var slope2 = getSlope(line2); - - if (measure.isSlopeEqual(slope1, slope2)) { - - //check for overlap - options.out_AreOverlapped = measure.isLineOverlapping(line1, line2, options.excludeTangents); - - return null; - } - - var pointOfIntersection: IPoint; - - if (!slope1.hasSlope) { - pointOfIntersection = verticalIntersectionPoint(line1, slope2); - } else if (!slope2.hasSlope) { - pointOfIntersection = verticalIntersectionPoint(line2, slope1); - } else { - // find intersection by line equation - var x = (slope2.yIntercept - slope1.yIntercept) / (slope1.slope - slope2.slope); - var y = slope1.slope * x + slope1.yIntercept; - pointOfIntersection = [x, y]; - } - - return pointOfIntersection; - } - /** * @private */ @@ -361,7 +290,7 @@ namespace MakerJs.path { function circleToCircle(circle1: IPathCircle, circle2: IPathCircle, options: IPathIntersectionOptions): number[][] { //see if circles are the same - if (circle1.radius == circle2.radius && point.areEqual(circle1.origin, circle2.origin, .0001)) { + if (circle1.radius == circle2.radius && measure.isPointEqual(circle1.origin, circle2.origin, .0001)) { options.out_AreOverlapped = true; return null; } diff --git a/src/core/maker.ts b/src/core/maker.ts index e7ed3698a..8014fb1e6 100644 --- a/src/core/maker.ts +++ b/src/core/maker.ts @@ -515,6 +515,15 @@ namespace MakerJs { return item && (item.paths || item.models); } + /** + * @private + */ + export interface IPathInside { + path: IPath; + isInside?: boolean; + uniqueForeignIntersectionPoints: IPoint[]; + } + /** * Reference to a path id within a model. */ diff --git a/src/core/measure.ts b/src/core/measure.ts index 4ce2b10fc..c6bdb87df 100644 --- a/src/core/measure.ts +++ b/src/core/measure.ts @@ -9,17 +9,6 @@ namespace MakerJs.measure { (...values: number[]): number; } - /** - * Total angle of an arc between its start and end angles. - * - * @param arc The arc to measure. - * @returns Angle of arc. - */ - export function arcAngle(arc: IPathArc): number { - var endAngle = angle.ofArcEnd(arc); - return endAngle - arc.startAngle; - } - /** * Check for arc being concave or convex towards a given point. * @@ -96,7 +85,7 @@ namespace MakerJs.measure { export function isBetweenArcAngles(angleInQuestion: number, arc: IPathArc, exclusive: boolean): boolean { var startAngle = angle.noRevolutions(arc.startAngle); - var span = arcAngle(arc); + var span = angle.ofArcSpan(arc); var endAngle = startAngle + span; angleInQuestion = angle.noRevolutions(angleInQuestion); @@ -149,27 +138,28 @@ namespace MakerJs.measure { } /** - * Check for slope equality. - * - * @param slope1 The ISlope to test. - * @param slope2 The ISlope to check for equality. - * @returns Boolean true if slopes are equal. + * Gets the slope of a line. */ - export function isSlopeEqual(slope1: ISlope, slope2: ISlope): boolean { - - if (!slope1.hasSlope && !slope2.hasSlope) { - - //lines are both vertical, see if x are the same - return round(slope1.line.origin[0] - slope2.line.origin[0]) == 0; + export function lineSlope(line: IPathLine): ISlope { + var dx = line.end[0] - line.origin[0]; + if (round(dx) == 0) { + return { + line: line, + hasSlope: false + }; } - if (slope1.hasSlope && slope2.hasSlope && (round(slope1.slope - slope2.slope, .00001) == 0)) { + var dy = line.end[1] - line.origin[1]; - //lines are parallel, but not vertical, see if y-intercept is the same - return round(slope1.yIntercept - slope2.yIntercept, .00001) == 0; - } + var slope = dy / dx; + var yIntercept = line.origin[1] - slope * line.origin[0]; - return false; + return { + line: line, + hasSlope: true, + slope: slope, + yIntercept: yIntercept + }; } /** @@ -266,7 +256,7 @@ namespace MakerJs.measure { map[pathType.Arc] = function (arc: IPathArc) { map[pathType.Circle](arc); //this sets the value var - var pct = arcAngle(arc) / 360; + var pct = angle.ofArcSpan(arc) / 360; value *= pct; } diff --git a/src/core/path.ts b/src/core/path.ts index e85f6e8f9..60484f0b6 100644 --- a/src/core/path.ts +++ b/src/core/path.ts @@ -1,51 +1,5 @@ namespace MakerJs.path { - /** - * @private - */ - interface IPathAreEqualMap { - [type: string]: (path1: IPath, path2: IPath, withinPointDistance?: number) => boolean; - } - - /** - * @private - */ - var pathAreEqualMap: IPathAreEqualMap = {}; - - pathAreEqualMap[pathType.Line] = function (line1: IPathLine, line2: IPathLine, withinPointDistance?: number): boolean { - return (point.areEqual(line1.origin, line2.origin, withinPointDistance) && point.areEqual(line1.end, line2.end, withinPointDistance)) - || (point.areEqual(line1.origin, line2.end, withinPointDistance) && point.areEqual(line1.end, line2.origin, withinPointDistance)); - }; - - pathAreEqualMap[pathType.Circle] = function (circle1: IPathCircle, circle2: IPathCircle, withinPointDistance): boolean { - return point.areEqual(circle1.origin, circle2.origin, withinPointDistance) && circle1.radius == circle2.radius; - }; - - pathAreEqualMap[pathType.Arc] = function (arc1: IPathArc, arc2: IPathArc, withinPointDistance): boolean { - return pathAreEqualMap[pathType.Circle](arc1, arc2, withinPointDistance) && angle.areEqual(arc1.startAngle, arc2.startAngle) && angle.areEqual(arc1.endAngle, arc2.endAngle); - }; - - /** - * Find out if two paths are equal. - * - * @param a First path. - * @param b Second path. - * @returns true if paths are the same, false if they are not - */ - export function areEqual(path1: IPath, path2: IPath, withinPointDistance?: number): boolean { - - var result = false; - - if (path1.type == path2.type) { - var fn = pathAreEqualMap[path1.type]; - if (fn) { - result = fn(path1, path2, withinPointDistance); - } - } - - return result; - } - /** * Create a clone of a path, mirrored on either or both x and y axes. * diff --git a/src/core/paths.ts b/src/core/paths.ts index e5ae22ea4..75886750c 100644 --- a/src/core/paths.ts +++ b/src/core/paths.ts @@ -232,7 +232,7 @@ namespace MakerJs.paths { } //find intersection of slopes of perpendiculars - this.origin = path.slopeIntersectionPoint(perpendiculars[0], perpendiculars[1]); + this.origin = point.fromSlopeIntersection(perpendiculars[0], perpendiculars[1]); //radius is distance to any of the 3 points this.radius = measure.pointDistance(this.origin, args[0]); diff --git a/src/core/point.ts b/src/core/point.ts index 0e5fc66c5..8ad52287f 100644 --- a/src/core/point.ts +++ b/src/core/point.ts @@ -23,34 +23,6 @@ namespace MakerJs.point { return newPoint; } - /** - * 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 - */ - export function areEqual(a: IPoint, b: IPoint, withinDistance?: number): boolean { - if (!withinDistance) { - return a[0] == b[0] && a[1] == b[1]; - } else { - var distance = measure.pointDistance(a, b); - return distance <= withinDistance; - } - } - - /** - * 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 - */ - export function areEqualRounded(a: IPoint, b: IPoint, accuracy = .0000001): boolean { - return round(a[0], accuracy) == round(b[0], accuracy) && round(a[1], accuracy) == round(b[1], accuracy); - } - /** * Get the average of two points. * @@ -160,6 +132,52 @@ namespace MakerJs.point { return result; } + /** + * @private + */ + function verticalIntersectionPoint(verticalLine: IPathLine, nonVerticalSlope: ISlope): IPoint { + var x = verticalLine.origin[0]; + var y = nonVerticalSlope.slope * x + nonVerticalSlope.yIntercept; + return [x, y]; + } + + /** + * 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. + */ + export function fromSlopeIntersection(line1: IPathLine, line2: IPathLine, options: IPathIntersectionOptions = {}): IPoint { + + var slope1 = measure.lineSlope(line1); + var slope2 = measure.lineSlope(line2); + + if (measure.isSlopeEqual(slope1, slope2)) { + + //check for overlap + options.out_AreOverlapped = measure.isLineOverlapping(line1, line2, options.excludeTangents); + + return null; + } + + var pointOfIntersection: IPoint; + + if (!slope1.hasSlope) { + pointOfIntersection = verticalIntersectionPoint(line1, slope2); + } else if (!slope2.hasSlope) { + pointOfIntersection = verticalIntersectionPoint(line2, slope1); + } else { + // find intersection by line equation + var x = (slope2.yIntercept - slope1.yIntercept) / (slope1.slope - slope2.slope); + var y = slope1.slope * x + slope1.yIntercept; + pointOfIntersection = [x, y]; + } + + return pointOfIntersection; + } + /** * Get the middle point of a path. * diff --git a/src/core/simplify.ts b/src/core/simplify.ts index 9bba73b80..86fe9e6e8 100644 --- a/src/core/simplify.ts +++ b/src/core/simplify.ts @@ -42,7 +42,7 @@ var startAngle = angle.noRevolutions(arc.startAngle); return { startAngle: startAngle, - endAngle: measure.arcAngle(arc) + startAngle + endAngle: angle.ofArcSpan(arc) + startAngle }; } @@ -78,7 +78,7 @@ }; map[pathType.Line] = function (lineRef: IRefPathInModel) { - var slope = path.getSlope(lineRef.pathContext); + var slope = measure.lineSlope(lineRef.pathContext); similarLines.addItemToCollection(slope, lineRef); }; diff --git a/src/core/svg.ts b/src/core/svg.ts index 2af643813..e2ec89043 100644 --- a/src/core/svg.ts +++ b/src/core/svg.ts @@ -190,7 +190,7 @@ namespace MakerJs.exporter { var arcPoints = point.fromArc(arc); - if (point.areEqual(arcPoints[0], arcPoints[1])) { + if (measure.isPointEqual(arcPoints[0], arcPoints[1])) { circleInPaths(id, arc.origin, arc.radius, layer); } else { diff --git a/target/tsconfig.json b/target/tsconfig.json index 8140dd9b4..f29b4def4 100644 --- a/target/tsconfig.json +++ b/target/tsconfig.json @@ -18,6 +18,7 @@ "../src/core/simplify.ts", "../src/core/expand.ts", "../src/core/units.ts", + "../src/core/equal.ts", "../src/core/measure.ts", "../src/core/exporter.ts", "../src/core/dxf.ts", diff --git a/tsconfig.json b/tsconfig.json index ee95a3124..5fd669ec4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,6 +16,7 @@ "src/core/simplify.ts", "src/core/expand.ts", "src/core/units.ts", + "src/core/equal.ts", "src/core/measure.ts", "src/core/exporter.ts", "src/core/dxf.ts", From 4b287a7c50bf9d9c7cb4ee7e9d7758b7b6106964 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Sat, 9 Apr 2016 11:07:19 -0700 Subject: [PATCH 2/6] added equal.js --- playground/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/playground/index.html b/playground/index.html index 6b7fbbc02..b18f5e978 100644 --- a/playground/index.html +++ b/playground/index.html @@ -48,6 +48,7 @@ + From 242970b3de505447b9e0f3665625c97847b91507 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Sat, 9 Apr 2016 11:10:47 -0700 Subject: [PATCH 3/6] added outline --- src/core/expand.ts | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/core/expand.ts b/src/core/expand.ts index 2dbcc6d4d..63821f526 100644 --- a/src/core/expand.ts +++ b/src/core/expand.ts @@ -84,13 +84,13 @@ namespace MakerJs.model { * Expand all paths in a model, then combine the resulting expansions. * * @param modelToExpand Model to expand. - * @param expansion Distance 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. */ - export function expandPaths(modelToExpand: IModel, expansion: number, joints = 0): IModel { + export function expandPaths(modelToExpand: IModel, distance: number, joints = 0): IModel { - if (expansion <= 0) return null; + if (distance <= 0) return null; var result: IModel = { models: { @@ -105,7 +105,7 @@ namespace MakerJs.model { var originated = originate(modelToExpand); walkPaths(originated, function (modelContext: IModel, pathId: string, pathContext: IPath) { - var expandedPathModel = path.expand(pathContext, expansion, true); + var expandedPathModel = path.expand(pathContext, distance, true); if (expandedPathModel) { var newId = getSimilarModelId(result.models['expansions'], pathId); @@ -159,4 +159,34 @@ namespace MakerJs.model { return result; } + /** + * Outline a model by a specified distance. + * + * @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. + * @returns Model which surrounds the paths outside of the original model. + */ + export function outline(modelToOutline:IModel, distance: number, joints?: number): IModel { + var expanded = expandPaths(modelToOutline, distance, joints); + + if (!expanded) return null; + + var loops = findLoops(expanded); + if (loops && loops.models) { + + var i = 0; + + while (loops.models[i]) { + delete loops.models[i + 1]; + delete loops.models[i + 2]; + i += 4; + } + + return loops; + } + + return null; + } + } From 704ba9c0a0be8afacb0b2a2bc23e759e80fd3a21 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Sat, 9 Apr 2016 11:15:45 -0700 Subject: [PATCH 4/6] added kerf comment --- src/core/expand.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/expand.ts b/src/core/expand.ts index 63821f526..f9418a39e 100644 --- a/src/core/expand.ts +++ b/src/core/expand.ts @@ -160,7 +160,7 @@ namespace MakerJs.model { } /** - * Outline a model by a specified distance. + * Outline a model by a specified distance. Useful for accommadating for kerf. * * @param modelToOutline Model to outline. * @param distance Distance to outline. From a792458be4f5d24382035f100f1a5d117bc62c3f Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Sat, 9 Apr 2016 11:16:02 -0700 Subject: [PATCH 5/6] added keywords, version bump --- package.json | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7af45e935..0b05f4be7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "makerjs", - "version": "0.7.0", + "version": "0.7.1", "description": "Maker.js, a Microsoft Garage project, is a JavaScript library for creating and sharing modular line drawings for CNC and laser cutters.", "main": "index.js", "scripts": { @@ -25,10 +25,20 @@ "2D", "vector", "drawing", + "path", + "arc", + "circle", + "line", + "outline", + "kerf", + "shape", + "geometry", + "trigonometry", "SVG", "DXF", "CNC", - "Laser cutter", + "laser", + "cutter", "Water jet" ], "author": "Dan Marshall / Microsoft Corporation", From e20dd66ca910a7bc3ff5086335f41f681b45e45d Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Sat, 9 Apr 2016 11:18:26 -0700 Subject: [PATCH 6/6] new build for 0.7.1 --- archive/browser.0.7.0.maker.js | 403 +- archive/browser.0.7.1.maker.js | 4705 ++++++++++++++++++++++++ archive/node.0.7.0.maker.js | 403 +- archive/node.0.7.1.maker.js | 4536 +++++++++++++++++++++++ index.js | 436 +-- playground/export-format.js.map | 2 +- playground/playground.js | 2 +- playground/playground.js.map | 2 +- playground/pointer.js | 2 +- playground/pointer.js.map | 2 +- playground/require-iframe.js | 4 +- playground/require-iframe.js.map | 2 +- playground/worker/export-worker.js.map | 2 +- target/js/browser.maker.js | 436 +-- target/js/node.maker.js | 436 +-- target/ts/makerjs.d.ts | 140 +- 16 files changed, 10409 insertions(+), 1104 deletions(-) create mode 100644 archive/browser.0.7.1.maker.js create mode 100644 archive/node.0.7.1.maker.js diff --git a/archive/browser.0.7.0.maker.js b/archive/browser.0.7.0.maker.js index 0d8782bdf..1c0398b60 100644 --- a/archive/browser.0.7.0.maker.js +++ b/archive/browser.0.7.0.maker.js @@ -332,21 +332,6 @@ var MakerJs; (function (MakerJs) { var angle; (function (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, angle2, accuracy) { - if (accuracy === void 0) { accuracy = .0001; } - var a1 = noRevolutions(angle1); - var a2 = noRevolutions(angle2); - var d = noRevolutions(MakerJs.round(a2 - a1, accuracy)); - return d == 0; - } - angle.areEqual = areEqual; /** * Ensures an angle is not greater than 360 * @@ -403,9 +388,20 @@ var MakerJs; */ function ofArcMiddle(arc, ratio) { if (ratio === void 0) { ratio = .5; } - return arc.startAngle + MakerJs.measure.arcAngle(arc) * ratio; + return arc.startAngle + ofArcSpan(arc) * ratio; } angle.ofArcMiddle = ofArcMiddle; + /** + * Total angle of an arc between its start and end angles. + * + * @param arc The arc to measure. + * @returns Angle of arc. + */ + function ofArcSpan(arc) { + var endAngle = angle.ofArcEnd(arc); + return endAngle - arc.startAngle; + } + angle.ofArcSpan = ofArcSpan; /** * Angle of a line path. * @@ -488,36 +484,6 @@ var MakerJs; return newPoint; } point.add = add; - /** - * 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, b, withinDistance) { - if (!withinDistance) { - return a[0] == b[0] && a[1] == b[1]; - } - else { - var distance = MakerJs.measure.pointDistance(a, b); - return distance <= withinDistance; - } - } - point.areEqual = areEqual; - /** - * 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, b, accuracy) { - if (accuracy === void 0) { accuracy = .0000001; } - return MakerJs.round(a[0], accuracy) == MakerJs.round(b[0], accuracy) && MakerJs.round(a[1], accuracy) == MakerJs.round(b[1], accuracy); - } - point.areEqualRounded = areEqualRounded; /** * Get the average of two points. * @@ -622,6 +588,47 @@ var MakerJs; return result; } point.fromPathEnds = fromPathEnds; + /** + * @private + */ + function verticalIntersectionPoint(verticalLine, nonVerticalSlope) { + var x = verticalLine.origin[0]; + var y = nonVerticalSlope.slope * x + nonVerticalSlope.yIntercept; + return [x, y]; + } + /** + * 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 fromSlopeIntersection(line1, line2, options) { + if (options === void 0) { options = {}; } + var slope1 = MakerJs.measure.lineSlope(line1); + var slope2 = MakerJs.measure.lineSlope(line2); + if (MakerJs.measure.isSlopeEqual(slope1, slope2)) { + //check for overlap + options.out_AreOverlapped = MakerJs.measure.isLineOverlapping(line1, line2, options.excludeTangents); + return null; + } + var pointOfIntersection; + if (!slope1.hasSlope) { + pointOfIntersection = verticalIntersectionPoint(line1, slope2); + } + else if (!slope2.hasSlope) { + pointOfIntersection = verticalIntersectionPoint(line2, slope1); + } + else { + // find intersection by line equation + var x = (slope2.yIntercept - slope1.yIntercept) / (slope1.slope - slope2.slope); + var y = slope1.slope * x + slope1.yIntercept; + pointOfIntersection = [x, y]; + } + return pointOfIntersection; + } + point.fromSlopeIntersection = fromSlopeIntersection; /** * Get the middle point of a path. * @@ -756,38 +763,6 @@ var MakerJs; (function (MakerJs) { var path; (function (path) { - /** - * @private - */ - var pathAreEqualMap = {}; - pathAreEqualMap[MakerJs.pathType.Line] = function (line1, line2, withinPointDistance) { - return (MakerJs.point.areEqual(line1.origin, line2.origin, withinPointDistance) && MakerJs.point.areEqual(line1.end, line2.end, withinPointDistance)) - || (MakerJs.point.areEqual(line1.origin, line2.end, withinPointDistance) && MakerJs.point.areEqual(line1.end, line2.origin, withinPointDistance)); - }; - pathAreEqualMap[MakerJs.pathType.Circle] = function (circle1, circle2, withinPointDistance) { - return MakerJs.point.areEqual(circle1.origin, circle2.origin, withinPointDistance) && circle1.radius == circle2.radius; - }; - pathAreEqualMap[MakerJs.pathType.Arc] = function (arc1, arc2, withinPointDistance) { - return pathAreEqualMap[MakerJs.pathType.Circle](arc1, arc2, withinPointDistance) && MakerJs.angle.areEqual(arc1.startAngle, arc2.startAngle) && MakerJs.angle.areEqual(arc1.endAngle, arc2.endAngle); - }; - /** - * Find out if two paths are equal. - * - * @param a First path. - * @param b Second path. - * @returns true if paths are the same, false if they are not - */ - function areEqual(path1, path2, withinPointDistance) { - var result = false; - if (path1.type == path2.type) { - var fn = pathAreEqualMap[path1.type]; - if (fn) { - result = fn(path1, path2, withinPointDistance); - } - } - return result; - } - path.areEqual = areEqual; /** * Create a clone of a path, mirrored on either or both x and y axes. * @@ -932,7 +907,7 @@ var MakerJs; var breakPathFunctionMap = {}; breakPathFunctionMap[MakerJs.pathType.Arc] = function (arc, pointOfBreak) { var angleAtBreakPoint = MakerJs.angle.ofPointInDegrees(arc.origin, pointOfBreak); - if (MakerJs.angle.areEqual(angleAtBreakPoint, arc.startAngle) || MakerJs.angle.areEqual(angleAtBreakPoint, arc.endAngle)) { + if (MakerJs.measure.isAngleEqual(angleAtBreakPoint, arc.startAngle) || MakerJs.measure.isAngleEqual(angleAtBreakPoint, arc.endAngle)) { return null; } function getAngleStrictlyBetweenArcAngles() { @@ -964,7 +939,7 @@ var MakerJs; return null; }; breakPathFunctionMap[MakerJs.pathType.Line] = function (line, pointOfBreak) { - if (MakerJs.point.areEqual(line.origin, pointOfBreak) || MakerJs.point.areEqual(line.end, pointOfBreak)) { + if (MakerJs.measure.isPointEqual(line.origin, pointOfBreak) || MakerJs.measure.isPointEqual(line.end, pointOfBreak)) { return null; } if (!MakerJs.measure.isBetweenPoints(pointOfBreak, line, true)) { @@ -1085,7 +1060,7 @@ var MakerJs; this.type = MakerJs.pathType.Arc; } return Arc; - })(); + }()); paths.Arc = Arc; /** * Class for circle path. @@ -1122,13 +1097,13 @@ var MakerJs; perpendiculars.push(MakerJs.path.rotate(lines[i], 90, midpoint)); } //find intersection of slopes of perpendiculars - this.origin = MakerJs.path.slopeIntersectionPoint(perpendiculars[0], perpendiculars[1]); + this.origin = MakerJs.point.fromSlopeIntersection(perpendiculars[0], perpendiculars[1]); //radius is distance to any of the 3 points this.radius = MakerJs.measure.pointDistance(this.origin, args[0]); } } return Circle; - })(); + }()); paths.Circle = Circle; /** * Class for line path. @@ -1143,7 +1118,7 @@ var MakerJs; this.type = MakerJs.pathType.Line; } return Line; - })(); + }()); paths.Line = Line; /** * Class for chord, which is simply a line path that connects the endpoints of an arc. @@ -1158,7 +1133,7 @@ var MakerJs; this.end = arcPoints[1]; } return Chord; - })(); + }()); paths.Chord = Chord; /** * Class for a parallel line path. @@ -1185,7 +1160,7 @@ var MakerJs; MakerJs.path.move(this, newOrigin); } return Parallel; - })(); + }()); paths.Parallel = Parallel; })(paths = MakerJs.paths || (MakerJs.paths = {})); })(MakerJs || (MakerJs = {})); @@ -1472,7 +1447,7 @@ var MakerJs; * @private */ function breakAlongForeignPath(segments, overlappedSegments, foreignPath) { - if (MakerJs.path.areEqual(segments[0].path, foreignPath, .0001)) { + if (MakerJs.measure.isPathEqual(segments[0].path, foreignPath, .0001)) { segments[0].overlapped = true; segments[0].duplicate = true; overlappedSegments.push(segments[0]); @@ -1529,7 +1504,7 @@ var MakerJs; var added = 0; function addUniquePoint(pointToAdd) { for (var i = 0; i < pointArray.length; i++) { - if (MakerJs.point.areEqual(pointArray[i], pointToAdd, .000000001)) { + if (MakerJs.measure.isPointEqual(pointArray[i], pointToAdd, .000000001)) { return; } } @@ -1637,7 +1612,7 @@ var MakerJs; */ function checkForEqualOverlaps(crossedPathsA, crossedPathsB, pointMatchingDistance) { function compareSegments(segment1, segment2) { - if (MakerJs.path.areEqual(segment1.path, segment2.path, pointMatchingDistance)) { + if (MakerJs.measure.isPathEqual(segment1.path, segment2.path, pointMatchingDistance)) { segment1.duplicate = segment2.duplicate = true; } } @@ -1774,7 +1749,7 @@ var MakerJs; } }; return Collector; - })(); + }()); MakerJs.Collector = Collector; })(MakerJs || (MakerJs = {})); var MakerJs; @@ -1811,7 +1786,7 @@ var MakerJs; var startAngle = MakerJs.angle.noRevolutions(arc.startAngle); return { startAngle: startAngle, - endAngle: MakerJs.measure.arcAngle(arc) + startAngle + endAngle: MakerJs.angle.ofArcSpan(arc) + startAngle }; } /** @@ -1840,7 +1815,7 @@ var MakerJs; similarCircles.addItemToCollection(circleRef.pathContext, circleRef); }; map[MakerJs.pathType.Line] = function (lineRef) { - var slope = MakerJs.path.getSlope(lineRef.pathContext); + var slope = MakerJs.measure.lineSlope(lineRef.pathContext); similarLines.addItemToCollection(slope, lineRef); }; var opts = { @@ -1955,7 +1930,7 @@ var MakerJs; * @returns Model of straight lines with same endpoints as the arc. */ function straighten(arc, bevel) { - var arcSpan = MakerJs.measure.arcAngle(arc); + var arcSpan = MakerJs.angle.ofArcSpan(arc); var joints = 1; if (arcSpan >= 270) { joints = 4; @@ -2121,18 +2096,96 @@ var MakerJs; var MakerJs; (function (MakerJs) { var measure; - (function (measure_1) { + (function (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 a First angle. + * @param b Second angle. + * @returns true if angles are the same, false if they are not */ - function arcAngle(arc) { - var endAngle = MakerJs.angle.ofArcEnd(arc); - return endAngle - arc.startAngle; + function isAngleEqual(angle1, angle2, accuracy) { + if (accuracy === void 0) { accuracy = .0001; } + var a1 = MakerJs.angle.noRevolutions(angle1); + var a2 = MakerJs.angle.noRevolutions(angle2); + var d = MakerJs.angle.noRevolutions(MakerJs.round(a2 - a1, accuracy)); + return d == 0; } - measure_1.arcAngle = arcAngle; + measure.isAngleEqual = isAngleEqual; + /** + * @private + */ + var pathAreEqualMap = {}; + pathAreEqualMap[MakerJs.pathType.Line] = function (line1, line2, withinPointDistance) { + return (isPointEqual(line1.origin, line2.origin, withinPointDistance) && isPointEqual(line1.end, line2.end, withinPointDistance)) + || (isPointEqual(line1.origin, line2.end, withinPointDistance) && isPointEqual(line1.end, line2.origin, withinPointDistance)); + }; + pathAreEqualMap[MakerJs.pathType.Circle] = function (circle1, circle2, withinPointDistance) { + return isPointEqual(circle1.origin, circle2.origin, withinPointDistance) && circle1.radius == circle2.radius; + }; + pathAreEqualMap[MakerJs.pathType.Arc] = function (arc1, arc2, withinPointDistance) { + return pathAreEqualMap[MakerJs.pathType.Circle](arc1, arc2, withinPointDistance) && isAngleEqual(arc1.startAngle, arc2.startAngle) && isAngleEqual(arc1.endAngle, arc2.endAngle); + }; + /** + * Find out if two paths are equal. + * + * @param a First path. + * @param b Second path. + * @returns true if paths are the same, false if they are not + */ + function isPathEqual(path1, path2, withinPointDistance) { + var result = false; + if (path1.type == path2.type) { + var fn = pathAreEqualMap[path1.type]; + if (fn) { + result = fn(path1, path2, withinPointDistance); + } + } + return result; + } + measure.isPathEqual = isPathEqual; + /** + * 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, b, withinDistance) { + if (!withinDistance) { + return a[0] == b[0] && a[1] == b[1]; + } + else { + var distance = measure.pointDistance(a, b); + return distance <= withinDistance; + } + } + measure.isPointEqual = isPointEqual; + /** + * Check for slope equality. + * + * @param slope1 The ISlope to test. + * @param slope2 The ISlope to check for equality. + * @returns Boolean true if slopes are equal. + */ + function isSlopeEqual(slope1, slope2) { + if (!slope1.hasSlope && !slope2.hasSlope) { + //lines are both vertical, see if x are the same + return MakerJs.round(slope1.line.origin[0] - slope2.line.origin[0]) == 0; + } + if (slope1.hasSlope && slope2.hasSlope && (MakerJs.round(slope1.slope - slope2.slope, .00001) == 0)) { + //lines are parallel, but not vertical, see if y-intercept is the same + return MakerJs.round(slope1.yIntercept - slope2.yIntercept, .00001) == 0; + } + return false; + } + measure.isSlopeEqual = isSlopeEqual; + })(measure = MakerJs.measure || (MakerJs.measure = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var measure; + (function (measure_1) { /** * Check for arc being concave or convex towards a given point. * @@ -2200,7 +2253,7 @@ var MakerJs; */ function isBetweenArcAngles(angleInQuestion, arc, exclusive) { var startAngle = MakerJs.angle.noRevolutions(arc.startAngle); - var span = arcAngle(arc); + var span = MakerJs.angle.ofArcSpan(arc); var endAngle = startAngle + span; angleInQuestion = MakerJs.angle.noRevolutions(angleInQuestion); //computed angles will not be negative, but the arc may have specified a negative angle, so check against one revolution forward and backward @@ -2248,24 +2301,27 @@ var MakerJs; } measure_1.isLineOverlapping = isLineOverlapping; /** - * Check for slope equality. - * - * @param slope1 The ISlope to test. - * @param slope2 The ISlope to check for equality. - * @returns Boolean true if slopes are equal. + * Gets the slope of a line. */ - function isSlopeEqual(slope1, slope2) { - if (!slope1.hasSlope && !slope2.hasSlope) { - //lines are both vertical, see if x are the same - return MakerJs.round(slope1.line.origin[0] - slope2.line.origin[0]) == 0; - } - if (slope1.hasSlope && slope2.hasSlope && (MakerJs.round(slope1.slope - slope2.slope, .00001) == 0)) { - //lines are parallel, but not vertical, see if y-intercept is the same - return MakerJs.round(slope1.yIntercept - slope2.yIntercept, .00001) == 0; + function lineSlope(line) { + var dx = line.end[0] - line.origin[0]; + if (MakerJs.round(dx) == 0) { + return { + line: line, + hasSlope: false + }; } - return false; + var dy = line.end[1] - line.origin[1]; + var slope = dy / dx; + var yIntercept = line.origin[1] - slope * line.origin[0]; + return { + line: line, + hasSlope: true, + slope: slope, + yIntercept: yIntercept + }; } - measure_1.isSlopeEqual = isSlopeEqual; + measure_1.lineSlope = lineSlope; /** * Calculates the distance between two points. * @@ -2347,7 +2403,7 @@ var MakerJs; }; map[MakerJs.pathType.Arc] = function (arc) { map[MakerJs.pathType.Circle](arc); //this sets the value var - var pct = arcAngle(arc) / 360; + var pct = MakerJs.angle.ofArcSpan(arc) / 360; value *= pct; }; var fn = map[pathToMeasure.type]; @@ -2493,7 +2549,7 @@ var MakerJs; } }; return Exporter; - })(); + }()); exporter.Exporter = Exporter; })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); })(MakerJs || (MakerJs = {})); @@ -2771,7 +2827,7 @@ var MakerJs; return null; }; map[MakerJs.pathType.Line][MakerJs.pathType.Line] = function (line1, line2, options) { - var intersectionPoint = slopeIntersectionPoint(line1, line2, options); + var intersectionPoint = MakerJs.point.fromSlopeIntersection(line1, line2, options); if (intersectionPoint) { //we have the point of intersection of endless lines, now check to see if the point is between both segemnts if (MakerJs.measure.isBetweenPoints(intersectionPoint, line1, options.excludeTangents) && MakerJs.measure.isBetweenPoints(intersectionPoint, line2, options.excludeTangents)) { @@ -2850,69 +2906,6 @@ var MakerJs; return null; return anglesWithinArc; } - /** - * Gets the slope of a line. - */ - function getSlope(line) { - var dx = line.end[0] - line.origin[0]; - if (MakerJs.round(dx) == 0) { - return { - line: line, - hasSlope: false - }; - } - var dy = line.end[1] - line.origin[1]; - var slope = dy / dx; - var yIntercept = line.origin[1] - slope * line.origin[0]; - return { - line: line, - hasSlope: true, - slope: slope, - yIntercept: yIntercept - }; - } - path.getSlope = getSlope; - /** - * @private - */ - function verticalIntersectionPoint(verticalLine, nonVerticalSlope) { - var x = verticalLine.origin[0]; - var y = nonVerticalSlope.slope * x + nonVerticalSlope.yIntercept; - return [x, y]; - } - /** - * 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, line2, options) { - if (options === void 0) { options = {}; } - var slope1 = getSlope(line1); - var slope2 = getSlope(line2); - if (MakerJs.measure.isSlopeEqual(slope1, slope2)) { - //check for overlap - options.out_AreOverlapped = MakerJs.measure.isLineOverlapping(line1, line2, options.excludeTangents); - return null; - } - var pointOfIntersection; - if (!slope1.hasSlope) { - pointOfIntersection = verticalIntersectionPoint(line1, slope2); - } - else if (!slope2.hasSlope) { - pointOfIntersection = verticalIntersectionPoint(line2, slope1); - } - else { - // find intersection by line equation - var x = (slope2.yIntercept - slope1.yIntercept) / (slope1.slope - slope2.slope); - var y = slope1.slope * x + slope1.yIntercept; - pointOfIntersection = [x, y]; - } - return pointOfIntersection; - } - path.slopeIntersectionPoint = slopeIntersectionPoint; /** * @private */ @@ -2970,7 +2963,7 @@ var MakerJs; */ function circleToCircle(circle1, circle2, options) { //see if circles are the same - if (circle1.radius == circle2.radius && MakerJs.point.areEqual(circle1.origin, circle2.origin, .0001)) { + if (circle1.radius == circle2.radius && MakerJs.measure.isPointEqual(circle1.origin, circle2.origin, .0001)) { options.out_AreOverlapped = true; return null; } @@ -3070,7 +3063,7 @@ var MakerJs; }; } function check(i1, i2) { - if (MakerJs.point.areEqual(path1Properties[i1].point, path2Properties[i2].point, .0001)) { + if (MakerJs.measure.isPointEqual(path1Properties[i1].point, path2Properties[i2].point, .0001)) { result = [ makeMatch(path1, path1Properties, i1), makeMatch(path2, path2Properties, i2) @@ -3094,7 +3087,7 @@ var MakerJs; return false; } properties[i].shardPoint = circleIntersection.intersectionPoints[0]; - if (MakerJs.point.areEqual(properties[i].point, circleIntersection.intersectionPoints[0], .0001)) { + if (MakerJs.measure.isPointEqual(properties[i].point, circleIntersection.intersectionPoints[0], .0001)) { if (circleIntersection.intersectionPoints.length > 1) { properties[i].shardPoint = circleIntersection.intersectionPoints[1]; } @@ -3171,7 +3164,7 @@ var MakerJs; path.rotate(guideLine, lineAngle, [0, 0]); path.moveRelative(guideLine, filletCenter); //get the intersection point of the slopes of the context line and the perpendicular line. This is where the fillet meets the line. - var intersectionPoint = path.slopeIntersectionPoint(line, guideLine); + var intersectionPoint = MakerJs.point.fromSlopeIntersection(line, guideLine); if (intersectionPoint) { result = { filletAngle: MakerJs.angle.ofPointInDegrees(filletCenter, intersectionPoint), @@ -3342,7 +3335,7 @@ var MakerJs; if (MakerJs.round(results[0].filletAngle - results[1].filletAngle) == 0) return null; var filletArc = new MakerJs.paths.Arc(center, filletRadius, results[0].filletAngle, results[1].filletAngle); - var filletSpan = MakerJs.measure.arcAngle(filletArc); + var filletSpan = MakerJs.angle.ofArcSpan(filletArc); //the algorithm is only valid for fillet less than 180 degrees if (filletSpan == 180) { return null; @@ -3655,7 +3648,7 @@ var MakerJs; return found; }; return DeadEndFinder; - })(); + }()); /** * Remove paths from a model which have endpoints that do not connect to other paths. * @@ -3772,7 +3765,7 @@ var MakerJs; } }; return XmlTag; - })(); + }()); exporter.XmlTag = XmlTag; })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); })(MakerJs || (MakerJs = {})); @@ -4114,7 +4107,7 @@ var MakerJs; } map[MakerJs.pathType.Arc] = function (id, arc, origin, layer) { var arcPoints = MakerJs.point.fromArc(arc); - if (MakerJs.point.areEqual(arcPoints[0], arcPoints[1])) { + if (MakerJs.measure.isPointEqual(arcPoints[0], arcPoints[1])) { circleInPaths(id, arc.origin, arc.radius, layer); } else { @@ -4239,7 +4232,7 @@ var MakerJs; } } return ConnectTheDots; - })(); + }()); models.ConnectTheDots = ConnectTheDots; ConnectTheDots.metaParameters = [ { title: "closed", type: "bool", value: true }, @@ -4279,7 +4272,7 @@ var MakerJs; return points; }; return Polygon; - })(); + }()); models.Polygon = Polygon; Polygon.metaParameters = [ { title: "number of sides", type: "range", min: 3, max: 24, value: 6 }, @@ -4302,7 +4295,7 @@ var MakerJs; } } return BoltCircle; - })(); + }()); models.BoltCircle = BoltCircle; BoltCircle.metaParameters = [ { title: "bolt circle radius", type: "range", min: 1, max: 100, value: 50 }, @@ -4330,7 +4323,7 @@ var MakerJs; } } return BoltRectangle; - })(); + }()); models.BoltRectangle = BoltRectangle; BoltRectangle.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 100 }, @@ -4369,7 +4362,7 @@ var MakerJs; } } return Dome; - })(); + }()); models.Dome = Dome; Dome.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4405,7 +4398,7 @@ var MakerJs; } } return RoundRectangle; - })(); + }()); models.RoundRectangle = RoundRectangle; RoundRectangle.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4424,7 +4417,7 @@ var MakerJs; this.paths = new models.RoundRectangle(width, height, Math.min(height / 2, width / 2)).paths; } return Oval; - })(); + }()); models.Oval = Oval; Oval.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4487,7 +4480,7 @@ var MakerJs; } } return OvalArc; - })(); + }()); models.OvalArc = OvalArc; OvalArc.metaParameters = [ { title: "start angle", type: "range", min: -360, max: 360, step: 1, value: 180 }, @@ -4508,7 +4501,7 @@ var MakerJs; this.paths = new models.ConnectTheDots(true, [[0, 0], [width, 0], [width, height], [0, height]]).paths; } return Rectangle; - })(); + }()); models.Rectangle = Rectangle; Rectangle.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4532,7 +4525,7 @@ var MakerJs; } } return Ring; - })(); + }()); models.Ring = Ring; Ring.metaParameters = [ { title: "outer radius", type: "range", min: 0, max: 100, step: 1, value: 50 }, @@ -4573,7 +4566,7 @@ var MakerJs; this.paths['curve_end'] = MakerJs.path.moveRelative(MakerJs.path.mirror(curve, true, true), [width, height]); } return SCurve; - })(); + }()); models.SCurve = SCurve; SCurve.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4604,7 +4597,7 @@ var MakerJs; this.origin = origin; } return Slot; - })(); + }()); models.Slot = Slot; Slot.metaParameters = [ { @@ -4635,7 +4628,7 @@ var MakerJs; this.paths = new models.Rectangle(side, side).paths; } return Square; - })(); + }()); models.Square = Square; Square.metaParameters = [ { title: "side", type: "range", min: 1, max: 100, value: 100 } @@ -4673,7 +4666,7 @@ var MakerJs; return 0; }; return Star; - })(); + }()); models.Star = Star; Star.metaParameters = [ { title: "number of sides", type: "range", min: 3, max: 24, value: 8 }, diff --git a/archive/browser.0.7.1.maker.js b/archive/browser.0.7.1.maker.js new file mode 100644 index 000000000..c0aa514c7 --- /dev/null +++ b/archive/browser.0.7.1.maker.js @@ -0,0 +1,4705 @@ +require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o spans[0].size) { + spans.push(span); + } + else { + spans.unshift(span); + } + } + var index = largeArc ? 1 : 0; + span = spans[index]; + this.origin = span.origin; + this.startAngle = span.startAngle; + this.endAngle = span.endAngle; + } + break; + case 4: + this.origin = args[0]; + this.radius = args[1]; + this.startAngle = args[2]; + this.endAngle = args[3]; + break; + case 3: + if (MakerJs.isPoint(args[2])) { + //from 3 points + Circle.apply(this, args); + var angles = []; + for (var i = 0; i < 3; i++) { + angles.push(MakerJs.angle.ofPointInDegrees(this.origin, args[i])); + } + this.startAngle = angles[0]; + this.endAngle = angles[2]; + //swap start and end angles if this arc does not contain the midpoint + if (!MakerJs.measure.isBetweenArcAngles(angles[1], this, false)) { + this.startAngle = angles[2]; + this.endAngle = angles[0]; + } + //do not fall through if this was 3 points + break; + } + //fall through to below if 2 points + case 2: + //from 2 points (and optional clockwise flag) + var clockwise = args[2]; + Circle.call(this, args[0], args[1]); + this.startAngle = MakerJs.angle.ofPointInDegrees(this.origin, args[clockwise ? 1 : 0]); + this.endAngle = MakerJs.angle.ofPointInDegrees(this.origin, args[clockwise ? 0 : 1]); + break; + } + //do this after Circle.apply / Circle.call to make sure this is an arc + this.type = MakerJs.pathType.Arc; + } + return Arc; + }()); + paths.Arc = Arc; + /** + * Class for circle path. + */ + var Circle = (function () { + function Circle() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i - 0] = arguments[_i]; + } + this.type = MakerJs.pathType.Circle; + if (args.length == 2) { + if (typeof args[1] === 'number') { + this.origin = args[0]; + this.radius = args[1]; + } + else { + //Circle from 2 points + this.origin = MakerJs.point.average(args[0], args[1]); + this.radius = MakerJs.measure.pointDistance(this.origin, args[0]); + } + } + else { + //Circle from 3 points + //create 2 lines with 2nd point in common + var lines = [ + new Line(args[0], args[1]), + new Line(args[1], args[2]) + ]; + //create perpendicular lines + var perpendiculars = []; + for (var i = 2; i--;) { + var midpoint = MakerJs.point.middle(lines[i]); + perpendiculars.push(MakerJs.path.rotate(lines[i], 90, midpoint)); + } + //find intersection of slopes of perpendiculars + this.origin = MakerJs.point.fromSlopeIntersection(perpendiculars[0], perpendiculars[1]); + //radius is distance to any of the 3 points + this.radius = MakerJs.measure.pointDistance(this.origin, args[0]); + } + } + return Circle; + }()); + paths.Circle = Circle; + /** + * Class for line path. + * + * @param origin The origin point of the line. + * @param end The end point of the line. + */ + var Line = (function () { + function Line(origin, end) { + this.origin = origin; + this.end = end; + this.type = MakerJs.pathType.Line; + } + return Line; + }()); + paths.Line = Line; + /** + * Class for chord, which is simply a line path that connects the endpoints of an arc. + * + * @param arc Arc to use as the basic for the chord. + */ + var Chord = (function () { + function Chord(arc) { + var arcPoints = MakerJs.point.fromArc(arc); + this.type = MakerJs.pathType.Line; + this.origin = arcPoints[0]; + this.end = arcPoints[1]; + } + return Chord; + }()); + paths.Chord = Chord; + /** + * Class for a parallel line path. + * + * @param toLine A line to be parallel to. + * @param distance Distance between parallel and original line. + * @param nearPoint Any point to determine which side of the line to place the parallel. + */ + var Parallel = (function () { + function Parallel(toLine, distance, nearPoint) { + this.type = MakerJs.pathType.Line; + this.origin = MakerJs.point.clone(toLine.origin); + this.end = MakerJs.point.clone(toLine.end); + var angleOfLine = MakerJs.angle.ofLineInDegrees(this); + function getNewOrigin(offsetAngle) { + var origin = MakerJs.point.add(toLine.origin, MakerJs.point.fromPolar(MakerJs.angle.toRadians(angleOfLine + offsetAngle), distance)); + return { + origin: origin, + nearness: MakerJs.measure.pointDistance(origin, nearPoint) + }; + } + var newOrigins = [getNewOrigin(-90), getNewOrigin(90)]; + var newOrigin = (newOrigins[0].nearness < newOrigins[1].nearness) ? newOrigins[0].origin : newOrigins[1].origin; + MakerJs.path.move(this, newOrigin); + } + return Parallel; + }()); + paths.Parallel = Parallel; + })(paths = MakerJs.paths || (MakerJs.paths = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var model; + (function (model) { + /** + * Count the number of child models within a given model. + * + * @param modelContext The model containing other models. + * @returns Number of child models. + */ + function countChildModels(modelContext) { + var count = 0; + if (modelContext.models) { + for (var id in modelContext.models) { + count++; + } + } + return count; + } + model.countChildModels = countChildModels; + /** + * Get an unused id in the models map with the same prefix. + * + * @param modelContext The model containing the models map. + * @param modelId The id to use directly (if unused), or as a prefix. + */ + function getSimilarModelId(modelContext, modelId) { + if (!modelContext.models) + return modelId; + var i = 0; + var newModelId = modelId; + while (newModelId in modelContext.models) { + i++; + newModelId = modelId + '_' + i; + } + return newModelId; + } + model.getSimilarModelId = getSimilarModelId; + /** + * Get an unused id in the paths map with the same prefix. + * + * @param modelContext The model containing the paths map. + * @param pathId The id to use directly (if unused), or as a prefix. + */ + function getSimilarPathId(modelContext, pathId) { + if (!modelContext.paths) + return pathId; + var i = 0; + var newPathId = pathId; + while (newPathId in modelContext.paths) { + i++; + newPathId = pathId + '_' + i; + } + return newPathId; + } + model.getSimilarPathId = getSimilarPathId; + /** + * Moves all of a model's children (models and paths, recursively) in reference to a single common origin. Useful when points between children need to connect to each other. + * + * @param modelToOriginate The model to originate. + * @param origin Optional offset reference point. + */ + function originate(modelToOriginate, origin) { + if (!modelToOriginate) + return; + var newOrigin = MakerJs.point.add(modelToOriginate.origin, origin); + if (modelToOriginate.paths) { + for (var id in modelToOriginate.paths) { + MakerJs.path.moveRelative(modelToOriginate.paths[id], newOrigin); + } + } + if (modelToOriginate.models) { + for (var id in modelToOriginate.models) { + originate(modelToOriginate.models[id], newOrigin); + } + } + modelToOriginate.origin = MakerJs.point.zero(); + return modelToOriginate; + } + model.originate = originate; + /** + * Create a clone of a model, mirrored on either or both x and y axes. + * + * @param modelToMirror The model to mirror. + * @param mirrorX Boolean to mirror on the x axis. + * @param mirrorY Boolean to mirror on the y axis. + * @returns Mirrored model. + */ + function mirror(modelToMirror, mirrorX, mirrorY) { + var newModel = {}; + if (modelToMirror.origin) { + newModel.origin = MakerJs.point.mirror(modelToMirror.origin, mirrorX, mirrorY); + } + if (modelToMirror.type) { + newModel.type = modelToMirror.type; + } + if (modelToMirror.units) { + newModel.units = modelToMirror.units; + } + if (modelToMirror.paths) { + newModel.paths = {}; + for (var id in modelToMirror.paths) { + var pathToMirror = modelToMirror.paths[id]; + if (!pathToMirror) + continue; + var pathMirrored = MakerJs.path.mirror(pathToMirror, mirrorX, mirrorY); + if (!pathMirrored) + continue; + newModel.paths[id] = pathMirrored; + } + } + if (modelToMirror.models) { + newModel.models = {}; + for (var id in modelToMirror.models) { + var childModelToMirror = modelToMirror.models[id]; + if (!childModelToMirror) + continue; + var childModelMirrored = model.mirror(childModelToMirror, mirrorX, mirrorY); + if (!childModelMirrored) + continue; + newModel.models[id] = childModelMirrored; + } + } + return newModel; + } + model.mirror = mirror; + /** + * Move a model to an absolute point. Note that this is also accomplished by directly setting the origin property. This function exists for chaining. + * + * @param modelToMove The model to move. + * @param origin The new position of the model. + * @returns The original model (for chaining). + */ + function move(modelToMove, origin) { + modelToMove.origin = MakerJs.point.clone(origin); + return modelToMove; + } + model.move = move; + /** + * Move a model's origin by a relative amount. + * + * @param modelToMove The model to move. + * @param delta The x & y adjustments as a point object. + * @returns The original model (for chaining). + */ + function moveRelative(modelToMove, delta) { + if (modelToMove) { + modelToMove.origin = MakerJs.point.add(modelToMove.origin || MakerJs.point.zero(), delta); + } + return modelToMove; + } + model.moveRelative = moveRelative; + /** + * Rotate a model. + * + * @param modelToRotate The model to rotate. + * @param angleInDegrees The amount of rotation, in degrees. + * @param rotationOrigin The center point of rotation. + * @returns The original model (for chaining). + */ + function rotate(modelToRotate, angleInDegrees, rotationOrigin) { + if (modelToRotate) { + var offsetOrigin = MakerJs.point.subtract(rotationOrigin, modelToRotate.origin); + if (modelToRotate.paths) { + for (var id in modelToRotate.paths) { + MakerJs.path.rotate(modelToRotate.paths[id], angleInDegrees, offsetOrigin); + } + } + if (modelToRotate.models) { + for (var id in modelToRotate.models) { + rotate(modelToRotate.models[id], angleInDegrees, offsetOrigin); + } + } + } + return modelToRotate; + } + model.rotate = rotate; + /** + * Scale a model. + * + * @param modelToScale The model to scale. + * @param scaleValue The amount of scaling. + * @param scaleOrigin Optional boolean to scale the origin point. Typically false for the root model. + * @returns The original model (for chaining). + */ + function scale(modelToScale, scaleValue, scaleOrigin) { + if (scaleOrigin === void 0) { scaleOrigin = false; } + if (scaleOrigin && modelToScale.origin) { + modelToScale.origin = MakerJs.point.scale(modelToScale.origin, scaleValue); + } + if (modelToScale.paths) { + for (var id in modelToScale.paths) { + MakerJs.path.scale(modelToScale.paths[id], scaleValue); + } + } + if (modelToScale.models) { + for (var id in modelToScale.models) { + scale(modelToScale.models[id], scaleValue, true); + } + } + return modelToScale; + } + model.scale = scale; + /** + * Convert a model to match a different unit system. + * + * @param modeltoConvert The model to convert. + * @param destUnitType The unit system. + * @returns The scaled model (for chaining). + */ + function convertUnits(modeltoConvert, destUnitType) { + var validUnitType = false; + for (var id in MakerJs.unitType) { + if (MakerJs.unitType[id] == destUnitType) { + validUnitType = true; + break; + } + } + if (modeltoConvert.units && validUnitType) { + var ratio = MakerJs.units.conversionScale(modeltoConvert.units, destUnitType); + if (ratio != 1) { + scale(modeltoConvert, ratio); + //update the model with its new unit type + modeltoConvert.units = destUnitType; + } + } + return modeltoConvert; + } + model.convertUnits = convertUnits; + /** + * Recursively walk through all paths for a given model. + * + * @param modelContext The model to walk. + * @param callback Callback for each path. + */ + function walkPaths(modelContext, callback) { + if (modelContext.paths) { + for (var pathId in modelContext.paths) { + if (!modelContext.paths[pathId]) + continue; + callback(modelContext, pathId, modelContext.paths[pathId]); + } + } + if (modelContext.models) { + for (var id in modelContext.models) { + if (!modelContext.models[id]) + continue; + walkPaths(modelContext.models[id], callback); + } + } + } + model.walkPaths = walkPaths; + })(model = MakerJs.model || (MakerJs.model = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var model; + (function (model) { + /** + * @private + */ + function getNonZeroSegments(pathToSegment, breakPoint) { + var segmentType = pathToSegment.type; + var segment1 = MakerJs.cloneObject(pathToSegment); + var segment2 = MakerJs.path.breakAtPoint(segment1, breakPoint); + if (segment2) { + var segments = [segment1, segment2]; + for (var i = 2; i--;) { + if (MakerJs.round(MakerJs.measure.pathLength(segments[i]), .0001) == 0) { + return null; + } + } + return segments; + } + else if (segmentType == MakerJs.pathType.Circle) { + return [segment1]; + } + return null; + } + /** + * @private + */ + function breakAlongForeignPath(segments, overlappedSegments, foreignPath) { + if (MakerJs.measure.isPathEqual(segments[0].path, foreignPath, .0001)) { + segments[0].overlapped = true; + segments[0].duplicate = true; + overlappedSegments.push(segments[0]); + return; + } + var foreignPathEndPoints; + for (var i = 0; i < segments.length; i++) { + var pointsToCheck; + var options = {}; + var foreignIntersection = MakerJs.path.intersection(segments[i].path, foreignPath, options); + if (foreignIntersection) { + pointsToCheck = foreignIntersection.intersectionPoints; + } + else if (options.out_AreOverlapped) { + segments[i].overlapped = true; + overlappedSegments.push(segments[i]); + if (!foreignPathEndPoints) { + foreignPathEndPoints = MakerJs.point.fromPathEnds(foreignPath); + } + pointsToCheck = foreignPathEndPoints; + } + if (pointsToCheck) { + //break the path which intersected, and add the shard to the end of the array so it can also be checked in this loop for further sharding. + var subSegments = null; + var p = 0; + while (!subSegments && p < pointsToCheck.length) { + subSegments = getNonZeroSegments(segments[i].path, pointsToCheck[p]); + p++; + } + if (subSegments) { + segments[i].path = subSegments[0]; + if (subSegments[1]) { + var newSegment = { + path: subSegments[1], + pathId: segments[0].pathId, + overlapped: segments[i].overlapped, + uniqueForeignIntersectionPoints: [] + }; + if (segments[i].overlapped) { + overlappedSegments.push(newSegment); + } + segments.push(newSegment); + } + //re-check this segment for another deep intersection + i--; + } + } + } + } + /** + * @private + */ + function addUniquePoints(pointArray, pointsToAdd) { + var added = 0; + function addUniquePoint(pointToAdd) { + for (var i = 0; i < pointArray.length; i++) { + if (MakerJs.measure.isPointEqual(pointArray[i], pointToAdd, .000000001)) { + return; + } + } + pointArray.push(pointToAdd); + added++; + } + for (var i = 0; i < pointsToAdd.length; i++) { + addUniquePoint(pointsToAdd[i]); + } + return added; + } + /** + * @private + */ + function checkIntersectsForeignPath(segment, foreignPath, foreignPathId, farPoint) { + if (farPoint === void 0) { farPoint = [7654321, 1234567]; } + var origin = MakerJs.point.middle(segment.path); + var lineToFarPoint = new MakerJs.paths.Line(origin, farPoint); + var farInt = MakerJs.path.intersection(lineToFarPoint, foreignPath); + if (farInt) { + var added = addUniquePoints(segment.uniqueForeignIntersectionPoints, farInt.intersectionPoints); + //if number of intersections is an odd number, flip the flag. + if (added % 2 == 1) { + segment.isInside = !!!segment.isInside; + } + } + } + /** + * @private + */ + function checkInsideForeignModel(segment, modelToIntersect, farPoint) { + model.walkPaths(modelToIntersect, function (mx, pathId2, path2) { + if (path2) { + checkIntersectsForeignPath(segment, path2, pathId2, farPoint); + } + }); + } + /** + * Check to see if a path is inside of a model. + * + * @param pathContext The path to check. + * @param modelContext The model to check against. + * @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, modelContext, farPoint) { + var segment = { + path: pathContext, + isInside: false, + uniqueForeignIntersectionPoints: [] + }; + checkInsideForeignModel(segment, modelContext, farPoint); + return !!segment.isInside; + } + model.isPathInsideModel = isPathInsideModel; + /** + * Break a model's paths everywhere they intersect with another path. + * + * @param modelToBreak The model containing paths to be broken. + * @param modelToIntersect Optional model containing paths to look for intersection, or else the modelToBreak will be used. + */ + function breakPathsAtIntersections(modelToBreak, modelToIntersect) { + breakAllPathsAtIntersections(modelToBreak, modelToIntersect || modelToBreak, false); + } + model.breakPathsAtIntersections = breakPathsAtIntersections; + /** + * @private + */ + function breakAllPathsAtIntersections(modelToBreak, modelToIntersect, checkIsInside, farPoint) { + var crossedPaths = []; + var overlappedSegments = []; + model.walkPaths(modelToBreak, function (modelContext, pathId1, path1) { + if (!path1) + return; + //clone this path and make it the first segment + var segment = { + path: MakerJs.cloneObject(path1), + pathId: pathId1, + overlapped: false, + uniqueForeignIntersectionPoints: [] + }; + var thisPath = { + modelContext: modelContext, + pathId: pathId1, + segments: [segment] + }; + //keep breaking the segments anywhere they intersect with paths of the other model + model.walkPaths(modelToIntersect, function (mx, pathId2, path2) { + if (path2 && path1 !== path2) { + breakAlongForeignPath(thisPath.segments, overlappedSegments, path2); + } + }); + if (checkIsInside) { + //check each segment whether it is inside or outside + for (var i = 0; i < thisPath.segments.length; i++) { + checkInsideForeignModel(thisPath.segments[i], modelToIntersect, farPoint); + } + } + crossedPaths.push(thisPath); + }); + return { crossedPaths: crossedPaths, overlappedSegments: overlappedSegments }; + } + /** + * @private + */ + function checkForEqualOverlaps(crossedPathsA, crossedPathsB, pointMatchingDistance) { + function compareSegments(segment1, segment2) { + if (MakerJs.measure.isPathEqual(segment1.path, segment2.path, pointMatchingDistance)) { + segment1.duplicate = segment2.duplicate = true; + } + } + function compareAll(segment) { + for (var i = 0; i < crossedPathsB.length; i++) { + compareSegments(crossedPathsB[i], segment); + } + } + for (var i = 0; i < crossedPathsA.length; i++) { + compareAll(crossedPathsA[i]); + } + } + /** + * @private + */ + function addOrDeleteSegments(crossedPath, includeInside, includeOutside, keepDuplicates) { + function addSegment(modelContext, pathIdBase, segment) { + var id = model.getSimilarPathId(modelContext, pathIdBase); + modelContext.paths[id] = segment.path; + } + function checkAddSegment(modelContext, pathIdBase, segment) { + if (segment.isInside && includeInside || !segment.isInside && includeOutside) { + addSegment(modelContext, pathIdBase, segment); + } + } + //delete the original, its segments will be added + delete crossedPath.modelContext.paths[crossedPath.pathId]; + for (var i = 0; i < crossedPath.segments.length; i++) { + if (crossedPath.segments[i].duplicate) { + if (keepDuplicates) { + addSegment(crossedPath.modelContext, crossedPath.pathId, crossedPath.segments[i]); + } + } + else { + checkAddSegment(crossedPath.modelContext, crossedPath.pathId, crossedPath.segments[i]); + } + } + } + /** + * Combine 2 models. The models should be originated, and every path within each model should be part of a loop. + * + * @param modelA First model to combine. + * @param modelB Second model to combine. + * @param includeAInsideB Flag to include paths from modelA which are inside of modelB. + * @param includeAOutsideB Flag to include paths from modelA which are outside of modelB. + * @param includeBInsideA Flag to include paths from modelB which are inside of modelA. + * @param includeBOutsideA Flag to include paths from modelB which are outside of modelA. + * @param keepDuplicates Flag to include paths which are duplicate in both models. + * @param farPoint Optional point of reference which is outside the bounds of both models. + */ + function combine(modelA, modelB, includeAInsideB, includeAOutsideB, includeBInsideA, includeBOutsideA, options) { + if (includeAInsideB === void 0) { includeAInsideB = false; } + if (includeAOutsideB === void 0) { includeAOutsideB = true; } + if (includeBInsideA === void 0) { includeBInsideA = false; } + if (includeBOutsideA === void 0) { includeBOutsideA = true; } + var opts = { + trimDeadEnds: true, + pointMatchingDistance: .005 + }; + MakerJs.extendObject(opts, options); + var pathsA = breakAllPathsAtIntersections(modelA, modelB, true, opts.farPoint); + var pathsB = breakAllPathsAtIntersections(modelB, modelA, true, opts.farPoint); + checkForEqualOverlaps(pathsA.overlappedSegments, pathsB.overlappedSegments, opts.pointMatchingDistance); + for (var i = 0; i < pathsA.crossedPaths.length; i++) { + addOrDeleteSegments(pathsA.crossedPaths[i], includeAInsideB, includeAOutsideB, true); + } + for (var i = 0; i < pathsB.crossedPaths.length; i++) { + addOrDeleteSegments(pathsB.crossedPaths[i], includeBInsideA, includeBOutsideA, false); + } + if (opts.trimDeadEnds) { + model.removeDeadEnds({ models: { modelA: modelA, modelB: modelB } }); + } + } + model.combine = combine; + })(model = MakerJs.model || (MakerJs.model = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + /** + * Collects items that share a common key. + */ + var Collector = (function () { + function Collector(comparer) { + this.comparer = comparer; + this.collections = []; + } + Collector.prototype.addItemToCollection = function (key, item) { + var found = this.findCollection(key); + if (found) { + found.push(item); + } + else { + var collection = { key: key, items: [item] }; + this.collections.push(collection); + } + }; + Collector.prototype.findCollection = function (key, action) { + for (var i = 0; i < this.collections.length; i++) { + var collection = this.collections[i]; + if (this.comparer(key, collection.key)) { + if (action) { + action(i); + } + return collection.items; + } + } + return null; + }; + Collector.prototype.removeCollection = function (key) { + var _this = this; + if (this.findCollection(key, function (index) { _this.collections.splice(index, 1); })) { + return true; + } + return false; + }; + Collector.prototype.removeItemFromCollection = function (key, item) { + var collection = this.findCollection(key); + if (!collection) + return; + for (var i = 0; i < collection.length; i++) { + if (collection[i] === item) { + collection.splice(i, 1); + return true; + } + } + return false; + }; + Collector.prototype.getCollectionsOfMultiple = function (cb) { + for (var i = 0; i < this.collections.length; i++) { + var collection = this.collections[i]; + if (collection.items.length > 1) { + cb(collection.key, collection.items); + } + } + }; + return Collector; + }()); + MakerJs.Collector = Collector; +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var model; + (function (model) { + /** + * @private + */ + function checkForOverlaps(refPaths, isOverlapping, overlapUnion) { + var currIndex = 0; + do { + var root = refPaths[currIndex]; + do { + var overlaps = false; + for (var i = currIndex + 1; i < refPaths.length; i++) { + var arcRef = refPaths[i]; + overlaps = isOverlapping(root.pathContext, arcRef.pathContext, false); + if (overlaps) { + overlapUnion(root.pathContext, arcRef.pathContext); + delete arcRef.modelContext.paths[arcRef.pathId]; + refPaths.splice(i, 1); + break; + } + } + } while (overlaps); + currIndex++; + } while (currIndex < refPaths.length); + } + /** + * @private + */ + function normalizedArcLimits(arc) { + var startAngle = MakerJs.angle.noRevolutions(arc.startAngle); + return { + startAngle: startAngle, + endAngle: MakerJs.angle.ofArcSpan(arc) + startAngle + }; + } + /** + * Simplify a model's paths by reducing redundancy: combine multiple overlapping paths into a single path. + * + * @param modelContext The model to search for similar paths. + * @param options Optional options object. + * @returns The simplified model (for chaining). + */ + function simplify(modelToSimplify, options) { + function compareCircles(circle1, circle2) { + if (Math.abs(circle1.radius - circle2.radius) <= opts.scalarMatchingDistance) { + var distance = MakerJs.measure.pointDistance(circle1.origin, circle2.origin); + return distance <= opts.pointMatchingDistance; + } + return false; + } + var similarArcs = new MakerJs.Collector(compareCircles); + var similarCircles = new MakerJs.Collector(compareCircles); + var similarLines = new MakerJs.Collector(MakerJs.measure.isSlopeEqual); + var map = {}; + map[MakerJs.pathType.Arc] = function (arcRef) { + similarArcs.addItemToCollection(arcRef.pathContext, arcRef); + }; + map[MakerJs.pathType.Circle] = function (circleRef) { + similarCircles.addItemToCollection(circleRef.pathContext, circleRef); + }; + map[MakerJs.pathType.Line] = function (lineRef) { + var slope = MakerJs.measure.lineSlope(lineRef.pathContext); + similarLines.addItemToCollection(slope, lineRef); + }; + var opts = { + scalarMatchingDistance: .001, + pointMatchingDistance: .005 + }; + MakerJs.extendObject(opts, options); + //walk the model and collect: arcs on same center / radius, circles on same center / radius, lines on same y-intercept / slope. + model.walkPaths(modelToSimplify, function (modelContext, pathId, pathContext) { + var ref = { + modelContext: modelContext, + pathContext: pathContext, + pathId: pathId + }; + var fn = map[pathContext.type]; + if (fn) { + fn(ref); + } + }); + //for all arcs that are similar, see if they overlap. + //combine overlapping arcs into the first one and delete the second. + similarArcs.getCollectionsOfMultiple(function (key, arcRefs) { + checkForOverlaps(arcRefs, MakerJs.measure.isArcOverlapping, function (arc1, arc2) { + var limit1 = normalizedArcLimits(arc1); + var limit2 = normalizedArcLimits(arc2); + arc1.startAngle = Math.min(limit1.startAngle, limit2.startAngle); + arc1.endAngle = Math.max(limit1.endAngle, limit2.endAngle); + }); + }); + //for all circles that are similar, delete all but the first. + similarCircles.getCollectionsOfMultiple(function (key, circleRefs) { + for (var i = 1; i < circleRefs.length; i++) { + var circleRef = circleRefs[i]; + delete circleRef.modelContext.paths[circleRef.pathId]; + } + }); + //for all lines that are similar, see if they overlap. + //combine overlapping lines into the first one and delete the second. + similarLines.getCollectionsOfMultiple(function (slope, arcRefs) { + checkForOverlaps(arcRefs, MakerJs.measure.isLineOverlapping, function (line1, line2) { + var box = { paths: { line1: line1, line2: line2 } }; + var m = MakerJs.measure.modelExtents(box); + if (!slope.hasSlope) { + //vertical + line1.origin[1] = m.low[1]; + line1.end[1] = m.high[1]; + } + else { + //non-vertical + if (slope.slope < 0) { + //downward + line1.origin = [m.low[0], m.high[1]]; + line1.end = [m.high[0], m.low[1]]; + } + else if (slope.slope > 0) { + //upward + line1.origin = m.low; + line1.end = m.high; + } + else { + //horizontal + line1.origin[0] = m.low[0]; + line1.end[0] = m.high[0]; + } + } + }); + }); + return modelToSimplify; + } + model.simplify = simplify; + })(model = MakerJs.model || (MakerJs.model = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var path; + (function (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, expansion, isolateCaps) { + if (!pathToExpand) + return null; + var result; + var map = {}; + map[MakerJs.pathType.Arc] = function (arc) { + result = new MakerJs.models.OvalArc(arc.startAngle, arc.endAngle, arc.radius, expansion, false, isolateCaps); + }; + map[MakerJs.pathType.Circle] = function (circle) { + result = new MakerJs.models.Ring(circle.radius + expansion, circle.radius - expansion); + }; + map[MakerJs.pathType.Line] = function (line) { + result = new MakerJs.models.Slot(line.origin, line.end, expansion, isolateCaps); + }; + var fn = map[pathToExpand.type]; + if (fn) { + fn(pathToExpand); + result.origin = pathToExpand.origin; + } + return result; + } + path.expand = expand; + /** + * 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. + * @returns Model of straight lines with same endpoints as the arc. + */ + function straighten(arc, bevel) { + var arcSpan = MakerJs.angle.ofArcSpan(arc); + var joints = 1; + if (arcSpan >= 270) { + joints = 4; + } + else if (arcSpan > 180) { + joints = 3; + } + else if (arcSpan > 150 || bevel) { + joints = 2; + } + var jointAngleInRadians = MakerJs.angle.toRadians(arcSpan / joints); + var circumscribedRadius = MakerJs.models.Polygon.circumscribedRadius(arc.radius, jointAngleInRadians); + var ends = MakerJs.point.fromArc(arc); + var points = [MakerJs.point.subtract(ends[0], arc.origin)]; + var a = MakerJs.angle.toRadians(arc.startAngle) + jointAngleInRadians / 2; + for (var i = 0; i < joints; i++) { + points.push(MakerJs.point.fromPolar(a, circumscribedRadius)); + a += jointAngleInRadians; + } + points.push(MakerJs.point.subtract(ends[1], arc.origin)); + var result = new MakerJs.models.ConnectTheDots(false, points); + result.origin = arc.origin; + return result; + } + path.straighten = straighten; + })(path = MakerJs.path || (MakerJs.path = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var model; + (function (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, distance, joints) { + if (joints === void 0) { joints = 0; } + if (distance <= 0) + return null; + var result = { + models: { + expansions: { models: {} }, + caps: { models: {} } + } + }; + var first = true; + //TODO: work without origination + var originated = model.originate(modelToExpand); + model.walkPaths(originated, function (modelContext, pathId, pathContext) { + var expandedPathModel = MakerJs.path.expand(pathContext, distance, true); + if (expandedPathModel) { + var newId = model.getSimilarModelId(result.models['expansions'], pathId); + model.originate(expandedPathModel); + if (!first) { + model.combine(result, expandedPathModel); + } + result.models['expansions'].models[newId] = expandedPathModel; + if (expandedPathModel.models) { + var caps = expandedPathModel.models['Caps']; + if (caps) { + delete expandedPathModel.models['Caps']; + result.models['caps'].models[newId] = caps; + } + } + first = false; + } + }); + if (joints) { + var roundCaps = result.models['caps']; + model.simplify(roundCaps); + var straightCaps = { models: {} }; + //straighten each cap, optionally beveling + for (var id in roundCaps.models) { + var straightened = { models: {} }; + model.walkPaths(roundCaps.models[id], function (modelContext, pathId, pathContext) { + straightened.models[pathId] = MakerJs.path.straighten(pathContext, joints == 2); + }); + straightCaps.models[id] = straightened; + } + //replace the rounded with the straightened + result.models['caps'] = straightCaps; + } + return result; + } + model.expandPaths = expandPaths; + /** + * Outline a model by a specified distance. Useful for accommadating 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. + * @returns Model which surrounds the paths outside of the original model. + */ + function outline(modelToOutline, distance, joints) { + var expanded = expandPaths(modelToOutline, distance, joints); + if (!expanded) + return null; + var loops = model.findLoops(expanded); + if (loops && loops.models) { + var i = 0; + while (loops.models[i]) { + delete loops.models[i + 1]; + delete loops.models[i + 2]; + i += 4; + } + return loops; + } + return null; + } + model.outline = outline; + })(model = MakerJs.model || (MakerJs.model = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var units; + (function (units) { + /** + * The base type is arbitrary. Other conversions are then based off of this. + * @private + */ + var base = MakerJs.unitType.Millimeter; + /** + * Initialize all known conversions here. + * @private + */ + function init() { + addBaseConversion(MakerJs.unitType.Centimeter, 10); + addBaseConversion(MakerJs.unitType.Meter, 1000); + addBaseConversion(MakerJs.unitType.Inch, 25.4); + addBaseConversion(MakerJs.unitType.Foot, 25.4 * 12); + } + /** + * Table of conversions. Lazy load upon first conversion. + * @private + */ + var table; + /** + * Add a conversion, and its inversion. + * @private + */ + function addConversion(srcUnitType, destUnitType, value) { + function row(unitType) { + if (!table[unitType]) { + table[unitType] = {}; + } + return table[unitType]; + } + row(srcUnitType)[destUnitType] = value; + row(destUnitType)[srcUnitType] = 1 / value; + } + /** + * Add a conversion of the base unit. + * @private + */ + function addBaseConversion(destUnitType, value) { + addConversion(destUnitType, base, value); + } + /** + * Get a conversion ratio between a source unit and a destination unit. + * + * @param srcUnitType unitType converting from. + * @param destUnitType unitType converting to. + * @returns Numeric ratio of the conversion. + */ + function conversionScale(srcUnitType, destUnitType) { + if (srcUnitType == destUnitType) { + return 1; + } + //This will lazy load the table with initial conversions. + if (!table) { + table = {}; + init(); + } + //look for a cached conversion in the table. + if (!table[srcUnitType][destUnitType]) { + //create a new conversionsand cache it in the table. + addConversion(srcUnitType, destUnitType, table[srcUnitType][base] * table[base][destUnitType]); + } + return table[srcUnitType][destUnitType]; + } + units.conversionScale = conversionScale; + })(units = MakerJs.units || (MakerJs.units = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var measure; + (function (measure) { + /** + * 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 isAngleEqual(angle1, angle2, accuracy) { + if (accuracy === void 0) { accuracy = .0001; } + var a1 = MakerJs.angle.noRevolutions(angle1); + var a2 = MakerJs.angle.noRevolutions(angle2); + var d = MakerJs.angle.noRevolutions(MakerJs.round(a2 - a1, accuracy)); + return d == 0; + } + measure.isAngleEqual = isAngleEqual; + /** + * @private + */ + var pathAreEqualMap = {}; + pathAreEqualMap[MakerJs.pathType.Line] = function (line1, line2, withinPointDistance) { + return (isPointEqual(line1.origin, line2.origin, withinPointDistance) && isPointEqual(line1.end, line2.end, withinPointDistance)) + || (isPointEqual(line1.origin, line2.end, withinPointDistance) && isPointEqual(line1.end, line2.origin, withinPointDistance)); + }; + pathAreEqualMap[MakerJs.pathType.Circle] = function (circle1, circle2, withinPointDistance) { + return isPointEqual(circle1.origin, circle2.origin, withinPointDistance) && circle1.radius == circle2.radius; + }; + pathAreEqualMap[MakerJs.pathType.Arc] = function (arc1, arc2, withinPointDistance) { + return pathAreEqualMap[MakerJs.pathType.Circle](arc1, arc2, withinPointDistance) && isAngleEqual(arc1.startAngle, arc2.startAngle) && isAngleEqual(arc1.endAngle, arc2.endAngle); + }; + /** + * Find out if two paths are equal. + * + * @param a First path. + * @param b Second path. + * @returns true if paths are the same, false if they are not + */ + function isPathEqual(path1, path2, withinPointDistance) { + var result = false; + if (path1.type == path2.type) { + var fn = pathAreEqualMap[path1.type]; + if (fn) { + result = fn(path1, path2, withinPointDistance); + } + } + return result; + } + measure.isPathEqual = isPathEqual; + /** + * 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, b, withinDistance) { + if (!withinDistance) { + return a[0] == b[0] && a[1] == b[1]; + } + else { + var distance = measure.pointDistance(a, b); + return distance <= withinDistance; + } + } + measure.isPointEqual = isPointEqual; + /** + * Check for slope equality. + * + * @param slope1 The ISlope to test. + * @param slope2 The ISlope to check for equality. + * @returns Boolean true if slopes are equal. + */ + function isSlopeEqual(slope1, slope2) { + if (!slope1.hasSlope && !slope2.hasSlope) { + //lines are both vertical, see if x are the same + return MakerJs.round(slope1.line.origin[0] - slope2.line.origin[0]) == 0; + } + if (slope1.hasSlope && slope2.hasSlope && (MakerJs.round(slope1.slope - slope2.slope, .00001) == 0)) { + //lines are parallel, but not vertical, see if y-intercept is the same + return MakerJs.round(slope1.yIntercept - slope2.yIntercept, .00001) == 0; + } + return false; + } + measure.isSlopeEqual = isSlopeEqual; + })(measure = MakerJs.measure || (MakerJs.measure = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var measure; + (function (measure_1) { + /** + * Check for arc being concave or convex towards a given point. + * + * @param arc The arc to test. + * @param towardsPoint The point to test. + * @returns Boolean true if arc is concave towards point. + */ + function isArcConcaveTowardsPoint(arc, towardsPoint) { + if (pointDistance(arc.origin, towardsPoint) <= arc.radius) { + return true; + } + var midPointToNearPoint = new MakerJs.paths.Line(MakerJs.point.middle(arc), towardsPoint); + var options = {}; + var intersectionPoint = MakerJs.path.intersection(midPointToNearPoint, new MakerJs.paths.Chord(arc), options); + if (intersectionPoint || options.out_AreOverlapped) { + return true; + } + return false; + } + measure_1.isArcConcaveTowardsPoint = isArcConcaveTowardsPoint; + /** + * Check for arc overlapping another arc. + * + * @param arc1 The arc to test. + * @param arc2 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 arc2. + */ + function isArcOverlapping(arc1, arc2, excludeTangents) { + var pointsOfIntersection = []; + function checkAngles(a, b) { + function checkAngle(n) { + return measure.isBetweenArcAngles(n, a, excludeTangents); + } + return checkAngle(b.startAngle) || checkAngle(b.endAngle); + } + return checkAngles(arc1, arc2) || checkAngles(arc2, arc1) || (arc1.startAngle == arc2.startAngle && arc1.endAngle == arc2.endAngle); + } + measure_1.isArcOverlapping = isArcOverlapping; + /** + * 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 exclusive Flag to exclude equaling the limits. + * @returns Boolean true if value is between (or equal to) the limits. + */ + function isBetween(valueInQuestion, limit1, limit2, exclusive) { + if (exclusive) { + return Math.min(limit1, limit2) < valueInQuestion && valueInQuestion < Math.max(limit1, limit2); + } + else { + return Math.min(limit1, limit2) <= valueInQuestion && valueInQuestion <= Math.max(limit1, limit2); + } + } + measure_1.isBetween = isBetween; + /** + * Check if a given angle is between an arc's start and end angles. + * + * @param angleInQuestion The angle to test. + * @param arc Arc to test against. + * @param exclusive Flag to exclude equaling the start or end angles. + * @returns Boolean true if angle is between (or equal to) the arc's start and end angles. + */ + function isBetweenArcAngles(angleInQuestion, arc, exclusive) { + var startAngle = MakerJs.angle.noRevolutions(arc.startAngle); + var span = MakerJs.angle.ofArcSpan(arc); + var endAngle = startAngle + span; + angleInQuestion = MakerJs.angle.noRevolutions(angleInQuestion); + //computed angles will not be negative, but the arc may have specified a negative angle, so check against one revolution forward and backward + return (isBetween(angleInQuestion, startAngle, endAngle, exclusive) || isBetween(angleInQuestion, startAngle + 360, endAngle + 360, exclusive) || isBetween(angleInQuestion, startAngle - 360, endAngle - 360, exclusive)); + } + measure_1.isBetweenArcAngles = isBetweenArcAngles; + /** + * Check if a given point is between a line's end points. + * + * @param pointInQuestion The point to test. + * @param line Line to test against. + * @param exclusive Flag to exclude equaling the origin or end points. + * @returns Boolean true if point is between (or equal to) the line's origin and end points. + */ + function isBetweenPoints(pointInQuestion, line, exclusive) { + for (var i = 2; i--;) { + if (MakerJs.round(line.origin[i] - line.end[i], .000001) == 0) { + continue; + } + var origin_value = MakerJs.round(line.origin[i]); + var end_value = MakerJs.round(line.end[i]); + if (!isBetween(MakerJs.round(pointInQuestion[i]), origin_value, end_value, exclusive)) + return false; + } + return true; + } + measure_1.isBetweenPoints = isBetweenPoints; + /** + * Check for line overlapping another line. + * + * @param line1 The line to test. + * @param line2 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 line2. + */ + function isLineOverlapping(line1, line2, excludeTangents) { + var pointsOfIntersection = []; + function checkPoints(index, a, b) { + function checkPoint(p) { + return measure.isBetweenPoints(p, a, excludeTangents); + } + return checkPoint(b.origin) || checkPoint(b.end); + } + return checkPoints(0, line1, line2) || checkPoints(1, line2, line1); + } + measure_1.isLineOverlapping = isLineOverlapping; + /** + * Gets the slope of a line. + */ + function lineSlope(line) { + var dx = line.end[0] - line.origin[0]; + if (MakerJs.round(dx) == 0) { + return { + line: line, + hasSlope: false + }; + } + var dy = line.end[1] - line.origin[1]; + var slope = dy / dx; + var yIntercept = line.origin[1] - slope * line.origin[0]; + return { + line: line, + hasSlope: true, + slope: slope, + yIntercept: yIntercept + }; + } + measure_1.lineSlope = lineSlope; + /** + * Calculates the distance between two points. + * + * @param a First point. + * @param b Second point. + * @returns Distance between points. + */ + function pointDistance(a, b) { + var dx = b[0] - a[0]; + var dy = b[1] - a[1]; + return Math.sqrt(dx * dx + dy * dy); + } + measure_1.pointDistance = pointDistance; + /** + * @private + */ + function getExtremePoint(a, b, fn) { + return [ + fn(a[0], b[0]), + fn(a[1], b[1]) + ]; + } + /** + * Calculates the smallest rectangle which contains a path. + * + * @param pathToMeasure The path to measure. + * @returns object with low and high points. + */ + function pathExtents(pathToMeasure) { + var map = {}; + var measurement = { low: null, high: null }; + map[MakerJs.pathType.Line] = function (line) { + measurement.low = getExtremePoint(line.origin, line.end, Math.min); + measurement.high = getExtremePoint(line.origin, line.end, Math.max); + }; + map[MakerJs.pathType.Circle] = function (circle) { + var r = circle.radius; + measurement.low = MakerJs.point.add(circle.origin, [-r, -r]); + measurement.high = MakerJs.point.add(circle.origin, [r, r]); + }; + map[MakerJs.pathType.Arc] = function (arc) { + var r = arc.radius; + var arcPoints = MakerJs.point.fromArc(arc); + function extremeAngle(xyAngle, value, fn) { + var extremePoint = getExtremePoint(arcPoints[0], arcPoints[1], fn); + for (var i = 2; i--;) { + if (isBetweenArcAngles(xyAngle[i], arc, false)) { + extremePoint[i] = value + arc.origin[i]; + } + } + return extremePoint; + } + measurement.low = extremeAngle([180, 270], -r, Math.min); + measurement.high = extremeAngle([360, 90], r, Math.max); + }; + if (pathToMeasure) { + var fn = map[pathToMeasure.type]; + if (fn) { + fn(pathToMeasure); + } + } + return measurement; + } + measure_1.pathExtents = pathExtents; + /** + * Measures the length of a path. + * + * @param pathToMeasure The path to measure. + * @returns Length of the path. + */ + function pathLength(pathToMeasure) { + var map = {}; + var value = 0; + map[MakerJs.pathType.Line] = function (line) { + value = pointDistance(line.origin, line.end); + }; + map[MakerJs.pathType.Circle] = function (circle) { + value = 2 * Math.PI * circle.radius; + }; + map[MakerJs.pathType.Arc] = function (arc) { + map[MakerJs.pathType.Circle](arc); //this sets the value var + var pct = MakerJs.angle.ofArcSpan(arc) / 360; + value *= pct; + }; + var fn = map[pathToMeasure.type]; + if (fn) { + fn(pathToMeasure); + } + return value; + } + measure_1.pathLength = pathLength; + /** + * Measures the smallest rectangle which contains a model. + * + * @param modelToMeasure The model to measure. + * @returns object with low and high points. + */ + function modelExtents(modelToMeasure) { + var totalMeasurement = { low: [null, null], high: [null, null] }; + function lowerOrHigher(offsetOrigin, pathMeasurement) { + function getExtreme(a, b, fn) { + var c = MakerJs.point.add(b, offsetOrigin); + for (var i = 2; i--;) { + a[i] = (a[i] == null ? c[i] : fn(a[i], c[i])); + } + } + getExtreme(totalMeasurement.low, pathMeasurement.low, Math.min); + getExtreme(totalMeasurement.high, pathMeasurement.high, Math.max); + } + function measure(modelToMeasure, offsetOrigin) { + if (!modelToMeasure) + return; + var newOrigin = MakerJs.point.add(modelToMeasure.origin, offsetOrigin); + if (modelToMeasure.paths) { + for (var id in modelToMeasure.paths) { + lowerOrHigher(newOrigin, pathExtents(modelToMeasure.paths[id])); + } + } + if (modelToMeasure.models) { + for (var id in modelToMeasure.models) { + measure(modelToMeasure.models[id], newOrigin); + } + } + } + measure(modelToMeasure); + return totalMeasurement; + } + measure_1.modelExtents = modelExtents; + })(measure = MakerJs.measure || (MakerJs.measure = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var exporter; + (function (exporter) { + /** + * Try to get the unit system from a model + * @private + */ + function tryGetModelUnits(itemToExport) { + if (MakerJs.isModel(itemToExport)) { + return itemToExport.units; + } + } + exporter.tryGetModelUnits = tryGetModelUnits; + /** + * Class to traverse an item 's models or paths and ultimately render each path. + * @private + */ + var Exporter = (function () { + /** + * @param map Object containing properties: property name is the type of path, e.g. "line", "circle"; property value + * is a function to render a path. Function parameters are path and point. + * @param fixPoint Optional function to modify a point prior to export. Function parameter is a point; function must return a point. + * @param fixPath Optional function to modify a path prior to output. Function parameters are path and offset point; function must return a path. + */ + function Exporter(map, fixPoint, fixPath, beginModel, endModel) { + this.map = map; + this.fixPoint = fixPoint; + this.fixPath = fixPath; + this.beginModel = beginModel; + this.endModel = endModel; + } + /** + * Export a path. + * + * @param pathToExport The path to export. + * @param offset The offset position of the path. + */ + Exporter.prototype.exportPath = function (id, pathToExport, offset, layer) { + if (pathToExport) { + var fn = this.map[pathToExport.type]; + if (fn) { + fn(id, this.fixPath ? this.fixPath(pathToExport, offset) : pathToExport, offset, layer); + } + } + }; + /** + * Export a model. + * + * @param modelToExport The model to export. + * @param offset The offset position of the model. + */ + Exporter.prototype.exportModel = function (modelId, modelToExport, offset) { + if (this.beginModel) { + this.beginModel(modelId, modelToExport); + } + var newOffset = MakerJs.point.add((this.fixPoint ? this.fixPoint(modelToExport.origin) : modelToExport.origin), offset); + if (modelToExport.paths) { + for (var id in modelToExport.paths) { + var currPath = modelToExport.paths[id]; + if (!currPath) + continue; + this.exportPath(id, currPath, newOffset, currPath.layer || modelToExport.layer); + } + } + if (modelToExport.models) { + for (var id in modelToExport.models) { + var currModel = modelToExport.models[id]; + if (!currModel) + continue; + this.exportModel(id, currModel, newOffset); + } + } + if (this.endModel) { + this.endModel(modelToExport); + } + }; + /** + * Export an object. + * + * @param item The object to export. May be a path, an array of paths, a model, or an array of models. + * @param offset The offset position of the object. + */ + Exporter.prototype.exportItem = function (itemId, itemToExport, origin) { + if (MakerJs.isModel(itemToExport)) { + this.exportModel(itemId, itemToExport, origin); + } + else if (MakerJs.isPath(itemToExport)) { + this.exportPath(itemId, itemToExport, origin, null); + } + else { + for (var id in itemToExport) { + this.exportItem(id, itemToExport[id], origin); + } + } + }; + return Exporter; + }()); + exporter.Exporter = Exporter; + })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var exporter; + (function (exporter_1) { + /** + * Renders an item in AutoDesk DFX file format. + * + * @param itemToExport Item to render: may be a path, an array of paths, or a model object. + * @param options Rendering options object. + * @param options.units String of the unit system. May be omitted. See makerjs.unitType for possible values. + * @returns String of DXF content. + */ + function toDXF(itemToExport, options) { + //DXF format documentation: + //http://images.autodesk.com/adsk/files/acad_dxf0.pdf + if (options === void 0) { options = {}; } + var opts = {}; + MakerJs.extendObject(opts, options); + if (MakerJs.isModel(itemToExport)) { + var modelToExport = itemToExport; + if (modelToExport.exporterOptions) { + MakerJs.extendObject(opts, modelToExport.exporterOptions['toDXF']); + } + } + var dxf = []; + function append(value) { + dxf.push(value); + } + function defaultLayer(pathContext, layer) { + return pathContext.layer || layer || 0; + } + var map = {}; + map[MakerJs.pathType.Line] = function (id, line, origin, layer) { + append("0"); + append("LINE"); + append("8"); + append(defaultLayer(line, layer)); + append("10"); + append(line.origin[0] + origin[0]); + append("20"); + append(line.origin[1] + origin[1]); + append("11"); + append(line.end[0] + origin[0]); + append("21"); + append(line.end[1] + origin[1]); + }; + map[MakerJs.pathType.Circle] = function (id, circle, origin, layer) { + append("0"); + append("CIRCLE"); + append("8"); + append(defaultLayer(circle, layer)); + append("10"); + append(circle.origin[0] + origin[0]); + append("20"); + append(circle.origin[1] + origin[1]); + append("40"); + append(circle.radius); + }; + map[MakerJs.pathType.Arc] = function (id, arc, origin, layer) { + append("0"); + append("ARC"); + append("8"); + append(defaultLayer(arc, layer)); + append("10"); + append(arc.origin[0] + origin[0]); + append("20"); + append(arc.origin[1] + origin[1]); + append("40"); + append(arc.radius); + append("50"); + append(arc.startAngle); + append("51"); + append(arc.endAngle); + }; + function section(sectionFn) { + append("0"); + append("SECTION"); + sectionFn(); + append("0"); + append("ENDSEC"); + } + function header() { + var units = dxfUnit[opts.units]; + append("2"); + append("HEADER"); + append("9"); + append("$INSUNITS"); + append("70"); + append(units); + } + function entities() { + append("2"); + append("ENTITIES"); + var exporter = new exporter_1.Exporter(map); + exporter.exportItem('entities', itemToExport, MakerJs.point.zero()); + } + //fixup options + if (!opts.units) { + var units = exporter_1.tryGetModelUnits(itemToExport); + if (units) { + opts.units = units; + } + } + //also pass back to options parameter + MakerJs.extendObject(options, opts); + //begin dxf output + if (opts.units) { + section(header); + } + section(entities); + append("0"); + append("EOF"); + return dxf.join('\n'); + } + exporter_1.toDXF = toDXF; + /** + * @private + */ + var dxfUnit = {}; + //DXF format documentation: + //http://images.autodesk.com/adsk/files/acad_dxf0.pdf + //Default drawing units for AutoCAD DesignCenter blocks: + //0 = Unitless; 1 = Inches; 2 = Feet; 3 = Miles; 4 = Millimeters; 5 = Centimeters; 6 = Meters; 7 = Kilometers; 8 = Microinches; + dxfUnit[''] = 0; + dxfUnit[MakerJs.unitType.Inch] = 1; + dxfUnit[MakerJs.unitType.Foot] = 2; + dxfUnit[MakerJs.unitType.Millimeter] = 4; + dxfUnit[MakerJs.unitType.Centimeter] = 5; + dxfUnit[MakerJs.unitType.Meter] = 6; + })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var solvers; + (function (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. + * @returns Angle opposite of the side represented by the first parameter. + */ + function solveTriangleSSS(length1, length2, length3) { + return MakerJs.angle.toDegrees(Math.acos((length2 * length2 + length3 * length3 - length1 * length1) / (2 * length2 * length3))); + } + solvers.solveTriangleSSS = solveTriangleSSS; + /** + * Solves for the length of a side of a triangle when you know length of one side and 2 angles. + * + * @param oppositeAngleInDegrees Angle which is opposite of the side you are trying to find. + * @param lengthOfSideBetweenAngles Length of one side of the triangle which is between the provided angles. + * @param otherAngleInDegrees An other angle of the triangle. + * @returns Length of the side of the triangle which is opposite of the first angle parameter. + */ + function solveTriangleASA(oppositeAngleInDegrees, lengthOfSideBetweenAngles, otherAngleInDegrees) { + var angleOppositeSide = 180 - oppositeAngleInDegrees - otherAngleInDegrees; + return (lengthOfSideBetweenAngles * Math.sin(MakerJs.angle.toRadians(oppositeAngleInDegrees))) / Math.sin(MakerJs.angle.toRadians(angleOppositeSide)); + } + solvers.solveTriangleASA = solveTriangleASA; + })(solvers = MakerJs.solvers || (MakerJs.solvers = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var path; + (function (path) { + /** + * @private + */ + var map = {}; + map[MakerJs.pathType.Arc] = {}; + map[MakerJs.pathType.Circle] = {}; + map[MakerJs.pathType.Line] = {}; + map[MakerJs.pathType.Arc][MakerJs.pathType.Arc] = function (arc1, arc2, options) { + var angles = circleToCircle(arc1, arc2, options); + if (angles) { + var arc1Angles = getAnglesWithinArc(angles[0], arc1, options); + var arc2Angles = getAnglesWithinArc(angles[1], arc2, options); + if (arc1Angles && arc2Angles) { + return { + intersectionPoints: pointsFromAnglesOnCircle(arc1Angles, arc1), + path1Angles: arc1Angles, + path2Angles: arc2Angles + }; + } + } + else { + if (options.out_AreOverlapped) { + //overlapped for circle, reset and see if arcs actually overlap. + options.out_AreOverlapped = MakerJs.measure.isArcOverlapping(arc1, arc2, options.excludeTangents); + } + } + return null; + }; + map[MakerJs.pathType.Arc][MakerJs.pathType.Circle] = function (arc, circle, options) { + var angles = circleToCircle(arc, circle, options); + if (angles) { + var arcAngles = getAnglesWithinArc(angles[0], arc, options); + if (arcAngles) { + var circleAngles; + //if both point are on arc, use both on circle + if (arcAngles.length == 2) { + circleAngles = angles[1]; + } + else { + //use the corresponding point on circle + var index = findCorrespondingAngleIndex(angles, arcAngles); + circleAngles = [angles[1][index]]; + } + return { + intersectionPoints: pointsFromAnglesOnCircle(arcAngles, arc), + path1Angles: arcAngles, + path2Angles: circleAngles + }; + } + } + return null; + }; + map[MakerJs.pathType.Arc][MakerJs.pathType.Line] = function (arc, line, options) { + var angles = lineToCircle(line, arc, options); + if (angles) { + var arcAngles = getAnglesWithinArc(angles, arc, options); + if (arcAngles) { + return { + intersectionPoints: pointsFromAnglesOnCircle(arcAngles, arc), + path1Angles: arcAngles + }; + } + } + return null; + }; + map[MakerJs.pathType.Circle][MakerJs.pathType.Arc] = function (circle, arc, options) { + var result = map[MakerJs.pathType.Arc][MakerJs.pathType.Circle](arc, circle, options); + if (result) { + return swap(result); + } + return null; + }; + map[MakerJs.pathType.Circle][MakerJs.pathType.Circle] = function (circle1, circle2, options) { + var angles = circleToCircle(circle1, circle2, options); + if (angles) { + return { + intersectionPoints: pointsFromAnglesOnCircle(angles[0], circle1), + path1Angles: angles[0], + path2Angles: angles[1] + }; + } + return null; + }; + map[MakerJs.pathType.Circle][MakerJs.pathType.Line] = function (circle, line, options) { + var angles = lineToCircle(line, circle, options); + if (angles) { + return { + intersectionPoints: pointsFromAnglesOnCircle(angles, circle), + path1Angles: angles + }; + } + return null; + }; + map[MakerJs.pathType.Line][MakerJs.pathType.Arc] = function (line, arc, options) { + var result = map[MakerJs.pathType.Arc][MakerJs.pathType.Line](arc, line, options); + if (result) { + return swap(result); + } + return null; + }; + map[MakerJs.pathType.Line][MakerJs.pathType.Circle] = function (line, circle, options) { + var result = map[MakerJs.pathType.Circle][MakerJs.pathType.Line](circle, line, options); + if (result) { + return swap(result); + } + return null; + }; + map[MakerJs.pathType.Line][MakerJs.pathType.Line] = function (line1, line2, options) { + var intersectionPoint = MakerJs.point.fromSlopeIntersection(line1, line2, options); + if (intersectionPoint) { + //we have the point of intersection of endless lines, now check to see if the point is between both segemnts + if (MakerJs.measure.isBetweenPoints(intersectionPoint, line1, options.excludeTangents) && MakerJs.measure.isBetweenPoints(intersectionPoint, line2, options.excludeTangents)) { + return { + intersectionPoints: [intersectionPoint] + }; + } + } + return null; + }; + /** + * @private + */ + function swap(result) { + var temp = result.path1Angles; + if (result.path2Angles) { + result.path1Angles = result.path2Angles; + } + else { + delete result.path1Angles; + } + result.path2Angles = temp; + return result; + } + /** + * Find the point(s) where 2 paths intersect. + * + * @param path1 First path to find intersection. + * @param path2 Second path to find intersection. + * @param options Optional IPathIntersectionOptions. + * @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, path2, options) { + if (options === void 0) { options = {}; } + if (path1 && path2) { + var fn = map[path1.type][path2.type]; + if (fn) { + return fn(path1, path2, options); + } + } + return null; + } + path.intersection = intersection; + /** + * @private + */ + function findCorrespondingAngleIndex(circleAngles, arcAngle) { + for (var i = 0; i < circleAngles.length; i++) { + if (circleAngles[i][0] == arcAngle[0]) + return i; + } + } + /** + * @private + */ + function pointsFromAnglesOnCircle(anglesInDegrees, circle) { + var result = []; + for (var i = 0; i < anglesInDegrees.length; i++) { + result.push(MakerJs.point.fromAngleOnCircle(anglesInDegrees[i], circle)); + } + return result; + } + /** + * @private + */ + function getAnglesWithinArc(angles, arc, options) { + if (!angles) + return null; + var anglesWithinArc = []; + for (var i = 0; i < angles.length; i++) { + if (MakerJs.measure.isBetweenArcAngles(angles[i], arc, options.excludeTangents)) { + anglesWithinArc.push(angles[i]); + } + } + if (anglesWithinArc.length == 0) + return null; + return anglesWithinArc; + } + /** + * @private + */ + function lineToCircle(line, circle, options) { + var radius = MakerJs.round(circle.radius); + //clone the line + var clonedLine = new MakerJs.paths.Line(MakerJs.point.subtract(line.origin, circle.origin), MakerJs.point.subtract(line.end, circle.origin)); + //get angle of line + var lineAngleNormal = MakerJs.angle.ofLineInDegrees(line); + //use the positive horizontal angle + var lineAngle = (lineAngleNormal >= 180) ? lineAngleNormal - 360 : lineAngleNormal; + //rotate the line to horizontal + path.rotate(clonedLine, -lineAngle, MakerJs.point.zero()); + //remember how to undo the rotation we just did + function unRotate(resultAngle) { + var unrotated = resultAngle + lineAngle; + return MakerJs.angle.noRevolutions(unrotated); + } + //line is horizontal, get the y value from any point + var lineY = MakerJs.round(clonedLine.origin[1]); + var lineYabs = Math.abs(lineY); + //if y is greater than radius, there is no intersection + if (lineYabs > radius) { + return null; + } + var anglesOfIntersection = []; + //if horizontal Y is the same as the radius, we know it's 90 degrees + if (lineYabs == radius) { + if (options.excludeTangents) { + return null; + } + anglesOfIntersection.push(unRotate(lineY > 0 ? 90 : 270)); + } + else { + function intersectionBetweenEndpoints(x, angleOfX) { + if (MakerJs.measure.isBetween(MakerJs.round(x), MakerJs.round(clonedLine.origin[0]), MakerJs.round(clonedLine.end[0]), options.excludeTangents)) { + anglesOfIntersection.push(unRotate(angleOfX)); + } + } + //find angle where line intersects + var intersectRadians = Math.asin(lineY / radius); + var intersectDegrees = MakerJs.angle.toDegrees(intersectRadians); + //line may intersect in 2 places + var intersectX = Math.cos(intersectRadians) * radius; + intersectionBetweenEndpoints(-intersectX, 180 - intersectDegrees); + intersectionBetweenEndpoints(intersectX, intersectDegrees); + } + if (anglesOfIntersection.length > 0) { + return anglesOfIntersection; + } + return null; + } + /** + * @private + */ + function circleToCircle(circle1, circle2, options) { + //see if circles are the same + if (circle1.radius == circle2.radius && MakerJs.measure.isPointEqual(circle1.origin, circle2.origin, .0001)) { + options.out_AreOverlapped = true; + return null; + } + //get offset from origin + var offset = MakerJs.point.subtract(MakerJs.point.zero(), circle1.origin); + //clone circle1 and move to origin + var c1 = new MakerJs.paths.Circle(MakerJs.point.zero(), circle1.radius); + //clone circle2 and move relative to circle1 + var c2 = new MakerJs.paths.Circle(MakerJs.point.subtract(circle2.origin, circle1.origin), circle2.radius); + //rotate circle2 to horizontal, c2 will be to the right of the origin. + var c2Angle = MakerJs.angle.ofPointInDegrees(MakerJs.point.zero(), c2.origin); + path.rotate(c2, -c2Angle, MakerJs.point.zero()); + function unRotate(resultAngle) { + var unrotated = resultAngle + c2Angle; + return MakerJs.angle.noRevolutions(unrotated); + } + //get X of c2 origin + var x = c2.origin[0]; + //see if c2 is outside of c1 + if (x - c2.radius > c1.radius) { + return null; + } + //see if c2 is within c1 + if (x + c2.radius < c1.radius) { + return null; + } + //see if c1 is within c2 + if (x - c2.radius < -c1.radius) { + return null; + } + //see if circles are tangent interior + if (MakerJs.round(c2.radius - x - c1.radius) == 0) { + if (options.excludeTangents) { + return null; + } + return [[unRotate(180)], [unRotate(180)]]; + } + //see if circles are tangent exterior + if (MakerJs.round(x - c2.radius - c1.radius) == 0) { + if (options.excludeTangents) { + return null; + } + return [[unRotate(0)], [unRotate(180)]]; + } + function bothAngles(oneAngle) { + return [unRotate(oneAngle), unRotate(MakerJs.angle.mirror(oneAngle, false, true))]; + } + var c1IntersectionAngle = MakerJs.solvers.solveTriangleSSS(c2.radius, c1.radius, x); + var c2IntersectionAngle = MakerJs.solvers.solveTriangleSSS(c1.radius, x, c2.radius); + return [bothAngles(c1IntersectionAngle), bothAngles(180 - c2IntersectionAngle)]; + } + })(path = MakerJs.path || (MakerJs.path = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var path; + (function (path) { + /** + * @private + */ + function getPointProperties(pathToInspect) { + var points = MakerJs.point.fromPathEnds(pathToInspect); + if (points) { + function pointProperty(index) { + return { point: points[index], propertyName: propertyNames[index] }; + } + var propertyNames = null; + var map = {}; + map[MakerJs.pathType.Arc] = function (arc) { + propertyNames = ['startAngle', 'endAngle']; + }; + map[MakerJs.pathType.Line] = function (line) { + propertyNames = ['origin', 'end']; + }; + var fn = map[pathToInspect.type]; + if (fn) { + fn(pathToInspect); + return [pointProperty(0), pointProperty(1)]; + } + } + return null; + } + /** + * @private + */ + function getMatchingPointProperties(path1, path2, options) { + var path1Properties = getPointProperties(path1); + var path2Properties = getPointProperties(path2); + var result = null; + function makeMatch(pathContext, pointProperties, index) { + return { + path: pathContext, + isStart: index == 0, + propertyName: pointProperties[index].propertyName, + point: pointProperties[index].point, + oppositePoint: pointProperties[1 - index].point + }; + } + function check(i1, i2) { + if (MakerJs.measure.isPointEqual(path1Properties[i1].point, path2Properties[i2].point, .0001)) { + result = [ + makeMatch(path1, path1Properties, i1), + makeMatch(path2, path2Properties, i2) + ]; + return true; + } + return false; + } + check(0, 0) || check(0, 1) || check(1, 0) || check(1, 1); + return result; + } + /** + * @private + */ + function populateShardPointsFromReferenceCircle(filletRadius, center, properties, options) { + var referenceCircle = new MakerJs.paths.Circle(center, filletRadius); + //get reference circle intersection points + for (var i = 0; i < 2; i++) { + var circleIntersection = path.intersection(referenceCircle, properties[i].path); + if (!circleIntersection) { + return false; + } + properties[i].shardPoint = circleIntersection.intersectionPoints[0]; + if (MakerJs.measure.isPointEqual(properties[i].point, circleIntersection.intersectionPoints[0], .0001)) { + if (circleIntersection.intersectionPoints.length > 1) { + properties[i].shardPoint = circleIntersection.intersectionPoints[1]; + } + else { + return false; + } + } + } + return true; + } + /** + * @private + */ + function cloneAndBreakPath(pathToShard, shardPoint) { + var shardStart = MakerJs.cloneObject(pathToShard); + var shardEnd = path.breakAtPoint(shardStart, shardPoint); + return [shardStart, shardEnd]; + } + /** + * @private + */ + function getGuidePath(context, filletRadius, nearPoint) { + var result = null; + var map = {}; + map[MakerJs.pathType.Arc] = function (arc) { + var guideRadius = arc.radius; + //see if the guideline should be external or internal to the context arc. + var guideArcShard = cloneAndBreakPath(arc, context.shardPoint)[context.isStart ? 0 : 1]; + if (guideArcShard) { + if (MakerJs.measure.isArcConcaveTowardsPoint(guideArcShard, nearPoint)) { + guideRadius -= filletRadius; + } + else { + guideRadius += filletRadius; + } + result = new MakerJs.paths.Arc(arc.origin, guideRadius, arc.startAngle, arc.endAngle); + } + }; + map[MakerJs.pathType.Line] = function (line) { + result = new MakerJs.paths.Parallel(line, filletRadius, nearPoint); + }; + var fn = map[context.path.type]; + if (fn) { + fn(context.path); + } + return result; + } + /** + * @private + */ + function getFilletResult(context, filletRadius, filletCenter) { + var result = null; + var map = {}; + map[MakerJs.pathType.Arc] = function (arc) { + var guideLine = new MakerJs.paths.Line(arc.origin, filletCenter); + var guideLineAngle = MakerJs.angle.ofLineInDegrees(guideLine); + var filletAngle = guideLineAngle; + //the context is an arc and the fillet is an arc so they will be tangent. If the fillet is external to the arc then the tangent is opposite. + if (!MakerJs.measure.isArcConcaveTowardsPoint(arc, filletCenter)) { + filletAngle += 180; + } + result = { + filletAngle: MakerJs.angle.noRevolutions(filletAngle), + clipPath: function () { + arc[context.propertyName] = guideLineAngle; + } + }; + }; + map[MakerJs.pathType.Line] = function (line) { + //make a small vertical line + var guideLine = new MakerJs.paths.Line([0, 0], [0, 1]); + //rotate this vertical line the same angle as the line context. It will be perpendicular. + var lineAngle = MakerJs.angle.ofLineInDegrees(line); + path.rotate(guideLine, lineAngle, [0, 0]); + path.moveRelative(guideLine, filletCenter); + //get the intersection point of the slopes of the context line and the perpendicular line. This is where the fillet meets the line. + var intersectionPoint = MakerJs.point.fromSlopeIntersection(line, guideLine); + if (intersectionPoint) { + result = { + filletAngle: MakerJs.angle.ofPointInDegrees(filletCenter, intersectionPoint), + clipPath: function () { + line[context.propertyName] = intersectionPoint; + } + }; + } + }; + var fn = map[context.path.type]; + if (fn) { + fn(context.path); + } + if (!testFilletResult(context, result)) { + result = null; + } + return result; + } + /** + * @private + */ + function getDogboneResult(context, filletCenter) { + var result = { + filletAngle: MakerJs.angle.ofPointInDegrees(filletCenter, context.shardPoint), + clipPath: function () { + context.path[context.propertyName] = context.shardPoint; + } + }; + if (!testFilletResult(context, result)) { + result = null; + } + return result; + } + /** + * @private + */ + function testFilletResult(context, result) { + var test = false; + if (result) { + //temporarily clip the path. + var originalValue = context.path[context.propertyName]; + result.clipPath(); + //don't allow a fillet which effectivly eliminates the path. + if (MakerJs.measure.pathLength(context.path) > 0) { + test = true; + } + //revert the clipping we just did. + context.path[context.propertyName] = originalValue; + } + return test; + } + /** + * @private + */ + function getLineRatio(lines) { + var totalLength = 0; + var lengths = []; + for (var i = 0; i < lines.length; i++) { + var length = MakerJs.measure.pathLength(lines[i]); + lengths.push(length); + totalLength += length; + } + return lengths[0] / totalLength; + } + /** + * 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. + * @returns Arc path object of the new fillet. + */ + function dogbone(line1, line2, filletRadius, options) { + if (MakerJs.isPathLine(line1) && MakerJs.isPathLine(line2) && filletRadius && filletRadius > 0) { + var opts = { + pointMatchingDistance: .005 + }; + MakerJs.extendObject(opts, options); + //first find the common point + var commonProperty = getMatchingPointProperties(line1, line2, options); + if (commonProperty) { + //get the ratio comparison of the two lines + var ratio = getLineRatio([line1, line2]); + //draw a line between the two endpoints, and get the bisection point at the ratio + var span = new MakerJs.paths.Line(commonProperty[0].oppositePoint, commonProperty[1].oppositePoint); + var midRatioPoint = MakerJs.point.middle(span, ratio); + //use the bisection theorem to get the angle bisecting the lines + var bisectionAngle = MakerJs.angle.ofPointInDegrees(commonProperty[0].point, midRatioPoint); + var center = MakerJs.point.add(commonProperty[0].point, MakerJs.point.fromPolar(MakerJs.angle.toRadians(bisectionAngle), filletRadius)); + if (!populateShardPointsFromReferenceCircle(filletRadius, center, commonProperty, opts)) { + return null; + } + //get the angles of the fillet and a function which clips the path to the fillet. + var results = []; + for (var i = 0; i < 2; i++) { + var result = getDogboneResult(commonProperty[i], center); + if (!result) { + return null; + } + results.push(result); + } + var filletArc = new MakerJs.paths.Arc(center, filletRadius, results[0].filletAngle, results[1].filletAngle); + //make sure midpoint of fillet is outside of the angle + if (MakerJs.round(MakerJs.angle.noRevolutions(MakerJs.angle.ofArcMiddle(filletArc))) == MakerJs.round(bisectionAngle)) { + filletArc.startAngle = results[1].filletAngle; + filletArc.endAngle = results[0].filletAngle; + } + //clip the paths and return the fillet arc. + results[0].clipPath(); + results[1].clipPath(); + return filletArc; + } + } + return null; + } + path.dogbone = dogbone; + /** + * 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. + * @returns Arc path object of the new fillet. + */ + function fillet(path1, path2, filletRadius, options) { + if (path1 && path2 && filletRadius && filletRadius > 0) { + var opts = { + pointMatchingDistance: .005 + }; + MakerJs.extendObject(opts, options); + //first find the common point + var commonProperty = getMatchingPointProperties(path1, path2, options); + if (commonProperty) { + //since arcs can curl beyond, we need a local reference point. + //An intersection with a circle of the same radius as the desired fillet should suffice. + if (!populateShardPointsFromReferenceCircle(filletRadius, commonProperty[0].point, commonProperty, opts)) { + return null; + } + //get "parallel" guidelines + var guidePaths = []; + for (var i = 0; i < 2; i++) { + var otherPathShardPoint = commonProperty[1 - i].shardPoint; + if (!otherPathShardPoint) { + return null; + } + var guidePath = getGuidePath(commonProperty[i], filletRadius, otherPathShardPoint); + guidePaths.push(guidePath); + } + //the center of the fillet is the point where the guidelines intersect. + var intersectionPoint = path.intersection(guidePaths[0], guidePaths[1]); + if (intersectionPoint) { + var center; + //if guidelines intersect in more than one place, choose the closest one. + if (intersectionPoint.intersectionPoints.length == 1) { + center = intersectionPoint.intersectionPoints[0]; + } + else { + center = MakerJs.point.closest(commonProperty[0].point, intersectionPoint.intersectionPoints); + } + //get the angles of the fillet and a function which clips the path to the fillet. + var results = []; + for (var i = 0; i < 2; i++) { + var result = getFilletResult(commonProperty[i], filletRadius, center); + if (!result) { + return null; + } + results.push(result); + } + //the two paths may actually be on the same line + if (MakerJs.round(results[0].filletAngle - results[1].filletAngle) == 0) + return null; + var filletArc = new MakerJs.paths.Arc(center, filletRadius, results[0].filletAngle, results[1].filletAngle); + var filletSpan = MakerJs.angle.ofArcSpan(filletArc); + //the algorithm is only valid for fillet less than 180 degrees + if (filletSpan == 180) { + return null; + } + if (filletSpan > 180) { + //swap to make smallest angle + filletArc.startAngle = results[1].filletAngle; + filletArc.endAngle = results[0].filletAngle; + } + //clip the paths and return the fillet arc. + results[0].clipPath(); + results[1].clipPath(); + return filletArc; + } + } + } + return null; + } + path.fillet = fillet; + })(path = MakerJs.path || (MakerJs.path = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var kit; + (function (kit) { + //construct a model + /** + * Helper function to use the JavaScript "apply" function in conjunction with the "new" keyword. + * + * @param ctor The constructor for the class which is an IKit. + * @param args The array of parameters passed to the constructor. + * @returns A new instance of the class, which implements the IModel interface. + */ + function construct(ctor, args) { + function F() { + return ctor.apply(this, args); + } + F.prototype = ctor.prototype; + return new F(); + } + kit.construct = construct; + /** + * Extract just the initial sample values from a kit. + * + * @param ctor The constructor for the class which is an IKit. + * @returns Array of the inital sample values provided in the metaParameters array. + */ + function getParameterValues(ctor) { + var parameters = []; + var metaParams = ctor.metaParameters; + if (metaParams) { + for (var i = 0; i < metaParams.length; i++) { + var value = metaParams[i].value; + if (Array.isArray(value)) { + value = value[0]; + } + parameters.push(value); + } + } + return parameters; + } + kit.getParameterValues = getParameterValues; + })(kit = MakerJs.kit || (MakerJs.kit = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var model; + (function (model) { + /** + * @private + */ + function getOpposedLink(linkedPaths, pathContext) { + if (linkedPaths[0].path === pathContext) { + return linkedPaths[1]; + } + return linkedPaths[0]; + } + /** + * @private + */ + function getFirstPathFromModel(modelContext) { + if (!modelContext.paths) + return null; + for (var pathId in modelContext.paths) { + return modelContext.paths[pathId]; + } + return null; + } + /** + * @private + */ + function collectLoop(loop, loops, detach) { + loops.push(loop); + if (detach) { + detachLoop(loop); + } + } + /** + * @private + */ + function follow(connections, loops, detach) { + //for a given point, follow the paths that connect to each other to form loops + for (var p in connections) { + var linkedPaths = connections[p]; + if (linkedPaths) { + var loopModel = { + paths: {}, + insideCount: 0 + }; + var firstLink = linkedPaths[0]; + var currLink = firstLink; + while (true) { + var currPath = currLink.path; + currPath.reversed = currLink.reversed; + var id = model.getSimilarPathId(loopModel, currPath.pathId); + loopModel.paths[id] = currPath; + if (!connections[currLink.nextConnection]) + break; + var nextLink = getOpposedLink(connections[currLink.nextConnection], currLink.path); + connections[currLink.nextConnection] = null; + if (!nextLink) + break; + currLink = nextLink; + if (currLink.path === firstLink.path) { + //loop is closed + collectLoop(loopModel, loops, detach); + break; + } + } + } + } + } + /** + * Find paths that have common endpoints and form loops. + * + * @param modelContext The model to search for loops. + * @param options Optional options object. + * @returns A new model with child models ranked according to their containment within other found loops. The paths of models will be IPathDirectionalWithPrimeContext. + */ + function findLoops(modelContext, options) { + var loops = []; + var connections = {}; + var result = { models: {} }; + var opts = { + pointMatchingDistance: .005 + }; + MakerJs.extendObject(opts, options); + function getLinkedPathsOnConnectionPoint(p) { + var serializedPoint = MakerJs.point.serialize(p, .0001); //TODO convert to pointmap + if (!(serializedPoint in connections)) { + connections[serializedPoint] = []; + } + return connections[serializedPoint]; + } + function spin(callback) { + for (var i = 0; i < loops.length; i++) { + callback(loops[i]); + } + } + function getModelByDepth(depth) { + var id = depth.toString(); + if (!(id in result.models)) { + var newModel = { models: {} }; + result.models[id] = newModel; + } + return result.models[id]; + } + //todo: remove dead ends first + model.originate(modelContext); + //find loops by looking at all paths in this model + model.walkPaths(modelContext, function (modelContext, pathId, pathContext) { + if (!pathContext) + return; + var safePath = MakerJs.cloneObject(pathContext); + safePath.pathId = pathId; + safePath.modelContext = modelContext; + //circles are loops by nature + if (safePath.type == MakerJs.pathType.Circle) { + var loopModel = { + paths: {}, + insideCount: 0 + }; + loopModel.paths[pathId] = safePath; + collectLoop(loopModel, loops, opts.removeFromOriginal); + } + else { + //gather both endpoints from all non-circle segments + safePath.endPoints = MakerJs.point.fromPathEnds(safePath); + for (var i = 2; i--;) { + var linkedPath = { + path: safePath, + nextConnection: MakerJs.point.serialize(safePath.endPoints[1 - i], .0001), + reversed: i != 0 + }; + getLinkedPathsOnConnectionPoint(safePath.endPoints[i]).push(linkedPath); + } + } + }); + //follow paths to find loops + follow(connections, loops, opts.removeFromOriginal); + //now we have all loops, we need to see which are inside of each other + spin(function (firstLoop) { + var firstPath = getFirstPathFromModel(firstLoop); + if (!firstPath) + return; + spin(function (secondLoop) { + if (firstLoop === secondLoop) + return; + if (model.isPathInsideModel(firstPath, secondLoop)) { + firstLoop.insideCount++; + } + }); + }); + //now we can group similar loops by their nested level + spin(function (loop) { + var depthModel = getModelByDepth(loop.insideCount); + var id = model.countChildModels(depthModel).toString(); + delete loop.insideCount; + depthModel.models[id] = loop; + }); + return result; + } + model.findLoops = findLoops; + /** + * Remove all paths in a loop model from the model(s) which contained them. + * + * @param loopToDetach The model to search for loops. + */ + function detachLoop(loopToDetach) { + for (var id in loopToDetach.paths) { + var pathDirectionalWithOriginalContext = loopToDetach.paths[id]; + var primeModel = pathDirectionalWithOriginalContext.modelContext; + if (primeModel && primeModel.paths && pathDirectionalWithOriginalContext.pathId) { + delete primeModel.paths[pathDirectionalWithOriginalContext.pathId]; + } + } + } + model.detachLoop = detachLoop; + /** + * @private + */ + var DeadEndFinder = (function () { + function DeadEndFinder(pointMatchingDistance) { + this.pointMatchingDistance = pointMatchingDistance; + function comparePoint(point1, point2) { + var distance = MakerJs.measure.pointDistance(point1, point2); + return distance <= pointMatchingDistance; + } + this.pointMap = new MakerJs.Collector(comparePoint); + } + DeadEndFinder.prototype.removeMatchingPathRefs = function (a, b) { + //see if any are the same in each array + for (var ai = 0; ai < a.length; ai++) { + for (var bi = 0; bi < b.length; bi++) { + if (a[ai] === b[bi]) { + var pathRef = a[ai]; + a.splice(ai, 1); + b.splice(bi, 1); + return pathRef; + } + } + } + return null; + }; + DeadEndFinder.prototype.removePathRef = function (pathRef) { + var _this = this; + var removePath = function (p) { + var pathRefs = _this.pointMap.findCollection(p); + for (var i = 0; i < pathRefs.length; i++) { + if (pathRefs[i] === pathRef) { + pathRefs.splice(i, 1); + return; + } + } + }; + for (var i = 2; i--;) { + removePath(pathRef.endPoints[i]); + } + }; + DeadEndFinder.prototype.removeDeadEnd = function () { + var found = false; + var oddPathRefs = null; + for (var i = 0; i < this.pointMap.collections.length; i++) { + var pathRefs = this.pointMap.collections[i].items; + if (pathRefs.length % 2 == 0) + continue; + if (pathRefs.length == 1) { + var pathRef = pathRefs[0]; + this.removePathRef(pathRef); + delete pathRef.modelContext.paths[pathRef.pathId]; + found = true; + } + else { + if (!oddPathRefs) { + //save this for another iteration + oddPathRefs = pathRefs; + } + else { + //compare with the saved + var pathRef = this.removeMatchingPathRefs(oddPathRefs, pathRefs); + if (pathRef) { + delete pathRef.modelContext.paths[pathRef.pathId]; + found = true; + //clear the saved + oddPathRefs = null; + } + } + } + } + return found; + }; + return DeadEndFinder; + }()); + /** + * 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, pointMatchingDistance) { + if (pointMatchingDistance === void 0) { pointMatchingDistance = .005; } + var serializedPointAccuracy = .0001; + var deadEndFinder = new DeadEndFinder(pointMatchingDistance); + model.walkPaths(modelContext, function (modelContext, pathId, pathContext) { + var endPoints = MakerJs.point.fromPathEnds(pathContext); + if (!endPoints) + return; + var pathRef = { modelContext: modelContext, pathId: pathId, endPoints: endPoints }; + for (var i = 2; i--;) { + deadEndFinder.pointMap.addItemToCollection(endPoints[i], pathRef); + } + }); + while (deadEndFinder.removeDeadEnd()) + ; + return modelContext; + } + model.removeDeadEnds = removeDeadEnds; + })(model = MakerJs.model || (MakerJs.model = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var exporter; + (function (exporter) { + /** + * Class for an XML tag. + * @private + */ + var XmlTag = (function () { + /** + * @param name Name of the XML tag. + * @param attrs Optional attributes for the tag. + */ + function XmlTag(name, attrs) { + this.name = name; + this.attrs = attrs; + /** + * Text between the opening and closing tags. + */ + this.innerText = ''; + } + /** + * Escapes certain characters within a string so that it can appear in a tag or its attribute. + * + * @returns Escaped string. + */ + XmlTag.escapeString = function (value) { + var escape = { + '&': '&', + '<': '<', + '>': '>', + '"': '"' + }; + for (var code in escape) { + //.split then .join is a 'replace' + value = value.split(code).join(escape[code]); + } + return value; + }; + /** + * Get the opening tag. + * + * @param selfClose Flag to determine if opening tag should be self closing. + */ + XmlTag.prototype.getOpeningTag = function (selfClose) { + var attrs = ''; + function outputAttr(attrName, attrValue) { + if (attrValue == null || typeof attrValue === 'undefined') + return; + if (typeof attrValue === 'string') { + attrValue = XmlTag.escapeString(attrValue); + } + attrs += ' ' + attrName + '="' + attrValue + '"'; + } + for (var name in this.attrs) { + outputAttr(name, this.attrs[name]); + } + return '<' + this.name + attrs + (selfClose ? '/' : '') + '>'; + }; + /** + * Get the inner text. + */ + XmlTag.prototype.getInnerText = function () { + if (this.innerTextEscaped) { + return this.innerText; + } + else { + return XmlTag.escapeString(this.innerText); + } + }; + /** + * Get the closing tag. + */ + XmlTag.prototype.getClosingTag = function () { + return ''; + }; + /** + * Output the entire tag as a string. + */ + XmlTag.prototype.toString = function () { + var selfClose = !this.innerText; + if (selfClose) { + return this.getOpeningTag(true); + } + else { + return this.getOpeningTag(false) + this.getInnerText() + this.getClosingTag(); + } + }; + return XmlTag; + }()); + exporter.XmlTag = XmlTag; + })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var exporter; + (function (exporter) { + /** + * @private + */ + function wrap(prefix, content, condition) { + if (condition) { + return prefix + '(' + content + ')'; + } + else { + return content; + } + } + /** + * @private + */ + function facetSizeToResolution(arcOrCircle, facetSize) { + if (!facetSize) + return; + var circle = new MakerJs.paths.Circle([0, 0], arcOrCircle.radius); + var length = MakerJs.measure.pathLength(circle); + if (!length) + return; + return length / facetSize; + } + /** + * @private + */ + function pathsToOpenJsCad(modelContext, facetSize) { + var head = ''; + var tail = ''; + var first = true; + var exit = false; + var reverseTail = false; + var beginMap = {}; + beginMap[MakerJs.pathType.Circle] = function (circle, dirPath) { + var circleOptions = { + center: MakerJs.point.rounded(circle.origin), + radius: circle.radius, + resolution: facetSizeToResolution(circle, facetSize) + }; + head = wrap('CAG.circle', JSON.stringify(circleOptions), true); + exit = true; + }; + beginMap[MakerJs.pathType.Line] = function (line, dirPath) { + head = wrap('new CSG.Path2D', JSON.stringify(dirPath.reversed ? [dirPath.endPoints[1], dirPath.endPoints[0]] : dirPath.endPoints), true); + }; + beginMap[MakerJs.pathType.Arc] = function (arc, dirPath) { + var endAngle = MakerJs.angle.ofArcEnd(arc); + if (dirPath.reversed) { + reverseTail = true; + } + var arcOptions = { + center: MakerJs.point.rounded(arc.origin), + radius: arc.radius, + startangle: arc.startAngle, + endangle: endAngle, + resolution: facetSizeToResolution(arc, facetSize) + }; + head = wrap('new CSG.Path2D.arc', JSON.stringify(arcOptions), true); + }; + var appendMap = {}; + appendMap[MakerJs.pathType.Line] = function (line, dirPath) { + var reverse = (reverseTail != dirPath.reversed); + var endPoint = MakerJs.point.rounded(dirPath.endPoints[reverse ? 0 : 1]); + append(wrap('.appendPoint', JSON.stringify(endPoint), true)); + }; + appendMap[MakerJs.pathType.Arc] = function (arc, dirPath) { + var reverse = (reverseTail != dirPath.reversed); + var endAngle = MakerJs.angle.ofArcEnd(arc); + var arcOptions = { + radius: arc.radius, + clockwise: reverse, + large: Math.abs(endAngle - arc.startAngle) > 180, + resolution: facetSizeToResolution(arc, facetSize) + }; + var endPoint = MakerJs.point.rounded(dirPath.endPoints[reverse ? 0 : 1]); + append(wrap('.appendArc', JSON.stringify(endPoint) + ',' + JSON.stringify(arcOptions), true)); + }; + function append(s) { + if (reverseTail) { + tail = s + tail; + } + else { + tail += s; + } + } + for (var pathId in modelContext.paths) { + var pathContext = modelContext.paths[pathId]; + var fn = first ? beginMap[pathContext.type] : appendMap[pathContext.type]; + if (fn) { + fn(pathContext, pathContext); + } + if (exit) { + return head; + } + first = false; + } + return head + tail + '.close().innerToCAG()'; + } + /** + * Creates a string of JavaScript code for execution with the OpenJsCad engine. + * + * @param modelToExport Model object to export. + * @param options Export options object. + * @param options.extrusion Height of 3D extrusion. + * @param options.resolution Size of facets. + * @returns String of JavaScript containing a main() function for OpenJsCad. + */ + function toOpenJsCad(modelToExport, options) { + if (!modelToExport) + return ''; + var all = ''; + var depth = 0; + var depthModel; + var opts = { + extrusion: 1, + pointMatchingDistance: .005, + functionName: 'main' + }; + MakerJs.extendObject(opts, options); + if (modelToExport.exporterOptions) { + MakerJs.extendObject(opts, modelToExport.exporterOptions['toOpenJsCad']); + } + //pass options back into calling object + MakerJs.extendObject(options, opts); + if (opts && opts.modelMap) { + all = exportFromOptionsMap(modelToExport, opts.modelMap); + } + if (!all) { + var result = []; + var loops = MakerJs.model.findLoops(modelToExport, opts); + while (depthModel = loops.models[depth]) { + var union = ''; + for (var modelId in depthModel.models) { + var subModel = depthModel.models[modelId]; + union += wrap('.union', pathsToOpenJsCad(subModel, opts.facetSize), union); + } + var operator = (depth % 2 == 0) ? '.union' : '.subtract'; + result.push(wrap(operator, union, result.length)); + depth++; + } + var extrudeOptions = { offset: [0, 0, opts.extrusion] }; + result.push(wrap('.extrude', JSON.stringify(extrudeOptions), true)); + all = 'return ' + result.join(''); + } + return 'function ' + opts.functionName + '(){' + all + ';}'; + } + exporter.toOpenJsCad = toOpenJsCad; + function exportFromOptionsMap(modelToExport, optionsMap) { + if (!modelToExport.models) + return; + var result = []; + var union = []; + var i = 0; + for (var key in optionsMap) { + var fName = 'f' + i; + var options = optionsMap[key]; + options.functionName = fName; + var childModel = modelToExport.models[key]; + if (childModel) { + result.push(toOpenJsCad(childModel, options)); + union.push('(' + fName + '())'); + } + i++; + } + if (!result.length) + return; + result.push('return ' + union.join('.union')); + return result.join(' '); + } + /** + * Executes a JavaScript string with the OpenJsCad engine - converts 2D to 3D. + * + * @param modelToExport Model object to export. + * @param options Export options object. + * @param options.extrusion Height of 3D extrusion. + * @param options.resolution Size of facets. + * @returns String of STL format of 3D object. + */ + function toSTL(modelToExport, options) { + if (options === void 0) { options = {}; } + if (!modelToExport) + return ''; + var script = toOpenJsCad(modelToExport, options); + script += 'return ' + options.functionName + '();'; + var f = new Function(script); + var csg = f(); + return csg.toStlString(); + } + exporter.toSTL = toSTL; + })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var exporter; + (function (exporter) { + /** + * Renders an item in SVG markup. + * + * @param itemToExport Item to render: may be a path, an array of paths, or a model object. + * @param options Rendering options object. + * @param options.annotate Boolean to indicate that the id's of paths should be rendered as SVG text elements. + * @param options.origin point object for the rendered reference origin. + * @param options.scale Number to scale the SVG rendering. + * @param options.stroke String color of the rendered paths. + * @param options.strokeWidth String numeric width and optional units of the rendered paths. + * @param options.units String of the unit system. May be omitted. See makerjs.unitType for possible values. + * @param options.useSvgPathOnly Boolean to use SVG path elements instead of line, circle etc. + * @returns String of XML / SVG content. + */ + function toSVG(itemToExport, options) { + var opts = { + annotate: false, + origin: null, + scale: 1, + stroke: "#000", + strokeWidth: '0.25mm', + fontSize: '9pt', + useSvgPathOnly: true, + viewBox: true + }; + MakerJs.extendObject(opts, options); + var modelToExport; + var itemToExportIsModel = MakerJs.isModel(itemToExport); + if (itemToExportIsModel) { + modelToExport = itemToExport; + if (modelToExport.exporterOptions) { + MakerJs.extendObject(opts, modelToExport.exporterOptions['toSVG']); + } + } + var elements = []; + var layers = {}; + function append(value, layer) { + if (layer) { + if (!(layer in layers)) { + layers[layer] = []; + } + layers[layer].push(value); + } + else { + elements.push(value); + } + } + function fixPoint(pointToFix) { + //in DXF Y increases upward. in SVG, Y increases downward + var pointMirroredY = MakerJs.point.mirror(pointToFix, false, true); + return MakerJs.point.scale(pointMirroredY, opts.scale); + } + function fixPath(pathToFix, origin) { + //mirror creates a copy, so we don't modify the original + var mirrorY = MakerJs.path.mirror(pathToFix, false, true); + return MakerJs.path.moveRelative(MakerJs.path.scale(mirrorY, opts.scale), origin); + } + function createElement(tagname, attrs, layer, innerText) { + if (innerText === void 0) { innerText = null; } + attrs['vector-effect'] = 'non-scaling-stroke'; + var tag = new exporter.XmlTag(tagname, attrs); + if (innerText) { + tag.innerText = innerText; + } + append(tag.toString(), layer); + } + function drawText(id, textPoint) { + createElement("text", { + "id": id + "_text", + "x": textPoint[0], + "y": textPoint[1] + }, null, id); + } + function drawPath(id, x, y, d, layer, textPoint) { + createElement("path", { + "id": id, + "d": ["M", MakerJs.round(x), MakerJs.round(y)].concat(d).join(" ") + }, layer); + if (opts.annotate) { + drawText(id, textPoint); + } + } + var map = {}; + map[MakerJs.pathType.Line] = function (id, line, origin, layer) { + var start = line.origin; + var end = line.end; + if (opts.useSvgPathOnly) { + drawPath(id, start[0], start[1], [MakerJs.round(end[0]), MakerJs.round(end[1])], layer, MakerJs.point.middle(line)); + } + else { + createElement("line", { + "id": id, + "x1": MakerJs.round(start[0]), + "y1": MakerJs.round(start[1]), + "x2": MakerJs.round(end[0]), + "y2": MakerJs.round(end[1]) + }, layer); + if (opts.annotate) { + drawText(id, MakerJs.point.middle(line)); + } + } + }; + map[MakerJs.pathType.Circle] = function (id, circle, origin, layer) { + var center = circle.origin; + if (opts.useSvgPathOnly) { + circleInPaths(id, center, circle.radius, layer); + } + else { + createElement("circle", { + "id": id, + "r": circle.radius, + "cx": MakerJs.round(center[0]), + "cy": MakerJs.round(center[1]) + }, layer); + } + if (opts.annotate) { + drawText(id, center); + } + }; + function circleInPaths(id, center, radius, layer) { + var d = ['m', -radius, 0]; + function halfCircle(sign) { + d.push('a'); + svgArcData(d, radius, [2 * radius * sign, 0]); + } + halfCircle(1); + halfCircle(-1); + drawPath(id, center[0], center[1], d, layer, center); + } + function svgArcData(d, radius, endPoint, largeArc, decreasing) { + var end = endPoint; + d.push(radius, radius); + d.push(0); //0 = x-axis rotation + d.push(largeArc ? 1 : 0); //large arc=1, small arc=0 + d.push(decreasing ? 0 : 1); //sweep-flag 0=decreasing, 1=increasing + d.push(MakerJs.round(end[0]), MakerJs.round(end[1])); + } + map[MakerJs.pathType.Arc] = function (id, arc, origin, layer) { + var arcPoints = MakerJs.point.fromArc(arc); + if (MakerJs.measure.isPointEqual(arcPoints[0], arcPoints[1])) { + circleInPaths(id, arc.origin, arc.radius, layer); + } + else { + var d = ['A']; + svgArcData(d, arc.radius, arcPoints[1], Math.abs(arc.endAngle - arc.startAngle) > 180, arc.startAngle > arc.endAngle); + drawPath(id, arcPoints[0][0], arcPoints[0][1], d, layer, MakerJs.point.middle(arc)); + } + }; + //fixup options + //measure the item to move it into svg area + if (itemToExportIsModel) { + modelToExport = itemToExport; + } + else if (Array.isArray(itemToExport)) { + //issue: this won't handle an array of models + modelToExport = { paths: itemToExport }; + } + else if (MakerJs.isPath(itemToExport)) { + modelToExport = { paths: { modelToMeasure: itemToExport } }; + } + var size = MakerJs.measure.modelExtents(modelToExport); + //try to get the unit system from the itemToExport + if (!opts.units) { + var unitSystem = exporter.tryGetModelUnits(itemToExport); + if (unitSystem) { + opts.units = unitSystem; + } + } + //convert unit system (if it exists) into SVG's units. scale if necessary. + var useSvgUnit = exporter.svgUnit[opts.units]; + if (useSvgUnit && opts.viewBox) { + opts.scale *= useSvgUnit.scaleConversion; + } + if (!opts.origin) { + var left = 0; + if (size.low[0] < 0) { + left = -size.low[0] * opts.scale; + } + opts.origin = [left, size.high[1] * opts.scale]; + } + //also pass back to options parameter + MakerJs.extendObject(options, opts); + //begin svg output + var modelGroup = new exporter.XmlTag('g'); + function beginModel(id, modelContext) { + modelGroup.attrs = { id: id }; + append(modelGroup.getOpeningTag(false), modelContext.layer); + } + function endModel(modelContext) { + append(modelGroup.getClosingTag(), modelContext.layer); + } + var svgAttrs; + if (opts.viewBox) { + var width = MakerJs.round(size.high[0] - size.low[0]) * opts.scale; + var height = MakerJs.round(size.high[1] - size.low[1]) * opts.scale; + var viewBox = [0, 0, width, height]; + var unit = useSvgUnit ? useSvgUnit.svgUnitType : ''; + svgAttrs = { + width: width + unit, + height: height + unit, + viewBox: viewBox.join(' ') + }; + } + var svgTag = new exporter.XmlTag('svg', MakerJs.extendObject(svgAttrs || {}, opts.svgAttrs)); + append(svgTag.getOpeningTag(false)); + var svgGroup = new exporter.XmlTag('g', { + id: 'svgGroup', + stroke: opts.stroke, + "stroke-width": opts.strokeWidth, + "stroke-linecap": "round", + "fill": "none", + "font-size": opts.fontSize + }); + append(svgGroup.getOpeningTag(false)); + var exp = new exporter.Exporter(map, fixPoint, fixPath, beginModel, endModel); + exp.exportItem('0', itemToExport, opts.origin); + //export layers as groups + for (var layer in layers) { + var layerGroup = new exporter.XmlTag('g', { id: layer }); + for (var i = 0; i < layers[layer].length; i++) { + layerGroup.innerText += layers[layer][i]; + } + layerGroup.innerTextEscaped = true; + append(layerGroup.toString()); + } + append(svgGroup.getClosingTag()); + append(svgTag.getClosingTag()); + return elements.join(''); + } + exporter.toSVG = toSVG; + /** + * Map of MakerJs unit system to SVG unit system + */ + exporter.svgUnit = {}; + //SVG Coordinate Systems, Transformations and Units documentation: + //http://www.w3.org/TR/SVG/coords.html + //The supported length unit identifiers are: em, ex, px, pt, pc, cm, mm, in, and percentages. + exporter.svgUnit[MakerJs.unitType.Inch] = { svgUnitType: "in", scaleConversion: 1 }; + exporter.svgUnit[MakerJs.unitType.Millimeter] = { svgUnitType: "mm", scaleConversion: 1 }; + exporter.svgUnit[MakerJs.unitType.Centimeter] = { svgUnitType: "cm", scaleConversion: 1 }; + //Add conversions for all unitTypes + exporter.svgUnit[MakerJs.unitType.Foot] = { svgUnitType: "in", scaleConversion: 12 }; + exporter.svgUnit[MakerJs.unitType.Meter] = { svgUnitType: "cm", scaleConversion: 100 }; + })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var ConnectTheDots = (function () { + function ConnectTheDots(isClosed, points) { + var _this = this; + this.paths = {}; + var connect = function (a, b) { + _this.paths["ShapeLine" + i] = new MakerJs.paths.Line(points[a], points[b]); + }; + for (var i = 1; i < points.length; i++) { + connect(i - 1, i); + } + if (isClosed && points.length > 2) { + connect(points.length - 1, 0); + } + } + return ConnectTheDots; + }()); + models.ConnectTheDots = ConnectTheDots; + ConnectTheDots.metaParameters = [ + { title: "closed", type: "bool", value: true }, + { + title: "points", type: "select", value: [ + [[0, 0], [40, 40], [60, 20], [100, 100], [60, 60], [40, 80]], + [[0, 0], [100, 0], [50, 87]] + ] + } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var Polygon = (function () { + function Polygon(numberOfSides, radius, firstCornerAngleInDegrees, circumscribed) { + this.paths = {}; + this.paths = new models.ConnectTheDots(true, Polygon.getPoints(numberOfSides, radius, firstCornerAngleInDegrees, circumscribed)).paths; + } + Polygon.circumscribedRadius = function (radius, angleInRadians) { + return radius / Math.cos(angleInRadians / 2); + }; + Polygon.getPoints = function (numberOfSides, radius, firstCornerAngleInDegrees, circumscribed) { + if (firstCornerAngleInDegrees === void 0) { firstCornerAngleInDegrees = 0; } + if (circumscribed === void 0) { circumscribed = false; } + var points = []; + var a1 = MakerJs.angle.toRadians(firstCornerAngleInDegrees); + var a = 2 * Math.PI / numberOfSides; + if (circumscribed) { + radius = Polygon.circumscribedRadius(radius, a); + } + for (var i = 0; i < numberOfSides; i++) { + points.push(MakerJs.point.fromPolar(a * i + a1, radius)); + } + return points; + }; + return Polygon; + }()); + models.Polygon = Polygon; + Polygon.metaParameters = [ + { title: "number of sides", type: "range", min: 3, max: 24, value: 6 }, + { title: "radius", type: "range", min: 1, max: 100, value: 50 }, + { title: "offset angle", type: "range", min: 0, max: 180, value: 0 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var BoltCircle = (function () { + function BoltCircle(boltRadius, holeRadius, boltCount, firstBoltAngleInDegrees) { + if (firstBoltAngleInDegrees === void 0) { firstBoltAngleInDegrees = 0; } + this.paths = {}; + var points = models.Polygon.getPoints(boltCount, boltRadius, firstBoltAngleInDegrees); + for (var i = 0; i < boltCount; i++) { + this.paths["bolt " + i] = new MakerJs.paths.Circle(points[i], holeRadius); + } + } + return BoltCircle; + }()); + models.BoltCircle = BoltCircle; + BoltCircle.metaParameters = [ + { title: "bolt circle radius", type: "range", min: 1, max: 100, value: 50 }, + { title: "hole radius", type: "range", min: 1, max: 50, value: 5 }, + { title: "bolt count", type: "range", min: 3, max: 24, value: 12 }, + { title: "offset angle", type: "range", min: 0, max: 180, value: 0 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var BoltRectangle = (function () { + function BoltRectangle(width, height, holeRadius) { + this.paths = {}; + var holes = { + "BottomLeft": [0, 0], + "BottomRight": [width, 0], + "TopRight": [width, height], + "TopLeft": [0, height] + }; + for (var id2 in holes) { + this.paths[id2 + "_bolt"] = new MakerJs.paths.Circle(holes[id2], holeRadius); + } + } + return BoltRectangle; + }()); + models.BoltRectangle = BoltRectangle; + BoltRectangle.metaParameters = [ + { title: "width", type: "range", min: 1, max: 100, value: 100 }, + { title: "height", type: "range", min: 1, max: 100, value: 50 }, + { title: "hole radius", type: "range", min: 1, max: 50, value: 5 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var Dome = (function () { + function Dome(width, height, radius) { + this.paths = {}; + var w2 = width / 2; + if (radius < 0) + radius = 0; + if (radius === void 0) + radius = w2; + radius = Math.min(radius, w2); + radius = Math.min(radius, height); + var wt = Math.max(w2 - radius, 0); + var hr = Math.max(height - radius, 0); + this.paths["Bottom"] = new MakerJs.paths.Line([-w2, 0], [w2, 0]); + if (hr) { + this.paths["Left"] = new MakerJs.paths.Line([-w2, 0], [-w2, hr]); + this.paths["Right"] = new MakerJs.paths.Line([w2, 0], [w2, hr]); + } + if (radius > 0) { + this.paths["TopLeft"] = new MakerJs.paths.Arc([-wt, hr], radius, 90, 180); + this.paths["TopRight"] = new MakerJs.paths.Arc([wt, hr], radius, 0, 90); + } + if (wt) { + this.paths["Top"] = new MakerJs.paths.Line([-wt, height], [wt, height]); + } + } + return Dome; + }()); + models.Dome = Dome; + Dome.metaParameters = [ + { title: "width", type: "range", min: 1, max: 100, value: 50 }, + { title: "height", type: "range", min: 1, max: 100, value: 100 }, + { title: "radius", type: "range", min: 0, max: 50, value: 25 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var RoundRectangle = (function () { + function RoundRectangle(width, height, radius) { + this.paths = {}; + var maxRadius = Math.min(height, width) / 2; + radius = Math.min(radius, maxRadius); + var wr = width - radius; + var hr = height - radius; + if (radius > 0) { + this.paths["BottomLeft"] = new MakerJs.paths.Arc([radius, radius], radius, 180, 270); + this.paths["BottomRight"] = new MakerJs.paths.Arc([wr, radius], radius, 270, 0); + this.paths["TopRight"] = new MakerJs.paths.Arc([wr, hr], radius, 0, 90); + this.paths["TopLeft"] = new MakerJs.paths.Arc([radius, hr], radius, 90, 180); + } + if (wr - radius > 0) { + this.paths["Bottom"] = new MakerJs.paths.Line([radius, 0], [wr, 0]); + this.paths["Top"] = new MakerJs.paths.Line([wr, height], [radius, height]); + } + if (hr - radius > 0) { + this.paths["Right"] = new MakerJs.paths.Line([width, radius], [width, hr]); + this.paths["Left"] = new MakerJs.paths.Line([0, hr], [0, radius]); + } + } + return RoundRectangle; + }()); + models.RoundRectangle = RoundRectangle; + RoundRectangle.metaParameters = [ + { title: "width", type: "range", min: 1, max: 100, value: 50 }, + { title: "height", type: "range", min: 1, max: 100, value: 100 }, + { title: "radius", type: "range", min: 0, max: 50, value: 11 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var Oval = (function () { + function Oval(width, height) { + this.paths = {}; + this.paths = new models.RoundRectangle(width, height, Math.min(height / 2, width / 2)).paths; + } + return Oval; + }()); + models.Oval = Oval; + Oval.metaParameters = [ + { title: "width", type: "range", min: 1, max: 100, value: 50 }, + { title: "height", type: "range", min: 1, max: 100, value: 100 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var OvalArc = (function () { + function OvalArc(startAngle, endAngle, sweepRadius, slotRadius, selfIntersect, isolateCaps) { + var _this = this; + if (selfIntersect === void 0) { selfIntersect = false; } + if (isolateCaps === void 0) { isolateCaps = false; } + this.paths = {}; + if (slotRadius <= 0 || sweepRadius <= 0) + return; + startAngle = MakerJs.angle.noRevolutions(startAngle); + endAngle = MakerJs.angle.noRevolutions(endAngle); + if (MakerJs.round(startAngle - endAngle) == 0) + return; + if (endAngle < startAngle) + endAngle += 360; + var capModel = this; + if (isolateCaps) { + this.models = { "Caps": { paths: {} } }; + capModel = this.models["Caps"]; + } + var addCap = function (id, tiltAngle, offsetStartAngle, offsetEndAngle) { + return capModel.paths[id] = new MakerJs.paths.Arc(MakerJs.point.fromPolar(MakerJs.angle.toRadians(tiltAngle), sweepRadius), slotRadius, tiltAngle + offsetStartAngle, tiltAngle + offsetEndAngle); + }; + var addSweep = function (id, offsetRadius) { + return _this.paths[id] = new MakerJs.paths.Arc([0, 0], sweepRadius + offsetRadius, startAngle, endAngle); + }; + addSweep("Outer", slotRadius); + var hasInner = (sweepRadius - slotRadius) > 0; + if (hasInner) { + addSweep("Inner", -slotRadius); + } + var caps = []; + caps.push(addCap("StartCap", startAngle, 180, 0)); + caps.push(addCap("EndCap", endAngle, 0, 180)); + //the distance between the cap origins + var d = MakerJs.measure.pointDistance(caps[0].origin, caps[1].origin); + if ((d / 2) < slotRadius) { + //the caps intersect + var int = MakerJs.path.intersection(caps[0], caps[1]); + if (int) { + if (!hasInner || !selfIntersect) { + caps[0].startAngle = int.path1Angles[0]; + caps[1].endAngle = int.path2Angles[0]; + } + if (!selfIntersect && hasInner && int.intersectionPoints.length == 2) { + addCap("StartCap2", startAngle, 180, 0).endAngle = int.path1Angles[1]; + addCap("EndCap2", endAngle, 0, 180).startAngle = int.path2Angles[1] + 360; + } + } + } + } + return OvalArc; + }()); + models.OvalArc = OvalArc; + OvalArc.metaParameters = [ + { title: "start angle", type: "range", min: -360, max: 360, step: 1, value: 180 }, + { title: "end angle", type: "range", min: -360, max: 360, step: 1, value: 0 }, + { title: "sweep", type: "range", min: 0, max: 100, step: 1, value: 50 }, + { title: "radius", type: "range", min: 0, max: 100, step: 1, value: 15 }, + { title: "self intersect", type: "bool", value: false } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var Rectangle = (function () { + function Rectangle(width, height) { + this.paths = {}; + this.paths = new models.ConnectTheDots(true, [[0, 0], [width, 0], [width, height], [0, height]]).paths; + } + return Rectangle; + }()); + models.Rectangle = Rectangle; + Rectangle.metaParameters = [ + { title: "width", type: "range", min: 1, max: 100, value: 50 }, + { title: "height", type: "range", min: 1, max: 100, value: 100 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var Ring = (function () { + function Ring(outerRadius, innerRadius) { + this.paths = {}; + var radii = { + "Ring_outer": outerRadius, + "Ring_inner": innerRadius + }; + for (var id in radii) { + this.paths[id] = new MakerJs.paths.Circle(MakerJs.point.zero(), radii[id]); + } + } + return Ring; + }()); + models.Ring = Ring; + Ring.metaParameters = [ + { title: "outer radius", type: "range", min: 0, max: 100, step: 1, value: 50 }, + { title: "inner radius", type: "range", min: 0, max: 100, step: 1, value: 20 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var SCurve = (function () { + function SCurve(width, height) { + this.paths = {}; + function findRadius(x, y) { + return x + (y * y - x * x) / (2 * x); + } + var h2 = height / 2; + var w2 = width / 2; + var radius; + var startAngle; + var endAngle; + var arcOrigin; + if (width > height) { + radius = findRadius(h2, w2); + startAngle = 270; + endAngle = 360 - MakerJs.angle.toDegrees(Math.acos(w2 / radius)); + arcOrigin = [0, radius]; + } + else { + radius = findRadius(w2, h2); + startAngle = 180 - MakerJs.angle.toDegrees(Math.asin(h2 / radius)); + endAngle = 180; + arcOrigin = [radius, 0]; + } + var curve = new MakerJs.paths.Arc(arcOrigin, radius, startAngle, endAngle); + this.paths['curve_start'] = curve; + this.paths['curve_end'] = MakerJs.path.moveRelative(MakerJs.path.mirror(curve, true, true), [width, height]); + } + return SCurve; + }()); + models.SCurve = SCurve; + SCurve.metaParameters = [ + { title: "width", type: "range", min: 1, max: 100, value: 50 }, + { title: "height", type: "range", min: 1, max: 100, value: 100 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var Slot = (function () { + function Slot(origin, endPoint, radius, isolateCaps) { + if (isolateCaps === void 0) { isolateCaps = false; } + this.paths = {}; + var capModel = this; + if (isolateCaps) { + this.models = { "Caps": { paths: {} } }; + capModel = this.models["Caps"]; + } + var a = MakerJs.angle.ofPointInDegrees(origin, endPoint); + var len = MakerJs.measure.pointDistance(origin, endPoint); + this.paths['Top'] = new MakerJs.paths.Line([0, radius], [len, radius]); + this.paths['Bottom'] = new MakerJs.paths.Line([0, -radius], [len, -radius]); + capModel.paths['StartCap'] = new MakerJs.paths.Arc([0, 0], radius, 90, 270); + capModel.paths['EndCap'] = new MakerJs.paths.Arc([len, 0], radius, 270, 90); + MakerJs.model.rotate(this, a, [0, 0]); + this.origin = origin; + } + return Slot; + }()); + models.Slot = Slot; + Slot.metaParameters = [ + { + title: "origin", type: "select", value: [ + [0, 0], + [10, 0], + [10, 10] + ] + }, + { + title: "end", type: "select", value: [ + [80, 0], + [0, 30], + [10, 30] + ] + }, + { title: "radius", type: "range", min: 1, max: 50, value: 10 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var Square = (function () { + function Square(side) { + this.paths = {}; + this.paths = new models.Rectangle(side, side).paths; + } + return Square; + }()); + models.Square = Square; + Square.metaParameters = [ + { title: "side", type: "range", min: 1, max: 100, value: 100 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var Star = (function () { + function Star(numberOfPoints, outerRadius, innerRadius, skipPoints) { + if (skipPoints === void 0) { skipPoints = 2; } + this.paths = {}; + if (!innerRadius) { + innerRadius = outerRadius * Star.InnerRadiusRatio(numberOfPoints, skipPoints); + } + var outerPoints = models.Polygon.getPoints(numberOfPoints, outerRadius); + var innerPoints = models.Polygon.getPoints(numberOfPoints, innerRadius, 180 / numberOfPoints); + var allPoints = []; + for (var i = 0; i < numberOfPoints; i++) { + allPoints.push(outerPoints[i]); + allPoints.push(innerPoints[i]); + } + var model = new models.ConnectTheDots(true, allPoints); + this.paths = model.paths; + delete model.paths; + } + Star.InnerRadiusRatio = function (numberOfPoints, skipPoints) { + //formula from http://www.jdawiseman.com/papers/easymath/surds_star_inner_radius.html + //Cos(Pi()*m/n) / Cos(Pi()*(m-1)/n) + if (numberOfPoints > 0 && skipPoints > 1 && skipPoints < numberOfPoints / 2) { + return Math.cos(Math.PI * skipPoints / numberOfPoints) / Math.cos(Math.PI * (skipPoints - 1) / numberOfPoints); + } + return 0; + }; + return Star; + }()); + models.Star = Star; + Star.metaParameters = [ + { title: "number of sides", type: "range", min: 3, max: 24, value: 8 }, + { title: "outer radius", type: "range", min: 1, max: 100, value: 50 }, + { title: "inner radius", type: "range", min: 0, max: 100, value: 15 }, + { title: "skip points (when inner radius is zero)", type: "range", min: 0, max: 12, value: 2 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); + +},{"clone":2}]},{},[]); diff --git a/archive/node.0.7.0.maker.js b/archive/node.0.7.0.maker.js index 9e562617a..9907ed64e 100644 --- a/archive/node.0.7.0.maker.js +++ b/archive/node.0.7.0.maker.js @@ -165,21 +165,6 @@ var MakerJs; (function (MakerJs) { var angle; (function (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, angle2, accuracy) { - if (accuracy === void 0) { accuracy = .0001; } - var a1 = noRevolutions(angle1); - var a2 = noRevolutions(angle2); - var d = noRevolutions(MakerJs.round(a2 - a1, accuracy)); - return d == 0; - } - angle.areEqual = areEqual; /** * Ensures an angle is not greater than 360 * @@ -236,9 +221,20 @@ var MakerJs; */ function ofArcMiddle(arc, ratio) { if (ratio === void 0) { ratio = .5; } - return arc.startAngle + MakerJs.measure.arcAngle(arc) * ratio; + return arc.startAngle + ofArcSpan(arc) * ratio; } angle.ofArcMiddle = ofArcMiddle; + /** + * Total angle of an arc between its start and end angles. + * + * @param arc The arc to measure. + * @returns Angle of arc. + */ + function ofArcSpan(arc) { + var endAngle = angle.ofArcEnd(arc); + return endAngle - arc.startAngle; + } + angle.ofArcSpan = ofArcSpan; /** * Angle of a line path. * @@ -321,36 +317,6 @@ var MakerJs; return newPoint; } point.add = add; - /** - * 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, b, withinDistance) { - if (!withinDistance) { - return a[0] == b[0] && a[1] == b[1]; - } - else { - var distance = MakerJs.measure.pointDistance(a, b); - return distance <= withinDistance; - } - } - point.areEqual = areEqual; - /** - * 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, b, accuracy) { - if (accuracy === void 0) { accuracy = .0000001; } - return MakerJs.round(a[0], accuracy) == MakerJs.round(b[0], accuracy) && MakerJs.round(a[1], accuracy) == MakerJs.round(b[1], accuracy); - } - point.areEqualRounded = areEqualRounded; /** * Get the average of two points. * @@ -455,6 +421,47 @@ var MakerJs; return result; } point.fromPathEnds = fromPathEnds; + /** + * @private + */ + function verticalIntersectionPoint(verticalLine, nonVerticalSlope) { + var x = verticalLine.origin[0]; + var y = nonVerticalSlope.slope * x + nonVerticalSlope.yIntercept; + return [x, y]; + } + /** + * 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 fromSlopeIntersection(line1, line2, options) { + if (options === void 0) { options = {}; } + var slope1 = MakerJs.measure.lineSlope(line1); + var slope2 = MakerJs.measure.lineSlope(line2); + if (MakerJs.measure.isSlopeEqual(slope1, slope2)) { + //check for overlap + options.out_AreOverlapped = MakerJs.measure.isLineOverlapping(line1, line2, options.excludeTangents); + return null; + } + var pointOfIntersection; + if (!slope1.hasSlope) { + pointOfIntersection = verticalIntersectionPoint(line1, slope2); + } + else if (!slope2.hasSlope) { + pointOfIntersection = verticalIntersectionPoint(line2, slope1); + } + else { + // find intersection by line equation + var x = (slope2.yIntercept - slope1.yIntercept) / (slope1.slope - slope2.slope); + var y = slope1.slope * x + slope1.yIntercept; + pointOfIntersection = [x, y]; + } + return pointOfIntersection; + } + point.fromSlopeIntersection = fromSlopeIntersection; /** * Get the middle point of a path. * @@ -589,38 +596,6 @@ var MakerJs; (function (MakerJs) { var path; (function (path) { - /** - * @private - */ - var pathAreEqualMap = {}; - pathAreEqualMap[MakerJs.pathType.Line] = function (line1, line2, withinPointDistance) { - return (MakerJs.point.areEqual(line1.origin, line2.origin, withinPointDistance) && MakerJs.point.areEqual(line1.end, line2.end, withinPointDistance)) - || (MakerJs.point.areEqual(line1.origin, line2.end, withinPointDistance) && MakerJs.point.areEqual(line1.end, line2.origin, withinPointDistance)); - }; - pathAreEqualMap[MakerJs.pathType.Circle] = function (circle1, circle2, withinPointDistance) { - return MakerJs.point.areEqual(circle1.origin, circle2.origin, withinPointDistance) && circle1.radius == circle2.radius; - }; - pathAreEqualMap[MakerJs.pathType.Arc] = function (arc1, arc2, withinPointDistance) { - return pathAreEqualMap[MakerJs.pathType.Circle](arc1, arc2, withinPointDistance) && MakerJs.angle.areEqual(arc1.startAngle, arc2.startAngle) && MakerJs.angle.areEqual(arc1.endAngle, arc2.endAngle); - }; - /** - * Find out if two paths are equal. - * - * @param a First path. - * @param b Second path. - * @returns true if paths are the same, false if they are not - */ - function areEqual(path1, path2, withinPointDistance) { - var result = false; - if (path1.type == path2.type) { - var fn = pathAreEqualMap[path1.type]; - if (fn) { - result = fn(path1, path2, withinPointDistance); - } - } - return result; - } - path.areEqual = areEqual; /** * Create a clone of a path, mirrored on either or both x and y axes. * @@ -765,7 +740,7 @@ var MakerJs; var breakPathFunctionMap = {}; breakPathFunctionMap[MakerJs.pathType.Arc] = function (arc, pointOfBreak) { var angleAtBreakPoint = MakerJs.angle.ofPointInDegrees(arc.origin, pointOfBreak); - if (MakerJs.angle.areEqual(angleAtBreakPoint, arc.startAngle) || MakerJs.angle.areEqual(angleAtBreakPoint, arc.endAngle)) { + if (MakerJs.measure.isAngleEqual(angleAtBreakPoint, arc.startAngle) || MakerJs.measure.isAngleEqual(angleAtBreakPoint, arc.endAngle)) { return null; } function getAngleStrictlyBetweenArcAngles() { @@ -797,7 +772,7 @@ var MakerJs; return null; }; breakPathFunctionMap[MakerJs.pathType.Line] = function (line, pointOfBreak) { - if (MakerJs.point.areEqual(line.origin, pointOfBreak) || MakerJs.point.areEqual(line.end, pointOfBreak)) { + if (MakerJs.measure.isPointEqual(line.origin, pointOfBreak) || MakerJs.measure.isPointEqual(line.end, pointOfBreak)) { return null; } if (!MakerJs.measure.isBetweenPoints(pointOfBreak, line, true)) { @@ -918,7 +893,7 @@ var MakerJs; this.type = MakerJs.pathType.Arc; } return Arc; - })(); + }()); paths.Arc = Arc; /** * Class for circle path. @@ -955,13 +930,13 @@ var MakerJs; perpendiculars.push(MakerJs.path.rotate(lines[i], 90, midpoint)); } //find intersection of slopes of perpendiculars - this.origin = MakerJs.path.slopeIntersectionPoint(perpendiculars[0], perpendiculars[1]); + this.origin = MakerJs.point.fromSlopeIntersection(perpendiculars[0], perpendiculars[1]); //radius is distance to any of the 3 points this.radius = MakerJs.measure.pointDistance(this.origin, args[0]); } } return Circle; - })(); + }()); paths.Circle = Circle; /** * Class for line path. @@ -976,7 +951,7 @@ var MakerJs; this.type = MakerJs.pathType.Line; } return Line; - })(); + }()); paths.Line = Line; /** * Class for chord, which is simply a line path that connects the endpoints of an arc. @@ -991,7 +966,7 @@ var MakerJs; this.end = arcPoints[1]; } return Chord; - })(); + }()); paths.Chord = Chord; /** * Class for a parallel line path. @@ -1018,7 +993,7 @@ var MakerJs; MakerJs.path.move(this, newOrigin); } return Parallel; - })(); + }()); paths.Parallel = Parallel; })(paths = MakerJs.paths || (MakerJs.paths = {})); })(MakerJs || (MakerJs = {})); @@ -1305,7 +1280,7 @@ var MakerJs; * @private */ function breakAlongForeignPath(segments, overlappedSegments, foreignPath) { - if (MakerJs.path.areEqual(segments[0].path, foreignPath, .0001)) { + if (MakerJs.measure.isPathEqual(segments[0].path, foreignPath, .0001)) { segments[0].overlapped = true; segments[0].duplicate = true; overlappedSegments.push(segments[0]); @@ -1362,7 +1337,7 @@ var MakerJs; var added = 0; function addUniquePoint(pointToAdd) { for (var i = 0; i < pointArray.length; i++) { - if (MakerJs.point.areEqual(pointArray[i], pointToAdd, .000000001)) { + if (MakerJs.measure.isPointEqual(pointArray[i], pointToAdd, .000000001)) { return; } } @@ -1470,7 +1445,7 @@ var MakerJs; */ function checkForEqualOverlaps(crossedPathsA, crossedPathsB, pointMatchingDistance) { function compareSegments(segment1, segment2) { - if (MakerJs.path.areEqual(segment1.path, segment2.path, pointMatchingDistance)) { + if (MakerJs.measure.isPathEqual(segment1.path, segment2.path, pointMatchingDistance)) { segment1.duplicate = segment2.duplicate = true; } } @@ -1607,7 +1582,7 @@ var MakerJs; } }; return Collector; - })(); + }()); MakerJs.Collector = Collector; })(MakerJs || (MakerJs = {})); var MakerJs; @@ -1644,7 +1619,7 @@ var MakerJs; var startAngle = MakerJs.angle.noRevolutions(arc.startAngle); return { startAngle: startAngle, - endAngle: MakerJs.measure.arcAngle(arc) + startAngle + endAngle: MakerJs.angle.ofArcSpan(arc) + startAngle }; } /** @@ -1673,7 +1648,7 @@ var MakerJs; similarCircles.addItemToCollection(circleRef.pathContext, circleRef); }; map[MakerJs.pathType.Line] = function (lineRef) { - var slope = MakerJs.path.getSlope(lineRef.pathContext); + var slope = MakerJs.measure.lineSlope(lineRef.pathContext); similarLines.addItemToCollection(slope, lineRef); }; var opts = { @@ -1788,7 +1763,7 @@ var MakerJs; * @returns Model of straight lines with same endpoints as the arc. */ function straighten(arc, bevel) { - var arcSpan = MakerJs.measure.arcAngle(arc); + var arcSpan = MakerJs.angle.ofArcSpan(arc); var joints = 1; if (arcSpan >= 270) { joints = 4; @@ -1954,18 +1929,96 @@ var MakerJs; var MakerJs; (function (MakerJs) { var measure; - (function (measure_1) { + (function (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 a First angle. + * @param b Second angle. + * @returns true if angles are the same, false if they are not */ - function arcAngle(arc) { - var endAngle = MakerJs.angle.ofArcEnd(arc); - return endAngle - arc.startAngle; + function isAngleEqual(angle1, angle2, accuracy) { + if (accuracy === void 0) { accuracy = .0001; } + var a1 = MakerJs.angle.noRevolutions(angle1); + var a2 = MakerJs.angle.noRevolutions(angle2); + var d = MakerJs.angle.noRevolutions(MakerJs.round(a2 - a1, accuracy)); + return d == 0; } - measure_1.arcAngle = arcAngle; + measure.isAngleEqual = isAngleEqual; + /** + * @private + */ + var pathAreEqualMap = {}; + pathAreEqualMap[MakerJs.pathType.Line] = function (line1, line2, withinPointDistance) { + return (isPointEqual(line1.origin, line2.origin, withinPointDistance) && isPointEqual(line1.end, line2.end, withinPointDistance)) + || (isPointEqual(line1.origin, line2.end, withinPointDistance) && isPointEqual(line1.end, line2.origin, withinPointDistance)); + }; + pathAreEqualMap[MakerJs.pathType.Circle] = function (circle1, circle2, withinPointDistance) { + return isPointEqual(circle1.origin, circle2.origin, withinPointDistance) && circle1.radius == circle2.radius; + }; + pathAreEqualMap[MakerJs.pathType.Arc] = function (arc1, arc2, withinPointDistance) { + return pathAreEqualMap[MakerJs.pathType.Circle](arc1, arc2, withinPointDistance) && isAngleEqual(arc1.startAngle, arc2.startAngle) && isAngleEqual(arc1.endAngle, arc2.endAngle); + }; + /** + * Find out if two paths are equal. + * + * @param a First path. + * @param b Second path. + * @returns true if paths are the same, false if they are not + */ + function isPathEqual(path1, path2, withinPointDistance) { + var result = false; + if (path1.type == path2.type) { + var fn = pathAreEqualMap[path1.type]; + if (fn) { + result = fn(path1, path2, withinPointDistance); + } + } + return result; + } + measure.isPathEqual = isPathEqual; + /** + * 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, b, withinDistance) { + if (!withinDistance) { + return a[0] == b[0] && a[1] == b[1]; + } + else { + var distance = measure.pointDistance(a, b); + return distance <= withinDistance; + } + } + measure.isPointEqual = isPointEqual; + /** + * Check for slope equality. + * + * @param slope1 The ISlope to test. + * @param slope2 The ISlope to check for equality. + * @returns Boolean true if slopes are equal. + */ + function isSlopeEqual(slope1, slope2) { + if (!slope1.hasSlope && !slope2.hasSlope) { + //lines are both vertical, see if x are the same + return MakerJs.round(slope1.line.origin[0] - slope2.line.origin[0]) == 0; + } + if (slope1.hasSlope && slope2.hasSlope && (MakerJs.round(slope1.slope - slope2.slope, .00001) == 0)) { + //lines are parallel, but not vertical, see if y-intercept is the same + return MakerJs.round(slope1.yIntercept - slope2.yIntercept, .00001) == 0; + } + return false; + } + measure.isSlopeEqual = isSlopeEqual; + })(measure = MakerJs.measure || (MakerJs.measure = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var measure; + (function (measure_1) { /** * Check for arc being concave or convex towards a given point. * @@ -2033,7 +2086,7 @@ var MakerJs; */ function isBetweenArcAngles(angleInQuestion, arc, exclusive) { var startAngle = MakerJs.angle.noRevolutions(arc.startAngle); - var span = arcAngle(arc); + var span = MakerJs.angle.ofArcSpan(arc); var endAngle = startAngle + span; angleInQuestion = MakerJs.angle.noRevolutions(angleInQuestion); //computed angles will not be negative, but the arc may have specified a negative angle, so check against one revolution forward and backward @@ -2081,24 +2134,27 @@ var MakerJs; } measure_1.isLineOverlapping = isLineOverlapping; /** - * Check for slope equality. - * - * @param slope1 The ISlope to test. - * @param slope2 The ISlope to check for equality. - * @returns Boolean true if slopes are equal. + * Gets the slope of a line. */ - function isSlopeEqual(slope1, slope2) { - if (!slope1.hasSlope && !slope2.hasSlope) { - //lines are both vertical, see if x are the same - return MakerJs.round(slope1.line.origin[0] - slope2.line.origin[0]) == 0; - } - if (slope1.hasSlope && slope2.hasSlope && (MakerJs.round(slope1.slope - slope2.slope, .00001) == 0)) { - //lines are parallel, but not vertical, see if y-intercept is the same - return MakerJs.round(slope1.yIntercept - slope2.yIntercept, .00001) == 0; + function lineSlope(line) { + var dx = line.end[0] - line.origin[0]; + if (MakerJs.round(dx) == 0) { + return { + line: line, + hasSlope: false + }; } - return false; + var dy = line.end[1] - line.origin[1]; + var slope = dy / dx; + var yIntercept = line.origin[1] - slope * line.origin[0]; + return { + line: line, + hasSlope: true, + slope: slope, + yIntercept: yIntercept + }; } - measure_1.isSlopeEqual = isSlopeEqual; + measure_1.lineSlope = lineSlope; /** * Calculates the distance between two points. * @@ -2180,7 +2236,7 @@ var MakerJs; }; map[MakerJs.pathType.Arc] = function (arc) { map[MakerJs.pathType.Circle](arc); //this sets the value var - var pct = arcAngle(arc) / 360; + var pct = MakerJs.angle.ofArcSpan(arc) / 360; value *= pct; }; var fn = map[pathToMeasure.type]; @@ -2326,7 +2382,7 @@ var MakerJs; } }; return Exporter; - })(); + }()); exporter.Exporter = Exporter; })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); })(MakerJs || (MakerJs = {})); @@ -2604,7 +2660,7 @@ var MakerJs; return null; }; map[MakerJs.pathType.Line][MakerJs.pathType.Line] = function (line1, line2, options) { - var intersectionPoint = slopeIntersectionPoint(line1, line2, options); + var intersectionPoint = MakerJs.point.fromSlopeIntersection(line1, line2, options); if (intersectionPoint) { //we have the point of intersection of endless lines, now check to see if the point is between both segemnts if (MakerJs.measure.isBetweenPoints(intersectionPoint, line1, options.excludeTangents) && MakerJs.measure.isBetweenPoints(intersectionPoint, line2, options.excludeTangents)) { @@ -2683,69 +2739,6 @@ var MakerJs; return null; return anglesWithinArc; } - /** - * Gets the slope of a line. - */ - function getSlope(line) { - var dx = line.end[0] - line.origin[0]; - if (MakerJs.round(dx) == 0) { - return { - line: line, - hasSlope: false - }; - } - var dy = line.end[1] - line.origin[1]; - var slope = dy / dx; - var yIntercept = line.origin[1] - slope * line.origin[0]; - return { - line: line, - hasSlope: true, - slope: slope, - yIntercept: yIntercept - }; - } - path.getSlope = getSlope; - /** - * @private - */ - function verticalIntersectionPoint(verticalLine, nonVerticalSlope) { - var x = verticalLine.origin[0]; - var y = nonVerticalSlope.slope * x + nonVerticalSlope.yIntercept; - return [x, y]; - } - /** - * 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, line2, options) { - if (options === void 0) { options = {}; } - var slope1 = getSlope(line1); - var slope2 = getSlope(line2); - if (MakerJs.measure.isSlopeEqual(slope1, slope2)) { - //check for overlap - options.out_AreOverlapped = MakerJs.measure.isLineOverlapping(line1, line2, options.excludeTangents); - return null; - } - var pointOfIntersection; - if (!slope1.hasSlope) { - pointOfIntersection = verticalIntersectionPoint(line1, slope2); - } - else if (!slope2.hasSlope) { - pointOfIntersection = verticalIntersectionPoint(line2, slope1); - } - else { - // find intersection by line equation - var x = (slope2.yIntercept - slope1.yIntercept) / (slope1.slope - slope2.slope); - var y = slope1.slope * x + slope1.yIntercept; - pointOfIntersection = [x, y]; - } - return pointOfIntersection; - } - path.slopeIntersectionPoint = slopeIntersectionPoint; /** * @private */ @@ -2803,7 +2796,7 @@ var MakerJs; */ function circleToCircle(circle1, circle2, options) { //see if circles are the same - if (circle1.radius == circle2.radius && MakerJs.point.areEqual(circle1.origin, circle2.origin, .0001)) { + if (circle1.radius == circle2.radius && MakerJs.measure.isPointEqual(circle1.origin, circle2.origin, .0001)) { options.out_AreOverlapped = true; return null; } @@ -2903,7 +2896,7 @@ var MakerJs; }; } function check(i1, i2) { - if (MakerJs.point.areEqual(path1Properties[i1].point, path2Properties[i2].point, .0001)) { + if (MakerJs.measure.isPointEqual(path1Properties[i1].point, path2Properties[i2].point, .0001)) { result = [ makeMatch(path1, path1Properties, i1), makeMatch(path2, path2Properties, i2) @@ -2927,7 +2920,7 @@ var MakerJs; return false; } properties[i].shardPoint = circleIntersection.intersectionPoints[0]; - if (MakerJs.point.areEqual(properties[i].point, circleIntersection.intersectionPoints[0], .0001)) { + if (MakerJs.measure.isPointEqual(properties[i].point, circleIntersection.intersectionPoints[0], .0001)) { if (circleIntersection.intersectionPoints.length > 1) { properties[i].shardPoint = circleIntersection.intersectionPoints[1]; } @@ -3004,7 +2997,7 @@ var MakerJs; path.rotate(guideLine, lineAngle, [0, 0]); path.moveRelative(guideLine, filletCenter); //get the intersection point of the slopes of the context line and the perpendicular line. This is where the fillet meets the line. - var intersectionPoint = path.slopeIntersectionPoint(line, guideLine); + var intersectionPoint = MakerJs.point.fromSlopeIntersection(line, guideLine); if (intersectionPoint) { result = { filletAngle: MakerJs.angle.ofPointInDegrees(filletCenter, intersectionPoint), @@ -3175,7 +3168,7 @@ var MakerJs; if (MakerJs.round(results[0].filletAngle - results[1].filletAngle) == 0) return null; var filletArc = new MakerJs.paths.Arc(center, filletRadius, results[0].filletAngle, results[1].filletAngle); - var filletSpan = MakerJs.measure.arcAngle(filletArc); + var filletSpan = MakerJs.angle.ofArcSpan(filletArc); //the algorithm is only valid for fillet less than 180 degrees if (filletSpan == 180) { return null; @@ -3488,7 +3481,7 @@ var MakerJs; return found; }; return DeadEndFinder; - })(); + }()); /** * Remove paths from a model which have endpoints that do not connect to other paths. * @@ -3605,7 +3598,7 @@ var MakerJs; } }; return XmlTag; - })(); + }()); exporter.XmlTag = XmlTag; })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); })(MakerJs || (MakerJs = {})); @@ -3947,7 +3940,7 @@ var MakerJs; } map[MakerJs.pathType.Arc] = function (id, arc, origin, layer) { var arcPoints = MakerJs.point.fromArc(arc); - if (MakerJs.point.areEqual(arcPoints[0], arcPoints[1])) { + if (MakerJs.measure.isPointEqual(arcPoints[0], arcPoints[1])) { circleInPaths(id, arc.origin, arc.radius, layer); } else { @@ -4072,7 +4065,7 @@ var MakerJs; } } return ConnectTheDots; - })(); + }()); models.ConnectTheDots = ConnectTheDots; ConnectTheDots.metaParameters = [ { title: "closed", type: "bool", value: true }, @@ -4112,7 +4105,7 @@ var MakerJs; return points; }; return Polygon; - })(); + }()); models.Polygon = Polygon; Polygon.metaParameters = [ { title: "number of sides", type: "range", min: 3, max: 24, value: 6 }, @@ -4135,7 +4128,7 @@ var MakerJs; } } return BoltCircle; - })(); + }()); models.BoltCircle = BoltCircle; BoltCircle.metaParameters = [ { title: "bolt circle radius", type: "range", min: 1, max: 100, value: 50 }, @@ -4163,7 +4156,7 @@ var MakerJs; } } return BoltRectangle; - })(); + }()); models.BoltRectangle = BoltRectangle; BoltRectangle.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 100 }, @@ -4202,7 +4195,7 @@ var MakerJs; } } return Dome; - })(); + }()); models.Dome = Dome; Dome.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4238,7 +4231,7 @@ var MakerJs; } } return RoundRectangle; - })(); + }()); models.RoundRectangle = RoundRectangle; RoundRectangle.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4257,7 +4250,7 @@ var MakerJs; this.paths = new models.RoundRectangle(width, height, Math.min(height / 2, width / 2)).paths; } return Oval; - })(); + }()); models.Oval = Oval; Oval.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4320,7 +4313,7 @@ var MakerJs; } } return OvalArc; - })(); + }()); models.OvalArc = OvalArc; OvalArc.metaParameters = [ { title: "start angle", type: "range", min: -360, max: 360, step: 1, value: 180 }, @@ -4341,7 +4334,7 @@ var MakerJs; this.paths = new models.ConnectTheDots(true, [[0, 0], [width, 0], [width, height], [0, height]]).paths; } return Rectangle; - })(); + }()); models.Rectangle = Rectangle; Rectangle.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4365,7 +4358,7 @@ var MakerJs; } } return Ring; - })(); + }()); models.Ring = Ring; Ring.metaParameters = [ { title: "outer radius", type: "range", min: 0, max: 100, step: 1, value: 50 }, @@ -4406,7 +4399,7 @@ var MakerJs; this.paths['curve_end'] = MakerJs.path.moveRelative(MakerJs.path.mirror(curve, true, true), [width, height]); } return SCurve; - })(); + }()); models.SCurve = SCurve; SCurve.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4437,7 +4430,7 @@ var MakerJs; this.origin = origin; } return Slot; - })(); + }()); models.Slot = Slot; Slot.metaParameters = [ { @@ -4468,7 +4461,7 @@ var MakerJs; this.paths = new models.Rectangle(side, side).paths; } return Square; - })(); + }()); models.Square = Square; Square.metaParameters = [ { title: "side", type: "range", min: 1, max: 100, value: 100 } @@ -4506,7 +4499,7 @@ var MakerJs; return 0; }; return Star; - })(); + }()); models.Star = Star; Star.metaParameters = [ { title: "number of sides", type: "range", min: 3, max: 24, value: 8 }, diff --git a/archive/node.0.7.1.maker.js b/archive/node.0.7.1.maker.js new file mode 100644 index 000000000..6ab3c6355 --- /dev/null +++ b/archive/node.0.7.1.maker.js @@ -0,0 +1,4536 @@ +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +//https://github.com/Microsoft/maker.js +/** + * Root module for Maker.js. + * + * Example: get a reference to Maker.js + * ``` + * var makerjs = require('makerjs'); + * ``` + * + */ +var MakerJs; +(function (MakerJs) { + //units + /** + * String-based enumeration of unit types: imperial, metric or otherwise. + * A model may specify the unit system it is using, if any. When importing a model, it may have different units. + * Unit conversion function is makerjs.units.conversionScale(). + * Important: If you add to this, you must also add a corresponding conversion ratio in the unit.ts file! + */ + MakerJs.unitType = { + Centimeter: 'cm', + Foot: 'foot', + Inch: 'inch', + Meter: 'm', + Millimeter: 'mm' + }; + /** + * Numeric rounding + * + * Example: round to 3 decimal places + * ``` + * makerjs.round(3.14159, .001); //returns 3.142 + * ``` + * + * @param n The number to round off. + * @param accuracy Optional exemplar of number of decimal places. + */ + function round(n, accuracy) { + if (accuracy === void 0) { accuracy = .0000001; } + var places = 1 / accuracy; + return Math.round(n * places) / places; + } + MakerJs.round = round; + /** + * @private + */ + var clone = require('clone'); + /** + * Clone an object. + * + * @param objectToClone The object to clone. + * @returns A new clone of the original object. + */ + function cloneObject(objectToClone) { + return clone(objectToClone); + } + MakerJs.cloneObject = cloneObject; + /** + * Copy the properties from one object to another object. + * + * Example: + * ``` + * makerjs.extendObject({ abc: 123 }, { xyz: 789 }); //returns { abc: 123, xyz: 789 } + * ``` + * + * @param target The object to extend. It will receive the new properties. + * @param other An object containing properties to merge in. + * @returns The original object after merging. + */ + function extendObject(target, other) { + if (target && other) { + for (var key in other) { + if (typeof other[key] !== 'undefined') { + target[key] = other[key]; + } + } + } + return target; + } + MakerJs.extendObject = extendObject; + /** + * Test to see if an object implements the required properties of a point. + * + * @param item The item to test. + */ + function isPoint(item) { + return (Array.isArray(item) && item.length == 2 && !isNaN(item[0]) && !isNaN(item[1])); + } + MakerJs.isPoint = isPoint; + /** + * Test to see if an object implements the required properties of a path. + * + * @param item The item to test. + */ + function isPath(item) { + return item && item.type && item.origin; + } + MakerJs.isPath = isPath; + /** + * Test to see if an object implements the required properties of a line. + * + * @param item The item to test. + */ + function isPathLine(item) { + return isPath(item) && item.type == MakerJs.pathType.Line && item.end; + } + MakerJs.isPathLine = isPathLine; + /** + * Test to see if an object implements the required properties of a circle. + * + * @param item The item to test. + */ + function isPathCircle(item) { + return isPath(item) && item.type == MakerJs.pathType.Circle && item.radius; + } + MakerJs.isPathCircle = isPathCircle; + /** + * Test to see if an object implements the required properties of an arc. + * + * @param item The item to test. + */ + function isPathArc(item) { + return isPath(item) && item.type == MakerJs.pathType.Arc && item.radius && item.startAngle && item.endAngle; + } + MakerJs.isPathArc = isPathArc; + /** + * String-based enumeration of all paths types. + * + * Examples: use pathType instead of string literal when creating a circle. + * ``` + * var circle: IPathCircle = { type: pathType.Circle, origin: [0, 0], radius: 7 }; //typescript + * var circle = { type: pathType.Circle, origin: [0, 0], radius: 7 }; //javascript + * ``` + */ + MakerJs.pathType = { + Line: "line", + Circle: "circle", + Arc: "arc" + }; + /** + * Test to see if an object implements the required properties of a model. + */ + function isModel(item) { + return item && (item.paths || item.models); + } + MakerJs.isModel = isModel; +})(MakerJs || (MakerJs = {})); +//CommonJs +module.exports = MakerJs; +var MakerJs; +(function (MakerJs) { + var angle; + (function (angle) { + /** + * Ensures an angle is not greater than 360 + * + * @param angleInDegrees Angle in degrees. + * @retiurns Same polar angle but not greater than 360 degrees. + */ + function noRevolutions(angleInDegrees) { + var revolutions = Math.floor(angleInDegrees / 360); + var a = angleInDegrees - (360 * revolutions); + return a < 0 ? a + 360 : a; + } + angle.noRevolutions = noRevolutions; + /** + * Convert an angle from degrees to radians. + * + * @param angleInDegrees Angle in degrees. + * @returns Angle in radians. + */ + function toRadians(angleInDegrees) { + return noRevolutions(angleInDegrees) * Math.PI / 180.0; + } + angle.toRadians = toRadians; + /** + * Convert an angle from radians to degrees. + * + * @param angleInRadians Angle in radians. + * @returns Angle in degrees. + */ + function toDegrees(angleInRadians) { + return angleInRadians * 180.0 / Math.PI; + } + angle.toDegrees = toDegrees; + /** + * Get an arc's end angle, ensured to be greater than its start angle. + * + * @param arc An arc path object. + * @returns End angle of arc. + */ + function ofArcEnd(arc) { + //compensate for values past zero. This allows easy compute of total angle size. + //for example 0 = 360 + if (arc.endAngle < arc.startAngle) { + return 360 + arc.endAngle; + } + return arc.endAngle; + } + angle.ofArcEnd = ofArcEnd; + /** + * Get the angle in the middle of an arc's start and end angles. + * + * @param arc An arc path object. + * @param ratio Optional number between 0 and 1 specifying percentage between start and end angles. Default is .5 + * @returns Middle angle of arc. + */ + function ofArcMiddle(arc, ratio) { + if (ratio === void 0) { ratio = .5; } + return arc.startAngle + ofArcSpan(arc) * ratio; + } + angle.ofArcMiddle = ofArcMiddle; + /** + * Total angle of an arc between its start and end angles. + * + * @param arc The arc to measure. + * @returns Angle of arc. + */ + function ofArcSpan(arc) { + var endAngle = angle.ofArcEnd(arc); + return endAngle - arc.startAngle; + } + angle.ofArcSpan = ofArcSpan; + /** + * Angle of a line path. + * + * @param line The line path to find the angle of. + * @returns Angle of the line path, in degrees. + */ + function ofLineInDegrees(line) { + return noRevolutions(toDegrees(ofPointInRadians(line.origin, line.end))); + } + angle.ofLineInDegrees = ofLineInDegrees; + /** + * Angle of a line through a point, in degrees. + * + * @param pointToFindAngle The point to find the angle. + * @param origin Point of origin of the angle. + * @returns Angle of the line throught the point, in degrees. + */ + function ofPointInDegrees(origin, pointToFindAngle) { + return toDegrees(ofPointInRadians(origin, pointToFindAngle)); + } + angle.ofPointInDegrees = ofPointInDegrees; + /** + * Angle of a line through a point, in radians. + * + * @param pointToFindAngle The point to find the angle. + * @param origin Point of origin of the angle. + * @returns Angle of the line throught the point, in radians. + */ + function ofPointInRadians(origin, pointToFindAngle) { + var d = MakerJs.point.subtract(pointToFindAngle, origin); + var x = d[0]; + var y = d[1]; + return Math.atan2(-y, -x) + Math.PI; + } + angle.ofPointInRadians = ofPointInRadians; + /** + * Mirror an angle on either or both x and y axes. + * + * @param angleInDegrees The angle to mirror. + * @param mirrorX Boolean to mirror on the x axis. + * @param mirrorY Boolean to mirror on the y axis. + * @returns Mirrored angle. + */ + function mirror(angleInDegrees, mirrorX, mirrorY) { + if (mirrorY) { + angleInDegrees = 360 - angleInDegrees; + } + if (mirrorX) { + angleInDegrees = (angleInDegrees < 180 ? 180 : 540) - angleInDegrees; + } + return angleInDegrees; + } + angle.mirror = mirror; + })(angle = MakerJs.angle || (MakerJs.angle = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var point; + (function (point) { + /** + * Add two points together and return the result as a new point object. + * + * @param a First point. + * @param b Second point. + * @param subtract Optional boolean to subtract instead of add. + * @returns A new point object. + */ + function add(a, b, subtract) { + var newPoint = clone(a); + if (!b) + return newPoint; + for (var i = 2; i--;) { + if (subtract) { + newPoint[i] -= b[i]; + } + else { + newPoint[i] += b[i]; + } + } + return newPoint; + } + point.add = add; + /** + * Get the average of two points. + * + * @param a First point. + * @param b Second point. + * @returns New point object which is the average of a and b. + */ + function average(a, b) { + function avg(i) { + return (a[i] + b[i]) / 2; + } + return [avg(0), avg(1)]; + } + point.average = average; + /** + * Clone a point into a new point. + * + * @param pointToClone The point to clone. + * @returns A new point with same values as the original. + */ + function clone(pointToClone) { + if (!pointToClone) + return point.zero(); + return [pointToClone[0], pointToClone[1]]; + } + point.clone = clone; + /** + * From an array of points, find the closest point to a given reference point. + * + * @param referencePoint The reference point. + * @param pointOptions Array of points to choose from. + * @returns The first closest point from the pointOptions. + */ + function closest(referencePoint, pointOptions) { + var smallest = { + index: 0, + distance: -1 + }; + for (var i = 0; i < pointOptions.length; i++) { + var distance = MakerJs.measure.pointDistance(referencePoint, pointOptions[i]); + if (smallest.distance == -1 || distance < smallest.distance) { + smallest.distance = distance; + smallest.index = i; + } + } + return pointOptions[smallest.index]; + } + point.closest = closest; + /** + * Get a point from its polar coordinates. + * + * @param angleInRadians The angle of the polar coordinate, in radians. + * @param radius The radius of the polar coordinate. + * @returns A new point object. + */ + function fromPolar(angleInRadians, radius) { + return [ + radius * Math.cos(angleInRadians), + radius * Math.sin(angleInRadians) + ]; + } + point.fromPolar = fromPolar; + /** + * Get a point on a circle or arc path, at a given angle. + * @param angleInDegrees The angle at which you want to find the point, in degrees. + * @param circle A circle or arc. + * @returns A new point object. + */ + function fromAngleOnCircle(angleInDegrees, circle) { + return add(circle.origin, fromPolar(MakerJs.angle.toRadians(angleInDegrees), circle.radius)); + } + point.fromAngleOnCircle = fromAngleOnCircle; + /** + * Get the two end points of an arc path. + * + * @param arc The arc path object. + * @returns Array with 2 elements: [0] is the point object corresponding to the start angle, [1] is the point object corresponding to the end angle. + */ + function fromArc(arc) { + return [fromAngleOnCircle(arc.startAngle, arc), fromAngleOnCircle(arc.endAngle, arc)]; + } + point.fromArc = fromArc; + /** + * Get the two end points of a path. + * + * @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) { + var result = null; + var map = {}; + map[MakerJs.pathType.Arc] = function (arc) { + result = point.fromArc(arc); + }; + map[MakerJs.pathType.Line] = function (line) { + result = [line.origin, line.end]; + }; + var fn = map[pathContext.type]; + if (fn) { + fn(pathContext); + } + return result; + } + point.fromPathEnds = fromPathEnds; + /** + * @private + */ + function verticalIntersectionPoint(verticalLine, nonVerticalSlope) { + var x = verticalLine.origin[0]; + var y = nonVerticalSlope.slope * x + nonVerticalSlope.yIntercept; + return [x, y]; + } + /** + * 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 fromSlopeIntersection(line1, line2, options) { + if (options === void 0) { options = {}; } + var slope1 = MakerJs.measure.lineSlope(line1); + var slope2 = MakerJs.measure.lineSlope(line2); + if (MakerJs.measure.isSlopeEqual(slope1, slope2)) { + //check for overlap + options.out_AreOverlapped = MakerJs.measure.isLineOverlapping(line1, line2, options.excludeTangents); + return null; + } + var pointOfIntersection; + if (!slope1.hasSlope) { + pointOfIntersection = verticalIntersectionPoint(line1, slope2); + } + else if (!slope2.hasSlope) { + pointOfIntersection = verticalIntersectionPoint(line2, slope1); + } + else { + // find intersection by line equation + var x = (slope2.yIntercept - slope1.yIntercept) / (slope1.slope - slope2.slope); + var y = slope1.slope * x + slope1.yIntercept; + pointOfIntersection = [x, y]; + } + return pointOfIntersection; + } + point.fromSlopeIntersection = fromSlopeIntersection; + /** + * Get the middle point of a path. + * + * @param pathContext The path object. + * @param ratio Optional ratio (between 0 and 1) of point along the path. Default is .5 for middle. + * @returns Point on the path, in the middle of the path. + */ + function middle(pathContext, ratio) { + if (ratio === void 0) { ratio = .5; } + var midPoint = null; + var map = {}; + map[MakerJs.pathType.Arc] = function (arc) { + var midAngle = MakerJs.angle.ofArcMiddle(arc, ratio); + midPoint = point.add(arc.origin, point.fromPolar(MakerJs.angle.toRadians(midAngle), arc.radius)); + }; + map[MakerJs.pathType.Circle] = function (circle) { + midPoint = point.add(circle.origin, [-circle.radius, 0]); + }; + map[MakerJs.pathType.Line] = function (line) { + function ration(a, b) { + return a + (b - a) * ratio; + } + ; + midPoint = [ + ration(line.origin[0], line.end[0]), + ration(line.origin[1], line.end[1]) + ]; + }; + var fn = map[pathContext.type]; + if (fn) { + fn(pathContext); + } + return midPoint; + } + point.middle = middle; + /** + * Create a clone of a point, mirrored on either or both x and y axes. + * + * @param pointToMirror The point to mirror. + * @param mirrorX Boolean to mirror on the x axis. + * @param mirrorY Boolean to mirror on the y axis. + * @returns Mirrored point. + */ + function mirror(pointToMirror, mirrorX, mirrorY) { + var p = clone(pointToMirror); + if (mirrorX) { + p[0] = -p[0]; + } + if (mirrorY) { + p[1] = -p[1]; + } + return p; + } + point.mirror = mirror; + /** + * Round the values of a point. + * + * @param pointContext The point to serialize. + * @param accuracy Optional exemplar number of decimal places. + * @returns A new point with the values rounded. + */ + function rounded(pointContext, accuracy) { + return [MakerJs.round(pointContext[0], accuracy), MakerJs.round(pointContext[1], accuracy)]; + } + point.rounded = rounded; + /** + * Rotate a point. + * + * @param pointToRotate The point to rotate. + * @param angleInDegrees The amount of rotation, in degrees. + * @param rotationOrigin The center point of rotation. + * @returns A new point. + */ + function rotate(pointToRotate, angleInDegrees, rotationOrigin) { + var pointAngleInRadians = MakerJs.angle.ofPointInRadians(rotationOrigin, pointToRotate); + var d = MakerJs.measure.pointDistance(rotationOrigin, pointToRotate); + var rotatedPoint = fromPolar(pointAngleInRadians + MakerJs.angle.toRadians(angleInDegrees), d); + return add(rotationOrigin, rotatedPoint); + } + point.rotate = rotate; + /** + * Scale a point's coordinates. + * + * @param pointToScale The point to scale. + * @param scaleValue The amount of scaling. + * @returns A new point. + */ + function scale(pointToScale, scaleValue) { + var p = clone(pointToScale); + for (var i = 2; i--;) { + p[i] *= scaleValue; + } + return p; + } + point.scale = scale; + /** + * 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, accuracy) { + var roundedPoint = rounded(pointContext, accuracy); + return JSON.stringify(roundedPoint); + } + point.serialize = serialize; + /** + * Subtract a point from another point, and return the result as a new point. Shortcut to Add(a, b, subtract = true). + * + * @param a First point. + * @param b Second point. + * @returns A new point object. + */ + function subtract(a, b) { + return add(a, b, true); + } + point.subtract = subtract; + /** + * A point at 0,0 coordinates. + * NOTE: It is important to call this as a method, with the empty parentheses. + * + * @returns A new point. + */ + function zero() { + return [0, 0]; + } + point.zero = zero; + })(point = MakerJs.point || (MakerJs.point = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var path; + (function (path) { + /** + * Create a clone of a path, mirrored on either or both x and y axes. + * + * @param pathToMirror The path to mirror. + * @param mirrorX Boolean to mirror on the x axis. + * @param mirrorY Boolean to mirror on the y axis. + * @param newId Optional id to assign to the new path. + * @returns Mirrored path. + */ + function mirror(pathToMirror, mirrorX, mirrorY, newId) { + var newPath = null; + if (pathToMirror) { + var origin = MakerJs.point.mirror(pathToMirror.origin, mirrorX, mirrorY); + var map = {}; + map[MakerJs.pathType.Line] = function (line) { + newPath = new MakerJs.paths.Line(origin, MakerJs.point.mirror(line.end, mirrorX, mirrorY)); + }; + map[MakerJs.pathType.Circle] = function (circle) { + newPath = new MakerJs.paths.Circle(origin, circle.radius); + }; + map[MakerJs.pathType.Arc] = function (arc) { + var startAngle = MakerJs.angle.mirror(arc.startAngle, mirrorX, mirrorY); + var endAngle = MakerJs.angle.mirror(MakerJs.angle.ofArcEnd(arc), mirrorX, mirrorY); + var xor = mirrorX != mirrorY; + newPath = new MakerJs.paths.Arc(origin, arc.radius, xor ? endAngle : startAngle, xor ? startAngle : endAngle); + }; + var fn = map[pathToMirror.type]; + if (fn) { + fn(pathToMirror); + } + } + return newPath; + } + path.mirror = mirror; + /** + * Move a path to an absolute point. + * + * @param pathToMove The path to move. + * @param origin The new origin for the path. + * @returns The original path (for chaining). + */ + function move(pathToMove, origin) { + if (pathToMove) { + var map = {}; + map[MakerJs.pathType.Line] = function (line) { + var delta = MakerJs.point.subtract(line.end, line.origin); + line.end = MakerJs.point.add(origin, delta); + }; + var fn = map[pathToMove.type]; + if (fn) { + fn(pathToMove); + } + pathToMove.origin = origin; + } + return pathToMove; + } + path.move = move; + /** + * Move a path's origin by a relative amount. + * + * @param pathToMove The path to move. + * @param delta The x & y adjustments as a point object. + * @returns The original path (for chaining). + */ + function moveRelative(pathToMove, delta) { + if (pathToMove) { + var map = {}; + map[MakerJs.pathType.Line] = function (line) { + line.end = MakerJs.point.add(line.end, delta); + }; + pathToMove.origin = MakerJs.point.add(pathToMove.origin, delta); + var fn = map[pathToMove.type]; + if (fn) { + fn(pathToMove); + } + } + return pathToMove; + } + path.moveRelative = moveRelative; + /** + * Rotate a path. + * + * @param pathToRotate The path to rotate. + * @param angleInDegrees The amount of rotation, in degrees. + * @param rotationOrigin The center point of rotation. + * @returns The original path (for chaining). + */ + function rotate(pathToRotate, angleInDegrees, rotationOrigin) { + if (!pathToRotate || angleInDegrees == 0) + return pathToRotate; + var map = {}; + map[MakerJs.pathType.Line] = function (line) { + line.end = MakerJs.point.rotate(line.end, angleInDegrees, rotationOrigin); + }; + map[MakerJs.pathType.Arc] = function (arc) { + arc.startAngle = MakerJs.angle.noRevolutions(arc.startAngle + angleInDegrees); + arc.endAngle = MakerJs.angle.noRevolutions(arc.endAngle + angleInDegrees); + }; + pathToRotate.origin = MakerJs.point.rotate(pathToRotate.origin, angleInDegrees, rotationOrigin); + var fn = map[pathToRotate.type]; + if (fn) { + fn(pathToRotate); + } + return pathToRotate; + } + path.rotate = rotate; + /** + * Scale a path. + * + * @param pathToScale The path to scale. + * @param scaleValue The amount of scaling. + * @returns The original path (for chaining). + */ + function scale(pathToScale, scaleValue) { + if (!pathToScale || scaleValue == 1) + return pathToScale; + var map = {}; + map[MakerJs.pathType.Line] = function (line) { + line.end = MakerJs.point.scale(line.end, scaleValue); + }; + map[MakerJs.pathType.Circle] = function (circle) { + circle.radius *= scaleValue; + }; + map[MakerJs.pathType.Arc] = map[MakerJs.pathType.Circle]; + pathToScale.origin = MakerJs.point.scale(pathToScale.origin, scaleValue); + var fn = map[pathToScale.type]; + if (fn) { + fn(pathToScale); + } + return pathToScale; + } + path.scale = scale; + })(path = MakerJs.path || (MakerJs.path = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var path; + (function (path_1) { + /** + * @private + */ + var breakPathFunctionMap = {}; + breakPathFunctionMap[MakerJs.pathType.Arc] = function (arc, pointOfBreak) { + var angleAtBreakPoint = MakerJs.angle.ofPointInDegrees(arc.origin, pointOfBreak); + if (MakerJs.measure.isAngleEqual(angleAtBreakPoint, arc.startAngle) || MakerJs.measure.isAngleEqual(angleAtBreakPoint, arc.endAngle)) { + return null; + } + function getAngleStrictlyBetweenArcAngles() { + var startAngle = MakerJs.angle.noRevolutions(arc.startAngle); + var endAngle = startAngle + MakerJs.angle.ofArcEnd(arc) - arc.startAngle; + var tries = [0, 1, -1]; + for (var i = 0; i < tries.length; i++) { + var add = +360 * tries[i]; + if (MakerJs.measure.isBetween(angleAtBreakPoint + add, startAngle, endAngle, true)) { + return arc.startAngle + angleAtBreakPoint + add - startAngle; + } + } + return null; + } + var angleAtBreakPointBetween = getAngleStrictlyBetweenArcAngles(); + if (angleAtBreakPointBetween == null) { + return null; + } + var savedEndAngle = arc.endAngle; + arc.endAngle = angleAtBreakPointBetween; + return new MakerJs.paths.Arc(arc.origin, arc.radius, angleAtBreakPointBetween, savedEndAngle); + }; + breakPathFunctionMap[MakerJs.pathType.Circle] = function (circle, pointOfBreak) { + circle.type = MakerJs.pathType.Arc; + var arc = circle; + var angleAtBreakPoint = MakerJs.angle.ofPointInDegrees(circle.origin, pointOfBreak); + arc.startAngle = angleAtBreakPoint; + arc.endAngle = angleAtBreakPoint + 360; + return null; + }; + breakPathFunctionMap[MakerJs.pathType.Line] = function (line, pointOfBreak) { + if (MakerJs.measure.isPointEqual(line.origin, pointOfBreak) || MakerJs.measure.isPointEqual(line.end, pointOfBreak)) { + return null; + } + if (!MakerJs.measure.isBetweenPoints(pointOfBreak, line, true)) { + return null; + } + var savedEndPoint = line.end; + line.end = pointOfBreak; + return new MakerJs.paths.Line(pointOfBreak, savedEndPoint); + }; + /** + * Breaks a path in two. The supplied path will end at the supplied pointOfBreak, + * a new path is returned which begins at the pointOfBreak and ends at the supplied path's initial end point. + * For Circle, the original path will be converted in place to an Arc, and null is returned. + * + * @param pathToBreak The path to break. + * @param pointOfBreak The point at which to break the path. + * @returns A new path of the same type, when path type is line or arc. Returns null for circle. + */ + function breakAtPoint(pathToBreak, pointOfBreak) { + if (pathToBreak && pointOfBreak) { + var fn = breakPathFunctionMap[pathToBreak.type]; + if (fn) { + return fn(pathToBreak, pointOfBreak); + } + } + return null; + } + path_1.breakAtPoint = breakAtPoint; + })(path = MakerJs.path || (MakerJs.path = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var paths; + (function (paths) { + /** + * Class for arc path. + */ + var Arc = (function () { + function Arc() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i - 0] = arguments[_i]; + } + switch (args.length) { + case 5: + //SVG style arc designation + this.radius = args[2]; + //find the 2 potential origins + var origins = MakerJs.path.intersection(new Circle(args[0], this.radius), new Circle(args[1], this.radius)); + //there may be a condition where the radius is insufficient! Why does the SVG spec allow this? + if (origins) { + var largeArc = args[3]; + var clockwise = args[4]; + var span; + var spans = []; + for (var i = 2; i--;) { + var origin = origins.intersectionPoints[i]; + var startAngle = MakerJs.angle.ofPointInDegrees(origin, args[clockwise ? 1 : 0]); + var endAngle = MakerJs.angle.ofPointInDegrees(origin, args[clockwise ? 0 : 1]); + if (endAngle < startAngle) { + endAngle += 360; + } + span = { + origin: origin, + startAngle: startAngle, + endAngle: endAngle, + size: endAngle - startAngle + }; + //insert sorted by size ascending + if (spans.length == 0 || span.size > spans[0].size) { + spans.push(span); + } + else { + spans.unshift(span); + } + } + var index = largeArc ? 1 : 0; + span = spans[index]; + this.origin = span.origin; + this.startAngle = span.startAngle; + this.endAngle = span.endAngle; + } + break; + case 4: + this.origin = args[0]; + this.radius = args[1]; + this.startAngle = args[2]; + this.endAngle = args[3]; + break; + case 3: + if (MakerJs.isPoint(args[2])) { + //from 3 points + Circle.apply(this, args); + var angles = []; + for (var i = 0; i < 3; i++) { + angles.push(MakerJs.angle.ofPointInDegrees(this.origin, args[i])); + } + this.startAngle = angles[0]; + this.endAngle = angles[2]; + //swap start and end angles if this arc does not contain the midpoint + if (!MakerJs.measure.isBetweenArcAngles(angles[1], this, false)) { + this.startAngle = angles[2]; + this.endAngle = angles[0]; + } + //do not fall through if this was 3 points + break; + } + //fall through to below if 2 points + case 2: + //from 2 points (and optional clockwise flag) + var clockwise = args[2]; + Circle.call(this, args[0], args[1]); + this.startAngle = MakerJs.angle.ofPointInDegrees(this.origin, args[clockwise ? 1 : 0]); + this.endAngle = MakerJs.angle.ofPointInDegrees(this.origin, args[clockwise ? 0 : 1]); + break; + } + //do this after Circle.apply / Circle.call to make sure this is an arc + this.type = MakerJs.pathType.Arc; + } + return Arc; + }()); + paths.Arc = Arc; + /** + * Class for circle path. + */ + var Circle = (function () { + function Circle() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i - 0] = arguments[_i]; + } + this.type = MakerJs.pathType.Circle; + if (args.length == 2) { + if (typeof args[1] === 'number') { + this.origin = args[0]; + this.radius = args[1]; + } + else { + //Circle from 2 points + this.origin = MakerJs.point.average(args[0], args[1]); + this.radius = MakerJs.measure.pointDistance(this.origin, args[0]); + } + } + else { + //Circle from 3 points + //create 2 lines with 2nd point in common + var lines = [ + new Line(args[0], args[1]), + new Line(args[1], args[2]) + ]; + //create perpendicular lines + var perpendiculars = []; + for (var i = 2; i--;) { + var midpoint = MakerJs.point.middle(lines[i]); + perpendiculars.push(MakerJs.path.rotate(lines[i], 90, midpoint)); + } + //find intersection of slopes of perpendiculars + this.origin = MakerJs.point.fromSlopeIntersection(perpendiculars[0], perpendiculars[1]); + //radius is distance to any of the 3 points + this.radius = MakerJs.measure.pointDistance(this.origin, args[0]); + } + } + return Circle; + }()); + paths.Circle = Circle; + /** + * Class for line path. + * + * @param origin The origin point of the line. + * @param end The end point of the line. + */ + var Line = (function () { + function Line(origin, end) { + this.origin = origin; + this.end = end; + this.type = MakerJs.pathType.Line; + } + return Line; + }()); + paths.Line = Line; + /** + * Class for chord, which is simply a line path that connects the endpoints of an arc. + * + * @param arc Arc to use as the basic for the chord. + */ + var Chord = (function () { + function Chord(arc) { + var arcPoints = MakerJs.point.fromArc(arc); + this.type = MakerJs.pathType.Line; + this.origin = arcPoints[0]; + this.end = arcPoints[1]; + } + return Chord; + }()); + paths.Chord = Chord; + /** + * Class for a parallel line path. + * + * @param toLine A line to be parallel to. + * @param distance Distance between parallel and original line. + * @param nearPoint Any point to determine which side of the line to place the parallel. + */ + var Parallel = (function () { + function Parallel(toLine, distance, nearPoint) { + this.type = MakerJs.pathType.Line; + this.origin = MakerJs.point.clone(toLine.origin); + this.end = MakerJs.point.clone(toLine.end); + var angleOfLine = MakerJs.angle.ofLineInDegrees(this); + function getNewOrigin(offsetAngle) { + var origin = MakerJs.point.add(toLine.origin, MakerJs.point.fromPolar(MakerJs.angle.toRadians(angleOfLine + offsetAngle), distance)); + return { + origin: origin, + nearness: MakerJs.measure.pointDistance(origin, nearPoint) + }; + } + var newOrigins = [getNewOrigin(-90), getNewOrigin(90)]; + var newOrigin = (newOrigins[0].nearness < newOrigins[1].nearness) ? newOrigins[0].origin : newOrigins[1].origin; + MakerJs.path.move(this, newOrigin); + } + return Parallel; + }()); + paths.Parallel = Parallel; + })(paths = MakerJs.paths || (MakerJs.paths = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var model; + (function (model) { + /** + * Count the number of child models within a given model. + * + * @param modelContext The model containing other models. + * @returns Number of child models. + */ + function countChildModels(modelContext) { + var count = 0; + if (modelContext.models) { + for (var id in modelContext.models) { + count++; + } + } + return count; + } + model.countChildModels = countChildModels; + /** + * Get an unused id in the models map with the same prefix. + * + * @param modelContext The model containing the models map. + * @param modelId The id to use directly (if unused), or as a prefix. + */ + function getSimilarModelId(modelContext, modelId) { + if (!modelContext.models) + return modelId; + var i = 0; + var newModelId = modelId; + while (newModelId in modelContext.models) { + i++; + newModelId = modelId + '_' + i; + } + return newModelId; + } + model.getSimilarModelId = getSimilarModelId; + /** + * Get an unused id in the paths map with the same prefix. + * + * @param modelContext The model containing the paths map. + * @param pathId The id to use directly (if unused), or as a prefix. + */ + function getSimilarPathId(modelContext, pathId) { + if (!modelContext.paths) + return pathId; + var i = 0; + var newPathId = pathId; + while (newPathId in modelContext.paths) { + i++; + newPathId = pathId + '_' + i; + } + return newPathId; + } + model.getSimilarPathId = getSimilarPathId; + /** + * Moves all of a model's children (models and paths, recursively) in reference to a single common origin. Useful when points between children need to connect to each other. + * + * @param modelToOriginate The model to originate. + * @param origin Optional offset reference point. + */ + function originate(modelToOriginate, origin) { + if (!modelToOriginate) + return; + var newOrigin = MakerJs.point.add(modelToOriginate.origin, origin); + if (modelToOriginate.paths) { + for (var id in modelToOriginate.paths) { + MakerJs.path.moveRelative(modelToOriginate.paths[id], newOrigin); + } + } + if (modelToOriginate.models) { + for (var id in modelToOriginate.models) { + originate(modelToOriginate.models[id], newOrigin); + } + } + modelToOriginate.origin = MakerJs.point.zero(); + return modelToOriginate; + } + model.originate = originate; + /** + * Create a clone of a model, mirrored on either or both x and y axes. + * + * @param modelToMirror The model to mirror. + * @param mirrorX Boolean to mirror on the x axis. + * @param mirrorY Boolean to mirror on the y axis. + * @returns Mirrored model. + */ + function mirror(modelToMirror, mirrorX, mirrorY) { + var newModel = {}; + if (modelToMirror.origin) { + newModel.origin = MakerJs.point.mirror(modelToMirror.origin, mirrorX, mirrorY); + } + if (modelToMirror.type) { + newModel.type = modelToMirror.type; + } + if (modelToMirror.units) { + newModel.units = modelToMirror.units; + } + if (modelToMirror.paths) { + newModel.paths = {}; + for (var id in modelToMirror.paths) { + var pathToMirror = modelToMirror.paths[id]; + if (!pathToMirror) + continue; + var pathMirrored = MakerJs.path.mirror(pathToMirror, mirrorX, mirrorY); + if (!pathMirrored) + continue; + newModel.paths[id] = pathMirrored; + } + } + if (modelToMirror.models) { + newModel.models = {}; + for (var id in modelToMirror.models) { + var childModelToMirror = modelToMirror.models[id]; + if (!childModelToMirror) + continue; + var childModelMirrored = model.mirror(childModelToMirror, mirrorX, mirrorY); + if (!childModelMirrored) + continue; + newModel.models[id] = childModelMirrored; + } + } + return newModel; + } + model.mirror = mirror; + /** + * Move a model to an absolute point. Note that this is also accomplished by directly setting the origin property. This function exists for chaining. + * + * @param modelToMove The model to move. + * @param origin The new position of the model. + * @returns The original model (for chaining). + */ + function move(modelToMove, origin) { + modelToMove.origin = MakerJs.point.clone(origin); + return modelToMove; + } + model.move = move; + /** + * Move a model's origin by a relative amount. + * + * @param modelToMove The model to move. + * @param delta The x & y adjustments as a point object. + * @returns The original model (for chaining). + */ + function moveRelative(modelToMove, delta) { + if (modelToMove) { + modelToMove.origin = MakerJs.point.add(modelToMove.origin || MakerJs.point.zero(), delta); + } + return modelToMove; + } + model.moveRelative = moveRelative; + /** + * Rotate a model. + * + * @param modelToRotate The model to rotate. + * @param angleInDegrees The amount of rotation, in degrees. + * @param rotationOrigin The center point of rotation. + * @returns The original model (for chaining). + */ + function rotate(modelToRotate, angleInDegrees, rotationOrigin) { + if (modelToRotate) { + var offsetOrigin = MakerJs.point.subtract(rotationOrigin, modelToRotate.origin); + if (modelToRotate.paths) { + for (var id in modelToRotate.paths) { + MakerJs.path.rotate(modelToRotate.paths[id], angleInDegrees, offsetOrigin); + } + } + if (modelToRotate.models) { + for (var id in modelToRotate.models) { + rotate(modelToRotate.models[id], angleInDegrees, offsetOrigin); + } + } + } + return modelToRotate; + } + model.rotate = rotate; + /** + * Scale a model. + * + * @param modelToScale The model to scale. + * @param scaleValue The amount of scaling. + * @param scaleOrigin Optional boolean to scale the origin point. Typically false for the root model. + * @returns The original model (for chaining). + */ + function scale(modelToScale, scaleValue, scaleOrigin) { + if (scaleOrigin === void 0) { scaleOrigin = false; } + if (scaleOrigin && modelToScale.origin) { + modelToScale.origin = MakerJs.point.scale(modelToScale.origin, scaleValue); + } + if (modelToScale.paths) { + for (var id in modelToScale.paths) { + MakerJs.path.scale(modelToScale.paths[id], scaleValue); + } + } + if (modelToScale.models) { + for (var id in modelToScale.models) { + scale(modelToScale.models[id], scaleValue, true); + } + } + return modelToScale; + } + model.scale = scale; + /** + * Convert a model to match a different unit system. + * + * @param modeltoConvert The model to convert. + * @param destUnitType The unit system. + * @returns The scaled model (for chaining). + */ + function convertUnits(modeltoConvert, destUnitType) { + var validUnitType = false; + for (var id in MakerJs.unitType) { + if (MakerJs.unitType[id] == destUnitType) { + validUnitType = true; + break; + } + } + if (modeltoConvert.units && validUnitType) { + var ratio = MakerJs.units.conversionScale(modeltoConvert.units, destUnitType); + if (ratio != 1) { + scale(modeltoConvert, ratio); + //update the model with its new unit type + modeltoConvert.units = destUnitType; + } + } + return modeltoConvert; + } + model.convertUnits = convertUnits; + /** + * Recursively walk through all paths for a given model. + * + * @param modelContext The model to walk. + * @param callback Callback for each path. + */ + function walkPaths(modelContext, callback) { + if (modelContext.paths) { + for (var pathId in modelContext.paths) { + if (!modelContext.paths[pathId]) + continue; + callback(modelContext, pathId, modelContext.paths[pathId]); + } + } + if (modelContext.models) { + for (var id in modelContext.models) { + if (!modelContext.models[id]) + continue; + walkPaths(modelContext.models[id], callback); + } + } + } + model.walkPaths = walkPaths; + })(model = MakerJs.model || (MakerJs.model = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var model; + (function (model) { + /** + * @private + */ + function getNonZeroSegments(pathToSegment, breakPoint) { + var segmentType = pathToSegment.type; + var segment1 = MakerJs.cloneObject(pathToSegment); + var segment2 = MakerJs.path.breakAtPoint(segment1, breakPoint); + if (segment2) { + var segments = [segment1, segment2]; + for (var i = 2; i--;) { + if (MakerJs.round(MakerJs.measure.pathLength(segments[i]), .0001) == 0) { + return null; + } + } + return segments; + } + else if (segmentType == MakerJs.pathType.Circle) { + return [segment1]; + } + return null; + } + /** + * @private + */ + function breakAlongForeignPath(segments, overlappedSegments, foreignPath) { + if (MakerJs.measure.isPathEqual(segments[0].path, foreignPath, .0001)) { + segments[0].overlapped = true; + segments[0].duplicate = true; + overlappedSegments.push(segments[0]); + return; + } + var foreignPathEndPoints; + for (var i = 0; i < segments.length; i++) { + var pointsToCheck; + var options = {}; + var foreignIntersection = MakerJs.path.intersection(segments[i].path, foreignPath, options); + if (foreignIntersection) { + pointsToCheck = foreignIntersection.intersectionPoints; + } + else if (options.out_AreOverlapped) { + segments[i].overlapped = true; + overlappedSegments.push(segments[i]); + if (!foreignPathEndPoints) { + foreignPathEndPoints = MakerJs.point.fromPathEnds(foreignPath); + } + pointsToCheck = foreignPathEndPoints; + } + if (pointsToCheck) { + //break the path which intersected, and add the shard to the end of the array so it can also be checked in this loop for further sharding. + var subSegments = null; + var p = 0; + while (!subSegments && p < pointsToCheck.length) { + subSegments = getNonZeroSegments(segments[i].path, pointsToCheck[p]); + p++; + } + if (subSegments) { + segments[i].path = subSegments[0]; + if (subSegments[1]) { + var newSegment = { + path: subSegments[1], + pathId: segments[0].pathId, + overlapped: segments[i].overlapped, + uniqueForeignIntersectionPoints: [] + }; + if (segments[i].overlapped) { + overlappedSegments.push(newSegment); + } + segments.push(newSegment); + } + //re-check this segment for another deep intersection + i--; + } + } + } + } + /** + * @private + */ + function addUniquePoints(pointArray, pointsToAdd) { + var added = 0; + function addUniquePoint(pointToAdd) { + for (var i = 0; i < pointArray.length; i++) { + if (MakerJs.measure.isPointEqual(pointArray[i], pointToAdd, .000000001)) { + return; + } + } + pointArray.push(pointToAdd); + added++; + } + for (var i = 0; i < pointsToAdd.length; i++) { + addUniquePoint(pointsToAdd[i]); + } + return added; + } + /** + * @private + */ + function checkIntersectsForeignPath(segment, foreignPath, foreignPathId, farPoint) { + if (farPoint === void 0) { farPoint = [7654321, 1234567]; } + var origin = MakerJs.point.middle(segment.path); + var lineToFarPoint = new MakerJs.paths.Line(origin, farPoint); + var farInt = MakerJs.path.intersection(lineToFarPoint, foreignPath); + if (farInt) { + var added = addUniquePoints(segment.uniqueForeignIntersectionPoints, farInt.intersectionPoints); + //if number of intersections is an odd number, flip the flag. + if (added % 2 == 1) { + segment.isInside = !!!segment.isInside; + } + } + } + /** + * @private + */ + function checkInsideForeignModel(segment, modelToIntersect, farPoint) { + model.walkPaths(modelToIntersect, function (mx, pathId2, path2) { + if (path2) { + checkIntersectsForeignPath(segment, path2, pathId2, farPoint); + } + }); + } + /** + * Check to see if a path is inside of a model. + * + * @param pathContext The path to check. + * @param modelContext The model to check against. + * @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, modelContext, farPoint) { + var segment = { + path: pathContext, + isInside: false, + uniqueForeignIntersectionPoints: [] + }; + checkInsideForeignModel(segment, modelContext, farPoint); + return !!segment.isInside; + } + model.isPathInsideModel = isPathInsideModel; + /** + * Break a model's paths everywhere they intersect with another path. + * + * @param modelToBreak The model containing paths to be broken. + * @param modelToIntersect Optional model containing paths to look for intersection, or else the modelToBreak will be used. + */ + function breakPathsAtIntersections(modelToBreak, modelToIntersect) { + breakAllPathsAtIntersections(modelToBreak, modelToIntersect || modelToBreak, false); + } + model.breakPathsAtIntersections = breakPathsAtIntersections; + /** + * @private + */ + function breakAllPathsAtIntersections(modelToBreak, modelToIntersect, checkIsInside, farPoint) { + var crossedPaths = []; + var overlappedSegments = []; + model.walkPaths(modelToBreak, function (modelContext, pathId1, path1) { + if (!path1) + return; + //clone this path and make it the first segment + var segment = { + path: MakerJs.cloneObject(path1), + pathId: pathId1, + overlapped: false, + uniqueForeignIntersectionPoints: [] + }; + var thisPath = { + modelContext: modelContext, + pathId: pathId1, + segments: [segment] + }; + //keep breaking the segments anywhere they intersect with paths of the other model + model.walkPaths(modelToIntersect, function (mx, pathId2, path2) { + if (path2 && path1 !== path2) { + breakAlongForeignPath(thisPath.segments, overlappedSegments, path2); + } + }); + if (checkIsInside) { + //check each segment whether it is inside or outside + for (var i = 0; i < thisPath.segments.length; i++) { + checkInsideForeignModel(thisPath.segments[i], modelToIntersect, farPoint); + } + } + crossedPaths.push(thisPath); + }); + return { crossedPaths: crossedPaths, overlappedSegments: overlappedSegments }; + } + /** + * @private + */ + function checkForEqualOverlaps(crossedPathsA, crossedPathsB, pointMatchingDistance) { + function compareSegments(segment1, segment2) { + if (MakerJs.measure.isPathEqual(segment1.path, segment2.path, pointMatchingDistance)) { + segment1.duplicate = segment2.duplicate = true; + } + } + function compareAll(segment) { + for (var i = 0; i < crossedPathsB.length; i++) { + compareSegments(crossedPathsB[i], segment); + } + } + for (var i = 0; i < crossedPathsA.length; i++) { + compareAll(crossedPathsA[i]); + } + } + /** + * @private + */ + function addOrDeleteSegments(crossedPath, includeInside, includeOutside, keepDuplicates) { + function addSegment(modelContext, pathIdBase, segment) { + var id = model.getSimilarPathId(modelContext, pathIdBase); + modelContext.paths[id] = segment.path; + } + function checkAddSegment(modelContext, pathIdBase, segment) { + if (segment.isInside && includeInside || !segment.isInside && includeOutside) { + addSegment(modelContext, pathIdBase, segment); + } + } + //delete the original, its segments will be added + delete crossedPath.modelContext.paths[crossedPath.pathId]; + for (var i = 0; i < crossedPath.segments.length; i++) { + if (crossedPath.segments[i].duplicate) { + if (keepDuplicates) { + addSegment(crossedPath.modelContext, crossedPath.pathId, crossedPath.segments[i]); + } + } + else { + checkAddSegment(crossedPath.modelContext, crossedPath.pathId, crossedPath.segments[i]); + } + } + } + /** + * Combine 2 models. The models should be originated, and every path within each model should be part of a loop. + * + * @param modelA First model to combine. + * @param modelB Second model to combine. + * @param includeAInsideB Flag to include paths from modelA which are inside of modelB. + * @param includeAOutsideB Flag to include paths from modelA which are outside of modelB. + * @param includeBInsideA Flag to include paths from modelB which are inside of modelA. + * @param includeBOutsideA Flag to include paths from modelB which are outside of modelA. + * @param keepDuplicates Flag to include paths which are duplicate in both models. + * @param farPoint Optional point of reference which is outside the bounds of both models. + */ + function combine(modelA, modelB, includeAInsideB, includeAOutsideB, includeBInsideA, includeBOutsideA, options) { + if (includeAInsideB === void 0) { includeAInsideB = false; } + if (includeAOutsideB === void 0) { includeAOutsideB = true; } + if (includeBInsideA === void 0) { includeBInsideA = false; } + if (includeBOutsideA === void 0) { includeBOutsideA = true; } + var opts = { + trimDeadEnds: true, + pointMatchingDistance: .005 + }; + MakerJs.extendObject(opts, options); + var pathsA = breakAllPathsAtIntersections(modelA, modelB, true, opts.farPoint); + var pathsB = breakAllPathsAtIntersections(modelB, modelA, true, opts.farPoint); + checkForEqualOverlaps(pathsA.overlappedSegments, pathsB.overlappedSegments, opts.pointMatchingDistance); + for (var i = 0; i < pathsA.crossedPaths.length; i++) { + addOrDeleteSegments(pathsA.crossedPaths[i], includeAInsideB, includeAOutsideB, true); + } + for (var i = 0; i < pathsB.crossedPaths.length; i++) { + addOrDeleteSegments(pathsB.crossedPaths[i], includeBInsideA, includeBOutsideA, false); + } + if (opts.trimDeadEnds) { + model.removeDeadEnds({ models: { modelA: modelA, modelB: modelB } }); + } + } + model.combine = combine; + })(model = MakerJs.model || (MakerJs.model = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + /** + * Collects items that share a common key. + */ + var Collector = (function () { + function Collector(comparer) { + this.comparer = comparer; + this.collections = []; + } + Collector.prototype.addItemToCollection = function (key, item) { + var found = this.findCollection(key); + if (found) { + found.push(item); + } + else { + var collection = { key: key, items: [item] }; + this.collections.push(collection); + } + }; + Collector.prototype.findCollection = function (key, action) { + for (var i = 0; i < this.collections.length; i++) { + var collection = this.collections[i]; + if (this.comparer(key, collection.key)) { + if (action) { + action(i); + } + return collection.items; + } + } + return null; + }; + Collector.prototype.removeCollection = function (key) { + var _this = this; + if (this.findCollection(key, function (index) { _this.collections.splice(index, 1); })) { + return true; + } + return false; + }; + Collector.prototype.removeItemFromCollection = function (key, item) { + var collection = this.findCollection(key); + if (!collection) + return; + for (var i = 0; i < collection.length; i++) { + if (collection[i] === item) { + collection.splice(i, 1); + return true; + } + } + return false; + }; + Collector.prototype.getCollectionsOfMultiple = function (cb) { + for (var i = 0; i < this.collections.length; i++) { + var collection = this.collections[i]; + if (collection.items.length > 1) { + cb(collection.key, collection.items); + } + } + }; + return Collector; + }()); + MakerJs.Collector = Collector; +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var model; + (function (model) { + /** + * @private + */ + function checkForOverlaps(refPaths, isOverlapping, overlapUnion) { + var currIndex = 0; + do { + var root = refPaths[currIndex]; + do { + var overlaps = false; + for (var i = currIndex + 1; i < refPaths.length; i++) { + var arcRef = refPaths[i]; + overlaps = isOverlapping(root.pathContext, arcRef.pathContext, false); + if (overlaps) { + overlapUnion(root.pathContext, arcRef.pathContext); + delete arcRef.modelContext.paths[arcRef.pathId]; + refPaths.splice(i, 1); + break; + } + } + } while (overlaps); + currIndex++; + } while (currIndex < refPaths.length); + } + /** + * @private + */ + function normalizedArcLimits(arc) { + var startAngle = MakerJs.angle.noRevolutions(arc.startAngle); + return { + startAngle: startAngle, + endAngle: MakerJs.angle.ofArcSpan(arc) + startAngle + }; + } + /** + * Simplify a model's paths by reducing redundancy: combine multiple overlapping paths into a single path. + * + * @param modelContext The model to search for similar paths. + * @param options Optional options object. + * @returns The simplified model (for chaining). + */ + function simplify(modelToSimplify, options) { + function compareCircles(circle1, circle2) { + if (Math.abs(circle1.radius - circle2.radius) <= opts.scalarMatchingDistance) { + var distance = MakerJs.measure.pointDistance(circle1.origin, circle2.origin); + return distance <= opts.pointMatchingDistance; + } + return false; + } + var similarArcs = new MakerJs.Collector(compareCircles); + var similarCircles = new MakerJs.Collector(compareCircles); + var similarLines = new MakerJs.Collector(MakerJs.measure.isSlopeEqual); + var map = {}; + map[MakerJs.pathType.Arc] = function (arcRef) { + similarArcs.addItemToCollection(arcRef.pathContext, arcRef); + }; + map[MakerJs.pathType.Circle] = function (circleRef) { + similarCircles.addItemToCollection(circleRef.pathContext, circleRef); + }; + map[MakerJs.pathType.Line] = function (lineRef) { + var slope = MakerJs.measure.lineSlope(lineRef.pathContext); + similarLines.addItemToCollection(slope, lineRef); + }; + var opts = { + scalarMatchingDistance: .001, + pointMatchingDistance: .005 + }; + MakerJs.extendObject(opts, options); + //walk the model and collect: arcs on same center / radius, circles on same center / radius, lines on same y-intercept / slope. + model.walkPaths(modelToSimplify, function (modelContext, pathId, pathContext) { + var ref = { + modelContext: modelContext, + pathContext: pathContext, + pathId: pathId + }; + var fn = map[pathContext.type]; + if (fn) { + fn(ref); + } + }); + //for all arcs that are similar, see if they overlap. + //combine overlapping arcs into the first one and delete the second. + similarArcs.getCollectionsOfMultiple(function (key, arcRefs) { + checkForOverlaps(arcRefs, MakerJs.measure.isArcOverlapping, function (arc1, arc2) { + var limit1 = normalizedArcLimits(arc1); + var limit2 = normalizedArcLimits(arc2); + arc1.startAngle = Math.min(limit1.startAngle, limit2.startAngle); + arc1.endAngle = Math.max(limit1.endAngle, limit2.endAngle); + }); + }); + //for all circles that are similar, delete all but the first. + similarCircles.getCollectionsOfMultiple(function (key, circleRefs) { + for (var i = 1; i < circleRefs.length; i++) { + var circleRef = circleRefs[i]; + delete circleRef.modelContext.paths[circleRef.pathId]; + } + }); + //for all lines that are similar, see if they overlap. + //combine overlapping lines into the first one and delete the second. + similarLines.getCollectionsOfMultiple(function (slope, arcRefs) { + checkForOverlaps(arcRefs, MakerJs.measure.isLineOverlapping, function (line1, line2) { + var box = { paths: { line1: line1, line2: line2 } }; + var m = MakerJs.measure.modelExtents(box); + if (!slope.hasSlope) { + //vertical + line1.origin[1] = m.low[1]; + line1.end[1] = m.high[1]; + } + else { + //non-vertical + if (slope.slope < 0) { + //downward + line1.origin = [m.low[0], m.high[1]]; + line1.end = [m.high[0], m.low[1]]; + } + else if (slope.slope > 0) { + //upward + line1.origin = m.low; + line1.end = m.high; + } + else { + //horizontal + line1.origin[0] = m.low[0]; + line1.end[0] = m.high[0]; + } + } + }); + }); + return modelToSimplify; + } + model.simplify = simplify; + })(model = MakerJs.model || (MakerJs.model = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var path; + (function (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, expansion, isolateCaps) { + if (!pathToExpand) + return null; + var result; + var map = {}; + map[MakerJs.pathType.Arc] = function (arc) { + result = new MakerJs.models.OvalArc(arc.startAngle, arc.endAngle, arc.radius, expansion, false, isolateCaps); + }; + map[MakerJs.pathType.Circle] = function (circle) { + result = new MakerJs.models.Ring(circle.radius + expansion, circle.radius - expansion); + }; + map[MakerJs.pathType.Line] = function (line) { + result = new MakerJs.models.Slot(line.origin, line.end, expansion, isolateCaps); + }; + var fn = map[pathToExpand.type]; + if (fn) { + fn(pathToExpand); + result.origin = pathToExpand.origin; + } + return result; + } + path.expand = expand; + /** + * 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. + * @returns Model of straight lines with same endpoints as the arc. + */ + function straighten(arc, bevel) { + var arcSpan = MakerJs.angle.ofArcSpan(arc); + var joints = 1; + if (arcSpan >= 270) { + joints = 4; + } + else if (arcSpan > 180) { + joints = 3; + } + else if (arcSpan > 150 || bevel) { + joints = 2; + } + var jointAngleInRadians = MakerJs.angle.toRadians(arcSpan / joints); + var circumscribedRadius = MakerJs.models.Polygon.circumscribedRadius(arc.radius, jointAngleInRadians); + var ends = MakerJs.point.fromArc(arc); + var points = [MakerJs.point.subtract(ends[0], arc.origin)]; + var a = MakerJs.angle.toRadians(arc.startAngle) + jointAngleInRadians / 2; + for (var i = 0; i < joints; i++) { + points.push(MakerJs.point.fromPolar(a, circumscribedRadius)); + a += jointAngleInRadians; + } + points.push(MakerJs.point.subtract(ends[1], arc.origin)); + var result = new MakerJs.models.ConnectTheDots(false, points); + result.origin = arc.origin; + return result; + } + path.straighten = straighten; + })(path = MakerJs.path || (MakerJs.path = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var model; + (function (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, distance, joints) { + if (joints === void 0) { joints = 0; } + if (distance <= 0) + return null; + var result = { + models: { + expansions: { models: {} }, + caps: { models: {} } + } + }; + var first = true; + //TODO: work without origination + var originated = model.originate(modelToExpand); + model.walkPaths(originated, function (modelContext, pathId, pathContext) { + var expandedPathModel = MakerJs.path.expand(pathContext, distance, true); + if (expandedPathModel) { + var newId = model.getSimilarModelId(result.models['expansions'], pathId); + model.originate(expandedPathModel); + if (!first) { + model.combine(result, expandedPathModel); + } + result.models['expansions'].models[newId] = expandedPathModel; + if (expandedPathModel.models) { + var caps = expandedPathModel.models['Caps']; + if (caps) { + delete expandedPathModel.models['Caps']; + result.models['caps'].models[newId] = caps; + } + } + first = false; + } + }); + if (joints) { + var roundCaps = result.models['caps']; + model.simplify(roundCaps); + var straightCaps = { models: {} }; + //straighten each cap, optionally beveling + for (var id in roundCaps.models) { + var straightened = { models: {} }; + model.walkPaths(roundCaps.models[id], function (modelContext, pathId, pathContext) { + straightened.models[pathId] = MakerJs.path.straighten(pathContext, joints == 2); + }); + straightCaps.models[id] = straightened; + } + //replace the rounded with the straightened + result.models['caps'] = straightCaps; + } + return result; + } + model.expandPaths = expandPaths; + /** + * Outline a model by a specified distance. Useful for accommadating 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. + * @returns Model which surrounds the paths outside of the original model. + */ + function outline(modelToOutline, distance, joints) { + var expanded = expandPaths(modelToOutline, distance, joints); + if (!expanded) + return null; + var loops = model.findLoops(expanded); + if (loops && loops.models) { + var i = 0; + while (loops.models[i]) { + delete loops.models[i + 1]; + delete loops.models[i + 2]; + i += 4; + } + return loops; + } + return null; + } + model.outline = outline; + })(model = MakerJs.model || (MakerJs.model = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var units; + (function (units) { + /** + * The base type is arbitrary. Other conversions are then based off of this. + * @private + */ + var base = MakerJs.unitType.Millimeter; + /** + * Initialize all known conversions here. + * @private + */ + function init() { + addBaseConversion(MakerJs.unitType.Centimeter, 10); + addBaseConversion(MakerJs.unitType.Meter, 1000); + addBaseConversion(MakerJs.unitType.Inch, 25.4); + addBaseConversion(MakerJs.unitType.Foot, 25.4 * 12); + } + /** + * Table of conversions. Lazy load upon first conversion. + * @private + */ + var table; + /** + * Add a conversion, and its inversion. + * @private + */ + function addConversion(srcUnitType, destUnitType, value) { + function row(unitType) { + if (!table[unitType]) { + table[unitType] = {}; + } + return table[unitType]; + } + row(srcUnitType)[destUnitType] = value; + row(destUnitType)[srcUnitType] = 1 / value; + } + /** + * Add a conversion of the base unit. + * @private + */ + function addBaseConversion(destUnitType, value) { + addConversion(destUnitType, base, value); + } + /** + * Get a conversion ratio between a source unit and a destination unit. + * + * @param srcUnitType unitType converting from. + * @param destUnitType unitType converting to. + * @returns Numeric ratio of the conversion. + */ + function conversionScale(srcUnitType, destUnitType) { + if (srcUnitType == destUnitType) { + return 1; + } + //This will lazy load the table with initial conversions. + if (!table) { + table = {}; + init(); + } + //look for a cached conversion in the table. + if (!table[srcUnitType][destUnitType]) { + //create a new conversionsand cache it in the table. + addConversion(srcUnitType, destUnitType, table[srcUnitType][base] * table[base][destUnitType]); + } + return table[srcUnitType][destUnitType]; + } + units.conversionScale = conversionScale; + })(units = MakerJs.units || (MakerJs.units = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var measure; + (function (measure) { + /** + * 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 isAngleEqual(angle1, angle2, accuracy) { + if (accuracy === void 0) { accuracy = .0001; } + var a1 = MakerJs.angle.noRevolutions(angle1); + var a2 = MakerJs.angle.noRevolutions(angle2); + var d = MakerJs.angle.noRevolutions(MakerJs.round(a2 - a1, accuracy)); + return d == 0; + } + measure.isAngleEqual = isAngleEqual; + /** + * @private + */ + var pathAreEqualMap = {}; + pathAreEqualMap[MakerJs.pathType.Line] = function (line1, line2, withinPointDistance) { + return (isPointEqual(line1.origin, line2.origin, withinPointDistance) && isPointEqual(line1.end, line2.end, withinPointDistance)) + || (isPointEqual(line1.origin, line2.end, withinPointDistance) && isPointEqual(line1.end, line2.origin, withinPointDistance)); + }; + pathAreEqualMap[MakerJs.pathType.Circle] = function (circle1, circle2, withinPointDistance) { + return isPointEqual(circle1.origin, circle2.origin, withinPointDistance) && circle1.radius == circle2.radius; + }; + pathAreEqualMap[MakerJs.pathType.Arc] = function (arc1, arc2, withinPointDistance) { + return pathAreEqualMap[MakerJs.pathType.Circle](arc1, arc2, withinPointDistance) && isAngleEqual(arc1.startAngle, arc2.startAngle) && isAngleEqual(arc1.endAngle, arc2.endAngle); + }; + /** + * Find out if two paths are equal. + * + * @param a First path. + * @param b Second path. + * @returns true if paths are the same, false if they are not + */ + function isPathEqual(path1, path2, withinPointDistance) { + var result = false; + if (path1.type == path2.type) { + var fn = pathAreEqualMap[path1.type]; + if (fn) { + result = fn(path1, path2, withinPointDistance); + } + } + return result; + } + measure.isPathEqual = isPathEqual; + /** + * 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, b, withinDistance) { + if (!withinDistance) { + return a[0] == b[0] && a[1] == b[1]; + } + else { + var distance = measure.pointDistance(a, b); + return distance <= withinDistance; + } + } + measure.isPointEqual = isPointEqual; + /** + * Check for slope equality. + * + * @param slope1 The ISlope to test. + * @param slope2 The ISlope to check for equality. + * @returns Boolean true if slopes are equal. + */ + function isSlopeEqual(slope1, slope2) { + if (!slope1.hasSlope && !slope2.hasSlope) { + //lines are both vertical, see if x are the same + return MakerJs.round(slope1.line.origin[0] - slope2.line.origin[0]) == 0; + } + if (slope1.hasSlope && slope2.hasSlope && (MakerJs.round(slope1.slope - slope2.slope, .00001) == 0)) { + //lines are parallel, but not vertical, see if y-intercept is the same + return MakerJs.round(slope1.yIntercept - slope2.yIntercept, .00001) == 0; + } + return false; + } + measure.isSlopeEqual = isSlopeEqual; + })(measure = MakerJs.measure || (MakerJs.measure = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var measure; + (function (measure_1) { + /** + * Check for arc being concave or convex towards a given point. + * + * @param arc The arc to test. + * @param towardsPoint The point to test. + * @returns Boolean true if arc is concave towards point. + */ + function isArcConcaveTowardsPoint(arc, towardsPoint) { + if (pointDistance(arc.origin, towardsPoint) <= arc.radius) { + return true; + } + var midPointToNearPoint = new MakerJs.paths.Line(MakerJs.point.middle(arc), towardsPoint); + var options = {}; + var intersectionPoint = MakerJs.path.intersection(midPointToNearPoint, new MakerJs.paths.Chord(arc), options); + if (intersectionPoint || options.out_AreOverlapped) { + return true; + } + return false; + } + measure_1.isArcConcaveTowardsPoint = isArcConcaveTowardsPoint; + /** + * Check for arc overlapping another arc. + * + * @param arc1 The arc to test. + * @param arc2 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 arc2. + */ + function isArcOverlapping(arc1, arc2, excludeTangents) { + var pointsOfIntersection = []; + function checkAngles(a, b) { + function checkAngle(n) { + return measure.isBetweenArcAngles(n, a, excludeTangents); + } + return checkAngle(b.startAngle) || checkAngle(b.endAngle); + } + return checkAngles(arc1, arc2) || checkAngles(arc2, arc1) || (arc1.startAngle == arc2.startAngle && arc1.endAngle == arc2.endAngle); + } + measure_1.isArcOverlapping = isArcOverlapping; + /** + * 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 exclusive Flag to exclude equaling the limits. + * @returns Boolean true if value is between (or equal to) the limits. + */ + function isBetween(valueInQuestion, limit1, limit2, exclusive) { + if (exclusive) { + return Math.min(limit1, limit2) < valueInQuestion && valueInQuestion < Math.max(limit1, limit2); + } + else { + return Math.min(limit1, limit2) <= valueInQuestion && valueInQuestion <= Math.max(limit1, limit2); + } + } + measure_1.isBetween = isBetween; + /** + * Check if a given angle is between an arc's start and end angles. + * + * @param angleInQuestion The angle to test. + * @param arc Arc to test against. + * @param exclusive Flag to exclude equaling the start or end angles. + * @returns Boolean true if angle is between (or equal to) the arc's start and end angles. + */ + function isBetweenArcAngles(angleInQuestion, arc, exclusive) { + var startAngle = MakerJs.angle.noRevolutions(arc.startAngle); + var span = MakerJs.angle.ofArcSpan(arc); + var endAngle = startAngle + span; + angleInQuestion = MakerJs.angle.noRevolutions(angleInQuestion); + //computed angles will not be negative, but the arc may have specified a negative angle, so check against one revolution forward and backward + return (isBetween(angleInQuestion, startAngle, endAngle, exclusive) || isBetween(angleInQuestion, startAngle + 360, endAngle + 360, exclusive) || isBetween(angleInQuestion, startAngle - 360, endAngle - 360, exclusive)); + } + measure_1.isBetweenArcAngles = isBetweenArcAngles; + /** + * Check if a given point is between a line's end points. + * + * @param pointInQuestion The point to test. + * @param line Line to test against. + * @param exclusive Flag to exclude equaling the origin or end points. + * @returns Boolean true if point is between (or equal to) the line's origin and end points. + */ + function isBetweenPoints(pointInQuestion, line, exclusive) { + for (var i = 2; i--;) { + if (MakerJs.round(line.origin[i] - line.end[i], .000001) == 0) { + continue; + } + var origin_value = MakerJs.round(line.origin[i]); + var end_value = MakerJs.round(line.end[i]); + if (!isBetween(MakerJs.round(pointInQuestion[i]), origin_value, end_value, exclusive)) + return false; + } + return true; + } + measure_1.isBetweenPoints = isBetweenPoints; + /** + * Check for line overlapping another line. + * + * @param line1 The line to test. + * @param line2 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 line2. + */ + function isLineOverlapping(line1, line2, excludeTangents) { + var pointsOfIntersection = []; + function checkPoints(index, a, b) { + function checkPoint(p) { + return measure.isBetweenPoints(p, a, excludeTangents); + } + return checkPoint(b.origin) || checkPoint(b.end); + } + return checkPoints(0, line1, line2) || checkPoints(1, line2, line1); + } + measure_1.isLineOverlapping = isLineOverlapping; + /** + * Gets the slope of a line. + */ + function lineSlope(line) { + var dx = line.end[0] - line.origin[0]; + if (MakerJs.round(dx) == 0) { + return { + line: line, + hasSlope: false + }; + } + var dy = line.end[1] - line.origin[1]; + var slope = dy / dx; + var yIntercept = line.origin[1] - slope * line.origin[0]; + return { + line: line, + hasSlope: true, + slope: slope, + yIntercept: yIntercept + }; + } + measure_1.lineSlope = lineSlope; + /** + * Calculates the distance between two points. + * + * @param a First point. + * @param b Second point. + * @returns Distance between points. + */ + function pointDistance(a, b) { + var dx = b[0] - a[0]; + var dy = b[1] - a[1]; + return Math.sqrt(dx * dx + dy * dy); + } + measure_1.pointDistance = pointDistance; + /** + * @private + */ + function getExtremePoint(a, b, fn) { + return [ + fn(a[0], b[0]), + fn(a[1], b[1]) + ]; + } + /** + * Calculates the smallest rectangle which contains a path. + * + * @param pathToMeasure The path to measure. + * @returns object with low and high points. + */ + function pathExtents(pathToMeasure) { + var map = {}; + var measurement = { low: null, high: null }; + map[MakerJs.pathType.Line] = function (line) { + measurement.low = getExtremePoint(line.origin, line.end, Math.min); + measurement.high = getExtremePoint(line.origin, line.end, Math.max); + }; + map[MakerJs.pathType.Circle] = function (circle) { + var r = circle.radius; + measurement.low = MakerJs.point.add(circle.origin, [-r, -r]); + measurement.high = MakerJs.point.add(circle.origin, [r, r]); + }; + map[MakerJs.pathType.Arc] = function (arc) { + var r = arc.radius; + var arcPoints = MakerJs.point.fromArc(arc); + function extremeAngle(xyAngle, value, fn) { + var extremePoint = getExtremePoint(arcPoints[0], arcPoints[1], fn); + for (var i = 2; i--;) { + if (isBetweenArcAngles(xyAngle[i], arc, false)) { + extremePoint[i] = value + arc.origin[i]; + } + } + return extremePoint; + } + measurement.low = extremeAngle([180, 270], -r, Math.min); + measurement.high = extremeAngle([360, 90], r, Math.max); + }; + if (pathToMeasure) { + var fn = map[pathToMeasure.type]; + if (fn) { + fn(pathToMeasure); + } + } + return measurement; + } + measure_1.pathExtents = pathExtents; + /** + * Measures the length of a path. + * + * @param pathToMeasure The path to measure. + * @returns Length of the path. + */ + function pathLength(pathToMeasure) { + var map = {}; + var value = 0; + map[MakerJs.pathType.Line] = function (line) { + value = pointDistance(line.origin, line.end); + }; + map[MakerJs.pathType.Circle] = function (circle) { + value = 2 * Math.PI * circle.radius; + }; + map[MakerJs.pathType.Arc] = function (arc) { + map[MakerJs.pathType.Circle](arc); //this sets the value var + var pct = MakerJs.angle.ofArcSpan(arc) / 360; + value *= pct; + }; + var fn = map[pathToMeasure.type]; + if (fn) { + fn(pathToMeasure); + } + return value; + } + measure_1.pathLength = pathLength; + /** + * Measures the smallest rectangle which contains a model. + * + * @param modelToMeasure The model to measure. + * @returns object with low and high points. + */ + function modelExtents(modelToMeasure) { + var totalMeasurement = { low: [null, null], high: [null, null] }; + function lowerOrHigher(offsetOrigin, pathMeasurement) { + function getExtreme(a, b, fn) { + var c = MakerJs.point.add(b, offsetOrigin); + for (var i = 2; i--;) { + a[i] = (a[i] == null ? c[i] : fn(a[i], c[i])); + } + } + getExtreme(totalMeasurement.low, pathMeasurement.low, Math.min); + getExtreme(totalMeasurement.high, pathMeasurement.high, Math.max); + } + function measure(modelToMeasure, offsetOrigin) { + if (!modelToMeasure) + return; + var newOrigin = MakerJs.point.add(modelToMeasure.origin, offsetOrigin); + if (modelToMeasure.paths) { + for (var id in modelToMeasure.paths) { + lowerOrHigher(newOrigin, pathExtents(modelToMeasure.paths[id])); + } + } + if (modelToMeasure.models) { + for (var id in modelToMeasure.models) { + measure(modelToMeasure.models[id], newOrigin); + } + } + } + measure(modelToMeasure); + return totalMeasurement; + } + measure_1.modelExtents = modelExtents; + })(measure = MakerJs.measure || (MakerJs.measure = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var exporter; + (function (exporter) { + /** + * Try to get the unit system from a model + * @private + */ + function tryGetModelUnits(itemToExport) { + if (MakerJs.isModel(itemToExport)) { + return itemToExport.units; + } + } + exporter.tryGetModelUnits = tryGetModelUnits; + /** + * Class to traverse an item 's models or paths and ultimately render each path. + * @private + */ + var Exporter = (function () { + /** + * @param map Object containing properties: property name is the type of path, e.g. "line", "circle"; property value + * is a function to render a path. Function parameters are path and point. + * @param fixPoint Optional function to modify a point prior to export. Function parameter is a point; function must return a point. + * @param fixPath Optional function to modify a path prior to output. Function parameters are path and offset point; function must return a path. + */ + function Exporter(map, fixPoint, fixPath, beginModel, endModel) { + this.map = map; + this.fixPoint = fixPoint; + this.fixPath = fixPath; + this.beginModel = beginModel; + this.endModel = endModel; + } + /** + * Export a path. + * + * @param pathToExport The path to export. + * @param offset The offset position of the path. + */ + Exporter.prototype.exportPath = function (id, pathToExport, offset, layer) { + if (pathToExport) { + var fn = this.map[pathToExport.type]; + if (fn) { + fn(id, this.fixPath ? this.fixPath(pathToExport, offset) : pathToExport, offset, layer); + } + } + }; + /** + * Export a model. + * + * @param modelToExport The model to export. + * @param offset The offset position of the model. + */ + Exporter.prototype.exportModel = function (modelId, modelToExport, offset) { + if (this.beginModel) { + this.beginModel(modelId, modelToExport); + } + var newOffset = MakerJs.point.add((this.fixPoint ? this.fixPoint(modelToExport.origin) : modelToExport.origin), offset); + if (modelToExport.paths) { + for (var id in modelToExport.paths) { + var currPath = modelToExport.paths[id]; + if (!currPath) + continue; + this.exportPath(id, currPath, newOffset, currPath.layer || modelToExport.layer); + } + } + if (modelToExport.models) { + for (var id in modelToExport.models) { + var currModel = modelToExport.models[id]; + if (!currModel) + continue; + this.exportModel(id, currModel, newOffset); + } + } + if (this.endModel) { + this.endModel(modelToExport); + } + }; + /** + * Export an object. + * + * @param item The object to export. May be a path, an array of paths, a model, or an array of models. + * @param offset The offset position of the object. + */ + Exporter.prototype.exportItem = function (itemId, itemToExport, origin) { + if (MakerJs.isModel(itemToExport)) { + this.exportModel(itemId, itemToExport, origin); + } + else if (MakerJs.isPath(itemToExport)) { + this.exportPath(itemId, itemToExport, origin, null); + } + else { + for (var id in itemToExport) { + this.exportItem(id, itemToExport[id], origin); + } + } + }; + return Exporter; + }()); + exporter.Exporter = Exporter; + })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var exporter; + (function (exporter_1) { + /** + * Renders an item in AutoDesk DFX file format. + * + * @param itemToExport Item to render: may be a path, an array of paths, or a model object. + * @param options Rendering options object. + * @param options.units String of the unit system. May be omitted. See makerjs.unitType for possible values. + * @returns String of DXF content. + */ + function toDXF(itemToExport, options) { + //DXF format documentation: + //http://images.autodesk.com/adsk/files/acad_dxf0.pdf + if (options === void 0) { options = {}; } + var opts = {}; + MakerJs.extendObject(opts, options); + if (MakerJs.isModel(itemToExport)) { + var modelToExport = itemToExport; + if (modelToExport.exporterOptions) { + MakerJs.extendObject(opts, modelToExport.exporterOptions['toDXF']); + } + } + var dxf = []; + function append(value) { + dxf.push(value); + } + function defaultLayer(pathContext, layer) { + return pathContext.layer || layer || 0; + } + var map = {}; + map[MakerJs.pathType.Line] = function (id, line, origin, layer) { + append("0"); + append("LINE"); + append("8"); + append(defaultLayer(line, layer)); + append("10"); + append(line.origin[0] + origin[0]); + append("20"); + append(line.origin[1] + origin[1]); + append("11"); + append(line.end[0] + origin[0]); + append("21"); + append(line.end[1] + origin[1]); + }; + map[MakerJs.pathType.Circle] = function (id, circle, origin, layer) { + append("0"); + append("CIRCLE"); + append("8"); + append(defaultLayer(circle, layer)); + append("10"); + append(circle.origin[0] + origin[0]); + append("20"); + append(circle.origin[1] + origin[1]); + append("40"); + append(circle.radius); + }; + map[MakerJs.pathType.Arc] = function (id, arc, origin, layer) { + append("0"); + append("ARC"); + append("8"); + append(defaultLayer(arc, layer)); + append("10"); + append(arc.origin[0] + origin[0]); + append("20"); + append(arc.origin[1] + origin[1]); + append("40"); + append(arc.radius); + append("50"); + append(arc.startAngle); + append("51"); + append(arc.endAngle); + }; + function section(sectionFn) { + append("0"); + append("SECTION"); + sectionFn(); + append("0"); + append("ENDSEC"); + } + function header() { + var units = dxfUnit[opts.units]; + append("2"); + append("HEADER"); + append("9"); + append("$INSUNITS"); + append("70"); + append(units); + } + function entities() { + append("2"); + append("ENTITIES"); + var exporter = new exporter_1.Exporter(map); + exporter.exportItem('entities', itemToExport, MakerJs.point.zero()); + } + //fixup options + if (!opts.units) { + var units = exporter_1.tryGetModelUnits(itemToExport); + if (units) { + opts.units = units; + } + } + //also pass back to options parameter + MakerJs.extendObject(options, opts); + //begin dxf output + if (opts.units) { + section(header); + } + section(entities); + append("0"); + append("EOF"); + return dxf.join('\n'); + } + exporter_1.toDXF = toDXF; + /** + * @private + */ + var dxfUnit = {}; + //DXF format documentation: + //http://images.autodesk.com/adsk/files/acad_dxf0.pdf + //Default drawing units for AutoCAD DesignCenter blocks: + //0 = Unitless; 1 = Inches; 2 = Feet; 3 = Miles; 4 = Millimeters; 5 = Centimeters; 6 = Meters; 7 = Kilometers; 8 = Microinches; + dxfUnit[''] = 0; + dxfUnit[MakerJs.unitType.Inch] = 1; + dxfUnit[MakerJs.unitType.Foot] = 2; + dxfUnit[MakerJs.unitType.Millimeter] = 4; + dxfUnit[MakerJs.unitType.Centimeter] = 5; + dxfUnit[MakerJs.unitType.Meter] = 6; + })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var solvers; + (function (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. + * @returns Angle opposite of the side represented by the first parameter. + */ + function solveTriangleSSS(length1, length2, length3) { + return MakerJs.angle.toDegrees(Math.acos((length2 * length2 + length3 * length3 - length1 * length1) / (2 * length2 * length3))); + } + solvers.solveTriangleSSS = solveTriangleSSS; + /** + * Solves for the length of a side of a triangle when you know length of one side and 2 angles. + * + * @param oppositeAngleInDegrees Angle which is opposite of the side you are trying to find. + * @param lengthOfSideBetweenAngles Length of one side of the triangle which is between the provided angles. + * @param otherAngleInDegrees An other angle of the triangle. + * @returns Length of the side of the triangle which is opposite of the first angle parameter. + */ + function solveTriangleASA(oppositeAngleInDegrees, lengthOfSideBetweenAngles, otherAngleInDegrees) { + var angleOppositeSide = 180 - oppositeAngleInDegrees - otherAngleInDegrees; + return (lengthOfSideBetweenAngles * Math.sin(MakerJs.angle.toRadians(oppositeAngleInDegrees))) / Math.sin(MakerJs.angle.toRadians(angleOppositeSide)); + } + solvers.solveTriangleASA = solveTriangleASA; + })(solvers = MakerJs.solvers || (MakerJs.solvers = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var path; + (function (path) { + /** + * @private + */ + var map = {}; + map[MakerJs.pathType.Arc] = {}; + map[MakerJs.pathType.Circle] = {}; + map[MakerJs.pathType.Line] = {}; + map[MakerJs.pathType.Arc][MakerJs.pathType.Arc] = function (arc1, arc2, options) { + var angles = circleToCircle(arc1, arc2, options); + if (angles) { + var arc1Angles = getAnglesWithinArc(angles[0], arc1, options); + var arc2Angles = getAnglesWithinArc(angles[1], arc2, options); + if (arc1Angles && arc2Angles) { + return { + intersectionPoints: pointsFromAnglesOnCircle(arc1Angles, arc1), + path1Angles: arc1Angles, + path2Angles: arc2Angles + }; + } + } + else { + if (options.out_AreOverlapped) { + //overlapped for circle, reset and see if arcs actually overlap. + options.out_AreOverlapped = MakerJs.measure.isArcOverlapping(arc1, arc2, options.excludeTangents); + } + } + return null; + }; + map[MakerJs.pathType.Arc][MakerJs.pathType.Circle] = function (arc, circle, options) { + var angles = circleToCircle(arc, circle, options); + if (angles) { + var arcAngles = getAnglesWithinArc(angles[0], arc, options); + if (arcAngles) { + var circleAngles; + //if both point are on arc, use both on circle + if (arcAngles.length == 2) { + circleAngles = angles[1]; + } + else { + //use the corresponding point on circle + var index = findCorrespondingAngleIndex(angles, arcAngles); + circleAngles = [angles[1][index]]; + } + return { + intersectionPoints: pointsFromAnglesOnCircle(arcAngles, arc), + path1Angles: arcAngles, + path2Angles: circleAngles + }; + } + } + return null; + }; + map[MakerJs.pathType.Arc][MakerJs.pathType.Line] = function (arc, line, options) { + var angles = lineToCircle(line, arc, options); + if (angles) { + var arcAngles = getAnglesWithinArc(angles, arc, options); + if (arcAngles) { + return { + intersectionPoints: pointsFromAnglesOnCircle(arcAngles, arc), + path1Angles: arcAngles + }; + } + } + return null; + }; + map[MakerJs.pathType.Circle][MakerJs.pathType.Arc] = function (circle, arc, options) { + var result = map[MakerJs.pathType.Arc][MakerJs.pathType.Circle](arc, circle, options); + if (result) { + return swap(result); + } + return null; + }; + map[MakerJs.pathType.Circle][MakerJs.pathType.Circle] = function (circle1, circle2, options) { + var angles = circleToCircle(circle1, circle2, options); + if (angles) { + return { + intersectionPoints: pointsFromAnglesOnCircle(angles[0], circle1), + path1Angles: angles[0], + path2Angles: angles[1] + }; + } + return null; + }; + map[MakerJs.pathType.Circle][MakerJs.pathType.Line] = function (circle, line, options) { + var angles = lineToCircle(line, circle, options); + if (angles) { + return { + intersectionPoints: pointsFromAnglesOnCircle(angles, circle), + path1Angles: angles + }; + } + return null; + }; + map[MakerJs.pathType.Line][MakerJs.pathType.Arc] = function (line, arc, options) { + var result = map[MakerJs.pathType.Arc][MakerJs.pathType.Line](arc, line, options); + if (result) { + return swap(result); + } + return null; + }; + map[MakerJs.pathType.Line][MakerJs.pathType.Circle] = function (line, circle, options) { + var result = map[MakerJs.pathType.Circle][MakerJs.pathType.Line](circle, line, options); + if (result) { + return swap(result); + } + return null; + }; + map[MakerJs.pathType.Line][MakerJs.pathType.Line] = function (line1, line2, options) { + var intersectionPoint = MakerJs.point.fromSlopeIntersection(line1, line2, options); + if (intersectionPoint) { + //we have the point of intersection of endless lines, now check to see if the point is between both segemnts + if (MakerJs.measure.isBetweenPoints(intersectionPoint, line1, options.excludeTangents) && MakerJs.measure.isBetweenPoints(intersectionPoint, line2, options.excludeTangents)) { + return { + intersectionPoints: [intersectionPoint] + }; + } + } + return null; + }; + /** + * @private + */ + function swap(result) { + var temp = result.path1Angles; + if (result.path2Angles) { + result.path1Angles = result.path2Angles; + } + else { + delete result.path1Angles; + } + result.path2Angles = temp; + return result; + } + /** + * Find the point(s) where 2 paths intersect. + * + * @param path1 First path to find intersection. + * @param path2 Second path to find intersection. + * @param options Optional IPathIntersectionOptions. + * @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, path2, options) { + if (options === void 0) { options = {}; } + if (path1 && path2) { + var fn = map[path1.type][path2.type]; + if (fn) { + return fn(path1, path2, options); + } + } + return null; + } + path.intersection = intersection; + /** + * @private + */ + function findCorrespondingAngleIndex(circleAngles, arcAngle) { + for (var i = 0; i < circleAngles.length; i++) { + if (circleAngles[i][0] == arcAngle[0]) + return i; + } + } + /** + * @private + */ + function pointsFromAnglesOnCircle(anglesInDegrees, circle) { + var result = []; + for (var i = 0; i < anglesInDegrees.length; i++) { + result.push(MakerJs.point.fromAngleOnCircle(anglesInDegrees[i], circle)); + } + return result; + } + /** + * @private + */ + function getAnglesWithinArc(angles, arc, options) { + if (!angles) + return null; + var anglesWithinArc = []; + for (var i = 0; i < angles.length; i++) { + if (MakerJs.measure.isBetweenArcAngles(angles[i], arc, options.excludeTangents)) { + anglesWithinArc.push(angles[i]); + } + } + if (anglesWithinArc.length == 0) + return null; + return anglesWithinArc; + } + /** + * @private + */ + function lineToCircle(line, circle, options) { + var radius = MakerJs.round(circle.radius); + //clone the line + var clonedLine = new MakerJs.paths.Line(MakerJs.point.subtract(line.origin, circle.origin), MakerJs.point.subtract(line.end, circle.origin)); + //get angle of line + var lineAngleNormal = MakerJs.angle.ofLineInDegrees(line); + //use the positive horizontal angle + var lineAngle = (lineAngleNormal >= 180) ? lineAngleNormal - 360 : lineAngleNormal; + //rotate the line to horizontal + path.rotate(clonedLine, -lineAngle, MakerJs.point.zero()); + //remember how to undo the rotation we just did + function unRotate(resultAngle) { + var unrotated = resultAngle + lineAngle; + return MakerJs.angle.noRevolutions(unrotated); + } + //line is horizontal, get the y value from any point + var lineY = MakerJs.round(clonedLine.origin[1]); + var lineYabs = Math.abs(lineY); + //if y is greater than radius, there is no intersection + if (lineYabs > radius) { + return null; + } + var anglesOfIntersection = []; + //if horizontal Y is the same as the radius, we know it's 90 degrees + if (lineYabs == radius) { + if (options.excludeTangents) { + return null; + } + anglesOfIntersection.push(unRotate(lineY > 0 ? 90 : 270)); + } + else { + function intersectionBetweenEndpoints(x, angleOfX) { + if (MakerJs.measure.isBetween(MakerJs.round(x), MakerJs.round(clonedLine.origin[0]), MakerJs.round(clonedLine.end[0]), options.excludeTangents)) { + anglesOfIntersection.push(unRotate(angleOfX)); + } + } + //find angle where line intersects + var intersectRadians = Math.asin(lineY / radius); + var intersectDegrees = MakerJs.angle.toDegrees(intersectRadians); + //line may intersect in 2 places + var intersectX = Math.cos(intersectRadians) * radius; + intersectionBetweenEndpoints(-intersectX, 180 - intersectDegrees); + intersectionBetweenEndpoints(intersectX, intersectDegrees); + } + if (anglesOfIntersection.length > 0) { + return anglesOfIntersection; + } + return null; + } + /** + * @private + */ + function circleToCircle(circle1, circle2, options) { + //see if circles are the same + if (circle1.radius == circle2.radius && MakerJs.measure.isPointEqual(circle1.origin, circle2.origin, .0001)) { + options.out_AreOverlapped = true; + return null; + } + //get offset from origin + var offset = MakerJs.point.subtract(MakerJs.point.zero(), circle1.origin); + //clone circle1 and move to origin + var c1 = new MakerJs.paths.Circle(MakerJs.point.zero(), circle1.radius); + //clone circle2 and move relative to circle1 + var c2 = new MakerJs.paths.Circle(MakerJs.point.subtract(circle2.origin, circle1.origin), circle2.radius); + //rotate circle2 to horizontal, c2 will be to the right of the origin. + var c2Angle = MakerJs.angle.ofPointInDegrees(MakerJs.point.zero(), c2.origin); + path.rotate(c2, -c2Angle, MakerJs.point.zero()); + function unRotate(resultAngle) { + var unrotated = resultAngle + c2Angle; + return MakerJs.angle.noRevolutions(unrotated); + } + //get X of c2 origin + var x = c2.origin[0]; + //see if c2 is outside of c1 + if (x - c2.radius > c1.radius) { + return null; + } + //see if c2 is within c1 + if (x + c2.radius < c1.radius) { + return null; + } + //see if c1 is within c2 + if (x - c2.radius < -c1.radius) { + return null; + } + //see if circles are tangent interior + if (MakerJs.round(c2.radius - x - c1.radius) == 0) { + if (options.excludeTangents) { + return null; + } + return [[unRotate(180)], [unRotate(180)]]; + } + //see if circles are tangent exterior + if (MakerJs.round(x - c2.radius - c1.radius) == 0) { + if (options.excludeTangents) { + return null; + } + return [[unRotate(0)], [unRotate(180)]]; + } + function bothAngles(oneAngle) { + return [unRotate(oneAngle), unRotate(MakerJs.angle.mirror(oneAngle, false, true))]; + } + var c1IntersectionAngle = MakerJs.solvers.solveTriangleSSS(c2.radius, c1.radius, x); + var c2IntersectionAngle = MakerJs.solvers.solveTriangleSSS(c1.radius, x, c2.radius); + return [bothAngles(c1IntersectionAngle), bothAngles(180 - c2IntersectionAngle)]; + } + })(path = MakerJs.path || (MakerJs.path = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var path; + (function (path) { + /** + * @private + */ + function getPointProperties(pathToInspect) { + var points = MakerJs.point.fromPathEnds(pathToInspect); + if (points) { + function pointProperty(index) { + return { point: points[index], propertyName: propertyNames[index] }; + } + var propertyNames = null; + var map = {}; + map[MakerJs.pathType.Arc] = function (arc) { + propertyNames = ['startAngle', 'endAngle']; + }; + map[MakerJs.pathType.Line] = function (line) { + propertyNames = ['origin', 'end']; + }; + var fn = map[pathToInspect.type]; + if (fn) { + fn(pathToInspect); + return [pointProperty(0), pointProperty(1)]; + } + } + return null; + } + /** + * @private + */ + function getMatchingPointProperties(path1, path2, options) { + var path1Properties = getPointProperties(path1); + var path2Properties = getPointProperties(path2); + var result = null; + function makeMatch(pathContext, pointProperties, index) { + return { + path: pathContext, + isStart: index == 0, + propertyName: pointProperties[index].propertyName, + point: pointProperties[index].point, + oppositePoint: pointProperties[1 - index].point + }; + } + function check(i1, i2) { + if (MakerJs.measure.isPointEqual(path1Properties[i1].point, path2Properties[i2].point, .0001)) { + result = [ + makeMatch(path1, path1Properties, i1), + makeMatch(path2, path2Properties, i2) + ]; + return true; + } + return false; + } + check(0, 0) || check(0, 1) || check(1, 0) || check(1, 1); + return result; + } + /** + * @private + */ + function populateShardPointsFromReferenceCircle(filletRadius, center, properties, options) { + var referenceCircle = new MakerJs.paths.Circle(center, filletRadius); + //get reference circle intersection points + for (var i = 0; i < 2; i++) { + var circleIntersection = path.intersection(referenceCircle, properties[i].path); + if (!circleIntersection) { + return false; + } + properties[i].shardPoint = circleIntersection.intersectionPoints[0]; + if (MakerJs.measure.isPointEqual(properties[i].point, circleIntersection.intersectionPoints[0], .0001)) { + if (circleIntersection.intersectionPoints.length > 1) { + properties[i].shardPoint = circleIntersection.intersectionPoints[1]; + } + else { + return false; + } + } + } + return true; + } + /** + * @private + */ + function cloneAndBreakPath(pathToShard, shardPoint) { + var shardStart = MakerJs.cloneObject(pathToShard); + var shardEnd = path.breakAtPoint(shardStart, shardPoint); + return [shardStart, shardEnd]; + } + /** + * @private + */ + function getGuidePath(context, filletRadius, nearPoint) { + var result = null; + var map = {}; + map[MakerJs.pathType.Arc] = function (arc) { + var guideRadius = arc.radius; + //see if the guideline should be external or internal to the context arc. + var guideArcShard = cloneAndBreakPath(arc, context.shardPoint)[context.isStart ? 0 : 1]; + if (guideArcShard) { + if (MakerJs.measure.isArcConcaveTowardsPoint(guideArcShard, nearPoint)) { + guideRadius -= filletRadius; + } + else { + guideRadius += filletRadius; + } + result = new MakerJs.paths.Arc(arc.origin, guideRadius, arc.startAngle, arc.endAngle); + } + }; + map[MakerJs.pathType.Line] = function (line) { + result = new MakerJs.paths.Parallel(line, filletRadius, nearPoint); + }; + var fn = map[context.path.type]; + if (fn) { + fn(context.path); + } + return result; + } + /** + * @private + */ + function getFilletResult(context, filletRadius, filletCenter) { + var result = null; + var map = {}; + map[MakerJs.pathType.Arc] = function (arc) { + var guideLine = new MakerJs.paths.Line(arc.origin, filletCenter); + var guideLineAngle = MakerJs.angle.ofLineInDegrees(guideLine); + var filletAngle = guideLineAngle; + //the context is an arc and the fillet is an arc so they will be tangent. If the fillet is external to the arc then the tangent is opposite. + if (!MakerJs.measure.isArcConcaveTowardsPoint(arc, filletCenter)) { + filletAngle += 180; + } + result = { + filletAngle: MakerJs.angle.noRevolutions(filletAngle), + clipPath: function () { + arc[context.propertyName] = guideLineAngle; + } + }; + }; + map[MakerJs.pathType.Line] = function (line) { + //make a small vertical line + var guideLine = new MakerJs.paths.Line([0, 0], [0, 1]); + //rotate this vertical line the same angle as the line context. It will be perpendicular. + var lineAngle = MakerJs.angle.ofLineInDegrees(line); + path.rotate(guideLine, lineAngle, [0, 0]); + path.moveRelative(guideLine, filletCenter); + //get the intersection point of the slopes of the context line and the perpendicular line. This is where the fillet meets the line. + var intersectionPoint = MakerJs.point.fromSlopeIntersection(line, guideLine); + if (intersectionPoint) { + result = { + filletAngle: MakerJs.angle.ofPointInDegrees(filletCenter, intersectionPoint), + clipPath: function () { + line[context.propertyName] = intersectionPoint; + } + }; + } + }; + var fn = map[context.path.type]; + if (fn) { + fn(context.path); + } + if (!testFilletResult(context, result)) { + result = null; + } + return result; + } + /** + * @private + */ + function getDogboneResult(context, filletCenter) { + var result = { + filletAngle: MakerJs.angle.ofPointInDegrees(filletCenter, context.shardPoint), + clipPath: function () { + context.path[context.propertyName] = context.shardPoint; + } + }; + if (!testFilletResult(context, result)) { + result = null; + } + return result; + } + /** + * @private + */ + function testFilletResult(context, result) { + var test = false; + if (result) { + //temporarily clip the path. + var originalValue = context.path[context.propertyName]; + result.clipPath(); + //don't allow a fillet which effectivly eliminates the path. + if (MakerJs.measure.pathLength(context.path) > 0) { + test = true; + } + //revert the clipping we just did. + context.path[context.propertyName] = originalValue; + } + return test; + } + /** + * @private + */ + function getLineRatio(lines) { + var totalLength = 0; + var lengths = []; + for (var i = 0; i < lines.length; i++) { + var length = MakerJs.measure.pathLength(lines[i]); + lengths.push(length); + totalLength += length; + } + return lengths[0] / totalLength; + } + /** + * 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. + * @returns Arc path object of the new fillet. + */ + function dogbone(line1, line2, filletRadius, options) { + if (MakerJs.isPathLine(line1) && MakerJs.isPathLine(line2) && filletRadius && filletRadius > 0) { + var opts = { + pointMatchingDistance: .005 + }; + MakerJs.extendObject(opts, options); + //first find the common point + var commonProperty = getMatchingPointProperties(line1, line2, options); + if (commonProperty) { + //get the ratio comparison of the two lines + var ratio = getLineRatio([line1, line2]); + //draw a line between the two endpoints, and get the bisection point at the ratio + var span = new MakerJs.paths.Line(commonProperty[0].oppositePoint, commonProperty[1].oppositePoint); + var midRatioPoint = MakerJs.point.middle(span, ratio); + //use the bisection theorem to get the angle bisecting the lines + var bisectionAngle = MakerJs.angle.ofPointInDegrees(commonProperty[0].point, midRatioPoint); + var center = MakerJs.point.add(commonProperty[0].point, MakerJs.point.fromPolar(MakerJs.angle.toRadians(bisectionAngle), filletRadius)); + if (!populateShardPointsFromReferenceCircle(filletRadius, center, commonProperty, opts)) { + return null; + } + //get the angles of the fillet and a function which clips the path to the fillet. + var results = []; + for (var i = 0; i < 2; i++) { + var result = getDogboneResult(commonProperty[i], center); + if (!result) { + return null; + } + results.push(result); + } + var filletArc = new MakerJs.paths.Arc(center, filletRadius, results[0].filletAngle, results[1].filletAngle); + //make sure midpoint of fillet is outside of the angle + if (MakerJs.round(MakerJs.angle.noRevolutions(MakerJs.angle.ofArcMiddle(filletArc))) == MakerJs.round(bisectionAngle)) { + filletArc.startAngle = results[1].filletAngle; + filletArc.endAngle = results[0].filletAngle; + } + //clip the paths and return the fillet arc. + results[0].clipPath(); + results[1].clipPath(); + return filletArc; + } + } + return null; + } + path.dogbone = dogbone; + /** + * 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. + * @returns Arc path object of the new fillet. + */ + function fillet(path1, path2, filletRadius, options) { + if (path1 && path2 && filletRadius && filletRadius > 0) { + var opts = { + pointMatchingDistance: .005 + }; + MakerJs.extendObject(opts, options); + //first find the common point + var commonProperty = getMatchingPointProperties(path1, path2, options); + if (commonProperty) { + //since arcs can curl beyond, we need a local reference point. + //An intersection with a circle of the same radius as the desired fillet should suffice. + if (!populateShardPointsFromReferenceCircle(filletRadius, commonProperty[0].point, commonProperty, opts)) { + return null; + } + //get "parallel" guidelines + var guidePaths = []; + for (var i = 0; i < 2; i++) { + var otherPathShardPoint = commonProperty[1 - i].shardPoint; + if (!otherPathShardPoint) { + return null; + } + var guidePath = getGuidePath(commonProperty[i], filletRadius, otherPathShardPoint); + guidePaths.push(guidePath); + } + //the center of the fillet is the point where the guidelines intersect. + var intersectionPoint = path.intersection(guidePaths[0], guidePaths[1]); + if (intersectionPoint) { + var center; + //if guidelines intersect in more than one place, choose the closest one. + if (intersectionPoint.intersectionPoints.length == 1) { + center = intersectionPoint.intersectionPoints[0]; + } + else { + center = MakerJs.point.closest(commonProperty[0].point, intersectionPoint.intersectionPoints); + } + //get the angles of the fillet and a function which clips the path to the fillet. + var results = []; + for (var i = 0; i < 2; i++) { + var result = getFilletResult(commonProperty[i], filletRadius, center); + if (!result) { + return null; + } + results.push(result); + } + //the two paths may actually be on the same line + if (MakerJs.round(results[0].filletAngle - results[1].filletAngle) == 0) + return null; + var filletArc = new MakerJs.paths.Arc(center, filletRadius, results[0].filletAngle, results[1].filletAngle); + var filletSpan = MakerJs.angle.ofArcSpan(filletArc); + //the algorithm is only valid for fillet less than 180 degrees + if (filletSpan == 180) { + return null; + } + if (filletSpan > 180) { + //swap to make smallest angle + filletArc.startAngle = results[1].filletAngle; + filletArc.endAngle = results[0].filletAngle; + } + //clip the paths and return the fillet arc. + results[0].clipPath(); + results[1].clipPath(); + return filletArc; + } + } + } + return null; + } + path.fillet = fillet; + })(path = MakerJs.path || (MakerJs.path = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var kit; + (function (kit) { + //construct a model + /** + * Helper function to use the JavaScript "apply" function in conjunction with the "new" keyword. + * + * @param ctor The constructor for the class which is an IKit. + * @param args The array of parameters passed to the constructor. + * @returns A new instance of the class, which implements the IModel interface. + */ + function construct(ctor, args) { + function F() { + return ctor.apply(this, args); + } + F.prototype = ctor.prototype; + return new F(); + } + kit.construct = construct; + /** + * Extract just the initial sample values from a kit. + * + * @param ctor The constructor for the class which is an IKit. + * @returns Array of the inital sample values provided in the metaParameters array. + */ + function getParameterValues(ctor) { + var parameters = []; + var metaParams = ctor.metaParameters; + if (metaParams) { + for (var i = 0; i < metaParams.length; i++) { + var value = metaParams[i].value; + if (Array.isArray(value)) { + value = value[0]; + } + parameters.push(value); + } + } + return parameters; + } + kit.getParameterValues = getParameterValues; + })(kit = MakerJs.kit || (MakerJs.kit = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var model; + (function (model) { + /** + * @private + */ + function getOpposedLink(linkedPaths, pathContext) { + if (linkedPaths[0].path === pathContext) { + return linkedPaths[1]; + } + return linkedPaths[0]; + } + /** + * @private + */ + function getFirstPathFromModel(modelContext) { + if (!modelContext.paths) + return null; + for (var pathId in modelContext.paths) { + return modelContext.paths[pathId]; + } + return null; + } + /** + * @private + */ + function collectLoop(loop, loops, detach) { + loops.push(loop); + if (detach) { + detachLoop(loop); + } + } + /** + * @private + */ + function follow(connections, loops, detach) { + //for a given point, follow the paths that connect to each other to form loops + for (var p in connections) { + var linkedPaths = connections[p]; + if (linkedPaths) { + var loopModel = { + paths: {}, + insideCount: 0 + }; + var firstLink = linkedPaths[0]; + var currLink = firstLink; + while (true) { + var currPath = currLink.path; + currPath.reversed = currLink.reversed; + var id = model.getSimilarPathId(loopModel, currPath.pathId); + loopModel.paths[id] = currPath; + if (!connections[currLink.nextConnection]) + break; + var nextLink = getOpposedLink(connections[currLink.nextConnection], currLink.path); + connections[currLink.nextConnection] = null; + if (!nextLink) + break; + currLink = nextLink; + if (currLink.path === firstLink.path) { + //loop is closed + collectLoop(loopModel, loops, detach); + break; + } + } + } + } + } + /** + * Find paths that have common endpoints and form loops. + * + * @param modelContext The model to search for loops. + * @param options Optional options object. + * @returns A new model with child models ranked according to their containment within other found loops. The paths of models will be IPathDirectionalWithPrimeContext. + */ + function findLoops(modelContext, options) { + var loops = []; + var connections = {}; + var result = { models: {} }; + var opts = { + pointMatchingDistance: .005 + }; + MakerJs.extendObject(opts, options); + function getLinkedPathsOnConnectionPoint(p) { + var serializedPoint = MakerJs.point.serialize(p, .0001); //TODO convert to pointmap + if (!(serializedPoint in connections)) { + connections[serializedPoint] = []; + } + return connections[serializedPoint]; + } + function spin(callback) { + for (var i = 0; i < loops.length; i++) { + callback(loops[i]); + } + } + function getModelByDepth(depth) { + var id = depth.toString(); + if (!(id in result.models)) { + var newModel = { models: {} }; + result.models[id] = newModel; + } + return result.models[id]; + } + //todo: remove dead ends first + model.originate(modelContext); + //find loops by looking at all paths in this model + model.walkPaths(modelContext, function (modelContext, pathId, pathContext) { + if (!pathContext) + return; + var safePath = MakerJs.cloneObject(pathContext); + safePath.pathId = pathId; + safePath.modelContext = modelContext; + //circles are loops by nature + if (safePath.type == MakerJs.pathType.Circle) { + var loopModel = { + paths: {}, + insideCount: 0 + }; + loopModel.paths[pathId] = safePath; + collectLoop(loopModel, loops, opts.removeFromOriginal); + } + else { + //gather both endpoints from all non-circle segments + safePath.endPoints = MakerJs.point.fromPathEnds(safePath); + for (var i = 2; i--;) { + var linkedPath = { + path: safePath, + nextConnection: MakerJs.point.serialize(safePath.endPoints[1 - i], .0001), + reversed: i != 0 + }; + getLinkedPathsOnConnectionPoint(safePath.endPoints[i]).push(linkedPath); + } + } + }); + //follow paths to find loops + follow(connections, loops, opts.removeFromOriginal); + //now we have all loops, we need to see which are inside of each other + spin(function (firstLoop) { + var firstPath = getFirstPathFromModel(firstLoop); + if (!firstPath) + return; + spin(function (secondLoop) { + if (firstLoop === secondLoop) + return; + if (model.isPathInsideModel(firstPath, secondLoop)) { + firstLoop.insideCount++; + } + }); + }); + //now we can group similar loops by their nested level + spin(function (loop) { + var depthModel = getModelByDepth(loop.insideCount); + var id = model.countChildModels(depthModel).toString(); + delete loop.insideCount; + depthModel.models[id] = loop; + }); + return result; + } + model.findLoops = findLoops; + /** + * Remove all paths in a loop model from the model(s) which contained them. + * + * @param loopToDetach The model to search for loops. + */ + function detachLoop(loopToDetach) { + for (var id in loopToDetach.paths) { + var pathDirectionalWithOriginalContext = loopToDetach.paths[id]; + var primeModel = pathDirectionalWithOriginalContext.modelContext; + if (primeModel && primeModel.paths && pathDirectionalWithOriginalContext.pathId) { + delete primeModel.paths[pathDirectionalWithOriginalContext.pathId]; + } + } + } + model.detachLoop = detachLoop; + /** + * @private + */ + var DeadEndFinder = (function () { + function DeadEndFinder(pointMatchingDistance) { + this.pointMatchingDistance = pointMatchingDistance; + function comparePoint(point1, point2) { + var distance = MakerJs.measure.pointDistance(point1, point2); + return distance <= pointMatchingDistance; + } + this.pointMap = new MakerJs.Collector(comparePoint); + } + DeadEndFinder.prototype.removeMatchingPathRefs = function (a, b) { + //see if any are the same in each array + for (var ai = 0; ai < a.length; ai++) { + for (var bi = 0; bi < b.length; bi++) { + if (a[ai] === b[bi]) { + var pathRef = a[ai]; + a.splice(ai, 1); + b.splice(bi, 1); + return pathRef; + } + } + } + return null; + }; + DeadEndFinder.prototype.removePathRef = function (pathRef) { + var _this = this; + var removePath = function (p) { + var pathRefs = _this.pointMap.findCollection(p); + for (var i = 0; i < pathRefs.length; i++) { + if (pathRefs[i] === pathRef) { + pathRefs.splice(i, 1); + return; + } + } + }; + for (var i = 2; i--;) { + removePath(pathRef.endPoints[i]); + } + }; + DeadEndFinder.prototype.removeDeadEnd = function () { + var found = false; + var oddPathRefs = null; + for (var i = 0; i < this.pointMap.collections.length; i++) { + var pathRefs = this.pointMap.collections[i].items; + if (pathRefs.length % 2 == 0) + continue; + if (pathRefs.length == 1) { + var pathRef = pathRefs[0]; + this.removePathRef(pathRef); + delete pathRef.modelContext.paths[pathRef.pathId]; + found = true; + } + else { + if (!oddPathRefs) { + //save this for another iteration + oddPathRefs = pathRefs; + } + else { + //compare with the saved + var pathRef = this.removeMatchingPathRefs(oddPathRefs, pathRefs); + if (pathRef) { + delete pathRef.modelContext.paths[pathRef.pathId]; + found = true; + //clear the saved + oddPathRefs = null; + } + } + } + } + return found; + }; + return DeadEndFinder; + }()); + /** + * 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, pointMatchingDistance) { + if (pointMatchingDistance === void 0) { pointMatchingDistance = .005; } + var serializedPointAccuracy = .0001; + var deadEndFinder = new DeadEndFinder(pointMatchingDistance); + model.walkPaths(modelContext, function (modelContext, pathId, pathContext) { + var endPoints = MakerJs.point.fromPathEnds(pathContext); + if (!endPoints) + return; + var pathRef = { modelContext: modelContext, pathId: pathId, endPoints: endPoints }; + for (var i = 2; i--;) { + deadEndFinder.pointMap.addItemToCollection(endPoints[i], pathRef); + } + }); + while (deadEndFinder.removeDeadEnd()) + ; + return modelContext; + } + model.removeDeadEnds = removeDeadEnds; + })(model = MakerJs.model || (MakerJs.model = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var exporter; + (function (exporter) { + /** + * Class for an XML tag. + * @private + */ + var XmlTag = (function () { + /** + * @param name Name of the XML tag. + * @param attrs Optional attributes for the tag. + */ + function XmlTag(name, attrs) { + this.name = name; + this.attrs = attrs; + /** + * Text between the opening and closing tags. + */ + this.innerText = ''; + } + /** + * Escapes certain characters within a string so that it can appear in a tag or its attribute. + * + * @returns Escaped string. + */ + XmlTag.escapeString = function (value) { + var escape = { + '&': '&', + '<': '<', + '>': '>', + '"': '"' + }; + for (var code in escape) { + //.split then .join is a 'replace' + value = value.split(code).join(escape[code]); + } + return value; + }; + /** + * Get the opening tag. + * + * @param selfClose Flag to determine if opening tag should be self closing. + */ + XmlTag.prototype.getOpeningTag = function (selfClose) { + var attrs = ''; + function outputAttr(attrName, attrValue) { + if (attrValue == null || typeof attrValue === 'undefined') + return; + if (typeof attrValue === 'string') { + attrValue = XmlTag.escapeString(attrValue); + } + attrs += ' ' + attrName + '="' + attrValue + '"'; + } + for (var name in this.attrs) { + outputAttr(name, this.attrs[name]); + } + return '<' + this.name + attrs + (selfClose ? '/' : '') + '>'; + }; + /** + * Get the inner text. + */ + XmlTag.prototype.getInnerText = function () { + if (this.innerTextEscaped) { + return this.innerText; + } + else { + return XmlTag.escapeString(this.innerText); + } + }; + /** + * Get the closing tag. + */ + XmlTag.prototype.getClosingTag = function () { + return ''; + }; + /** + * Output the entire tag as a string. + */ + XmlTag.prototype.toString = function () { + var selfClose = !this.innerText; + if (selfClose) { + return this.getOpeningTag(true); + } + else { + return this.getOpeningTag(false) + this.getInnerText() + this.getClosingTag(); + } + }; + return XmlTag; + }()); + exporter.XmlTag = XmlTag; + })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var exporter; + (function (exporter) { + /** + * @private + */ + function wrap(prefix, content, condition) { + if (condition) { + return prefix + '(' + content + ')'; + } + else { + return content; + } + } + /** + * @private + */ + function facetSizeToResolution(arcOrCircle, facetSize) { + if (!facetSize) + return; + var circle = new MakerJs.paths.Circle([0, 0], arcOrCircle.radius); + var length = MakerJs.measure.pathLength(circle); + if (!length) + return; + return length / facetSize; + } + /** + * @private + */ + function pathsToOpenJsCad(modelContext, facetSize) { + var head = ''; + var tail = ''; + var first = true; + var exit = false; + var reverseTail = false; + var beginMap = {}; + beginMap[MakerJs.pathType.Circle] = function (circle, dirPath) { + var circleOptions = { + center: MakerJs.point.rounded(circle.origin), + radius: circle.radius, + resolution: facetSizeToResolution(circle, facetSize) + }; + head = wrap('CAG.circle', JSON.stringify(circleOptions), true); + exit = true; + }; + beginMap[MakerJs.pathType.Line] = function (line, dirPath) { + head = wrap('new CSG.Path2D', JSON.stringify(dirPath.reversed ? [dirPath.endPoints[1], dirPath.endPoints[0]] : dirPath.endPoints), true); + }; + beginMap[MakerJs.pathType.Arc] = function (arc, dirPath) { + var endAngle = MakerJs.angle.ofArcEnd(arc); + if (dirPath.reversed) { + reverseTail = true; + } + var arcOptions = { + center: MakerJs.point.rounded(arc.origin), + radius: arc.radius, + startangle: arc.startAngle, + endangle: endAngle, + resolution: facetSizeToResolution(arc, facetSize) + }; + head = wrap('new CSG.Path2D.arc', JSON.stringify(arcOptions), true); + }; + var appendMap = {}; + appendMap[MakerJs.pathType.Line] = function (line, dirPath) { + var reverse = (reverseTail != dirPath.reversed); + var endPoint = MakerJs.point.rounded(dirPath.endPoints[reverse ? 0 : 1]); + append(wrap('.appendPoint', JSON.stringify(endPoint), true)); + }; + appendMap[MakerJs.pathType.Arc] = function (arc, dirPath) { + var reverse = (reverseTail != dirPath.reversed); + var endAngle = MakerJs.angle.ofArcEnd(arc); + var arcOptions = { + radius: arc.radius, + clockwise: reverse, + large: Math.abs(endAngle - arc.startAngle) > 180, + resolution: facetSizeToResolution(arc, facetSize) + }; + var endPoint = MakerJs.point.rounded(dirPath.endPoints[reverse ? 0 : 1]); + append(wrap('.appendArc', JSON.stringify(endPoint) + ',' + JSON.stringify(arcOptions), true)); + }; + function append(s) { + if (reverseTail) { + tail = s + tail; + } + else { + tail += s; + } + } + for (var pathId in modelContext.paths) { + var pathContext = modelContext.paths[pathId]; + var fn = first ? beginMap[pathContext.type] : appendMap[pathContext.type]; + if (fn) { + fn(pathContext, pathContext); + } + if (exit) { + return head; + } + first = false; + } + return head + tail + '.close().innerToCAG()'; + } + /** + * Creates a string of JavaScript code for execution with the OpenJsCad engine. + * + * @param modelToExport Model object to export. + * @param options Export options object. + * @param options.extrusion Height of 3D extrusion. + * @param options.resolution Size of facets. + * @returns String of JavaScript containing a main() function for OpenJsCad. + */ + function toOpenJsCad(modelToExport, options) { + if (!modelToExport) + return ''; + var all = ''; + var depth = 0; + var depthModel; + var opts = { + extrusion: 1, + pointMatchingDistance: .005, + functionName: 'main' + }; + MakerJs.extendObject(opts, options); + if (modelToExport.exporterOptions) { + MakerJs.extendObject(opts, modelToExport.exporterOptions['toOpenJsCad']); + } + //pass options back into calling object + MakerJs.extendObject(options, opts); + if (opts && opts.modelMap) { + all = exportFromOptionsMap(modelToExport, opts.modelMap); + } + if (!all) { + var result = []; + var loops = MakerJs.model.findLoops(modelToExport, opts); + while (depthModel = loops.models[depth]) { + var union = ''; + for (var modelId in depthModel.models) { + var subModel = depthModel.models[modelId]; + union += wrap('.union', pathsToOpenJsCad(subModel, opts.facetSize), union); + } + var operator = (depth % 2 == 0) ? '.union' : '.subtract'; + result.push(wrap(operator, union, result.length)); + depth++; + } + var extrudeOptions = { offset: [0, 0, opts.extrusion] }; + result.push(wrap('.extrude', JSON.stringify(extrudeOptions), true)); + all = 'return ' + result.join(''); + } + return 'function ' + opts.functionName + '(){' + all + ';}'; + } + exporter.toOpenJsCad = toOpenJsCad; + function exportFromOptionsMap(modelToExport, optionsMap) { + if (!modelToExport.models) + return; + var result = []; + var union = []; + var i = 0; + for (var key in optionsMap) { + var fName = 'f' + i; + var options = optionsMap[key]; + options.functionName = fName; + var childModel = modelToExport.models[key]; + if (childModel) { + result.push(toOpenJsCad(childModel, options)); + union.push('(' + fName + '())'); + } + i++; + } + if (!result.length) + return; + result.push('return ' + union.join('.union')); + return result.join(' '); + } + /** + * Executes a JavaScript string with the OpenJsCad engine - converts 2D to 3D. + * + * @param modelToExport Model object to export. + * @param options Export options object. + * @param options.extrusion Height of 3D extrusion. + * @param options.resolution Size of facets. + * @returns String of STL format of 3D object. + */ + function toSTL(modelToExport, options) { + if (options === void 0) { options = {}; } + if (!modelToExport) + return ''; + var script = toOpenJsCad(modelToExport, options); + script += 'return ' + options.functionName + '();'; + var f = new Function(script); + var csg = f(); + return csg.toStlString(); + } + exporter.toSTL = toSTL; + })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var exporter; + (function (exporter) { + /** + * Renders an item in SVG markup. + * + * @param itemToExport Item to render: may be a path, an array of paths, or a model object. + * @param options Rendering options object. + * @param options.annotate Boolean to indicate that the id's of paths should be rendered as SVG text elements. + * @param options.origin point object for the rendered reference origin. + * @param options.scale Number to scale the SVG rendering. + * @param options.stroke String color of the rendered paths. + * @param options.strokeWidth String numeric width and optional units of the rendered paths. + * @param options.units String of the unit system. May be omitted. See makerjs.unitType for possible values. + * @param options.useSvgPathOnly Boolean to use SVG path elements instead of line, circle etc. + * @returns String of XML / SVG content. + */ + function toSVG(itemToExport, options) { + var opts = { + annotate: false, + origin: null, + scale: 1, + stroke: "#000", + strokeWidth: '0.25mm', + fontSize: '9pt', + useSvgPathOnly: true, + viewBox: true + }; + MakerJs.extendObject(opts, options); + var modelToExport; + var itemToExportIsModel = MakerJs.isModel(itemToExport); + if (itemToExportIsModel) { + modelToExport = itemToExport; + if (modelToExport.exporterOptions) { + MakerJs.extendObject(opts, modelToExport.exporterOptions['toSVG']); + } + } + var elements = []; + var layers = {}; + function append(value, layer) { + if (layer) { + if (!(layer in layers)) { + layers[layer] = []; + } + layers[layer].push(value); + } + else { + elements.push(value); + } + } + function fixPoint(pointToFix) { + //in DXF Y increases upward. in SVG, Y increases downward + var pointMirroredY = MakerJs.point.mirror(pointToFix, false, true); + return MakerJs.point.scale(pointMirroredY, opts.scale); + } + function fixPath(pathToFix, origin) { + //mirror creates a copy, so we don't modify the original + var mirrorY = MakerJs.path.mirror(pathToFix, false, true); + return MakerJs.path.moveRelative(MakerJs.path.scale(mirrorY, opts.scale), origin); + } + function createElement(tagname, attrs, layer, innerText) { + if (innerText === void 0) { innerText = null; } + attrs['vector-effect'] = 'non-scaling-stroke'; + var tag = new exporter.XmlTag(tagname, attrs); + if (innerText) { + tag.innerText = innerText; + } + append(tag.toString(), layer); + } + function drawText(id, textPoint) { + createElement("text", { + "id": id + "_text", + "x": textPoint[0], + "y": textPoint[1] + }, null, id); + } + function drawPath(id, x, y, d, layer, textPoint) { + createElement("path", { + "id": id, + "d": ["M", MakerJs.round(x), MakerJs.round(y)].concat(d).join(" ") + }, layer); + if (opts.annotate) { + drawText(id, textPoint); + } + } + var map = {}; + map[MakerJs.pathType.Line] = function (id, line, origin, layer) { + var start = line.origin; + var end = line.end; + if (opts.useSvgPathOnly) { + drawPath(id, start[0], start[1], [MakerJs.round(end[0]), MakerJs.round(end[1])], layer, MakerJs.point.middle(line)); + } + else { + createElement("line", { + "id": id, + "x1": MakerJs.round(start[0]), + "y1": MakerJs.round(start[1]), + "x2": MakerJs.round(end[0]), + "y2": MakerJs.round(end[1]) + }, layer); + if (opts.annotate) { + drawText(id, MakerJs.point.middle(line)); + } + } + }; + map[MakerJs.pathType.Circle] = function (id, circle, origin, layer) { + var center = circle.origin; + if (opts.useSvgPathOnly) { + circleInPaths(id, center, circle.radius, layer); + } + else { + createElement("circle", { + "id": id, + "r": circle.radius, + "cx": MakerJs.round(center[0]), + "cy": MakerJs.round(center[1]) + }, layer); + } + if (opts.annotate) { + drawText(id, center); + } + }; + function circleInPaths(id, center, radius, layer) { + var d = ['m', -radius, 0]; + function halfCircle(sign) { + d.push('a'); + svgArcData(d, radius, [2 * radius * sign, 0]); + } + halfCircle(1); + halfCircle(-1); + drawPath(id, center[0], center[1], d, layer, center); + } + function svgArcData(d, radius, endPoint, largeArc, decreasing) { + var end = endPoint; + d.push(radius, radius); + d.push(0); //0 = x-axis rotation + d.push(largeArc ? 1 : 0); //large arc=1, small arc=0 + d.push(decreasing ? 0 : 1); //sweep-flag 0=decreasing, 1=increasing + d.push(MakerJs.round(end[0]), MakerJs.round(end[1])); + } + map[MakerJs.pathType.Arc] = function (id, arc, origin, layer) { + var arcPoints = MakerJs.point.fromArc(arc); + if (MakerJs.measure.isPointEqual(arcPoints[0], arcPoints[1])) { + circleInPaths(id, arc.origin, arc.radius, layer); + } + else { + var d = ['A']; + svgArcData(d, arc.radius, arcPoints[1], Math.abs(arc.endAngle - arc.startAngle) > 180, arc.startAngle > arc.endAngle); + drawPath(id, arcPoints[0][0], arcPoints[0][1], d, layer, MakerJs.point.middle(arc)); + } + }; + //fixup options + //measure the item to move it into svg area + if (itemToExportIsModel) { + modelToExport = itemToExport; + } + else if (Array.isArray(itemToExport)) { + //issue: this won't handle an array of models + modelToExport = { paths: itemToExport }; + } + else if (MakerJs.isPath(itemToExport)) { + modelToExport = { paths: { modelToMeasure: itemToExport } }; + } + var size = MakerJs.measure.modelExtents(modelToExport); + //try to get the unit system from the itemToExport + if (!opts.units) { + var unitSystem = exporter.tryGetModelUnits(itemToExport); + if (unitSystem) { + opts.units = unitSystem; + } + } + //convert unit system (if it exists) into SVG's units. scale if necessary. + var useSvgUnit = exporter.svgUnit[opts.units]; + if (useSvgUnit && opts.viewBox) { + opts.scale *= useSvgUnit.scaleConversion; + } + if (!opts.origin) { + var left = 0; + if (size.low[0] < 0) { + left = -size.low[0] * opts.scale; + } + opts.origin = [left, size.high[1] * opts.scale]; + } + //also pass back to options parameter + MakerJs.extendObject(options, opts); + //begin svg output + var modelGroup = new exporter.XmlTag('g'); + function beginModel(id, modelContext) { + modelGroup.attrs = { id: id }; + append(modelGroup.getOpeningTag(false), modelContext.layer); + } + function endModel(modelContext) { + append(modelGroup.getClosingTag(), modelContext.layer); + } + var svgAttrs; + if (opts.viewBox) { + var width = MakerJs.round(size.high[0] - size.low[0]) * opts.scale; + var height = MakerJs.round(size.high[1] - size.low[1]) * opts.scale; + var viewBox = [0, 0, width, height]; + var unit = useSvgUnit ? useSvgUnit.svgUnitType : ''; + svgAttrs = { + width: width + unit, + height: height + unit, + viewBox: viewBox.join(' ') + }; + } + var svgTag = new exporter.XmlTag('svg', MakerJs.extendObject(svgAttrs || {}, opts.svgAttrs)); + append(svgTag.getOpeningTag(false)); + var svgGroup = new exporter.XmlTag('g', { + id: 'svgGroup', + stroke: opts.stroke, + "stroke-width": opts.strokeWidth, + "stroke-linecap": "round", + "fill": "none", + "font-size": opts.fontSize + }); + append(svgGroup.getOpeningTag(false)); + var exp = new exporter.Exporter(map, fixPoint, fixPath, beginModel, endModel); + exp.exportItem('0', itemToExport, opts.origin); + //export layers as groups + for (var layer in layers) { + var layerGroup = new exporter.XmlTag('g', { id: layer }); + for (var i = 0; i < layers[layer].length; i++) { + layerGroup.innerText += layers[layer][i]; + } + layerGroup.innerTextEscaped = true; + append(layerGroup.toString()); + } + append(svgGroup.getClosingTag()); + append(svgTag.getClosingTag()); + return elements.join(''); + } + exporter.toSVG = toSVG; + /** + * Map of MakerJs unit system to SVG unit system + */ + exporter.svgUnit = {}; + //SVG Coordinate Systems, Transformations and Units documentation: + //http://www.w3.org/TR/SVG/coords.html + //The supported length unit identifiers are: em, ex, px, pt, pc, cm, mm, in, and percentages. + exporter.svgUnit[MakerJs.unitType.Inch] = { svgUnitType: "in", scaleConversion: 1 }; + exporter.svgUnit[MakerJs.unitType.Millimeter] = { svgUnitType: "mm", scaleConversion: 1 }; + exporter.svgUnit[MakerJs.unitType.Centimeter] = { svgUnitType: "cm", scaleConversion: 1 }; + //Add conversions for all unitTypes + exporter.svgUnit[MakerJs.unitType.Foot] = { svgUnitType: "in", scaleConversion: 12 }; + exporter.svgUnit[MakerJs.unitType.Meter] = { svgUnitType: "cm", scaleConversion: 100 }; + })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var ConnectTheDots = (function () { + function ConnectTheDots(isClosed, points) { + var _this = this; + this.paths = {}; + var connect = function (a, b) { + _this.paths["ShapeLine" + i] = new MakerJs.paths.Line(points[a], points[b]); + }; + for (var i = 1; i < points.length; i++) { + connect(i - 1, i); + } + if (isClosed && points.length > 2) { + connect(points.length - 1, 0); + } + } + return ConnectTheDots; + }()); + models.ConnectTheDots = ConnectTheDots; + ConnectTheDots.metaParameters = [ + { title: "closed", type: "bool", value: true }, + { + title: "points", type: "select", value: [ + [[0, 0], [40, 40], [60, 20], [100, 100], [60, 60], [40, 80]], + [[0, 0], [100, 0], [50, 87]] + ] + } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var Polygon = (function () { + function Polygon(numberOfSides, radius, firstCornerAngleInDegrees, circumscribed) { + this.paths = {}; + this.paths = new models.ConnectTheDots(true, Polygon.getPoints(numberOfSides, radius, firstCornerAngleInDegrees, circumscribed)).paths; + } + Polygon.circumscribedRadius = function (radius, angleInRadians) { + return radius / Math.cos(angleInRadians / 2); + }; + Polygon.getPoints = function (numberOfSides, radius, firstCornerAngleInDegrees, circumscribed) { + if (firstCornerAngleInDegrees === void 0) { firstCornerAngleInDegrees = 0; } + if (circumscribed === void 0) { circumscribed = false; } + var points = []; + var a1 = MakerJs.angle.toRadians(firstCornerAngleInDegrees); + var a = 2 * Math.PI / numberOfSides; + if (circumscribed) { + radius = Polygon.circumscribedRadius(radius, a); + } + for (var i = 0; i < numberOfSides; i++) { + points.push(MakerJs.point.fromPolar(a * i + a1, radius)); + } + return points; + }; + return Polygon; + }()); + models.Polygon = Polygon; + Polygon.metaParameters = [ + { title: "number of sides", type: "range", min: 3, max: 24, value: 6 }, + { title: "radius", type: "range", min: 1, max: 100, value: 50 }, + { title: "offset angle", type: "range", min: 0, max: 180, value: 0 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var BoltCircle = (function () { + function BoltCircle(boltRadius, holeRadius, boltCount, firstBoltAngleInDegrees) { + if (firstBoltAngleInDegrees === void 0) { firstBoltAngleInDegrees = 0; } + this.paths = {}; + var points = models.Polygon.getPoints(boltCount, boltRadius, firstBoltAngleInDegrees); + for (var i = 0; i < boltCount; i++) { + this.paths["bolt " + i] = new MakerJs.paths.Circle(points[i], holeRadius); + } + } + return BoltCircle; + }()); + models.BoltCircle = BoltCircle; + BoltCircle.metaParameters = [ + { title: "bolt circle radius", type: "range", min: 1, max: 100, value: 50 }, + { title: "hole radius", type: "range", min: 1, max: 50, value: 5 }, + { title: "bolt count", type: "range", min: 3, max: 24, value: 12 }, + { title: "offset angle", type: "range", min: 0, max: 180, value: 0 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var BoltRectangle = (function () { + function BoltRectangle(width, height, holeRadius) { + this.paths = {}; + var holes = { + "BottomLeft": [0, 0], + "BottomRight": [width, 0], + "TopRight": [width, height], + "TopLeft": [0, height] + }; + for (var id2 in holes) { + this.paths[id2 + "_bolt"] = new MakerJs.paths.Circle(holes[id2], holeRadius); + } + } + return BoltRectangle; + }()); + models.BoltRectangle = BoltRectangle; + BoltRectangle.metaParameters = [ + { title: "width", type: "range", min: 1, max: 100, value: 100 }, + { title: "height", type: "range", min: 1, max: 100, value: 50 }, + { title: "hole radius", type: "range", min: 1, max: 50, value: 5 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var Dome = (function () { + function Dome(width, height, radius) { + this.paths = {}; + var w2 = width / 2; + if (radius < 0) + radius = 0; + if (radius === void 0) + radius = w2; + radius = Math.min(radius, w2); + radius = Math.min(radius, height); + var wt = Math.max(w2 - radius, 0); + var hr = Math.max(height - radius, 0); + this.paths["Bottom"] = new MakerJs.paths.Line([-w2, 0], [w2, 0]); + if (hr) { + this.paths["Left"] = new MakerJs.paths.Line([-w2, 0], [-w2, hr]); + this.paths["Right"] = new MakerJs.paths.Line([w2, 0], [w2, hr]); + } + if (radius > 0) { + this.paths["TopLeft"] = new MakerJs.paths.Arc([-wt, hr], radius, 90, 180); + this.paths["TopRight"] = new MakerJs.paths.Arc([wt, hr], radius, 0, 90); + } + if (wt) { + this.paths["Top"] = new MakerJs.paths.Line([-wt, height], [wt, height]); + } + } + return Dome; + }()); + models.Dome = Dome; + Dome.metaParameters = [ + { title: "width", type: "range", min: 1, max: 100, value: 50 }, + { title: "height", type: "range", min: 1, max: 100, value: 100 }, + { title: "radius", type: "range", min: 0, max: 50, value: 25 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var RoundRectangle = (function () { + function RoundRectangle(width, height, radius) { + this.paths = {}; + var maxRadius = Math.min(height, width) / 2; + radius = Math.min(radius, maxRadius); + var wr = width - radius; + var hr = height - radius; + if (radius > 0) { + this.paths["BottomLeft"] = new MakerJs.paths.Arc([radius, radius], radius, 180, 270); + this.paths["BottomRight"] = new MakerJs.paths.Arc([wr, radius], radius, 270, 0); + this.paths["TopRight"] = new MakerJs.paths.Arc([wr, hr], radius, 0, 90); + this.paths["TopLeft"] = new MakerJs.paths.Arc([radius, hr], radius, 90, 180); + } + if (wr - radius > 0) { + this.paths["Bottom"] = new MakerJs.paths.Line([radius, 0], [wr, 0]); + this.paths["Top"] = new MakerJs.paths.Line([wr, height], [radius, height]); + } + if (hr - radius > 0) { + this.paths["Right"] = new MakerJs.paths.Line([width, radius], [width, hr]); + this.paths["Left"] = new MakerJs.paths.Line([0, hr], [0, radius]); + } + } + return RoundRectangle; + }()); + models.RoundRectangle = RoundRectangle; + RoundRectangle.metaParameters = [ + { title: "width", type: "range", min: 1, max: 100, value: 50 }, + { title: "height", type: "range", min: 1, max: 100, value: 100 }, + { title: "radius", type: "range", min: 0, max: 50, value: 11 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var Oval = (function () { + function Oval(width, height) { + this.paths = {}; + this.paths = new models.RoundRectangle(width, height, Math.min(height / 2, width / 2)).paths; + } + return Oval; + }()); + models.Oval = Oval; + Oval.metaParameters = [ + { title: "width", type: "range", min: 1, max: 100, value: 50 }, + { title: "height", type: "range", min: 1, max: 100, value: 100 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var OvalArc = (function () { + function OvalArc(startAngle, endAngle, sweepRadius, slotRadius, selfIntersect, isolateCaps) { + var _this = this; + if (selfIntersect === void 0) { selfIntersect = false; } + if (isolateCaps === void 0) { isolateCaps = false; } + this.paths = {}; + if (slotRadius <= 0 || sweepRadius <= 0) + return; + startAngle = MakerJs.angle.noRevolutions(startAngle); + endAngle = MakerJs.angle.noRevolutions(endAngle); + if (MakerJs.round(startAngle - endAngle) == 0) + return; + if (endAngle < startAngle) + endAngle += 360; + var capModel = this; + if (isolateCaps) { + this.models = { "Caps": { paths: {} } }; + capModel = this.models["Caps"]; + } + var addCap = function (id, tiltAngle, offsetStartAngle, offsetEndAngle) { + return capModel.paths[id] = new MakerJs.paths.Arc(MakerJs.point.fromPolar(MakerJs.angle.toRadians(tiltAngle), sweepRadius), slotRadius, tiltAngle + offsetStartAngle, tiltAngle + offsetEndAngle); + }; + var addSweep = function (id, offsetRadius) { + return _this.paths[id] = new MakerJs.paths.Arc([0, 0], sweepRadius + offsetRadius, startAngle, endAngle); + }; + addSweep("Outer", slotRadius); + var hasInner = (sweepRadius - slotRadius) > 0; + if (hasInner) { + addSweep("Inner", -slotRadius); + } + var caps = []; + caps.push(addCap("StartCap", startAngle, 180, 0)); + caps.push(addCap("EndCap", endAngle, 0, 180)); + //the distance between the cap origins + var d = MakerJs.measure.pointDistance(caps[0].origin, caps[1].origin); + if ((d / 2) < slotRadius) { + //the caps intersect + var int = MakerJs.path.intersection(caps[0], caps[1]); + if (int) { + if (!hasInner || !selfIntersect) { + caps[0].startAngle = int.path1Angles[0]; + caps[1].endAngle = int.path2Angles[0]; + } + if (!selfIntersect && hasInner && int.intersectionPoints.length == 2) { + addCap("StartCap2", startAngle, 180, 0).endAngle = int.path1Angles[1]; + addCap("EndCap2", endAngle, 0, 180).startAngle = int.path2Angles[1] + 360; + } + } + } + } + return OvalArc; + }()); + models.OvalArc = OvalArc; + OvalArc.metaParameters = [ + { title: "start angle", type: "range", min: -360, max: 360, step: 1, value: 180 }, + { title: "end angle", type: "range", min: -360, max: 360, step: 1, value: 0 }, + { title: "sweep", type: "range", min: 0, max: 100, step: 1, value: 50 }, + { title: "radius", type: "range", min: 0, max: 100, step: 1, value: 15 }, + { title: "self intersect", type: "bool", value: false } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var Rectangle = (function () { + function Rectangle(width, height) { + this.paths = {}; + this.paths = new models.ConnectTheDots(true, [[0, 0], [width, 0], [width, height], [0, height]]).paths; + } + return Rectangle; + }()); + models.Rectangle = Rectangle; + Rectangle.metaParameters = [ + { title: "width", type: "range", min: 1, max: 100, value: 50 }, + { title: "height", type: "range", min: 1, max: 100, value: 100 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var Ring = (function () { + function Ring(outerRadius, innerRadius) { + this.paths = {}; + var radii = { + "Ring_outer": outerRadius, + "Ring_inner": innerRadius + }; + for (var id in radii) { + this.paths[id] = new MakerJs.paths.Circle(MakerJs.point.zero(), radii[id]); + } + } + return Ring; + }()); + models.Ring = Ring; + Ring.metaParameters = [ + { title: "outer radius", type: "range", min: 0, max: 100, step: 1, value: 50 }, + { title: "inner radius", type: "range", min: 0, max: 100, step: 1, value: 20 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var SCurve = (function () { + function SCurve(width, height) { + this.paths = {}; + function findRadius(x, y) { + return x + (y * y - x * x) / (2 * x); + } + var h2 = height / 2; + var w2 = width / 2; + var radius; + var startAngle; + var endAngle; + var arcOrigin; + if (width > height) { + radius = findRadius(h2, w2); + startAngle = 270; + endAngle = 360 - MakerJs.angle.toDegrees(Math.acos(w2 / radius)); + arcOrigin = [0, radius]; + } + else { + radius = findRadius(w2, h2); + startAngle = 180 - MakerJs.angle.toDegrees(Math.asin(h2 / radius)); + endAngle = 180; + arcOrigin = [radius, 0]; + } + var curve = new MakerJs.paths.Arc(arcOrigin, radius, startAngle, endAngle); + this.paths['curve_start'] = curve; + this.paths['curve_end'] = MakerJs.path.moveRelative(MakerJs.path.mirror(curve, true, true), [width, height]); + } + return SCurve; + }()); + models.SCurve = SCurve; + SCurve.metaParameters = [ + { title: "width", type: "range", min: 1, max: 100, value: 50 }, + { title: "height", type: "range", min: 1, max: 100, value: 100 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var Slot = (function () { + function Slot(origin, endPoint, radius, isolateCaps) { + if (isolateCaps === void 0) { isolateCaps = false; } + this.paths = {}; + var capModel = this; + if (isolateCaps) { + this.models = { "Caps": { paths: {} } }; + capModel = this.models["Caps"]; + } + var a = MakerJs.angle.ofPointInDegrees(origin, endPoint); + var len = MakerJs.measure.pointDistance(origin, endPoint); + this.paths['Top'] = new MakerJs.paths.Line([0, radius], [len, radius]); + this.paths['Bottom'] = new MakerJs.paths.Line([0, -radius], [len, -radius]); + capModel.paths['StartCap'] = new MakerJs.paths.Arc([0, 0], radius, 90, 270); + capModel.paths['EndCap'] = new MakerJs.paths.Arc([len, 0], radius, 270, 90); + MakerJs.model.rotate(this, a, [0, 0]); + this.origin = origin; + } + return Slot; + }()); + models.Slot = Slot; + Slot.metaParameters = [ + { + title: "origin", type: "select", value: [ + [0, 0], + [10, 0], + [10, 10] + ] + }, + { + title: "end", type: "select", value: [ + [80, 0], + [0, 30], + [10, 30] + ] + }, + { title: "radius", type: "range", min: 1, max: 50, value: 10 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var Square = (function () { + function Square(side) { + this.paths = {}; + this.paths = new models.Rectangle(side, side).paths; + } + return Square; + }()); + models.Square = Square; + Square.metaParameters = [ + { title: "side", type: "range", min: 1, max: 100, value: 100 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var models; + (function (models) { + var Star = (function () { + function Star(numberOfPoints, outerRadius, innerRadius, skipPoints) { + if (skipPoints === void 0) { skipPoints = 2; } + this.paths = {}; + if (!innerRadius) { + innerRadius = outerRadius * Star.InnerRadiusRatio(numberOfPoints, skipPoints); + } + var outerPoints = models.Polygon.getPoints(numberOfPoints, outerRadius); + var innerPoints = models.Polygon.getPoints(numberOfPoints, innerRadius, 180 / numberOfPoints); + var allPoints = []; + for (var i = 0; i < numberOfPoints; i++) { + allPoints.push(outerPoints[i]); + allPoints.push(innerPoints[i]); + } + var model = new models.ConnectTheDots(true, allPoints); + this.paths = model.paths; + delete model.paths; + } + Star.InnerRadiusRatio = function (numberOfPoints, skipPoints) { + //formula from http://www.jdawiseman.com/papers/easymath/surds_star_inner_radius.html + //Cos(Pi()*m/n) / Cos(Pi()*(m-1)/n) + if (numberOfPoints > 0 && skipPoints > 1 && skipPoints < numberOfPoints / 2) { + return Math.cos(Math.PI * skipPoints / numberOfPoints) / Math.cos(Math.PI * (skipPoints - 1) / numberOfPoints); + } + return 0; + }; + return Star; + }()); + models.Star = Star; + Star.metaParameters = [ + { title: "number of sides", type: "range", min: 3, max: 24, value: 8 }, + { title: "outer radius", type: "range", min: 1, max: 100, value: 50 }, + { title: "inner radius", type: "range", min: 0, max: 100, value: 15 }, + { title: "skip points (when inner radius is zero)", type: "range", min: 0, max: 12, value: 2 } + ]; + })(models = MakerJs.models || (MakerJs.models = {})); +})(MakerJs || (MakerJs = {})); diff --git a/index.js b/index.js index 9e562617a..6ab3c6355 100644 --- a/index.js +++ b/index.js @@ -165,21 +165,6 @@ var MakerJs; (function (MakerJs) { var angle; (function (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, angle2, accuracy) { - if (accuracy === void 0) { accuracy = .0001; } - var a1 = noRevolutions(angle1); - var a2 = noRevolutions(angle2); - var d = noRevolutions(MakerJs.round(a2 - a1, accuracy)); - return d == 0; - } - angle.areEqual = areEqual; /** * Ensures an angle is not greater than 360 * @@ -236,9 +221,20 @@ var MakerJs; */ function ofArcMiddle(arc, ratio) { if (ratio === void 0) { ratio = .5; } - return arc.startAngle + MakerJs.measure.arcAngle(arc) * ratio; + return arc.startAngle + ofArcSpan(arc) * ratio; } angle.ofArcMiddle = ofArcMiddle; + /** + * Total angle of an arc between its start and end angles. + * + * @param arc The arc to measure. + * @returns Angle of arc. + */ + function ofArcSpan(arc) { + var endAngle = angle.ofArcEnd(arc); + return endAngle - arc.startAngle; + } + angle.ofArcSpan = ofArcSpan; /** * Angle of a line path. * @@ -321,36 +317,6 @@ var MakerJs; return newPoint; } point.add = add; - /** - * 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, b, withinDistance) { - if (!withinDistance) { - return a[0] == b[0] && a[1] == b[1]; - } - else { - var distance = MakerJs.measure.pointDistance(a, b); - return distance <= withinDistance; - } - } - point.areEqual = areEqual; - /** - * 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, b, accuracy) { - if (accuracy === void 0) { accuracy = .0000001; } - return MakerJs.round(a[0], accuracy) == MakerJs.round(b[0], accuracy) && MakerJs.round(a[1], accuracy) == MakerJs.round(b[1], accuracy); - } - point.areEqualRounded = areEqualRounded; /** * Get the average of two points. * @@ -455,6 +421,47 @@ var MakerJs; return result; } point.fromPathEnds = fromPathEnds; + /** + * @private + */ + function verticalIntersectionPoint(verticalLine, nonVerticalSlope) { + var x = verticalLine.origin[0]; + var y = nonVerticalSlope.slope * x + nonVerticalSlope.yIntercept; + return [x, y]; + } + /** + * 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 fromSlopeIntersection(line1, line2, options) { + if (options === void 0) { options = {}; } + var slope1 = MakerJs.measure.lineSlope(line1); + var slope2 = MakerJs.measure.lineSlope(line2); + if (MakerJs.measure.isSlopeEqual(slope1, slope2)) { + //check for overlap + options.out_AreOverlapped = MakerJs.measure.isLineOverlapping(line1, line2, options.excludeTangents); + return null; + } + var pointOfIntersection; + if (!slope1.hasSlope) { + pointOfIntersection = verticalIntersectionPoint(line1, slope2); + } + else if (!slope2.hasSlope) { + pointOfIntersection = verticalIntersectionPoint(line2, slope1); + } + else { + // find intersection by line equation + var x = (slope2.yIntercept - slope1.yIntercept) / (slope1.slope - slope2.slope); + var y = slope1.slope * x + slope1.yIntercept; + pointOfIntersection = [x, y]; + } + return pointOfIntersection; + } + point.fromSlopeIntersection = fromSlopeIntersection; /** * Get the middle point of a path. * @@ -589,38 +596,6 @@ var MakerJs; (function (MakerJs) { var path; (function (path) { - /** - * @private - */ - var pathAreEqualMap = {}; - pathAreEqualMap[MakerJs.pathType.Line] = function (line1, line2, withinPointDistance) { - return (MakerJs.point.areEqual(line1.origin, line2.origin, withinPointDistance) && MakerJs.point.areEqual(line1.end, line2.end, withinPointDistance)) - || (MakerJs.point.areEqual(line1.origin, line2.end, withinPointDistance) && MakerJs.point.areEqual(line1.end, line2.origin, withinPointDistance)); - }; - pathAreEqualMap[MakerJs.pathType.Circle] = function (circle1, circle2, withinPointDistance) { - return MakerJs.point.areEqual(circle1.origin, circle2.origin, withinPointDistance) && circle1.radius == circle2.radius; - }; - pathAreEqualMap[MakerJs.pathType.Arc] = function (arc1, arc2, withinPointDistance) { - return pathAreEqualMap[MakerJs.pathType.Circle](arc1, arc2, withinPointDistance) && MakerJs.angle.areEqual(arc1.startAngle, arc2.startAngle) && MakerJs.angle.areEqual(arc1.endAngle, arc2.endAngle); - }; - /** - * Find out if two paths are equal. - * - * @param a First path. - * @param b Second path. - * @returns true if paths are the same, false if they are not - */ - function areEqual(path1, path2, withinPointDistance) { - var result = false; - if (path1.type == path2.type) { - var fn = pathAreEqualMap[path1.type]; - if (fn) { - result = fn(path1, path2, withinPointDistance); - } - } - return result; - } - path.areEqual = areEqual; /** * Create a clone of a path, mirrored on either or both x and y axes. * @@ -765,7 +740,7 @@ var MakerJs; var breakPathFunctionMap = {}; breakPathFunctionMap[MakerJs.pathType.Arc] = function (arc, pointOfBreak) { var angleAtBreakPoint = MakerJs.angle.ofPointInDegrees(arc.origin, pointOfBreak); - if (MakerJs.angle.areEqual(angleAtBreakPoint, arc.startAngle) || MakerJs.angle.areEqual(angleAtBreakPoint, arc.endAngle)) { + if (MakerJs.measure.isAngleEqual(angleAtBreakPoint, arc.startAngle) || MakerJs.measure.isAngleEqual(angleAtBreakPoint, arc.endAngle)) { return null; } function getAngleStrictlyBetweenArcAngles() { @@ -797,7 +772,7 @@ var MakerJs; return null; }; breakPathFunctionMap[MakerJs.pathType.Line] = function (line, pointOfBreak) { - if (MakerJs.point.areEqual(line.origin, pointOfBreak) || MakerJs.point.areEqual(line.end, pointOfBreak)) { + if (MakerJs.measure.isPointEqual(line.origin, pointOfBreak) || MakerJs.measure.isPointEqual(line.end, pointOfBreak)) { return null; } if (!MakerJs.measure.isBetweenPoints(pointOfBreak, line, true)) { @@ -918,7 +893,7 @@ var MakerJs; this.type = MakerJs.pathType.Arc; } return Arc; - })(); + }()); paths.Arc = Arc; /** * Class for circle path. @@ -955,13 +930,13 @@ var MakerJs; perpendiculars.push(MakerJs.path.rotate(lines[i], 90, midpoint)); } //find intersection of slopes of perpendiculars - this.origin = MakerJs.path.slopeIntersectionPoint(perpendiculars[0], perpendiculars[1]); + this.origin = MakerJs.point.fromSlopeIntersection(perpendiculars[0], perpendiculars[1]); //radius is distance to any of the 3 points this.radius = MakerJs.measure.pointDistance(this.origin, args[0]); } } return Circle; - })(); + }()); paths.Circle = Circle; /** * Class for line path. @@ -976,7 +951,7 @@ var MakerJs; this.type = MakerJs.pathType.Line; } return Line; - })(); + }()); paths.Line = Line; /** * Class for chord, which is simply a line path that connects the endpoints of an arc. @@ -991,7 +966,7 @@ var MakerJs; this.end = arcPoints[1]; } return Chord; - })(); + }()); paths.Chord = Chord; /** * Class for a parallel line path. @@ -1018,7 +993,7 @@ var MakerJs; MakerJs.path.move(this, newOrigin); } return Parallel; - })(); + }()); paths.Parallel = Parallel; })(paths = MakerJs.paths || (MakerJs.paths = {})); })(MakerJs || (MakerJs = {})); @@ -1305,7 +1280,7 @@ var MakerJs; * @private */ function breakAlongForeignPath(segments, overlappedSegments, foreignPath) { - if (MakerJs.path.areEqual(segments[0].path, foreignPath, .0001)) { + if (MakerJs.measure.isPathEqual(segments[0].path, foreignPath, .0001)) { segments[0].overlapped = true; segments[0].duplicate = true; overlappedSegments.push(segments[0]); @@ -1362,7 +1337,7 @@ var MakerJs; var added = 0; function addUniquePoint(pointToAdd) { for (var i = 0; i < pointArray.length; i++) { - if (MakerJs.point.areEqual(pointArray[i], pointToAdd, .000000001)) { + if (MakerJs.measure.isPointEqual(pointArray[i], pointToAdd, .000000001)) { return; } } @@ -1470,7 +1445,7 @@ var MakerJs; */ function checkForEqualOverlaps(crossedPathsA, crossedPathsB, pointMatchingDistance) { function compareSegments(segment1, segment2) { - if (MakerJs.path.areEqual(segment1.path, segment2.path, pointMatchingDistance)) { + if (MakerJs.measure.isPathEqual(segment1.path, segment2.path, pointMatchingDistance)) { segment1.duplicate = segment2.duplicate = true; } } @@ -1607,7 +1582,7 @@ var MakerJs; } }; return Collector; - })(); + }()); MakerJs.Collector = Collector; })(MakerJs || (MakerJs = {})); var MakerJs; @@ -1644,7 +1619,7 @@ var MakerJs; var startAngle = MakerJs.angle.noRevolutions(arc.startAngle); return { startAngle: startAngle, - endAngle: MakerJs.measure.arcAngle(arc) + startAngle + endAngle: MakerJs.angle.ofArcSpan(arc) + startAngle }; } /** @@ -1673,7 +1648,7 @@ var MakerJs; similarCircles.addItemToCollection(circleRef.pathContext, circleRef); }; map[MakerJs.pathType.Line] = function (lineRef) { - var slope = MakerJs.path.getSlope(lineRef.pathContext); + var slope = MakerJs.measure.lineSlope(lineRef.pathContext); similarLines.addItemToCollection(slope, lineRef); }; var opts = { @@ -1788,7 +1763,7 @@ var MakerJs; * @returns Model of straight lines with same endpoints as the arc. */ function straighten(arc, bevel) { - var arcSpan = MakerJs.measure.arcAngle(arc); + var arcSpan = MakerJs.angle.ofArcSpan(arc); var joints = 1; if (arcSpan >= 270) { joints = 4; @@ -1824,13 +1799,13 @@ var MakerJs; * Expand all paths in a model, then combine the resulting expansions. * * @param modelToExpand Model to expand. - * @param expansion Distance 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, expansion, joints) { + function expandPaths(modelToExpand, distance, joints) { if (joints === void 0) { joints = 0; } - if (expansion <= 0) + if (distance <= 0) return null; var result = { models: { @@ -1842,7 +1817,7 @@ var MakerJs; //TODO: work without origination var originated = model.originate(modelToExpand); model.walkPaths(originated, function (modelContext, pathId, pathContext) { - var expandedPathModel = MakerJs.path.expand(pathContext, expansion, true); + var expandedPathModel = MakerJs.path.expand(pathContext, distance, true); if (expandedPathModel) { var newId = model.getSimilarModelId(result.models['expansions'], pathId); model.originate(expandedPathModel); @@ -1878,6 +1853,31 @@ var MakerJs; return result; } model.expandPaths = expandPaths; + /** + * Outline a model by a specified distance. Useful for accommadating 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. + * @returns Model which surrounds the paths outside of the original model. + */ + function outline(modelToOutline, distance, joints) { + var expanded = expandPaths(modelToOutline, distance, joints); + if (!expanded) + return null; + var loops = model.findLoops(expanded); + if (loops && loops.models) { + var i = 0; + while (loops.models[i]) { + delete loops.models[i + 1]; + delete loops.models[i + 2]; + i += 4; + } + return loops; + } + return null; + } + model.outline = outline; })(model = MakerJs.model || (MakerJs.model = {})); })(MakerJs || (MakerJs = {})); var MakerJs; @@ -1954,18 +1954,96 @@ var MakerJs; var MakerJs; (function (MakerJs) { var measure; - (function (measure_1) { + (function (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 a First angle. + * @param b Second angle. + * @returns true if angles are the same, false if they are not */ - function arcAngle(arc) { - var endAngle = MakerJs.angle.ofArcEnd(arc); - return endAngle - arc.startAngle; + function isAngleEqual(angle1, angle2, accuracy) { + if (accuracy === void 0) { accuracy = .0001; } + var a1 = MakerJs.angle.noRevolutions(angle1); + var a2 = MakerJs.angle.noRevolutions(angle2); + var d = MakerJs.angle.noRevolutions(MakerJs.round(a2 - a1, accuracy)); + return d == 0; } - measure_1.arcAngle = arcAngle; + measure.isAngleEqual = isAngleEqual; + /** + * @private + */ + var pathAreEqualMap = {}; + pathAreEqualMap[MakerJs.pathType.Line] = function (line1, line2, withinPointDistance) { + return (isPointEqual(line1.origin, line2.origin, withinPointDistance) && isPointEqual(line1.end, line2.end, withinPointDistance)) + || (isPointEqual(line1.origin, line2.end, withinPointDistance) && isPointEqual(line1.end, line2.origin, withinPointDistance)); + }; + pathAreEqualMap[MakerJs.pathType.Circle] = function (circle1, circle2, withinPointDistance) { + return isPointEqual(circle1.origin, circle2.origin, withinPointDistance) && circle1.radius == circle2.radius; + }; + pathAreEqualMap[MakerJs.pathType.Arc] = function (arc1, arc2, withinPointDistance) { + return pathAreEqualMap[MakerJs.pathType.Circle](arc1, arc2, withinPointDistance) && isAngleEqual(arc1.startAngle, arc2.startAngle) && isAngleEqual(arc1.endAngle, arc2.endAngle); + }; + /** + * Find out if two paths are equal. + * + * @param a First path. + * @param b Second path. + * @returns true if paths are the same, false if they are not + */ + function isPathEqual(path1, path2, withinPointDistance) { + var result = false; + if (path1.type == path2.type) { + var fn = pathAreEqualMap[path1.type]; + if (fn) { + result = fn(path1, path2, withinPointDistance); + } + } + return result; + } + measure.isPathEqual = isPathEqual; + /** + * 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, b, withinDistance) { + if (!withinDistance) { + return a[0] == b[0] && a[1] == b[1]; + } + else { + var distance = measure.pointDistance(a, b); + return distance <= withinDistance; + } + } + measure.isPointEqual = isPointEqual; + /** + * Check for slope equality. + * + * @param slope1 The ISlope to test. + * @param slope2 The ISlope to check for equality. + * @returns Boolean true if slopes are equal. + */ + function isSlopeEqual(slope1, slope2) { + if (!slope1.hasSlope && !slope2.hasSlope) { + //lines are both vertical, see if x are the same + return MakerJs.round(slope1.line.origin[0] - slope2.line.origin[0]) == 0; + } + if (slope1.hasSlope && slope2.hasSlope && (MakerJs.round(slope1.slope - slope2.slope, .00001) == 0)) { + //lines are parallel, but not vertical, see if y-intercept is the same + return MakerJs.round(slope1.yIntercept - slope2.yIntercept, .00001) == 0; + } + return false; + } + measure.isSlopeEqual = isSlopeEqual; + })(measure = MakerJs.measure || (MakerJs.measure = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var measure; + (function (measure_1) { /** * Check for arc being concave or convex towards a given point. * @@ -2033,7 +2111,7 @@ var MakerJs; */ function isBetweenArcAngles(angleInQuestion, arc, exclusive) { var startAngle = MakerJs.angle.noRevolutions(arc.startAngle); - var span = arcAngle(arc); + var span = MakerJs.angle.ofArcSpan(arc); var endAngle = startAngle + span; angleInQuestion = MakerJs.angle.noRevolutions(angleInQuestion); //computed angles will not be negative, but the arc may have specified a negative angle, so check against one revolution forward and backward @@ -2081,24 +2159,27 @@ var MakerJs; } measure_1.isLineOverlapping = isLineOverlapping; /** - * Check for slope equality. - * - * @param slope1 The ISlope to test. - * @param slope2 The ISlope to check for equality. - * @returns Boolean true if slopes are equal. + * Gets the slope of a line. */ - function isSlopeEqual(slope1, slope2) { - if (!slope1.hasSlope && !slope2.hasSlope) { - //lines are both vertical, see if x are the same - return MakerJs.round(slope1.line.origin[0] - slope2.line.origin[0]) == 0; - } - if (slope1.hasSlope && slope2.hasSlope && (MakerJs.round(slope1.slope - slope2.slope, .00001) == 0)) { - //lines are parallel, but not vertical, see if y-intercept is the same - return MakerJs.round(slope1.yIntercept - slope2.yIntercept, .00001) == 0; + function lineSlope(line) { + var dx = line.end[0] - line.origin[0]; + if (MakerJs.round(dx) == 0) { + return { + line: line, + hasSlope: false + }; } - return false; + var dy = line.end[1] - line.origin[1]; + var slope = dy / dx; + var yIntercept = line.origin[1] - slope * line.origin[0]; + return { + line: line, + hasSlope: true, + slope: slope, + yIntercept: yIntercept + }; } - measure_1.isSlopeEqual = isSlopeEqual; + measure_1.lineSlope = lineSlope; /** * Calculates the distance between two points. * @@ -2180,7 +2261,7 @@ var MakerJs; }; map[MakerJs.pathType.Arc] = function (arc) { map[MakerJs.pathType.Circle](arc); //this sets the value var - var pct = arcAngle(arc) / 360; + var pct = MakerJs.angle.ofArcSpan(arc) / 360; value *= pct; }; var fn = map[pathToMeasure.type]; @@ -2326,7 +2407,7 @@ var MakerJs; } }; return Exporter; - })(); + }()); exporter.Exporter = Exporter; })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); })(MakerJs || (MakerJs = {})); @@ -2604,7 +2685,7 @@ var MakerJs; return null; }; map[MakerJs.pathType.Line][MakerJs.pathType.Line] = function (line1, line2, options) { - var intersectionPoint = slopeIntersectionPoint(line1, line2, options); + var intersectionPoint = MakerJs.point.fromSlopeIntersection(line1, line2, options); if (intersectionPoint) { //we have the point of intersection of endless lines, now check to see if the point is between both segemnts if (MakerJs.measure.isBetweenPoints(intersectionPoint, line1, options.excludeTangents) && MakerJs.measure.isBetweenPoints(intersectionPoint, line2, options.excludeTangents)) { @@ -2683,69 +2764,6 @@ var MakerJs; return null; return anglesWithinArc; } - /** - * Gets the slope of a line. - */ - function getSlope(line) { - var dx = line.end[0] - line.origin[0]; - if (MakerJs.round(dx) == 0) { - return { - line: line, - hasSlope: false - }; - } - var dy = line.end[1] - line.origin[1]; - var slope = dy / dx; - var yIntercept = line.origin[1] - slope * line.origin[0]; - return { - line: line, - hasSlope: true, - slope: slope, - yIntercept: yIntercept - }; - } - path.getSlope = getSlope; - /** - * @private - */ - function verticalIntersectionPoint(verticalLine, nonVerticalSlope) { - var x = verticalLine.origin[0]; - var y = nonVerticalSlope.slope * x + nonVerticalSlope.yIntercept; - return [x, y]; - } - /** - * 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, line2, options) { - if (options === void 0) { options = {}; } - var slope1 = getSlope(line1); - var slope2 = getSlope(line2); - if (MakerJs.measure.isSlopeEqual(slope1, slope2)) { - //check for overlap - options.out_AreOverlapped = MakerJs.measure.isLineOverlapping(line1, line2, options.excludeTangents); - return null; - } - var pointOfIntersection; - if (!slope1.hasSlope) { - pointOfIntersection = verticalIntersectionPoint(line1, slope2); - } - else if (!slope2.hasSlope) { - pointOfIntersection = verticalIntersectionPoint(line2, slope1); - } - else { - // find intersection by line equation - var x = (slope2.yIntercept - slope1.yIntercept) / (slope1.slope - slope2.slope); - var y = slope1.slope * x + slope1.yIntercept; - pointOfIntersection = [x, y]; - } - return pointOfIntersection; - } - path.slopeIntersectionPoint = slopeIntersectionPoint; /** * @private */ @@ -2803,7 +2821,7 @@ var MakerJs; */ function circleToCircle(circle1, circle2, options) { //see if circles are the same - if (circle1.radius == circle2.radius && MakerJs.point.areEqual(circle1.origin, circle2.origin, .0001)) { + if (circle1.radius == circle2.radius && MakerJs.measure.isPointEqual(circle1.origin, circle2.origin, .0001)) { options.out_AreOverlapped = true; return null; } @@ -2903,7 +2921,7 @@ var MakerJs; }; } function check(i1, i2) { - if (MakerJs.point.areEqual(path1Properties[i1].point, path2Properties[i2].point, .0001)) { + if (MakerJs.measure.isPointEqual(path1Properties[i1].point, path2Properties[i2].point, .0001)) { result = [ makeMatch(path1, path1Properties, i1), makeMatch(path2, path2Properties, i2) @@ -2927,7 +2945,7 @@ var MakerJs; return false; } properties[i].shardPoint = circleIntersection.intersectionPoints[0]; - if (MakerJs.point.areEqual(properties[i].point, circleIntersection.intersectionPoints[0], .0001)) { + if (MakerJs.measure.isPointEqual(properties[i].point, circleIntersection.intersectionPoints[0], .0001)) { if (circleIntersection.intersectionPoints.length > 1) { properties[i].shardPoint = circleIntersection.intersectionPoints[1]; } @@ -3004,7 +3022,7 @@ var MakerJs; path.rotate(guideLine, lineAngle, [0, 0]); path.moveRelative(guideLine, filletCenter); //get the intersection point of the slopes of the context line and the perpendicular line. This is where the fillet meets the line. - var intersectionPoint = path.slopeIntersectionPoint(line, guideLine); + var intersectionPoint = MakerJs.point.fromSlopeIntersection(line, guideLine); if (intersectionPoint) { result = { filletAngle: MakerJs.angle.ofPointInDegrees(filletCenter, intersectionPoint), @@ -3175,7 +3193,7 @@ var MakerJs; if (MakerJs.round(results[0].filletAngle - results[1].filletAngle) == 0) return null; var filletArc = new MakerJs.paths.Arc(center, filletRadius, results[0].filletAngle, results[1].filletAngle); - var filletSpan = MakerJs.measure.arcAngle(filletArc); + var filletSpan = MakerJs.angle.ofArcSpan(filletArc); //the algorithm is only valid for fillet less than 180 degrees if (filletSpan == 180) { return null; @@ -3488,7 +3506,7 @@ var MakerJs; return found; }; return DeadEndFinder; - })(); + }()); /** * Remove paths from a model which have endpoints that do not connect to other paths. * @@ -3605,7 +3623,7 @@ var MakerJs; } }; return XmlTag; - })(); + }()); exporter.XmlTag = XmlTag; })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); })(MakerJs || (MakerJs = {})); @@ -3947,7 +3965,7 @@ var MakerJs; } map[MakerJs.pathType.Arc] = function (id, arc, origin, layer) { var arcPoints = MakerJs.point.fromArc(arc); - if (MakerJs.point.areEqual(arcPoints[0], arcPoints[1])) { + if (MakerJs.measure.isPointEqual(arcPoints[0], arcPoints[1])) { circleInPaths(id, arc.origin, arc.radius, layer); } else { @@ -4072,7 +4090,7 @@ var MakerJs; } } return ConnectTheDots; - })(); + }()); models.ConnectTheDots = ConnectTheDots; ConnectTheDots.metaParameters = [ { title: "closed", type: "bool", value: true }, @@ -4112,7 +4130,7 @@ var MakerJs; return points; }; return Polygon; - })(); + }()); models.Polygon = Polygon; Polygon.metaParameters = [ { title: "number of sides", type: "range", min: 3, max: 24, value: 6 }, @@ -4135,7 +4153,7 @@ var MakerJs; } } return BoltCircle; - })(); + }()); models.BoltCircle = BoltCircle; BoltCircle.metaParameters = [ { title: "bolt circle radius", type: "range", min: 1, max: 100, value: 50 }, @@ -4163,7 +4181,7 @@ var MakerJs; } } return BoltRectangle; - })(); + }()); models.BoltRectangle = BoltRectangle; BoltRectangle.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 100 }, @@ -4202,7 +4220,7 @@ var MakerJs; } } return Dome; - })(); + }()); models.Dome = Dome; Dome.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4238,7 +4256,7 @@ var MakerJs; } } return RoundRectangle; - })(); + }()); models.RoundRectangle = RoundRectangle; RoundRectangle.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4257,7 +4275,7 @@ var MakerJs; this.paths = new models.RoundRectangle(width, height, Math.min(height / 2, width / 2)).paths; } return Oval; - })(); + }()); models.Oval = Oval; Oval.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4320,7 +4338,7 @@ var MakerJs; } } return OvalArc; - })(); + }()); models.OvalArc = OvalArc; OvalArc.metaParameters = [ { title: "start angle", type: "range", min: -360, max: 360, step: 1, value: 180 }, @@ -4341,7 +4359,7 @@ var MakerJs; this.paths = new models.ConnectTheDots(true, [[0, 0], [width, 0], [width, height], [0, height]]).paths; } return Rectangle; - })(); + }()); models.Rectangle = Rectangle; Rectangle.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4365,7 +4383,7 @@ var MakerJs; } } return Ring; - })(); + }()); models.Ring = Ring; Ring.metaParameters = [ { title: "outer radius", type: "range", min: 0, max: 100, step: 1, value: 50 }, @@ -4406,7 +4424,7 @@ var MakerJs; this.paths['curve_end'] = MakerJs.path.moveRelative(MakerJs.path.mirror(curve, true, true), [width, height]); } return SCurve; - })(); + }()); models.SCurve = SCurve; SCurve.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4437,7 +4455,7 @@ var MakerJs; this.origin = origin; } return Slot; - })(); + }()); models.Slot = Slot; Slot.metaParameters = [ { @@ -4468,7 +4486,7 @@ var MakerJs; this.paths = new models.Rectangle(side, side).paths; } return Square; - })(); + }()); models.Square = Square; Square.metaParameters = [ { title: "side", type: "range", min: 1, max: 100, value: 100 } @@ -4506,7 +4524,7 @@ var MakerJs; return 0; }; return Star; - })(); + }()); models.Star = Star; Star.metaParameters = [ { title: "number of sides", type: "range", min: 3, max: 24, value: 8 }, diff --git a/playground/export-format.js.map b/playground/export-format.js.map index 7860dd116..11e07d901 100644 --- a/playground/export-format.js.map +++ b/playground/export-format.js.map @@ -1 +1 @@ -{"version":3,"file":"export-format.js","sourceRoot":"","sources":["export-format.ts"],"names":["MakerJsPlaygroundExport","MakerJsPlaygroundExport.ExportFormat"],"mappings":"AAAA,IAAU,uBAAuB,CA0DhC;AA1DD,WAAU,uBAAuB,EAAC,CAAC;IAE/BA,WAAYA,YAAYA;QACpBC,+CAAIA,CAAAA;QACJA,6CAAGA,CAAAA;QACHA,6CAAGA,CAAAA;QACHA,yDAASA,CAAAA;QACTA,6CAAGA,CAAAA;IACPA,CAACA,EANWD,oCAAYA,KAAZA,oCAAYA,QAMvBA;IANDA,IAAYA,YAAYA,GAAZA,oCAMXA,CAAAA;IAAAA,CAACA;IAuBSA,iCAASA,GAA2BA,EAAEA,CAACA;IAElDA,iCAASA,CAACA,YAAYA,CAACA,IAAIA,CAACA,GAAGA;QAC3BA,SAASA,EAAEA,kBAAkBA;QAC7BA,aAAaA,EAAEA,MAAMA;KACxBA,CAACA;IAEFA,iCAASA,CAACA,YAAYA,CAACA,GAAGA,CAACA,GAAGA;QAC1BA,SAASA,EAAEA,iBAAiBA;QAC5BA,aAAaA,EAAEA,KAAKA;KACvBA,CAACA;IAEFA,iCAASA,CAACA,YAAYA,CAACA,GAAGA,CAACA,GAAGA;QAC1BA,SAASA,EAAEA,eAAeA;QAC1BA,aAAaA,EAAEA,KAAKA;KACvBA,CAACA;IAEFA,iCAASA,CAACA,YAAYA,CAACA,SAASA,CAACA,GAAGA;QAChCA,SAASA,EAAEA,YAAYA;QACvBA,aAAaA,EAAEA,KAAKA;KACvBA,CAACA;IAEFA,iCAASA,CAACA,YAAYA,CAACA,GAAGA,CAACA,GAAGA;QAC1BA,SAASA,EAAEA,iBAAiBA;QAC5BA,aAAaA,EAAEA,KAAKA;KACvBA,CAACA;AAENA,CAACA,EA1DS,uBAAuB,KAAvB,uBAAuB,QA0DhC"} \ No newline at end of file +{"version":3,"file":"export-format.js","sourceRoot":"","sources":["export-format.ts"],"names":[],"mappings":"AAAA,IAAU,uBAAuB,CA0DhC;AA1DD,WAAU,uBAAuB,EAAC,CAAC;IAE/B,WAAY,YAAY;QACpB,+CAAI,CAAA;QACJ,6CAAG,CAAA;QACH,6CAAG,CAAA;QACH,yDAAS,CAAA;QACT,6CAAG,CAAA;IACP,CAAC,EANW,oCAAY,KAAZ,oCAAY,QAMvB;IAND,IAAY,YAAY,GAAZ,oCAMX,CAAA;IAAA,CAAC;IAuBS,iCAAS,GAA2B,EAAE,CAAC;IAElD,iCAAS,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG;QAC3B,SAAS,EAAE,kBAAkB;QAC7B,aAAa,EAAE,MAAM;KACxB,CAAC;IAEF,iCAAS,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG;QAC1B,SAAS,EAAE,iBAAiB;QAC5B,aAAa,EAAE,KAAK;KACvB,CAAC;IAEF,iCAAS,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG;QAC1B,SAAS,EAAE,eAAe;QAC1B,aAAa,EAAE,KAAK;KACvB,CAAC;IAEF,iCAAS,CAAC,YAAY,CAAC,SAAS,CAAC,GAAG;QAChC,SAAS,EAAE,YAAY;QACvB,aAAa,EAAE,KAAK;KACvB,CAAC;IAEF,iCAAS,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG;QAC1B,SAAS,EAAE,iBAAiB;QAC5B,aAAa,EAAE,KAAK;KACvB,CAAC;AAEN,CAAC,EA1DS,uBAAuB,KAAvB,uBAAuB,QA0DhC"} \ No newline at end of file diff --git a/playground/playground.js b/playground/playground.js index bbf18bf0c..641185b8a 100644 --- a/playground/playground.js +++ b/playground/playground.js @@ -13,7 +13,7 @@ var MakerJsPlayground; } } return QueryStringParams; - })(); + }()); //private members var pixelsPerInch = 100; var iframe; diff --git a/playground/playground.js.map b/playground/playground.js.map index b9e689177..60dad4c38 100644 --- a/playground/playground.js.map +++ b/playground/playground.js.map @@ -1 +1 @@ -{"version":3,"file":"playground.js","sourceRoot":"","sources":["playground.ts"],"names":["MakerJsPlayground","MakerJsPlayground.QueryStringParams","MakerJsPlayground.QueryStringParams.constructor","MakerJsPlayground.isLandscapeOrientation","MakerJsPlayground.isHttp","MakerJsPlayground.isIJavaScriptErrorDetails","MakerJsPlayground.populateParams","MakerJsPlayground.generateCodeFromKit","MakerJsPlayground.resetDownload","MakerJsPlayground.Frown","MakerJsPlayground.highlightCodeError","MakerJsPlayground.dockEditor","MakerJsPlayground.arraysEqual","MakerJsPlayground.lockToPath","MakerJsPlayground.getLockedPathSvgElement","MakerJsPlayground.getLockedPathAndOffset","MakerJsPlayground.updateLockedPathNotes","MakerJsPlayground.measureLockedPath","MakerJsPlayground.getModelNaturalSize","MakerJsPlayground.getViewSize","MakerJsPlayground.areSameHeightMeasurement","MakerJsPlayground.initialize","MakerJsPlayground.onPointerClick","MakerJsPlayground.onPointerReset","MakerJsPlayground.getZoom","MakerJsPlayground.setZoom","MakerJsPlayground.onProcessed","MakerJsPlayground.runCodeFromEditor","MakerJsPlayground.setNotes","MakerJsPlayground.updateZoomScale","MakerJsPlayground.processResult","MakerJsPlayground.setParam","MakerJsPlayground.toggleSliderNumberBox","MakerJsPlayground.activateParam","MakerJsPlayground.activateParam.activate","MakerJsPlayground.deActivateParam","MakerJsPlayground.fitNatural","MakerJsPlayground.fitOnScreen","MakerJsPlayground.browserIsMicrosoft","MakerJsPlayground.render","MakerJsPlayground.filenameFromRequireId","MakerJsPlayground.downloadScript","MakerJsPlayground.toggleClassAndResize","MakerJsPlayground.toggleClass","MakerJsPlayground.getExport","MakerJsPlayground.downloadClick","MakerJsPlayground.copyToClipboard","MakerJsPlayground.cancelExport","MakerJsPlayground.isSmallDevice","MakerJsPlayground.onWindowResize"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"playground.js","sourceRoot":"","sources":["playground.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/playground/pointer.js b/playground/pointer.js index 1c27061f1..de61088ff 100644 --- a/playground/pointer.js +++ b/playground/pointer.js @@ -266,7 +266,7 @@ var Pointer; }, this.wheelTimeout); }; return Manager; - })(); + }()); Pointer.Manager = Manager; // Find out where an element is on the page // From http://www.quirksmode.org/js/findpos.html diff --git a/playground/pointer.js.map b/playground/pointer.js.map index 65f1f75ef..b27270eef 100644 --- a/playground/pointer.js.map +++ b/playground/pointer.js.map @@ -1 +1 @@ -{"version":3,"file":"pointer.js","sourceRoot":"","sources":["pointer.ts"],"names":["Pointer","Pointer.distanceBetweenCurrent2Points","Pointer.average","Pointer.Manager","Pointer.Manager.constructor","Pointer.Manager.getPointRelative","Pointer.Manager.reset","Pointer.Manager.asArray","Pointer.Manager.erase","Pointer.Manager.drawPointer","Pointer.Manager.drawPointer.createElement","Pointer.Manager.drawPointer.createCircle","Pointer.Manager.drawPointer.createLine","Pointer.Manager.draw","Pointer.Manager.isWithinMargin","Pointer.Manager.viewPointerDown","Pointer.Manager.viewPointerMove","Pointer.Manager.viewPointerUp","Pointer.Manager.scaleCenterPoint","Pointer.Manager.viewWheel","Pointer.pageOffset"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"pointer.js","sourceRoot":"","sources":["pointer.ts"],"names":[],"mappings":"AAEA,IAAO,OAAO,CAgab;AAhaD,WAAO,OAAO,EAAC,CAAC;IACD,sBAAc,GAAG,GAAG,CAAC;IACrB,qBAAa,GAAG,CAAC,CAAC;IAyC7B,uCAAuC,GAAe;QAClD,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/F,CAAC;IAED,iBAAiB,GAAe,EAAE,UAAmB;QAEjD,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;YAAC,MAAM,CAAC,IAAI,CAAC;QAEjC,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,IAAI,CAAC,GAAG,CAAC,CAAC;QAEV,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAClC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YACvB,IAAI,KAAK,GAAG,UAAU,GAAG,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,iBAAiB,CAAC;YAC5D,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;YACd,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED;QAYI,iBACY,IAAoB,EACpB,gBAAwB,EACxB,MAAsB,EACtB,OAAuB,EACvB,OAAoC,EACpC,OAAqC,EACrC,OAAkB;YAnBlC,iBAkVC;YArUe,SAAI,GAAJ,IAAI,CAAgB;YACpB,qBAAgB,GAAhB,gBAAgB,CAAQ;YACxB,WAAM,GAAN,MAAM,CAAgB;YACtB,YAAO,GAAP,OAAO,CAAgB;YACvB,YAAO,GAAP,OAAO,CAA6B;YACpC,YAAO,GAAP,OAAO,CAA8B;YACrC,YAAO,GAAP,OAAO,CAAW;YAhBtB,yCAAoC,GAAmB,IAAI,CAAC;YAC5D,mCAA8B,GAAmB,IAAI,CAAC;YAGtD,iBAAY,GAAG,GAAG,CAAC;YAEpB,SAAI,GAAgB,EAAE,CAAC;YAa1B,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,UAAC,CAAkB,IAAO,KAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/E,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,UAAC,CAAe,IAAO,KAAI,CAAC,eAAe,CAAC,CAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACzG,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,UAAC,CAAe,IAAO,KAAI,CAAC,eAAe,CAAC,CAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACzG,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,UAAC,CAAe,IAAO,KAAI,CAAC,aAAa,CAAC,CAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAErG,iIAAiI;YACjI,QAAQ,CAAC,gBAAgB,CAAC,UAAU,EAAE,UAAC,CAAa;gBAChD,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;oBAAC,MAAM,CAAC;gBAC7B,KAAI,CAAC,KAAK,EAAE,CAAC;YACjB,CAAC,CAAC,CAAC;YACH,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,UAAC,CAAa,IAAO,KAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3E,QAAQ,CAAC,gBAAgB,CAAC,aAAa,EAAE,UAAC,CAAiB,IAAO,KAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACvF,CAAC;QAEM,kCAAgB,GAAvB,UAAwB,EAAe;YACnC,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;YACtB,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,IAAI,UAAU,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACjF,IAAI,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YACnD,IAAI,YAAY,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;YACtD,IAAI,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;YAEtF,MAAM,CAAC;gBACH,UAAU,EAAE,UAAU;gBACtB,iBAAiB,EAAE,iBAAiB;gBACpC,OAAO,EAAE,OAAO;aACnB,CAAC;QACN,CAAC;QAEM,uBAAK,GAAZ;YACI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAE3C,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;YAEf,IAAI,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;QAEM,yBAAO,GAAd;YAEI,IAAI,MAAM,GAAe,EAAE,CAAC;YAE5B,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;gBACvB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/B,CAAC;YAED,MAAM,CAAC,MAAM,CAAC;QAClB,CAAC;QAEM,uBAAK,GAAZ;YACI,IAAI,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,gBAAgB,CAAe,CAAC;YAC1E,IAAI,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAe,CAAC;YACzD,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YACtD,MAAM,CAAC,WAAW,CAAC;QACvB,CAAC;QAEO,6BAAW,GAAnB,UAAoB,EAAU,EAAE,KAAqB,EAAE,EAAU,EAAE,WAAoB;YAEnF,uBAAuB,OAAe,EAAE,KAAU;gBAC9C,IAAI,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;gBAE/C,GAAG,CAAC,CAAC,IAAI,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC;oBACzB,IAAI,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;oBAC5B,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;gBAC7C,CAAC;gBAED,MAAM,CAAC,EAAE,CAAC;YACd,CAAC;YAED,sBAAsB,QAAgB,EAAE,EAAmB,EAAE,EAAmB,EAAE,CAAkB;gBAChG,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE;oBAC3B,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,EAAE;oBACR,IAAI,EAAE,EAAE;oBACR,GAAG,EAAE,CAAC;iBACT,CAAqB,CAAC;YAC3B,CAAC;YAED,oBAAoB,MAAc,EAAE,EAAmB,EAAE,EAAmB,EAAE,EAAmB,EAAE,EAAmB;gBAClH,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE;oBACzB,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,EAAE;oBACR,IAAI,EAAE,EAAE;oBACR,IAAI,EAAE,EAAE;oBACR,IAAI,EAAE,EAAE;iBACX,CAAmB,CAAC;YACzB,CAAC;YAED,IAAI,CAAC,GAAG,aAAa,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAgB,CAAC;YAExD,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;gBAEd,IAAI,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;gBACvD,IAAI,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBAEvD,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;gBACjB,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YAErB,CAAC;YAAC,IAAI,CAAC,CAAC;gBAEJ,IAAI,CAAC,GAAG,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAClD,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YAErB,CAAC;YAED,MAAM,CAAC,CAAC,CAAC;QACb,CAAC;QAEM,sBAAI,GAAX,UAAY,QAAoB;YAE5B,oBAAoB;YACpB,IAAI,WAAW,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;YAE/B,IAAI,EAAE,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAE3C,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACvC,IAAI,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAC1B,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC;YACnH,CAAC;YAED,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC;gBACvB,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,IAAI,CAAC,8BAA8B,EAAE,SAAS,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;YAC5G,CAAC;YAED,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC5C,CAAC;QAEM,gCAAc,GAArB,UAAsB,CAAiB;YAEnC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;gBAAC,MAAM,CAAC,KAAK,CAAC;YAC7H,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;gBAAC,MAAM,CAAC,KAAK,CAAC;YAE9H,MAAM,CAAC,IAAI,CAAC;QAChB,CAAC;QAEM,iCAAe,GAAtB,UAAuB,CAAgB;YAEnC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAE9B,IAAI,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;YAE7C,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;gBAAC,MAAM,CAAC;YAEhD,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,CAAC,CAAC,eAAe,EAAE,CAAC;YAEpB,IAAI,OAAO,GAAa;gBACpB,EAAE,EAAE,CAAC,CAAC,SAAS;gBACf,IAAI,EAAE,CAAC,CAAC,WAAW;gBACnB,OAAO,EAAE,aAAa;gBACtB,QAAQ,EAAE,aAAa;gBACvB,OAAO,EAAE,aAAa;gBACtB,UAAU,EAAE,CAAC,CAAC,UAAU;aAC3B,CAAC;YAEF,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC;YAChC,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;YAE/B,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;gBAEjB,KAAK,CAAC;oBACF,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;oBACrB,KAAK,CAAC;gBAEV,KAAK,CAAC;oBACF,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;oBAEzB,IAAI,CAAC,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC;oBAC9C,IAAI,CAAC,eAAe,GAAG,6BAA6B,CAAC,GAAG,CAAC,CAAC;oBAC1D,IAAI,CAAC,oCAAoC,GAAG,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;oBAChE,IAAI,CAAC,8BAA8B,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;oBAEzD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBACf,KAAK,CAAC;gBAEV;oBACI,IAAI,CAAC,KAAK,EAAE,CAAC;oBACb,KAAK,CAAC;YACd,CAAC;QAEL,CAAC;QAEM,iCAAe,GAAtB,UAAuB,CAAgB;YACnC,IAAI,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACrC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;gBAAC,MAAM,CAAC;YAErB,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAE9B,IAAI,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;YAC7C,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;gBAAC,MAAM,CAAC;YAEhD,CAAC,CAAC,eAAe,EAAE,CAAC;YACpB,CAAC,CAAC,cAAc,EAAE,CAAC;YAEnB,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;YACnC,OAAO,CAAC,OAAO,GAAG,aAAa,CAAC;YAEhC,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;YACtC,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;YACtB,IAAI,QAAwB,CAAC;YAE7B,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;gBAClB,YAAY;gBAEZ,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;gBAE/E,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YAEzB,CAAC;YAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;gBACzB,eAAe;gBAEf,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;gBAEzB,KAAK;gBAEL,IAAI,6BAA6B,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBAEvD,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,6BAA6B,EAAE,IAAI,CAAC,8BAA8B,CAAC,CAAC;gBAE1F,IAAI,CAAC,8BAA8B,GAAG,6BAA6B,CAAC;gBAEpE,MAAM;gBAEN,IAAI,eAAe,GAAG,6BAA6B,CAAC,GAAG,CAAC,CAAC;gBAEzD,IAAI,QAAQ,GAAG,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC;gBAEtD,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,GAAG,QAAQ,EAAE,IAAI,CAAC,oCAAoC,CAAC,CAAC;gBAEvG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC;YAED,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAE3C,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC;QAEM,+BAAa,GAApB,UAAqB,CAAgB;YAEjC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAE9B,IAAI,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACrC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;gBAEV,CAAC,CAAC,eAAe,EAAE,CAAC;gBACpB,CAAC,CAAC,cAAc,EAAE,CAAC;gBAEnB,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;gBAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;gBAEb,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;oBAElB,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;wBAEf,IAAI,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;wBAExG,EAAE,CAAC,CAAC,WAAW,IAAI,qBAAa,CAAC,CAAC,CAAC;4BAC/B,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;wBACrC,CAAC;oBACL,CAAC;oBAED,IAAI,CAAC,KAAK,EAAE,CAAC;gBAEjB,CAAC;gBAAC,IAAI,CAAC,CAAC;oBACJ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC9B,CAAC;YACL,CAAC;QACL,CAAC;QAEM,kCAAgB,GAAvB,UAAwB,OAAiB,EAAE,OAAe,EAAE,4BAA4C;YACpG,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;YACtB,IAAI,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;YAChC,IAAI,QAAQ,GAAG,OAAO,GAAG,YAAY,CAAC;YACtC,IAAI,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,4BAA4B,EAAE,YAAY,CAAC,CAAC;YAC/E,IAAI,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,oBAAoB,EAAE,QAAQ,CAAC,CAAC;YAClE,IAAI,eAAe,GAAG,CAAC,CAAC,QAAQ,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,CAAC;YAE5E,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC;YACvB,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;QACtD,CAAC;QAEM,2BAAS,GAAhB,UAAiB,CAAkB;YAAnC,iBA+BC;YA7BG,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;YAErB,IAAI,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;YAE7C,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;gBAAC,MAAM,CAAC;YAEhD,CAAC,CAAC,cAAc,EAAE,CAAC;YAEnB,IAAI,OAAO,GAAa;gBACpB,EAAE,EAAE,CAAC;gBACL,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,aAAa;gBACtB,QAAQ,EAAE,aAAa;gBACvB,OAAO,EAAE,aAAa;gBACtB,UAAU,EAAE,CAAC,CAAC,UAAU;aAC3B,CAAC;YACF,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YACtD,IAAI,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,GAAG,sBAAc,CAAC,CAAC;YAEvE,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;YAEvF,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YAEpC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YAErB,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC9B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;gBACzB,KAAI,CAAC,KAAK,EAAE,CAAC;YACjB,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC1B,CAAC;QAEL,cAAC;IAAD,CAAC,AAlVD,IAkVC;IAlVY,eAAO,UAkVnB,CAAA;IAED,2CAA2C;IAC3C,iDAAiD;IACjD,oBAA2B,EAAe;QACtC,IAAI,OAAO,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC;QAC5B,EAAE,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;YAClB,GAAG,CAAC;gBACA,OAAO,IAAI,EAAE,CAAC,UAAU,CAAC;gBACzB,MAAM,IAAI,EAAE,CAAC,SAAS,CAAC;YAC3B,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,YAA2B,EAAE;QAClD,CAAC;QACD,MAAM,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7B,CAAC;IATe,kBAAU,aASzB,CAAA;AACL,CAAC,EAhaM,OAAO,KAAP,OAAO,QAgab"} \ No newline at end of file diff --git a/playground/require-iframe.js b/playground/require-iframe.js index 93bba0d9f..8a8d2ccde 100644 --- a/playground/require-iframe.js +++ b/playground/require-iframe.js @@ -17,12 +17,12 @@ var MakerJsRequireIframe; this.loaded = 0; }; return Counter; - })(); + }()); var Dummy = (function () { function Dummy() { } return Dummy; - })(); + }()); function runCodeIsolated(javaScript) { var Fn = new Function('require', 'module', 'document', 'console', javaScript); var result = new Fn(window.require, window.module, document, parent.console); //call function with the "new" keyword so the "this" keyword is an instance diff --git a/playground/require-iframe.js.map b/playground/require-iframe.js.map index 154fa45d6..56acf9ec2 100644 --- a/playground/require-iframe.js.map +++ b/playground/require-iframe.js.map @@ -1 +1 @@ -{"version":3,"file":"require-iframe.js","sourceRoot":"","sources":["require-iframe.ts"],"names":["MakerJsRequireIframe","MakerJsRequireIframe.Counter","MakerJsRequireIframe.Counter.constructor","MakerJsRequireIframe.Counter.addLoaded","MakerJsRequireIframe.Counter.reset","MakerJsRequireIframe.Dummy","MakerJsRequireIframe.Dummy.constructor","MakerJsRequireIframe.runCodeIsolated","MakerJsRequireIframe.runCodeGlobal","MakerJsRequireIframe.load","complete2","complete1"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"require-iframe.js","sourceRoot":"","sources":["require-iframe.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/playground/worker/export-worker.js.map b/playground/worker/export-worker.js.map index aa43ac95b..e0554989f 100644 --- a/playground/worker/export-worker.js.map +++ b/playground/worker/export-worker.js.map @@ -1 +1 @@ -{"version":3,"file":"export-worker.js","sourceRoot":"","sources":["export-worker.ts"],"names":["toStl","getExporter"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"export-worker.js","sourceRoot":"","sources":["export-worker.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/target/js/browser.maker.js b/target/js/browser.maker.js index 0d8782bdf..c0aa514c7 100644 --- a/target/js/browser.maker.js +++ b/target/js/browser.maker.js @@ -332,21 +332,6 @@ var MakerJs; (function (MakerJs) { var angle; (function (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, angle2, accuracy) { - if (accuracy === void 0) { accuracy = .0001; } - var a1 = noRevolutions(angle1); - var a2 = noRevolutions(angle2); - var d = noRevolutions(MakerJs.round(a2 - a1, accuracy)); - return d == 0; - } - angle.areEqual = areEqual; /** * Ensures an angle is not greater than 360 * @@ -403,9 +388,20 @@ var MakerJs; */ function ofArcMiddle(arc, ratio) { if (ratio === void 0) { ratio = .5; } - return arc.startAngle + MakerJs.measure.arcAngle(arc) * ratio; + return arc.startAngle + ofArcSpan(arc) * ratio; } angle.ofArcMiddle = ofArcMiddle; + /** + * Total angle of an arc between its start and end angles. + * + * @param arc The arc to measure. + * @returns Angle of arc. + */ + function ofArcSpan(arc) { + var endAngle = angle.ofArcEnd(arc); + return endAngle - arc.startAngle; + } + angle.ofArcSpan = ofArcSpan; /** * Angle of a line path. * @@ -488,36 +484,6 @@ var MakerJs; return newPoint; } point.add = add; - /** - * 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, b, withinDistance) { - if (!withinDistance) { - return a[0] == b[0] && a[1] == b[1]; - } - else { - var distance = MakerJs.measure.pointDistance(a, b); - return distance <= withinDistance; - } - } - point.areEqual = areEqual; - /** - * 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, b, accuracy) { - if (accuracy === void 0) { accuracy = .0000001; } - return MakerJs.round(a[0], accuracy) == MakerJs.round(b[0], accuracy) && MakerJs.round(a[1], accuracy) == MakerJs.round(b[1], accuracy); - } - point.areEqualRounded = areEqualRounded; /** * Get the average of two points. * @@ -622,6 +588,47 @@ var MakerJs; return result; } point.fromPathEnds = fromPathEnds; + /** + * @private + */ + function verticalIntersectionPoint(verticalLine, nonVerticalSlope) { + var x = verticalLine.origin[0]; + var y = nonVerticalSlope.slope * x + nonVerticalSlope.yIntercept; + return [x, y]; + } + /** + * 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 fromSlopeIntersection(line1, line2, options) { + if (options === void 0) { options = {}; } + var slope1 = MakerJs.measure.lineSlope(line1); + var slope2 = MakerJs.measure.lineSlope(line2); + if (MakerJs.measure.isSlopeEqual(slope1, slope2)) { + //check for overlap + options.out_AreOverlapped = MakerJs.measure.isLineOverlapping(line1, line2, options.excludeTangents); + return null; + } + var pointOfIntersection; + if (!slope1.hasSlope) { + pointOfIntersection = verticalIntersectionPoint(line1, slope2); + } + else if (!slope2.hasSlope) { + pointOfIntersection = verticalIntersectionPoint(line2, slope1); + } + else { + // find intersection by line equation + var x = (slope2.yIntercept - slope1.yIntercept) / (slope1.slope - slope2.slope); + var y = slope1.slope * x + slope1.yIntercept; + pointOfIntersection = [x, y]; + } + return pointOfIntersection; + } + point.fromSlopeIntersection = fromSlopeIntersection; /** * Get the middle point of a path. * @@ -756,38 +763,6 @@ var MakerJs; (function (MakerJs) { var path; (function (path) { - /** - * @private - */ - var pathAreEqualMap = {}; - pathAreEqualMap[MakerJs.pathType.Line] = function (line1, line2, withinPointDistance) { - return (MakerJs.point.areEqual(line1.origin, line2.origin, withinPointDistance) && MakerJs.point.areEqual(line1.end, line2.end, withinPointDistance)) - || (MakerJs.point.areEqual(line1.origin, line2.end, withinPointDistance) && MakerJs.point.areEqual(line1.end, line2.origin, withinPointDistance)); - }; - pathAreEqualMap[MakerJs.pathType.Circle] = function (circle1, circle2, withinPointDistance) { - return MakerJs.point.areEqual(circle1.origin, circle2.origin, withinPointDistance) && circle1.radius == circle2.radius; - }; - pathAreEqualMap[MakerJs.pathType.Arc] = function (arc1, arc2, withinPointDistance) { - return pathAreEqualMap[MakerJs.pathType.Circle](arc1, arc2, withinPointDistance) && MakerJs.angle.areEqual(arc1.startAngle, arc2.startAngle) && MakerJs.angle.areEqual(arc1.endAngle, arc2.endAngle); - }; - /** - * Find out if two paths are equal. - * - * @param a First path. - * @param b Second path. - * @returns true if paths are the same, false if they are not - */ - function areEqual(path1, path2, withinPointDistance) { - var result = false; - if (path1.type == path2.type) { - var fn = pathAreEqualMap[path1.type]; - if (fn) { - result = fn(path1, path2, withinPointDistance); - } - } - return result; - } - path.areEqual = areEqual; /** * Create a clone of a path, mirrored on either or both x and y axes. * @@ -932,7 +907,7 @@ var MakerJs; var breakPathFunctionMap = {}; breakPathFunctionMap[MakerJs.pathType.Arc] = function (arc, pointOfBreak) { var angleAtBreakPoint = MakerJs.angle.ofPointInDegrees(arc.origin, pointOfBreak); - if (MakerJs.angle.areEqual(angleAtBreakPoint, arc.startAngle) || MakerJs.angle.areEqual(angleAtBreakPoint, arc.endAngle)) { + if (MakerJs.measure.isAngleEqual(angleAtBreakPoint, arc.startAngle) || MakerJs.measure.isAngleEqual(angleAtBreakPoint, arc.endAngle)) { return null; } function getAngleStrictlyBetweenArcAngles() { @@ -964,7 +939,7 @@ var MakerJs; return null; }; breakPathFunctionMap[MakerJs.pathType.Line] = function (line, pointOfBreak) { - if (MakerJs.point.areEqual(line.origin, pointOfBreak) || MakerJs.point.areEqual(line.end, pointOfBreak)) { + if (MakerJs.measure.isPointEqual(line.origin, pointOfBreak) || MakerJs.measure.isPointEqual(line.end, pointOfBreak)) { return null; } if (!MakerJs.measure.isBetweenPoints(pointOfBreak, line, true)) { @@ -1085,7 +1060,7 @@ var MakerJs; this.type = MakerJs.pathType.Arc; } return Arc; - })(); + }()); paths.Arc = Arc; /** * Class for circle path. @@ -1122,13 +1097,13 @@ var MakerJs; perpendiculars.push(MakerJs.path.rotate(lines[i], 90, midpoint)); } //find intersection of slopes of perpendiculars - this.origin = MakerJs.path.slopeIntersectionPoint(perpendiculars[0], perpendiculars[1]); + this.origin = MakerJs.point.fromSlopeIntersection(perpendiculars[0], perpendiculars[1]); //radius is distance to any of the 3 points this.radius = MakerJs.measure.pointDistance(this.origin, args[0]); } } return Circle; - })(); + }()); paths.Circle = Circle; /** * Class for line path. @@ -1143,7 +1118,7 @@ var MakerJs; this.type = MakerJs.pathType.Line; } return Line; - })(); + }()); paths.Line = Line; /** * Class for chord, which is simply a line path that connects the endpoints of an arc. @@ -1158,7 +1133,7 @@ var MakerJs; this.end = arcPoints[1]; } return Chord; - })(); + }()); paths.Chord = Chord; /** * Class for a parallel line path. @@ -1185,7 +1160,7 @@ var MakerJs; MakerJs.path.move(this, newOrigin); } return Parallel; - })(); + }()); paths.Parallel = Parallel; })(paths = MakerJs.paths || (MakerJs.paths = {})); })(MakerJs || (MakerJs = {})); @@ -1472,7 +1447,7 @@ var MakerJs; * @private */ function breakAlongForeignPath(segments, overlappedSegments, foreignPath) { - if (MakerJs.path.areEqual(segments[0].path, foreignPath, .0001)) { + if (MakerJs.measure.isPathEqual(segments[0].path, foreignPath, .0001)) { segments[0].overlapped = true; segments[0].duplicate = true; overlappedSegments.push(segments[0]); @@ -1529,7 +1504,7 @@ var MakerJs; var added = 0; function addUniquePoint(pointToAdd) { for (var i = 0; i < pointArray.length; i++) { - if (MakerJs.point.areEqual(pointArray[i], pointToAdd, .000000001)) { + if (MakerJs.measure.isPointEqual(pointArray[i], pointToAdd, .000000001)) { return; } } @@ -1637,7 +1612,7 @@ var MakerJs; */ function checkForEqualOverlaps(crossedPathsA, crossedPathsB, pointMatchingDistance) { function compareSegments(segment1, segment2) { - if (MakerJs.path.areEqual(segment1.path, segment2.path, pointMatchingDistance)) { + if (MakerJs.measure.isPathEqual(segment1.path, segment2.path, pointMatchingDistance)) { segment1.duplicate = segment2.duplicate = true; } } @@ -1774,7 +1749,7 @@ var MakerJs; } }; return Collector; - })(); + }()); MakerJs.Collector = Collector; })(MakerJs || (MakerJs = {})); var MakerJs; @@ -1811,7 +1786,7 @@ var MakerJs; var startAngle = MakerJs.angle.noRevolutions(arc.startAngle); return { startAngle: startAngle, - endAngle: MakerJs.measure.arcAngle(arc) + startAngle + endAngle: MakerJs.angle.ofArcSpan(arc) + startAngle }; } /** @@ -1840,7 +1815,7 @@ var MakerJs; similarCircles.addItemToCollection(circleRef.pathContext, circleRef); }; map[MakerJs.pathType.Line] = function (lineRef) { - var slope = MakerJs.path.getSlope(lineRef.pathContext); + var slope = MakerJs.measure.lineSlope(lineRef.pathContext); similarLines.addItemToCollection(slope, lineRef); }; var opts = { @@ -1955,7 +1930,7 @@ var MakerJs; * @returns Model of straight lines with same endpoints as the arc. */ function straighten(arc, bevel) { - var arcSpan = MakerJs.measure.arcAngle(arc); + var arcSpan = MakerJs.angle.ofArcSpan(arc); var joints = 1; if (arcSpan >= 270) { joints = 4; @@ -1991,13 +1966,13 @@ var MakerJs; * Expand all paths in a model, then combine the resulting expansions. * * @param modelToExpand Model to expand. - * @param expansion Distance 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, expansion, joints) { + function expandPaths(modelToExpand, distance, joints) { if (joints === void 0) { joints = 0; } - if (expansion <= 0) + if (distance <= 0) return null; var result = { models: { @@ -2009,7 +1984,7 @@ var MakerJs; //TODO: work without origination var originated = model.originate(modelToExpand); model.walkPaths(originated, function (modelContext, pathId, pathContext) { - var expandedPathModel = MakerJs.path.expand(pathContext, expansion, true); + var expandedPathModel = MakerJs.path.expand(pathContext, distance, true); if (expandedPathModel) { var newId = model.getSimilarModelId(result.models['expansions'], pathId); model.originate(expandedPathModel); @@ -2045,6 +2020,31 @@ var MakerJs; return result; } model.expandPaths = expandPaths; + /** + * Outline a model by a specified distance. Useful for accommadating 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. + * @returns Model which surrounds the paths outside of the original model. + */ + function outline(modelToOutline, distance, joints) { + var expanded = expandPaths(modelToOutline, distance, joints); + if (!expanded) + return null; + var loops = model.findLoops(expanded); + if (loops && loops.models) { + var i = 0; + while (loops.models[i]) { + delete loops.models[i + 1]; + delete loops.models[i + 2]; + i += 4; + } + return loops; + } + return null; + } + model.outline = outline; })(model = MakerJs.model || (MakerJs.model = {})); })(MakerJs || (MakerJs = {})); var MakerJs; @@ -2121,18 +2121,96 @@ var MakerJs; var MakerJs; (function (MakerJs) { var measure; - (function (measure_1) { + (function (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 a First angle. + * @param b Second angle. + * @returns true if angles are the same, false if they are not */ - function arcAngle(arc) { - var endAngle = MakerJs.angle.ofArcEnd(arc); - return endAngle - arc.startAngle; + function isAngleEqual(angle1, angle2, accuracy) { + if (accuracy === void 0) { accuracy = .0001; } + var a1 = MakerJs.angle.noRevolutions(angle1); + var a2 = MakerJs.angle.noRevolutions(angle2); + var d = MakerJs.angle.noRevolutions(MakerJs.round(a2 - a1, accuracy)); + return d == 0; } - measure_1.arcAngle = arcAngle; + measure.isAngleEqual = isAngleEqual; + /** + * @private + */ + var pathAreEqualMap = {}; + pathAreEqualMap[MakerJs.pathType.Line] = function (line1, line2, withinPointDistance) { + return (isPointEqual(line1.origin, line2.origin, withinPointDistance) && isPointEqual(line1.end, line2.end, withinPointDistance)) + || (isPointEqual(line1.origin, line2.end, withinPointDistance) && isPointEqual(line1.end, line2.origin, withinPointDistance)); + }; + pathAreEqualMap[MakerJs.pathType.Circle] = function (circle1, circle2, withinPointDistance) { + return isPointEqual(circle1.origin, circle2.origin, withinPointDistance) && circle1.radius == circle2.radius; + }; + pathAreEqualMap[MakerJs.pathType.Arc] = function (arc1, arc2, withinPointDistance) { + return pathAreEqualMap[MakerJs.pathType.Circle](arc1, arc2, withinPointDistance) && isAngleEqual(arc1.startAngle, arc2.startAngle) && isAngleEqual(arc1.endAngle, arc2.endAngle); + }; + /** + * Find out if two paths are equal. + * + * @param a First path. + * @param b Second path. + * @returns true if paths are the same, false if they are not + */ + function isPathEqual(path1, path2, withinPointDistance) { + var result = false; + if (path1.type == path2.type) { + var fn = pathAreEqualMap[path1.type]; + if (fn) { + result = fn(path1, path2, withinPointDistance); + } + } + return result; + } + measure.isPathEqual = isPathEqual; + /** + * 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, b, withinDistance) { + if (!withinDistance) { + return a[0] == b[0] && a[1] == b[1]; + } + else { + var distance = measure.pointDistance(a, b); + return distance <= withinDistance; + } + } + measure.isPointEqual = isPointEqual; + /** + * Check for slope equality. + * + * @param slope1 The ISlope to test. + * @param slope2 The ISlope to check for equality. + * @returns Boolean true if slopes are equal. + */ + function isSlopeEqual(slope1, slope2) { + if (!slope1.hasSlope && !slope2.hasSlope) { + //lines are both vertical, see if x are the same + return MakerJs.round(slope1.line.origin[0] - slope2.line.origin[0]) == 0; + } + if (slope1.hasSlope && slope2.hasSlope && (MakerJs.round(slope1.slope - slope2.slope, .00001) == 0)) { + //lines are parallel, but not vertical, see if y-intercept is the same + return MakerJs.round(slope1.yIntercept - slope2.yIntercept, .00001) == 0; + } + return false; + } + measure.isSlopeEqual = isSlopeEqual; + })(measure = MakerJs.measure || (MakerJs.measure = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var measure; + (function (measure_1) { /** * Check for arc being concave or convex towards a given point. * @@ -2200,7 +2278,7 @@ var MakerJs; */ function isBetweenArcAngles(angleInQuestion, arc, exclusive) { var startAngle = MakerJs.angle.noRevolutions(arc.startAngle); - var span = arcAngle(arc); + var span = MakerJs.angle.ofArcSpan(arc); var endAngle = startAngle + span; angleInQuestion = MakerJs.angle.noRevolutions(angleInQuestion); //computed angles will not be negative, but the arc may have specified a negative angle, so check against one revolution forward and backward @@ -2248,24 +2326,27 @@ var MakerJs; } measure_1.isLineOverlapping = isLineOverlapping; /** - * Check for slope equality. - * - * @param slope1 The ISlope to test. - * @param slope2 The ISlope to check for equality. - * @returns Boolean true if slopes are equal. + * Gets the slope of a line. */ - function isSlopeEqual(slope1, slope2) { - if (!slope1.hasSlope && !slope2.hasSlope) { - //lines are both vertical, see if x are the same - return MakerJs.round(slope1.line.origin[0] - slope2.line.origin[0]) == 0; - } - if (slope1.hasSlope && slope2.hasSlope && (MakerJs.round(slope1.slope - slope2.slope, .00001) == 0)) { - //lines are parallel, but not vertical, see if y-intercept is the same - return MakerJs.round(slope1.yIntercept - slope2.yIntercept, .00001) == 0; + function lineSlope(line) { + var dx = line.end[0] - line.origin[0]; + if (MakerJs.round(dx) == 0) { + return { + line: line, + hasSlope: false + }; } - return false; + var dy = line.end[1] - line.origin[1]; + var slope = dy / dx; + var yIntercept = line.origin[1] - slope * line.origin[0]; + return { + line: line, + hasSlope: true, + slope: slope, + yIntercept: yIntercept + }; } - measure_1.isSlopeEqual = isSlopeEqual; + measure_1.lineSlope = lineSlope; /** * Calculates the distance between two points. * @@ -2347,7 +2428,7 @@ var MakerJs; }; map[MakerJs.pathType.Arc] = function (arc) { map[MakerJs.pathType.Circle](arc); //this sets the value var - var pct = arcAngle(arc) / 360; + var pct = MakerJs.angle.ofArcSpan(arc) / 360; value *= pct; }; var fn = map[pathToMeasure.type]; @@ -2493,7 +2574,7 @@ var MakerJs; } }; return Exporter; - })(); + }()); exporter.Exporter = Exporter; })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); })(MakerJs || (MakerJs = {})); @@ -2771,7 +2852,7 @@ var MakerJs; return null; }; map[MakerJs.pathType.Line][MakerJs.pathType.Line] = function (line1, line2, options) { - var intersectionPoint = slopeIntersectionPoint(line1, line2, options); + var intersectionPoint = MakerJs.point.fromSlopeIntersection(line1, line2, options); if (intersectionPoint) { //we have the point of intersection of endless lines, now check to see if the point is between both segemnts if (MakerJs.measure.isBetweenPoints(intersectionPoint, line1, options.excludeTangents) && MakerJs.measure.isBetweenPoints(intersectionPoint, line2, options.excludeTangents)) { @@ -2850,69 +2931,6 @@ var MakerJs; return null; return anglesWithinArc; } - /** - * Gets the slope of a line. - */ - function getSlope(line) { - var dx = line.end[0] - line.origin[0]; - if (MakerJs.round(dx) == 0) { - return { - line: line, - hasSlope: false - }; - } - var dy = line.end[1] - line.origin[1]; - var slope = dy / dx; - var yIntercept = line.origin[1] - slope * line.origin[0]; - return { - line: line, - hasSlope: true, - slope: slope, - yIntercept: yIntercept - }; - } - path.getSlope = getSlope; - /** - * @private - */ - function verticalIntersectionPoint(verticalLine, nonVerticalSlope) { - var x = verticalLine.origin[0]; - var y = nonVerticalSlope.slope * x + nonVerticalSlope.yIntercept; - return [x, y]; - } - /** - * 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, line2, options) { - if (options === void 0) { options = {}; } - var slope1 = getSlope(line1); - var slope2 = getSlope(line2); - if (MakerJs.measure.isSlopeEqual(slope1, slope2)) { - //check for overlap - options.out_AreOverlapped = MakerJs.measure.isLineOverlapping(line1, line2, options.excludeTangents); - return null; - } - var pointOfIntersection; - if (!slope1.hasSlope) { - pointOfIntersection = verticalIntersectionPoint(line1, slope2); - } - else if (!slope2.hasSlope) { - pointOfIntersection = verticalIntersectionPoint(line2, slope1); - } - else { - // find intersection by line equation - var x = (slope2.yIntercept - slope1.yIntercept) / (slope1.slope - slope2.slope); - var y = slope1.slope * x + slope1.yIntercept; - pointOfIntersection = [x, y]; - } - return pointOfIntersection; - } - path.slopeIntersectionPoint = slopeIntersectionPoint; /** * @private */ @@ -2970,7 +2988,7 @@ var MakerJs; */ function circleToCircle(circle1, circle2, options) { //see if circles are the same - if (circle1.radius == circle2.radius && MakerJs.point.areEqual(circle1.origin, circle2.origin, .0001)) { + if (circle1.radius == circle2.radius && MakerJs.measure.isPointEqual(circle1.origin, circle2.origin, .0001)) { options.out_AreOverlapped = true; return null; } @@ -3070,7 +3088,7 @@ var MakerJs; }; } function check(i1, i2) { - if (MakerJs.point.areEqual(path1Properties[i1].point, path2Properties[i2].point, .0001)) { + if (MakerJs.measure.isPointEqual(path1Properties[i1].point, path2Properties[i2].point, .0001)) { result = [ makeMatch(path1, path1Properties, i1), makeMatch(path2, path2Properties, i2) @@ -3094,7 +3112,7 @@ var MakerJs; return false; } properties[i].shardPoint = circleIntersection.intersectionPoints[0]; - if (MakerJs.point.areEqual(properties[i].point, circleIntersection.intersectionPoints[0], .0001)) { + if (MakerJs.measure.isPointEqual(properties[i].point, circleIntersection.intersectionPoints[0], .0001)) { if (circleIntersection.intersectionPoints.length > 1) { properties[i].shardPoint = circleIntersection.intersectionPoints[1]; } @@ -3171,7 +3189,7 @@ var MakerJs; path.rotate(guideLine, lineAngle, [0, 0]); path.moveRelative(guideLine, filletCenter); //get the intersection point of the slopes of the context line and the perpendicular line. This is where the fillet meets the line. - var intersectionPoint = path.slopeIntersectionPoint(line, guideLine); + var intersectionPoint = MakerJs.point.fromSlopeIntersection(line, guideLine); if (intersectionPoint) { result = { filletAngle: MakerJs.angle.ofPointInDegrees(filletCenter, intersectionPoint), @@ -3342,7 +3360,7 @@ var MakerJs; if (MakerJs.round(results[0].filletAngle - results[1].filletAngle) == 0) return null; var filletArc = new MakerJs.paths.Arc(center, filletRadius, results[0].filletAngle, results[1].filletAngle); - var filletSpan = MakerJs.measure.arcAngle(filletArc); + var filletSpan = MakerJs.angle.ofArcSpan(filletArc); //the algorithm is only valid for fillet less than 180 degrees if (filletSpan == 180) { return null; @@ -3655,7 +3673,7 @@ var MakerJs; return found; }; return DeadEndFinder; - })(); + }()); /** * Remove paths from a model which have endpoints that do not connect to other paths. * @@ -3772,7 +3790,7 @@ var MakerJs; } }; return XmlTag; - })(); + }()); exporter.XmlTag = XmlTag; })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); })(MakerJs || (MakerJs = {})); @@ -4114,7 +4132,7 @@ var MakerJs; } map[MakerJs.pathType.Arc] = function (id, arc, origin, layer) { var arcPoints = MakerJs.point.fromArc(arc); - if (MakerJs.point.areEqual(arcPoints[0], arcPoints[1])) { + if (MakerJs.measure.isPointEqual(arcPoints[0], arcPoints[1])) { circleInPaths(id, arc.origin, arc.radius, layer); } else { @@ -4239,7 +4257,7 @@ var MakerJs; } } return ConnectTheDots; - })(); + }()); models.ConnectTheDots = ConnectTheDots; ConnectTheDots.metaParameters = [ { title: "closed", type: "bool", value: true }, @@ -4279,7 +4297,7 @@ var MakerJs; return points; }; return Polygon; - })(); + }()); models.Polygon = Polygon; Polygon.metaParameters = [ { title: "number of sides", type: "range", min: 3, max: 24, value: 6 }, @@ -4302,7 +4320,7 @@ var MakerJs; } } return BoltCircle; - })(); + }()); models.BoltCircle = BoltCircle; BoltCircle.metaParameters = [ { title: "bolt circle radius", type: "range", min: 1, max: 100, value: 50 }, @@ -4330,7 +4348,7 @@ var MakerJs; } } return BoltRectangle; - })(); + }()); models.BoltRectangle = BoltRectangle; BoltRectangle.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 100 }, @@ -4369,7 +4387,7 @@ var MakerJs; } } return Dome; - })(); + }()); models.Dome = Dome; Dome.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4405,7 +4423,7 @@ var MakerJs; } } return RoundRectangle; - })(); + }()); models.RoundRectangle = RoundRectangle; RoundRectangle.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4424,7 +4442,7 @@ var MakerJs; this.paths = new models.RoundRectangle(width, height, Math.min(height / 2, width / 2)).paths; } return Oval; - })(); + }()); models.Oval = Oval; Oval.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4487,7 +4505,7 @@ var MakerJs; } } return OvalArc; - })(); + }()); models.OvalArc = OvalArc; OvalArc.metaParameters = [ { title: "start angle", type: "range", min: -360, max: 360, step: 1, value: 180 }, @@ -4508,7 +4526,7 @@ var MakerJs; this.paths = new models.ConnectTheDots(true, [[0, 0], [width, 0], [width, height], [0, height]]).paths; } return Rectangle; - })(); + }()); models.Rectangle = Rectangle; Rectangle.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4532,7 +4550,7 @@ var MakerJs; } } return Ring; - })(); + }()); models.Ring = Ring; Ring.metaParameters = [ { title: "outer radius", type: "range", min: 0, max: 100, step: 1, value: 50 }, @@ -4573,7 +4591,7 @@ var MakerJs; this.paths['curve_end'] = MakerJs.path.moveRelative(MakerJs.path.mirror(curve, true, true), [width, height]); } return SCurve; - })(); + }()); models.SCurve = SCurve; SCurve.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4604,7 +4622,7 @@ var MakerJs; this.origin = origin; } return Slot; - })(); + }()); models.Slot = Slot; Slot.metaParameters = [ { @@ -4635,7 +4653,7 @@ var MakerJs; this.paths = new models.Rectangle(side, side).paths; } return Square; - })(); + }()); models.Square = Square; Square.metaParameters = [ { title: "side", type: "range", min: 1, max: 100, value: 100 } @@ -4673,7 +4691,7 @@ var MakerJs; return 0; }; return Star; - })(); + }()); models.Star = Star; Star.metaParameters = [ { title: "number of sides", type: "range", min: 3, max: 24, value: 8 }, diff --git a/target/js/node.maker.js b/target/js/node.maker.js index 9e562617a..6ab3c6355 100644 --- a/target/js/node.maker.js +++ b/target/js/node.maker.js @@ -165,21 +165,6 @@ var MakerJs; (function (MakerJs) { var angle; (function (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, angle2, accuracy) { - if (accuracy === void 0) { accuracy = .0001; } - var a1 = noRevolutions(angle1); - var a2 = noRevolutions(angle2); - var d = noRevolutions(MakerJs.round(a2 - a1, accuracy)); - return d == 0; - } - angle.areEqual = areEqual; /** * Ensures an angle is not greater than 360 * @@ -236,9 +221,20 @@ var MakerJs; */ function ofArcMiddle(arc, ratio) { if (ratio === void 0) { ratio = .5; } - return arc.startAngle + MakerJs.measure.arcAngle(arc) * ratio; + return arc.startAngle + ofArcSpan(arc) * ratio; } angle.ofArcMiddle = ofArcMiddle; + /** + * Total angle of an arc between its start and end angles. + * + * @param arc The arc to measure. + * @returns Angle of arc. + */ + function ofArcSpan(arc) { + var endAngle = angle.ofArcEnd(arc); + return endAngle - arc.startAngle; + } + angle.ofArcSpan = ofArcSpan; /** * Angle of a line path. * @@ -321,36 +317,6 @@ var MakerJs; return newPoint; } point.add = add; - /** - * 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, b, withinDistance) { - if (!withinDistance) { - return a[0] == b[0] && a[1] == b[1]; - } - else { - var distance = MakerJs.measure.pointDistance(a, b); - return distance <= withinDistance; - } - } - point.areEqual = areEqual; - /** - * 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, b, accuracy) { - if (accuracy === void 0) { accuracy = .0000001; } - return MakerJs.round(a[0], accuracy) == MakerJs.round(b[0], accuracy) && MakerJs.round(a[1], accuracy) == MakerJs.round(b[1], accuracy); - } - point.areEqualRounded = areEqualRounded; /** * Get the average of two points. * @@ -455,6 +421,47 @@ var MakerJs; return result; } point.fromPathEnds = fromPathEnds; + /** + * @private + */ + function verticalIntersectionPoint(verticalLine, nonVerticalSlope) { + var x = verticalLine.origin[0]; + var y = nonVerticalSlope.slope * x + nonVerticalSlope.yIntercept; + return [x, y]; + } + /** + * 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 fromSlopeIntersection(line1, line2, options) { + if (options === void 0) { options = {}; } + var slope1 = MakerJs.measure.lineSlope(line1); + var slope2 = MakerJs.measure.lineSlope(line2); + if (MakerJs.measure.isSlopeEqual(slope1, slope2)) { + //check for overlap + options.out_AreOverlapped = MakerJs.measure.isLineOverlapping(line1, line2, options.excludeTangents); + return null; + } + var pointOfIntersection; + if (!slope1.hasSlope) { + pointOfIntersection = verticalIntersectionPoint(line1, slope2); + } + else if (!slope2.hasSlope) { + pointOfIntersection = verticalIntersectionPoint(line2, slope1); + } + else { + // find intersection by line equation + var x = (slope2.yIntercept - slope1.yIntercept) / (slope1.slope - slope2.slope); + var y = slope1.slope * x + slope1.yIntercept; + pointOfIntersection = [x, y]; + } + return pointOfIntersection; + } + point.fromSlopeIntersection = fromSlopeIntersection; /** * Get the middle point of a path. * @@ -589,38 +596,6 @@ var MakerJs; (function (MakerJs) { var path; (function (path) { - /** - * @private - */ - var pathAreEqualMap = {}; - pathAreEqualMap[MakerJs.pathType.Line] = function (line1, line2, withinPointDistance) { - return (MakerJs.point.areEqual(line1.origin, line2.origin, withinPointDistance) && MakerJs.point.areEqual(line1.end, line2.end, withinPointDistance)) - || (MakerJs.point.areEqual(line1.origin, line2.end, withinPointDistance) && MakerJs.point.areEqual(line1.end, line2.origin, withinPointDistance)); - }; - pathAreEqualMap[MakerJs.pathType.Circle] = function (circle1, circle2, withinPointDistance) { - return MakerJs.point.areEqual(circle1.origin, circle2.origin, withinPointDistance) && circle1.radius == circle2.radius; - }; - pathAreEqualMap[MakerJs.pathType.Arc] = function (arc1, arc2, withinPointDistance) { - return pathAreEqualMap[MakerJs.pathType.Circle](arc1, arc2, withinPointDistance) && MakerJs.angle.areEqual(arc1.startAngle, arc2.startAngle) && MakerJs.angle.areEqual(arc1.endAngle, arc2.endAngle); - }; - /** - * Find out if two paths are equal. - * - * @param a First path. - * @param b Second path. - * @returns true if paths are the same, false if they are not - */ - function areEqual(path1, path2, withinPointDistance) { - var result = false; - if (path1.type == path2.type) { - var fn = pathAreEqualMap[path1.type]; - if (fn) { - result = fn(path1, path2, withinPointDistance); - } - } - return result; - } - path.areEqual = areEqual; /** * Create a clone of a path, mirrored on either or both x and y axes. * @@ -765,7 +740,7 @@ var MakerJs; var breakPathFunctionMap = {}; breakPathFunctionMap[MakerJs.pathType.Arc] = function (arc, pointOfBreak) { var angleAtBreakPoint = MakerJs.angle.ofPointInDegrees(arc.origin, pointOfBreak); - if (MakerJs.angle.areEqual(angleAtBreakPoint, arc.startAngle) || MakerJs.angle.areEqual(angleAtBreakPoint, arc.endAngle)) { + if (MakerJs.measure.isAngleEqual(angleAtBreakPoint, arc.startAngle) || MakerJs.measure.isAngleEqual(angleAtBreakPoint, arc.endAngle)) { return null; } function getAngleStrictlyBetweenArcAngles() { @@ -797,7 +772,7 @@ var MakerJs; return null; }; breakPathFunctionMap[MakerJs.pathType.Line] = function (line, pointOfBreak) { - if (MakerJs.point.areEqual(line.origin, pointOfBreak) || MakerJs.point.areEqual(line.end, pointOfBreak)) { + if (MakerJs.measure.isPointEqual(line.origin, pointOfBreak) || MakerJs.measure.isPointEqual(line.end, pointOfBreak)) { return null; } if (!MakerJs.measure.isBetweenPoints(pointOfBreak, line, true)) { @@ -918,7 +893,7 @@ var MakerJs; this.type = MakerJs.pathType.Arc; } return Arc; - })(); + }()); paths.Arc = Arc; /** * Class for circle path. @@ -955,13 +930,13 @@ var MakerJs; perpendiculars.push(MakerJs.path.rotate(lines[i], 90, midpoint)); } //find intersection of slopes of perpendiculars - this.origin = MakerJs.path.slopeIntersectionPoint(perpendiculars[0], perpendiculars[1]); + this.origin = MakerJs.point.fromSlopeIntersection(perpendiculars[0], perpendiculars[1]); //radius is distance to any of the 3 points this.radius = MakerJs.measure.pointDistance(this.origin, args[0]); } } return Circle; - })(); + }()); paths.Circle = Circle; /** * Class for line path. @@ -976,7 +951,7 @@ var MakerJs; this.type = MakerJs.pathType.Line; } return Line; - })(); + }()); paths.Line = Line; /** * Class for chord, which is simply a line path that connects the endpoints of an arc. @@ -991,7 +966,7 @@ var MakerJs; this.end = arcPoints[1]; } return Chord; - })(); + }()); paths.Chord = Chord; /** * Class for a parallel line path. @@ -1018,7 +993,7 @@ var MakerJs; MakerJs.path.move(this, newOrigin); } return Parallel; - })(); + }()); paths.Parallel = Parallel; })(paths = MakerJs.paths || (MakerJs.paths = {})); })(MakerJs || (MakerJs = {})); @@ -1305,7 +1280,7 @@ var MakerJs; * @private */ function breakAlongForeignPath(segments, overlappedSegments, foreignPath) { - if (MakerJs.path.areEqual(segments[0].path, foreignPath, .0001)) { + if (MakerJs.measure.isPathEqual(segments[0].path, foreignPath, .0001)) { segments[0].overlapped = true; segments[0].duplicate = true; overlappedSegments.push(segments[0]); @@ -1362,7 +1337,7 @@ var MakerJs; var added = 0; function addUniquePoint(pointToAdd) { for (var i = 0; i < pointArray.length; i++) { - if (MakerJs.point.areEqual(pointArray[i], pointToAdd, .000000001)) { + if (MakerJs.measure.isPointEqual(pointArray[i], pointToAdd, .000000001)) { return; } } @@ -1470,7 +1445,7 @@ var MakerJs; */ function checkForEqualOverlaps(crossedPathsA, crossedPathsB, pointMatchingDistance) { function compareSegments(segment1, segment2) { - if (MakerJs.path.areEqual(segment1.path, segment2.path, pointMatchingDistance)) { + if (MakerJs.measure.isPathEqual(segment1.path, segment2.path, pointMatchingDistance)) { segment1.duplicate = segment2.duplicate = true; } } @@ -1607,7 +1582,7 @@ var MakerJs; } }; return Collector; - })(); + }()); MakerJs.Collector = Collector; })(MakerJs || (MakerJs = {})); var MakerJs; @@ -1644,7 +1619,7 @@ var MakerJs; var startAngle = MakerJs.angle.noRevolutions(arc.startAngle); return { startAngle: startAngle, - endAngle: MakerJs.measure.arcAngle(arc) + startAngle + endAngle: MakerJs.angle.ofArcSpan(arc) + startAngle }; } /** @@ -1673,7 +1648,7 @@ var MakerJs; similarCircles.addItemToCollection(circleRef.pathContext, circleRef); }; map[MakerJs.pathType.Line] = function (lineRef) { - var slope = MakerJs.path.getSlope(lineRef.pathContext); + var slope = MakerJs.measure.lineSlope(lineRef.pathContext); similarLines.addItemToCollection(slope, lineRef); }; var opts = { @@ -1788,7 +1763,7 @@ var MakerJs; * @returns Model of straight lines with same endpoints as the arc. */ function straighten(arc, bevel) { - var arcSpan = MakerJs.measure.arcAngle(arc); + var arcSpan = MakerJs.angle.ofArcSpan(arc); var joints = 1; if (arcSpan >= 270) { joints = 4; @@ -1824,13 +1799,13 @@ var MakerJs; * Expand all paths in a model, then combine the resulting expansions. * * @param modelToExpand Model to expand. - * @param expansion Distance 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, expansion, joints) { + function expandPaths(modelToExpand, distance, joints) { if (joints === void 0) { joints = 0; } - if (expansion <= 0) + if (distance <= 0) return null; var result = { models: { @@ -1842,7 +1817,7 @@ var MakerJs; //TODO: work without origination var originated = model.originate(modelToExpand); model.walkPaths(originated, function (modelContext, pathId, pathContext) { - var expandedPathModel = MakerJs.path.expand(pathContext, expansion, true); + var expandedPathModel = MakerJs.path.expand(pathContext, distance, true); if (expandedPathModel) { var newId = model.getSimilarModelId(result.models['expansions'], pathId); model.originate(expandedPathModel); @@ -1878,6 +1853,31 @@ var MakerJs; return result; } model.expandPaths = expandPaths; + /** + * Outline a model by a specified distance. Useful for accommadating 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. + * @returns Model which surrounds the paths outside of the original model. + */ + function outline(modelToOutline, distance, joints) { + var expanded = expandPaths(modelToOutline, distance, joints); + if (!expanded) + return null; + var loops = model.findLoops(expanded); + if (loops && loops.models) { + var i = 0; + while (loops.models[i]) { + delete loops.models[i + 1]; + delete loops.models[i + 2]; + i += 4; + } + return loops; + } + return null; + } + model.outline = outline; })(model = MakerJs.model || (MakerJs.model = {})); })(MakerJs || (MakerJs = {})); var MakerJs; @@ -1954,18 +1954,96 @@ var MakerJs; var MakerJs; (function (MakerJs) { var measure; - (function (measure_1) { + (function (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 a First angle. + * @param b Second angle. + * @returns true if angles are the same, false if they are not */ - function arcAngle(arc) { - var endAngle = MakerJs.angle.ofArcEnd(arc); - return endAngle - arc.startAngle; + function isAngleEqual(angle1, angle2, accuracy) { + if (accuracy === void 0) { accuracy = .0001; } + var a1 = MakerJs.angle.noRevolutions(angle1); + var a2 = MakerJs.angle.noRevolutions(angle2); + var d = MakerJs.angle.noRevolutions(MakerJs.round(a2 - a1, accuracy)); + return d == 0; } - measure_1.arcAngle = arcAngle; + measure.isAngleEqual = isAngleEqual; + /** + * @private + */ + var pathAreEqualMap = {}; + pathAreEqualMap[MakerJs.pathType.Line] = function (line1, line2, withinPointDistance) { + return (isPointEqual(line1.origin, line2.origin, withinPointDistance) && isPointEqual(line1.end, line2.end, withinPointDistance)) + || (isPointEqual(line1.origin, line2.end, withinPointDistance) && isPointEqual(line1.end, line2.origin, withinPointDistance)); + }; + pathAreEqualMap[MakerJs.pathType.Circle] = function (circle1, circle2, withinPointDistance) { + return isPointEqual(circle1.origin, circle2.origin, withinPointDistance) && circle1.radius == circle2.radius; + }; + pathAreEqualMap[MakerJs.pathType.Arc] = function (arc1, arc2, withinPointDistance) { + return pathAreEqualMap[MakerJs.pathType.Circle](arc1, arc2, withinPointDistance) && isAngleEqual(arc1.startAngle, arc2.startAngle) && isAngleEqual(arc1.endAngle, arc2.endAngle); + }; + /** + * Find out if two paths are equal. + * + * @param a First path. + * @param b Second path. + * @returns true if paths are the same, false if they are not + */ + function isPathEqual(path1, path2, withinPointDistance) { + var result = false; + if (path1.type == path2.type) { + var fn = pathAreEqualMap[path1.type]; + if (fn) { + result = fn(path1, path2, withinPointDistance); + } + } + return result; + } + measure.isPathEqual = isPathEqual; + /** + * 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, b, withinDistance) { + if (!withinDistance) { + return a[0] == b[0] && a[1] == b[1]; + } + else { + var distance = measure.pointDistance(a, b); + return distance <= withinDistance; + } + } + measure.isPointEqual = isPointEqual; + /** + * Check for slope equality. + * + * @param slope1 The ISlope to test. + * @param slope2 The ISlope to check for equality. + * @returns Boolean true if slopes are equal. + */ + function isSlopeEqual(slope1, slope2) { + if (!slope1.hasSlope && !slope2.hasSlope) { + //lines are both vertical, see if x are the same + return MakerJs.round(slope1.line.origin[0] - slope2.line.origin[0]) == 0; + } + if (slope1.hasSlope && slope2.hasSlope && (MakerJs.round(slope1.slope - slope2.slope, .00001) == 0)) { + //lines are parallel, but not vertical, see if y-intercept is the same + return MakerJs.round(slope1.yIntercept - slope2.yIntercept, .00001) == 0; + } + return false; + } + measure.isSlopeEqual = isSlopeEqual; + })(measure = MakerJs.measure || (MakerJs.measure = {})); +})(MakerJs || (MakerJs = {})); +var MakerJs; +(function (MakerJs) { + var measure; + (function (measure_1) { /** * Check for arc being concave or convex towards a given point. * @@ -2033,7 +2111,7 @@ var MakerJs; */ function isBetweenArcAngles(angleInQuestion, arc, exclusive) { var startAngle = MakerJs.angle.noRevolutions(arc.startAngle); - var span = arcAngle(arc); + var span = MakerJs.angle.ofArcSpan(arc); var endAngle = startAngle + span; angleInQuestion = MakerJs.angle.noRevolutions(angleInQuestion); //computed angles will not be negative, but the arc may have specified a negative angle, so check against one revolution forward and backward @@ -2081,24 +2159,27 @@ var MakerJs; } measure_1.isLineOverlapping = isLineOverlapping; /** - * Check for slope equality. - * - * @param slope1 The ISlope to test. - * @param slope2 The ISlope to check for equality. - * @returns Boolean true if slopes are equal. + * Gets the slope of a line. */ - function isSlopeEqual(slope1, slope2) { - if (!slope1.hasSlope && !slope2.hasSlope) { - //lines are both vertical, see if x are the same - return MakerJs.round(slope1.line.origin[0] - slope2.line.origin[0]) == 0; - } - if (slope1.hasSlope && slope2.hasSlope && (MakerJs.round(slope1.slope - slope2.slope, .00001) == 0)) { - //lines are parallel, but not vertical, see if y-intercept is the same - return MakerJs.round(slope1.yIntercept - slope2.yIntercept, .00001) == 0; + function lineSlope(line) { + var dx = line.end[0] - line.origin[0]; + if (MakerJs.round(dx) == 0) { + return { + line: line, + hasSlope: false + }; } - return false; + var dy = line.end[1] - line.origin[1]; + var slope = dy / dx; + var yIntercept = line.origin[1] - slope * line.origin[0]; + return { + line: line, + hasSlope: true, + slope: slope, + yIntercept: yIntercept + }; } - measure_1.isSlopeEqual = isSlopeEqual; + measure_1.lineSlope = lineSlope; /** * Calculates the distance between two points. * @@ -2180,7 +2261,7 @@ var MakerJs; }; map[MakerJs.pathType.Arc] = function (arc) { map[MakerJs.pathType.Circle](arc); //this sets the value var - var pct = arcAngle(arc) / 360; + var pct = MakerJs.angle.ofArcSpan(arc) / 360; value *= pct; }; var fn = map[pathToMeasure.type]; @@ -2326,7 +2407,7 @@ var MakerJs; } }; return Exporter; - })(); + }()); exporter.Exporter = Exporter; })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); })(MakerJs || (MakerJs = {})); @@ -2604,7 +2685,7 @@ var MakerJs; return null; }; map[MakerJs.pathType.Line][MakerJs.pathType.Line] = function (line1, line2, options) { - var intersectionPoint = slopeIntersectionPoint(line1, line2, options); + var intersectionPoint = MakerJs.point.fromSlopeIntersection(line1, line2, options); if (intersectionPoint) { //we have the point of intersection of endless lines, now check to see if the point is between both segemnts if (MakerJs.measure.isBetweenPoints(intersectionPoint, line1, options.excludeTangents) && MakerJs.measure.isBetweenPoints(intersectionPoint, line2, options.excludeTangents)) { @@ -2683,69 +2764,6 @@ var MakerJs; return null; return anglesWithinArc; } - /** - * Gets the slope of a line. - */ - function getSlope(line) { - var dx = line.end[0] - line.origin[0]; - if (MakerJs.round(dx) == 0) { - return { - line: line, - hasSlope: false - }; - } - var dy = line.end[1] - line.origin[1]; - var slope = dy / dx; - var yIntercept = line.origin[1] - slope * line.origin[0]; - return { - line: line, - hasSlope: true, - slope: slope, - yIntercept: yIntercept - }; - } - path.getSlope = getSlope; - /** - * @private - */ - function verticalIntersectionPoint(verticalLine, nonVerticalSlope) { - var x = verticalLine.origin[0]; - var y = nonVerticalSlope.slope * x + nonVerticalSlope.yIntercept; - return [x, y]; - } - /** - * 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, line2, options) { - if (options === void 0) { options = {}; } - var slope1 = getSlope(line1); - var slope2 = getSlope(line2); - if (MakerJs.measure.isSlopeEqual(slope1, slope2)) { - //check for overlap - options.out_AreOverlapped = MakerJs.measure.isLineOverlapping(line1, line2, options.excludeTangents); - return null; - } - var pointOfIntersection; - if (!slope1.hasSlope) { - pointOfIntersection = verticalIntersectionPoint(line1, slope2); - } - else if (!slope2.hasSlope) { - pointOfIntersection = verticalIntersectionPoint(line2, slope1); - } - else { - // find intersection by line equation - var x = (slope2.yIntercept - slope1.yIntercept) / (slope1.slope - slope2.slope); - var y = slope1.slope * x + slope1.yIntercept; - pointOfIntersection = [x, y]; - } - return pointOfIntersection; - } - path.slopeIntersectionPoint = slopeIntersectionPoint; /** * @private */ @@ -2803,7 +2821,7 @@ var MakerJs; */ function circleToCircle(circle1, circle2, options) { //see if circles are the same - if (circle1.radius == circle2.radius && MakerJs.point.areEqual(circle1.origin, circle2.origin, .0001)) { + if (circle1.radius == circle2.radius && MakerJs.measure.isPointEqual(circle1.origin, circle2.origin, .0001)) { options.out_AreOverlapped = true; return null; } @@ -2903,7 +2921,7 @@ var MakerJs; }; } function check(i1, i2) { - if (MakerJs.point.areEqual(path1Properties[i1].point, path2Properties[i2].point, .0001)) { + if (MakerJs.measure.isPointEqual(path1Properties[i1].point, path2Properties[i2].point, .0001)) { result = [ makeMatch(path1, path1Properties, i1), makeMatch(path2, path2Properties, i2) @@ -2927,7 +2945,7 @@ var MakerJs; return false; } properties[i].shardPoint = circleIntersection.intersectionPoints[0]; - if (MakerJs.point.areEqual(properties[i].point, circleIntersection.intersectionPoints[0], .0001)) { + if (MakerJs.measure.isPointEqual(properties[i].point, circleIntersection.intersectionPoints[0], .0001)) { if (circleIntersection.intersectionPoints.length > 1) { properties[i].shardPoint = circleIntersection.intersectionPoints[1]; } @@ -3004,7 +3022,7 @@ var MakerJs; path.rotate(guideLine, lineAngle, [0, 0]); path.moveRelative(guideLine, filletCenter); //get the intersection point of the slopes of the context line and the perpendicular line. This is where the fillet meets the line. - var intersectionPoint = path.slopeIntersectionPoint(line, guideLine); + var intersectionPoint = MakerJs.point.fromSlopeIntersection(line, guideLine); if (intersectionPoint) { result = { filletAngle: MakerJs.angle.ofPointInDegrees(filletCenter, intersectionPoint), @@ -3175,7 +3193,7 @@ var MakerJs; if (MakerJs.round(results[0].filletAngle - results[1].filletAngle) == 0) return null; var filletArc = new MakerJs.paths.Arc(center, filletRadius, results[0].filletAngle, results[1].filletAngle); - var filletSpan = MakerJs.measure.arcAngle(filletArc); + var filletSpan = MakerJs.angle.ofArcSpan(filletArc); //the algorithm is only valid for fillet less than 180 degrees if (filletSpan == 180) { return null; @@ -3488,7 +3506,7 @@ var MakerJs; return found; }; return DeadEndFinder; - })(); + }()); /** * Remove paths from a model which have endpoints that do not connect to other paths. * @@ -3605,7 +3623,7 @@ var MakerJs; } }; return XmlTag; - })(); + }()); exporter.XmlTag = XmlTag; })(exporter = MakerJs.exporter || (MakerJs.exporter = {})); })(MakerJs || (MakerJs = {})); @@ -3947,7 +3965,7 @@ var MakerJs; } map[MakerJs.pathType.Arc] = function (id, arc, origin, layer) { var arcPoints = MakerJs.point.fromArc(arc); - if (MakerJs.point.areEqual(arcPoints[0], arcPoints[1])) { + if (MakerJs.measure.isPointEqual(arcPoints[0], arcPoints[1])) { circleInPaths(id, arc.origin, arc.radius, layer); } else { @@ -4072,7 +4090,7 @@ var MakerJs; } } return ConnectTheDots; - })(); + }()); models.ConnectTheDots = ConnectTheDots; ConnectTheDots.metaParameters = [ { title: "closed", type: "bool", value: true }, @@ -4112,7 +4130,7 @@ var MakerJs; return points; }; return Polygon; - })(); + }()); models.Polygon = Polygon; Polygon.metaParameters = [ { title: "number of sides", type: "range", min: 3, max: 24, value: 6 }, @@ -4135,7 +4153,7 @@ var MakerJs; } } return BoltCircle; - })(); + }()); models.BoltCircle = BoltCircle; BoltCircle.metaParameters = [ { title: "bolt circle radius", type: "range", min: 1, max: 100, value: 50 }, @@ -4163,7 +4181,7 @@ var MakerJs; } } return BoltRectangle; - })(); + }()); models.BoltRectangle = BoltRectangle; BoltRectangle.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 100 }, @@ -4202,7 +4220,7 @@ var MakerJs; } } return Dome; - })(); + }()); models.Dome = Dome; Dome.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4238,7 +4256,7 @@ var MakerJs; } } return RoundRectangle; - })(); + }()); models.RoundRectangle = RoundRectangle; RoundRectangle.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4257,7 +4275,7 @@ var MakerJs; this.paths = new models.RoundRectangle(width, height, Math.min(height / 2, width / 2)).paths; } return Oval; - })(); + }()); models.Oval = Oval; Oval.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4320,7 +4338,7 @@ var MakerJs; } } return OvalArc; - })(); + }()); models.OvalArc = OvalArc; OvalArc.metaParameters = [ { title: "start angle", type: "range", min: -360, max: 360, step: 1, value: 180 }, @@ -4341,7 +4359,7 @@ var MakerJs; this.paths = new models.ConnectTheDots(true, [[0, 0], [width, 0], [width, height], [0, height]]).paths; } return Rectangle; - })(); + }()); models.Rectangle = Rectangle; Rectangle.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4365,7 +4383,7 @@ var MakerJs; } } return Ring; - })(); + }()); models.Ring = Ring; Ring.metaParameters = [ { title: "outer radius", type: "range", min: 0, max: 100, step: 1, value: 50 }, @@ -4406,7 +4424,7 @@ var MakerJs; this.paths['curve_end'] = MakerJs.path.moveRelative(MakerJs.path.mirror(curve, true, true), [width, height]); } return SCurve; - })(); + }()); models.SCurve = SCurve; SCurve.metaParameters = [ { title: "width", type: "range", min: 1, max: 100, value: 50 }, @@ -4437,7 +4455,7 @@ var MakerJs; this.origin = origin; } return Slot; - })(); + }()); models.Slot = Slot; Slot.metaParameters = [ { @@ -4468,7 +4486,7 @@ var MakerJs; this.paths = new models.Rectangle(side, side).paths; } return Square; - })(); + }()); models.Square = Square; Square.metaParameters = [ { title: "side", type: "range", min: 1, max: 100, value: 100 } @@ -4506,7 +4524,7 @@ var MakerJs; return 0; }; return Star; - })(); + }()); models.Star = Star; Star.metaParameters = [ { title: "number of sides", type: "range", min: 3, max: 24, value: 8 }, diff --git a/target/ts/makerjs.d.ts b/target/ts/makerjs.d.ts index b878b8897..5ccb91644 100644 --- a/target/ts/makerjs.d.ts +++ b/target/ts/makerjs.d.ts @@ -2,6 +2,20 @@ // Project: https://github.com/Microsoft/maker.js // Definitions by: Dan Marshall // Definitions: https://github.com/borisyankov/DefinitelyTyped +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ /** * Root module for Maker.js. * @@ -396,6 +410,14 @@ declare namespace MakerJs { * Test to see if an object implements the required properties of a model. */ function isModel(item: any): boolean; + /** + * @private + */ + interface IPathInside { + path: IPath; + isInside?: boolean; + uniqueForeignIntersectionPoints: IPoint[]; + } /** * Reference to a path id within a model. */ @@ -469,14 +491,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 * @@ -513,6 +527,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. * @@ -556,23 +577,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. * @@ -625,6 +629,15 @@ declare namespace MakerJs.point { * @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[]; + /** + * 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 fromSlopeIntersection(line1: IPathLine, line2: IPathLine, options?: IPathIntersectionOptions): IPoint; /** * Get the middle point of a path. * @@ -692,14 +705,6 @@ declare namespace MakerJs.point { function zero(): IPoint; } declare namespace MakerJs.path { - /** - * Find out if two paths are equal. - * - * @param a First path. - * @param b Second path. - * @returns true if paths are the same, false if they are not - */ - function areEqual(path1: IPath, path2: IPath, withinPointDistance?: number): boolean; /** * Create a clone of a path, mirrored on either or both x and y axes. * @@ -1050,11 +1055,20 @@ declare namespace MakerJs.model { * Expand all paths in a model, then combine the resulting expansions. * * @param modelToExpand Model to expand. - * @param expansion Distance 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, expansion: number, joints?: number): IModel; + function expandPaths(modelToExpand: IModel, distance: number, joints?: number): IModel; + /** + * Outline a model by a specified distance. Useful for accommadating 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. + * @returns Model which surrounds the paths outside of the original model. + */ + function outline(modelToOutline: IModel, distance: number, joints?: number): IModel; } declare namespace MakerJs.units { /** @@ -1068,12 +1082,39 @@ 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 a First angle. + * @param b Second angle. + * @returns true if angles are the same, false if they are not + */ + function isAngleEqual(angle1: number, angle2: number, accuracy?: number): boolean; + /** + * Find out if two paths are equal. + * + * @param a First path. + * @param b Second path. + * @returns true if paths are the same, false if they are not + */ + function isPathEqual(path1: IPath, path2: IPath, withinPointDistance?: number): 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 slope1 The ISlope to test. + * @param slope2 The ISlope to check for equality. + * @returns Boolean true if slopes are equal. */ - function arcAngle(arc: IPathArc): number; + function isSlopeEqual(slope1: ISlope, slope2: ISlope): boolean; +} +declare namespace MakerJs.measure { /** * Check for arc being concave or convex towards a given point. * @@ -1129,13 +1170,9 @@ declare namespace MakerJs.measure { */ function isLineOverlapping(line1: IPathLine, line2: IPathLine, excludeTangents: boolean): boolean; /** - * Check for slope equality. - * - * @param slope1 The ISlope to test. - * @param slope2 The ISlope to check for equality. - * @returns Boolean true if slopes are equal. + * Gets the slope of a line. */ - function isSlopeEqual(slope1: ISlope, slope2: ISlope): boolean; + function lineSlope(line: IPathLine): ISlope; /** * Calculates the distance between two points. * @@ -1261,19 +1298,6 @@ 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; - /** - * Gets the slope of a line. - */ - function getSlope(line: IPathLine): ISlope; - /** - * 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 { /**