or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

binding-animation.mdcore-diagram.mddata-models.mdgeometry-collections.mdgraphobject-hierarchy.mdindex.mdinteractive-tools.mdlayout-system.mdtheme-management.mdvisual-elements.md
tile.json

geometry-collections.mddocs/

Geometry and Collections

GoJS provides comprehensive mathematical classes for 2D geometry operations and specialized collection classes optimized for diagram operations with iteration support.

Geometry Classes

Point

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;
}

Size

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;
}

Rect

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;
}

Margin

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;
}

Collection Classes

List<T>

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>;
}

Set<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>;
}

Map<K, V>

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<T>

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>;
}

Usage Examples

Geometry Operations

// 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);

Collection Operations

// 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);

Iterator Patterns

// 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);
  }
});

Geometric Calculations for Custom Layouts

// 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;
}