--- url: /api/introduction/overview.md --- # Overview BIMData API is a tool to interact with your models stored on BIMData’s servers. Once your account on BIMData Connect is created, you can: * Create and manage clouds * Create and manage projects * Upload IFC, DWG, PDF, plan images * Request data from clouds, projects, and models ![all API features](/images/api/API-features.png) ## APIs BIMData API is composed of five APIs: ### Model API * Upload Models * IFC (2x3 to 4.3) * DWG * DXF * PDF * Point Clouds (las, laz, ply, xyz, e57) * plan images (jpg, png) * Retrieve and update Model’s data in real-time * 3D models throught [glTF format](https://www.khronos.org/gltf/) ### BCF API * Create BCF * Share BCFs with other services * Build a complete automated error management flow * We implement the [BCF 2.1 API](https://github.com/buildingSMART/BCF-API) defined by BuildingSMART ### Collaboration API * Create clouds and projects * Invite users * Manage their rights * Share models, data and documents ### Webhook API * Get informed in real-time of your projects activities * Build automated workflow ### Single Sign-On (SSO) API * Log in on desktop, tablet, mobile * Log in all your BIM Services through BIMData Connect: * Log in through your own SSO (OpenID Connect or SAMLv2) ## General Principles BIMData API follows these general principles: * All API access is over HTTPS * All non-binary data is sent and received as JSON * Errors are sent using standard HTTP response codes (400, 401, 403, 404) * Actions are indicated by HTTP verbs: GET, POST, PUT, PATCH, DELETE ::: warning Calls made over plain HTTP will respond a 302, redirecting to the same URL over HTTPS. ::: The API Endpoint is: ## OpenID Connect BIMData API uses the [OpenID Connect](https://openid.net/connect/) protocol (technically very similar to the OAuth2 protocol). Any [OpenID library](https://openid.net/developers/libraries/) you may find online to help you implement the protocol also works with BIMData API. --- --- url: /api/introduction/quick_start.md --- # Quick start ## Create an application The first step is to create an application. Follow the [guide to create your application](/api/guides/application.html#how-to-create-your-application-on-bimdata-connect) and come back here to follow the next steps once you get a `client_id` and a `client_secret`. ## Get your Access Token Once you have created your app, you have a `client_id` and a `client_secret` that you can exchange for an Access Token through an HTTP call. You will need this Access Token for every call of the bimdata’s API ```bash curl --request POST "https://iam.bimdata.io/auth/realms/bimdata/protocol/openid-connect/token" \ --header "Content-Type: application/x-www-form-urlencoded" \ --data "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET" ``` ::: warning This API call doesn’t accept JSON. Be sure to use application/x-www-form-urlencoded encoding. ::: Once you have the access\_token, you can start doing API calls! ## Create a Cloud Next, let's create a [Cloud](/api/introduction/concepts.html#cloud). A Cloud is a configurable space where projects are created. All projects in this Cloud share the Cloud’s configuration. A Cloud just needs a name: ```bash curl --request POST 'https://api.bimdata.io/cloud' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \ --data '{"name": "My First Cloud"}' ``` You get a Cloud ID in the response. We need it for our next API call. ## Create a Project Once you have your first Cloud, you can create your first [Project](/api/introduction/concepts.html#project). For this tutorial, we will use a special endpoint that creates a demo Project with our demo Model: createDemo. ```bash curl --request POST 'https://api.bimdata.io/cloud/YOUR_CLOUD_ID/create-demo' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' ``` You receive back the created Project (its ID). ## Retrieve a Model Let’s retrieve the Model in the demo project using the getIfcs endpoint! ```bash curl --request GET 'https://api.bimdata.io/cloud/YOUR_CLOUD_ID/project/YOUR_PROJECT_ID/ifc' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' ``` You get an array of the Models in the Project. Keep the IFC ID, you need it in the next call. ## Get properties With the IFC ID we get from the previous call, let’s get the properties of all the doors of the Model. ```bash curl --request GET 'https://api.bimdata.io/cloud/YOUR_CLOUD_ID/project/YOUR_PROJECT_ID/ifc/YOUR_IFC_ID/element/simple?type=IfcDoor' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' ``` And it’s done! :tada: You get all the properties of all the doors of the Model! --- --- url: /api/introduction/concepts.md --- # Concepts ## Cloud (or Space) A cloud is a set of projects sharing the same configuration. Each projects contains your models, your Document Management System and BCFs. Cloud administrators are also projects admin by default, they can see every [user](#user) in their cloud and change everyone’s roles. Cloud [users](#user) can’t see cloud collaborators. This means that a contractor on a project can’t see every collaborators of the company. On BIMData Platform, cloud have been renamed "Space". For compatibility reasons, we did not rename every route on the API. Cloud and Spaces are two names for the same entity. ![BIMData Connect](/images/api/API-cloud.png) ## Project A project is a place where IFC files and documents are stored. IFC files and documents can be uploaded and organized, checkplans are defined. A project is attached to a cloud and a cloud can host an infinite number of projects. A project may contains: * IFCs * Document Management System * BCFs * ... ::: tip Note A BCF is linked to a Project, not a Model. ::: A project member can see all other members, and an admin member can manage the users of the project. ![BIMData Connect](/images/api/API-project.png) ## IFC BIMData API exposes a lot of tools to extract, update and manipulate information from IFC files. The tools are compatible with IFC2x3TC1 and IFC4 Add2. Depending on the options you chose, you can: * Retrieve the model as a 3D GLTF file? * Retrieve elements and properties. * Retrieve the spatial structure. * Retrieve classifications, systems and zones. * Retrieve 2D plans in SVG format. ![BIMData Connect](/images/api/API-ifc.png) ### Upload an IFC To upload an IFC file, you have to [upload a `document`](#upload-a-document). When the BIMData API detects an IFC format (based on the file name ending with `.ifc` or `.ifczip`), it will trigger the IFC process. IFC files are tied to a `document` which represents the actual uploaded file. We use HTTP Compression to speed up the file transfer. HTTP Compression will start as soon as you upload a file. Files are decompressed at the output of the API. There is no size limit to the IFC upload. ### Workflow After being uploaded, the IFC will be processed on our servers. ::: tip Note The process takes from few minutes to an hour depending on the size of the file and the options activated. ::: You can follow the progress on the `status` field: | Status | Name | Description | | :----: | :--------: | :----------------------------------------------------------------------------------------------------------------------------- | | P | Pending | Your IFC will soon be processed. | | I | In process | The process has started. | | C | Completed | The process is complete and you can retrieve data from the API. | | E | Error | The process has failed. It’s more likely to be a problem on our side. An alert is triggered and our team will fix it promptly. | ## Folders & Documents The API exposes a complete set of methods to upload and manage documents. ![BIMData Connect](/images/api/API-folder\&document.png) ### Folders Every project is created with a root folder. It is the starting point to create other folders or upload documents. #### Example Fetching `https://api.bimdata.io/cloud/1/project/1` returns : (with the correct granted access) ```json { "id": 1, "name": "my project", "cloud": {...}, "status": "A", "created_at": "2017-12-01T10:09:54Z", "updated_at": "2018-02-21T17:07:25Z", "root_folder_id": 3, } ``` ::: tip Note * If a folder is created without `parent_id`, it will be placed under the root folder. * You can’t create a loop with folders (a parent being itself or a loop including multiple folders). ::: ### Documents BIMData API allows you to upload any kind of file (IFC, Office, images, binaries, etc.). Those files are named `documents`. You can define in which folder you want to put the file using a `parent_id`. #### Upload a document File upload is one of the few API calls which does not use the `application/json` Content Type. This call uses `x-www-urlencoded` with `form-data`. The name of the file field must be `“file”`, this means that you have to fire multiple calls if you want to upload many files. ::: code-group ```bash [cURL] curl -X POST \ 'https://api.bimdata.io/cloud/1/project/1/document' \ -H 'authorization: Bearer ZeZr9oYxHspA8OdSCo9uftaLaEHX1N' \ -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \ -F name=my_custom_name \ -F file=@/path/to/XXX.pdf ``` ```python [python] import requests url = "https://api.bimdata.io/cloud/1/project/1/document" headers = { 'authorization': 'Bearer ZeZr9oYxHspA8OdSCo9uftaLaEHX1N', } payload = { 'name': 'my_custom_name', } files = {'file': open('/path/to/XXX.pdf', 'rb')} response = requests.request("POST", url, data=payload, files=files, headers=headers) print(response.text) ``` ```javascript [javascript] var fs = require("fs"); var request = require("request"); var options = { method: "POST", url: "https://api.bimdata.io/cloud/1/project/1/document", headers: { authorization: "Bearer ZeZr9oYxHspA8OdSCo9uftaLaEHX1N", "content-type": "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW", }, formData: { name: "my_custom_name", file: { value: 'fs.createReadStream("/path/to/XXX.pdf")', options: { filename: "/path/to/XXX.pdf", contentType: null }, }, }, }; request(options, function(error, response, body) { if (error) throw new Error(error); console.log(body); }); ``` ::: Response example : ```json { "id": 424, "parent": 1, "creator": 134, "project": "1", "name": "my_custom_name", "file_name": "XXX.pdf", "description": null, "file": "https://storage.gra3.cloud.ovh.net/v1/AUTH_b6a1c0b6b7c041d3a71d56f84ce25102/bimdata-staging-dev/cloud_1/project_1/XXX.pdf?temp_url_sig=311d34059bbebc87cd7f37de244bb6b62d114679&temp_url_expires=1527771256", "size": 175780, "created_at": "2018-05-31T12:24:16Z", "updated_at": "2018-05-31T12:24:16Z", "ifc_id": null, "parent_id": 1 } ``` ::: tip Note The filesize is the compressed size and not the actual size of the initial file due to HTTP Compression. ::: #### Download a document You can download files using the URL returned by the API. The URL is valid for 1 hour. ::: code-group ```bash [cURL] curl -X GET \ 'https://storage.gra3.cloud.ovh.net/v1/AUTH_b6a1c0b6b7c041d3a71d56f84ce25102/bimdata-staging-dev/cloud_1/project_1/XXX.pdf?temp_url_sig=311d34059bbebc87cd7f37de244bb6b62d114679&temp_url_expires=1527771256' ``` ```python [python] import requests url = "https://api.bimdata.io/cloud/1/project/1/ifc" querystring = {"status":"C"} headers = { 'Content-Type': "application/json", 'Authorization': "Bearer ZeZr9oYxHspA8OdSCo9uftaLaEHX1N", } response = requests.request("GET", url, headers=headers, params=querystring) print(response.text) ``` ```javascript [javascript] const url = "https://storage.gra3.cloud.ovh.net/v1/AUTH_b6a1c0b6b7c041d3a71d56f84ce25102/bimdata-staging-dev/cloud_1/project_1/XXX.pdf?temp_url_sig=311d34059bbebc87cd7f37de244bb6b62d114679&temp_url_expires=1527771256"; const response = await fetch(url); console.log(await response.text()); ``` ::: ## User User has a Role and belongs to a Project. There are currently 3 roles. * admin * user * guest When checking User’s role through the API, the values are: ### Constant values in API #### Cloud role’s values * admin: 100 * user: 50 #### Project role’s values * admin: 100 * user: 50 * guest: 25 ### User in the Cloud Every User in the Cloud is linked to a Project. #### Admin A cloud Admin can see every other member of the Cloud, can invite other Users as admin in the Cloud. By default, the cloud Admin has admin rights on every project on the Cloud. A cloud admin can ban any User from the Cloud. ::: warning Ban a User exclude the User from all Projects of the Cloud. ::: #### Member A Cloud member is at least a member of one Project. ### User in the Project Any User in any Project can read the user list and see the other users of the project. #### Admin A Project admin can invite Users to the Project. ::: tip Note The User is implicitly invited in the Cloud. ::: The Project admin manages the Roles of the Users: the admin can add, edit or delete Roles. #### Member A member can read and write DMS, model, and BCF. #### Guest A guest can read-only: DMS, models, BCF and write BCF content. --- --- url: /api/guides/application.md --- # Create your application ## How-To create your application on BIMData Connect * Create an account on the website. * After the login step, go to “Manage your application” and click on `Create an application`. * In the form to Create an Application, let’s type “Wonderful app” in the field Name. The other fields can be edited later. * Click on create. ::: tip Your user has no access to what your application created. To grant access to your user see [how-to share data with your app](/api/guides/share_data.html). ::: You created your first application and now have access to 2 new pieces of information: * the Client ID * the Client Secret ### Fields description #### Name You can choose whatever you want. The name is displayed to users when requesting permissions and in their application list. #### Scopes Select scopes your app needs. See the [Scopes documentation](/api/guides/scopes.html) to learn more. #### Redirect URIs The list of authorized redirect URIs. After allowing your app to access their data, users will be redirected to your app on one of these URIs. By default, the redirect URI is: `http://localhost:8080/oidc-callback` ::: warning For security reasons, avoid using local URLs such as localhost, 127.0.0.1, 192.168.x.x, etc. for applications in production. ::: ::: tip See also See also [our documentation about Security](/api/guides/security.html). ::: --- --- url: /api/guides/authentication.md --- # Authentication There are many ways to authenticate to BIMData API. This guide will help you find the most suitable authentication depending on your use-case. ## I want to access the API from a backend First, you need to [create an application](/api/guides/application.html#how-to-create-your-application-on-bimdata-connect). The access type must be set to `Confidential`. Even if base\_url and redirect\_uri won't be used, you must set values. Once created, you'll be given a `client_id`, a `client_secret` and an `ApiKey`. ### Use client\_credentials You can either use `client_id` and `client_secret` and [exchange them with an AccessToken usable on the API as explained here](/api/introduction/quick_start.html#get-your-access-token). * ✅ Pros : Uses the standard OpenID Connect protocol, compatible with many libraries * ❌ Cons : One more HTTP request to do before calling BIMData API ### Use ApiKey Or you can also directly use the ApiKey to call the API: ```bash curl --request POST 'https://api.bimdata.io/cloud' \ --header 'Content-Type: application/json' \ --header 'Authorization: ApiKey YOUR_API_KEY' \ --data '{"name": "My First Cloud"}' ``` * ✅ Pros : Can be directly used without additionnal HTTP request * ❌ Cons : Doesn't have an expire date. If you leak it, the only way to secure your data is to revoke the ApiKey on the [application management page](https://connect.bimdata.io/developers/client/). ## I want to run BIMData Viewer on my website BIMData Viewer needs an access token to load data from the API. As the viewer run in users' browser, your application's token must not be used. A malicious user could retrieve the token and access or delete all your data. To avoid exposing your app token to your users, you can [create a ProjectAccessToken](https://api.bimdata.io/doc#/collaboration/createProjectAccessToken). It allows you to create a temporary token with limited rights. The requests takes two parameters: * `expires_at`, an ISO 8601 date. It is recommended to dynamically create a 12 hours token each time a user opens the Viewer. * `scopes`, an array of token's permissions: * `bcf:read` The token can read BCF data * `bcf:write` The token can create BCF Topics or comment BCFs * `document:read` The token can read document files * `document:write` The token can upload or delete documents * `model:read` The token can open models (IFC, DWG, PDF, plans) * `model:write` The token can create models (Meta Building) and update model properties. To open the viewer, `model:read` is the minimum scope required. ## I want to impersonate users OpenID Connect allows you to impersonate users with your app. These flows are complex and already well documented all around Internet. ## I have another use case There are many possibilities, please contact us: support@bimdata.io --- --- url: /api/guides/share_data.md --- # Access Data between App and Platform Your application don't automatically have access to your user's data. If you want to see your app data on the BIMData Platform, you must invite yourself on a cloud created with your app. ## How can I share data between my app and BIMData Platform? First choose an existing Cloud **created by your application** or create one if there is none (see [createCloud](https://api.bimdata.io/doc#/collaboration/createCloud)): ```bash curl --request POST 'https://api.bimdata.io/cloud' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_APP_ACCESS_TOKEN' \ --data '{"name": "YOUR_CLOUD_NAME"}' ``` You can then invite your user in the Cloud you created with your app (see [inviteCloudUser](https://api.bimdata.io/doc#/collaboration/inviteCloudUser)): ```bash curl --request POST 'https://api.bimdata.io/cloud/YOUR_CLOUD_ID/invitation' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_APP_ACCESS_TOKEN' \ --data '{"email": "YOUR_EMAIL_ADDRESS", "redirect_uri": "https://platform.bimdata.io/invitations"}' ``` ::: tip Check if the Platform URL (`redirect_uri`) is the correct one for your Platform access. ::: You will receive an email asking you to accept the invitation. Once accepted, you can open the Platform and see the Cloud created by the application. Now every data created in the shared Cloud will be accessible by both the application and the user (via the Platform and API). --- --- url: /api/guides/scopes.md --- # Scopes A scope is an important concept using the API. Using scopes is a way to handle the credentials of your application. ## What’s a scope? A scope is a limitation to the data on a given resource. A scope is described by two words: the resource and the limitation, i.e. model:write Access Token is validated by the BIMData Connect authentication service and the scopes are attached to an Access Token. ::: tip Note About scopes Scopes provide a way to limit the amount of access that is granted to an access token. For example, an access token issued to a client app may be granted READ and WRITE access to protected resources, or just READ access. You can implement your APIs to enforce any scope or combination of scopes you wish. So, if a client receives a token that has READ scope, and it tries to call an API endpoint that requires WRITE access, the call will fail. source : ::: Your application’s user sees the scopes you registered as granted for your application and gives consent to the usage of their data based on this information. Set only the scopes you need. The limitations are: * Read: access to the data in read-only mode * Write: edit the data * Manage: link the elements, create/delete the links between elements ## List of scopes available * `bcf:read`: Can do GET requests on BCF routes * `bcf:write`: Can do POST, PATCH, DELETE requests on BCF routes * `cloud:read`: Can list cloud users * `cloud:manage`: Can do POST, PATCH, DELETE on cloud routes and change users permissions * `document:read`: Can do GET requests on DMS routes * `document:write`: Can do POST, PATCH, DELETE requests on DMS routes * `model:read`: Can do GET requests on model routes * `model:write`: Can do POST, PATCH, DELETE requests on model routes * `org:manage`: Can invite users, manage DMS tags, users groups, create projects and manage [ProjectAccessTokens](/api/guides/authentication.html#i-want-to-run-bimdata-viewer-on-my-website) * `user:read`: Can go GET requests on current user (works only with user impersonation) * `user:write`: Can accept invitation requets (works only with user impersonation) * `webhook:manage`: Can call webhook routes ## How to set the scopes of your application The resources and possible scopes are pre-defined. You can set a scope by typing scopes in a list in the form field Scopes. Each line contains only one scope. In the Manage your application screen, you can add, edit or remove from the Scopes list the granted access. --- --- url: /api/guides/security.md --- # Security We treat your data with care and apply state-of-the-art security, following the OWASP recommendations. Here are answers on how we keep your data secure. ## Where is my BIMData hosted? Your BIMData data and BIMData.io infrastructure are hosted in France by OVH. Files (DMS and IFCs) are stored with [OVH Object Storage](https://www.ovh.com/fr/public-cloud/object-storage/). ## How often are backups made? Your data are saved on a daily basis. ## HTTPS BIMData’s HTTPS implementation is graded A+ on SSL Labs website. ![SSL report](/images/api/API-ssl-report.png) --- --- url: /api/guides/webhooks.md --- # Webhooks Webhooks let you build automation around BIMData API. Your app can subscribe to certain events on BIMData API and when one event is triggered, we’ll send an HTTP POST payload to the configured URL. Webhooks can be configured on a cloud. All projects of this cloud emits events. ## Events Each event corresponds to a set of actions. | Event | Triggered when… | | ----------------------- | ----------------------------------------------------- | | bcf.topic.creation | a BCF Topic is created | | bcf.topic.update | a BCF Topic is updated | | bcf.topic.deletion | a BCF Topic is deleted | | bcf.comment.creation | a BCF comment is created | | bcf.comment.update | a BCF comment is updated | | bcf.comment.deletion | a BCF comment is deleted | | bcf.topic.full.creation | a BCF Topic is created, send a FullTopic object | | bcf.topic.full.update | a BCF Topic is updated, send a FullTopic object | | ifc.process\_update | the status of an IFC is changed (when it’s processed) | | project.update | a project is updated | | project.creation | a project is created | | visa.creation | a validation on a document is created | | visa.update | a validation is updated | | visa.validation.add | a user responds to a validation demand | | visa.validation.remove | a user delete a response to a validation demand | | document.creation | a document is uploaded | | document.update | a document is updated | If you need more webhooks, please contact us at . ## Payload Every payload send by BIMData API looks like: ```json { "event_name": event_name, "cloud_id": cloud_id, "data": payload } ``` Where: * `event_name` is the name of the triggered event. * `cloud_id` is the cloud that triggered the event. * `payload` is the content of the event. It mostly uses the same serialization than the API Models. ## Signature To verify if the Webhook is sent from BIMData API and not from a malicious user, we sign out HTTP POST requests. The signature is an HMAC hex digest generated using the `sha256` hash function and the secret as the HMAC key signing the body of the request. This signature is sent over the `x-bimdata-signature` HTTP Header. Here is a python example to check the signature: ```python import hmac import hashlib def is_signed(request): req_signature = request.META.get("HTTP_X_BIMDATA_SIGNATURE") if not req_signature: return False body_signature = hmac.new( WEBHOOK_SECRET.encode(), request.body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(req_signature, body_signature) ``` ## Authorizations API routes to manage Webhooks require the webhook:manage scope. As these calls don’t involve a user, the app needs to be authorized itself on the Cloud and can’t behave as a User. --- --- url: /api/external_libraries.md --- # External libraries We’re currently maintaining two external libraries auto-generated from [our OpenAPI specification file](https://api.bimdata.io/doc#/) using [openapi-generator](https://github.com/OpenAPITools/openapi-generator). ## Typescript * Install via NPM: ```bash npm install @bimdata/typescript-fetch-api-client --save ``` * URL: * Repository: **Note:** the *typescript-fetch-api-client* can be used in JavaScript & TypeScript codebase the same way. ## Python * URL: * Repository: ::: warning IMPORTANT Requirements: Python 2.7 and 3.4+ ::: ## Generate your own We offer our OpenAPI file to let you use it. You can use one of those generators to get a client in your favorite programmation language: 1. Install OpenAPI Generator following [their documentation](https://openapi-generator.tech/docs/installation/). 2. With a local version (or not) of our OpenAPI file, generate your client with `openapi-generator generate` options depending on your install. 3. Add your new API client in your software stack, everything is in the README generated along with your client. 4. Use it and check [our API Reference documentation](/api/reference.html). --- --- url: /api/reference.md --- # Reference --- --- url: /api/viewer-reference.md --- # Viewer Reference --- --- url: /api/support.md --- # Support ## Where do I go if I have more questions? Please contact us by email: support@bimdata.io --- --- url: /viewer.md --- # Getting started The BIMData Viewer displays models of many formats in a web page. Each format is handled by its own native built-in viewer, with **display**, **navigation**, **measurement** and **annotation** available on all of them. This guide takes you from an empty file to a model running in your browser. No account needed for the first step. Count about 15 minutes for the whole page. ## See it running Create an `index.html` file, paste this, and open it. The identifiers below point to our public demo model, so it works as-is. ::: code-group ```html [CDN] BIMDataViewer - Quick start
``` ```html [NPM] BIMDataViewer - Quick start
``` ::: That is the entire integration: an import, four identifiers, and a `mount()`. ::: warning Double-clicking the file will not work ES modules are blocked on the `file://` protocol, so opening the file directly gives you a blank page and a CORS error in the console. Serve it over HTTP instead, with the *Live Server* extension in VS Code or `npx serve` in the folder. ::: ::: tip Blank page, no error? The viewer fills its parent element. If the container has no height, nothing renders. That is what the `height: 100vh` wrapper above is for. ::: ::: tip Pin the version in production `@latest` is convenient while you experiment, but it means your page changes whenever we ship a release. Pin an explicit version once you go live. ::: ## Use your own models The demo identifiers are read-only and shared. To display your own data you need your own `cloudId`, `projectId`, `modelIds` and `accessToken`. ### 1. Create an application An **application** is your developer identity with BIMData, and it is what gives you API credentials. 1. Go to [connect.bimdata.io](https://connect.bimdata.io) and sign in. 2. Open **Manage your application** → **Create an application**. 3. Set the access type to **`Confidential`**. 4. `base_url` and `redirect_uri` are required even though you will not use them here. `http://localhost:8080/oidc-callback` will do. You get a `client_id`, a `client_secret` and an `ApiKey`. See [Create your application](/api/guides/application) for details. ::: danger Keep these on your server These credentials grant full access to your data. They belong in your backend, never in a web page. Step 3 covers what to put in the browser instead. ::: ### 2. Create a cloud, a project and a model The fastest route is our demo endpoint, which creates a project with a model already in it, with no upload and no processing wait. ```bash # Create a cloud curl --request POST 'https://api.bimdata.io/cloud' \ --header 'Content-Type: application/json' \ --header 'Authorization: ApiKey YOUR_API_KEY' \ --data '{"name": "My First Cloud"}' # Create a demo project inside it curl --request POST 'https://api.bimdata.io/cloud/CLOUD_ID/create-demo' \ --header 'Content-Type: application/json' \ --header 'Authorization: ApiKey YOUR_API_KEY' # List its models curl --request GET 'https://api.bimdata.io/cloud/CLOUD_ID/project/PROJECT_ID/model' \ --header 'Authorization: ApiKey YOUR_API_KEY' ``` Each response gives you the identifier for the next call. You can also create a project and upload your own IFC from the [BIMData Platform](https://platform.bimdata.io/), then read the identifiers from the URL. ::: warning A project created by hand is not visible to your app Your application does not automatically have access to your user's data, and the reverse is also true. To connect the two, invite yourself into a cloud created by your app. See [Share data between App and Platform](/api/guides/share_data). ::: ### 3. Create a token for the browser Whatever you write in the page is readable by your users. So the token you pass to the viewer must not be your application's `ApiKey`, which can read *and delete* everything you own. Use a **ProjectAccessToken** instead: temporary, read-only, limited to one project. ```bash curl --request POST 'https://api.bimdata.io/cloud/CLOUD_ID/project/PROJECT_ID/access-token' \ --header 'Content-Type: application/json' \ --header 'Authorization: ApiKey YOUR_API_KEY' \ --data '{ "expires_at": "2026-12-31T23:59:00Z", "scopes": ["model:read"] }' ``` `model:read` opens models and is the minimum scope the viewer requires. See [Scopes](/api/guides/scopes) for the full list, and [Authentication](/api/guides/authentication) for other flows. ::: tip In production Generate a fresh 12-hour token from your backend each time a user opens the viewer. Your `ApiKey` stays on your server, and the browser only ever holds a short-lived, narrowly scoped token. ::: Drop your four values into the snippet above, and you are running on your own data. ## Make it yours The default interface carries BIMData branding. One configuration block removes it and lets the viewer blend into your own product: ```js const bimdataViewer = makeBIMDataViewer({ api: { /* ... */ }, locale: "fr", ui: { header: false, bimdataLogo: false, version: false, style: { backgroundColor: "F5F5F5" }, }, }); ``` Native plugins can be turned off entirely with `plugins: false`, or one by one: ```js plugins: { bcf: false, measure3d: false, section: false, viewer3d: { navCube: false, help: false }, } ``` Full list of options: [makeBIMDataViewer](/viewer/reference/makeBIMDataViewer) and [Native Plugins](/viewer/reference/native_plugins). ## Going further **Other formats.** Everything above works the same way for plans, DWG, DXF and point clouds. Pass the relevant model ID and the matching viewer takes over. A project can hold several formats at once, and you can display them side by side. **Rearrange the workspace.** Choose which panels appear where, split the window, build your own layout. See [User Interface](/viewer/guide/). **Add your own features.** The viewer exposes a JavaScript plugin API built on [Vue 3](https://vuejs.org/). You don't need to master Vue.js to develop a plugin, and you can still update the DOM with jQuery if you like. Start with [Plugins](/viewer/guide/plugins), or clone the [Viewer SDK](/viewer/viewer_sdk) for a pre-configured development environment. **Mobile and offline.** The viewer supports touch devices ([Mobile](/viewer/mobile)) and disconnected use ([Offline Mode](/viewer/reference/offline_mode)). The viewer is bound to the [BIMData API](/api/introduction/overview), which you can use to upload and manage models programmatically. --- --- url: /viewer/guide.md --- # Graphical User Interface This guide shows how to quickly customize the existing BIMDataViewer UI. ## Header & Windows As the name suggests, the [**Header**](../reference/header) is located at the top of the BIMDataViewer. [**Windows**](../reference/window) share the remaining space. Different layouts can be created, with or without [**Header**](../reference/header), and with as many [**Windows**](../reference/window) as required. It is possible to completly remove the [**Header**](../reference/header) using the `ui` property of the [`makeBIMDataViewer`](../reference/makeBIMDataViewer) configuration parameter: ```js const bimdataViewer = makeBIMDataViewer({ ui: { header: false, }, }); ``` To display the desire layout, use the second parameter of the [`bimdataViewer.mount`](../reference/mount) method: ```js const bimdataViewer = makeBIMDataViewer({ ui: { header: false, }, }); const layout = { ratios: [70, 30], children: [ "3d", { direction: "column", ratios: [40, 60], children: [ "2d", "properties" ], }, ], }; bimdataViewer.mount("#viewer", layout); ``` And you get the following layout: ## BIMData Logo and Viewer Version By default, the BIMData Logo and the Viewer version are displayed on the UI. They may change location depending on the number of [**Windows**](../reference/window). If only one [**Window**](../reference/window) without [**Header**](../reference/header), they are displayed on the bottom left corner of the UI. Else, they are displayed on the right of the [**Header**](../reference/header). They can be removed using the `ui` property of the [`makeBIMDataViewer`](../reference/makeBIMDataViewer) configuration parameter: ```js const bimdataViewer = makeBIMDataViewer({ ui: { bimdataLogo: false, version: false, }, }); ``` ## Colors 🎨 You can change the colors of the viewer and the BIMData Design System components. All customizable colors are defined in the [BIMData Design System documentation](https://design.bimdata.io/guidelines-utilities/colors) You can overide any color you want to change using a value as a `string` representing any valid CSS value ("red", "#FF0000", "rgb(255, 0, 0)", etc). ```javascript const bimdataViewer = makeBIMDataViewer({ ui: { style: { backgroundColor: "", colorPrimary: "", colorPrimaryLighter: "", colorPrimaryLight: "", colorPrimaryDark: "", colorSecondary: "", colorSecondaryLight: "", colorSecondaryLighter: "", colorSecondaryDark: "", colorSilverLight: "", colorSilver: "", colorSilverDark: "", colorGraniteLight: "", colorGranite: "", colorSuccess: "", colorSuccessLight: "", colorSuccessLighter: "", colorSuccessDark: "", colorWarning: "", colorWarningLight: "", colorWarningLighter: "", colorWarningDark: "", colorHigh: "", colorHighLight: "", colorHighLighter: "", colorHighDark: "", colorText: "", headerHeight: "", }, }, }); ``` --- --- url: /viewer/guide/plugins.md --- # Plugins In the previous part, we covers the differen UI elements used by the BIMData viewer. In this part, we will cover the main aspect you need to know to manipulate the BIMData viewer environment using [**Plugins**](../reference/plugin.html). ## Plugin types Firstly, we need to differentiate between these three classes: [**Plugin**](../reference/plugin.html), [**PluginInstance**](../reference/plugin.html#plugin-instance) and [**PluginComponentInstance**](../reference/plugin.html#plugin-component-instance). To understand the difference, we have to keep in mind that a [**Plugin**](../reference/plugin.html) is added to a [**Window**](../reference/window.html) as a child. This [**Window**](../reference/window.html) can be open several times on the same BIMDataViewer instance, and the same plugin can also be added to different [**Windows**](../reference/window.html). For this reasons, there is a difference between the [**Plugin**](../reference/plugin.html) and its instances across all displayed [**Windows**](../reference/window.html). ```js const myPlugin = bimdataViewer.registerPlugin({ name: "myPlugin", component: { template: "
My plugin component template
" created() { this; // this represents the plugin component instance. this.$plugin; // global API to get the corresponding plugin instance. } } }); ``` In this example, myPlugin is a [**Plugin**](../reference/plugin.html). `this.$plugin` allows to get the [**PluginInstance**](../reference/plugin.html#plugin-instance), while `this` it the instance of the [ Vue.js 3](https://vuejs.org/) component, also named [**PluginComponentInstance**](../reference/plugin.html#plugin-component-instance) in the context of the BIMDataViewer. Plugins don't necessarily need to be represented (with a `component`), and it can sometimes be useful to register a plugin that will only act as a function for manipulating the viewer. The corresponding API is [`startupScript`](../reference/plugin.html#startupscript). ```js{3} const myPlugin = bimdataViewer.registerPlugin({ name: "myPlugin", startupScript($viewer) { // add logic here }, }); ``` ## Plugin UI [**Plugins**](../reference/plugin.html) are [**Window**](../reference/window.html) children and can be displayed in different ways. ### Default representation The default representation is on the [**Window**](../reference/window.html) area. ```js const myPlugin = bimdataViewer.registerPlugin({ name: "myPlugin", component: { template: "
My plugin component template
" } }); ``` ### Plugin as button [**Plugins**](../reference/plugin.html) can also be displayed as a side button, on the left or right of the [**Windows**](../reference/window.html). By clicking on it, the [**Plugin**](../reference/plugin.html) opens and its content is displayed in 3 different ways: * **simple** : plugin content displayed close to its corresponding button, on a small panel. ```js{8} const myPlugin = bimdataViewer.registerPlugin({ name: "myPlugin", component: { template: "
My plugin component template
" }, button: { position: "left", content: "simple" } }); ``` * **panel** : plugin content displayed on the whole [**Window**](../reference/window.html) height. ```js{8} const myPlugin = bimdataViewer.registerPlugin({ name: "myPlugin", component: { template: "
My plugin component template
" }, button: { position: "right", content: "panel" } }); ``` * **free** : plugin content displayed on the side of the button, without any layout. Its size is determined by its content. ```js{8} const myPlugin = bimdataViewer.registerPlugin({ name: "myPlugin", component: { template: "
My plugin component template
" }, button: { position: "right", content: "free" } }); ``` :::tip Checkout [the example about the GUI Layout](../examples/gui_layout.html) for practical application. ::: ### Context Menu & Keyboard Shortcuts The [**Context Menu**](../reference/context_menu.html) and the [**Keyobard Shortcuts**](../reference/keyboard_shortcuts.html) can be personalized using [**Plugins**](../reference/plugin.html). Both of them take into account the context of the request. In this way, it is possible to launch a specific action in a particular [**Window**](../reference/window.html) when a keyboard key is pressed while the mouse is hovering that [**Window**](../reference/window.html). In the same way, it is possible to add to the [**Context Menu**](../reference/context_menu.html) only a list of commands specific to the place where the click was made. The [**Context Menu**](../reference/context_menu.html) is usually displayed while right clicking on the screen. Here is an example of a shortcut and a context menu command: ```js const MyPlugin = { name: "context-menu-and-keyboard-shortcut", startupScript($viewer) { $viewer.globalContext.registerShortcut({ name: "message", key: "L", execute: () => { if ($viewer.state.selectedObjects.length > 0) { console.log($viewer.state.selectedObjects) } } }); $viewer.contextMenu.registerCommand({ label: "Log selection", execute: () => console.log($viewer.state.selectedObjects), predicate: () => $viewer.state.selectedObjects.length > 0, picto: "L" }); }, }; ``` ## $viewer [`$viewer`](../reference/$viewer.html) is the main entry point for a plugin to interact with other elements of the BIMData viewer. It is globally available and can be accessed directly on the plugin component instance using [`this.$viewer`](../reference/$viewer.html). ```js const myPluginComponent = { created() { const $viewer = this.$viewer; // ... } } ``` Via [`$viewer`](../reference/$viewer.html), you can access important properties like: * [`localContext`](../reference/local_context.html), used to manipulate the parent [**Window**](../reference/window.html) UI and state. * [`globalContext`](../reference/global_context.html), used to manipulate the global UI. * [`api`](../reference/$viewer.html#api), used to do all the things related to the connection with the [BIMData API](/api/introduction/overview.html). * [`state`](../reference/state.html), used to manipulate the BIM object states, the annotations and listen to BIM object state changes. * [`i18n`](../reference/$viewer.html#i18n), used to do internationalization. Notice that [`$viewer`](../reference/$viewer.html) is also available as first argument of the [`startupScript`](../reference/plugin.html#startupscript) method and can be [injected](https://vuejs.org/api/composition-api-dependency-injection.html#inject) to be used on [component setup method](https://vuejs.org/api/composition-api-setup.html#composition-api-setup). ```js import { inject } from "vue"; const myPluginComponent = { setup() { const $viewer = inject("$viewer"); // ... } } const myPlugin = { name: "my-plugin", component: myPluginComponent, startupScript($viewer) { // TODO } } ``` ## Global & Local Contexts The [`globalContext`](../reference/global_context.html) and the [`localContext`](../reference/local_context.html) are two essential entities of the BIMDataViewer API. ### Global Context The [`globalContext`](../reference/global_context.html) is the entity to interact with the UI at a global level. It has API to manipulate the [**Window**](../reference/window.html) layout like `open`, `swap`, `close`... It is also the access point for the viewer [`header` API](../reference/header.html): `globalContext.header`. It is also used to register [keyboard shortcuts](../reference/keyboard_shortcuts.html) globally, display [loading spinner](../reference/$viewer.html#spinners) or display [modal](../reference/$viewer.html#modals) on the entire viewer view. It can be also considered as the [`localContexts`](../reference/local_context.html) parent. Indeed, it has API to get all viewer's [`localContexts`](../reference/local_context.html), [**PluginInstances**](../reference/plugin.html#plugin-instance), [**PluginComponentInstances**](../reference/plugin.html#plugin-component-instance) (using `globalContext.plugins` API)... ### Local Context The [`localContext`](../reference/local_context.html) is the entity to interact with the [**Window**](../reference/window.html) UI. It is used to register [keyboard shortcuts](../reference/keyboard_shortcuts.html) locally, display [loading spinner](../reference/$viewer.html#spinners) or display [modal](../reference/$viewer.html#modals) bounded on the [**Window**](../reference/window.html) view. It also owns the [**Window**](../reference/window.html) state (loadedModels, modelTypes, selectedStorey...). Notice that the [`$viewer.localContext`](../reference/local_context.html) property is context dependent. It returns the corresponding [`localContext`](../reference/local_context.html) of where it is called. In another hand, [`$viewer.globalContext`](../reference/global_context.html) is always the same wherever it is called. #### Difference from Window [`localContext`](../reference/local_context.html) and [**Window**](../reference/window.html) can be mistaken as a single entity, but the main difference is that you can load different [**Window**](../reference/window.html) using the same localContext. The [**Windows**](../reference/window.html) have to be registered first, and then can be loaded using the [`bimdataViewer.mount`](../reference/mount.html) second argument, or the [`localContext.loadWindow`](../reference/local_context.html) method. The [`localContext`](../reference/local_context.html) is like the *host* that can accept different [**Window**](../reference/window.html) to be loaded in it. #### UI bounds A good image to see the difference between the bounds of the [`localContext`](../reference/local_context.html) and the [`globalContext`](../reference/global_context.html) is the spinner which is displayed when the `globalContext.loadingProcessStart()` or `localContext.loadingProcessStart()` is called : :::tip [See the global and local context plugins example.](../examples/context_plugins.html) ::: ## Design System 🧑‍🎨 The [BIMData design system](https://design.bimdata.io/) is globally available on the viewer and can be used to quickly style the [**Plugin Components**](../reference/plugin.html#plugin-component-instance). In the following example, the [`BIMDataButton` ](https://design.bimdata.io/components/buttons) is not imported as it is globally available: ```js{2} const myPluginComponent = { template: "Click !", methods: { onClick() { console.log("clicked !"); } } } ``` --- --- url: /viewer/examples/gui_layout.md --- # GUI Layout This example shows how to create a complex UI layout with 3 windows and 4 plugins. 3 plugins as button and one with default representation, displayed on the window area. The plugins are registered first with different display options. Then the window, with registered plugins as children. Then the layout reference the registered window names. ### Demo ### HTML ```html BIMDataViewer
``` --- --- url: /viewer/examples/layout_manipulation.md --- # Layout Manipulation The [Global Context API](../reference/global_context.md) offers a way to perform layout manipulation dynamically (after viewer instanciation) through `open()`, `close()` and `swap()` methods. The following example illustrate how these methods can be used in simple plugins. **Split layout plugin:** when clicked, this button plugin will modify the layout as follow: * If both a 3D and 2D viewers are already open then close current window (local context). * Else if the current window is a 3D viewer then split the layout and open a new 2D viewer beside it. * Else if the current window is a 2D viewer then split the layout and open a new 3D viewer beside it. **Swap layout plugin:** swap the content of the first two windows in the layout. ### Demo ### Code **Plugin definitions:** ```js // file: split-layout.plugin.js export default { name: "splitLayoutPlugin", addToWindows: ["3d", "2d"], i18n: { en: { tooltip: "" }, }, button: { position: "right", tooltip: "splitLayoutPlugin.tooltip", icon: { component: "BIMDataIconWindowRight", options: { size: "m" }, }, }, component: { onOpen() { if ( this.$viewer.globalContext.getLocalContexts("3d").length > 0 && this.$viewer.globalContext.getLocalContexts("2d").length > 0 ) { // If both 3D and 2D viewers are open the close current window this.$viewer.localContext.close(); } else { // Else if this is a 3D (resp. 2D) viewer window then open a 2D (resp. 3D) window beside it const windowName = this.$viewer.localContext.window.name; const modelIds = this.$viewer.localContext.loadedModelIds; const split = windowToOpen => { this.$viewer.globalContext.open({ ratio: 50, direction: "row", insertAfter: true, windowName: windowToOpen, windowState: { modelIds } }); }; if (windowName === "3d") split("2d"); if (windowName === "2d") split("3d"); } setTimeout(() => this.$close()); }, } }; ``` ```js // file: swap-layout.plugin.js export default { name: "swapLayoutPlugin", addToWindows: ["3d", "2d"], i18n: { en: { tooltip: "" }, }, button: { position: "right", tooltip: "swapLayoutPlugin.tooltip", icon: { component: "BIMDataIconSwap", options: { size: "m" }, }, }, component: { onOpen() { // Get the first two contexts in the local context list const [ctx1, ctx2] = this.$viewer.globalContext.localContexts; if (ctx2) this.$viewer.globalContext.swap(ctx1.id, ctx2.id); setTimeout(() => this.$close()); }, } }; ``` **Viewer instanciation:** ```js // file: main.js import makeBIMDataViewer from "@bimdata/viewer"; import SplitLayoutPlugin from "./split-layout.plugin.js"; import SwapLayoutPlugin from "./swap-layout.plugin.js"; const viewer = makeBIMDataViewer({ api: { // ... }, }); viewer.registerPlugin(SplitLayoutPlugin); viewer.registerPlugin(SwapLayoutPlugin); viewer.mount(viewerId, "3d"); ``` --- --- url: /viewer/examples/context_plugins.md --- # Global and Local Context Plugins This example shows how to communicate from different plugins across the BIMDataViewer window layout using the `globalContext` and the `localContext`. ### Demo ### HTML ```html BIMDataViewer
``` :::tip Notice that [PluginInstances](../reference/plugin.html#plugin-instance) and [PluginComponentInstances](../reference/plugin.html#plugin-component-instance) (the entities returned by `localContext.plugins` or `globalContext.plugins`) do not use the same API to open the plugin. Also, `globalContext.pluginInstances` return an Array of [PluginInstances](../reference/plugin.html#plugin-instance) because the same plugin can be instantiated many times on different [Windows](../reference/window.html). ::: --- --- url: /viewer/examples/ifc_annotations.md --- # IFC Annotations Here is an example of an IFC annotation plugin that demonstrate the use of the annotation API to create synchronized annotations between 2D and 3D. ### Demo ### Code **Plugin definition:** ```js // file: ifc-annotations.plugin.js import IfcAnnotationsPlugin from "./IfcAnnotationsPlugin.js"; export default { name: "ifcAnnotations", component: IfcAnnotationsPlugin, addToWindows: ["3d", "2d"], button: { position: "right", keepOpen: true, tooltip: "Annotations", icon: { component: "BIMDataIconLocation", options: { size: "m" }, }, }, }; ``` **Plugin component:** ```js // file: IfcAnnotationsPlugin.js import IfcAnnotation from "./IfcAnnotation.js"; export default { render() { return null; }, onOpen() { const state = this.$viewer.state; const context = this.$viewer.localContext; // Register an annotation callback to perform the desired action on click context.startAnnotationMode(({ x, y, z }) => { // Create a synchronized annotation in the state state.addAnnotation({ component: IfcAnnotation, x, y, z, }); // Unregister the callback when finished context.stopAnnotationMode(); this.$close(); }); }, }; ``` **Annotation component and styles:** ```js // file: IfcAnnotation.js export default { template: `
{{ annotation.id }}
`, props: { // An `annotation` prop is passed to your component // so we can interact directly with the annotation object annotation: Object, }, methods: { remove() { // `this.$viewer` is also accessible in your annotation component this.$viewer.state.removeAnnotation(this.annotation); }, }, }; ``` ```css .ifc-annotation { /* This is a trick to place the marker under the cursor */ transform: translate(-50%, -50%); width: 32px; height: 32px; border-radius: 50%; border: 1px solid var(--color-primary); background-color: var(--color-high); font-weight: bold; display: flex; justify-content: center; align-items: center; user-select: none; cursor: grab; } ``` **Viewer instanciation:** ```js // file: main.js import makeBIMDataViewer from "@bimdata/viewer"; import IfcAnnotationsPlugin from "./ifc-annotations.plugin.js"; const viewer = makeBIMDataViewer({ api: { // ... }, }); viewer.registerPlugin(IfcAnnotationsPlugin); viewer.mount("#app", { ratios: [50, 50], children: ["2d", "3d"] }); ``` --- --- url: /viewer/examples/plan_annotations.md --- # Plan Annotations This example will show you how to create a plugin that use the annotation API to create, edit and delete annotations on a PDF plan. The plugin will be a button that you can click to add an annotation anywhere on a plan. Once the annotation is added you can drag & drop it to change its position. You can also delete it by double clicking it. ### Demo ### Setup First lets setup a viewer with a simple configuration and register a custom plugin: ```js // file: main.js import makeBIMDataViewer from "@bimdata/viewer"; import PlanAnnotationsPlugin from "./plan-annotations-plugin.js"; const viewer = makeBIMDataViewer({ api: { // ... }, }); viewer.registerPlugin(PlanAnnotationsPlugin); viewer.mount("#app", "plan"); ``` ### Create the plugin definition Next, we'll define our plugin configuration: ```js // file: plan-annotations-plugin.js import PlanAnnotationsPluginComponent from "./PlanAnnotationsPlugin.js"; export default { name: "planAnnotations", component: PlanAnnotationsPluginComponent, addToWindows: ["plan"], button: { position: "right", keepOpen: true, tooltip: "Annotations", icon: { component: "BIMDataIconLocation", options: { size: "m" }, }, }, }; ``` ### Create plugin components Then we'll create the plugin component that will hold the logic: ```js // file: PdfAnnotationsPlugin.js import PlanAnnotation from "./PlanAnnotation.vue"; export default { render() { return null; }, onOpen() { const state = this.$viewer.state; const context = this.$viewer.localContext; // Register an annotation callback to perform the desired action on click context.startAnnotationMode(({ x, y }) => { // Create a synchronized annotation in the state state.addAnnotation({ component: PlanAnnotation, x, y, z: 0, }); // Unregister the callback when finished context.stopAnnotationMode(); this.$close(); }); }, }; ``` Finally we'll add the component that will materialize the PDF annotation on the plan: ```js // file: PlanAnnotation.js export default { template: `
{{ annotation.id }}
`, props: { // An `annotation` prop is passed to your component // so we can interact directly with the annotation object annotation: Object, }, methods: { remove() { // `this.$viewer` is also accessible in your annotation component this.$viewer.state.removeAnnotation(this.annotation); }, }, }; ``` You can also add the following rules to your page stylesheet: ```css .plan-annotation { /* This is a trick to place the marker under the cursor */ transform: translate(-50%, -50%); width: 32px; height: 32px; border-radius: 50%; border: 1px solid var(--color-primary); background-color: var(--color-high); font-weight: bold; display: flex; justify-content: center; align-items: center; user-select: none; cursor: grab; } ``` Notice the use of [BIMData css variables](https://design.bimdata.io/guidelines-utilities/variables) like `--color-primary`. It allows to stay in sync with the global theme and to track colors that may have been changed [when the viewer was initialized](../guide/#colors-🎨). --- --- url: /viewer/examples/global_components.md --- # Global Components This example shows how to use the BIMDataViewer [global components](../reference/global_components.html). ### Demo ### HTML ```html BIMDataViewer
``` --- --- url: /viewer/examples/partial_loading.md --- # Partial loading Thanks to the `api.onlyLoadUuids` configuration it is possible to filter elements before they are loaded in the viewer. This can be very useful when you have large IFC files with many elements but you only want to work an a subset of them (e.g. a single storey). It helps avoid performance issues and focus on specific part of the model. You can specify a list of element UUIDs to load for each model in the following way: ```js makeBIMDataViewer({ api: { // ... modelIds: [101, 102, 103], onlyLoadUuids: { 101: ["uuid-1", "uuid-2", "uuid-3"], 102: ["uuid-1", "uuid-00", "abcdef"], } } }); ``` If no UUIDs are specified for a given model then all elements are loaded (default behavior). ::: warning Make sure the UUIDs you're providing in `onlyLoadUuids` are correct (i.e. they match existing elements in the model). Providing wrong UUIDs can result in an empty viewer where all elements have been filtered. If nothing is displayed when you use `onlyLoadUuids` then check that your UUIDs are correct. ::: ### Demo ### Code ```js // file: main.js import makeBIMDataViewer from "@bimdata/viewer"; const viewer = makeBIMDataViewer({ api: { cloudId: 123, projectId: 456, modelIds: [123456] onlyLoadUuids: { 123456: [""] } }, // ... }); viewer.mount("#app", { ratios: [40, 60], children: ["structure", "3d"] }); ``` --- --- url: /viewer/reference/window.md --- # Window ## Registration A window is composed of [plugins](./plugin.md) and can be registered using two ways : * The first and most commonly used method is to add a window configuration object when registering a plugin. * The second is by registering it directly on the BIMData viewer object. ```javascript const bimdataViewer = makeBIMDataViewer(/* {...} */); const windowConfigurationObject = { name: "windowName", plugins: [ /* plugins */ ], }; // first way: register via plugin bimdataViewer.registerPlugin({ /* plugin specific fields */ window: windowConfigurationObject, }); // second way: register directly bimdataViewer.registerWindow(windowConfigurationObject); ``` ## Loading A window can be loaded using the `localContext.loadWindow(windowName)` method. Notice that a `string` must be passed to this method, meaning that the corresponding window must be registered before. Once loaded, the window can be accessed directly via `localContext.window`. ## Window API Window and window configuration objects have the same API: | Property | Description | | :----------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- | | `name`: `string` | **Required** The name of the window. Must be unique. | | `label`: `string` | The label that is displayed to the user. Can be a key to be translated like : "viewer3d.window\_label". | | `plugins`: `Array` | An array of plugins name which will be added to the window. | | `header: boolean` | *Default* to `true`. Defines if the Header must be shown when only this window is displayed. | | `icon.imgUri`: `string` | A string that is injected into an `img` HTML element as a src. This image will be displayed while selecting the window on the window selector. | | `modelTypes: Array` | The model types handled by this window. Model types are "IFC", "DWG", "PDF", "JPEG", "PNG", "METABUILDING" and "POINT\_CLOUD". | | `multiModel: boolean` | *Default* to `true`. Defines if the window can handle more than one model at a time. | | `noModel: boolean` | *Default* to `false`. Defines if the window handle models. | | `logoAndVersion: boolean` | *Default* to `false`. Defines if the BIMData logo and version are shown on the bottom left corner when only this window is displayed. | | `defaultWindow: boolean` | *Default* to `false`. Defines this window as the viewer default window. The default window is displayed when no window are loaded on a localContext. | | `displayedInWindowSelector: boolean` | *Default* to `true`. Defines if this window is shown on the window selector plugin. (the UI list of all available window ) | --- --- url: /viewer/reference/plugin.md --- # Plugin The viewer is shipped with native plugins but others can be added to add new features and more possibilities. A plugin is mainly either a [Vuejs 3.x component](https://vuejs.org/guide/essentials/component-basics.html) or a simple function that is run once when the viewer is mounted into the [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model). ## Registration and Plugin API A plugin is added to the viewer by registering it : ```javascript import makeBIMDataViewer from "@bimdata/viewer"; import MyPlugin from "@myOrganisation/plugin"; const bimdataViewer = makeBIMDataViewer(/* {...} */); bimdataViewer.registerPlugin(MyPlugin); ``` The `registerPlugin` method take a `PluginDefinition` object as argument: | Property | Description | | :-------------------------- | :--------------------------------------------------- | | `name`: `string` | **Required** The name of the plugin. Must be unique. | | `component`: `object` | A Vuejs (v3.x) component. | | `i18nTokenPrefix`: `string` | *Default* to `plugin.name`. Prefix to add before i18n tokens. | | `i18n`: `object` | An object containing translations for internationalization. | | `startupScript`: `Function` | A callback that is executed when the viewer is mounted and takes [`$viewer`](/viewer/reference/$viewer.html) as argument. | | `button`: `object` | An [object](#plugin-as-button) that describe the display of the plugin if the plugin is shown as button. | | `window`: `Window` | An [Window configuration object](./window.html#window-api) used to register a window with this plugin in it. This plugin is automatically added to the `window.plugins` list. | | `addToWindows`: `string[]` | An array of [window](./window.html) name in which to include this plugin. | | `isViewer`: `boolean` | *Default* to `false`. Defines if this plugin must be considered as a `viewer`. See [viewer plugins](./viewer_plugins.md). | | `settings`: `object` | An object with the corresponding options passed to the [`makeBIMDataViewer()`](./makeBIMDataViewer.md) method. | Note that additional custom data are forward to the registered Plugin to let you configure your plugins as you need to. Once registered, the plugin is available on the viewer with the same interface as the object used to register it. ## Plugin instance Once registered, the plugin is on the list of the registered plugins. But when a window is loaded with a particular plugin as a child, the resulting plugin is a **plugin instance**. A unique copy of the registered plugin, with additional APIs. The Plugin Instance inherits all of the [Plugin APIs](#registration-and-plugin-api). The additional APIs are the followings: | Property | Description | | :---------------------------- | :--------------------------------------------------------------------------------------------------------------- | | `open`: `Function` | Used to open the plugin as button component. Arguments are passed to the `onOpen` option API of the component. | | `close`: `Function` | Used to close the plugin as button component. Arguments are passed to the `onClose` option API of the component. | | `isOpen`: `boolean` | `true` if the plugin as button component is open. | | `show`: `Function` | Used to show the plugin component. | | `hide`: `Function` | Used to hide the plugin component. | | `shown`: `boolean` | `true` if the plugin component is shown. | | `loading`: `boolean` | `true` if the plugin component is being opened or closed. Used in case of async plugin as button component. | | `componentInstance`: `object` | The [Vuejs 3.x component](https://vuejs.org/guide/essentials/component-basics.html) instance. | | `buttonText`: `string` | The text displayed on the plugin button. (getter & setter) | To retrieve a plugin instance: ```js const myPluginInstance = localContext.pluginInstances.get("myPlugin"); // or const myPluginInstance = localContext.plugins.get("myPlugin").$plugin; ``` ## Plugin Component Instance A plugin component is a [Vuejs 3.x component](https://vuejs.org/guide/essentials/component-basics.html) with some additional features. By default, a plugin component is displayed on the window content. (the orange area on the image below) Some additional properties are natively available on the component instance: (`this` on computed, lifeCycles, methods...) * `$viewer`, the entry point of the BIMDataViewer internal API. * `$plugin`, the entry point of the plugin API, a [Plugin Instance](#plugin-instance). ::: warning If a component uses the Vue.js composition API, `$viewer` and `$plugin` need to be injected. ::: ```js setup() { const $viewer = inject("$viewer"); const $plugin = inject("$plugin"); // ... } ``` For more convenience, some of the [Plugin Instance](#plugin-instance) APIs are available on the component instance, with a `$` in front of it: * `$show()`: Function, a `function` to show the plugin component. * `$hide()`: Function, a `function` to hide the plugin component. * `$open()`: Function, a `function` to open the plugin component (plugin as button only). * `$close()`: Function, a `function` to close the plugin component (plugin as button only). * `$isOpen`: boolean, `true` if the plugin component is open (plugin as button only). * `$loading`: boolean, `true` if the plugin component is opening or closing (async plugin as button only). * `$shown`: boolean, `true` if the plugin is shown. To retrieve a plugin component instance: ```js const myPluginComponentInstance = localContext.plugins.get("myPlugin") ``` ## Plugin as button Another way to display a plugin component is as a button. To do so, when registering a plugin, the `pluginToRegister.button` object must implement the following interface: | Property | Description | | :-------------------------- | :----------------------------------------------------------- | | `position`: `string` | "left" or "right". The position of the button in the window. | | `stance`: `number` | A `number` used to sort the plugin as buttons registered on the same side of a window. | | `tooltip`: `string` | A string that is displayed when the plugin button is hovered. It can be a key to be translated ex: "myPluginName.tooltip". | | `content`: `string` | "simple", "panel" or "free"(default). [Different way to display the component](#content) when the button is clicked. | | `keepOpen`: `boolean` | Default to `false`. If `true`, the plugin stay open even if the user click away from it. | | `icon.imgUri`: `string` | An uri to an image for the button. | | `iconOpen.imgUri`: `string` | An uri to an image for the button when the plugin is displayed (open). | If only the `icon` is defined, the corresponding image is always displayed on the button. A similar `iconOpen` option can be defined to display a different icon when the button is open. ### Content A plugin as button can be displayed in 3 different ways, defined by the plugin `content` property. * **simple** : plugin content displayed close to its corresponding button, on a small panel. - **panel** : plugin content displayed on the whole window height. * **free** : plugin content displayed on the side of the button, without any layout. Its size is determined by its content. ### Additional Component API A plugin component will have an additional API if it is registered as a button. #### onOpen and onClose `onOpen` and `onClose` are two methods that can be added as options API on plugin component. As their names suggest, `onOpen` is run when the user request the plugin to be opened, while `onClose` is run when the user request the plugin to be closed. If they return a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), `onOpen` and `onClose` methods can prevent user from spam clicking a plugin button. Indeed, it will not be possible to the user to open or close the plugin if the returned [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) is not resolved. ```javascript const myComponent = { async onOpen() { await new Promise((res) => setTimeout(res, 1000)); }, onClose() { return new Promise((res) => setTimeout(res, 2000)); }, methods: { onClick() { console.log("clicked !"); }, }, template: `
`, }; ``` The result: ![Viewer async plugin](/images/viewer/viewer-async_plugin.gif) These methods are useful when an action needs to be awaited before the plugin can be opened or closed again. ::: tip The plugin can be opened or closed using the UI (by clicking) or [programmatically using javascript](#open-and-close). ::: #### $open and $close A plugin can be opened or closed using the UI (by clicking) but you may want to do it programmatically using javascript. To do so, you can use `$open` or `$close` methods available on [`pluginComponentInstance`](#plugin-component-instance). Example: a plugin component opened at startup and that close itself after 2 seconds. ```javascript const myPluginComponent = { mounted() { this.$open(); setTimeout(() => this.$close(), 2000); }, }; ``` You can also provide any parameter you want when you call `$open` or `$close`. These paramters will be passed to the `onOpen` or `onClose` method respectively. Example: ```js const myPluginComponent = { template: ` `, data() { return { count: 0 }; }, onOpen(msg) { console.log("open message: ", msg); }, methods: { onClick() { this.$open(`count = ${this.count++}`); } } }; ``` ## startupScript The `startupScript` option of the plugin registration API allows to register a function that is executed once the viewer is mounted into the DOM. The function has [`$viewer`](./$viewer.md) as parameter. ```javascript const myFunction = ($viewer) => { $viewer.state.hub.on("objects-selected", (objects) => console.log("New objects are selected", objects) ); }; bimdataViewer.registerPlugin({ name: "myPlugin", startupScript: myFunction, }) ``` ## i18n It is possible to add internationalization for plugins. ### Translate text To add i18n files, use the `i18n` plugin property. To translate a text, use `$t("pluginName.textKey")`. Example: ```javascript const EN = { "textKey": "This text is in english.", }; const FR = { "textKey": "Ce texte est en français", }; const myPlugin = { name: "myPlugin", i18n: { en: EN, fr: FR, }, component: { template: "
{{ $t('myPlugin.textKey') }}
" } }; ``` ### Set the viewer locale To set the viewer language, use the `locale` property of the [makeBIMDataViewer](/viewer/reference/makeBIMDataViewer.html) configuration object: ```javascript const viewer = makeBIMDataViewer({ locale: "en", // ... }); ``` --- --- url: /viewer/reference/makeBIMDataViewer.md --- # makeBIMDataViewer `makeBIMDataViewer` is the function that is available after importing the viewer. ```javascript import makeBIMDataViewer from "@bimdata/viewer"; const bimdataViewer = makeBIMDataViewer({ /* configuration object */ }); ``` It takes a configuration object that accept the following properties : ## locale * **Type**: `String` * **Details**: A string to determine the locale of the viewer. Available locales are: * English: `en` (default) * French: `fr` * Spanish: `es` * German: `de` * Italian: `it` ## api * **Type**: `Object` * **Details**: An object containing [BIMData API](../../api/introduction/overview.md) connection config. Example : ```javascript const bimdataViewer = makeBIMDataViewer({ api: { modelIds: [15097], cloudId: 10344, projectId: 237466, accessToken: "TAbdyPzoQeYgVSMe4GUKoCEfYctVhcwJ", }, }); ``` The `api` properties are: | Name | Type | Description | | :------------ | :--------- | :----------------------------- | | `apiUrl` | `string` | (**Optional**) The BIMData API URL. Default to `https://api.bimdata.io` | | `archiveUrl` | `string` | (**Optional**) The BIMData Archive backend URL. Default to `https://archive.bimdata.io` | | `pdfBackendUrl` | `string` | (**Optional**) The BIMData API URL. Default to `https://pdf-backend.bimdata.io` | | `accessToken` | `string` | The access token. | | `cloudId` | `number` | The cloud id. | | `projectId` | `number` | The project id. | | `modelIds` | `number[]` | (**Optional**) An array of model ids to load on startup. | | `offline` | `object` | Offline mode configuration. | | `onlyLoadUuids` | `object` | A 'model id' to 'element uuids' mapping to filter elements ([see example](../examples/partial_loading)). | Here are the `offline` configuration options: | Name | Type | Description | | :------------ | :--------- | :----------------------------- | | `enabled` | `boolean` | Default to `false`. Enable/Disable offline mode. | | `data` | `Blob | string` | A Blob or URL of the *offline-package* | You can refer to [the dedicated page](./offline_mode.md) to learn more about offline mode. ## ui * **Type**: `Object` * **Details**: An object to customize the global UI of the viewer. Example : ```javascript const bimdataViewer = makeBIMDataViewer({ ui: { style: { backgroundColor: "FFFFFF", }, header: false, version: false, bimdataLogo: false, contextMenu: false, resizable: true, mobile: false, }, }); ``` The `ui` properties are: | Name | Type | Description | | :---------------------- | :-------- | :-------------------------------------------------------------------------- | | `style` | `object` | An set of props to customize [viewer colors](../guide/index#colors-🎨). | | `header` | `boolean` | **Default** to `true`. If `false`, the header is hidden. | | `version` | `boolean` | **Default** to `true`. If `false`, the viewer version is hidden. | | `bimdataLogo` | `boolean` | **Default** to `true`. If `false`, the BIMData logo is hidden. | | `contextMenu` | `boolean` | **Default** to `true`. If `false`, the context menu is disabled. | | `resizable` | `boolean` | **Default** to `true`. If `false`, the layout is not resizable from the UI. | | `mobile` | `boolean` | **Default** to `false`. Enable / Disable mobile UI. | ## plugins * **Type**: `Object` | `boolean` * **Details**: An object to customize the BIMData viewer native plugins. If `false`, no native plugins are available. Each property is a plugin name and the value is either a boolean or an object. An object is considered as `true` and the object content is provided to the plugin instance on `this.$plugin.settings`. Some native plugins are enabled by default and others disabled. To enabled plugins that are disabled by default, you must provide their names with `true` or an object with plugin specific options. Example : ```javascript const bimdataViewer = makeBIMDataViewer({ plugins: { split: true, bcf: false, header: false, fullscreen: false, projection: false, search: false, section: false, windowSelector: false, "structure-properties": { merge: true, export: true, editProperties: true, }, viewer3d: { pivotMarker: false, navCube: false, edges: false, }, "window-manager": false, }, }); ``` :::tip For more details about native plugins, see [the native plugins reference](/viewer/reference/native_plugins.html). ::: The returned object of the `makeBIMDataViewer` function have the following interface: | Property | Description | | :-------------------------------------------------- | :----------- | | `mount(containerElementOrSelector: HTMLElement | string, layout?: Object): Object` | Mount the viewer on the corresponding DOM element with the specified layout. See [`mount`](./mount.md) | | `setLocale(locale: string): void` | Set the [viewer locale](#locale). | | `registerPlugin(plugin: Object, cfg: Object): void` | Register a plugin. See [plugin registration](./plugin.md#registration-and-plugin-api). | | `registerWindow(window: Object): void` | Register a window. See [window registration](./window.md#registration). | | `unregisterWindow(windowName: string): void` | Unregister the corresponding window. | | `setAccessToken(accessToken: string): void` | Set API access token. | | `async loadModels(modelIds: number[]): Object[]` | Load the corresponding models. | | `destroy(): void` | Destroy the viewer. All the plugins will be destroyed and the DOM won't react anymore. **Warning:** If you remove the viewer's `
` without calling this method, there will be a huge memory leak | --- --- url: /viewer/reference/mount.md --- # mount Once created, the BIMDataViewer must be mounted to a [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) element in order to be displayed to the user. ```javascript bimdataViewer.mount("#viewerId"); // 'viewerId' must be the id of an existing element. ``` The mount method take an optional second argument: the [`layout`](../examples/gui_layout.md). The [`layout`](../examples/gui_layout.md) is the configuration of the windows displayed at startup. The **default** value is `"3d"`, which is the name of a window registered by default. The `"3d"` window includes many BIMData plugins like [`"viewer3d"`](./native_plugins.md#viewer-3d-ifc), [`"section"`](./native_plugins.md#section), [`"projection"`](./native_plugins.md#projection), [`"structure-properties"`](./native_plugins.md#structure-and-properties)... The layout object passed to the `bimdataviewer.mount` method can be either a `string` or an `object`. * If string, it must be the name of a registered window. * If object, the layout represents a window or a recursive object representing a container of window names. ## Window A window is represented by a `string` with its name or the following Object: | Name | Type | Description | | :------------ | :-------------------------------------------------------- | :------------------------------------------------------- | | `windowName` | `string` | The name of the window to load. | | `windowState` | `{ modelIds: number, viewpoint: Object, storey: string }` | The state to load. (the storey string is the storey key) | ## Container | Name | Type | Description | | :---------- | :--------------------- | :------------------------------------------------------------------------------ | | `ratios` | `number[]` | **Required**. The amount of space (in %) taken by respective children. | | `children` | `string[] | object[]` | **Required**. An array of window names as string or other containers as object. | | `direction` | `string` | `"column"` or `"row"` (**default**). The direction of the container. | Here is an example of a complex layout: ```js const layout = { ratios: [40, 60], children: [ "window-1", { direction: "column", ratios: [40, 60], children: [ "window-2", { windowName: "window-3", windowState: { modelIds: [4717], }, }, ], }, ], }; ``` The result is the following UI layout: --- --- url: /viewer/reference/$viewer.md --- # `$viewer` The `$viewer` object can be accessed on any component instance (using `this.$viewer`), it is also passed as the first argument of the `startupScript` method of a plugin. It is the entrypoint to interact with the viewer core. If a component uses the Vue.js composition API, `$viewer` needs to be [injected](https://vuejs.org/api/composition-api-dependency-injection.html#inject): ```js setup() { const $viewer = inject("$viewer"); // ... } ``` Below is a description of its interface: ```typescript interface $Viewer { readonly version: string; // the viewer version readonly locale: string; readonly i18n: i18n; readonly api: Api; readonly state: State; readonly uiSettings: Object; // the settings of the ui property passed to the mabeBIMDataViewer function readonly pluginsCfg: Object; // the settings of the plugins property passed to the mabeBIMDataViewer function readonly registeredWindows: string[]; // List of registered window names readonly registeredPlugins: string[]; // List of registered plugin names readonly globalContext: GlobalContext; readonly localContext: LocalContext; readonly contextMenu: ContextMenu; } ``` ## i18n `$viewer.i18n` is used to access the viewer internationalization API: ```typescript enum ViewerLocale { "de", "en", "es", "fr", "it" } interface i18n { i18nVuePlugin: any; registerTranslations(messages: Object): void; // Register a set of messages changeLocale(locale: ViewerLocale): void; // Change the current viewer locale } ``` Example usage: register translations that will be used in a plugin template. ```javascript this.$viewer.i18n.registerTranslations({ en: { hello: "Hello world !" }, fr: { hello: "Boujour le monde !" } }); ``` ## API The `$viewer.api` object is used to interact with the [BIMData API](/api/introduction/overview.html). ```typescript interface Api { readonly apiClient: BIMDataApiClient; readonly apiUrl: string; readonly archiveUrl: string; readonly cloudId: number; readonly projectId: number; readonly permissions: Permissions; accessToken: string; getModel(modelId: number): Promise; getModelStructure(model: Model): Promise; getRawElements(modelId: number): Promise; waitForModelProcess(model: Model): Promise; enableOfflineMode(blob: Blob | string): Promise; disableOfflineMode(): void; } ``` ::: tip See [the doc of the **typescript-fetch-api-client**](/api/external_libraries.html#typescript) to learn more about what you can do with `$viewer.api.apiClient`. ::: Here is an example of how to get an IFC element from the API: ```javascript const modelId = 123; const uuid = "my element uuid"; const element = await this.$viewer.api.apiClient.modelApi.getElement( this.$viewer.api.cloudId, modelId, this.$viewer.api.projectId, uuid ); ``` ### Permissions The `$viewer.api.permissions` object hold a set of flags that tell which actions the user is allowed to perform. ```typescript interface Permissions { hasAdminPermission: boolean; hasBcfReadPermission: boolean; hasBcfWritePermission: boolean; hasDocReadPermission: boolean; hasDocWritePermission: boolean; hasModelReadPermission: boolean; hasModelWritePermission: boolean; hasReadPermission: boolean; hasWritePermission: boolean; userRole: string; tokenScopes: { bcf?: string[]; model?: string[]; document?: string[]; }; usableScopes: { bcf?: string[]; model?: string[]; document?: string[]; }; } ``` ### getRawElements The `$viewer.api.getRawElements()` method retrieves all objects, their properties, classifications, systems and layers. For performance reasons, the API sends a formatted JSON that needs to be rebuilt in order to be used in javascript. If you want to parse data to filter objects, you probably want to use this method. ```javascript const modelId = 123; const elements = await this.$viewer.api.getRawElements(modelId); ``` The result is an object where keys are uuids and value are the element data formatted like the [API response](https://api.bimdata.io/doc#/model/getElement). ### waitForModelProcess The `$viewer.api.waitForModelProcess()` method can be used to wait until a given model is processed, i.e. it has a status of `C` (COMPLETED), `E` (ERROR) or `X` (WON'T FIX). It takes a **model** object as parameter. A typical usage example is when you need to upload a model and then wait for it to be processed before opening it in a viewer. ```javascript const processedModel = await this.$viewer.api.waitForModelProcess(model); ``` ### enableOfflineMode The `$viewer.api.enableOfflineMode()` method is used to activate offline mode. Here is its signature: ```ts enableOfflineMode(blob: Blob | string): Promise; ``` The `blob` parameter can be either a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or an url (string) that will be fetched (using the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)). Refer to the [Offline Mode](./offline_mode) page for more information on how to work with offline mode. ### disableOfflineMode The `$viewer.api.disableOfflineMode()` method allows you to switch offline mode off. ## State The `$viewer.state` object provide a way to interact with [the global state](./state.md). ## Global and Local contexts For a more detailed description of the global/local context interfaces, refer to their respective documentation: * [Global Context](./global_context.md) * [Local Context](./local_context.md) ### Shortcuts You can use `globalContext`/`localContext` to register shortcuts that depends on the context. When triggering a shortcut, the current context is the window the mouse is hovering. If two shortcuts are registered on the same key, one on the `localContext`, the other on the `globalContext`, the `localContext` shortcut will be executed on keystroke if the mouse is hovering the window, else, it will be the `globalContext` one (the mouse is hovering another window or the header). A shortcut object has the following interface: ```typescript interface Shortcut { name: string; // [Required] A name to identify the shortcut. key: string; // [Required] This key the shortcut is bound to (case insensitive). ctrlKey: boolean; // [Default to `false`] Does the `ctrl` (or `meta`) key must be pressed to trigger the shortcut ? shiftKey: boolean; // [Default to `false`] Does the `shift` key must be pressed to trigger the shortcut ? altKey: boolean; // [Default to `false`] Does the `alt` key must be pressed to trigger the shortcut ? execute(): void; // [Required] The function that will be executed when the key is pressed. } ``` Example usage: ```javascript this.$viewer.globalContext.registerShortcut({ name: "log", key: "l", ctrlKey: true, execute: () => console.log("Log from global shortcut."), }); this.$viewer.localContext.registerShortcut({ name: "log", key: "l", ctrlKey: true, execute: () => console.log("Log from local shortcut."), }); ``` Shortcuts can be unregistered calling the `unregisterShortcut()` method with the shortcut name. ```javascript this.$viewer.globalContext.unregisterShortcut("log"); this.$viewer.localContext.unregisterShortcut("log"); ``` ### Spinners You can display a spinner to tell the user to wait until some process is finished. Spinners can be displayed on the whole UI (**globalContext**) or just the current window (**localContext**). ```javascript // A spinner on the whole UI this.$viewer.globalContext.loadingProcessStart(); // A spinner on the current window this.$viewer.localContext.loadingProcessStart(); ``` To stop spinners use the following methods: ```javascript this.$viewer.globalContext.loadingProcessEnd(); this.$viewer.localContext.loadingProcessEnd(); ``` There is a `loading` property (on both `globalContext` and `localContext`) that indicates if a spinner is displayed on the related context. The global spinner can also be customized via the `spinner` property on `globalContext`: ```javascript // Set custom spinner to be used as global spinner this.$viewer.globalContext.spinner = { component: SpinnerComponent, props: SpinnerProps, }; // Reset global spinner to default this.$viewer.globalContext.spinner = null; ``` ### Modals In a similar way, you can choose to show a modal on the whole UI or just the current window using modals manager available on `globalContext.modals` and `localContext.modals`. Modal manager allows to display modals. Modals are queued so if more than one modals are sent to the same modals manager, they will be displayed in order. To open a modal, call `pushModal()` method on a modal manager. | Property | Description | | :---------------------------- | :------------------------------------------------------------------------------------------------------- | | `pushModal(component, props)` | Add a modal to the queue. `component` is a valid vuejs component. `props` is the component props values. | | `clearModal()` | Clear the current modal. | ```javascript this.$viewer.localContext.modals.pushModal(MyModalComponent); ``` To close a modal, click outside of its content or emit the `"close"` event inside the modal component. ```javascript this.$emit("close"); ``` ## Context Menu You can manage [the viewer context menu](./context_menu.md) with `$viewer.contextMenu`. --- --- url: /viewer/reference/state.md --- # State The state contains [Models](#models), [Objects](#objects) and [Annotations](#annotations) logic. It can be accessed with `$viewer.state`. ```typescript interface State { hub: EventHandler; /**** Models ****/ readonly models: Model[]; readonly modelsMap: Map; loadModels(ids: number[]): Promise; unloadModels(ids: number[]); getStoreyFromAbsoluteElevation(model: Model, elevation: number): Storey; /**** Objects ****/ readonly objects: StateObject[]; readonly objectsIds: number[]; readonly objectsUuids: string[]; readonly objectsMap: Map; readonly uuidsMap: { get(uuid: string): StateObject[]; }; getObject(id: number): StateObject; getObjectsByUuids(uuids: string[]): StateObject[]; getObjectsOfType(type: string): StateObject[]; getObjectsWithTheSameTypeAs(ids: number[]): StateObject[]; getTypesOf(ids: number[]): string[]; readonly visibleObjects: StateObject[]; readonly visibleObjectsIds: number[]; readonly visibleObjectsUuids: string[]; showObjects(ids: number[], options?: any): void; showObjectsByUuids(uuids: string[], options?: any): void; readonly unvisibleObjects: StateObject[]; readonly unvisibleObjectsIds: number[]; readonly unvisibleObjectsUuids: string[]; hideObjects(ids: number[], options?: any): void; hideObjectsByUuids(uuids: string[], options?: any): void; readonly pickableObjects: StateObject[]; readonly pickableObjectsIds: number[]; readonly pickableObjectsUuids: string[]; setObjectsPickable(ids: number[], options?: any): void; setObjectsPickableByUuids(uuids: string[], options?: any): void; readonly unpickableObjects: StateObject[]; readonly unpickableObjectsIds: number[]; readonly unpickableObjectsUuids: string[]; setObjectsUnpickable(ids: number[], options?: any): void; setObjectsUnpickableByUuids(uuids: string[], options?: any): void; readonly selectedObjects: StateObject[]; readonly selectedObjectsIds: number[]; readonly selectedObjectsUuids: string[]; selectObjects(ids: number[], options?: any): void; selectObjectsByUuids(uuids: string[], options?: any): void; readonly deselectedObjects: StateObject[]; readonly deselectedObjectsIds: number[]; readonly deselectedObjectsUuids: string[]; deselectObjects(ids: number[], options?: any): void; deselectObjectsByUuids(uuids: string[], options?: any): void; readonly highlightedObjects: StateObject[]; readonly highlightedObjectsIds: number[]; readonly highlightedObjectsUuids: string[]; highlightObjects(ids: number[], options?: any): void; highlightObjectsByUuids(uuids: string[], options?: any): void; readonly unhighlightedObjects: StateObject[]; readonly unhighlightedObjectsIds: number[]; readonly unhighlightedObjectsUuids: string[]; unhighlightObjects(ids: number[], options?: any): void; unhighlightObjectsByUuids(uuids: string[], options?: any): void; readonly xrayedObjects: StateObject[]; readonly xrayedObjectsIds: number[]; readonly xrayedObjectsUuids: string[]; xrayObjects(ids: number[], options?: any): void; xrayObjectsByUuids(uuids: string[], options?: any): void; readonly unxrayedObjects: StateObject[]; readonly unxrayedObjectsIds: number[]; readonly unxrayedObjectsUuids: string[]; unxrayObjects(ids: number[], options?: any): void; unxrayObjectsByUuids(uuids: string[], options?: any): void; readonly colorizedObjects: StateObject[]; readonly colorizedObjectsIds: number[]; readonly colorizedObjectsUuids: string[]; colorizeObjects(ids: number[], color?: string, options?: any): void; colorizeObjectsByUuids(uuids: string[], color?: string, options?: any): void; /**** Annotations ****/ readonly annotations: Annotation[]; addAnnotation(annotation: Annotation, options?: any): Annotation; removeAnnotation(annotation: Annotation, options?: any): boolean; clearAnnotations(): void; } ``` ## Models A state `Model` is a [model object from API](https://api.bimdata.io/doc#/model/getModel) extended with some additional fields. ```typescript interface Model extends ApiModel { structure: Object; uuids: Map; objects: StateObject[]; storeys: Storey[]; } ``` The `structure` object is obtained by fetching and parsing the file pointed by the model `structure_file` property. The `uuids` map can be used to retrieve model objects directly (using their uuids). The `objects` array is the list of model objects. The `storeys` array is the list of model storeys. `Storey` objects have the following interface: ```typescript interface Storey { uuid: string; name: string; model: Model; // model that contain the storey plans: Plan[]; // list of storey plans object: StateObject; // storey object (from IFC) uuids: Set; // UUIDs of all storey descendents elevation: number; // vertical position (z) of the storey in model coordinates topElevation: number; // elevation of the next storey (in model coordinates) absoluteElevation: number; // vertical position of the storey (z) in world coordinates absoluteTopElevation: number; // elevation of the next storey (in world coordinates) key: string; // storey unique key } interface Plan { plan: ApiModel; /* see: https://api.bimdata.io/doc#/model/getModel */ translation_x: number; translation_y: number; rotate_z: number; scale: number; opacity: number; key: string; // plan unique key } ``` ## Objects ```typescript interface StateObject { // Properties id: number; uuid: string; name: string; longname: string; type: string; object_type: string; model: Model; parent: StateObject; children: StateObject[]; // State visible: boolean; pickable: boolean; selected: boolean; highlighted: boolean; xrayed: boolean; color: string; // Advanced getters readonly descendants: StateObject[]; readonly ancestors: StateObject[]; readonly site: StateObject; readonly building: StateObject; readonly storey: StateObject; readonly layout: StateObject; readonly space: StateObject; getFirstAncestorWithType: (type: string) => StateObject; } ``` ### Objects maps | Name | Description | | :------------------------------------- | :--------------------------------------- | | `objectsMap: Map` | A Map of all objects keyed by **id**. | | `uuidsMap: Map` | A Map of all objects keyed by **uuids**. | **Note:** As object uuids may not be unique, `uuidsMap.get()` always returns an array of objects. ### Objects getters The state provide getters that allows to quickly access a set of objects with specific properties. | Name | Description | | :--------------------------------------------------------- | :----------------------------------------------------- | | **properties** | | | `visibleObjects` | List of visible objects. | | `unvisibleObjects` | List of objects that are not visible. | | `pickableObjects` | List of pickable objects. | | `unpickableObjects` | List of objects that are not pickable. | | `selectedObjects` | List of selected objects. | | `deselectedObjects` | List of objects that are not selected. | | `highlightedObjects` | List of highlighted objects. | | `unhighlightedObjects` | List of objects that are not highlighted. | | `xrayedObjects` | List of xrayed objects. | | `unxrayedObjects` | List of objects that are not xrayed. | | `colorizedObjects` | List of colorized objects. | | **methods** | | | `getObject(id: number)` | Returns the object with the specified id. | | `getObjectsByUuids(uuids: string[])` | Returns objects with corresponding uuids. | | `getObjectsOfType(type: string)` | Returns objects with corresponding type. | | `getObjectsWithTheSameTypeAs(ids: number[] \| Set\)` | Returns all objects with the same type as objects ids. | | `getTypesOf(ids: number[] \| Set\)` | Returns all the types of the corresponding objects. | **Note:** for convenience, all getter properties have also `ids` and `uuids` equivalent: ```javascript $viewer.state.selectedObjects; // list of selected objects $viewer.state.selectedObjectsIds; // list of selected objects ids $viewer.state.selectedObjectsUuids; // list of selected objects uuids ``` ### Objects setters Setters allows to update the objects state. | Name | Description | | :-------------------------------------------------------------- | :---------------------------------------------- | | `showObjects(ids: number[], options?: any)` | Show objects. | | `hideObjects(ids: number[], options?: any)` | Hide objects. | | `setObjectsPickable(ids: number[], options?: any)` | Set objects as pickable. | | `setObjectsUnpickable(ids: number[], options?: any)` | Set objects as unpickable. | | `selectObjects(ids: number[], options?: any)` | Select objects. | | `deselectObjects(ids: number[], options?: any)` | Deselect objects. | | `highlightObjects(ids: number[], options?: any)` | Highlight objects. | | `unhighlightObjects(ids: number[], options?: any)` | Unhighlight objects. | | `xrayObjects(ids: number[], options?: any)` | Xray objects. | | `unxrayObjects(ids: number[], options?: any)` | Unxray objects. | | `colorizeObjects(ids: number[], color?: string, options?: any)` | Set objects color (ex: "#FFFFFF"). | **Note:** as for [getters](#objects-getters), setters have `uuids` equivalent as well: ```javascript $viewer.state.selectObjects(ids); // selects objects by ids $viewer.state.selectObjectsByUuids(uuids); // selects objects by uuids ``` Moreover, every setter has an optional `options` argument that can be used to pass additional data to the triggered event payload. This provide more flexibility and allows to handle some complex use cases. An example usage is to ensure that a plugin will not "auto-trigger" itself by emitting an `"objects-selected"` event while still being able to react to other plugins `"objects-selected"` events: ```javascript this.$viewer.state.hub.on("objects-selected", ({ objects, options }) => { if (options.emitter === this) return; /* Do something if the event comes from another plugin. */ }); // Pass an `emitter` option to ensure the plugin will not trigger itself this.$viewer.state.selectObjects(ids, { emitter: this }); ``` ## Annotations See the [dedicated reference page](./annotations.md) to learn more about Annotation API. ## Events | Name | Payload | Description | | :---------------------- | :--------------------------------------------------------- | :---------- | | **Models events** | | | | `models-loaded` | `{ models: Model[] }` | One or more models have been loaded in the state | | `models-unloaded` | `{ models: Model[] }` | One or more models have been unloaded from the state | | `plan-created` | `{ plan: Plan }` | A storey plan has been created | | `plan-updated` | `{ plan: Plan }` | A storey plan has been updated | | `plan-deleted` | `{ plan: Plan }` | A storey plan has been deleted | | **Objects events** | | | | `objects-added` | `{ objects: StateObject[] }` | Some objects have been added to the state | | `objects-removed` | `{ objects: StateObject[] }` | Some objects have been removed from the state | | `objects-shown` | `{ objects: StateObject[], options?: any }` | Some objects have been made visible | | `objects-hidden` | `{ objects: StateObject[], options?: any }` | Some objects have been hidden | | `objects-pickable` | `{ objects: StateObject[], options?: any }` | Some objects have been made pickable | | `objects-unpickable` | `{ objects: StateObject[], options?: any }` | Some objects have been made unpickable | | `objects-selected` | `{ objects: StateObject[], options?: any }` | Some objects have been selected | | `objects-deselected` | `{ objects: StateObject[], options?: any }` | Some objects have been deselected | | `objects-highlighted` | `{ objects: StateObject[], options?: any }` | Some objects have been highlighted | | `objects-unhighlighted` | `{ objects: StateObject[], options?: any }` | Some objects have been unhighlighted | | `objects-xrayed` | `{ objects: StateObject[], options?: any }` | Some objects have been xrayed | | `objects-unxrayed` | `{ objects: StateObject[], options?: any }` | Some objects have been unxrayed | | `objects-colorized` | `{ objects: StateObject[], color: string, options?: any }` | Some objects have been colorized | | **Annotations events** | | | | `annotation-added` | `{ annotation: Annotation, options?: any }` | An annotation has been added | | `annotation-updated` | `{ annotation: Annotation, options?: any }` | An annotation has been updated/moved | | `annotation-removed` | `{ annotation: Annotation, options?: any }` | An annotation has been removed | :::tip For more information about the state hub interface, see [the hub reference](hubs.html). ::: Examples: ```js state.hub.on("models-loaded", ({ models }) => { /* Handle newly loaded models */ }); state.hub.on("objects-selected", ({ objects, options }) => { /* Do something with selected objects */ }); ``` --- --- url: /viewer/reference/global_context.md --- # Global Context The `globalContext` shares a `Context` interface with the `localContext`. Here is the full `GlobalContext` interface: ```typescript interface Context { readonly hub: EventHandler; registerShortcut(shortcut: Shortcut, context: GlobalContext | LocalContext): boolean; unregisterShortcut(name: string, context: GlobalContext | LocalContext): boolean; readonly loading: boolean; loadingProcessStart(): void; loadingProcessEnd(): void; spinner: { component: Object, props: Object }; // a custom spinner replacing the default BIMDataSpinner modals: { pushModal(component: any, props?: any, options?: any): void; clearModal(): void; }; el: HTMLElement; } ``` ```typescript interface GlobalContext extends Context { resizable: boolean; open({ ratio: number; direction?: "column" | "row"; // defaults to "row" insertAfter?: boolean; // defaults to true windowName?: string; windowState?: { modelIds: number[]; viewpoint: Object; storey: string; }; localContextId?: number; }): Promise; close(localContextId: number): Promise; swap(localContextIdA: number, localContextIdB: number): Promise; header: ViewerHeader; readonly activeLocalContext?: LocalContext; readonly localContexts: LocalContext[]; getLocalContexts(windowName: string): LocalContext[]; readonly pluginInstances: Map; readonly plugins: Map; getViewers(): ModelViewerInstance[]; readonly loadedModels: StateModel[]; readonly loadedModelIds: number[]; readonly loadingModelIds: number[]; } ``` ## Global Context API | Name | Description | | :--------------------------------- | :--------------------------------------------------------------------- | | **properties** | | | `resizable` | If `true`, the user can resize the windows by dragging the window separators. | | `activeLocalContext` | The currently active local context (the one associated to the window that is currently hovered by the cursor). | | `localContexts` | List of all local contexts. | | `pluginInstances` | A map of all plugin instances, map keys are plugin names and values are list of instances. | | `plugins` | A map of all plugin [**component instances**](./plugin.md#plugin-component-instance). | | `loadedModels` | List of currently loaded models (in all windows). | | `loadedModelIds` | List of currently loaded model ids (in all windows). | | `loadingModelIds` | List of currently loading model ids (in all windows). | | **methods** | | | `open(options: any)` | (**async**) Split the given context with the specified options (ratio, direction, window, etc...). | | `close(id: number)` | (**async**) Close the given context. | | `swap(id1: number, id2: number)` | (**async**) Swap the given contexts. | | `getLocalContexts(name: string)` | Returns local contexts that are associated with a given window. | | `getViewers()` | Returns all [viewer plugins](./viewer_plugins.md) instances. | ## Events The table below describe global context specific events: | Name | Payload | Description | | :------------- | :----------------------- | :-------------------------------------------------------------------- | | `window-open` | the opened window object | Sent when a [window](./window.md) is selected on the window selector. | | `window-close` | the closed window object | Sent when a [window](./window.md) is closed. | Additionally a set of [local context events](/viewer/reference/local_context.html#events-emitted-on-both-global-local-contexts) are also emitted on global context. --- --- url: /viewer/reference/local_context.md --- # Local Context The `localContext` shares a `Context` interface with the `globalContext`. Here is the full `LocalContext` interface: ```typescript interface Context { readonly hub: EventHandler; registerShortcut(shortcut: Shortcut, context: GlobalContext | LocalContext): boolean; unregisterShortcut(name: string, context: GlobalContext | LocalContext): boolean; readonly loading: boolean; loadingProcessStart(): void; loadingProcessEnd(): void; spinner: { component: Object, props: Object }; // a custom spinner replacing the default BIMDataSpinner modals: { pushModal(component: any, props?: any, options?: any): void; clearModal(): void; }; el: HTMLElement; } ``` ```typescript interface LocalContext extends Context { id: number; readonly x: number; readonly y: number; readonly width: number; readonly height: number; resolution: number; close(): void; // Local state readonly multiModel: boolean; readonly modelTypes?: string[]; readonly loadedModels: StateModel[]; readonly loadedModelIds: number[]; readonly loadingModelIds: number[]; readonly selectedStorey: StateStorey | null; loadModels(ids: number[]): Promise; unloadModels(ids: number[]): boolean; selectStorey(storey: StateStorey, { showPlans?: boolean, fitViewRequested?: boolean }): void; showPlan(plan: StatePlan): void; hidePlan(plan: StatePlan): void; // Viewer Interface readonly viewer: ModelViewerInstance | null; readonly annotationMode: boolean; getViewpoint: (options?: any) => any | Promise; setViewpoint: (viewpoint: any, options?: any) => void | Promise; startAnnotationMode: (callback: Function) => void; stopAnnotationMode: () => void; fitView: (options?: any) => void; showUI: (options?: any) => void; hideUI: (options?: { exceptions: string[] }) => Promise; // Context Window readonly window: Window; loadWindow(windowName: string, windowState?: { modelIds: number, viewpoint: Object, storey: string }): void; unloadWindow(): void; // Plugins readonly pluginInstances: new Map; readonly plugins: Map; } ``` ## Local State The [global state](./state.md) allows to manage a set of shared data that is not tied to a specific context. To manage models, storeys and plans for a given context you can use the `localContext` object. | Name | Description | | :--------------------------------- | :--------------------------------------------------------------------- | | **properties** | | | `loadedModels` | List of currently loaded models | | `loadedModelIds` | List of currently loaded model ids | | `loadingModelIds` | List of model ids that are currently loading | | `selectedStorey` | Storey that is currently active | | **methods** | | | `loadModels(ids: number[])` | Load the given models in this context | | `unloadModels(ids: number[])` | Unload the given models from this context | | `selectStorey(storey: Storey, { showPlans?: boolean, fitViewRequested?: boolean })` | Set storey as the current storey. If `showPlans` is `false` (default to `true`), the corresponding storey plans are not shown. `fitViewRequested` (default to `true`) is an hint indicating to the `"storey-selected"` listeners that a fit view should be done. Useful if a custom fit view is performed just after selecting the storey. | | `showPlan(plan: Plan)` | Show plan | | `hidePlan(plan: Plan)` | Hide plan | The properties described above are reactive and can be [watched](https://vuejs.org/guide/essentials/watchers.html) by Vue to trigger effects: ```javascript watch( () => $viewer.localContext.loadedModels models => { console.log("Currently loaded models: ", models); } ); ``` ## Viewer Interface For [viewer windows](./viewer_plugins.md) the `localContext` provide an API to interact with the local model viewer. It is a set of methods that are independent on the type of viewer (`IFC`, `DWG`, `Plan`, ...). If the current context is not a viewer window, an error is thrown when these methods are called. | Name | Description | | :-------------------------------------------- | :---------------------------------------------------------------------------------- | | **properties** | | | `viewer` | Model viewer instance of this context, `null` if the context is not a viewer window | | `annotationMode` | `true` if annotation mode is enabled, `false` otherwise | | **methods** | | | `getSnapshot()` | (*async*) Get a snapshot of the current viewer: `{ snapshot_type: string, snapshot_data: string (Data URL) }` | | `getViewpoint(options?: any)` | (*async*) Get a [BCF viewpoint](https://api.bimdata.io/doc#/bcf/getViewpoint) of the current viewer | | `setViewpoint(viewpoint: any, options?: any)` | (*async*) Set model viewer viewpoint | | `startAnnotationMode(callback: Function)` | Enable annotation mode (see [annotation API](./annotations.md#usage)) | | `stopAnnotationMode()` | Disable annotation mode | | `fitView(options?: any)` | Apply a "fit view" command to the model viewer | | `showUI(options?: any)` | (*async*) Makes all UI elements of the context visible (such as plugins and model selector) | | `hideUI(options?: { exceptions: string[] })` | (*async*) Hide all UI elements of the context (some exceptions can be specified) | ## Events ### Local Context specific events | Name | Payload | Description | | :----------------- | :---------------------------------- | :------------------------------------------------------- | | `alert` | `{ type: string, message: string }` | A plugin in this context raised an alert to be displayed | | `context-resize` | `{ width: number, height: number }` | The context window has been resized | | `models-loaded` | `{ models: Model[] }` | One or more models have been loaded in this context | | `models-unloaded` | `{ models: Model[] }` | One or more models have been unloaded from this context | | `models-loading` | `{ ids: number[] }` | One or more models are loading in this context | | `storey-selected` | `{ storey: Storey }` | The current active storey has changed | | `plan-shown` | `{ plan: Plan }` | A storey plan is now visible | | `plan-hidden` | `{ plan: Plan }` | A storey plan has been hidden | | `pdf-page-changed` | `{ model: Model, page: any }` | The current PDF page changed | | `drawing-created` | `{ drawing: Drawing }` | A new drawing has been created on the current model | | `drawing-updated` | `{ drawing: Drawing }` | A drawing has been updated on the current model | | `drawing-deleted` | `{ drawing: Drawing }` | A drawing has been deleted on the current model | ### Events emitted on both Global & Local contexts | Name | Payload | Description | | :-------------------------- | :------------------------------------------- | :--------------------------------------------------- | | `plugin-created` | `{ name: string, plugin: PluginInstance }` | A plugin has been added to this context | | `plugin-destroyed` | `{ name: string, plugin: PluginInstance }` | A plugin has been removed from this context | | `3d-model-loaded` | `{ model: Model, plugin: ViewerIfc3D }` | An IFC model has been loaded in an IFC 3D viewer | | `3d-model-unloaded` | `{ model: Model, plugin: ViewerIfc3D }` | An IFC model has been unloaded from an IFC 3D viewer | | `2d-model-loaded` | `{ model: Model, plugin: ViewerIfc2D }` | An IFC model has been loaded in an IFC 2D viewer | | `2d-model-unloaded` | `{ model: Model, plugin: ViewerIfc2D }` | An IFC model has been unloaded from an IFC 2D viewer | | `dwg-model-loaded` | `{ model: Model, plugin: ViewerDwg }` | A DWG model has been loaded | | `dwg-model-unloaded` | `{ model: Model, plugin: ViewerDwg }` | A DWG model has been unloaded | | `dxf-model-loaded` | `{ model: Model, plugin: ViewerDwg }` | A DXF model has been loaded | | `dxf-model-unloaded` | `{ model: Model, plugin: ViewerDwg }` | A DXF model has been unloaded | | `plan-model-loaded` | `{ model: Model, plugin: ViewerPlan }` | A Plan/Meta-Building model has been loaded | | `plan-model-unloaded` | `{ model: Model, plugin: ViewerPlan }` | A Plan/Meta-Building model has been unloaded | | `pointcloud-model-loaded` | `{ model: Model, plugin: ViewerPointCloud }` | A Point Cloud model has been loaded | | `pointcloud-model-unloaded` | `{ model: Model, plugin: ViewerPointCloud }` | A Point Cloud model has been unloaded | --- --- url: /viewer/reference/context_menu.md --- # Context Menu The context menu is displayed after right clicking on the viewer. It displays commands that may depends on the contexts and can be customized. ## Get the context menu The context menu can be accessed on the `$viewer` object: ```javascript $viewer.contextMenu; ``` ## Interface | Property | Description | | :------------------------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------- | | `registerContextCommand(command: ContextMenuCommand): number` | Add command for the openning context menu. Returns the command id. | | `registerCommand(command: ContextMenuCommand): number` | Add command on context menu, displayed if the predicate exists and returns true. Returns the command id. | | `unregisterCommand(commandId: number): boolean` | Remove the command corresponding to the given id. Returns `true` if a command was removed, `false` otherwise. | | `preventDefault(): void;` | Prevent registered commands to show. Useful when only context commands are needed. | | `groupPositions: Object` | An object with `select`, `visibility` and `color` properties that represent the group positions of corresponding default commands. | ## Command Interface | Property | Description | | :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `label: string` | The text displayed on the menu. | | `picto: string` | Usually a letter to show the associated shortcut. | | `execute()` | The function to execute when the command is clicked. | | `predicate()?` | An optional predicate function that is run when the context menu opens. The command is displayed if the function returns `true`. If the predicate is an `async` function, the command is displayed when the `Promise` returned by the function resolves. | | `group?: number` | The group the command belongs to. **Default** to 0. | | `position?: number` | The position where to display the command in its group. **Default** to 0. | ## Examples This examples are plugins or plugin components. ### Command with predicate **Description**: The following plugin register a command using the startupScript method. The command is displayed on the context menu only if at least one element is selected. Once clicked, the selected objects are logged. ```javascript const MyPlugin = { name: "selection-log", startupScript($viewer) { const myCommand = { label: "Log selection", execute: () => console.log($viewer.state.selectedObjects), predicate: () => $viewer.state.selectedObjects.length > 0, }; $viewer.contextMenu.registerCommand(myCommand); }, }; ``` ### Context command **Description**: Right clicking on the button element clear default commands and add a custom command to the context menu. The command is called "Hello" and log "Hello World !" on the console. ```javascript { methods: { onContextMenu() { this.$viewer.contextMenu.registerContextCommand({ label: "Hello", execute: () => console.log("Hello World !"), }); }, }, template: `
`, } ``` --- --- url: /viewer/reference/keyboard_shortcuts.md --- # Keyboard shortcuts Keyboard shortcuts can be registered using the `localContext` and the `globalContext`. `localContext` keyboard shortcuts are triggered only if the mouse is hovering the correspinding `localContext`, taking priority over `globalContext` keyboard shortcuts registered on the same key. ```js const myComponent = { created() { this.$viewer.globalContext.registerShortcut({ name: "message", key: "m", execute: () => console.log(`"m" key pressed GLOBALLY`), }); this.$viewer.localContext.registerShortcut({ name: "message", key: "m", execute: () => console.log(`"m" key pressed LOCALLY`), }); }, } ``` --- --- url: /viewer/reference/header.md --- # Header The `header` API is available on the `globalContext` and allows to add content on the viewer header. The API is the following: | Property | Description | | :------------------------------------------ | :------------------------------------------- | | `addContent(content: HeaderContent)` | Add content into the header. | | `removeContent(contentName: string)` | Remove a content by its name. | | `headerContent: Map` | A map containing the header content objects. | The `HeaderContent` interface is the following: | Property | Description | | :---------------------------- | :----------------------------------------------------------------------------------------------------- | | `name: string` | **Required** A name to identify the content. | | `component: Object` | A Vue.js 3.x component to be rendered on the viewer header. | | `position: "left" or "right"` | The position of the content on the viewer header. | | `order: number` | A number for sorting the content along other contents displayed on the same side on the viewer header. | Here is an example of a plugin using the `startupScript` option to register content into the viewer header: ```js bimdataViewer.registerPlugin({ name: "headerPlugin", startupScript($viewer) { const { globalContext } = $viewer; globalContext.header.addContent({ name: "window-manager", component: MyComponent, position: "right", order: 1, }); } }) ``` --- --- url: /viewer/reference/native_plugins.md --- # Native plugins The BIMDataViewer is shipped with native plugins that allow basic interaction with ifcs/models. To enable/disable/configure them, use their name with the corresponding configuration on the `plugins` section of the `makeBIMDataViewer` configuration object. Example: ```javascript const viewer = makeBIMDataViewer({ plugins: { viewer3d: { navCube: false, }, split: true, "structure-properties": { merge: true, }, }, }); ``` Some plugins have an [instance](./plugin.md#plugin-component-instance) API that can be used to interact with them: Example: ```javascript $viewer.globalContext .plugins.get("structure-properties") .forEach(plugin => plugin.reloadTrees()); ``` ## BCF * name: `bcf` The BCF plugin allows to interact with the BIMData BCF API by opening the [BCF Manager plugin](#bcf-manager). This is a button plugin that can be added to any [**viewer window**](./viewer_plugins.md). ::: warning Note In order to use BCF features you have to enable the [**BCF Manager plugin**](#bcf-manager) (enabled by default). The BCF plugin will be useless if BCF Manager is not enabled. ::: ### Configuration | Name | Type | Description | | :---------- | :------- | :---------- | | `topicGuid` | `string` | **guid** of the topic that will be opened automatically when the plugin is mounted | ## Drawing Tools * name: `drawing-tools` The Drawing Tools plugin allows to enrich plans from the [**viewer plan**](#viewer-plan) with drawings. Drawings can be predefined shapes like lines, arrows, circles or rectangles, free hand drawings or texts. Except for texts, the line width and the color can be customized for each drawing. Once created, the drawings are stored on the BIMData API. It is possible to move or delete drawings using the corresponding tools (pointer / eraser). It is also possible to edit the text drawing by clicking on them while the text tool is active. Once the input is active, the font size and the text content can be changed. The Drawing Tools plugin is disabled by default. To enable it, add the following entry into the `plugins` property object of the [`makeBIMDataViewer`](#native-plugins) function: ```js const viewer = makeBIMDataViewer({ plugins: { "drawing-tools": true, }, }); ``` ## BCF Manager * name: `bcfManager` The BCF Manager plugin is a window plugin that provides a complete UI to view/create/update/delete BCF topics in the current project. ## Fullscreen * name: `fullscreen` A plugin as button that allows to request fullscreen on the window it lays in. ## Projection * name: `projection` A plugin as button that sends projection type information on the `localContext.hub` when user change it through the UI. It **requires** the `viewer3d` plugin. ## Search * name: `search` A plugin as button that allows to search object by uuids or names. ## Section * name: `section` A plugin as button that allows to create section planes in the `viewer3d` plugin. As mentionned, it **requires** the `viewer3d` plugin to work properly. ## Split * name: `split` Disabled by default, the split plugin add the ability to split the ifc according to the selection, through a command on the context menu. ## Structure * name: `structure` The `structure` plugin displays the tree structures of the IFCs. ### Instance API | Name | Description | | :--------------- | :----------------------------------- | | `reload(): void` | Reload the trees of the loaded IFCs. | ## Structure and properties * name: `structure-properties` This plugin is actually two plugins merged together. The `structure` plugin that displays the tree structures of the IFCs. The `properties` plugin that displays the properties of the selected objects. ### Configuration | Name | Type | Description | | :--------------------- | :-------- | :------------------------------------------------------------------- | | `merge` | `boolean` | **Default** to `false`. Add the merge ifcs option on the structure. | | `export` | `boolean` | **Default** to `false`. Add the export ifcs option on the structure. | | `editProperties` | `boolean` | **Default** to `false`. Allows editing properties. | | `translateIfcEntities` | `boolean` | **Default** to `false`. Enable IFC Entites translation. | | `customTranslations` | `Object` | Provide custom translations for IFC types (see example below). | Here is an example usage of the `customTranslations` configuration: ```js const customTranslations = { fr: { IfcBeam: "Poutre", IfcDoor: "Porte", IfcSlab: "Dalle", IfcSpace: "Pièce / Espace", IfcWall: "Mur / Paroi", IfcWindow: "Fenêtre / Ouverture", // etc... }, en: { IfcBeam: "Beam", IfcDoor: "Custom Door name", IfcSlab: "Slab", IfcSpace: "Space", IfcWall: "Wall", IfcWindow: "Window", // etc... }, }; const viewer = makeBIMDataViewer({ // ... plugins: { "structure-properties": { translateIfcEntities: true, // has to be true to display translations customTranslations, } } }); ``` ### Instance API | Name | Description | | :-------------------- | :----------------------------------- | | `reloadTrees(): void` | Reload the trees of the loaded IFCs. | ## Window Manager * name: `window-manager` This plugin is in two parts. The first part is displayed if there is only one window without header. It is displayed as a button on the top-right of the window, and add the possibility to split the current window by half, and add the new window where the user want (top, bottom, right or left). The second part is on the right side of the header, and allows to enable split and shows window option. ## Viewer 3D (IFC) * name: `viewer3d` This plugin allows to view 3D representation of IFC models. This is a [viewer plugin](./viewer_plugins.md). ### Configuration | Name | Type | Description | | :------------------------ | :-------- | :---------- | | `pivotMarker` | `boolean` | **Default** to `true`. Add a pivot marker of the rotation center when pivoting | | `navCube` | `boolean` | **Default** to `true`. Add the navCube to facilitate the 3D navigation | | `edges` | `boolean` | **Default** to `true`. Add model edges | | `enableOffsets` | `boolean` | **Default** to `false`. Allow model objects to be translated. This increase GPU memory usage | | `enableDynamicLOD` | `boolean` | **Default** to `true`. If FPS are too low, complex objects will be hidden during camera moves. This allow a better navigation on low-end computers or with very big models. This decrease GPU memory usage | | `home` | `boolean` | **Default** to `true`. Reinitialize point of view and reset all objects state (visibility, x-ray) | | `navigationVersionsModel` | `boolean` | **Default** to `true`. Allows navigation between various version of models | | `interactiveSpaces` | `boolean` | **Default** to `false`. Allow interaction with IfcSpaces | `scaleCanvasResolution` | `boolean` | **Default** to `true`. Scale down the canvas resolution when the camera is moving. `defaultScaleCanvasResolutionFactor` | `number` | **Default** to `0.8`. Default canvas resolution scale factor. Value between `0` and `1`. Lower values increase performance but decrease quality. | `performanceModeScaleCanvasResolutionFactor` | `number` | **Default** to `0.5`. Scale down the canvas resolution when the performance mode is activated. Value between `0` and `1`. Lower values increase performance but decrease quality. | ### Events | Name | Payload | Description | Emitted on | | :------------------ | :------ | :---------- | :--------- | | `3d-model-loading` | `{ ifc, plugin }` | Emitted when a 3D model is loading. | `localContext` and `globalContext` | | `3d-model-loaded` | `{ model, plugin }` | Emitted when a 3D model is loaded. | `localContext` and `globalContext` | | `3d-model-unloaded` | `{ model, plugin }` | Emitted when a 3D model is unloaded. | `localContext` and `globalContext` | | `annotation-create` | [`{ id, annotation }`](https://xeokit.github.io/xeokit-sdk/docs/class/src/plugins/AnnotationsPlugin/Annotation.js~Annotation.html) | Emitted when an annotation marker is created. | `localContext` and `globalContext` | | `annotation-click` | [`{ id, annotation }`](https://xeokit.github.io/xeokit-sdk/docs/class/src/plugins/AnnotationsPlugin/Annotation.js~Annotation.html) | Emitted when an annotation marker is clicked. | `localContext` and `globalContext` | | `annotation-delete` | `{ id }` | Emitted when an annotation marker is deleted. | `localContext` and `globalContext` | | `annotation-clear` | No payload | Emitted when annotation marker are cleared. | `localContext` and `globalContext` | | `3d-camera-update` | `{ eye: number[], look: number[], up: number[] }` | Emitted when the camera is updated | `globalContext` | ### Instance API This API is available in a `3d` window: ```javascript const viewer3dPlugin = this.$viewer.localContext.plugins.get("viewer3d"); ``` | Name | Description | | :--- | :---------- | | `xeokit` | [The Xeokit viewer](https://xeokit.github.io/xeokit-sdk/docs/class/src/viewer/Viewer.js~Viewer.html) | | `xeokitSdk` | [The Xeokit SDK](https://xeokit.github.io/xeokit-sdk/docs/) | | `selectOnClick: boolean` | **Default** to `true`. If true, clicking an object select it. | | `highlightOnHover: boolean` | **Default** to `true`. If true, hovering an object highlight it. | | `getProjection(): string` | Return current projection | | `changeProjection(projection: string): void` | Set current projection | | `isolateObjects(ids: string[], options: object): void` | Objects with ids not included in `ids` are set to `xrayed = true` & `pickable = false`. | | `isolateObjectsByUuids(uuids: string[], options: object): void` | The same as `isolateObjects` but with `uuids` instead of `ids`. | | `reintegrateObjects(): void` | Unisolate objects (opposite action of `isolateObjects`). | | `setObjectsVisible(ids: string[], visible: boolean)`| Update the `visible` property of the corresponding objects. | | `setObjectsSelected(ids: string[], selected: boolean)`| Update the `selected` property of the corresponding objects. | | `setObjectsColorized(ids: string[], color: boolean)`| Update the `colorized` property of the corresponding objects. | | `setObjectsHighlighted(ids: string[], highlighted: boolean)`| Update the `highlighted` property of the corresponding objects. | | `setObjectsPickable(ids: string[], pickable: boolean)`| Update the `pickable` property of the corresponding objects. | | `setObjectsXrayed(ids: string[], xrayed: boolean)`| Update the `xrayed` property of the corresponding objects. | | `setObjectsOpacity(ids: string[], opacity: boolean)`| Update the `opacity` property of the corresponding objects. | | `setObjectsCulled(ids: string[], culled: boolean)`| Update the `culled` property of the corresponding objects. | | `setInteractiveSpaces(interact: boolean)`| Makes IfcSpace objects pickable. | `setCameraOnTop(uuids: string[]): void` | Set the camera on top of the given objects, looking at their center. | `getObjectsCenter(uuids: string[]): number[]` | Return the world coordinates of the center of the given objects. | ## Viewer 2D (IFC) * name: `viewer2d` This plugin allows 2D representation of an IFC. This is a [viewer plugin](./viewer_plugins.md). ### Configuration | Name | Type | Description | | :------------------------ | :-------- | :---------- | | `compass` | `boolean` | Whether to display compass or not. Defaults to `true`. | | `help` | `boolean` | Whether to display help button or not. Defaults to `true`. | | `modelLoader` | `string` | See [viewers config](./viewer_plugins.md#viewers-common-config). Possible values: `"hidden"`, `"disabled"`, allows to control models loader display. By default model loader is displayed and enabled. | | `storeySelector` | `boolean` | Whether to display storey selector or not. Defaults to `true`. | | `storeySelectorAutoOpen` | `boolean` | Whether storey selector should auto open on model loading or not. Defaults to `true`. | ### Events | Name | Payload | Description | Emitted on | | :------------------ | :------------------ | :----------------------------------- | :--------------------------------- | | `2d-model-loaded` | `{ model, plugin }` | Emitted when a 2D model is loaded. | `localContext` and `globalContext` | | `2d-model-unloaded` | `{ model, plugin }` | Emitted when a 2D model is unloaded. | `localContext` and `globalContext` | ### Instance API This API is available in a `2d` window: ```javascript const viewer2dPlugin = this.$viewer.localContext.plugins.get("viewer2d"); ``` | Name | Description | | :--- | :---------- | | `viewer: E2D.Viewer` | The [engine 2D viewer](https://2d-engine.bimdata.io). | | `selectOnClick: boolean` | **Default** to `true`. If true, clicking an object select it. | | `highlightOnHover: boolean` | **Default** to `true`. If true, hovering an object highlight it. | | `spacesVisible: boolean` | **Default** to `true`. If `true`, the space names are displayed. | | `doorsDisplayed: boolean` | **Default** to `false`. If `true`, the doors are displayed. | | `compassDisplayed: boolean` | **Default** to `true`. If `true`, the compass is displayed. | | `camera3DSynchronization: boolean` | **Default** to `false`. If `true`, the camera follows the rotation of a 3D camera and an icon representing the 3D camera position is displayed. | | `syncRotationFrom3DCamera(eye: number[], look: number[], up: number[]): void` | **Default** arguments are `eye = [0, 0, 0], look = [0, 0, 0],up = [0, 1, 0]`. Synchronize the rotation between the given 3D camera parameters and the 2D camera. | ## Viewer DWG * name: `dwg` This plugin allows to view DWG models. This is a [viewer plugin](./viewer_plugins.md). ### Events | Name | Payload | Description | Emitted on | | :------------------- | :------------------ | :------------------------------------ | :--------------------------------- | | `dwg-model-loaded` | `{ model, plugin }` | Emitted when a DWG model is loaded. | `localContext` and `globalContext` | | `dwg-model-unloaded` | `{ model, plugin }` | Emitted when a DWG model is unloaded. | `localContext` and `globalContext` | ### Instance API This API is available in a `dwg` window: ```javascript const viewerDWGPlugin = this.$viewer.localContext.plugins.get("dwg"); ``` | Name | Description | | :-------------------------- | :--------------------------------------------------------------- | | `viewer: E2D.Viewer` | The [engine 2D viewer](https://2d-engine.bimdata.io). | | `selectOnClick: boolean` | **Default** to `true`. If true, clicking an object select it. | | `highlightOnHover: boolean` | **Default** to `true`. If true, hovering an object highlight it. | | `hideAll(): void` | Hide all objects. | ## Viewer DXF * name: `dxf` This plugin allows to view DXF models. This is a [viewer plugin](./viewer_plugins.md). **Events** and **Instance API** are the same as the [Viewer DWG](#viewer-dwg). ## Viewer Plan * name: `plan` This plugin allows to view bitmap plans (PDF, PNG, JPG, METABUILDING models). This is a [viewer plugin](./viewer_plugins.md). ### Configuration | Name | Type | Description | | :------------------------ | :-------- | :---------- | | `help` | `boolean` | Whether to display help button or not. Defaults to `true`. | | `modelLoader` | `string` | See [viewers config](./viewer_plugins.md#viewers-common-config). Possible values: `"hidden"`, `"disabled"`, allows to control models loader display. By default model loader is displayed and enabled. | | `metaBuildingStructure` | `boolean` | Wether to display meta-building structure panel when a meta-building is loaded. If set to `false` a storey selector will be used instead. Defaults to `true`. | | `storeySelector` | `boolean` | Whether to display storey selector or not. Defaults to `true`. | | `storeySelectorAutoOpen` | `boolean` | Whether storey selector should auto open on model loading or not. Defaults to `true`. | ### Events | Name | Payload | Description | Emitted on | | :------------------- | :------------------ | :------------------------------------- | :--------------------------------- | | `plan-model-loaded` | `{ model, plugin }` | Emitted when a plan model is loaded. | `localContext` and `globalContext` | | `plan-model-unloaded` | `{ model, plugin }` | Emitted when a plan model is unloaded. | `localContext` and `globalContext` | | `pdf-page-changed` | `{ model, page }` | Emitted when a pdf page is changed. | `localContext` only | | `storey-loaded` | `{ storey }` | Emitted when a storey is fully loaded. | `localContext` and `globalContext` | ### Instance API This API is available in a `plan` window: ```javascript const viewerPlanPlugin = this.$viewer.localContext.plugins.get("plan"); ``` | Name | Description | | :------------------- | :---------------------------------------------------- | | `viewer: E2D.Viewer` | The [engine 2D viewer](https://2d-engine.bimdata.io). | | `selectedStorey: Storey` | Currently selected (displayed) storey (`null` if not a METABUILDING model) | | `bitmaps: any[]` | Array of loaded bitmaps | | `pdfPages: any[]` | Array of pages models (for multipage PDF) | | `pdfPageIndex: number` | Current PDF page index (for multipage PDF) | | `nextPdfPage(): Promise` | (*async*) Switch to the next PDF page (if any) | | `prevPdfPage(): Promise` | (*async*) Switch to the previouos PDF page (if any) | | `setPdfPage(index: number): Promise` | (*async*) Go to the specified PDF page (if it exist). **Note:** pages are indexed from 0 to n-1. | | `exportAsPNG(): Promise` | (*async*) Get a base64 URL of PNG screenshot of the viewer | | `exportAsJPG(): Promise` | (*async*) Get a base64 URL of JPG screenshot of the viewer | | `exportAsPDF(): Promise` | (*async*) Generate and return a PDF with the viewer content | ## Viewer Point Cloud * name: `pointCloud` This plugin allows to view point cloud models. This is a [viewer plugin](./viewer_plugins.md). ### Events | Name | Payload | Description | Emitted on | | :---------------------------- | :------------------ | :-------------------------------- | :--------------------------------- | | `pointcloud-model-loaded` | `{ model, plugin }` | Emitted when a model is loaded. | `localContext` and `globalContext` | | `pointcloud-model-unloaded` | `{ model, plugin }` | Emitted when a model is unloaded. | `localContext` and `globalContext` | ### Instance API This API is available in a `pointCloud` window: ```javascript const pointCloudPlugin = this.$viewer.localContext.plugins.get("pointCloud"); ``` | Name | Description | | :--- | :---------- | | `xeokit` | [The Xeokit viewer](https://xeokit.github.io/xeokit-sdk/docs/class/src/viewer/Viewer.js~Viewer.html) | | `xeokitSdk` | [The Xeokit SDK](https://xeokit.github.io/xeokit-sdk/docs/) | ## 3D parameters * name: `viewer3d-parameters` A button plugin that allows to configure highlight, edges and spaces visibility. Parameters are saved in local storage. ## 2D parameters * name: `viewer2d-parameters` A button plugin that allows to configure door openings and space names. Parameters are saved in local storage. ## 2D measurements * name: `measure2d` A button plugin that allows to measure distances, angles and surfaces in the 2D viewer Measurements are saved in local storage. ## Zone Editor Button * name: `zone-editor-button` This plugin opens the [Zone Editor plugin](#zone-editor). ## Zone Editor * name: `zone-editor` The Zone Editor plugin is a window plugin that provides a complete UI to manage zones on a Meta Building. ### Events | Name | Payload | Description | Emitted on | | :---------------------------- | :------------------- | :-------------------------------- | :--------------------------------- | | `zone-created` | `{ zone }` | Emitted when a zone is created. | `localContext` and `globalContext` | | `space-created` | `{ space }` | Emitted when a space is created. | `localContext` and `globalContext` | | `zone-deleted` | `{ zone }` | Emitted when a zone is deleted. | `localContext` and `globalContext` | | `space-deleted` | `{ space }` | Emitted when a space is deleted. | `localContext` and `globalContext` | | `zone-updated` | `{ zone, changes }` | Emitted when a zone is updated. | `localContext` and `globalContext` | | `space-updated` | `{ space, changes }` | Emitted when a space is updated. | `localContext` and `globalContext` | --- --- url: /viewer/reference/viewer_plugins.md --- # Viewer Plugins Viewer plugins (also referred to as *viewer windows*) are a special kind of plugin that provide a model viewer. They share some [common configuration options](#viewers-common-config) and a [common API](#viewers-common-api) to perform some generic operations and can also have some specific methods that depend on the type(s) of model they can handle. Here is the list of native viewer plugins: * [Viewer IFC 3D](#viewer-ifc-3d) * [Viewer IFC 2D](#viewer-ifc-2d) * [Viewer DWG/DXF](#viewer-dwg-dxf) * [Viewer Plan](#viewer-plan) * [Viewer Point Cloud](#viewer-point-cloud) ## Viewers common config Every viewer plugin has the following config properties: ```typescript interface ModelViewerConfig { /** * Control the model loader visibility: * - If `hidden`, the component isn't shown but it will load models defined in the viewer parameters. * - If `disabled`, the models won't be loaded and you must load them manually (using the `viewer.loadModels` method). */ modelLoader?: "hidden" | "disabled"; } ``` ## Viewers common API ```typescript interface ModelViewerInstance extends PluginInstance { modelTypes?: string[]; annotationMode: boolean; getViewpoint(options?: any): Promise; setViewpoint(viewpoint: any, options?: any): Promise; startAnnotationMode(callback: Function): void; stopAnnotationMode(): void; fitView(options?: any): void; showUI(options?: any): Promise; hideUI(options?: { exceptions: string[] }): Promise; } ``` **Note:** these APIs are also available [on the `localContext`](./local_context.md#viewer-interface). ## Viewer IFC 3D * Window name: `3d` * Plugin name: `viewer3d` ```typescript interface ViewerIfc3D extends ModelViewerInstance { xeokit: XktViewer; xktModels: Map; // Parameters edgesDisplayed: boolean; highlightOnHover: boolean; selectOnClick: boolean; // Methods getProjection(): string; changeProjection(projection: string): void; isolateObjects(ids: number[], options?: any): void; // Objects with ids not included in `ids` are set to `xrayed = true` & `pickable = false`. isolateObjectsByUuids(uuids: string[], options?: any): void; // The same as `isolateObjects` but with `uuids` instead of `ids`. reintegrateObjects(): void; // Unisolate objects (opposite action of `isolateObjects`). setObjectsVisible(ids: number[], visible: boolean); // Update the `visible` property of the corresponding objects. setObjectsPickable(ids: number[], pickable: boolean); // Update the `pickable` property of the corresponding objects. setObjectsSelected(ids: number[], selected: boolean); // Update the `selected` property of the corresponding objects. setObjectsHighlighted(ids: number[], highlighted: boolean); // Update the `highlighted` property of the corresponding objects. setObjectsXrayed(ids: number[], xrayed: boolean); // Update the `xrayed` property of the corresponding objects. setObjectsColorized(ids: number[], color: boolean); // Update the `colorized` property of the corresponding objects. setObjectsOpacity(ids: number[], opacity: boolean); // Update the `opacity` property of the corresponding objects. setObjectsCulled(ids: number[], culled: boolean); // Update the `culled` property of the corresponding objects. } ``` ## Viewer IFC 2D * Window name: `2d` * Plugin name: `viewer2d` ```typescript interface ViewerIfc2D extends ModelViewerInstance { viewer: E2D.Viewer; model: Model | null; selectedStorey: Storey | null; // Parameters camera3DSynchronization: boolean; compassDisplayed: boolean; doorsDisplayed: boolean; highlightOnHover: boolean, selectOnClick: boolean; spacesVisible: boolean; } ``` ## Viewer DWG/DXF * Window name: `dwg` / `dxf` * Plugin name: `dwg` / `dxf` ```typescript interface ViewerDwg extends ModelViewerInstance { viewer: E2D.Viewer; // Parameters highlightOnHover: boolean; selectOnClick: boolean; } ``` ## Viewer Plan * Window name: `plan` * Plugin name: `plan` ```typescript interface ViewerPlan extends ModelViewerInstance { viewer: E2D.Viewer; model: Model | null; selectedStorey: Storey | null; pdfPages: any[]; pdfPageIndex: number; // Methods nextPdfPage(): Promise; prevPdfPage(): Promise; setPdfPage(n: number): Promise; exportAsPNG(): Promise; // Get a base64 URL of PNG screenshot of the viewer exportAsJPG(): Promise; // Get a base64 URL of JPG screenshot of the viewer // Generate a PDF document with the viewer content exportAsPDF({ pagesToScan?: number[] }): Promise; } ``` ## Viewer Point Cloud * Window name: `pointCloud` * Plugin name: `pointCloud` ```typescript interface ViewerPointCloud extends ModelViewerInstance { xeokit: XktViewer; // Parameters viewDistance: number; } ``` --- --- url: /viewer/reference/global_components.md --- # Global components Global components are available to allows quick integration (no import needed): * `BIMDataModelLoader` * `BIMDataNoModelWindowPlaceHolder` * `BIMDataStoreySelector` These components are already binded to their corresponding localContext and can be used to update/display the local state. (selected storey, loaded models...) ```html ``` Have a look at [this demo example](../examples/global_components.md) to see how they can be used. ## ModelsLoader ### On viewers By default, the `BIMDataModelLoader` component is available on viewers (3d, 2d, plan, ...). It allows to load/unload models. It is possible [to hide it or disable it](./viewer_plugins.md#viewers-common-config). The `BIMDataModelLoader` has the following interface: | Props | Description | | :--------------------------- | :--------------------------------------------------------------------------------- | | `preview: boolean` | *Default* to `false`. If `true`, hovering a model on the list display its preview. | | `windowPositioning: boolean` | *Default* to `true`. If `false`, it is displayed as a `block`. | | `width: string` | *Default* to `"350px"`. | | `customFilter: Function` | An optional function to filter the models. | --- --- url: /viewer/reference/hubs.md --- # Event Hubs A Hub is an event manager. It allows to register event handler and to trigger events. There are three hubs on the viewer: * The state hub, available on `$viewer.state.hub`. * The local context hub, available on `$viewer.localContext.hub`. * The global context hub, available on `$viewer.globalContext.hub`. The interface of a hub is the following: | Property | Description | | :---------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `on(eventName: string, callback: function, options?: object): number` | A method that register an handler on the event name. When the event is emitted on the hub, the callback function is executed with the event payload as first argument. The `number` returned by the function is the subscription id that can be used to remove the handler. | | `once(eventName: string, callback: function, options?: object): number` | This method is the same as the `on` method, but the callback is executed only once for the given event and then removed from the listerners. | | `off(subscriptionId: number): void` | Cancel the corresponding subscription. | | `emit(eventName: string, payload?: any): void` | Emit an event with a optional payload. | | `clear(): void` | Remove all subscriptions of this hub. | The third parameter `options` is an optional `Object` that accepts the property `getLastEvent` as a boolean (default to `false`). If `true`, the callback is trigered with the last event immediately (if it exists). It can be useful for state synchronization. :::tip Many of the events you may use are State events. Find more [reading the State reference](./state.html#events). ::: :::tip Other useful events are from the global and the local context. Find more reading the [globalContext](./global_context.md#events) and [localContext](./local_context.md#events) references. ::: --- --- url: /viewer/reference/annotations.md --- # Annotation API ### State The [state](./state.md) provide a way to manage a set of annotation objects. ```typescript interface Annotation { readonly id: number; // Coordinates x: number; y: number; z: number; // Settings draggable: boolean; grabberSelector?: string; // Vue component used to render annotation on viewer component: any; // Optional props to pass to the annotation component props?: any; } ``` Annotation related fields and methods accessible from the [state](./state.md): | Name | Description | | :-------------------------------------- | :-------------------------------------------------------------- | | `annotations` | The list of all annotations (read only) | | `addAnnotation(annotation, options)` | Add an annotation to the state | | `removeAnnotation(annotation, options)` | Remove the given annotation from state | | `clearAnnotations()` | Remove all annotations from state | Annotation related events emitted on the [state](./state.md): | Name | Payload | Description | | :---------------------- | :------------------------------------------ | :----------------------------------- | | `annotation-added` | `{ annotation: Annotation, options?: any }` | An annotation has been added | | `annotation-updated` | `{ annotation: Annotation, options?: any }` | An annotation has been updated/moved | | `annotation-removed` | `{ annotation: Annotation, options?: any }` | An annotation has been removed | ### Viewers plugins The [viewers common interface](./viewer_plugins.md#viewers-common-api) includes the following fields and methods to handle annotations: | Name | Description | | :-------------------------------------- | :---------------------------------------------------------------- | | `annotationMode` | Whether annotation mode is enabled or not | | `startAnnotationMode(callback)` | Start (enable) annotation mode with the given annotation callback | | `stopAnnotationMode()` | Stop (disable) annotation mode | The **annotation callback** passed to the`startAnnotationMode()` method as the following signature: ```typescript type AnnotationCallback = ({ // Annotation coordinates x: number, y: number, z: number, // Additional data models: StateModel[], // currently loaded models storey?: StateStorey, // current storey pdfPages?: any[], // list of PDF pages (only relevant for multipage PDF models) pdfPageIndex?: number, // current PDF page index (only relevant for multipage PDF models) object?: StateObject, // annotated IFC element (only relevant for IFC models) }) => void; ``` ## Usage The annotation API is designed to help developers create/update/delete custom annotations that are synchronized between viewer windows. Below are some explanations on the basic usage of the API, you can have a look at the [examples](../examples/ifc_annotations.md) to get a more concrete integration example. #### 1. Add annotations Given any viewer window we can use the [`localContext API`](./local_context.md#viewer-interface) to register an annotation callback that we will allow us to get annotation coordinates on click. The coordinates are used to add a new annotation to the state: ```js const { state, localContext } = $viewer; localContext.startAnnotationMode(({ x, y, z }) => { const annotation = state.addAnnotation({ component: MyAnnotationComponent x, y, z, }); console.log("new annotation: ", annotation); }); ``` When we are done adding annotations we can use `stopAnnotationMode()` to unregister annotation callback: ```js localContext.stopAnnotationMode(); ``` The annotation component (`MyAnnotationComponent` here) can be any valid Vue component, it will be used to render the annotation on the viewer. For convenience, an `annotation` prop, that hold the associated annotation object from the state, is passed to the component. It is also possible to provide some custom props to the component via the `props` field of annotation object. #### 2. Update/Drag annotation Each annotation as a `draggable` property (which is `true` by default) that control whether the annotation can be moved by dragging it on the canvas. Setting `draggable` to `false` will prevent the annotation to be moved. This can be used to implement some kind of annotation lock/unlock mechanism. **Note:** The state will emit an `"annotation-updated"` event on every annotation move. #### 3. Remove annotation Annotations can be removed from the state using the `removeAnnotation()` method: ```js $viewer.state.removeAnnotation(annotation); ``` Annotations can also be removed all at once with `clearAnnotations()`: ```js $viewer.state.clearAnnotations(); ``` --- --- url: /viewer/reference/offline_mode.md --- # Offline Mode In some cases it may be necessary to use the Viewer without network access. A typical usage is when the viewer is embed in a mobile app that will be used in situation where network availability is not guaranteed. For those cases it is possible to enable **offline mode**. Offline mode can be configured on viewer creation using the `api.offline` configuration: ```js // Offline data are passed as a Blob const blob = getOfflineData(); const viewer = makeBIMDataViewer({ api: { // ... offline: { enabled: true, data: blob } }, // ... }); ``` It is also possible to enable offline mode dynamically after the viewer was instanciated using the [`enableOfflineMode()`](./$viewer.md#api) method. ```js // Enable offline mode await $viewer.api.enableOfflineMode(blob); // Offline mode can also be disabled later $viewer.api.disableOfflineMode(); ``` ## How it works For the viewer to work in offline mode you need to provide an *"offline package"* which is a zip archive that contains data prefetched from BIMData API and needed by the viewer to work properly. To generate an offline package you have to use the `/offline-package` route on our archive backend (https://archive.bimdata.io/). An archive is generated for a given set of models that must be specified as query parameters. Here is an example using `curl` to create an archive for models `123` and `456` that are in project `2` of space `1`: ```bash curl "https://archive.bimdata.io/cloud/1/project/2/offline-package?modelId=123&modelId=456" \ -H "Authorization: Bearer " \ -o my-offline-package.zip ``` Once generated you need to make the archive accessible to your application and load it as a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) using javascript before pasing it to the viewer. The way the archive is made accessible and loaded depends on your environment and is up to you. ## Android example In the context of an Android app using [WebViews](https://developer.android.com/reference/android/webkit/WebView) it is possible to package your archive with your application and use a [WebViewAssetLoader](https://developer.android.com/reference/androidx/webkit/WebViewAssetLoader) to load the archive using an URL of the form `https://appassets.androidplatform.net/*`. You can have a look at our [android-example repository](https://github.com/bimdata/android-example) to get a demo project showing how to integrate the viewer into an android application and use it in oflline mode. --- --- url: /viewer/mobile.md --- # Mobile ## Config In order to have functional UI for mobile you need to set the [`ui.mobile` config](./reference//makeBIMDataViewer.md#ui) to `true`. ## Mobile Viewer IFC A plugin with specific mobile interactions is natively available in the BIMDataViewer. To use it, give the `"mobile"` window name as second argument of the [mount method](./reference/mount.md) when mounting the BIMDataViewer into the DOM. ```js bimdataViewer.mount("#app", "mobile"); ``` The plugin is composed of **three** main elements from top to bottom: * storey selector * viewer 2D as a mini map * viewer 3D It has the following [instance](./reference/plugin.md#plugin-component-instance) API: | property | Description | | :-------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------- | | `map2dShown: boolean` | If `false`, the viewer 2D or mini map is not shown. | | `viewer2d: Object` | The [Vue.js](https://vuejs.org/) component holding the [BIMData 2D-Engine](https://2d-engine.bimdata.io/) on the `engine2d` property. | | `viewer3d: Object` | The [Vue.js](https://vuejs.org/) component holding the 3D viewer from the [xeokit-sdk](https://github.com/xeokit/xeokit-sdk) on the `xeokit` property. | ```js const mobilePlugin = $viewer.globalContext.plugins.get("mobile")[0]; const engine2d = mobilePlugin.viewer2d.engine2d; const xeokit = mobilePlugin.viewer3d.xeokit; ``` ## Mobile Viewer Plan You can use the mobile specific plan viewer with the `"mobile-plan"` window. ```js bimdataViewer.mount("#app", "mobile-plan"); ``` ## Mobile Viewer DWG / DXF You can use the mobile DWG viewer with the `"mobile-dwg"` window (or `"mobile-dxf"` for DXF models). ```js bimdataViewer.mount("#app", "mobile-dwg"); // for DWG bimdataViewer.mount("#app", "mobile-dxf"); // for DXF ``` ## Loading model The model loaded into the mobile plugin is the one loaded on the [localContext](./reference/local_context.md#local-state). ```js this.$viewer.localContext.loadModels([myModelId]); ``` Or at startup using the config object of the [makeBIMDataViewer](./reference/makeBIMDataViewer.md#api) function. ```js const bimdataViewer = makeBIMDataViewer({ api: { modelIds: [15097], // < --- cloudId: 10344, projectId: 237466, accessToken: "TAbdyPzoQeYgVSMe4GUKoCEfYctVhcwJ", }, }); ``` ## Mobile browsers If you plan to embed the viewer into a web page that will be accessed on mobile make sure to add the following `` tag in the `` of your html document: ```html ``` This ensure that the viewer is displayed properly on both desktop and mobile devices ([learn more](https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag)). --- --- url: /viewer/viewer_sdk.md --- # Viewer SDK We have pre-configured a **VueJS** environment to develop BIMData Viewer plugins. You can develop, test, build, package and share your plugin easily. In this section, you get tutorials and references for installing and using the [BIMData Viewer SDK](https://github.com/bimdata/bimdata-viewer-sdk) ## Setup First, you have to clone the sdk repo and install SDK dependencies : ```bash git clone https://github.com/bimdata/bimdata-viewer-sdk.git cd bimdata-viewer-sdk npm install ``` > *Note:* > > If you want to create you own application you can copy the `.env.example` file : > > ```bash > cp .env.example .env > ``` > > Then you can read this guide : [Create your application](https://developers.bimdata.io/api/guides/application.html#which-app-will-you-create) ### Compiles and hot-reloads for development ```bash npm run dev ``` ### Usage When going on http://localhost:8080, a simple interface will let you open the project and model you want. You can directly open one by opening an URL using specific Ids, for example : http://localhost:8080/viewer?cloudId=391\&projectId=634\&ifcId=1491 ## Create your plugin ```bash npm run init-plugin ``` This tool asks you a couple of questions about the plugin you develop and generate from your answers boilerplate files for your plugin. Files are created in the directory `src/plugins/{name_of_your_plugin}`. Then import your newly created plugin in `src/viewer/viewer.vue` and add it to the `registeredPlugin` array. ```javascript import SnowflakesPlugin from "@/plugins/snowflakes/src/snowflakes.plugin.js"; import SplitPlugin from "@/plugins/split/src/split.plugin.js"; ... mounted() { this.$refs.bimdataViewerInstance.registerPlugins([ SnowflakesPlugin, SplitPlugin, ]); } ... ``` ## Package your plugin To load your plugin in a real environment, you need to package and publish your plugin. The plugin template is pre-configured with a [rollup](https://rollupjs.org/) config that let you do this easily: ```bash cd src/plugins/{your_plugin} npm install npm run build ``` This creates a `dist/` folder in your plugin directory with a simple js file. This minified file includes the CSS and the assets (encoded in base64). It's not the most performant way, but it's the simplest and the Viewer loads many mega-bytes models anyway. You can either copy-paste this file in your environment and load it at your convenience, or you can publish it on NPM. To publish it, update the `package.json` file with the proper information and just run an `npm publish`. The code is minified to protect your code as much as possible. ### More info about how it works The SDK itself uses *Webpack* to build. The packaging uses *Rollup*. If you need a complex JS flow, it may lead to some issues. To see these issues before deploying, load the packaged version in the SDK: ```bash cd src/plugins/{your_plugin} npm run watch ``` And load the dist version of the plugin: ```js import SplitPlugin from "@/plugins/split/dist/split.plugin.js"; ... mounted() { this.$refs.bimdataViewerInstance.registerPlugins([ SplitPlugin, ]); } ... ``` You can also edit the webpack and rollup config as you want. --- --- url: /viewer/release_notes.md --- # Release Notes ## v2.18.0 (2026-08-26) ### Feature * **New Fragments Viewer** !!! * Layout: allow multiple side panels in local context * Mobile: Viewer Mobile DWG ### Bugfixes * BCF: topic state sync ## v2.17.2 (2026-05-25) ### Features * IFC 3D: add color selector in context menu ### Bugfixes * IFC 2D / DWG: white lines in dark mode ## v2.17.1 (2026-04-23) ### Bugfixes * IFC 3D: fix demo xkt loading ## v2.17.0 (2026-04-08) ### Features * IFC 2D: new synchronization plugin (with anchors) * Plan: fit view on all plans ### Bugfixes * IFC: fix bug in first person view mode * IFC: fix fit view when loading multiple models at once * IFC: improve performance of structure plugin ## v2.16.3 (2026-02-26) ### Bugfixes * IFC 2D: show spaces areas * IFC 2D: fix rotation issue * Plan: add tooltip on clibration button * BCF: avoid error when exporting many topics ## v2.16.2 (2026-02-10) ### Bugfixes * IFC 2D: fix rotation plugin for Mac OS * Mobile: fix 3D engine setup and 2D camera positioning * Point Cloud: tile handle full rootTransform matrix ## v2.16.1 (2026-01-22) ### Bugfixes * DWG: fix new Engine 2D integration ## v2.16.0 (2026-01-08) ### Features * DWG: new Engine 2D with better perfomance ### Bugfixes * Plan: fix drawings in PDF models ## v2.15.1 (2026-01-07) ### Bugfixes * Plan: fix measurement plugin ## v2.15.0 (2025-12-09) ### Features * IFC/Plan: Annotation 360 ### Bugfixes * BCF: fix bcf export when all topics are selected * Point Cloud: handle tile data with no content * Point Cloud: fix tiles center positioning * Plan: fix model transform with multiple plans ## v2.14.0 (2025-11-14) ### Features * IFC: partial loading: ability to filter loaded elements via viewer config ([see example](./examples/partial_loading.md)) * Plan: display zones/spaces for models other than Meta Building * Plan: rotation plugin * Plan: 360 annotations * BCF: view annotations of all topics * BCF: topic documents and groups ### Bugfixes * BCF: properly handle overflow for topic objects list * i18n: update and fix translations for English, German and Spanish ## v2.13.0 (2025-10-27) ### Features * Viewer Plan: add `fitViewRequested` param to [`selectStorey`](./reference/local_context.md#local-state) method ### Bugfixes * Fix bug with button plugin active state * Fix bugs with multiple viewer instances on the same page * Fix 3D camera control keymap * Fix 3D model loading with no chunks * Fix Point Cloud section plugin * Fix caliper for DWG measures * Plan: Fix `fitView` for zones/spaces ## v2.12.0 (2025-07-30) ### Features * Viewer Plan refactoring * [Viewer Plan Mobile](./mobile.md#mobile-viewer-plan) * Plan: add plan mask feature * Plan: add 'panDisabled' option to drawing-tools config * Plan: use `model.transform` instead of storey plan porsitioning * Plan: label plugin * DWG: add calibration tool ### Bugfixes * MetaBuilding: fix view fit on storey change * IFC 2D: fix setPickable/Unpickable * Plan: fix bug when spam clicking 'next page' button * Plan: use Pointer Events instead of Touch Events in drawing-tools ## v2.11.0 (2025-06-11) ### Features * BCF: add 'stage' field to export and filters * IFC: 3D models chunks * Plan: Model Positioning * Plan: add drawing events on create, update, delete ### Bugfixes * BCF: handle topics whith no model attached * BCF: open topic 'default' window if no layout is specified * BCF: use user locale in xlsx export * Model Loader: fix bug with model preview * IFC: properly handle model unload in structure * Plan: fix drawings on PDF pages * Plan: fix PDF export on chromium based browsers ## v2.10.1 (2025-05-12) ### Bugfixes * Avoid error when switching PDF pages quickly * Update API client to v10.21.3 ## v2.10.0 (2025-04-28) ### Features * 3D Section plugin rework. The section planes are no longer disabled when the plugin is closed. ### Bugfixes * BCF comment snapshot with multi-windows was broken * DWG Layers CSS issue ## v2.9.0 (2025-04-23) ### Features * New model loader UI * Viewer IFC 3D: add 'Interactive Spaces' parameter (can be switched *On* or *Off*, was always *On* before) * Improve IFC structure performance * Improve PDF export performance ### Bugfixes * Fix: handle viewer photosphere topic viewpoint * Fix: improve mobile compatibility * Fix: encapsulate internal styles to avoid CSS leaks * Fix: drawings creation on mobile device * Fix: children count in IFC structure tree * Fix: PDF viewer window resize ## v2.8.0 (2025-03-10) ### Features * Drawing tools text color ### Bugfixes * Fix plan section deletion error ## v2.7.0 (2025-02-17) ### Features * Photosphere viewer * Improve PDF export performance * Improve Structure performance * i18n: Update translations ### Bugfixes * Fix BCF annotation edition (create/update/delete) * Avoid annotation drag & drop on right-click ## v2.6.1 (2024-12-12) ### Features * Add "field of view" param to point cloud viewer parameters * Smartview selection feature * Smartview show/hide feature * Edit smartviews feature ## v2.6.0 (2024-11-18) ### Feature * DWG Viewer now supports layouts. You can now switch between different layouts in the same DWG file. * [BIMData Viewer can no be used on mobile with a special UI](./mobile.html) * Offline archives with PDF models can be lighter with the trade off of higher CPU usage during load. * Point density on point clouds is now better * Smartviews plugin has been improve and allow to mix many views ### Bugfixes * Editing properies works again * Fix annotations on 3D and 2D at the same time when 3D annotation goes behind the camera * Many fixes in PDF exports with drawings * Fix performance issue with Minimap ## v2.5.0 (2024-09-25) ### Feature * Viewer Plan: add `includeDrawings` param to `exportAsPdf()` method * Add button-structure and button-properties plugins * Add `bimdata_elevation` field to state storeys * Add zone creation event on local/global contexts * Update translations * Add `area` and `perimeter` getters on state zones ### Bugfixes * Fix: injection for annotation components * Fix: pdf page selection in building maker * Fix: properly set localContext resolution on pdf export * Fix: load xkt file on models with no explicit xkt versions * Fix: add model name to IfcProject structure * Fix(Viewer 3D): LOD * Fix(Viewer Plan): properly handle models without document * Fix: add touch event for 3D annotation mode & annotations drag & drop ## v2.4.1 (2024-08-14) ### Bugfixes * Correctly load viewpoint if no topic layout specified * Fix persistent spinner when opening BCF Manager * Fix Meta-Building storey change handler ## v2.4.0 (2024-08-09) ### BREAKING CHANGES #### Window Lifecycle `loadWindow` is called in *setup* intead of *mounted*, This means that it is no longer possible to access `localContext.el` in the `created()` hook, it will only be available from the `mounted()` hook and after. Before: ```js export default { created() { this.$viewer.localContext.el.addEventListener( "contextmenu", this.onContextMenu ); }, // ... }; ``` Now: ```js export default { created() { // `this.$viewer.localContext.el` is null here }, mounted() { this.$viewer.localContext.el.addEventListener( "contextmenu", this.onContextMenu ); }, // ... }; ``` #### Annotation API Annotation API has been simplified to provide developers with more flexibility and ease of use. Examples ([IFC](./examples/ifc_annotations.md) and [Plan](./examples/plan_annotations.md)) have been updated accordingly. See [viewer reference](./reference/annotations.md) to learn more. ### Features * [Add globalContext models API](./reference/global_context.md) * Provide annotated object to annotation callback (IFC only) * [Add `metaBuildingStructure` to viewer plan settings](./reference/native_plugins.md#configuration-5) * [Improve PDF export feature](./reference/viewer_plugins.md#viewer-plan) * Save & restore BCF topic layout * Update xeokit * Update english and german translations ### Bugfixes * Fix keyboard shortcuts displayed in help modal * Fix 3D annotations visibility update * Fix IFC property edition ## v2.3.0 (2024-06-27) ### Features * Meta-Building Structure * First person view + Mini map * Add offline options param * Add ability to remove the zone editor "Done" button * Viewer 3D parameters rework * Re-enabled structures root element to show/select all * Viewer plan `fitView()` now accepts zone/space UUIDs as parameters * Add the ability to dynamically change viewer 3D keyboard layout * PDF export optimization ### Bugfixes * Fix error on storey change when no model is loaded * Fix synchronization & background-2d plugins position * Fix viewer plan `fitView()` * Fix: `buildingElevation` fallbacks to `siteElevation` if not set * Fix: model loader spinner on initialization ## v2.2.0 (2024-04-29) ### Features * Update english translations * Add `loadDrawings` and `clearDrawings` methods to drawing tools plugin interface ### Bugfixes * Fix "scroll on zoom" bug for 3D and point cloud viewers * Fix handle touch events for drawing tools * Keep current selection when opening BCF topic creation form * BCF topic auto open * Fix typos ## v2.1.0 (2024-03-22) ### Features * [Add ability to switch offline mode dynamically](./reference/offline_mode.html) * [Add offline methods customization options](./reference/offline_mode.html) ### Bugfixes * Add missing iconOpen plugin option. * window open/close events payload was incorrect. * Change 'api.offline.dataFile' to 'api.offline.data'. * add bcfApi and collaborationApi offline customization options. * remove deprecated of local context & global context plugins getters. ## v2.0.0 (2024-03-07) ### BREAKING CHANGES #### Vue 3 Update to [Vue.js framework version 3](https://vuejs.org/). This brings some breaking changes in the writting of plugins due to the major version increase. Please follow [this guide](https://v3-migration.vuejs.org/) to update your plugins. #### Import via CDN The UMD build is no longer available. To use the global `makeBIMDataViewer` function, you need to update the url and add `type="module"` in the script tag. Before: ```js ``` Now: ```js ``` #### Viewer configuration * **(1)** `menuVisible` property of the `makeBIMDataViewer` `ui` configuration changed to `header`: ```js // OLD makeBIMDataViewer({ ui: { menuVisible: true }}); // NEW makeBIMDataViewer({ ui: { header: true }}); ``` * **(2)** `"window-split"` plugin replaced by `"window-manager"` ### FEATURES [Vue.js v3](https://vuejs.org/) brings the new [composition API](https://vuejs.org/guide/introduction.html#composition-api) & the [script setup support](https://vuejs.org/api/sfc-script-setup.html). [`$viewer`](./reference/$viewer) is available via injection. Example of a plugin using the composition API: ```js import { inject } from "vue"; export default { setup() { const $viewer = inject("$viewer"); // your code here } }; ``` ### DEPRECATED * To limit incompatibility issues, `destroyed` & `beforeDestroy` vue.js component lifecyles are still available but logged as deprecated. Please migrate to `beforeUnmount` & `unmounted`. * `localContext` & `globalContext` `incrementSpinnerProcesses` & `decrementSpinnerProcesses` are deprecated, please use `loadingProcessStart` & `loadingProcessEnd` instead. * `localContext.getPlugin(pluginName: string): Plugin` is deprecated, please use `localContext.plugins: Map` instead. * `globalContext.getPlugins(pluginName: string): Plugin[]` is deprecated, please use `globalContext.plugins: Map` instead. * `BIMDataViewerVue` is the `vue.js` instance the viewer is based on. Use it to write render functions or if you use the composition API in your plugins. ### PLUGIN BUILD Due to the major Vue.js update, plugin build configuration must be updated. As the `h` function is now exposed on the vue.js instance, please use the globally available `BIMDataViewerVue` singleton. Example of vite configuration: ```js import { defineConfig } from "vite"; import vue from "@vitejs/plugin-vue"; import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js"; import externalGlobals from "rollup-plugin-external-globals"; export default defineConfig(() => { return { build: { lib: { entry: "./src/myPlugin.js", formats: ["es"], name: "myPlugin", fileName: "myPlugin.plugin", }, minify: 'terser', }, plugins: [ vue(), cssInjectedByJsPlugin(), externalGlobals({ vue: 'BIMDataViewerVue', // MANDATORY }), ], }; }); ``` ## v1.10.1 (2023-06-14) #### Usages * Add Point Cloud Viewer section plugin * Add spinner while loading models on Point Cloud Viewer * Add PDF Viewer multipage & export features * Add BCF import/export features * The viewer embed native Roboto Font * New Smartview Plugin * Viewer DWG handles hatches / textures * Viewer 3D handles duplicated uuids - It is now possible to open two versions of the same model on the same Viewer 3D. * New viewer 2D shortcut help modal * Add nav-cube to Point Cloud Viewer * Rework DWG Layers * Show properties for systems and zones * Distinguish objects property sets from type property sets in the properties plugin #### Developers * Improved annotation api * [Add Viewer Plan "pdf-page-changed" event](./reference/native_plugins#viewer-plan) * [Add ability to pass params to plugin onOpen/onClose methods](./guide/plugins#plugin_as_button) * Add viewer common interface * [Context menu handles async predicates](./reference/context_menu#command-interface) * [New bimdataViewer `destroy` method to propertly clean it](./reference/makeBIMDataViewer) * [New `setObjectsOpacity` method on the Viewer3D plugin](./reference/native_plugins#viewer-3d-ifc) * [Point Cloud Viewer has `xeokitSdk` exposed and its `viewer` property is renamed as `xeokit`](./reference/native_plugins#viewer-point-cloud) * [Add Viewer Plan 'plan-model-loaded' and 'plan-model-unloaded' events](./reference/native_plugins#viewer-plan) #### Bugfixes * Exported PDF have correct annotation size * Viewer DWG correctly handles unvisible objects when a new model is loaded * Viewer DWG handles opacity & stroke opacity * Selection is deactivated when annotation mode is turned on * Fix annotation API transform style - remove the `transform: translate(-50%, -50%)` native style * Update some english translations * Fix elevation loading on react and angular * Fix IFC Export * Fix select behaviour on GLTF models * Fix structure plugin translation types * Fix DWG texts anchors * An error when attempting to load an already loaded model * Do not clear object selection when opening BCF creation form * Handle deprecated BIMDataAPI IfcApi methods properly ## v1.9.0 (2022-11-24) #### Usages * New DWG & DXF viewer windows * New GED window * New Building Maker window * New BCF Manager window * New Viewer Plan * It is now possible to open different models on different windows (2D, 3D, ...) * New 2D Plan synchronisation * Preview in 3D Model loader * Improved 2D performance * Improved 2D drawing capabilities * 2D Texts * Improved Properties: search + link documents + PDF preview * 3D Measures * Annotations * Calibration * 2D & 3D parameters Space visibility toggle * Rounded 2D lines * 2D Storey selector can be hidden #### Developers * [Exposed Modelsloader](./reference/global_components#modelsloader) * Upgrade xeokit dependency to 2.2 * Upgrade bimdata 2d-engine dependency to 1.14 * Command Manager removed * Logger removed * Warning plugin removed * Add getLocalContexts(windowName) on [$viewer](./reference/$viewer) * [Embed BIMData design system](./guide/index) * Improve state performances * Customizable colors * Use BIMData model API * Refactor state: change ifc to model #### Bugfixes * Display 2D compass correctly while zoomed * Fix 2D storey navigation (2D state, plan draw order, ) * Fix 2D zoom * Fix 2D measurement plugin * improve 3D LOD * Fix 3D orhtographic projection * Fix viewer 3D out of sync state * Fix 2D/3D canvas mouse detection behind Model loader & Storey selector * 2D/3D parameters clean destroy when the window is closed * Fix shortcut error while openning the same window twice * Handle properties long names * Fix property edition * Fix window registration * Fix context menu crash on some conditions * CSS/SCSS Fixes * Fix model loader dropdownlist * Fix autocomplete on search & tags inputs * Fix crash while openning the viewer twice * Better viewer bundle packing * Fix window switching style * Fix properties showing last selected object * Hide plugin as button tooltip while the plugin is open ## v1.8.2 (2021-11-12) #### Developers * Add [`translateIfcEntities` option](./reference/native_plugins#structure-and-properties) ## v1.8.1 (2021-11-10) #### Developers * `getLastEvent` is now referenced in `index.d.ts`. Don't forget to use it (even with .js files) to bring auto-complete in your development tools. ## v1.8.0 (2021-11-10) #### Usages * 2D Measurement can now snap to lines. Press CTRL (or cmd) while measuring. * 3D and 2D camera synchronization is now available in 2D parameters. * IFC Entities (IfcWall, IfcDoor, etc) are now translated in French (If you want to help us translate them into other languages, please contact us!) * BCF search now filters on all BCF fields and not only on the title. * Upgraded Spanish translation #### Developers * 2D engine now uses the same coordinates as the 3D engine. You can build even more powerful 2D and 3D interactions. * Events now have an option `getLastEvent`. If `true`, the last event (if any) is instantly triggered. It is useful for state synchronization on plugin initialization. ## v1.7.4 (2021-10-18) #### Usages * Archived models can now be loaded in multi-model if the first model loaded is archived ## v1.7.3 (2021-10-13) #### Usages * Add first iteration of Spanish translations ## v1.7.2 (2021-10-11) #### Usages * Add first iteration of German translations ## v1.7.1 (2021-09-29) #### Developers * Alerts plugin is now enabled on 2d window by default #### Bugfixes * Update api client to fix issues with `getExtensions`, `updateExtensions`, `createClassificationElementRelations` and `listClassificationElementRelations` methods ## v1.7.0 (2021-09-17) #### Usages * New menu to select windowed plugins * New UI to manage viewers and windows * You can now open properties in a new window * Add ability to take 2D screenshots with annotations * 3D lights have been improved * Viewpoint is no more reset when loading another model in the viewer * Improved 2D rendering * 2D plan are now aligned to the screen * 2D now have a compass * UX improvements with 2D zoom * 2D improve path measure validation #### Developers * Add `2d-model-loaded` and `2d-model-unloaded` [events](./reference/native_plugins#events-1) * The new 2D engine is now [documented](https://2d-engine.bimdata.io). You can develop plugin drawing stuff in 2D! * Windows can now have an [icon](./guide/index) * Add 3D annotations [events](./reference/native_plugins#events) #### Bugfixes * Fix 2D crash if the page loading the viewer doesn't allow `eval` or `new Function()` * Fix rare 2D crash * Improve 2D performances on some models * Fix some French BCF translations * Fix many small bugs on some browsers * Object state is now correctly set when opening a new 3D window ## v1.6.2 (2021-05-12) #### Bugfixes * Fix bug with logarithmicDepthBuffer. It could cause glitches if two surfaces were too close to each other ## v1.6.1 (2021-05-10) #### Usages * Improve default 2D and 3D parameters (Edges, highlight, spaces and space names are enabled by default) ## v1.6.0 (2021-05-10) #### Usages * Brand new 2D viewer * Faster and more accurate rendering * New measurment plugin: Measure distances, angle and surfaces easily! * Space names are shown in 2D * Door openings are shown in 2D * You can disable and enable door openings and space names * 2D objects can be colorized * 2D objects can be textured * User's 3D and 2D configurations are saved * Many performances improvements #### Developers * Open and close event are now always triggered on edge-cases #### Bugfixes * Section plane plugin now show sections loaded from BCF * Fix loadIfc method when ifcId is a string instead of an integer ## v1.5.6 (2021-03-25) #### Bugfixes * Performance fixes ## v1.5.0 (2021-02-19) #### Developers * Add [showAllAnnotations option](./reference/native_plugins#bcf) to BCF plugin * Add structure window as available window by default. `bimdataViewer.unregisterWindow('structure')` to remove it. * Add [getRawElements()](./reference/$viewer#getrawelements) #### Bugfixes * Fix BCF bucket tip which showed the wrong shortcut * Fix objects being cut when to close from camera * Fix xraySetters ## v1.4.1 (2021-02-08) #### Bugfixes * Fix [object properties](./reference/state.html#object) that may not be accessible in some contexts ## v1.4.0 (2021-02-02) #### Usages * Improve 3D rendering performances up to 25% #### Developers * [BCF current-user can now be fetched from a custom endpoint](./reference/native_plugins#bcf) * [Add method to reload Structure plugin](./reference/native_plugins#structure-and-properties) * [Move getRawElements() method to $viewer.state.api](./reference/$viewer#getrawelements) #### Bugfixes * Fix picking on big 3D models * Fix `object.getFirstAncestorWithType()` which may be not defined on some cases * Fix plugin `$close()` triggered even if the plugin wasn't opened when `keepOpen = false` ## v1.3.0 (2021-01-20) #### Usages * New Section planes tool * New pivot marker * New pivot behavior when clicking outside the model. It's easier than ever to navigate in the model * Spatial tree is no more opened if model have more than 8 IfcBuildings (to decrease loading time) * First person projection is now named "Flight mode" * Elements highlight on mouse hover is now disabled in Flight mode #### Developers * [BCF users can now be fetched from a custom endpoint](./reference/native_plugins#bcf) * [Increase render and pick precision for very large models](https://github.com/xeokit/xeokit-sdk/issues/254) * [Add methods to retrieve objects, children, siblings and parents](./reference/state#objects) * [Add logger level configuration in makeBIMDataViewer](./reference/makeBIMDataViewer#logger) * [Add viewer instance setLocale method](./reference/makeBIMDataViewer#locale) #### Bugfixes * Fix BCF interface if loading was slower than the human * Fix multi model selection if there was too many models in the project * Fix context menu (right click) after full screen is swifted off * Fix french typo ## Migration Guide from 0.x to 1.x This is the first major BIMData Viewer update. Thanks to your feebacks, we have improved the API. It is now more intuitive, more powerful and there are many new features. This guide will only show you how to upgrade your plugins. If you want to see the new feature in detail, see the [viewer documentation](./index). Major features: * The 2D Viewer is now available. * Implement your plugins in [dedicated windows and build even more powerful tools](./guide/index). * Implement [loading screens](./reference/$viewer#global-and-local-contexts). * [Modals](./reference/$viewer#modals). * [Custom Right click actions](./reference/context_menu#get-the-context-menu). * Improved integration in various web environments. * Better performances. * Improved multi-models loading and positioning. * [Undo/Redo (CTRL-Z)](./reference/state#undo-redo) on state change actions. ### Viewer instance #### ES Module ::: code-group ```javascript [Version 0.x] import BIMDataViewer from "@bimdata/viewer"; const cfg = { cloudId: 88, projectId: 100, ifcIds: [175], bimdataPlugins: { bcf: false, merge: false, allowExport: false } }; const accessToken = 'DEMO_TOKEN'; const { viewer, store, eventHub, setAccessToken } = initBIMDataViewer('app', accessToken, cfg); ``` ```javascript [Version 1.x] import makeBIMDataViewer from "@bimdata/viewer"; const bimdataViewer = makeBIMDataViewer({ api: { ifcIds: [2283], cloudId: 515, projectId: 756, accessToken: "fc83e49ca9444d3ea41d212599f39040", apiUrl: "https://api.bimdata.io", }, plugins: { bcf: false, "structure-properties": { merge: false, export: false } } }); const vm = bimdataViewer.mount("#app"); ``` ```javascript [Both] /******* VERSION 0.X *******/ import BIMDataViewer from "@bimdata/viewer"; const cfg = { cloudId: 88, projectId: 100, ifcIds: [175], bimdataPlugins: { bcf: false, merge: false, allowExport: false } }; const accessToken = 'DEMO_TOKEN'; const { viewer, store, eventHub, setAccessToken } = initBIMDataViewer('app', accessToken, cfg); /******* VERSION 1.X *******/ import makeBIMDataViewer from "@bimdata/viewer"; const bimdataViewer = makeBIMDataViewer({ api: { ifcIds: [2283], cloudId: 515, projectId: 756, accessToken: "fc83e49ca9444d3ea41d212599f39040", apiUrl: "https://api.bimdata.io", }, plugins: { bcf: false, "structure-properties": { merge: false, export: false } } }); const vm = bimdataViewer.mount("#app"); ``` ::: #### Script tag ::: code-group ```html [Version 0.x] ``` ```html [Version 1.x] ``` ::: #### Refresh access token ::: code-group ```javascript [Version 0.x] const {viewer, store, eventHub, setAccessToken} = initBIMDataViewer('app', accessToken, cfg); setAccessToken(newToken); ``` ```javascript [Version 1.x] bimdataViewer.setAccessToken(newToken); ``` ::: #### Change language ::: code-group ```javascript [Version 0.x] const {viewer, store, eventHub, setAccessToken} = initBIMDataViewer('app', accessToken, cfg); viewer.$i18n.locale = locale; ``` ```javascript [Version 1.x] viewerVm.$i18n.locale = locale; ``` ::: ### Plugin configuration file ::: code-group ```javascript [Version 0.x] export default { name: "bimObjectPlugin", component: BimobjectComponent, display: { iconPosition: "right", content: "windowed", }, keepActive: true, tooltip: "tooltip", icon: { imgUri: icon, }, i18n: { en: { tooltip: "BIMobject", successMessage: "Objects updated", }, fr: { tooltip: "BIMobject", successMessage: "Objects mis à jour", }, }, }; ``` ```javascript [Version 1.x] export default { name: "bimObjectPlugin", component: BimobjectComponent, addToWindows: ["3d", "2d"], // You must define in which windows your plugin will be visible. ["3d", "2d"] is the default behavior button: { position: "right", content: "panel", keepOpen: true, tooltip: "bimObjectPlugin.tooltip", // All tranlations are injected is an intermediate object named as the plugin to avoid conflicts. You must prefix all translations with the plugin name icon: { imgUri: icon, }, }, i18n: { en: { tooltip: "BIMobject", successMessage: "Element(s) updated", }, fr: { tooltip: "BIMobject", successMessage: "Élément(s) mis à jour", }, }, }; ``` ```javascript [Both] /******* VERSION 0.X *******/ export default { name: "bimObjectPlugin", component: BimobjectComponent, display: { iconPosition: "right", content: "windowed", }, keepActive: true, tooltip: "tooltip", icon: { imgUri: icon, }, i18n: { en: { tooltip: "BIMobject", successMessage: "Objects updated", }, fr: { tooltip: "BIMobject", successMessage: "Objects mis à jour", }, }, }; /******* VERSION 1.X *******/ export default { name: "bimObjectPlugin", component: BimobjectComponent, addToWindows: ["3d", "2d"], // You must define in which windows your plugin will be visible. ["3d", "2d"] is the default behavior button: { position: "right", content: "panel", keepOpen: true, tooltip: "bimObjectPlugin.tooltip", // All tranlations are injected is an intermediate object named as the plugin to avoid conflicts. You must prefix all translations with the plugin name icon: { imgUri: icon, }, }, i18n: { en: { tooltip: "BIMobject", successMessage: "Element(s) updated", }, fr: { tooltip: "BIMobject", successMessage: "Élément(s) mis à jour", }, }, }; ``` ::: ### Plugin API #### Object change ::: warning Version 0.x used objects `uuids` as `id`. To handle identical `uuids` (eg: in model versioning), objects in version 1.x now have a unique `id` added by the viewer. It is still possible to access `uuid` using `object.uuid`. All viewer methods used `id` and not `uuid`. Be carefull to correctly link the two properties. ::: ::: tip There are `uuids` utilities. See the [state reference](./reference/state#objects). ::: ::: code-group ```javascript [Version 0.x] this.$hub.on("select-objects", ({ ids }) => { /* Do something with ids. */ }); ``` ```javascript [Version 1.x] this.$viewer.state.hub.on("objects-selected", ({ objects }) => { /* Do something with objects. */ }); ``` ::: #### Setters ::: code-group ```javascript [Version 0.x] this.$hub.emit("select-objects", { ids: [/* object ids to be selected */] }); ``` ```javascript [Version 1.x] this.$viewer.state.selectObjects([/* object ids to be selected */]); ``` ::: #### Getters ::: code-group ```javascript [Version 0.x] this.$utils.getCloudId(); this.$utils.getProjectId(); this.$utils.getAccessToken(); ``` ```javascript [Version 1.x] this.$viewer.api.cloudId; this.$viewer.api.projectId; this.$viewer.api.accessToken; ``` ::: ::: tip * [$viewer reference](./reference/$viewer). * [State getters reference](./reference/state#objects-getters). ::: #### BIMData API Client ::: code-group ```javascript [Version 0.x] const apiClient = new this.$bimdataApiClient.IfcApi(); ``` ```javascript [Version 1.x] const apiClient = new this.$viewer.api.apiClient.IfcApi(); // All API calls are the same ``` ::: #### Structure helpers ::: code-group ```javascript [Version 0.x] this.$utils.getObjectParent(id); this.$utils.getObjectSpace(id); this.$utils.getObjectAncestorByType(id, type); ``` ```javascript [Version 1.x] // structure methods are now object's methods object.parent; object.space; object.getFirstAncestorWithType(type); ``` ::: ::: tip See [state object reference](./reference/state#objects). ::: #### Model Loading ::: code-group ```javascript [Version 0.x] this.$utils.loadIfc(ifcs); this.$utils.unloadIfc(ifcs); const loadedIfc = this.$utils.getSelectedIfcs()[0]; ``` ```javascript [Version 1.x] await this.$viewer.state.loadIfcs([ifcIds]); // Resolve when ifcs are added in the state, not when the 3D viewer has loaded them this.$viewer.state.unloadIfcs([ifcIds]); const loadedIfc = this.$viewer.state.ifcs[0]; ``` ::: #### Error message ::: code-group ```javascript [Version 0.x] this.$hub.emit("alert", { type: "success", message: this.$t("successMessage"), }); ``` ```javascript [Version 1.x] this.$viewer.localContext.hub.emit("alert", { type: "success", message: this.$t("bimObjectPlugin.successMessage"), }); ``` ::: #### Modals ::: code-group ```javascript [Version 0.x] this.$plugins.modalManager.pushModal(modal); ``` ```javascript [Version 1.x] this.$viewer.globalContext.modals.pushModal(modal); ``` ::: --- --- url: /on-premises/getting_started.md --- # Introduction This document explains how to install BIMData.io applications on your servers. You can test our products on our [SaaS Platform](https://platform.bimdata.io). ## How to have access to on-premises You must contact our [sales services](mailto:contact@bimdata.io) to have access to the necessary resources for the installation. ## Architecture The BIMData.io softwares are separated into multiple components, each one with its role. ### Web applications Web applications are the components with which the users interact: * **BIMData Connect**: manage users and authentication, * **BIMData API**: to interact with the data, * **BIMData Platform**: allow the use of the previous components in our ergonomic interface.\ The plaform is split in two components: * **Platform\_front** * **Platform\_back** * **BIMData Marketplace**: to manage differents plugins. The Marketplace is split in two components: * **Marketplace\_front** * **Marketplace\_back** * **BIMData Archive**: to download zip archives from the DMS. * **BIMData Documentation**: a copy of our documentation, in the right version, so you can always access it. ### Workers Workers are the components that will be used to extract, transform, convert or produce data from models or other documents. There are a lot of different workers: * GLTF: * SVG: * XKT: * Preview: * Extract: * Export: * Merge: ### Third-party components BIMData.io softwares need other components to work: * [Keycloak](https://www.keycloak.org/): an open-source identify and access management solution used for the authentication, * [Postgresql](https://www.postgresql.org/): an open-source relational database used to store structured data; Used by all BIMData.io backends and keycloak, * [RabbitMQ](https://www.rabbitmq.com): an open-source message broker used for asynchronous communications between our components. Used by Workers. They can also use some optional components: * an SMTP server to send mail, * an Object Storage (like S3) to store uploaded files. There are a lot of different components, it can be complicated to understand their interactions, so we hope this diagram can help you to apprehend the different network flows: ![Diagram showing the communication between the different components](/images/on-premises/Onpremise-network_flow.png) --- --- url: /on-premises/install/prerequisites.md --- # Prerequisites ## Hardware ### Minimal | Server | CPU | RAM | Disk | |:--------------------------:|:----------:|:---------:|:-----------:| | Applications + databases | 4 cores | 16 GB | 500GB SSD | | Model processing (workers) | 4 cores | 16 GB | 120 GB SSD | ### Recommended | Server | CPU | RAM | Disk | |:--------------------------:|:----------:|:---------:|:-----------:| | Applications | 8 cores | 32 GB | 120 GB SSD | | Databases | 8 cores | 32 GB | 500 GB SSD | | Model processing (workers) | 16 cores | 64 GB | 120 GB SSD | ### High Availability For the High availability, the prerequisites are the same as the *Recommended* configuration with more servers: each server need to have at least two instances. ## Software BIMData.io softwares are distributed with their dependencies in the form of Docker Images. This facilitated the installation but makes it necessary to use a technology capable of running the containers (Docker, Containerd, etc.). Moreover, here the minimal version for the third party components: | Component | Needed Version | | --------------- |:--------------:| | Keycloak | >=11 | | Postgres | >=11 | | RabbitMQ | AMQP 0-9-1 | ## Databases Five databases are necessary for the proper functioning of our applications: * one for the API, * one for the platform, * one for Connect, * one for Keycloak. One Postgresql extension is necessary: `hstore`. Our apps will create it when needed, but the Postgresql user needs to have the `CREATE` permission on the database for that. You can otherwise create it manually. ## Security ### Firewall Here are the ports to open for the good communication of all the elements. Each port can be customized and the flow matrix must be adapted if necessary. | Source | Protocol | Port | Destination | Note | |:------------------:|:--------:|:---------:|:-------------------:|:-------------------:| | Web-front-end | TCP | 8000 | API | | | Web-front-end | TCP | 8000 | Connect | | | Web-front-end | TCP | 8000 | Platform (back) | | | Web-front-end | TCP | 80 | Platform (front) | | | Web-front-end | TCP | 8000 | Marketplace (back) | | | Web-front-end | TCP | 8000 | Marketplace (front) | | | Web-front-end | TCP | 8080 | Keycloak | | | Web-front-end | TCP | 15672 | RabbitMQ | Admin interface | | Web-front-end | TCP | 8080 | Archive | | | Web-front-end | TCP | 80 | Documentation | | |||||| | API | TCP | 80 / 443 | Web-front-end | | | Connect | TCP | 80 / 443 | Web-front-end | | | Platform (back) | TCP | 80 / 443 | Web-front-end | | | Marketplace (back) | TCP | 80 / 443 | Web-front-end | | | Archive | TCP | 80 / 443 | Web-front-end | | | Workers | TCP | 80 / 443 | Web-front-end | | |||||| | API | TCP | 5432 | Postgres | | | Connect | TCP | 5432 | Postgres | | | Keycloak | TCP | 5432 | Postgres | | | Platform (back) | TCP | 5432 | Postgres | | | Marketplace (back) | TCP | 5432 | Postgres | | |||||| | API | TCP | 5672 | RabbitMQ | | | Workers | TCP | 5672 | RabbitMQ | | |||||| | API | TCP | 587 | SMTP | Optional | | Connect | TCP | 587 | SMTP | Optional | | Platform (back) | TCP | 587 | SMTP | Optional | | Workers | TCP | 587 | SMTP | Optional | |||||| | Users | TCP | 80 / 443 | Web-front-end | | | Users | TCP | 80 / 443 | Object Storage | Optional | |||||| | Archive | TCP | 80 / 443 | Object Storage | Optional | --- --- url: /on-premises/install/quickstart/install.md --- # Installation We have a [quickstart Ansible playbook](https://github.com/bimdata/quickstart-onpremise/tree/feat/quickstart-creation) to help you install our applications. This is not intended for production usage, this is an example of how to deploy the different parts of our product. You may need to modify it to suit your needs. ## Limitations * This project is an example of how to quickly install our applications. You may need to do multiple modifications to match your infrastructure and your security needs. * This project does not support high availability deployment. ## Prerequisites * You need to be able to download docker images from the Internet. By default, some images come from *Dockerhub* and some from our *private registry*. * You need to have *python3* and *python3-venv* on the computer that will run Ansible. * Servers must be Debian 10 / 11 with Python3. * Servers must be accessible through SSH. * You must be sudo / root on the servers. ## Environment This quickstart uses Ansible to install Docker, Docker-compose, and the BIMData applications on the configured servers. This doesn't support HA deployment currently. ## How to start ### The easy way We provide a script to simplify the Ansible usage. Keep in mind that it will not let you completely personalize how you want to install the BIMData.io apps. Clone the repository: ``` git clone https://github.com/bimdata/quickstart-onpremise.git cd quickstart-onpremise ``` You need to ensure that you have `python3` and `python3-venv` installed on your system. Then you just need to run the script, it will install the other dependencies and ask you how you want to install it. ``` ./install.sh ``` ### The "Ansible" way Clone the repository: ``` git clone https://github.com/bimdata/quickstart-onpremise.git cd quickstart-onpremise ``` You will need to install some python dependencies, you may want to do it in a virtualenv. If this is the case, you need to create it: ``` python3 -m venv venv source venv/bin/activate ``` Now you need to install the dependencies: ``` pip install -r requirements.txt ``` This playbook comes with an example inventory. The easiest way to start is to copy this inventory and modify the copy: ``` cp -rp inventories/sample inventories/my-own-inventory ``` First, you need to edit the inventory file `inventories/my-own-inventory/inventory.ini`. There are three groups: * `app`: this is where all the web app will be deployed, * `db`: this is where all databases will be deployed if you don't use an external Postgres cluster. * `workers`: this is where all the workers that process data will be deployed. Currently, `app` and `db` do not support multiples hosts. This project can't be use for a fully redundant infrastructure. Then, you need to modify the variables to match your needs. When everything is configured, you can deploy: ``` ansible-playbook -i inventories/my-own-inventory/inventory.ini install-bimdata.yml ``` You may need to add options: | Options | Effect | |------------------|---------------------------| | -k | Prompt for ssh password. | | -K | Prompt for sudo password. | | --ask-vault-pass | Prompt for vault password | If you can't use `sudo`, you can check the [Ansible documentation](https://docs.ansible.com/ansible/latest/user_guide/become.html) on how to configure another way to manage privilege escalation. --- --- url: /on-premises/install/quickstart/config.md --- # Configuration This lists all variables you can use to configure our playbook. ## applications.yml ### DNS configuration ::: v-pre | Variables | Default value | Description | |-----------------------------|----------------------------------------|--------------------------------------------------------| | app\_dns\_domain | "domain.tld" | DNS (sub)domain use to build the app URLs. | | api\_dns\_name | "api.{{ app\_dns\_domain }}" | DNS name use for the API URL. | | connect\_dns\_name | "connect.{{ app\_dns\_domain }}" | DNS name use for the Connect URL. | | platform\_back\_dns\_name | "platform-back.{{ app\_dns\_domain }}" | DNS name use for the Platform back URL. | | platform\_front\_dns\_name | "platform.{{ app\_dns\_domain }}" | DNS name use for the Platform URL. | | iam\_dns\_name | "iam.{{ app\_dns\_domain }}" | DNS name use for the Keycloak (identity provider) URL. | | documentation\_dns\_name |"doc.{{ app\_dns\_domain }}" | DNS name use for the documentation URL. | | archive\_dns\_name |"archive.{{ app\_dns\_domain }}" | DNS name use for the archive URL. | | marketplace\_back\_dns\_name |"marketplace-back.{{ app\_dns\_domain }}" | DNS name use for the marketplace back URL. | | marketplace\_front\_dns\_name |"marketplace.{{ app\_dns\_domain }}" | DNS name use for fhe marketplace URL. | ::: For example if: ``` app_dns_domain: bimdata.company.tld api_dns_name: `"api.{{ app_dns_domain }}"` ``` The DNS name for the API will be: `api.bimdata.company.tld`. Each name needs to be defined in the corresponding authoritative DNS server. This playbook does not manage this. ### SMTP Configuration ::: v-pre | Variables | Default value | Description | |--------------------|-------------------------|----------------------------------------------------------| | smtp\_host | "" | SMTP server address. | | smtp\_port | 587 | SMTP server port. | | smtp\_user | "" | User used for the authentication on the SMTP server. | | smtp\_pass | "{{ vault\_smtp\_pass }}" | Password used for the authentication on the SMTP server. | | smtp\_use\_tls | true | If the SMTP connection should use TLS or not. | | smtp\_default\_email | "" | Email address use as default sender. | ::: ### Web configuration | Variables | Default value | Description | |---------------------|---------------|---------------------------------------------------| | external\_port\_http | 80 | TCP port for HTTP connections on the web server. | | external\_port\_https | 443 | TCP port for HTTPS connections on the web server. | | max\_upload\_size | "1g" | Maximum upload file size (ifc… etc). | ### Data storage ::: v-pre | Variables | Default value | Description | |----------------------------|----------------------------------|-------------------------------------------------------------| | bimdata\_path | "/opt/bimdata" | Where we will install our needed files on the servers. | | bimdata\_docker\_volume\_path | "{{ bimdata\_path }}/datas" | Where will your datas will be store on the servers. | | bimdata\_dockerfiles\_path | "{{ bimdata\_path }}/dockerfiles" | Where we store the dockerfiles use to start the containers. | ::: Object storage (Swift): ::: v-pre | Variables | Default value | Description | |------------------------------|----------------------------------|-----------------------------------------------------| | swift\_enabled | false | Enable the swift storage or not. | | swift\_auth\_url | "" | The URL of the auth server. | | swift\_tenant\_id | "" | The tenant/project id to use when authenticating. | | swift\_tenant\_name | "" | The tenant/project name to use when authenticating. | | swift\_username | "" | The username to use to authenticate. | | swift\_password | "{{ vault\_swift\_password }}" | The password/key to use to authenticate. | | swift\_temp\_url\_key | "{{ vault\_swift\_temp\_url\_key }}" | The temporary URL key ([see openstack documentation](https://docs.openstack.org/kilo/config-reference/content/object-storage-tempurl.html)) | | swift\_api\_container\_name | "" | The container in which to store the API files. | | swift\_connect\_container\_name | "" | The container in which to store the Connect files. | ::: ### Applications configuration ::: v-pre | Variables | Default value | Description | |--------------------------------------------|--------------------------------------------------------------------------|------------------------------------------------------------------| | api\_secret\_key | "{{ vault\_api\_secret\_key }}" | You should not change this. | |||| | connect\_secret\_key | "{{ vault\_connect\_secret\_key }}" | You should not change this. | | connect\_invitation\_secret | "{{ vault\_connect\_invitation\_secret }}" | You should not change this. | | connect\_invitation\_client\_secret | "{{ vault\_connect\_invitation\_client\_secret }}" | You should not change this. | |||| | platform\_back\_secret\_key | "{{ vault\_platform\_back\_secret\_key }}" | You should not change this. | | platform\_back\_webhook\_secret | "{{ vault\_platform\_back\_webhook\_secret }}" | You should not change this. | |||| | platform\_front\_project\_status\_limit\_new | "5" | Number of days during which the project is considered new. | | platform\_front\_project\_status\_limit\_active | "15" | Number of days during before the project is considered inactive. | |||| | iam\_user | "admin" | Keycloak administrator user. | | iam\_password | "{{ vault\_iam\_password }}" | Keycloak administrator password. | |||| | marketplace\_enabled | false | Enable / disable marketplace. | | marketplace\_back\_secret\_key | "{{ vault\_marketplace\_back\_secret\_key }}" | You should not change this. | |||| | marketplace\_front\_workers | 2 | Number of node workers. | |||| | workers\_export\_instance | 1 | Number of replicas deployed on *each* server. | | workers\_export\_cpu | 1 | Number of CPUs allocated for each replicas. | | workers\_gltf\_instance | 1 | Number of replicas deployed on *each* server. | | workers\_gltf\_cpu | 1 | Number of CPUs allocated for each replicas. | | workers\_extract\_instance | 1 | Number of replicas deployed on *each* server. | | workers\_extract\_cpu | 1 | Number of CPUs allocated for each replicas. | | workers\_extract\_quantities\_instance | 1 | Number of replicas deployed on *each* server. | | workers\_extract\_quantities\_cpu | 1 | Number of CPUs allocated for each replicas. | | workers\_svg\_instance | 1 | Number of replicas deployed on *each* server. | | workers\_svg\_cpu | 1 | Number of CPUs allocated for each replicas. | | workers\_merge\_instance | 1 | Number of replicas deployed on *each* server. | | workers\_merge\_cpu | 1 | Number of CPUs allocated for each replicas. | | workers\_xkt\_instance | 1 | Number of replicas deployed on *each* server. | | workers\_xkt\_cpu | 1 | Number of CPUs allocated for each replicas. | | workers\_preview\_instance | 1 | Number of replicas deployed on *each* server. | | workers\_preview\_cpu | 1 | Number of CPUs allocated for each replicas. | |||| | master\_token | "{{ vault\_master\_token }}" | Master token use for authentication between workers and API. | | app\_env | "staging" | Environnement definition for some app. Must not be changed. | | mapbox\_token | "{{ vault\_mapbox\_token }}" | Token for authentication on the Mapbox API. | ::: ## connectivity.yml ### Ansible connectivity | Variables | Default value | Description | |----------------------------|--------------------|-------------------------------| | ansible\_python\_interpreter | "/usr/bin/python3" | Force the use of python3. | | ansible\_ssh\_pipelining | true | Improve ansible performances. | ### SSH Bastion If you can't use SSH directly from this computer to the servers where you want to install our applications, you can use a *bastion* that will proxy the ssh connections. ::: v-pre | Variables | Default value | Description | |---------------------------|-------------------------------|------------------------------------------------| | use\_bastion | false | Configure if you want to use a bastion or not. | | bastion\_ssh\_addr | "" | Bastion adresse use for the ssh connection. | | bastion\_ssh\_port | 22 | Bastion TCP port use for the ssh connection. | | bastion\_ssh\_user | "{{ lookup('env', 'USER') }}" | SSH user for authentication on the Bastion. | | bastion\_ssh\_extra\_options | *undefined* | String to add other SSH options. | ::: ### Proxy If your servers can't access the web directly, you may need to configure a proxy to access our docker registry for example. | Variables | Default value | Description | |-------------|---------------|--------------------------------------------------------| | http\_proxy | "" | HTTP proxy address. | | https\_proxy | "" | HTTPS proxy address. | | no\_proxy | \[] | List of domains / IP where the proxy must not be used. | ## databases.yml ### External postgres cluster | Variables | Default value | Description | |------------------|---------------|----------------------------------------------------------------------------------| | use\_external\_db | false | Configure if you want to use a postgres instance manage by this playbook or not. | | external\_db\_host | "" | Postgres cluster address use for connection if use\_external\_db: true. | | external\_db\_port | 5432 | Postgres cluster TCP port use for connection if use\_external\_db: true. | ### Databases ::: v-pre | Variables | Default value | Description | |-------------------------|---------------------------------------|----------------------------------------| | db\_api\_name | "api" | Database name for the API. | | db\_api\_user | "api" | Postgres user for the API. | | db\_api\_password | "{{ vault\_db\_api\_password }}" | Postgres password for the API. | |||| | db\_connect\_name | "connect" | Database name for Connect. | | db\_connect\_user | "connect" | Postgres user for Connect. | | db\_connect\_password | "{{ vault\_db\_connect\_password }}" | Postgres password for Connect. | |||| | db\_platform\_name | "platform" | Database name for the Platform. | | db\_platform\_user | "platform" | Postgres user for the Platform. | | db\_platform\_password | "{{ vault\_db\_platform\_password }}" | Postgres password for the Platform. | |||| | db\_iam\_name | "iam" | Database name for Keycloak. | | db\_iam\_user | "iam" | Postgres user for Keycloak. | | db\_iam\_password | "{{ vault\_db\_iam\_password }}" | Postgres password for Keycloak. | |||| | db\_marketplace\_name | "marketplace" | Database name for the Marketplace. | | db\_marketplace\_user | "marketplace" | Postgres user for the Marketplace. | | db\_marketplace\_password | "{{ vault\_db\_marketplace\_password }}" | Postgres password for the Marketplace. | ::: If `use_external_db: false` AND if the \[db] server is different from the \[app] server (in the inventory) each Postgres instance will need to use its own TCP port. There are defined with these variables. You will need to configure your firewall: the \[app] server will need to be able to communication with the \[db] server on these ports. ::: v-pre | Variables | Default value | Description | |------------------------------|----------------------------------------------------------------------|------------------------------------------------------------------------------------------| | db\_api\_external\_port | 5432 | Postgres external port for the API. | | db\_connect\_external\_port | 5433 | Postgres external port for Connect. | | db\_platform\_external\_port | 5434 | Postgres external port for the Platform. | | db\_iam\_external\_port | 5435 | Postgres external port for Keycloak. | | db\_marketplace\_external\_port | 5436 | Postgres external port for Keycloak. | | db\_server\_addr | "{{ hostvars\[groups\['db']\[0]]\['ansible\_default\_ipv4']\['address'] }}" | Use to determine the IP that will be use for Postgres connection between \[app] and \[db]. | ::: ## docker\_images.yml ::: v-pre | Variables | Default value | Description | |-----------------------------------------|-------------------------------------------------------------|---------------------------------------------------------------------------| | docker\_private\_registry | "docker-registry.bimdata.io" | Define the registry address from which most of the images will come from. | | docker\_registries | | List of registries informations use to configure docker authentication. | | docker\_rabbitmq\_image | "rabbitmq" | RabbitMQ docker image (use Dockerhub by default). | | docker\_rabbitmq\_tag | "3.8-management-alpine" | RabbitMQ docker tag. | | docker\_postgres\_image | "postgres" | Postgres docker image (use Dockerhub by default). | | docker\_postgres\_tag | "10-alpine" | Postgres docker tag. | | docker\_api\_image | "{{ docker\_private\_registry }}/on-prem/api" | API docker image. | | docker\_api\_tag | latest | API docker tag. | | docker\_connect\_image | "{{ docker\_private\_registry }}/on-prem/connect" | Connect docker image. | | docker\_connect\_tag | latest | Connect docker tag. | | docker\_platform\_back\_image | "{{ docker\_private\_registry }}/on-prem/platform\_back" | Platform back docker image. | | docker\_platform\_back\_tag | latest | Platform back docker tag. | | docker\_platform\_front\_image | "{{ docker\_private\_registry }}/on-prem/platform" | Platform front docker image. | | docker\_platform\_front\_tag | latest | Platform front docker tag. | | docker\_iam\_image | "{{ docker\_private\_registry }}/on-prem/iam" | Keycloak docker image. | | docker\_iam\_tag | latest | Keycloak docker tag. | | docker\_documentation\_image | "{{ docker\_private\_registry }}/on-prem/documentation" | Documentation docker image. | | docker\_documentation\_tag | latest | Documentation docker tag. | | docker\_archive\_image | "{{ docker\_private\_registry }}/on-prem/archive" | Archive docker image. | | docker\_archive\_tag | latest | Archive docker tag. | | docker\_marketplace\_back\_image | "{{ docker\_private\_registry }}/on-premise/marketplace\_back" | Marketplace back images. | | docker\_marketplace\_back\_tag | latest | Marketplace back docker tag. | | docker\_marketplace\_front\_image | "{{ docker\_private\_registry }}/on-premise/marketplace" | Marketplace front docker image. | | docker\_marketplace\_front\_tag | latest | Marketplace front docker tag. | | docker\_workers\_export\_image | "{{ docker\_private\_registry }}/on-prem/workers" | Worker export docker image. | | docker\_workers\_export\_tag | latest | Worker export docker tag. | | docker\_workers\_gltf\_image | "{{ docker\_private\_registry }}/on-prem/workers" | Worker GLTF docker image. | | docker\_workers\_gltf\_tag | latest | Worker GLTF docker tag. | | docker\_workers\_extract\_image | "{{ docker\_private\_registry }}/on-prem/workers" | Worker extract docker image. | | docker\_workers\_extract\_tag | latest | Worker extract docker tag. | | docker\_workers\_extract\_quantities\_image | "{{ docker\_private\_registry }}/on-prem/workers" | Worker extract quantities docker image. | | docker\_workers\_extract\_quantities\_tag | latest | Worker extract quantities docker tag. | | docker\_workers\_svg\_image | "{{ docker\_private\_registry }}/on-prem/workers" | Worker SVG docker image. | | docker\_workers\_svg\_tag | latest | Worker SVG docker tag. | | docker\_workers\_merge\_image | "{{ docker\_private\_registry }}/on-prem/workers" | Worker merge docker image. | | docker\_workers\_merge\_tag | latest | Worker merge docker tag. | | docker\_workers\_xkt\_image | "{{ docker\_private\_registry }}/on-prem/xkt\_worker" | Worker XKT docker image. | | docker\_workers\_xkt\_tag | latest | Worker XKT docker tag. | | docker\_workers\_preview\_image | "{{ docker\_private\_registry }}/on-prem/viewer\_360" | Worker preview docker image. | | docker\_workers\_preview\_tag | latest | Worker preview docker tag. | ::: ## docker.yml ::: v-pre | Variables | Default value | Description | |----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------| | install\_docker | true | Install Docker or not (if not, docker need to be already installed). | | docker\_apt\_dependencies | \["python3-docker", "gnupg", "apt-transport-https", "ca-certificates"] | List of APT packages to install before Docker. | | docker\_apt\_release\_channel | "stable" | Docker version that will be installed. | | docker\_repo\_base\_url | "https://download.docker.com/linux" | Docker APT repository. | | docker\_apt\_key\_url | "{{ docker\_repo\_base\_url }}/{{ ansible\_distribution | lower }}/gpg" | URL of APT GPG key needed for Docker installation. | | docker\_apt\_repo\_url | "{{ docker\_repo\_base\_url }}/{{ ansible\_distribution | lower }}" | URL of APT repository for Docker installation. | |||| | docker\_edition | ce | Docker edition that will be installed ('ee' for 'Enterprise Edition' or 'ce' for 'Community Edition') | | docker\_pkg\_name | "docker-{{ docker\_edition }}" | Docker APT package name that will be installed. | | docker\_pkg\_version | "" | Docker APT package version that will be installed. | | docker\_pkg\_version\_hold | "{{ docker\_pkg\_version | default(false) | ternary(true, false) }}" | Should APT be configure to hold the Docker version (false by default, true if docker\_pkg\_version is defined) | |||| | docker\_svc\_name | "docker" | Docker service name. | | docker\_install\_compose | true | Install Docker compose or not (if noot, need to be already installed.) | | docker\_compose\_version | "1.29.2" | Docker compose version to install. | | docker\_compose\_url | "https://github.com/docker/compose/releases/download/{{ docker\_compose\_version }}/docker-compose-{{ ansible\_system }}-{{ ansible\_architecture }}" | URL to download docker compose. | | docker\_compose\_path | "/usr/local/bin/docker-compose" | Path of where Docker compose will be installed. | |||| | docker\_use\_extra\_hosts | false | Add /etc/hosts value in containers if needed. | | docker\_extra\_hosts | \[] | list of hosts that will be added to /etc/hosts of containers. | ::: ## nginx.yml You should not have to modify these variables in most cases. | Variables | Default value | Description | |----------------------|---------------|-----------------------------| | nginx\_custom\_conf | | Nginx custom configuration. | | nginx\_vhost\_override | | Nginx vhost configuration. | ## rabbitmq.yml ::: v-pre | Variables | Default value | Description | |-------------------------|---------------------------------|------------------------------------------------------------| | use\_external\_rabbitmq | false | Set to true if you want to use your own RabbitMQ instance. | | external\_rabbitmq\_host | "" | RabbitMQ cluster address if use\_external\_rabbitmq: true. | | external\_rabbitmq\_port | 5672 | RabbitMQ cluster TCP port if use\_external\_rabbitmq: true. | | rabbitmq\_user | "bimdata" | RabbitMQ user use for authentication. | | rabbitmq\_password | "{{ vault\_rabbitmq\_password }}" | RabbitMQ password use for authentication. | | rabbitmq\_admin\_dns\_name | "rabbitmq.{{ app\_dns\_domain }}" | RabbitMQ dns name. | | rabbitmq\_external\_port | 5672 | RabbitMQ external port. | | rabbitmq\_server\_addr | "{{ rabbitmq\_admin\_dns\_name }}" | RabbitMQ server address. | ::: ## tls.yml ::: v-pre | Variables | Default value | Description | |----------------------------|-----------------------------------------|--------------------------------------------------------------------------------------------------------------------------------| | tls\_enabled | false | Enable external TLS or not. | | nginx\_use\_pregen\_dh | true | Use pre-defined diffie hellman parameters. If false it'll generate new one. This take a lot of time. | | tls\_ca\_certificate | "" | CA certificate of the CA used to sign the certificates for the applications. (PEM format.) | | tls\_subca\_certificates | \[] | If a complexe CA architecture is used, tls\_ca\_certificate should contain the main CA, and this list all the intermediate ones. | | tls\_api\_key | "{{ vault\_tls\_api\_key }}" | API TLS key (PEM format). | | tls\_api\_cert | "" | API TLS Certificate (PEM format). | | tls\_connect\_key | "{{ vault\_tls\_connect\_key }}" | Connect TLS key (PEM format). | | tls\_connect\_cert | "" | Connect TLS Certificate (PEM format). | | tls\_platform\_back\_key | "{{ vault\_tls\_platform\_back\_key }}" | Platform back TLS key (PEM format). | | tls\_platform\_back\_cert | "" | Platform back TLS Certificate (PEM format). | | tls\_platform\_front\_key | "{{ vault\_tls\_platform\_front\_key }}" | Platform front TLS key (PEM format). | | tls\_platform\_front\_cert | "" | Platform front TLS Certificate (PEM format). | | tls\_iam\_key | "{{ vault\_tls\_iam\_key }}" | Keycloak TLS key (PEM format). | | tls\_iam\_cert | "" | Keycloak TLS Certificate (PEM format). | | tls\_rabbitmq\_admin\_key | "{{ vault\_tls\_rabbitmq\_admin\_key }}" | RabbitMQ TLS key (PEM format). (Only needed if use\_external\_rabbitmq: false.) | | tls\_rabbitmq\_admin\_cert | "" | RabbitMQ TLS Certificate (PEM format). (Only needed if use\_external\_rabbitmq: false.) | | tls\_documentation\_key | "{{ vault\_tls\_documentation\_key }}" | Documentation TLS key (PEM format). | | tls\_documentation\_cert | "" | Documentation TLS Certificate (PEM format). | | tls\_archive\_key | "{{ vault\_tls\_archive\_key }}" | Archive TLS key (PEM format). | | tls\_archive\_cert | "" | Archive TLS Certificate (PEM format). | | tls\_marketplace\_back\_key | "{{ vault\_tls\_marketplace\_back\_key }}" | Marketplace back TLS key (PEM format). | | tls\_marketplace\_back\_cert | "" | Marketplace back TLS Certificate (PEM format). | | tls\_marketplace\_front\_key | "{{ vault\_tls\_marketplace\_front\_key }}" | Marketplace front TLS key (PEM format). | | tls\_marketplace\_front\_cert | "" | Marketplace front TLS Certificate (PEM format). | ::: ## vault.yml In this file, all private pieces of information are defined. Like passwords, TLS keys, or other security stuff. You should replace all the values and encrypt the file with [`ansible-vault`](https://docs.ansible.com/ansible/latest/user_guide/vault.html). --- --- url: /on-premises/install/high_availability.md --- # High availability Most of BIMData's components are stateless, so we can simply increase the number of replicas and run them across multiple nodes and use the leverage of the internal mechanism of the orchestrator to distribute the charge across them. However, for the third party components, it's expected that the user installs and configure them to be highly available. This include : * a highly available PostgreSQL cluster, * a highly available RabbitMQ cluster, * a highly available Keycloak cluser. ## BIMData API BIMData API itself is stateless, but it manages the storage of uploaded data by users. Therefore, you have two possibilities: * use a redundant swift object storage to store the data, * you need to provide a redundant storage shared between all the API containers. ## BIMData Connect BIMData Connect itself is stateless, but it manages the storage of uploaded data by users. Therefore, you have two possibilities: * use a redundant swift object storage to store the data, * you need to provide a redundant storage shared between all the Connect containers. --- --- url: /on-premises/config/env/api.md --- # BIMData API ## URLs of BIMData apps | Variables | Default value | Description | |-------------|---------------|----------------------------| | API\_URL | "" | BIMData API URL. | | CONNECT\_URL | "" | BIMData Connect URL. | | DOC\_URL | "" | BIMData Documentation URL. | ## Database configuration There variables are needed for the database authentication. | Variables | Default value | Description | |----------------------|------------------|----------------------------| | DB\_HOST | | Postgresql server address. | | DB\_PORT | | Postgresql server port. | | DB\_NAME | | Postgresql database name. | | DB\_USER | | Postgresql user. | | DB\_PASSWORD | | Postgresql password. | If your Postgresql cluster use read-only replicas, you can configure the API with these variables to distribute the read-only requests through all of them. Each of these variable is a comma separated list. If each replica have a different configuration, the order in each list matter: the first element `REPLICA_DB_HOSTS` will use the first port in `REPLICA_DB_PORTS` and so on. | Variables | Default value | Description | |----------------------|---------------------|-------------------------------------------------------| | REPLICA\_DB\_HOSTS | "" | list of postgresql read-only replicas server address. | | REPLICA\_DB\_PORTS | Same as DB\_PORT | list of postgresql read-only replicas server port. | | REPLICA\_DB\_NAMES | Same as DB\_NAME | list of postgresql read-only database name. | | REPLICA\_DB\_USERS | Same as DB\_USER | list of postgresql read-only database user. | | REPLICA\_DB\_PASSWORDS | Same as DB\_PASSWORD | list of postgresql read-only database user. | ## RabbitMQ configuration | Variables | Default value | Description | |-------------------|---------------|--------------------------| | RABBITMQ\_HOST | | RabbitMQ server address. | | RABBITMQ\_PORT | | RabbitMQ server port. | | RABBITMQ\_USER | | RabbitMQ username. | | RABBITMQ\_PASSWORD | | RabbitMQ password. | ## OpenID configuration ::: v-pre | Variables | Default value | Description | |------------------------------|-------------------------|------------------------| | IAM\_URL | | OIDC provider address. | | IAM\_ADMIN\_LOGIN | | OIDC admin username. | | IAM\_ADMIN\_PASSWORD | | OIDC admin password. | ::: ## Storage configuration By default, the API use a local storage in `/opt/storage` to store all the uploaded datas. But these datas are not serve by the API itself. It's necessary to configure a web server, like other static files. That's why we recommande using an object storage for production. To enable Swift usage, you need to set `SWIFT_AUTH_URL`, and if this variable is set, alors the other variables `SWIFT_*` need to be set. | Variables | Default value | Description | |------------------------------------------|----------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------| | SWIFT\_AUTH\_URL | | The URL for the auth server. | | SWIFT\_USERNAME | | The username to use to authenticate. | | SWIFT\_PASSWORD | | The key (password) to use to authenticate. | | SWIFT\_AUTH\_VERSION | 3 | The version of the authentication protocol to use. | | SWIFT\_TENANT\_NAME / SWIFT\_PROJECT\_NAME | None | The tenant/project name to use when authenticating. | | SWIFT\_TENANT\_ID / SWIFT\_PROJECT\_ID | None | The tenant/project id to use when authenticating. | | SWIFT\_USER\_DOMAIN\_NAME | None | The domain name we authenticate to. | | SWIFT\_USER\_DOMAIN\_ID | "default" | The domain id we authenticate to. | | SWIFT\_PROJECT\_DOMAIN\_NAME | "default" | The domain name our project is located in. | | SWIFT\_PROJECT\_DOMAIN\_ID | None | The domain id our project is located in. | | SWIFT\_REGION\_NAME | None | OpenStack region if needed. Check with your provider. | | SWIFT\_CONTAINER\_NAME | None | The container in which to store the files. | | SWIFT\_STATIC\_CONTAINER\_NAME | None | Alternate container for storing staticfiles. | | SWIFT\_AUTO\_CREATE\_CONTAINER | True | Should the container be created if it does not exist? | | SWIFT\_AUTO\_CREATE\_CONTAINER\_PUBLIC | False | Set the auto created container as public on creation | | SWIFT\_AUTO\_CREATE\_CONTAINER\_ALLOW\_ORIGIN | "\*" | Set the container's X-Container-Meta-Access-Control-Allow-Origin value, to support CORS requests. | | SWIFT\_AUTO\_BASE\_URL | True | Query the authentication server for the base URL. | | SWIFT\_BASE\_URL | None | The base URL from which the files can be retrieved. | | SWIFT\_NAME\_PREFIX | "" | Prefix that gets added to all filenames. | | SWIFT\_USE\_TEMP\_URLS | True | Generate temporary URLs for file access (allows files to be accessed without a permissive ACL). | | SWIFT\_TEMP\_URL\_KEY | None | Temporary URL key. | | SWIFT\_TEMP\_URL\_DURATION | 2 \* 60 \* 60 | How long a temporary URL remains valid, in seconds. | | SWIFT\_EXTRA\_OPTIONS | {} | Extra options. | | SWIFT\_STATIC\_AUTO\_BASE\_URL | True | Query the authentication server for the static base URL. | | SWIFT\_STATIC\_BASE\_URL | None | The base URL from which the static files can be retrieved, | | SWIFT\_STATIC\_NAME\_PREFIX | None | Prefix that gets added to all static filenames. | | SWIFT\_CONTENT\_TYPE\_FROM\_FD | False | Determine the files mimetypes from the actual content rather than from their filename (default). | | SWIFT\_FULL\_LISTING | True | Ensures to get whole directory contents (by default swiftclient limits it to 10000 entries) | | SWIFT\_AUTH\_TOKEN\_DURATION | 60 \* 60 \* 23 | How long a token is expected to be valid in seconds. | | SWIFT\_LAZY\_CONNECT | True | If True swift connection will be obtained on first use, if False it will be obtained during storage instantiation. | | SWIFT\_GZIP\_CONTENT\_TYPES | \[None,"text/plain","application/json","application/octet-stream","image/svg+xml","text/xml"] | List of content type that will be compressed. | | SWIFT\_GZIP\_COMPRESSION\_LEVEL | 4 | Gzip compression level from 0 to 9. 0 = no compression, 9 = max compression | | SWIFT\_GZIP\_UNKNOWN\_CONTENT\_TYPE | True | If set to True and the content-type can't be guessed, gzip anyway | | SWIFT\_CACHE\_HEADERS | False | Headers cache on/off switcher | ## Email configuration | Variables | Default value | Description | |----------------------|------------------------|-------------------------------| | SMTP\_HOST | | SMTP server address. | | SMTP\_PORT | | SMTP server port. | | SMTP\_USE\_TLS | | SMTP communication use TLS. | | SMTP\_USER | | SMTP authentication user. | | SMTP\_PASS | | SMTP authentication password. | | DEFAULT\_FROM\_EMAIL | "support@bimdata.io" | SMTP default from email. | | MODELS\_SUPPORT\_EMAIL | \[] | | ### Image configuration | Variables | Default value | Description | |----------------------|---------------|--------------------------------------------------------| | WORKERS | 4 | Configure Gunicorn workers. | | PORT | 8000 | Configure Gunicorn listen port. | | CA\_CERT | "" | Path of a certificate to add to container trusted CAs. | | COMPILE\_SCSS | 0 | 0 or 1. Configure if django compilescss during init. | | COLLECT\_STATIC | 1 | 0 or 1. Configure if django collectstatic during init. | | APPLY\_MIGRATION | 1 | 0 or 1. Configure if django migrate during init. | | PROCESS\_TASKS | 0 | 0 or 1. Configure if django process\_tasks. | ## Other configuration | Variables | Default value | Description | |----------------------------------|-------------------------------------|----------------------------------------------------| | SECRET\_KEY | "SET\_DEVELOPMENT\_DJANGO\_SECRET\_KEY" | | | MASTER\_TOKEN | "" | | | DATA\_UPLOAD\_MAX\_MEMORY\_SIZE | 1 \* 1024 \*\* 3 | | | DATA\_UPLOAD\_MAX\_NUMBER\_FIELDS | 1000 | | | ADMIN\_URL | "" | Use to be able to deploy separate admin interface. | | ADMIN\_INTERFACE | | Use to be able to deploy separate admin interface. | | DJANGO\_SETTINGS\_MODULE | "bimdata.settings.api" | Use to be able to deploy separate admin interface. | | ENV | "development" | | | ALLOWED\_HOSTS | \[] | | | DEBUG | False | Enable debug mode. | --- --- url: /on-premises/config/env/connect.md --- # BIMData Connect ## URLs of BIMData apps | Variables | Default value | Description | |--------------|---------------|----------------------------| | SITE\_URL | "" | BIMData Connect URL. | | API\_URL | "" | BIMData API URL. | | DOC\_URL | "" | BIMData Documentation URL. | | PLATFORM\_URL | "" | BIMData Platform URL. | ## Database configuration There variables are needed for the database authentication. | Variables | Default value | Description | |----------------------|------------------|----------------------------| | DB\_HOST | | Postgresql server address. | | DB\_PORT | | Postgresql server port. | | DB\_NAME | | Postgresql database name. | | DB\_USER | | Postgresql user. | | DB\_PASSWORD | | Postgresql password. | If your Postgresql cluster use read-only replicas, you can configure the API with these variables to distribute the read-only requests through all of them. Each of these variable is a comma separated list. If each replica have a different configuration, the order in each list matter: the first element `REPLICA_DB_HOSTS` will use the first port in `REPLICA_DB_PORTS` and so on. | Variables | Default value | Description | |----------------------|---------------------|-------------------------------------------------------| | REPLICA\_DB\_HOSTS | "" | list of postgresql read-only replicas server address. | | REPLICA\_DB\_PORTS | Same as DB\_PORT | list of postgresql read-only replicas server port. | | REPLICA\_DB\_NAMES | Same as DB\_NAME | list of postgresql read-only database name. | | REPLICA\_DB\_USERS | Same as DB\_USER | list of postgresql read-only database user. | | REPLICA\_DB\_PASSWORDS | Same as DB\_PASSWORD | list of postgresql read-only database user. | ## OpenID configuration ::: v-pre | Variables | Default value | Description | |-----------------------------|---------------|------------------------| | IAM\_URL | "" | OIDC provider address. | | IAM\_ADMIN\_LOGIN | "" | OIDC admin username. | | IAM\_ADMIN\_PASSWORD | "" | OIDC admin password. | ::: ## Storage configuration By default, the API use a local storage in `/opt/storage` to store all the uploaded datas. But these datas are not serve by the API itself. It's necessary to configure a web server, like other static files. That's why we recommande using an object storage for production. To enable Swift usage, you need to set `SWIFT_AUTH_URL`, and if this variable is set, alors the other variables `SWIFT_*` need to be set. | Variables | Default value | Description | |------------------------------------------|----------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------| | SWIFT\_AUTH\_URL | | The URL for the auth server. | | SWIFT\_USERNAME | | The username to use to authenticate. | | SWIFT\_PASSWORD | | The key (password) to use to authenticate. | | SWIFT\_AUTH\_VERSION | 3 | The version of the authentication protocol to use. | | SWIFT\_TENANT\_NAME / SWIFT\_PROJECT\_NAME | None | The tenant/project name to use when authenticating. | | SWIFT\_TENANT\_ID / SWIFT\_PROJECT\_ID | None | The tenant/project id to use when authenticating. | | SWIFT\_USER\_DOMAIN\_NAME | None | The domain name we authenticate to. | | SWIFT\_USER\_DOMAIN\_ID | "default" | The domain id we authenticate to. | | SWIFT\_PROJECT\_DOMAIN\_NAME | "default" | The domain name our project is located in. | | SWIFT\_PROJECT\_DOMAIN\_ID | None | The domain id our project is located in. | | SWIFT\_REGION\_NAME | None | OpenStack region if needed. Check with your provider. | | SWIFT\_CONTAINER\_NAME | None | The container in which to store the files. | | SWIFT\_STATIC\_CONTAINER\_NAME | None | Alternate container for storing staticfiles. | | SWIFT\_AUTO\_CREATE\_CONTAINER | True | Should the container be created if it does not exist? | | SWIFT\_AUTO\_CREATE\_CONTAINER\_PUBLIC | False | Set the auto created container as public on creation | | SWIFT\_AUTO\_CREATE\_CONTAINER\_ALLOW\_ORIGIN | "\*" | Set the container's X-Container-Meta-Access-Control-Allow-Origin value, to support CORS requests. | | SWIFT\_AUTO\_BASE\_URL | True | Query the authentication server for the base URL. | | SWIFT\_BASE\_URL | None | The base URL from which the files can be retrieved. | | SWIFT\_NAME\_PREFIX | "" | Prefix that gets added to all filenames. | | SWIFT\_EXTRA\_OPTIONS | {} | Extra options. | | SWIFT\_STATIC\_AUTO\_BASE\_URL | True | Query the authentication server for the static base URL. | | SWIFT\_STATIC\_BASE\_URL | None | The base URL from which the static files can be retrieved, | | SWIFT\_STATIC\_NAME\_PREFIX | None | Prefix that gets added to all static filenames. | | SWIFT\_CONTENT\_TYPE\_FROM\_FD | False | Determine the files mimetypes from the actual content rather than from their filename (default). | | SWIFT\_FULL\_LISTING | True | Ensures to get whole directory contents (by default swiftclient limits it to 10000 entries) | | SWIFT\_AUTH\_TOKEN\_DURATION | 60 \* 60 \* 23 | How long a token is expected to be valid in seconds. | | SWIFT\_LAZY\_CONNECT | True | If True swift connection will be obtained on first use, if False it will be obtained during storage instantiation. | | SWIFT\_GZIP\_CONTENT\_TYPES | \[None,"text/plain","application/json","application/octet-stream","image/svg+xml","text/xml"] | List of content type that will be compressed. | | SWIFT\_GZIP\_COMPRESSION\_LEVEL | 4 | Gzip compression level from 0 to 9. 0 = no compression, 9 = max compression | | SWIFT\_GZIP\_UNKNOWN\_CONTENT\_TYPE | True | If set to True and the content-type can't be guessed, gzip anyway | | SWIFT\_CACHE\_HEADERS | False | Headers cache on/off switcher | ### Email configuration | Variables | Default value | Description | |--------------------|------------------------|-------------------------------| | SMTP\_HOST | None | SMTP server address. | | SMTP\_PORT | | SMTP server port. | | SMTP\_USE\_TLS | | SMTP communication use TLS. | | SMTP\_USER | | SMTP authentication user. | | SMTP\_PASS | | SMTP authentication password. | | DEFAULT\_FROM\_EMAIL | "no-reply@bimdata.io" | SMTP default from email. | ## Image configuration | Variables | Default value | Description | |----------------------|---------------|--------------------------------------------------------| | WORKERS | 4 | Configure Gunicorn workers. | | PORT | 8000 | Configure Gunicorn listen port. | | CA\_CERT | "" | Path of a certificate to add to container trusted CAs. | | COMPILE\_SCSS | 0 | 0 or 1. Configure if django compilescss during init. | | COLLECT\_STATIC | 1 | 0 or 1. Configure if django collectstatic during init. | | APPLY\_MIGRATION | 1 | 0 or 1. Configure if django migrate during init. | | PROCESS\_TASKS | 0 | 0 or 1. Configure if django process\_tasks. | ## Other configuration | Variables | Default value | Description | |-----------------------------|------------------------------------------------------|-------------| | API\_TOKEN | "" | | | INVITATION\_SECRET | "" | | | INVITATION\_CLIENT\_ID | "" | | | INVITATION\_CLIENT\_SECRET | "" | | | SECRET\_KEY | "SET\_DEVELOPMENT\_DJANGO\_SECRET\_KEY" | | | ENV | "development" | | | ALLOWED\_HOSTS | \[] | | | ADMIN\_INTERFACE | False | | | ADMIN\_URL | "" | | | DEBUG | False | | | DATA\_UPLOAD\_MAX\_MEMORY\_SIZE | 1 \* 1024 \*\* 3 | | --- --- url: /on-premises/config/env/platform_front.md --- # BIMData Platform Front ## URLs of BIMData apps | Variables | Default value | Description | |----------------------------|---------------|-----------------------------| | VUE\_APP\_BASE\_URL | | BIMData Platform front URL. | | VUE\_APP\_BACKEND\_BASE\_URL | | BIMData Platform back URL. | | VUE\_APP\_API\_BASE\_URL | | BIMData API URL. | | VUE\_APP\_ARCHIVE\_BASE\_URL | | BIMData Archive URL. | | VUE\_APP\_URL\_BIMDATACONNECT | | BIMData Connect URL. | | VUE\_APP\_URL\_DOCUMENTATION | | BIMData documentation URL. | | VUE\_APP\_URL\_MARKETPLACE | | BIMData marketplace URL. | | VUE\_APP\_URL\_OLD\_PLATFORM | | BIMData old platform URL. | ## OpenID configuration | Variables | Default value | Description | |---------------------------------------|---------------|---------------------------------------------| | VUE\_APP\_IAM\_BASE\_URL | | OIDC provider address. | | VUE\_APP\_OIDC\_CLIENT\_ID | | Your Client ID | | VUE\_APP\_AUTHORIZED\_IDENTITY\_PROVIDERS | | Comma separated list of identity provider | ## Other configuration | Variables | Default value | Description | |-------------------------------------|---------------|------------------------------------------------------------------------------| | VUE\_APP\_MAPBOX\_TOKEN | | Mapbox token use to show the map. | | VUE\_APP\_MAX\_UPLOAD\_SIZE | | Maximum size in bytes for upload. | | VUE\_APP\_PROJECT\_STATUS\_LIMIT\_NEW | | Number of days for which a project is considered "New" after its creation. | | VUE\_APP\_PROJECT\_STATUS\_LIMIT\_ACTIVE | | Number of days since last update for which a project is considered "Active". | --- --- url: /on-premises/config/env/platform_back.md --- # BIMData Platform Back ## URLs of BIMData apps | Variables | Default value | Description | |-------------------|----------------|-----------------------------| | API\_URL | "" | BIMData API URL. | | PLATFORM\_URL | "" | BIMData platform front URL. | | PLATFORM\_BACK\_URL | "" | BIMData platform back URL. | ## Database configuration There variables are needed for the database authentication. | Variables | Default value | Description | |----------------------|------------------|----------------------------| | DB\_HOST | | Postgresql server address. | | DB\_PORT | | Postgresql server port. | | DB\_NAME | | Postgresql database name. | | DB\_USER | | Postgresql user. | | DB\_PASSWORD | | Postgresql password. | If your Postgresql cluster use read-only replicas, you can configure the API with these variables to distribute the read-only requests through all of them. Each of these variable is a comma separated list. If each replica have a different configuration, the order in each list matter: the first element `REPLICA_DB_HOSTS` will use the first port in `REPLICA_DB_PORTS` and so on. | Variables | Default value | Description | |----------------------|---------------------|-------------------------------------------------------| | REPLICA\_DB\_HOSTS | None | list of postgresql read-only replicas server address. | | REPLICA\_DB\_PORTS | Same as DB\_PORT | list of postgresql read-only replicas server port. | | REPLICA\_DB\_NAMES | Same as DB\_NAME | list of postgresql read-only database name. | | REPLICA\_DB\_USERS | Same as DB\_USER | list of postgresql read-only database user. | | REPLICA\_DB\_PASSWORDS | Same as DB\_PASSWORD | list of postgresql read-only database user. | ## OpenID configuration ::: v-pre | Variables | Default value | Description | |-------------------|---------------|------------------------| | IAM\_URL | | OIDC provider address. | | IAM\_CLIENT\_ID | | OIDC client ID. | | IAM\_CLIENT\_SECRET | | OIDC client secret. | ::: ## Email configuration | Variables | Default value | Description | |----------------------|----------------------|-------------------------------| | SMTP\_HOST | | SMTP server address. | | SMTP\_PORT | | SMTP server port. | | SMTP\_USE\_TLS | | SMTP communication use TLS. | | SMTP\_USER | | SMTP authentication user. | | SMTP\_PASS | | SMTP authentication password. | | DEFAULT\_FROM\_EMAIL | "support@bimdata.io" | SMTP default from email. | ### Image configuration | Variables | Default value | Description | |----------------------|---------------|--------------------------------------------------------| | WORKERS | 4 | Configure Gunicorn workers. | | PORT | 8000 | Configure Gunicorn listen port. | | CA\_CERT | "" | Path of a certificate to add to container trusted CAs. | | COMPILE\_SCSS | 0 | 0 or 1. Configure if django compilescss during init. | | COLLECT\_STATIC | 1 | 0 or 1. Configure if django collectstatic during init. | | APPLY\_MIGRATION | 1 | 0 or 1. Configure if django migrate during init. | | PROCESS\_TASKS | 0 | 0 or 1. Configure if django process\_tasks. | ## Other configuration | Variables | Default value | Description | |----------------------------------|----------------------------------------|----------------------------------------------------| | ENV | "development" | | | ALLOWED\_HOSTS | \[] | | | DEBUG | False | | | ADMIN\_INTERFACE | | Use to be able to deploy separate admin interface. | | DJANGO\_SETTINGS\_MODULE | "platform\_back.settings.platform\_back" | Use to be able to deploy separate admin interface. | | SECRET\_KEY | "SET\_DEVELOPMENT\_DJANGO\_SECRET\_KEY" | | | WEBHOOKS\_SECRET | "" | | | MASTER\_TOKEN | "" | | | REQUESTS\_CA\_BUNDLE | "" | | --- --- url: /on-premises/config/env/archive.md --- # BIMData Archive ## URLs of BIMData apps | Variables | Default value | Description | |-------------|---------------|-------------------------| | API\_URL | "" | BIMData API URL. | ## Image configuration | Variables | Default value | Description | |----------------------|---------------|--------------------------------------------------------| | CA\_CERT | "" | Path of a certificate to add to container trusted CAs. | ## Other configuration | Variables | Default value | Description | |----------------------------------|---------------|-------------| | APP\_NAME | "archive" | | | SERVER\_PORT | "8080" | | | WORKERS\_NB | 1 | | --- --- url: /on-premises/config/env/workers.md --- # BIMData workers ## Workers ### URLs of BIMData apps | Variables | Default value | Description | |-------------|-------------------------|-------------------------| | API\_URL | "http://0.0.0.0:8000" | BIMData API URL. | ### RabbitMQ configuration | Variables | Default value | Description | |-------------------|---------------|--------------------------| | RABBITMQ\_HOST | "127.0.0.1" | RabbitMQ server address. | | RABBITMQ\_PORT | "5672" | RabbitMQ server port. | | RABBITMQ\_USER | "guest" | RabbitMQ username. | | RABBITMQ\_PASSWORD | "guest" | RabbitMQ password. | ### Email configuration | Variables | Default value | Description | |----------------------|------------------------|-------------------------------| | SMTP\_HOST | "smtp.mandrillapp.com" | SMTP server address. | | SMTP\_PORT | 587 | SMTP server port. | | SMTP\_USE\_TLS | "True" | SMTP communication use TLS. | | SMTP\_USER | "BIMData.io" | SMTP authentication user. | | SMTP\_PASS | "" | SMTP authentication password. | | DEFAULT\_FROM\_EMAIL | "bug@bimdata.io" | SMTP default from email. | | MODELS\_SUPPORT\_EMAIL | \[] | | | DEFAULT\_TO\_EMAILS | process-errors@bimdata.io,maquettes-en-erreur@boostinlyon.flowdock.com | | ### Other configuration | Variables | Default value | Description | |----------------------------------|-------------------------------|-------------| | MASTER\_TOKEN | "123" | | | ENV | "development" | | ## Workers xkt ### URLs of BIMData apps | Variables | Default value | Description | |-------------|----------------------------------|-------------------------| | API\_URL | "https://api-staging.bimdata.io" | BIMData API URL. | ### RabbitMQ configuration | Variables | Default value | Description | |-------------------|---------------|--------------------------| | RABBITMQ\_HOST | "127.0.0.1" | RabbitMQ server address. | | RABBITMQ\_PORT | "5672" | RabbitMQ server port. | | RABBITMQ\_USER | "guest" | RabbitMQ username. | | RABBITMQ\_PASSWORD | "guest" | RabbitMQ password. | ## Worker headless viewer 360 ### URLs of BIMData apps | Variables | Default value | Description | |-------------|----------------------------------|-------------------------| | API\_URL | "https://api-staging.bimdata.io" | BIMData API URL. | ### RabbitMQ configuration | Variables | Default value | Description | |-------------------|---------------|--------------------------| | RABBITMQ\_HOST | "127.0.0.1" | RabbitMQ server address. | | RABBITMQ\_PORT | "5672" | RabbitMQ server port. | | RABBITMQ\_USER | "guest" | RabbitMQ username. | | RABBITMQ\_PASSWORD | "guest" | RabbitMQ password. | ## Image configuration | Variables | Default value | Description | |----------------------|---------------|--------------------------------------------------------| | CA\_CERT | "" | Path of a certificate to add to container trusted CAs. | --- --- url: /user-guide/creer-un-compte-bimdata.md --- # Créer un compte BIMData ## Qui peut utiliser cette fonctionnalité Tout le monde peut créer un compte BIMData gratuit et bénéficier d'un espace gratuit limité à 300Mo de stockage. Pour collaborer avec d'autres utilisateurs, vous devrez les inviter dans vos divers projets. Si un utilisateur vous invite à accéder à un projet, vous pouvez créer un compte BIMData pour commencer à collaborer. ## Adresse e-mail Inscrivez-vous à BIMData avec votre **adresse e-mail** et un **mot de passe unique**. 1. Rendez-vous sur [BIMData.io](https://bimdata.io) et cliquez sur **Commencez gratuitement** dans le coin supérieur droit. 2. Saisissez votre **adresse e-mail** dans le champ prévu à cet effet. 3. Saisissez votre **prénom** et **nom** 4. Saisissez un **mot de passe** unique dans le champ situé en dessous. 5. Cliquez sur le bouton **S'enregistrer** pour terminer le processus. 6. BIMData vous enverra un e-mail pour vérifier votre compte. Ouvrez cet e-mail et cliquez sur le bouton de vérification pour terminer le processus et vous connecter à votre nouveau compte BIMData. ![Formulaire](/images/user-guide/formulaire.png) ## Et ensuite ? Une fois le processus terminé, vous serez redirigé vers la plateforme BIMData. Vous pourrez ici accéder à votre projet de démo créé automatiquement lors de votre inscription. * La version gratuite vous permet de collaborer sur dans **1** espace sans limite de projet mais avec une contrainte de stockage de **300Mo**. * Optez pour un l'offre Professionnel payante pour collaborer sur un autre espace sans limite de projet ou de nombre d'utilisateur avec une contrainte de stockage de **10Go**. --- --- url: /user-guide/bimdata-platform/tableau-de-bord.md --- # Tableau de bord La page d'accueil de la plateforme se présente sous la forme d'un tableau de bord. Vous y trouverez un accès direct à vos espaces et projets récents. ![Dashboard plateforme](/images/user-guide/dashboard.png) ### Espace de démo L’espace ”BIMData.io DEMO” est automatiquement généré lors de votre première connexion, et vous permet de découvrir les diverses fonctionnalités de la plateforme et la visionneuse. --- --- url: /user-guide/bimdata-platform/espace.md --- # Espace Un **"espace"** sur la plateforme BIMData représente une unité organisationnelle dédiée à la gestion de vos projets. ![Espace demo](/images/user-guide/demo.png) Chaque espace regroupe un ensemble de projets spécifiques et dispose de sa propre gestion des droits utilisateur, vous permettant de contrôler précisément les accès et les permissions pour chaque membre de l’équipe. ![Espace user](/images/user-guide/user-espace.png) En outre, chaque espace est associé à un **compte de facturation distinct**, facilitant ainsi la gestion financière et le suivi des coûts pour l’ensemble des projets qu’il englobe. ## Rôles au niveau de l’espace Au sein d’un espace, deux rôles principaux permettent de gérer l’accès et l’administration : * **Utilisateur de l’espace** Un utilisateur de l’espace dispose de droits spécifiques : il est **automatiquement ajouté à tous les projets existants de l’espace**, ainsi qu’à **tous les projets à venir**. Cela permet de garantir un accès systématique aux projets sans devoir l’ajouter manuellement à chaque création. * **Administrateur de l’espace** L’administrateur de l’espace dispose des droits de gestion au niveau de l’espace. Il peut notamment : * **modifier** les paramètres de l’espace, * **créer et supprimer** des projets, * **gérer les droits utilisateurs** (au niveau des projets et/ou de l’espace selon vos règles), * **inviter** d’autres **administrateurs** et des **utilisateurs de l’espace**. --- --- url: /user-guide/bimdata-platform/compte-de-facturation.md --- # Compte de facturation Le **compte de facturation** est l’entité qui centralise la **gestion des abonnements** et la **facturation** des espaces BIMData.io qui lui sont rattachés. ## Accéder à la gestion des comptes de facturation La **création** et l’**édition** des comptes de facturation se fait uniquement depuis la page **“Mes espaces”**, via le bouton **“Comptes de facturation”** (en haut à droite). ![Compte de facturation](/images/user-guide/compte-de-facturation.png) ## Abonnements Depuis le **tableau de bord**, onglet **“Abonnements”**, vous accédez à la liste des abonnements en cours associés au compte de facturation, par exemple : * les **espaces payants**, * les **Data Packs**. ## Facturation Dans cette même section, vous retrouvez la partie **Facturation**, qui liste les **factures émises par BIMData**, avec la possibilité de les **télécharger**. ## Créer un nouvel espace payant Il est également possible de **créer un nouvel espace payant** en le rattachant au **compte de facturation de votre choix** (utile si vous gérez plusieurs entités, clients ou projets). --- --- url: /user-guide/bimdata-platform/page-projet.md --- # Page projet ## Espace démo personnel Lors de la création de votre compte, nous mettons à votre disposition un espace démo personnel contenant une maquette **.IFC** préchargée. Cet espace vous permet de : * découvrir la plateforme, * tester la visionneuse 3D BIMData, * explorer une maquette numérique directement depuis votre compte. ![Page projet](/images/user-guide/projet.png) ## Navigation dans la page projet En haut de la page, vous trouverez les principaux éléments de navigation : * **À gauche** : un *fil d’Ariane dynamique* pour naviguer rapidement entre les espaces et les projets. * **Au centre** : trois onglets permettant de basculer entre différentes vues du projet : * Projet * GED * BCF ![Navigation projet](/images/user-guide/navigation-projet.png) ## Prévisualisation et localisation Le premier bloc de la page projet vous offrira une prévisualisation ainsi que des informations de localisation du/des modèles (.ifc, .dwg, .dxf, .pdf) préalablement téléchargés dans votre projet projet. ![Preview projet](/images/user-guide/preview.png) ### Modifier la localisation Pour renseigner ou modifier l’adresse du modèle : 1. Cliquez sur le bouton **"Édition"** en haut à droite de la vue plan. 2. Saisissez la nouvelle adresse. ![Maptiler projet](/images/user-guide/maptiler.png) ## Gestion des utilisateurs À droite du bloc de prévisualisation, vous trouverez un espace dédié à : * la gestion des **invitations**, * la gestion des **droits utilisateurs** du projet. ![Invitation projet](/images/user-guide/invitation.png) ## Gestionnaire de modèles Le **Gestionnaire de modèles** est la vue dédiée pour **organiser, retrouver et exploiter** les fichiers d’un projet (BIM, CAD et documents). Il propose une navigation par **onglets** (ex. **.ifc**, **.dwg**, **.dxf**, **.pdf**, **nuages de points**, **photos**, etc.) qui permet de filtrer rapidement le contenu — comme une vue “orientée métier” de la GED. ![Model manager projet](/images/user-guide/model-manager.png) ### Ouvrir les fichiers dans la visionneuse BIMData Depuis le Gestionnaire de modèles, vous pouvez **ouvrir les fichiers compatibles** directement dans la **visionneuse multi-formats BIMData** (ex. IFC, PDF, images, etc.), pour consulter et partager sans téléchargement. ### Archiver des modèles L’onglet **Archives** permet de gérer l’**archivage** des modèles : vous pouvez y conserver des versions ou livrables précédents pour faciliter le suivi dans le temps, sans encombrer la vue principale. ### Structurer un bâtiment avec MetaBuilding Le Gestionnaire de modèles permet aussi de créer et gérer des **MetaBuilding** : une **arborescence de bâtiment** (par exemple Bâtiment → Niveaux/étages → lots) pour **classer vos documents** au bon endroit. > ***Exemple:*** ranger le **plan PDF de l’étage 1** dans le nœud Étage 1, puis faire de même pour chaque niveau. ### Gérer les photosphères Les **photosphères** sont également accessibles depuis cette vue et peuvent être **visualisées** via le **viewer photosphère**. ## Ajouter un modèle Vous pouvez ajouter un nouveau modèle de deux façons : ### 1. Depuis le bouton principal Cliquez sur le bouton **"Ajouter un modèle"**. ![Upload model projet](/images/user-guide/upload-model.png) ### 2. Depuis le gestionnaire de modèles 1. Rendez-vous dans le bloc **Gestionnaire de modèles**. 2. Cliquez sur le bouton **"Ajouter"** en haut à droite. ![Upload model maanger projet](/images/user-guide/upload-model-manager.png) > ***NOTE:*** Une fois votre "modèle" (.ifc, .dwg, .dxf, .pdf, nuages de points, photos) téléchargé dans votre projet, s'ensuivra l'étape de conversion plus ou moins longue selon le poids et le type de fichier. --- --- url: /user-guide/bimdata-platform/ged/introduction.md --- # Introduction La **GED (Gestion Électronique de Documents)** de BIMData permet de centraliser les fichiers d’un projet (IFC, DWG, DXF, PDF, images, etc.) afin de les retrouver facilement et de travailler à plusieurs sur une base commune. Elle sert à organiser les documents du projet et à garantir que chacun accède aux bons fichiers, au bon moment, selon ses permissions. La GED intègre un mécanisme de **versioning** : lorsqu’un document est mis à jour, l’historique des versions est conservé. Cela permet de suivre les évolutions d’un fichier au fil des révisions, d’identifier la version la plus récente et, si nécessaire, de revenir à une version antérieure (selon les droits attribués). Un processus de **VISA** est également disponible pour encadrer la validation des documents techniques. Il permet de soumettre un document à validation, de suivre son statut et de conserver une trace des approbations et des remarques associées, afin d’assurer la continuité et la traçabilité des échanges autour des livrables. Enfin, l’accès aux documents est encadré par une **gestion des droits**. Selon votre rôle et les permissions définies au niveau de l’espace et/ou du projet, vous pouvez consulter, ajouter, modifier, supprimer ou télécharger des fichiers. Cette gestion permet d’adapter l’accès à la GED aux responsabilités de chacun et de limiter les actions sensibles aux personnes autorisées. ![GED](/images/user-guide/ged.png) --- --- url: /user-guide/bimdata-platform/ged/navigation.md --- # Navigation La GED s’adapte à vos projets et permet de réaliser des opérations destinées à centraliser, organiser, archiver et à sécuriser vos documents. ![GED](/images/user-guide/ged-2.png) Dans la GED (Gestion Électronique des Documents) de BIMData, la navigation se fait via trois onglets principaux pour une gestion optimale de vos documents de projet : **1. Dossiers :** Cet onglet vous permet de visualiser l’arborescence des dossiers. Il offre une navigation simple et intuitive à travers les différents dossiers du projet, facilitant ainsi l’organisation et la recherche des documents. **2. Tous les fichiers :** Ici, vous trouverez la liste complète des fichiers disponibles dans la GED. L'accès à ces fichiers est géré en fonction des droits d’accès qui vous sont attribués, garantissant une gestion sécurisée et personnalisée des documents. **3. Mes visas :** Cet onglet regroupe tous les visas émis et reçus dans le cadre du projet. Il permet un suivi précis des approbations et des validations documentaires, essentiel pour le bon déroulement des opérations. Cette structure en onglets rend la gestion documentaire simple et efficace, en s'adaptant aux besoins spécifiques de votre projet. ![Onglet GED](/images/user-guide/onglet-ged.png) --- --- url: /user-guide/bimdata-platform/ged/arborescence.md --- # Arborescence ### Créer des dossiers et importer des fichiers dans la GED ![Arborescence](/images/user-guide/arborescence.png) La **GED BIMData** permet une organisation efficace de vos documents grâce à la création de dossiers et l’importation de fichiers. * **Créer un dossier :** Cliquez sur le bouton **"Créer un dossier"**, situé en haut à gauche de l’interface. Donnez un nom au dossier, puis validez pour l’ajouter à votre arborescence. * **Importer des fichiers :** Cliquez sur le bouton **"Importer"**, également situé en haut à gauche de l’interface. Sélectionnez les fichiers depuis votre ordinateur et validez pour les intégrer à la GED. Avec ces fonctionnalités, vous pouvez structurer vos documents de manière claire et accessible, facilitant ainsi leur gestion et leur consultation dans vos projets. --- --- url: /user-guide/bimdata-platform/ged/gestion-des-droits-d-acces.md --- # Gestion des droits d'accès La plateforme BIMData vous permet de gérer précisément les droits d'accès à votre GED (Gestion Électronique des Documents) grâce à un système de groupes d'utilisateurs. ## Création et gestion des groupes Accédez à la gestion/création de vos groupes en haut à droite sur votre page projet. ![Groupes](/images/user-guide/groupes.png) Vous pouvez créer des groupes et y ajouter ou supprimer des utilisateurs selon vos besoins. La création de groupes est un **pré-requis** pour la gestion des droits d’accès aux dossiers : les permissions se définissent **au niveau des groupes d’utilisateurs**, et non directement utilisateur par utilisateur. Cela permet d’appliquer ou de modifier des droits pour plusieurs personnes en une seule opération. ## Importation de groupes existants ![Importer groupes](/images/user-guide/importer-groupes.png) Pour gagner du temps, vous pouvez également importer les groupes utilisateurs d'autres projets dans lesquels vous êtes administrateur. Pour cela, cliquez sur **"Importer un groupe"**, en haut à droite de la page **"Gestion des groupes"**, et sélectionnez les groupes que vous souhaitez intégrer. ## Paramétrage des droits d'accès ![Gestion des droits](/images/user-guide/gestion-des-droits.png) Pour chaque groupe, vous pouvez définir les niveaux d'accès aux dossiers de votre GED : * **Accès refusé :** les membres du groupe ne peuvent ni voir ni interagir avec le contenu. * **Lecture seule :** les membres peuvent consulter les fichiers et les télécharger, mais ne peuvent pas les modifier ni en ajouter. * **Lecture et écriture :** les membres peuvent consulter, modifier, et ajouter des fichiers. ## Propagation des droits aux sous-dossiers Si vous souhaitez appliquer les droits définis à tous les sous-dossiers d’un dossier, cochez la case dédiée avant de valider vos changements. Cette option garantit une gestion cohérente des permissions sur l’ensemble de la structure des dossiers. --- --- url: /user-guide/bimdata-platform/ged/visa.md --- # Visa La fonctionnalité **VISA** permet de gérer une validation **simple** des documents dans BIMData. Elle sert à centraliser les échanges et le statut de validation autour d’un fichier. **À ce stade, aucun workflow automatisé n’est intégré** : le VISA repose sur une utilisation flexible (soumission, suivi, commentaires) et a vocation à être **enrichi progressivement**. ## Accès à la fonctionnalité VISA ![Visa](/images/user-guide/visa-menu.png) Depuis la **GED**, vous pouvez accéder à cette fonctionnalité directement via le menu d’un fichier. Cliquez sur **"Demande de validation"** pour initier une nouvelle demande. ## Création d’une demande de validation ![Création d'un visa](/images/user-guide/formulaire-visa.png) Une fois cette option sélectionnée, un formulaire s’affiche. Vous pourrez : * Ajouter un ou plusieurs utilisateurs en tant que responsables de la validation. * Définir une **date d’échéance** pour le traitement de la demande. * Ajouter une **description** pour préciser les objectifs ou le contexte de la validation. ## Suivi et gestion des VISA ![Detail des visas](/images/user-guide/detail-visa.png) Une fois la demande validée, vous pourrez suivre et gérer vos demandes de validation directement dans l’onglet **"Mes visas"** de la GED. Cet espace regroupe : * Les VISA que vous avez **créés**. * Les VISA pour lesquels vous êtes **responsables de la validation**. --- --- url: /user-guide/bimdata-platform/ged/versionning.md --- # Versionning La plateforme BIMData propose une fonctionnalité d'historique de version pour assurer un suivi rigoureux des évolutions de vos fichiers. ## Ajout d’une nouvelle version ![Ajouter nouvelle version](/images/user-guide/menu-version.png) * Depuis la **GED**, accédez au menu du fichier souhaité. * Cliquez sur **"Ajouter une version"**. * Téléversez la nouvelle version du fichier en cliquant sur le bouton **"Ajouter une nouvelle version"**. ## Historique des versions ![Historique version](/images/user-guide/ajouter-version.png) Une fois plusieurs versions ajoutées, vous pourrez : * **Consulter les documents :** ouvrez les différentes versions du fichier si elles sont compatibles avec la visionneuse BIMData. * **Restaurer une version précédente :** revenez à une version antérieure si nécessaire. * **Supprimer des versions :** supprimez des versions obsolètes ou inutiles. ![Consulter version](/images/user-guide/consulter-version.png) --- --- url: /user-guide/bimdata-platform/ged/fonctionnalites-avancees.md --- # Fonctionnalités avancées La plateforme BIMData propose plusieurs fonctionnalités pratiques pour gérer vos documents de manière efficace. ## Importer la structure d’un autre projet ![Importer GED](/images/user-guide/importer-ged.png) Si vous êtes administrateur, vous pouvez importer la structure de fichiers d’un autre projet situé dans le même espace de travail : 1. Cliquez sur le bouton **"Menu"**, situé à gauche des boutons **"Créer un dossier"** et **"Importer"**. 2. Sélectionnez l’option pour **importer une structure GED**. 3. Une liste des projets disponibles s’affiche. Choisissez le projet souhaité. 4. Une prévisualisation de l’arborescence des fichiers à importer sera affichée, vous permettant de confirmer ou d’ajuster vos choix avant l’importation. ## Charger un dossier via drag and drop ![Importer dossier](/images/user-guide/importer-dossier.png) La plateforme simplifie l’importation en vous permettant de **glisser-déposer** vos dossiers directement dans l’interface de la GED. 1. Cliquez sur le bouton **"Menu"**, situé à gauche des boutons **"Créer un dossier"** et **"Importer"**. 2. Sélectionnez l’option pour **importer un dossier**. 3. Faites-les glisser dans la zone prévue à cette effet. Une fois déposés, le chargement commencera automatiquement. ## Télécharger l’intégralité de la GED Pour conserver une copie locale de tous les fichiers de votre projet : 1. Cliquez sur le bouton **"Menu"**, situé à gauche des boutons **"Créer un dossier"** et **"Importer"**. 2. Sélectionnez l’option pour **Télécharger la GED**. 3. Les fichiers et dossiers seront compressés dans une seule archive **ZIP**, que vous pourrez récupérer pour un stockage local ou une consultation hors ligne. --- --- url: /user-guide/bimdata-platform/bcf-plateforme.md --- # BCF Plateforme ## Rapport d'annotation Le tableau de bord des BCF de la plateforme BIMData facilite la gestion complète des commentaires BCF de votre projet. Il permet d’ouvrir, de gérer et de télécharger les commentaires, offrant ainsi un suivi centralisé et efficace des échanges pour une meilleure collaboration entre les parties prenantes. ![Rapport annotation](/images/user-guide/rapport-annotation.png) ## Importer vos fichiers BCF La plateforme BIMData vous permet d’importer facilement vos fichiers BCF. * Sur la page du tableau de bord des BCF, cliquez sur le bouton **"Importer"**, situé en haut à droite de l’interface. * Sélectionnez le fichier BCF à importer depuis votre ordinateur. Une fois le fichier importé, les annotations et commentaires contenus dans celui-ci seront automatiquement ajoutés au projet, vous permettant de les consulter et de les gérer. ## Créer un commentaire BCF La création d’un commentaire BCF sur la plateforme BIMData est simple et rapide grâce à un formulaire dédié. ![Créer un BCF](/images/user-guide/creation-bcf.png) Dans le tableau de bord des BCF, cliquez sur le bouton **"Créer un BCF"**, situé en haut à droite de l'interface. * Un formulaire s’affiche, vous permettant de saisir les informations nécessaires pour créer votre commentaire. * Le champ **"Titre"** est obligatoire. Il doit résumer brièvement le commentaire ou la problématique que vous souhaitez soulever. * D’autres champs comme **"Description"**, **"Priorité"**, **"Type"**, etc., peuvent être remplis selon vos besoins. * Contrairement au formulaire BCF de la visionneuse BIMData, ici, le champ **"Image"** ne contient pas un point de vue de la maquette 3D, mais un fichier **image** que vous pouvez télécharger directement depuis votre ordinateur. ## Paramètres BCF La plateforme BIMData offre des **paramètres personnalisables** pour optimiser la gestion des annotations BCF et s’adapter aux besoins spécifiques de votre projet. ![Paramètres BCF](/images/user-guide/parametres-bcf.png) Pour accéder à ces derniers, cliquez sur la roue dentée à gauche du bouton "Importer". ## Paramètres par défaut La plateforme BIMData propose par défaut cinq catégories de paramètres : * **Priorités** (Medium, Low, High) * **Types** (Clash, Information, Error) * **Phases** (Preliminary Planning End, Construction Start, Construction End) * **Statuts** (Opened, Closed, Resolved) * **Tags** (Architecture, Structural, MEP, Heating) ![Paramètres defaut](/images/user-guide/parametres-defaut.png) ## Personnalisation des paramètres BIMData vous permet de personnaliser ces listes en fonction des besoins spécifiques de votre projet. Pour cela, vous pouvez : * **Ajouter** de nouveaux éléments dans une catégorie (par exemple, ajouter "Urgent" dans Priorités). * **Modifier** des éléments existants (par exemple, remplacer "Medium" par "Moyen"). * **Supprimer** les éléments qui ne sont pas pertinents pour votre projet. ![Personnalisation paramètres](/images/user-guide/personnalisation-parametres.png) --- --- url: /viewer/examples.md --- # Examples Here you can find more advanced examples of the viewer APIs usage to achieve further customization and develop your own features. ### Content * [GUI Layout](./gui_layout.md) * [Global and Local Context Plugins](./context_plugins.md) * [Layout Manipulation](./layout_manipulation.md) * [IFC Annotations (2D/3D)](./ifc_annotations.md) * [Plan Annotations](./plan_annotations.md) * [Global Components](./global_components.md) * [Partial Loading](./partial_loading.md) --- --- url: /viewer/reference.md --- # Reference