How to Use Selector Refs for CAD Geometry Selection in text-to-cad

Selector refs are compact string tokens (e.g., #o1.2.f3) that uniquely identify geometric elements—occurrences, shapes, faces, edges, and vertices—within a STEP-based CAD model, enabling precise programmatic addressing of geometry across the text-to-cad toolchain.

The earthtojake/text-to-cad repository implements a hierarchical selector reference system that bridges high-level CAD commands with low-level geometry data. This system allows developers and CLI users to reference specific topological entities using stable, deterministic identifiers rather than volatile memory addresses or complex geometric queries. Understanding how to generate, canonicalize, and resolve these selectors is essential for building automation pipelines, inspection scripts, and integration tools that manipulate CAD geometry programmatically.

Understanding the Selector Ref Syntax

Selector refs follow a predictable dotted hierarchy that reflects the topological structure of a STEP model. The syntax uses a # prefix followed by numeric identifiers separated by periods, where each position represents a specific geometric level.

Anatomy of a Selector Token

The generic pattern follows this hierarchy:


#<occurrence>                           → Occurrence selector (e.g., #o1)
#<occurrence>.<shape>                   → Shape selector (e.g., #o1.2)
#<occurrence>.<shape>.<face>            → Face selector (e.g., #o1.2.f3)
#<occurrence>.<shape>.<face>.<edge>     → Edge selector (e.g., #o1.2.f3.e5)
#<occurrence>.<shape>.<face>.<edge>.<vertex> → Vertex selector (e.g., #o1.2.f3.e5.v7)

Each component uses a type prefix (o for occurrence, f for face, e for edge, v for vertex) followed by a stable numeric ID derived from the STEP file ordering. This deterministic numbering ensures that the same model always generates identical selector strings, making them reliable for version control and automated testing.

Core Components

The selector reference system is implemented across several specialized modules in packages/cadpy/src/cadpy/. These files handle parsing, data modeling, indexing, and validation.

cad_ref_syntax.py – Parsing and Validation

The cad_ref_syntax.py module contains the core logic for parsing raw selector strings into structured objects. It validates syntax patterns, extracts numeric IDs, and handles canonicalization of user input. Functions in this file ensure that malformed selectors (such as missing type prefixes or invalid numeric ranges) are caught early with descriptive error messages.

Key responsibilities include tokenizing strings like #o1.2.f3 into constituent parts and validating that each topological reference actually exists within the model manifest.

selector_types.py – Data Structures

This module defines the SelectorBundle and SelectorProfile classes that carry collections of selectors together with their associated manifest metadata. A SelectorBundle typically contains groups of related selectors (for example, all faces belonging to a particular shape) and provides the container structure used when passing geometry references between CLI commands and internal APIs.

These type definitions ensure type safety when selectors are passed through the Python API and help maintain consistency across the various subsystems that consume geometric references.

lookup.py – Indexing and Lookup

The lookup.py module provides high-performance selector resolution through the build_selector_index() function. This function constructs an in-memory index (using Python namedtuple structures) from a model's JSON manifest, enabling O(1) lookups of geometric metadata by selector string.

Critical functions include:

  • canonicalize_selector(raw_selector, index) – Normalizes shorthand or malformed selectors to fully qualified canonical form
  • lookup.selector() – Resolves a canonical selector to its geometric metadata and bounding information
  • edge_adjacent_face_selectors() – Finds topological relationships between geometric entities for adjacency queries

validators.py – Sanity Checks

This utility module provides assertion functions such as selector_count() and assert_selector_count() used by the CLI to validate that models contain expected quantities of specific selector types. These functions are particularly useful in automated testing pipelines where you need to verify that a generated model contains exactly N faces or edges before proceeding with downstream processing.

Practical Usage Examples

Working with selector refs involves both CLI workflows for quick inspection and Python API integration for programmatic geometry manipulation.

Listing Selector Refs from the CLI

Generate selector refs for an existing CAD model using the built-in refs command:


# Generate a model and its associated manifest

text-to-cad cad build --output model.glb

# List all available selector refs

text-to-cad cad refs model.glb

Typical output shows the hierarchical structure:

#o1
#o1.2
#o1.2.f3
#o1.2.f3.e5
#o1.2.f3.e5.v7

Filter by specific topological types to reduce output noise:


# Display only face selectors

text-to-cad cad refs --type face model.glb

Resolving Selectors in Python

Access the selector system programmatically through the cadpy library:

from cadpy import lookup, cad_ref_syntax as crs
from pathlib import Path
import json

# Load the manifest generated alongside the GLB file

manifest_path = Path("model.glb.manifest.json")
manifest = json.loads(manifest_path.read_text())

# Build the selector index for fast lookups

selector_index = lookup.build_selector_index(manifest)

# Canonicalize user-provided selector strings

raw_input = "o1.2.f3"  # Missing # prefix

canonical = lookup.canonicalize_selector(raw_input, selector_index)
print(f"Canonical: {canonical}")  # Output: #o1.2.f3

# Resolve to geometric metadata

selector, metadata = lookup.lookup_selector("#o1.2.f3", selector_index)
print(f"Face area: {metadata.get('area')}")

Inspecting Specific Geometry

Use selector refs to target specific geometric features for detailed inspection:


# Inspect a specific face using its canonical selector

text-to-cad cad inspect --selector "#o1.2.f3" model.glb

This command outputs dimensional data, surface type, and bounding box coordinates, and generates a deep link to the CAD Viewer with the referenced geometry highlighted and centered in the viewport.

Computing Positioning Deltas

Selector refs enable precise mating calculations between geometric features:


# Define source and target face selectors

moving="#o2.4.f1"
target="#o5.3.f7"

# Calculate transform delta required for alignment

text-to-cad cad positioning --from "$moving" --to "$target" model.glb

The output provides the translation vector and rotation quaternion needed to align the moving face with the target face, along with a new selector reference pointing to the transformed geometry.

Summary

  • Selector refs provide stable, human-readable identifiers for CAD topology using the #o1.2.f3 dotted notation.
  • Canonicalization via lookup.canonicalize_selector() ensures user input is normalized to valid, fully qualified tokens.
  • Indexing through lookup.build_selector_index() creates fast lookup tables from model manifests for O(1) resolution performance.
  • Validation utilities in validators.py enable automated checking of selector counts and model completeness.
  • CLI integration supports listing, filtering, inspecting, and positioning geometry using canonical selector strings.

Frequently Asked Questions

What is the difference between a selector ref and a raw geometry ID?

A raw geometry ID is an internal integer or UUID assigned by the STEP parser, often volatile and implementation-dependent. A selector ref is a stable, hierarchical string (like #o1.2.f3) derived from the deterministic ordering of entities in the STEP file. According to the text-to-cad source code in step_scene.py, these selectors remain consistent across regenerations of the same model, making them suitable for automation scripts and persistent references.

How does canonicalization handle malformed selector strings?

The canonicalize_selector() function in lookup.py normalizes variations such as missing # prefixes, extra whitespace, or inconsistent casing into the standard #o{num}.{shape}.{face} format. If the numeric components exceed available entities in the manifest, the function raises a SelectorError with the specific invalid token and available range, preventing downstream lookup failures.

Can selector refs persist across different versions of a CAD model?

Selector refs are deterministic for identical geometry, but they depend on the entity ordering within the STEP file. If a new version introduces additional occurrences, shapes, or faces earlier in the topological hierarchy, numeric IDs may shift. The validators.py module provides selector_count() assertions to detect such structural changes by verifying that expected selector patterns exist before processing.

Where does the #o1.2.f3 syntax originate in the codebase?

The parsing logic resides in cad_ref_syntax.py, which defines the regex patterns and tokenization rules for extracting occurrence (o), shape (implicit numeric), face (f), edge (e), and vertex (v) components. The step_targets.py module then wraps these selectors in StepTarget objects that automatically include SelectorBundle information when required by CAD commands.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →