Projects, archives and twins

Projects, archives and twins

When you load something with the core API you are working with a source for model data. There are two kinds of sources, and it helps to know which one you're dealing with: a project/archive or a twin. They look similar when you list them, but they play different roles — and twins are built from archives.

The two types of model sources

 

Project / Archive

Twin

 

Project / Archive

Twin

What it is

A container holding the raw files you have uploaded (IFC, DWG, PDF, …).

A model assembled according to a specification from files imported from one or more archives.

What it contains

Source files and their version history.

A ready-to-render model plus twin-level metadata (name, property sets, quantities).

Versioning

Each file is versioned on its own.

The twin itself is versioned. Every twin version pins an exact version of each file it uses.

Linked to

One or more archives, listed in the twin's relatedContainerIds.

How you load it

getIfcChanges() + api.ifc.add(...)

TwinInput + api.ifc.add(...)

How they relate

A twin copies files that are imported from archives named in its relatedContainerIds and pins an exact version of each one. That makes a twin a stable snapshot: it keeps rendering the same thing even after new files are uploaded to the archive, until a new twin version is published.

So the rule of thumb is:

  • Reach for a project/archive when you want to work directly with the files you uploaded — pick which IFCs to load, filter them, and so on.

  • Reach for a twin when you want the curated, versioned model that has been built from those files, without caring which individual files went into it. This lets you keep stable references to objects in the model and work with the most reliable representation of the current state of the building.

Working with projects and archives

This is the everyday case covered in Containers and loading your digital twin: list your containers, pick the one you want, fetch its IFC files and add them to the scene.

async function loadArchive(): Promise<void> { const api = await getApi(); // Containers are your projects and archives. const containers = await api.backend.getContainers(); const archive = containers.find( (c) => c.name.toLowerCase() === 'hellotwinfinityworld' ); // Set the container, but skip auto-loading geometry so we stay in control // of exactly what gets loaded. await api.setContainer(archive!, 'skip-ifc-load'); // Fetch the IFC files in the archive and add the ones you are interested in. const files = await api.backend.getIfcChanges(archive!); await api.ifc.add(files); api.viewer.addOrUpdateEnvironment({ boundingInfo: api.ifc.regionBoundingInfo }); api.viewer.camera.zoomToExtent(api.ifc.regionBoundingInfo, 'top'); }

getIfcChanges() returns the IFC files; if you need other file types (DWG, PDF, blobs, …) use the more general api.backend.getChanges(container, query) with a PredefinedBimChangeMetadataQuery.

Working with twins

Twins are reached through the same api client, under api.backend.twins. List the twins that belong to an archive by passing that archive's container id, then load the one you want straight into the scene. A TwinInput is just another input to api.ifc.add — exactly like an IFC file.

import { TwinInput } from '@twinfinity/core'; async function loadTwin(): Promise<void> { const api = await getApi(); // List the twins related to this archive (pass its container id). const twins = await api.backend.twins.listAllTwins(); const twin = twins.find((t) => t.name === 'My building'); // Need more detail? getTwin returns the full metadata for a twin: // its version, related archives and property sets. // const details = await api.backend.twins.getTwin(twin!.id); // Load the latest version of the twin into the scene. await api.ifc.add(TwinInput.create(twin!)); // ...or load a specific, pinned version instead: // await api.ifc.add(new TwinInput(twin!.id, twin!.version)); api.viewer.addOrUpdateEnvironment({ boundingInfo: api.ifc.regionBoundingInfo }); api.viewer.camera.zoomToExtent(api.ifc.regionBoundingInfo, 'top'); }

A few useful calls on api.backend.twins:

  • listTwins(relatedContainerId?, page?, limit?) — a single page of twins, optionally filtered to one archive.

  • listAllTwins(relatedContainerId?) — the same, but auto-paginated into one array.

  • getTwin(twinId) or getTwin({ id, version }) — full metadata for a twin (or a specific version of it).

Loading vs. inspecting. TwinInput + api.ifc.add renders the twin's geometry in the viewer. If you only need its data — property sets, quantities, related archives — getTwin gives you that without loading any geometry.

Note: Only a twin that has finished processing into a renderable model can be loaded. If you pass a twin that has no model yet, api.ifc.add will reject. Use the metadata from getTwin / listTwins to decide what to offer in your UI.

In short

  • Both projects/archives and twins are model sources you load through the core API.

  • An archive holds your raw files; a twin is a versioned model built from a pinned set of those files and linked back to its archive(s) via relatedContainerIds.

  • Load an archive with getIfcChanges()api.ifc.add(files); load a twin with TwinInputapi.ifc.add(twinInput).

  • Browse and inspect twins through api.backend.twins.