function maxFlow(num_vertices, source, sink, edges, capacities, flow, dual) { num_vertices |= 0 source |= 0 sink |= 0 //Compute dual of graph if not specified if(!dual) { top.normalize(edges, capacities) dual = top.dual(edges) } //Allocate new flow field if necessary if(!flow) { flow = new Float64Array(edges.length) } else { for(var i=0; i<edges.length; ++i) { flow[i] = 0.0 } } //Initialization initFlow(num_vertices) initFIFO(num_vertices) dischargeSource(num_vertices, source, sink, edges, capacities, flow, dual) globalRelabel(num_vertices, source, sink, edges, capacities, flow, dual) //Solve using Goldberg&Tarjan's two-phase algorithm pushRelabel(num_vertices, source, sink, edges, capacities, flow, dual) removeExcess(num_vertices, source, sink, edges, capacities, flow, dual) return flow }
function Layout(cells, dimension, options) { dimension = dimension || 2 options = options || {} this.lo = options.lo || numeric.rep([dimension], -Infinity) this.hi = options.hi || numeric.rep([dimension], Infinity) var num_vertices = sc.countVertices(cells) this.cells = sc.unique(sc.normalize(sc.explode(cells))) this.stars = sc.dual(cells, num_vertices) this.temperature = 1.0 for(var i=0; i<this.stars.length; ++i) { var s = this.stars[i] var n = [] for(var j=0; j<s.length; ++j) { n = n.concat(cells[s[j]]) } n.sort() this.stars[i] = uniq(n) } this.dimension = dimension|0 this.numVertices = num_vertices|0 this.radius = options.radius || 1.0 this.positions = numeric.rep([num_vertices, dimension], 0.0) this.velocities = numeric.rep([num_vertices, dimension], 0.0) this.forces = numeric.rep([num_vertices, dimension], 0.0) this.grid = numeric.rep([num_vertices<<dimension, dimension+1], 0) for(var i=0; i<num_vertices; ++i) { if(options.lo && options.hi) { for(var j=0; j<dimension; ++j) { this.positions[i][j] = (Math.random() * (this.hi[j]-this.lo[j])) + this.lo[j] } } else { for(var j=0; j<dimension; ++j) { this.positions[i][j] = (Math.random() - 0.5) * num_vertices * this.radius } } } }
function minCut(num_vertices, source, sink, edges, capacities, cut, dual) { num_vertices |= 0 source |= 0 sink |= 0 //Compute dual of graph if not specified if(!dual) { top.normalize(edges, capacities) dual = top.dual(edges) } //Allocate new flow field if necessary var flow = FLOW_BUFFER if(FLOW_BUFFER.length < edges.length) { FLOW_BUFFER = new Float64Array(edges.length) flow = FLOW_BUFFER } else { for(var i=0; i<edges.length; ++i) { flow[i] = 0.0 } } //Initialization initFlow(num_vertices) initFIFO(num_vertices) dischargeSource(num_vertices, source, sink, edges, capacities, flow, dual) globalRelabel(num_vertices, source, sink, edges, capacities, flow, dual) //Only do push-relabel phase, can compute cut from saturated preflow pushRelabel(num_vertices, source, sink, edges, capacities, flow, dual) if(!cut) { cut = new Uint8Array(num_vertices) } for(var i=0; i<num_vertices; ++i) { cut[i] = LABEL[i] > GAP } return cut }
var bunny = require('bunny') //require('conway-hart')('I') var sc = require('simplicial-complex') var faceNormals = require('normals').faceNormals var positions = bunny.positions var triangles = sc.normalize(bunny.cells) var normals = faceNormals(triangles, positions) var lo = [Infinity,Infinity,Infinity] var hi = [-Infinity,-Infinity,-Infinity] for(var i=0; i<positions.length; ++i) { var p = positions[i] for(var j=0; j<3; ++j) { lo[j] = Math.min(lo[j], p[j]) hi[j] = Math.max(hi[j], p[j]) } } var s = 0.5 / Math.max(hi[0]-lo[0],hi[1]-lo[1],hi[2]-lo[2]) var o = [0.5*(lo[0]+hi[0]), 0.5*(lo[1]+hi[1]), 0.5*(lo[2]+hi[2])] var npositions = positions.map(function(p) { return [s*(p[0]-o[0]),s*(p[1]-o[1]),s*(p[2]-o[2])] }) var mesh = [] for(var i=0; i<triangles.length; ++i) { var t = triangles[i] var n = normals[i] for(var j=0; j<3; ++j) {