"use strict" var ch = require("incremental-convex-hull") var uniq = require("uniq") module.exports = triangulate function LiftedPoint(p, i) { this.point = p this.index = i } function compareLifted(a, b) { var ap = a.point var bp = b.point var d = ap.length for(var i=0; i<d; ++i) { var s = bp[i] - ap[i] if(s) { return s } } return 0 } function triangulate1D(n, points, includePointAtInfinity) { if(n === 1) { if(includePointAtInfinity) { return [ [-1, 0] ] } else { return [] } } var lifted = points.map(function(p, i) { return [ p[0], i ] }) lifted.sort(function(a,b) { return a[0] - b[0] }) var cells = new Array(n - 1) for(var i=1; i<n; ++i) { var a = lifted[i-1] var b = lifted[i] cells[i-1] = [ a[1], b[1] ] } if(includePointAtInfinity) { cells.push( [ -1, cells[0][1], ], [ cells[n-1][1], -1 ]) } return cells } function triangulate(points, includePointAtInfinity) { var n = points.length if(n === 0) { return [] } var d = points[0].length if(d < 1) { return [] } //Special case: For 1D we can just sort the points if(d === 1) { return triangulate1D(n, points, includePointAtInfinity) } //Lift points, sort var lifted = new Array(n) var upper = 1.0 for(var i=0; i<n; ++i) { var p = points[i] var x = new Array(d+1) var l = 0.0 for(var j=0; j<d; ++j) { var v = p[j] x[j] = v l += v * v } x[d] = l lifted[i] = new LiftedPoint(x, i) upper = Math.max(l, upper) } uniq(lifted, compareLifted) //Double points n = lifted.length //Create new list of points var dpoints = new Array(n + d + 1) var dindex = new Array(n + d + 1) //Add steiner points at top var u = (d+1) * (d+1) * upper var y = new Array(d+1) for(var i=0; i<=d; ++i) { y[i] = 0.0 } y[d] = u dpoints[0] = y.slice() dindex[0] = -1 for(var i=0; i<=d; ++i) { var x = y.slice() x[i] = 1 dpoints[i+1] = x dindex[i+1] = -1 } //Copy rest of the points over for(var i=0; i<n; ++i) { var h = lifted[i] dpoints[i + d + 1] = h.point dindex[i + d + 1] = h.index } //Construct convex hull var hull = ch(dpoints, false) if(includePointAtInfinity) { hull = hull.filter(function(cell) { var count = 0 for(var j=0; j<=d; ++j) { var v = dindex[cell[j]] if(v < 0) { if(++count >= 2) { return false } } cell[j] = v } return true }) } else { hull = hull.filter(function(cell) { for(var i=0; i<=d; ++i) { var v = dindex[cell[i]] if(v < 0) { return false } cell[i] = v } return true }) } if(d & 1) { for(var i=0; i<hull.length; ++i) { var h = hull[i] var x = h[0] h[0] = h[1] h[1] = x } } return hull }