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"
}
}
Related Types
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"
);
}