Skip to content

Commit

Permalink
Made nodes capable of handling edge weights
Browse files Browse the repository at this point in the history
Also made it so that fontSize for node label changes dynamically.

Issue: #78
  • Loading branch information
AdrianSolberg committed Jul 1, 2024
1 parent f3bc130 commit 4ad71fa
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 26 deletions.
78 changes: 66 additions & 12 deletions src/Components/Derived/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,40 @@ const defaultNodeOptions: NodeOptions = {
type Edge = {
node: Node;
line: Line;
weight?: number;
}

class Node extends Circle {
adjacencyList: Edge[];
label?: Text;

constructor(x = 0, y = 0, radius = 5, adjacencyList:Edge[] = [], options?: NodeOptions) {
super(x, y, radius, options);
const { label } = { ...defaultNodeOptions, ...options };
if (label) {
this.add(new Text(label, {position: [0,0], fontSize: radius/2, anchorX: "center", anchorY: "middle", responsiveScale: false}))
this.label = new Text(label, {position: [0,0], fontSize: this.calculateFontSize(label, radius), anchorX: "center", anchorY: "middle", responsiveScale: false});
this.add(this.label)
}
this.adjacencyList = [...adjacencyList];
}

private calculateFontSize(text: string, radius: number): number {
const maxDiameter = radius * 2;
let fontSize = radius;

while (fontSize > 0 && text.length * fontSize * 0.6 > maxDiameter) {
fontSize -= 0.25;
}

return fontSize;
}

isAdjacentTo(node: Node): boolean {
return this.adjacencyList.map((edge) => edge.node).includes(node);
}

connectTo(other: Node, directed: boolean) {
if (!this.isAdjacentTo(other)) {
connectTo(other: Node, directed: boolean, value?: number): void {
if (!this.isAdjacentTo(other) && !(!directed && other.isAdjacentTo(this))) {
const dx = other.position.x - this.position.x;
const dy = other.position.y - this.position.y;
const dist = Math.sqrt(dx * dx + dy * dy);
Expand All @@ -46,8 +60,8 @@ class Node extends Circle {
const outlineX2 = other.position.x - cos * other.radius;
const outlineY2 = other.position.y - sin * other.radius;

const line = new Line([outlineX1, outlineY1], [outlineX2-this.position.x, outlineY2-this.position.y], {arrowhead: directed, curve: directed ? 5 : 0, label: "1"});
this.adjacencyList.push({node: other, line: line});
const line = new Line([outlineX1, outlineY1], [outlineX2-this.position.x, outlineY2-this.position.y], {arrowhead: directed, curve: directed ? 5 : 0, label: value !== undefined ? value.toString() : ""});
this.adjacencyList.push({node: other, line: line, weight: value});
this.add(line);
}
else if (dx >= 0 && dy < 0) {
Expand All @@ -56,8 +70,8 @@ class Node extends Circle {
const outlineX2 = other.position.x - cos * other.radius;
const outlineY2 = other.position.y + sin * other.radius;

const line = new Line([outlineX1, outlineY1], [outlineX2-this.position.x, outlineY2-this.position.y], {arrowhead: directed, curve: directed ? 5 : 0, label: "1"});
this.adjacencyList.push({node: other, line: line});
const line = new Line([outlineX1, outlineY1], [outlineX2-this.position.x, outlineY2-this.position.y], {arrowhead: directed, curve: directed ? 5 : 0, label: value !== undefined ? value.toString() : ""});
this.adjacencyList.push({node: other, line: line, weight: value});
this.add(line);
}
else if (dx < 0 && dy < 0) {
Expand All @@ -66,8 +80,8 @@ class Node extends Circle {
const outlineX2 = other.position.x + cos * other.radius;
const outlineY2 = other.position.y + sin * other.radius;

const line = new Line([outlineX1, outlineY1], [outlineX2-this.position.x, outlineY2-this.position.y], {arrowhead: directed, curve: directed ? 5 : 0, label: "1"});
this.adjacencyList.push({node: other, line: line});
const line = new Line([outlineX1, outlineY1], [outlineX2-this.position.x, outlineY2-this.position.y], {arrowhead: directed, curve: directed ? 5 : 0, label: value !== undefined ? value.toString() : ""});
this.adjacencyList.push({node: other, line: line, weight: value});
this.add(line);
}
else {
Expand All @@ -76,8 +90,8 @@ class Node extends Circle {
const outlineX2 = other.position.x + cos * other.radius;
const outlineY2 = other.position.y - sin * other.radius;

const line = new Line([outlineX1, outlineY1], [outlineX2-this.position.x, outlineY2-this.position.y], {arrowhead: directed, curve: directed ? 5 : 0, label: "1"});
this.adjacencyList.push({node: other, line: line});
const line = new Line([outlineX1, outlineY1], [outlineX2-this.position.x, outlineY2-this.position.y], {arrowhead: directed, curve: directed ? 5 : 0, label: value !== undefined ? value.toString() : ""});
this.adjacencyList.push({node: other, line: line, weight: value});
this.add(line);
}

Expand All @@ -87,7 +101,7 @@ class Node extends Circle {
}
}

disconnectFrom(other: Node) {
disconnectFrom(other: Node): void {
const index = this.adjacencyList.map((edge) => edge.node).indexOf(other);
if (index > -1) {
const directed = this.adjacencyList[index].line.arrowhead;
Expand All @@ -99,6 +113,46 @@ class Node extends Circle {
}
}

getWeight(other: Node): (number | undefined) {
const index = this.adjacencyList.map((edge) => edge.node).indexOf(other);
if (index > -1) {
return this.adjacencyList[index].weight;
} else {
return undefined;
}
}

addWeight(other: Node, value: number): void {
const index = this.adjacencyList.map((edge) => edge.node).indexOf(other);
if (index > -1) {
if (this.adjacencyList[index].weight !== undefined) {
this.adjacencyList[index].weight! += value;
} else {
this.adjacencyList[index].weight = value;
}
this.adjacencyList[index].line.setLabel(this.adjacencyList[index].weight?.toString()!);
}
}

setWeight(other: Node, value: number): void {
const index = this.adjacencyList.map((edge) => edge.node).indexOf(other);
if (index > -1) {
this.adjacencyList[index].weight = value;
this.adjacencyList[index].line.setLabel(value.toString());
}
}

setLabel(label: string) {
if (this.label !== undefined) {
this.label.setText(label);
this.label.setFontSize(this.calculateFontSize(label, this.radius));
}
else {
this.label = new Text(label, {position: [0,0], fontSize: this.calculateFontSize(label, this.radius), anchorX: "center", anchorY: "middle", responsiveScale: false});
this.add(this.label)
}
}

}

export default Node;
13 changes: 9 additions & 4 deletions src/Components/Line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ class Line extends Component implements Collider {
const dir = midPoint.clone().sub(startPosition).normalize();
let normal:Vector2;
if (this.arrowhead) {
normal = new Vector2(-dir.y, dir.x).normalize().multiplyScalar(this.curve);
normal = new Vector2(-dir.y, dir.x).normalize().multiplyScalar(this.curve).multiplyScalar(1.1);
} else {
normal = new Vector2(-dir.y, dir.x).normalize().multiplyScalar(this.curve).addScalar(1);
normal = new Vector2(-dir.y, dir.x).normalize().multiplyScalar(1.1);
}
const labelPoint = midPoint.clone().add(normal);
this.label.setPosition([labelPoint.x, labelPoint.y]);
Expand Down Expand Up @@ -210,10 +210,11 @@ class Line extends Component implements Collider {
const midPoint = new Vector2(startPosition.x+(endPosition.x-startPosition.x)/2, startPosition.y+(endPosition.y-startPosition.y)/2);
const direction = midPoint.clone().sub(startPosition).normalize();
let normal:Vector2;
this.label
if (this.arrowhead) {
normal = new Vector2(-direction.y, direction.x).normalize().multiplyScalar(this.curve);
normal = new Vector2(-direction.y, direction.x).normalize().multiplyScalar(this.curve).multiplyScalar(1.1);
} else {
normal = new Vector2(-direction.y, direction.x).normalize().multiplyScalar(this.curve).addScalar(1);
normal = new Vector2(-direction.y, direction.x).normalize().multiplyScalar(1.1);
}
const labelPoint = midPoint.clone().add(normal);
this.label.setPosition([labelPoint.x, labelPoint.y]);
Expand Down Expand Up @@ -259,6 +260,10 @@ class Line extends Component implements Collider {
this.curve = curve;
}

public setLabel(label: string): void {
this.label.setText(label);
}

update(camera: OrthographicCamera) {
this.updateGeometry(this.start, this.end, this.arrowhead, camera);
}
Expand Down
4 changes: 4 additions & 0 deletions src/Components/Text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ class Text extends Component implements Collider {
this.renderText.text = text;
}

setFontSize(fontSize: number): void {
this.renderText.fontSize = fontSize;
}

update(camera: OrthographicCamera) {
if (this.responsiveScale) {
this.scale.set(1 / camera.zoom, 1 / camera.zoom, 1);
Expand Down
23 changes: 13 additions & 10 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,19 @@ import { falseDependencies } from "mathjs";

const core = new Core();
//const grid = new Grid();
const node = new Node(0,10,5,[],{label: "Node 1"});
const node2 = new Node(0,-20,5,[],{label: "Node 2"}));
const node3 = new Node(20,0,5,[],{label: "Node 3"});
const node4 = new Node(-40,-40,5,[],{label: "Node 4"});
const node5 = new Node(20,-50,5,[],{label: "Node 5"});
node.connectTo(node2, false);
node2.connectTo(node3, false);
node2.connectTo(node4, true);
node5.connectTo(node2, false);
node4.connectTo(node2, true);
const node = new Node(-20,20,5,[],{label: "Node 123456789"});
const node2 = new Node(0,-20,5,[],{label: "Node 2 Mer tekst"}));
const node3 = new Node(40,20,5,[],{label: "3"});
const node4 = new Node(30,-40,5,[],{label: "4"});
const node5 = new Node(-50,20,5,[]);
node.connectTo(node2, false, 10);
node2.connectTo(node3, true, 5);
node2.connectTo(node4, true, 5);
node4.connectTo(node2, true, 20);
node.connectTo(node5, true);
node5.connectTo(node, true);
node.setLabel("Hei");
node5.setLabel("5");
//node3.connectTo(node2, true);
//core.add(grid);
core.add(node);
Expand Down

0 comments on commit 4ad71fa

Please sign in to comment.