INodeData Interface Documentation

Overview

INodeData is the core data interface for scene graph nodes, describing the complete data structure for various types of nodes in the scene graph. This interface defines the basic properties, state, rendering information, animation data, and metadata of nodes.

Interface Definition

interface INodeData {
    guid: Iguid;
    name: string;
    type: "DOCUMENT" | "VIEWER" | "LAYER" | "FEATURE" | "CONTAINER";
    parentIndex: INodeParentIndex;
    visible: boolean;
    locked: boolean;
    render?: INodeRenderData | null | undefined;
    animation?: INodeAnimationDataItem[];
    meta: Record<string, any>;
}

Property Details

guid

  • Type: Iguid
  • Required: Yes
  • Description: Globally unique identifier for the node
  • Details:
    • Composed of localId (local unique identifier) and sessionId (session unique identifier)
    • Used to uniquely identify a node throughout the scene graph
    • Format: sessionId:localId

Iguid Interface Definition:

interface Iguid {
    localId: number; // Local unique identifier
    sessionId: number; // Session unique identifier
}

name

  • Type: string
  • Required: Yes
  • Description: Display name of the node
  • Details:
    • Used to display the node name in the user interface
    • Can be any string, uniqueness is not required
    • Meaningful descriptive names are recommended

type

  • Type: "DOCUMENT" | "VIEWER" | "LAYER" | "FEATURE" | "CONTAINER"
  • Required: Yes
  • Description: Node type identifier
  • Details:
    • DOCUMENT: Document root node, typically the top-level node of the scene graph
    • VIEWER: View node, representing a 3D view instance
    • LAYER: Layer node, used to organize and manage scene elements
    • FEATURE: Feature node, representing specific visualization objects (models, annotations, etc.)
    • CONTAINER: Container node, used for logical grouping and organizing child nodes

parentIndex

  • Type: INodeParentIndex
  • Required: Yes
  • Description: Parent node index information, used to determine the node's position in the scene graph
  • Details:
    • Locates the node through the parent node's GUID and position within the parent
    • position uses a decimal index system, supporting flexible node ordering and insertion

INodeParentIndex Interface Definition:

interface INodeParentIndex {
    guid: Iguid; // Unique identifier of the parent node
    position: string; // Position within parent node (decimal index)
}

Decimal Index Explanation:

  • Uses decimals represented as strings to determine node order
  • Examples: "1", "2", "1.5", etc.
  • New nodes can be inserted between any two nodes without reordering

visible

  • Type: boolean
  • Required: Yes
  • Description: Node visibility state
  • Details:
    • true: Node and its children are visible
    • false: Node and its children are hidden
    • Affects the node's rendering behavior

locked

  • Type: boolean
  • Required: Yes
  • Description: Node lock state
  • Details:
    • true: Node is locked, cannot be edited or interacted with
    • false: Node can be edited and interacted with normally
    • Used to protect important nodes from accidental modification

render

  • Type: INodeRenderData | null | undefined
  • Required: No (optional)
  • Description: Node rendering data configuration
  • Details:
    • Defines how the node is rendered in the scene
    • Contains geometry information, render type, and render properties
    • null or undefined indicates the node does not directly participate in rendering (e.g., container nodes)

INodeRenderData Interface Definition:

interface INodeRenderData {
    type: string; // Render type
    geometry?: Geometry; // Geometry (GeoJSON)
    properties: Record<string, any>; // Render properties
}

animation

  • Type: INodeAnimationDataItem[]
  • Required: No (optional)
  • Description: Node animation data collection
  • Details:
    • Stores all animation configurations for the node
    • Each animation item contains an animation name and action sequence
    • Supports multiple animations coexisting

INodeAnimationDataItem Interface Definition:

interface INodeAnimationDataItem {
    name: string; // Animation name
    actions: INodeAnimationActionData[]; // Animation action sequence
}

INodeAnimationActionData Interface Definition:

interface INodeAnimationActionData {
    duration: number; // Animation duration (milliseconds)
    [key: string]: any; // Other animation properties (e.g., transform, keyframes, etc.)
}

meta

  • Type: Record<string, any>
  • Required: Yes
  • Description: Node metadata dictionary
  • Details:
    • Stores any custom data associated with the node
    • Can be used to extend node functionality without modifying the interface definition
    • Common uses:
      • Business data association
      • Custom properties
      • Temporary state storage
      • Plugin data

Common meta Field Examples:

{
    // Business ID
    businessId: "building-001",

    // Creation information
    createdAt: "2026-01-16T10:00:00Z",
    createdBy: "user123",

    // Custom tags
    tags: ["important", "checked"],

    // Extended properties
    customProperties: {
        floor: 3,
        area: 120.5,
        category: "residential"
    }
}

Geometry (from GeoJSON)

type Geometry
    = | Point
        | MultiPoint
        | LineString
        | MultiLineString
        | Polygon
        | MultiPolygon
        | GeometryCollection;

From the GeoJSON specification, used to describe geographic or spatial geometries.


Usage Examples

Example 1: Creating a Document Root Node

const documentNode: INodeData = {
    guid: {
        localId: 0,
        sessionId: 1
    },
    name: "Root Document",
    type: "DOCUMENT",
    parentIndex: {
        guid: { localId: -1, sessionId: -1 }, // Root node has no parent
        position: "0"
    },
    visible: true,
    locked: false,
    meta: {
        createdAt: new Date().toISOString(),
        version: "1.0.0"
    }
};

Example 2: Creating a Layer Node

const layerNode: INodeData = {
    guid: {
        localId: 1,
        sessionId: 1
    },
    name: "Building Layer",
    type: "LAYER",
    parentIndex: {
        guid: { localId: 0, sessionId: 1 }, // Parent is document root node
        position: "1"
    },
    visible: true,
    locked: false,
    render: {
        type: "3DTILES",
        properties: {
            url: "xxxx"
        }
    },
    meta: {
        description: "All building models",
        category: "building"
    }
};

Example 3: Creating a Feature Node with Render Data

const featureNode: INodeData = {
    guid: {
        localId: 2,
        sessionId: 1
    },
    name: "Point Measurement",
    type: "FEATURE",
    parentIndex: {
        guid: { localId: 1, sessionId: 1 }, // Parent is layer
        position: "1"
    },
    visible: true,
    locked: false,
    render: {
        type: "PointMeasurement",
        geometry: {
            type: "Point",
            coordinates: [116.397, 39.908, 0]
        },
        properties: {}
    },
    meta: {
        buildingId: "BLD-001",
        height: 50.0,
        floors: 15
    }
};
### Example 4: Creating a Container Node (Logical Grouping) ```typescript const containerNode: INodeData = { guid: { localId: 4, sessionId: 1 }, name: "First Floor Room Group", type: "CONTAINER", parentIndex: { guid: { localId: 2, sessionId: 1 }, position: "1" }, visible: true, locked: false, render: undefined, // Container nodes typically don't need render data meta: { floor: 1, roomCount: 8 } };

Node Type Relationships

DOCUMENT (Document Root Node) └── VIEWER (View Node) ├── FEATURE (Feature Node) └── CONTAINER (Container Node) └── LAYER (Layer Node)

Best Practices

1. GUID Management

  • Use GUID.gen() to generate new unique identifiers
  • Avoid manually creating GUIDs to prevent conflicts
  • Handle GUIDs correctly during serialization/deserialization

2. Decimal Index Usage

  • Recommend using the fractional-indexing library for generation

3. Render Data Optimization

  • Only set the render property on nodes that actually need rendering
  • Container and organizational nodes should have render set to undefined
  • Reuse identical render configurations to save memory

4. Metadata Design

  • Use clear naming conventions
  • Avoid storing large amounts of data in meta
  • Consider using nested structures to organize related metadata

5. Visibility and Locking

  • When a parent node's visible is false, all child nodes are invisible
  • Lock state is not automatically inherited and needs to be handled in business logic
  • Consider the impact on child nodes when modifying node state

Type Checking Helpers

// Type guard function
function isValidNodeType(type: string): type is INodeData["type"] {
    return ["DOCUMENT", "VIEWER", "LAYER", "FEATURE", "CONTAINER"].includes(type);
}

// Node validation function
function validateNodeData(data: any): data is INodeData {
    return (
        data
        && typeof data === "object"
        && "guid" in data
        && "name" in data
        && typeof data.name === "string"
        && "type" in data
        && isValidNodeType(data.type)
        && "parentIndex" in data
        && "visible" in data
        && typeof data.visible === "boolean"
        && "locked" in data
        && typeof data.locked === "boolean"
        && "meta" in data
        && typeof data.meta === "object"
    );
}