Neural Sketch

Auto-Incremental IDs

Automatically manage and reference primitives in your diagrams

Neural Sketch makes structure easy to reference by giving every shape a name—even when you don’t.

Whether you're drawing blocks, placing coordinates, or organizing groups, the system assigns incremental, unique IDs to every primitive.

These IDs unlock a powerful reference model: one where you can position, style, or annotate elements relative to one another—without thinking about bookkeeping.


What is an ID?

An ID in Neural Sketch is a symbolic handle: a name by which you can refer to a primitive you've defined.

It's used for things like:

  • Relative positioning: right=1cm of blockA
  • Routing and connections: arrows from blockB.east to blockC.north
  • Cross-referencing: anchors for labels, annotations, bridges, or spy/zoom elements

How IDs are created

Every primitive gets an ID one of two ways:

  • Manual (user-defined): You write id=myBlock
  • Automatic (system-assigned): Neural Sketch infers and assigns one for you

If omitted, the ID is generated using:

<shape-type><counter>

So your first unnamed rectangle becomes rectangle1, the second rectangle2, and so on.

Auto-increment counters reset at the beginning of every nskFigure, so you get clean, predictable IDs per diagram.

Example: ID Generation

When creating any primitives, for example an \nskBlock, you can define an ID using the id key:

\nskBlock[id=myblock, ...]

If no explicit ID is provided, Neural Sketch auto-generates one using the pattern:

<shape-type><counter>

For example:

  • The first rectangle: rectangle1
  • The second diamond: diamond2
  • The third ellipse: ellipse3

Referencing an Element’s Own ID

\nskBlock[
  text-north={This block’s ID is \nskBlockID},
]

The macro \nskBlockID expands to the ID of the current block inside its definition.

\nskBlockID only works within the lifetime of the block being drawn.

Handling Duplicated IDs

By default, if no id= is provided, one is autogenerated (as described above), producing the following result:

\nskContainer[...]{
  \foreach \i in {1,...,4} {
      \nskBlock[last-pos-s={right=}, text-north=\nskBlockID] 
    }
}

However, if we attempt to assign the same id= to multiple elements, by default each subsequent element is incremented accordingly to produce an unique id:

\nskContainer[...]{
  \foreach \i in {1,...,4} {
      \nskBlock[id=a, last-pos-s={right=}, text-north=\nskBlockID] 
    }
}

For a more intuitive experience, we don't rewrite the history timeline i.e., we keep the first registered block name as-is.

This behavior can be disable by setting the package option auto-increment-duplicates=false

\usepackage[
  auto-increment-duplicates=false, 
]{neural-sketch}
\nskUseModule{*}

Neural Sketch keeps track of everything you draw. And lets you reference them—even if you didn’t name them.

Tip

Neural Sketch tracks every drawing operation, giving you a rich set of utilities to reference and reuse elements declaratively. This makes it easy to build complex diagrams by relating parts to each other—not by coordinates, but by intention.

\nskID{n} — Relative (Backwards)

Use \nskID{n} to reach into the past. It returns the nthn^{th} previously drawn element-ID.

Sometimes, it’s easier to refer back to what you just drew—without the overhead of naming it.

\nskBlock[text-center=A]
\nskBlock[pos={right=of \nskID{1}}, text-center=B]
\nskBlock[pos={right=of \nskID{1}}, text-center=C]
  • The first \nskID{1} resolves to the block labeled A
  • The second \nskID{1} now points to B, which was just added

This is very useful when you want to quickly reference previous, or dynamically created elements.

Tip

Use \nskID{n} to reference the nthn^{th} most recent element.

\nskID!{n} — Absolute (Forwards)

Sometimes, you want to go back to the beginning. That’s what the bang! form gives you:

\nskID!{1}  % first-created element
\nskID!{3}  % third-created element

Tip

In some cases, it's more natural to reference elements by when they were created, not how recently—counting from the beginning instead of the end.

 
\nskBlock[text-center=A]
 
% [...] many elements later
 
\nskBlock[pos={right=of \nskID{1}}, text-center=E]
 
% easily draw a line between the last and first element
\nskConnect[from=\nskID{1}, to=\nskID!{1}]

Tip

You can use \nskID{n} and \nskID!{n} anywhere a reference is needed—like inside pos or connect-to. But for most layout work, consider the higher-level utilities: pos, last-pos, and last-pos-s. These give you a more semantic way to express relative placement—without needing to count.

Learn more in the Positioning Mechanism guide.

Scoped and Predictable

All IDs—whether auto-generated or manually assigned—are scoped locally to their nskFigure.

This means:

  • You can reuse id=main in multiple diagrams
  • Auto-generated counters won’t bleed across figures
  • The global sequence resets with every figure

Internals

Internally, Neural Sketch tracks IDs with \g_nsk_block_id_history_seq. Each figure resets this sequence, ensuring ID hygiene.

Custom vs. Auto-generated IDs

FeatureCustom IDsAuto-generated IDs
Explicit Assignment✅ Yes❌ No
Auto-incremental❌ No✅ Yes
Scoped to Figure✅ Yes✅ Yes
Overrideable✅ Yes❌ No

User-defined IDs are intentionally flexible; specifying the same ID multiple times within a figure overrides the previous definition, allowing convenient reuse in loops or iterative diagram segments.

Takeaway

ID management in Neural Sketch is designed for momentum—not micromanagement. It gives you a referential language to build layouts that scale.

Practical Patterns

Explicit and Auto-generated IDs

% Explicit ID
\nskBlock[id=main, text-center={Main Block}]
 
% Auto-generated ID (rectangle1)
\nskBlock[pos={right=of main}, text-center={Auto ID: \nskBlockID}]
 
% Reference last auto-generated block
\nskBlock[pos={below=1cm of \nskID{1}}, text-center={Below rectangle1}]

Loops

\begin{nskFigure}
  \foreach \x in {0,2,4} {
    \nskBlock[x=\x, y=0, text-center={x=\x}]
  }
 
  % References the last block, without explicitly name it
  \nskBlock[pos={below=1cm of \nskID{1}}, text-south=Below last element]
\end{nskFigure}

Loops with Reused IDs

\begin{nskFigure}
  \foreach \x in {0,2,4} {
    \nskBlock[id=iter, x=\x, y=0, text-center={x=\x}]
  }
 
  % References the last 'iter' (x=4)
  \nskBlock[pos={below=1cm of iter}, text-center={Below last iter}]
\end{nskFigure}

Here, iter is reused on each loop iteration, but only the last one matters—because only the last survives.


Commands

MacroDescription
\nskID{n}Returns the nthn^{th} previous ID from the block history
\nskID!{n}Returns the nthn^{th} ID counting forward instead of backward