GoJS provides comprehensive mathematical classes for 2D geometry operations and specialized collection classes optimized for diagram operations with iteration support.
Represents 2D coordinates with mathematical operations for positioning and calculations.
class Point {
/**
* Creates a new Point.
* @param x - X coordinate (default: 0)
* @param y - Y coordinate (default: 0)
*/
constructor(x?: number, y?: number);
x: number;
y: number;
// Mathematical Operations
add(p: Point): Point;
subtract(p: Point): Point;
multiply(n: number): Point;
scale(sx: number, sy: number): Point;
rotate(angle: number): Point;
normalize(): Point;
negate(): Point;
// Distance and Direction
distance(p: Point): number;
distanceSquared(p: Point): number;
direction(p: Point): number;
// Comparison and Utility
equals(p: Point): boolean;
equalsApprox(p: Point, epsilon?: number): boolean;
copy(): Point;
setTo(x: number, y: number): Point;
set(p: Point): Point;
offset(dx: number, dy: number): Point;
// String Conversion
toString(): string;
// Static Constants and Methods
static readonly Origin: Point;
static parse(str: string): Point;
static stringify(p: Point): string;
static distanceLineSegmentSquared(px: number, py: number, x1: number, y1: number, x2: number, y2: number): number;
}Represents width and height dimensions with utility methods.
class Size {
/**
* Creates a new Size.
* @param w - Width (default: 0)
* @param h - Height (default: 0)
*/
constructor(w?: number, h?: number);
width: number;
height: number;
// Comparison and Utility
equals(s: Size): boolean;
equalsApprox(s: Size, epsilon?: number): boolean;
copy(): Size;
setTo(w: number, h: number): Size;
set(s: Size): Size;
// String Conversion
toString(): string;
// Static Methods
static parse(str: string): Size;
static stringify(s: Size): string;
}Represents rectangular bounds with position and size.
class Rect {
/**
* Creates a new Rect.
* @param x - X coordinate (default: 0)
* @param y - Y coordinate (default: 0)
* @param w - Width (default: 0)
* @param h - Height (default: 0)
*/
constructor(x?: number, y?: number, w?: number, h?: number);
x: number;
y: number;
width: number;
height: number;
// Computed Properties
left: number;
top: number;
right: number;
bottom: number;
centerX: number;
centerY: number;
center: Point;
position: Point;
size: Size;
// Geometric Operations
contains(x: number, y: number): boolean;
containsPoint(p: Point): boolean;
containsRect(r: Rect): boolean;
intersects(r: Rect): boolean;
intersectsRect(r: Rect): boolean;
union(r: Rect): Rect;
intersect(r: Rect): Rect;
// Modification
inflate(dx: number, dy: number): Rect;
grow(m: Margin): Rect;
subtract(m: Margin): Rect;
offset(dx: number, dy: number): Rect;
// Utility
isEmpty(): boolean;
equals(r: Rect): boolean;
equalsApprox(r: Rect, epsilon?: number): boolean;
copy(): Rect;
setTo(x: number, y: number, w: number, h: number): Rect;
set(r: Rect): Rect;
setPoint(p: Point): Rect;
setSize(s: Size): Rect;
// String Conversion
toString(): string;
// Static Methods
static parse(str: string): Rect;
static stringify(r: Rect): string;
}Represents spacing around elements (top, right, bottom, left).
class Margin {
/**
* Creates a new Margin.
* @param t - Top margin (default: 0)
* @param r - Right margin (default: t)
* @param b - Bottom margin (default: t)
* @param l - Left margin (default: r)
*/
constructor(t?: number, r?: number, b?: number, l?: number);
top: number;
right: number;
bottom: number;
left: number;
// Utility
equals(m: Margin): boolean;
equalsApprox(m: Margin, epsilon?: number): boolean;
copy(): Margin;
setTo(t: number, r?: number, b?: number, l?: number): Margin;
set(m: Margin): Margin;
// String Conversion
toString(): string;
// Static Methods
static parse(str: string): Margin;
static stringify(m: Margin): string;
}Dynamic array-like collection with GoJS-specific iteration and manipulation methods.
class List<T> implements Iterable<T> {
/**
* Creates a new List.
* @param type - Optional type constructor for type checking
*/
constructor(type?: Function);
// Properties
count: number;
length: number;
iterator: Iterator<T>;
// Element Access
elt(i: number): T;
get(i: number): T;
first(): T | null;
last(): T | null;
// Modification
add(val: T): boolean;
addAll(coll: Iterable<T>): boolean;
insert(i: number, val: T): void;
insertAt(i: number, val: T): void;
set(i: number, val: T): T;
removeAt(i: number): T;
remove(val: T): boolean;
removeAll(coll: Iterable<T>): boolean;
clear(): void;
// Queries
contains(val: T): boolean;
containsAll(coll: Iterable<T>): boolean;
containsAny(coll: Iterable<T>): boolean;
indexOf(val: T): number;
// Functional Operations
each(func: (val: T) => void): List<T>;
map<U>(func: (val: T) => U): List<U>;
filter(pred: (val: T) => boolean): List<T>;
any(pred: (val: T) => boolean): boolean;
all(pred: (val: T) => boolean): boolean;
// Conversion
toArray(): T[];
toSet(): Set<T>;
// Sorting
sort(sortfunc?: (a: T, b: T) => number): List<T>;
sortRange(from: number, to: number, sortfunc?: (a: T, b: T) => number): List<T>;
reverse(): List<T>;
// String Conversion
toString(): string;
// Iteration Support
[Symbol.iterator](): IterableIterator<T>;
}Collection that ensures unique elements with set operations.
class Set<T> implements Iterable<T> {
/**
* Creates a new Set.
* @param type - Optional type constructor for type checking
*/
constructor(type?: Function);
// Properties
count: number;
size: number;
iterator: Iterator<T>;
// Modification
add(val: T): boolean;
addAll(coll: Iterable<T>): boolean;
remove(val: T): boolean;
removeAll(coll: Iterable<T>): boolean;
clear(): void;
delete(val: T): boolean;
// Queries
contains(val: T): boolean;
has(val: T): boolean;
containsAll(coll: Iterable<T>): boolean;
containsAny(coll: Iterable<T>): boolean;
first(): T | null;
// Set Operations
copy(): Set<T>;
// Functional Operations
each(func: (val: T) => void): Set<T>;
any(pred: (val: T) => boolean): boolean;
all(pred: (val: T) => boolean): boolean;
// Conversion
toArray(): T[];
toList(): List<T>;
// String Conversion
toString(): string;
// Iteration Support
[Symbol.iterator](): IterableIterator<T>;
}Key-value collection with efficient lookups and iteration.
class Map<K, V> {
/**
* Creates a new Map.
* @param keytype - Optional key type constructor
* @param valtype - Optional value type constructor
*/
constructor(keytype?: Function, valtype?: Function);
// Properties
count: number;
size: number;
// Key-Value Operations
add(key: K, val: V): boolean;
getValue(key: K): V | null;
get(key: K): V | null;
set(key: K, val: V): Map<K, V>;
setValue(key: K, val: V): V | null;
remove(key: K): boolean;
delete(key: K): boolean;
clear(): void;
// Queries
contains(key: K): boolean;
has(key: K): boolean;
containsKey(key: K): boolean;
containsValue(val: V): boolean;
// Iteration
iterator: Iterator<KeyValuePair<K, V>>;
iteratorKeys: Iterator<K>;
iteratorValues: Iterator<V>;
// Functional Operations
each(func: (kvp: KeyValuePair<K, V>) => void): Map<K, V>;
eachKey(func: (key: K) => void): Map<K, V>;
eachValue(func: (val: V) => void): Map<K, V>;
// Conversion
toArray(): KeyValuePair<K, V>[];
toKeySet(): Set<K>;
toValueSet(): Set<V>;
// String Conversion
toString(): string;
// Iteration Support
[Symbol.iterator](): IterableIterator<KeyValuePair<K, V>>;
}
interface KeyValuePair<K, V> {
key: K;
value: V;
}Iterator interface for traversing collections with GoJS-specific patterns.
interface Iterator<T> extends Iterable<T> {
iterator: Iterator<T>;
// Navigation
next(): boolean;
hasNext(): boolean;
first(): T | null;
// Current Value
value: T;
key?: any;
// State
count: number;
// Functional Operations
each(func: (val: T) => void): Iterator<T>;
any(pred: (val: T) => boolean): boolean;
all(pred: (val: T) => boolean): boolean;
// Iteration Support
[Symbol.iterator](): IterableIterator<T>;
}// Point calculations
const p1 = new go.Point(10, 20);
const p2 = new go.Point(30, 40);
const distance = p1.distance(p2);
const midpoint = p1.add(p2.subtract(p1).multiply(0.5));
// Rectangle operations
const rect1 = new go.Rect(0, 0, 100, 50);
const rect2 = new go.Rect(50, 25, 100, 50);
const union = rect1.union(rect2);
const intersection = rect1.intersect(rect2);
const contains = rect1.contains(25, 25); // true
// Margin calculations
const margin = new go.Margin(10, 5, 10, 5);
const paddedRect = rect1.grow(margin);// List operations
const nodeList = new go.List<go.Node>();
nodeList.add(node1);
nodeList.add(node2);
nodeList.add(node3);
// Functional operations
const selectedNodes = nodeList.filter(n => n.isSelected);
const nodeNames = nodeList.map(n => n.data.name);
const hasHighlighted = nodeList.any(n => n.isHighlighted);
// Set operations for unique collections
const visitedNodes = new go.Set<go.Node>();
visitedNodes.add(startNode);
diagram.nodes.each(node => {
if (shouldVisit(node) && !visitedNodes.contains(node)) {
visitedNodes.add(node);
processNode(node);
}
});
// Map for key-value relationships
const nodeDataMap = new go.Map<string, go.ObjectData>();
diagram.model.nodeDataArray.forEach(data => {
nodeDataMap.add(data.key, data);
});
// Efficient lookups
const userData = nodeDataMap.getValue(userKey);// Standard GoJS iteration pattern
const it = diagram.nodes.iterator;
while (it.next()) {
const node = it.value;
console.log('Node:', node.data.name);
}
// Modern JavaScript iteration
for (const node of diagram.nodes) {
console.log('Node:', node.data.name);
}
// Functional iteration
diagram.nodes.each(node => {
if (node.isSelected) {
console.log('Selected node:', node.data.name);
}
});
// Map iteration
const linkCounts = new go.Map<go.Node, number>();
diagram.links.each(link => {
const fromNode = link.fromNode;
if (fromNode) {
const current = linkCounts.getValue(fromNode) || 0;
linkCounts.setValue(fromNode, current + 1);
}
});// Calculate optimal positions in a circle
function arrangeNodesInCircle(nodes: go.List<go.Node>, center: go.Point, radius: number) {
const angleStep = 2 * Math.PI / nodes.count;
nodes.each((node, i) => {
const angle = i * angleStep;
const x = center.x + radius * Math.cos(angle);
const y = center.y + radius * Math.sin(angle);
node.position = new go.Point(x, y);
});
}
// Find bounding box of selected nodes
function getSelectionBounds(diagram: go.Diagram): go.Rect {
let bounds = new go.Rect();
let first = true;
diagram.selection.each(part => {
if (first) {
bounds = part.actualBounds.copy();
first = false;
} else {
bounds = bounds.union(part.actualBounds);
}
});
return bounds;
}