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.
StackGenVis/frontend/node_modules/cdt2d/lib/monotone.js

188 lines
4.2 KiB

4 years ago
'use strict'
var bsearch = require('binary-search-bounds')
var orient = require('robust-orientation')[3]
var EVENT_POINT = 0
var EVENT_END = 1
var EVENT_START = 2
module.exports = monotoneTriangulate
//A partial convex hull fragment, made of two unimonotone polygons
function PartialHull(a, b, idx, lowerIds, upperIds) {
this.a = a
this.b = b
this.idx = idx
this.lowerIds = lowerIds
this.upperIds = upperIds
}
//An event in the sweep line procedure
function Event(a, b, type, idx) {
this.a = a
this.b = b
this.type = type
this.idx = idx
}
//This is used to compare events for the sweep line procedure
// Points are:
// 1. sorted lexicographically
// 2. sorted by type (point < end < start)
// 3. segments sorted by winding order
// 4. sorted by index
function compareEvent(a, b) {
var d =
(a.a[0] - b.a[0]) ||
(a.a[1] - b.a[1]) ||
(a.type - b.type)
if(d) { return d }
if(a.type !== EVENT_POINT) {
d = orient(a.a, a.b, b.b)
if(d) { return d }
}
return a.idx - b.idx
}
function testPoint(hull, p) {
return orient(hull.a, hull.b, p)
}
function addPoint(cells, hulls, points, p, idx) {
var lo = bsearch.lt(hulls, p, testPoint)
var hi = bsearch.gt(hulls, p, testPoint)
for(var i=lo; i<hi; ++i) {
var hull = hulls[i]
//Insert p into lower hull
var lowerIds = hull.lowerIds
var m = lowerIds.length
while(m > 1 && orient(
points[lowerIds[m-2]],
points[lowerIds[m-1]],
p) > 0) {
cells.push(
[lowerIds[m-1],
lowerIds[m-2],
idx])
m -= 1
}
lowerIds.length = m
lowerIds.push(idx)
//Insert p into upper hull
var upperIds = hull.upperIds
var m = upperIds.length
while(m > 1 && orient(
points[upperIds[m-2]],
points[upperIds[m-1]],
p) < 0) {
cells.push(
[upperIds[m-2],
upperIds[m-1],
idx])
m -= 1
}
upperIds.length = m
upperIds.push(idx)
}
}
function findSplit(hull, edge) {
var d
if(hull.a[0] < edge.a[0]) {
d = orient(hull.a, hull.b, edge.a)
} else {
d = orient(edge.b, edge.a, hull.a)
}
if(d) { return d }
if(edge.b[0] < hull.b[0]) {
d = orient(hull.a, hull.b, edge.b)
} else {
d = orient(edge.b, edge.a, hull.b)
}
return d || hull.idx - edge.idx
}
function splitHulls(hulls, points, event) {
var splitIdx = bsearch.le(hulls, event, findSplit)
var hull = hulls[splitIdx]
var upperIds = hull.upperIds
var x = upperIds[upperIds.length-1]
hull.upperIds = [x]
hulls.splice(splitIdx+1, 0,
new PartialHull(event.a, event.b, event.idx, [x], upperIds))
}
function mergeHulls(hulls, points, event) {
//Swap pointers for merge search
var tmp = event.a
event.a = event.b
event.b = tmp
var mergeIdx = bsearch.eq(hulls, event, findSplit)
var upper = hulls[mergeIdx]
var lower = hulls[mergeIdx-1]
lower.upperIds = upper.upperIds
hulls.splice(mergeIdx, 1)
}
function monotoneTriangulate(points, edges) {
var numPoints = points.length
var numEdges = edges.length
var events = []
//Create point events
for(var i=0; i<numPoints; ++i) {
events.push(new Event(
points[i],
null,
EVENT_POINT,
i))
}
//Create edge events
for(var i=0; i<numEdges; ++i) {
var e = edges[i]
var a = points[e[0]]
var b = points[e[1]]
if(a[0] < b[0]) {
events.push(
new Event(a, b, EVENT_START, i),
new Event(b, a, EVENT_END, i))
} else if(a[0] > b[0]) {
events.push(
new Event(b, a, EVENT_START, i),
new Event(a, b, EVENT_END, i))
}
}
//Sort events
events.sort(compareEvent)
//Initialize hull
var minX = events[0].a[0] - (1 + Math.abs(events[0].a[0])) * Math.pow(2, -52)
var hull = [ new PartialHull([minX, 1], [minX, 0], -1, [], [], [], []) ]
//Process events in order
var cells = []
for(var i=0, numEvents=events.length; i<numEvents; ++i) {
var event = events[i]
var type = event.type
if(type === EVENT_POINT) {
addPoint(cells, hull, points, event.a, event.idx)
} else if(type === EVENT_START) {
splitHulls(hull, points, event)
} else {
mergeHulls(hull, points, event)
}
}
//Return triangulation
return cells
}