vcad.
Back to IR & Format
IR & Format

IR Types

TypeScript and Rust types for the intermediate representation

The vcad IR (Intermediate Representation) is the serializable format for CAD documents. Both Rust (vcad-ir) and TypeScript (@vcad/ir) provide equivalent types.

Document

The root container for a vcad file.

TYPEDocument
interface Document {
  version: "0.1";
  nodes: Record<string, Node>;
  materials: Record<string, MaterialDef>;
  roots: SceneEntry[];
}
versionstringrequired

Format version. Currently always "0.1".

nodesRecord<string, Node>required

All nodes in the document, keyed by ID as string.

materialsRecord<string, MaterialDef>required

Material definitions, keyed by material name.

rootsSceneEntry[]required

Which nodes to render and their materials.

Node

A single operation in the CSG graph.

TYPENode
interface Node {
  id: number;
  name: string | null;
  op: CsgOp;
}
idnumberrequired

Unique identifier for this node. Used for references.

namestring | nullrequired

Optional display name. null for anonymous intermediate nodes.

opCsgOprequired

The operation this node represents.

CsgOp

Tagged union of all CSG operations.

Primitives

TYPECube
{ type: "Cube", size: Vec3 }

Box with corner at origin, extending to size.

TYPECylinder
{ type: "Cylinder", radius: number, height: number, segments: number }

Cylinder along Z axis, base at origin.

TYPESphere
{ type: "Sphere", radius: number, segments: number }

Sphere centered at origin.

TYPECone
{
  type: "Cone",
  radiusBottom: number,
  radiusTop: number,
  height: number,
  segments: number
}

Cone or frustum along Z axis, base at origin.

Boolean Operations

TYPEUnion
{ type: "Union", left: NodeId, right: NodeId }

Combines two shapes.

TYPEDifference
{ type: "Difference", left: NodeId, right: NodeId }

Subtracts right from left.

TYPEIntersection
{ type: "Intersection", left: NodeId, right: NodeId }

Keeps only overlapping region.

Transforms

TYPETranslate
{ type: "Translate", child: NodeId, offset: Vec3 }

Moves a shape by offset.

TYPERotate
{ type: "Rotate", child: NodeId, angles: Vec3 }

Rotates a shape. Angles in degrees.

TYPEScale
{ type: "Scale", child: NodeId, factor: Vec3 }

Scales a shape non-uniformly.

Patterns

TYPELinearPattern
{
  type: "LinearPattern",
  child: NodeId,
  direction: Vec3,
  count: number,
  spacing: number
}

Creates copies along a line.

TYPECircularPattern
{
  type: "CircularPattern",
  child: NodeId,
  axis: Vec3,
  count: number,
  angle: number
}

Creates copies around an axis.

Vec3

3D vector used for positions, sizes, and directions.

TYPEVec3
interface Vec3 {
  x: number;
  y: number;
  z: number;
}

NodeId

Reference to another node by its ID.

TYPENodeId
type NodeId = number;

MaterialDef

PBR material definition.

TYPEMaterialDef
interface MaterialDef {
  name: string;
  color: [number, number, number];
  metallic: number;
  roughness: number;
  density?: number;
  description?: string;
}
namestringrequired

Display name for the material.

color[number, number, number]required

RGB color values, 0.0-1.0.

metallicnumberrequired

Metallic factor, 0.0-1.0.

roughnessnumberrequired

Roughness factor, 0.0-1.0.

densitynumberoptional

Material density in kg/m³. For physics simulation.

descriptionstringoptional

Human-readable description.

SceneEntry

Connects a root node to a material for rendering.

TYPESceneEntry
interface SceneEntry {
  root: NodeId;
  material: string;
}
rootNodeIdrequired

ID of the node to render.

materialstringrequired

Key into the materials dictionary.

Complete Example

const document: Document = {
  version: "0.1",
  nodes: {
    "1": {
      id: 1,
      name: "plate",
      op: { type: "Cube", size: { x: 100, y: 60, z: 5 } }
    },
    "2": {
      id: 2,
      name: null,
      op: {
        type: "Translate",
        child: 1,
        offset: { x: -50, y: -30, z: -2.5 }
      }
    },
    "3": {
      id: 3,
      name: "hole",
      op: { type: "Cylinder", radius: 3, height: 10, segments: 32 }
    },
    "4": {
      id: 4,
      name: "result",
      op: { type: "Difference", left: 2, right: 3 }
    }
  },
  materials: {
    aluminum: {
      name: "Aluminum",
      color: [0.9, 0.9, 0.92],
      metallic: 0.95,
      roughness: 0.3
    }
  },
  roots: [
    { root: 4, material: "aluminum" }
  ]
};

TypeScript Import

import type {
  Document,
  Node,
  CsgOp,
  Vec3,
  MaterialDef,
  SceneEntry,
} from "@vcad/ir";

Rust Import

use vcad_ir::{
    Document,
    Node,
    CsgOp,
    Vec3,
    MaterialDef,
    SceneEntry,
};

Serialization

Both implementations use JSON with the same schema:

// Rust
let json = serde_json::to_string_pretty(&document)?;
let doc: Document = serde_json::from_str(&json)?;
// TypeScript
const json = JSON.stringify(document, null, 2);
const doc: Document = JSON.parse(json);