jkstra
Version:
Small JavaScript graph routing library
129 lines (112 loc) • 3.13 kB
JavaScript
import { IN, OUT } from './constants.js';
import { propsMatch } from './utils.js';
class Graph {
constructor() {
this.vertices = [];
this.edges = [];
}
get vertexCount() {
return this.vertices.length;
}
get edgeCount() {
return this.edges.length;
}
addVertex(data) {
const vertex = {
_in: [],
_out: [],
data: data
};
this.vertices.push(vertex);
return vertex;
}
addEdge(from, to, data) {
const edge = {
from: from,
to: to,
data: data || {}
};
from._out.push(edge);
to._in.push(edge);
this.edges.push(edge);
return edge;
}
/**
Shortcut to add an edge and its reverse,
sharing the same data.
*/
addEdgePair(a, b, data) {
return [
this.addEdge(a, b, data),
this.addEdge(b, a, data)
];
}
removeEdge(edge) {
const index = this.edges.indexOf(edge);
if(index !== -1) {
// remove from extremity this.vertices first
edge.from._out.splice(edge.from._out.indexOf(edge), 1);
edge.to._in.splice(edge.to._in.indexOf(edge), 1);
this.edges.splice(index, 1);
}
}
removeVertex(vertex) {
const index = this.vertices.indexOf(vertex);
if(index !== -1) {
// remove all incident this.edges first
const edgesToRemove = vertex._in.concat(vertex._out);
for(let i = 0; i < edgesToRemove.length; i++) {
this.removeEdge(edgesToRemove[i]);
}
this.vertices.splice(index, 1);
}
}
outEdges(vertex, filter) {
return this.incidentEdges(vertex, OUT, filter);
}
inEdges(vertex, filter) {
return this.incidentEdges(vertex, IN, filter);
}
/**
Returns all this.edges incident to a vertex, in one direction (outgoing or incoming),
optionnaly filtered by a given function.
*/
incidentEdges(vertex, direction, filter) {
if (!filter) {
return direction ? vertex._out : vertex._in;
}
const edges = direction ? vertex._out : vertex._in;
return edges.filter(filter);
}
vertex(props) {
const vertices = this.vertices;
for (let i = 0, l = vertices.length; i < l; i++) {
if (propsMatch(vertices[i].data, props)) {
return vertices[i];
}
}
return null;
}
edge(props) {
const edges = this.edges;
for (let i = 0, l = edges.length; i < l; i++) {
if (propsMatch(edges[i].data, props)) {
return edges[i];
}
}
return null;
}
/**
Perform an action on each vertex of the graph
*/
forEachVertex(action) {
this.vertices.forEach(v => action(v));
}
/**
Perform an action on each edge of the graph
*/
forEachEdge(action) {
this.edges.forEach(e => action(e));
}
};
export default Graph;