# BCF Format

## Overview

The BIM Collaboration Format (BCF) is an open file format used for storing data (comments, screenshots, etc.) about IFC models. The official documentation for BCF can be found here. This document describes how to load a BCF file and interact with the data in the HOOPS Web Viewer.

Find information about which BCF versions are currently supported on the Supported Formats page.

## BCF API

### BCFManager

The BCFManager class facilitates loading, accessing, and editing data from a BCF file.

### BCFData

The BCFData class represents a single BCF file. It contains a set of `BCFTopics`, as well as information about the BCF filename and version.

### BCFTopic

Each BCF file can contain multiple topics. Each topic contains a `BCFMarkup`, set of BCFSnapshots, and set of BCFViewpoints. Each `BCFViewpoint` can have exactly one corresponding snapshot.

Each topic has a unique id and contains images, camera viewpoints, markup, and comments. The /api_ref/viewing/classes/Communicator.BCFTopic class provides access to this data via the `BCFMarkup`, `BCFViewpoint`, and `BCFSnapshot` classes.

### BCFMarkup

The BCFMarkup class contains textual information about the topic. This includes the title, author, description, comments, etc. For a list of all markup data to query, see the webviewer API Reference.

### BCFSnapshot

The BCFSnapshot class contains image data related to the topic.

### BCFViewpoint

The BCFViewpoint class contains information about components related to the topic, camera settings, and possible markup and clipping information. This class can be used to activate a view, which will change the camera, visibility, cutting planes, colors, and markup.

## BCF import

To load a file via HTTP request:

    // Load a BCF file named 'example.bcf' via HTTP request.
    hwv.BCFManager.addBCFFromFile("example.bcf");

After a BCF is loaded, the `bcfLoaded` callback is triggered. This callback contains an ID that corresponds to the `BCFData` object representing the BCF file and can be used to retrieve it.

## Interacting with BCF data

It is also possible to create BCF data using the BCFManager createBCFData function.

    // Create a BCFData object representing a file named 'example.bcf'.
    hwv.BCFManager.createBCFData("example");

Using the ID that is returned in the `bcfLoaded` callback, you can get the `BCFData` object.

                let bcfData = hwv.BCFManager.getBCFData(id);

The getTopics function will return a map containing the `BCFTopic` IDs and `BCFTopic` objects.

Each topic can have only one markup and can contain multiple snapshots and viewpoints.

        // Map associating BCF topic ids to BCF topic data.
        let topics = bcfData.getTopics();
        topics.forEach((topic, id) => {
            // BCFMarkup class
            let markup = topic.getMarkup();

            // A map associating viewpoint filenames with viewpoint data.
            let viewpoints = topic.getViewpointMap();

            // A map associating snapshot filenames with snapshot data.
            let snapshots = topic.getSnapshotMap();
        });

To add a topic to our `BCFData`, first we create the topic, and then add it using the `addTopic` function.

        let bcfDataId = bcfData.getId();
        let bcfFilename = bcfData.getFilename();
        let topicId = Communicator.UUID.create();

        let markupView = hwv.markupManager.getActiveMarkupView();
        topic = await Communicator.BCFTopic.createTopic(
            hwv,
            bcfDataId,
            bcfFilename,
            "topic title",
            markupView,
        );
        bcfData.addTopic(topicId, topic);

To delete a topic, remove it from the `BCFData` topics map.

        let topics = bcfData.getTopics();
        topics.delete(topicId);

Topic comments are part of the markup class. Below we create and add a comment, update it, then delete it.

        let markup = topic.getMarkup();

        // create a comment
        let comment = markup.addComment(new Date(), "author name", "comment text");

        //update a comment
        comment.setText("new comment text");

        // delete a comment
        let comments = markup.getComments();
        comments.delete(comment.getId());

To correlate a snapshot and viewpoint, we first create them and then add them to the topic snapshot and viewpoint maps, as well as add it to the markup class. The viewpoint and snapshot name prefixes do not have to match but are associated by the markup class.

        let id = Communicator.UUID.create();

        let image = await hwv.takeSnapshot();

        let snapshotFilename = id + ".png";
        let viewpointFilename = id + ".bcfv";

        let snapshot = Communicator.BCFSnapshot.createFromImage(id + ".png", image);
        let viewpoint = await Communicator.BCFViewpoint.createViewpoint(hwv, id + ".bcfv");

        topic.setSnapshot(snapshotFilename, snapshot);
        topic.setViewpoint(viewpointFilename, viewpoint);
        topic.getMarkup().addViewpoint(id, viewpointFilename, snapshotFilename);

## BCF export

To export a BCF and download a zip file, use the exportBCF function.

        let bcfFilename = bcfData.getFilename();
        bcfData.exportBCF(bcfFilename);

## Callbacks

There are two callbacks related to BCF, bcfLoaded and bcfRemoved.

        hwv.setCallbacks({
            bcfLoaded: (id, filename) => {
                // BCF loaded

                //! [BCF_Data]
                let bcfData = hwv.BCFManager.getBCFData(id);
                //! [BCF_Data]
            },
            bcfRemoved: (id) => {
                // BCF removed
            },
        });