poly2tri
Version:
A 2D constrained Delaunay triangulation library
276 lines (242 loc) • 6.98 kB
JavaScript
/*
* 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;