forum-logic/src/tests/scripts/force-directed.test.js

87 lines
2.8 KiB
JavaScript

import { Box } from '../../classes/display/box.js';
import { ForceDirectedGraph } from '../../classes/display/force-directed.js';
import { Rectangle, Vector } from '../../classes/supporting/geometry/index.js';
import { overlapRepulsionForce, targetRadiusForce } from '../../classes/display/pairwise-forces.js';
import { delayOrWait } from '../../classes/display/scene-controls.js';
import { Scene } from '../../classes/display/scene.js';
import { EPSILON } from '../../util/constants.js';
import { mochaRun } from '../../util/helpers.js';
const rootElement = document.getElementById('scene');
const rootBox = new Box('rootBox', rootElement).flex();
window.scene = new Scene('WDG test', rootBox);
describe('Force-Directed Graph', function tests() {
this.timeout(0);
let graph;
before(() => {
graph = (window.graph = new ForceDirectedGraph('test1', window.scene.middleSection.el, {
width: 800, height: 600,
}));
graph.addVertex('v1', 'box1');
});
it('rectangle should be a polygon with 4 vertices', () => {
const rect = new Rectangle([0, 0], [1, 1]);
rect.vertices[0].should.eql([0, 0]);
rect.vertices[1].should.eql([0, 1]);
rect.vertices[2].should.eql([1, 1]);
rect.vertices[3].should.eql([1, 0]);
});
it('overlapping boxes should repel', () => {
const rect1 = new Rectangle([0, 0], [1, 1]);
const rect2 = new Rectangle([0, 0], [1, 2]);
rect1.center.should.eql([0.5, 0.5]);
rect2.center.should.eql([0.5, 1]);
const force1 = overlapRepulsionForce(rect1, rect2, 10);
force1.should.eql([0, 10]);
});
it('boxes at target radius should have no net force', () => {
const rect1 = new Rectangle([0, 0], [1, 1]);
const rect2 = new Rectangle([10, 0], [1, 1]);
rect1.center.should.eql([0.5, 0.5]);
rect2.center.should.eql([10.5, 0.5]);
const force = targetRadiusForce(rect1, rect2, 10);
force[0].should.be.within(-EPSILON, EPSILON);
force[1].should.be.within(-EPSILON, EPSILON);
});
it('can construct a unit vector', () => {
Vector.unitVector(0, 2).should.eql([1, 0]);
Vector.unitVector(1, 2).should.eql([0, 1]);
});
it('normalized vector should have length = 1', () => {
const v = Vector.from([2, 0]);
const u = v.normalize();
u.magnitude.should.be.within(1 - EPSILON, 1 + EPSILON);
});
it('random unit vector should have length = 1', () => {
const u = Vector.randomUnitVector(2);
u.magnitude.should.be.within(1 - EPSILON, 1 + EPSILON);
});
it('can add a second box to the graph', async () => {
await delayOrWait(1000);
const v = graph.addVertex('v1', 'box2');
v.setProperty('prop', 'value');
});
it('can add an edge to the graph', async () => {
await delayOrWait(1000);
graph.addEdge('e1', 'box1', 'box2', 1);
});
it('runs until reaching equilibrium', async () => {
await graph.runUntilEquilibrium();
});
});
mochaRun();