diff --git a/index.ts b/index.ts index 033319fa080..111f8b4d36b 100644 --- a/index.ts +++ b/index.ts @@ -1,11 +1,11 @@ -import pattern from './lib/pattern' -import point from './lib/point' +import { Pattern } from './lib/pattern' +import { Point } from './lib/point' import bezier from 'bezier-js' var Freesewing = { version: '0.0.1', - pattern, - point, + pattern: Pattern, + point: Point, bezier } diff --git a/lib/option.ts b/lib/option.ts index 9c4c18d7d0b..0ce3517347a 100644 --- a/lib/option.ts +++ b/lib/option.ts @@ -1,5 +1,5 @@ import { PatternOption } from './types' -export default class Option { +export class Option { id: string; config: PatternOption; val: number; diff --git a/lib/part.ts b/lib/part.ts index bf822a52494..ebf99edf360 100644 --- a/lib/part.ts +++ b/lib/part.ts @@ -1,20 +1,24 @@ -import Point from './point' +import { Point } from './point' -export default class Part { - id: string | number; +export class Part { + id: string; + render: boolean; points: { [index: string]: Point; } [propName: string]: any; - constructor(id: string | number) { + constructor(id: string) { this.id = id; + this.render = (id.substr(0,1) === '_') ? false : true; this.points = {}; return this; } - newPoint(id: string | number, x: number, y: number) { - this.points[id] = new Point(x, y); - } + +// purge = { +// points = function(prefix: string): void {} +// paths = function(prefix: string): void {} +// } } diff --git a/lib/pattern.ts b/lib/pattern.ts index e774f8ae79f..9611d68bbee 100644 --- a/lib/pattern.ts +++ b/lib/pattern.ts @@ -1,8 +1,8 @@ import { PatternConfig, PatternOption } from './types' -import Part from './part' -import Option from './option' +import { Part } from './part' +import { Option } from './option' -export default class Pattern { +export class Pattern { config: PatternConfig; parts: {[propName: string]: Part}; options: {[propName: string]: number}; diff --git a/lib/point.ts b/lib/point.ts index f885e7e5966..7ed8d6683c0 100644 --- a/lib/point.ts +++ b/lib/point.ts @@ -1,24 +1,25 @@ +import { round, rad2deg, deg2rad } from './utils'; + const PRECISION = 2; -const RAD = 57.29577951308232; +// A poor man's rad2deg() - -export default class Point { +export class Point { x: number; y: number; constructor(x: number, y: number) { - this.x = +x.toFixed(PRECISION); - this.y = +y.toFixed(PRECISION); + this.x = round(x); + this.y = round(y); return this; } /** Returns the distance between this point and that point */ - distance(that: Point): number { + dist(that: Point): number { let dx = this.x - that.x; let dy = this.y - that.y; - return Math.sqrt(Math.pow(dx, 2) + Math.pow(dy,2)); + return round(Math.sqrt(Math.pow(dx, 2) + Math.pow(dy,2))); } /** Returns slope of a line made by this point and that point */ @@ -26,37 +27,76 @@ export default class Point { return (that.y - this.y) / (that.x - this.x); } + /** Returns the x-delta between this point and that point */ + dx(that: Point): number { + return that.x - this.x; + } + + /** Returns the y-delta between this point and that point */ + dy(that: Point): number { + return that.y - this.y; + } + /** Returns the angle between this point and that point */ angle(that: Point): number { - let dx = this.x - that.x; - let dy = this.y - that.y; - let rad = Math.atan2(-1 * dy, dy); + let rad = Math.atan2(-1 * this.dy(that), this.dx(that)); while (rad < 0) rad += 2 * Math.PI; - // A poor man's rad2deg() - return rad * RAD; + return rad2deg(rad); } - /** Rotate this point degrees around that point */ - rotate(degrees: number, that: Point) { - let radius = this.distance(that); + /** Rotate this point deg around that point */ + rotate(deg: number, that: Point): Point { + let radius = this.dist(that); let angle = this.angle(that); - let x = that.x + radius * Math.cos((angle + degrees) / RAD) * -1; - let y = that.y + radius * Math.sin((angle + degrees) / RAD); + let x = that.x + radius * Math.cos(deg2rad(angle + deg)) * -1; + let y = that.y + radius * Math.sin(deg2rad(angle + deg)); return new Point(x, y); } - /** Shifts this point distance in the degrees direction */ - shift(degrees: number, distance: number): Point { - let p = this.copy(); - p.x += distance; - - return p.rotate(degrees, this); - } - /** returns an identical copy of this point */ copy(): Point { return new Point(this.x, this.y); } + + /** checks whether this point is equal to that point */ + equals(that: Point): boolean { + return (this.x === that.x && this.y === that.y) ? true : false; + } + + /** Mirrors this point around X value of that point */ + flipX(that: Point): Point + { + return new Point(that.x + this.dx(that), that.y); + } + + /** Mirrors this point around Y value of that point */ + flipY(that: Point): Point + { + return new Point(that.x, that.y + this.dy(that)); + } + + /** Shifts this point distance in the deg direction */ + shift(deg: number, distance: number): Point { + let p = this.copy(); + p.x += distance; + + return p.rotate(deg, this); + } + + /** Shifts this point distance in the direction of that point */ + shiftTowards(that: Point, distance: number): Point { + return this.shift(this.angle(that), distance); + } + + /** Shifts this point fraction of the distance towards that point */ + shiftFractionTowards(that: Point, fraction: number): Point { + return this.shiftTowards(that, this.dist(that) * fraction); + } + + /** Shifts this point distance beyond that point */ + shiftOutwards(that: Point, distance: number): Point { + return this.shiftTowards(that, this.dist(that) + distance); + } } diff --git a/lib/utils.ts b/lib/utils.ts new file mode 100644 index 00000000000..adb0b5f9222 --- /dev/null +++ b/lib/utils.ts @@ -0,0 +1,15 @@ +/** Rounds a value to PRECISION */ +export function round(value: number): number { + return Math.round(value * 1e2) / 1e2; +} + +/** Radians to degrees */ +export function rad2deg(radians: number): number { + return radians * 57.29577951308232; +} + +/** Degrees to radians */ +export function deg2rad(degrees: number): number { + return degrees / 57.29577951308232; +} + diff --git a/package-lock.json b/package-lock.json index 9f7dca7fc5c..78ec702a0be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,18 @@ "integrity": "sha512-N+/UZFYVp9ka8Xby7hZSHsXqKm6FJIXK/+BRH0BpEfb18aVTtRBPzGIQfDRexAZPYgtWupqP6afapmYYKjvWoQ==", "dev": true }, + "@types/chai": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.4.tgz", + "integrity": "sha512-h6+VEw2Vr3ORiFCyyJmcho2zALnUq9cvdB/IO8Xs9itrJVCenC7o26A6+m7D0ihTTr65eS259H5/Ghl/VjYs6g==", + "dev": true + }, + "@types/mocha": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.4.tgz", + "integrity": "sha512-XMHApnKWI0jvXU5gLcSTsRjJBpSzP0BG+2oGv98JFyS4a5R0tRy0oshHBRndb3BuHb9AwDKaUL8Ja7GfUvsG4g==", + "dev": true + }, "@types/node": { "version": "10.5.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.2.tgz", @@ -65,6 +77,18 @@ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, "async-each": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", @@ -132,6 +156,38 @@ "repeat-element": "1.1.2" } }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", + "dev": true + }, + "chai": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "dev": true, + "requires": { + "assertion-error": "1.1.0", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.8" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, "chokidar": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", @@ -153,6 +209,12 @@ "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.0.tgz", "integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw==" }, + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -191,6 +253,15 @@ "ms": "0.7.1" } }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -201,6 +272,12 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, "duplexer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", @@ -221,6 +298,12 @@ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -324,6 +407,12 @@ "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, "fsevents": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", @@ -786,6 +875,26 @@ } } }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, "glob-base": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", @@ -808,6 +917,24 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, "http-auth": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/http-auth/-/http-auth-3.1.3.tgz", @@ -842,6 +969,16 @@ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=" }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", @@ -955,6 +1092,12 @@ "serve-index": "1.9.1" } }, + "make-error": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", + "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", + "dev": true + }, "map-stream": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", @@ -1011,6 +1154,57 @@ "brace-expansion": "1.1.11" } }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, "morgan": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.0.tgz", @@ -1089,6 +1283,15 @@ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, "opn": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", @@ -1118,6 +1321,12 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, "pause-stream": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", @@ -1300,6 +1509,22 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz", + "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==", + "dev": true, + "requires": { + "buffer-from": "1.1.0", + "source-map": "0.6.1" + } + }, "split": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", @@ -1329,11 +1554,50 @@ "safe-buffer": "5.1.2" } }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, + "ts-node": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.0.tgz", + "integrity": "sha512-klJsfswHP0FuOLsvBZ/zzCfUvakOSSxds78mVeK7I+qP76YWtxf16hEZsp3U+b0kIo82R5UatGFeblYMqabb2Q==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "buffer-from": "1.1.0", + "diff": "3.5.0", + "make-error": "1.3.4", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "source-map-support": "0.5.6", + "yn": "2.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, "typescript": { "version": "2.9.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", @@ -1383,6 +1647,18 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true } } } diff --git a/package.json b/package.json index 9bd1ab98803..e9af91d5232 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", + "test": "mocha -r ts-node/register tests/*.test.js", "build": "tsc", "build-watch": "tsc -w", "run": "nodemon node dist/index.js", @@ -25,8 +25,13 @@ "bezier-js": "^2.2.13" }, "devDependencies": { - "typescript": "^2.9.2", "@types/bezier-js": "0.0.7", - "@types/node": "^10.5.2" + "@types/chai": "^4.1.4", + "@types/mocha": "^5.2.4", + "@types/node": "^10.5.2", + "chai": "^4.1.2", + "mocha": "^5.2.0", + "ts-node": "^7.0.0", + "typescript": "^2.9.2" } } diff --git a/tests/point.test.js b/tests/point.test.js new file mode 100644 index 00000000000..5bddf92e850 --- /dev/null +++ b/tests/point.test.js @@ -0,0 +1,151 @@ +var expect = require('chai').expect; +var Point = require('../dist/lib/point').Point; + + +it('should return point object', () => { + let result = new Point(2,4); + expect(result).to.be.a('object'); + expect(result.x).to.equal(2); + expect(result.y).to.equal(4); +}); + +it('should limit point precision', () => { + let result = new Point(2.12345,4.98765); + expect(result.x).to.equal(2.12); + expect(result.y).to.equal(4.99); +}); + +it('should return distance', () => { + expect(new Point(2,4).dist(new Point(-123, -32423))).to.equal(32427.24); +}); + +it('should return slope', () => { + let from = new Point(0,0); + expect(from.slope(new Point( 0, -10))).to.equal(-Infinity); + expect(from.slope(new Point( 10, 0))).to.equal(0); + expect(from.slope(new Point( 0, 10))).to.equal(Infinity); + expect(from.slope(new Point(-10, 0))).to.equal(-0); + expect(from.slope(new Point( 10, 10))).to.equal(1); + expect(from.slope(new Point(-10, 5))).to.equal(-0.5); +}); + +it('should return angle', () => { + let from = new Point(0,0); + expect(from.angle(new Point( 10, 0))).to.equal(0); + expect(from.angle(new Point(-20, 0))).to.equal(180); + expect(from.angle(new Point( 0, -10))).to.equal(90); + expect(from.angle(new Point( 0, 10))).to.equal(270); + expect(from.angle(new Point( 10, -10))).to.equal(45); + expect(from.angle(new Point( 10, 10))).to.equal(315); +}); + +it('should copy a point', () => { + let result = new Point(2,4).copy(); + expect(result.x).to.equal(2); + expect(result.y).to.equal(4); +}); + +it('should check points for equality', () => { + let a = new Point(-123,456); + let b = new Point(-123,456); + expect(a).to.deep.equal(b); +}); + +it('should flip point around X value', () => { + let result = new Point(2,4).flipX(new Point(-20, 4)); + expect(result.x).to.equal(-42); + expect(result.y).to.equal(4); +}); + +it('should flip point around Y value', () => { + let result = new Point(2,4).flipY(new Point(2, -14)); + expect(result.x).to.equal(2); + expect(result.y).to.equal(-32); +}); + +it('should shift a point', () => { + let origin = new Point(0,0); + let n = origin.shift(90, 10); + let e = origin.shift(0, 10); + let s = origin.shift(270, 10); + let w = origin.shift(180, 10); + expect(n.x).to.equal(0); + expect(n.y).to.equal(-10); + expect(e.x).to.equal(10); + expect(e.y).to.equal(0); + expect(s.x).to.equal(0); + expect(s.y).to.equal(10); + expect(w.x).to.equal(-10); + expect(w.y).to.equal(0); + let rand = origin.shift(-123, 456); + expect(rand.x).to.equal(-248.36); + expect(rand.y).to.equal(382.43); +}); + +it('should shift a point towards another', () => { + let origin = new Point(0,0); + let n = new Point( 0, -10); + let e = new Point( 10, 0); + let s = new Point( 0, 10); + let w = new Point(-10, 0); + let sn = origin.shiftTowards(n, 123); + let se = origin.shiftTowards(e, 123); + let ss = origin.shiftTowards(s, 123); + let sw = origin.shiftTowards(w, 123); + expect(sn.x).to.equal(0); + expect(sn.y).to.equal(-123); + expect(se.x).to.equal(123); + expect(se.y).to.equal(0); + expect(ss.x).to.equal(0); + expect(ss.y).to.equal(123); + expect(sw.x).to.equal(-123); + expect(sw.y).to.equal(0); + expect(sw.shiftTowards(sn, 100).x).to.equal(-52.29); + expect(ss.shiftTowards(se, 200).y).to.equal(-18.42); +}); + +it('should shift a point a fraction towards another', () => { + let origin = new Point(0,0); + let n = new Point( 0, -10); + let e = new Point( 10, 0); + let s = new Point( 0, 10); + let w = new Point(-10, 0); + let sn = origin.shiftFractionTowards(n, 1.5); + let se = origin.shiftFractionTowards(e, 1.5); + let ss = origin.shiftFractionTowards(s, 0.5); + let sw = origin.shiftFractionTowards(w, 2.5); + expect(sn.x).to.equal(0); + expect(sn.y).to.equal(-15); + expect(se.x).to.equal(15); + expect(se.y).to.equal(0); + expect(ss.x).to.equal(0); + expect(ss.y).to.equal(5); + expect(sw.x).to.equal(-25); + expect(sw.y).to.equal(0); + expect(sw.shiftFractionTowards(sn, 100).x).to.equal(2474.59); + expect(ss.shiftFractionTowards(se, 200).y).to.equal(-994.91); +}); + +it('should shift a point beyond another', () => { + let origin = new Point(0,0); + let n = new Point( 0, -10); + let e = new Point( 10, 0); + let s = new Point( 0, 10); + let w = new Point(-10, 0); + let sn = origin.shiftOutwards(n, 100); + let se = origin.shiftOutwards(e, 100); + let ss = origin.shiftOutwards(s, 100); + let sw = origin.shiftOutwards(w, 100); + expect(sn.x).to.equal(0); + expect(sn.y).to.equal(-110); + expect(se.x).to.equal(110); + expect(se.y).to.equal(0); + expect(ss.x).to.equal(0); + expect(ss.y).to.equal(110); + expect(sw.x).to.equal(-110); + expect(sw.y).to.equal(0); + expect(sw.shiftOutwards(sn, 100).x).to.equal(70.71); + expect(ss.shiftOutwards(se, 200).y).to.equal(-141.42); +}); + +