UNPKG

poly2tri

Version:

A 2D constrained Delaunay triangulation library

276 lines (242 loc) 6.98 kB
/* * Poly2Tri Copyright (c) 2009-2014, Poly2Tri Contributors * http://code.google.com/p/poly2tri/ * * poly2tri.js (JavaScript port) (c) 2009-2014, Poly2Tri Contributors * https://github.com/r3mi/poly2tri.js * * All rights reserved. * * Distributed under the 3-clause BSD License, see LICENSE.txt */ "use strict"; /* * Note * ==== * the structure of this JavaScript version of poly2tri intentionally follows * as closely as possible the structure of the reference C++ version, to make it * easier to keep the 2 versions in sync. */ var xy = require('./xy'); // ------------------------------------------------------------------------Point /** * Construct a point * @example * var point = new poly2tri.Point(150, 150); * @public * @constructor * @struct * @param {number=} x coordinate (0 if undefined) * @param {number=} y coordinate (0 if undefined) */ var Point = function(x, y) { /** * @type {number} * @expose */ this.x = +x || 0; /** * @type {number} * @expose */ this.y = +y || 0; // All extra fields added to Point are prefixed with _p2t_ // to avoid collisions if custom Point class is used. /** * The edges this point constitutes an upper ending point * @private * @type {Array.<Edge>} */ this._p2t_edge_list = null; }; /** * For pretty printing * @example * "p=" + new poly2tri.Point(5,42) * // → "p=(5;42)" * @returns {string} <code>"(x;y)"</code> */ Point.prototype.toString = function() { return xy.toStringBase(this); }; /** * JSON output, only coordinates * @example * JSON.stringify(new poly2tri.Point(1,2)) * // → '{"x":1,"y":2}' */ Point.prototype.toJSON = function() { return { x: this.x, y: this.y }; }; /** * Creates a copy of this Point object. * @return {Point} new cloned point */ Point.prototype.clone = function() { return new Point(this.x, this.y); }; /** * Set this Point instance to the origo. <code>(0; 0)</code> * @return {Point} this (for chaining) */ Point.prototype.set_zero = function() { this.x = 0.0; this.y = 0.0; return this; // for chaining }; /** * Set the coordinates of this instance. * @param {number} x coordinate * @param {number} y coordinate * @return {Point} this (for chaining) */ Point.prototype.set = function(x, y) { this.x = +x || 0; this.y = +y || 0; return this; // for chaining }; /** * Negate this Point instance. (component-wise) * @return {Point} this (for chaining) */ Point.prototype.negate = function() { this.x = -this.x; this.y = -this.y; return this; // for chaining }; /** * Add another Point object to this instance. (component-wise) * @param {!Point} n - Point object. * @return {Point} this (for chaining) */ Point.prototype.add = function(n) { this.x += n.x; this.y += n.y; return this; // for chaining }; /** * Subtract this Point instance with another point given. (component-wise) * @param {!Point} n - Point object. * @return {Point} this (for chaining) */ Point.prototype.sub = function(n) { this.x -= n.x; this.y -= n.y; return this; // for chaining }; /** * Multiply this Point instance by a scalar. (component-wise) * @param {number} s scalar. * @return {Point} this (for chaining) */ Point.prototype.mul = function(s) { this.x *= s; this.y *= s; return this; // for chaining }; /** * Return the distance of this Point instance from the origo. * @return {number} distance */ Point.prototype.length = function() { return Math.sqrt(this.x * this.x + this.y * this.y); }; /** * Normalize this Point instance (as a vector). * @return {number} The original distance of this instance from the origo. */ Point.prototype.normalize = function() { var len = this.length(); this.x /= len; this.y /= len; return len; }; /** * Test this Point object with another for equality. * @param {!XY} p - any "Point like" object with {x,y} * @return {boolean} <code>true</code> if same x and y coordinates, <code>false</code> otherwise. */ Point.prototype.equals = function(p) { return this.x === p.x && this.y === p.y; }; // -----------------------------------------------------Point ("static" methods) /** * Negate a point component-wise and return the result as a new Point object. * @param {!XY} p - any "Point like" object with {x,y} * @return {Point} the resulting Point object. */ Point.negate = function(p) { return new Point(-p.x, -p.y); }; /** * Add two points component-wise and return the result as a new Point object. * @param {!XY} a - any "Point like" object with {x,y} * @param {!XY} b - any "Point like" object with {x,y} * @return {Point} the resulting Point object. */ Point.add = function(a, b) { return new Point(a.x + b.x, a.y + b.y); }; /** * Subtract two points component-wise and return the result as a new Point object. * @param {!XY} a - any "Point like" object with {x,y} * @param {!XY} b - any "Point like" object with {x,y} * @return {Point} the resulting Point object. */ Point.sub = function(a, b) { return new Point(a.x - b.x, a.y - b.y); }; /** * Multiply a point by a scalar and return the result as a new Point object. * @param {number} s - the scalar * @param {!XY} p - any "Point like" object with {x,y} * @return {Point} the resulting Point object. */ Point.mul = function(s, p) { return new Point(s * p.x, s * p.y); }; /** * Perform the cross product on either two points (this produces a scalar) * or a point and a scalar (this produces a point). * This function requires two parameters, either may be a Point object or a * number. * @param {XY|number} a - Point object or scalar. * @param {XY|number} b - Point object or scalar. * @return {Point|number} a Point object or a number, depending on the parameters. */ Point.cross = function(a, b) { if (typeof(a) === 'number') { if (typeof(b) === 'number') { return a * b; } else { return new Point(-a * b.y, a * b.x); } } else { if (typeof(b) === 'number') { return new Point(b * a.y, -b * a.x); } else { return a.x * b.y - a.y * b.x; } } }; // -----------------------------------------------------------------"Point-Like" /* * The following functions operate on "Point" or any "Point like" object * with {x,y} (duck typing). */ Point.toString = xy.toString; Point.compare = xy.compare; Point.cmp = xy.compare; // backward compatibility Point.equals = xy.equals; /** * Peform the dot product on two vectors. * @public * @param {!XY} a - any "Point like" object with {x,y} * @param {!XY} b - any "Point like" object with {x,y} * @return {number} The dot product */ Point.dot = function(a, b) { return a.x * b.x + a.y * b.y; }; // ---------------------------------------------------------Exports (public API) module.exports = Point;