StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
2.9 KiB
159 lines
2.9 KiB
"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
|
|
} |