Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions documentation/docs/components/LiveCodeSnippet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ export function LiveCodeSnippet(props: LiveCodeSnippetProps) {
return (
<LiveProvider
code={children}
transpileOptions={{
transforms: {
classes: false,
asyncAwait: false
}
}}
transformCode={(code: string) => {
const fullCode = `
// make these things to be available in live-editor
Expand Down
305 changes: 155 additions & 150 deletions documentation/docs/examples/cad-save-viewerstate.mdx
Original file line number Diff line number Diff line change
@@ -1,150 +1,155 @@
---
id: cad-save-viewerstate
title: Saving viewer state
description: Demo shows how to save viewerstate of 3d models from CDF with Cognite3DViewer.
---
import { DemoWrapper } from '@site/docs/components/DemoWrapper';

Reveal supports saving the camera state and styled filters that have been applied to the loaded model(s).
This functionality can help support sharing links and local storage of a given view.
Internally the input to a given filter is stored and is replayed when restoring the view.
This usually means that substantially less data needs to be serialized in order to share the given state of the viewer.
The serialized JSON blob also keeps information about styling/filtering of the model by storing all [styled sets](./cad-styling.mdx).

<DemoWrapper name="Cognite3DViewerDemo" />

## Getting the viewer state
In the example below we apply some filter to our loaded model using the `NodeCollectionBase` type from [Styling Cad models](./cad-styling.mdx).
Then we can call the ```viewer.getViewState()``` function which return a serialized JSON blob containing the view state.
Depending on the application, the view state can be additionally transformed into e.g. a URL parameter and transferred through a link.

In the example below, we keep simply print it to the developer console.

```js runnable
const allPipes = new PropertyFilterNodeCollection(sdk, model);
allPipes.executeFilter({'PDMS': {'Type': 'PIPE'}});
model.setDefaultNodeAppearance(DefaultNodeAppearance.Ghosted);
model.assignStyledNodeCollection(allPipes, { renderGhosted: false, color: [40, 200, 20] } );

console.log(JSON.stringify(viewer.getViewState(), null, 2));
```

## Setting the viewer state
Restoring the viewer state is simply a matter of feeding back the JSON blob retrieved from ```const myState = viewer.getViewState()``` into ```viewer.setViewState(myState)```.
In the example below, a previously stored state is applied which applies a red color to nodes that have an attribute `'PDMS.Type'`.

:::note
Setting the viewer state assumes that model has already been loaded.
An error will be thrown if a given state is loaded for a model which does not exist.
:::

```js runnable

const myState = {
"camera": {
"position": {
"x": 165.603,
"y": 41.649,
"z": -10.940
},
"target": {
"x": 130.537,
"y": 49.138,
"z": -119.095
}
},
"models": [
{
"defaultNodeAppearance": {
"renderGhosted": true
},
"modelId": 3356984403684032,
"revisionId": 6664823881595566,
"styledSets": [
{
"token": "PropertyFilterNodeCollection",
"state": {
"PDMS": {
"Type": "PIPE"
}
},
"options": {
"requestPartitions": 1
},
"appearance": {
"renderGhosted": false,
"color": [
200,
40,
20
]
}
}
]
}
]
};

viewer.setViewState(myState);
```

## Serializing and deserializing custom node colletions
When working with styled custom node collections, the Reveal viewer needs to know how to serialize and deserialize the set.
Serialization is handled through the abstract method `serialize` which needs to be implemented when extending `NodeCollectionBase`.
The output of `serialize` is of type `SerializedNodeCollection` and contains a `token` which is used to recreate
the `NodeCollectionBase` during deserialization, and a `state` object which contains the data needed to restore
the `NodeCollectionBase`. It is up to the application developer to fill this state object with any nessesary
data needed to recreate the state of the `NodeCollectionBase`. An optional `options` object can also be supplied
containing any metadata for loading data (e.g. the number of API calls to fetch the needed data in parallel).
The contents returned from `serialize` is contained in the result of `getViewState`.

In addition to serialization, Reveal also needs to know how to recreate the custom `NodeCollectionBase` during
deserialization. This is done by calling the free-function `registerCustomNodeCollectionType` with the same `token`
defined by the custom `NodeCollectionBase` and a lambda function which instantiates and restore the state of
the `NodeCollectionBase`. The lambda function has two parameters: the `descriptor` containing the state and
options which should be applied to the `NodeCollectionBase` and the context containing an instance of
the [CogniteClient from the Cognite SDK](https://docs.cognite.com/dev/guides/sdk/js/) and the `Cognite3DModel`
which the `NodeCollectionBase` was originally applied to. It is up to the application developer how and if they
want to use the context and/or descriptor, but it is provided as a convinience.

An example of a simple custom `NodeCollectionBase` can be seen below.
For more information on creating a custom `NodeCollectionBase`, see [create custom node collections](cad-styling-custom).
```jsx
// MyNodeCollection.ts

import { NodeCollectionBase, registerCustomNodeCollectionType } from '@cognite/reveal';

class MyNodeCollection extends NodeCollectionBase {

isLoading = false;
private _indexSet: IndexSet;

constructor(model: Cognite3DModel) {
// token used for serialization / deserialization
super('MyNodeCollection');

this._indexSet = new IndexSet();
for (let i = 0; i < model.nodeCount / 2; i++) {
this._indexSet.add(i);
}
}

getIndexSet() {
return this._indexSet;
}

serialize(): SerializedNodeCollection {
return { token: this.classToken, state: this._indexSet.toRangeArray()}
}

clear() {
this._indexSet.clear();
this.notifyChanged();
}
};

// Register deserializer for type
registerCustomNodeCollectionType<MyNodeCollection>('MyNodeCollection', (descriptor, context) => {
return Promise.resolve(new MyNodeCollection(context.model));
});
```
---
id: cad-save-viewerstate
title: Saving viewer state
description: Demo shows how to save viewerstate of 3d models from CDF with Cognite3DViewer.
---
import { DemoWrapper } from '@site/docs/components/DemoWrapper';

Reveal supports saving the camera state and styled filters that have been applied to the loaded model(s).
This functionality can help support sharing links and local storage of a given view.
Internally the input to a given filter is stored and is replayed when restoring the view.
This usually means that substantially less data needs to be serialized in order to share the given state of the viewer.
The serialized JSON blob also keeps information about styling/filtering of the model by storing all [styled sets](./cad-styling.mdx).

<DemoWrapper name="Cognite3DViewerDemo" />

## Getting the viewer state
In the example below we apply some filter to our loaded model using the `NodeCollectionBase` type from [Styling Cad models](./cad-styling.mdx).
Then we can call the ```viewer.getViewState()``` function which return a serialized JSON blob containing the view state.
Depending on the application, the view state can be additionally transformed into e.g. a URL parameter and transferred through a link.

In the example below, we keep simply print it to the developer console.

```js runnable
const allPipes = new PropertyFilterNodeCollection(sdk, model);
allPipes.executeFilter({'PDMS': {'Type': 'PIPE'}});
model.setDefaultNodeAppearance(DefaultNodeAppearance.Ghosted);
model.assignStyledNodeCollection(allPipes, { renderGhosted: false, color: [40, 200, 20] } );

console.log(JSON.stringify(viewer.getViewState(), null, 2));
```

## Setting the viewer state
Restoring the viewer state is simply a matter of feeding back the JSON blob retrieved from ```const myState = viewer.getViewState()``` into ```viewer.setViewState(myState)```.
In the example below, a previously stored state is applied which applies a red color to nodes that have an attribute `'PDMS.Type'`.

:::note
Setting the viewer state assumes that model has already been loaded.
An error will be thrown if a given state is loaded for a model which does not exist.
:::

```js runnable

const myState = {
"camera": {
"position": {
"x": 165.603,
"y": 41.649,
"z": -10.940
},
"target": {
"x": 130.537,
"y": 49.138,
"z": -119.095
}
},
"models": [
{
"defaultNodeAppearance": {
"renderGhosted": true
},
"modelId": 3356984403684032,
"revisionId": 6664823881595566,
"styledSets": [
{
"token": "PropertyFilterNodeCollection",
"state": {
"PDMS": {
"Type": "PIPE"
}
},
"options": {
"requestPartitions": 1
},
"appearance": {
"renderGhosted": false,
"color": [
200,
40,
20
]
}
}
]
}
]
};

viewer.setViewState(myState);
```

## Serializing and deserializing custom node collections

When working with styled custom node collections, the Reveal viewer needs to know how to serialize and deserialize the set.
Serialization is handled through the abstract method `serialize` which needs to be implemented when extending `NodeCollectionBase`.
The output of `serialize` is of type `SerializedNodeCollection` and contains a `token` which is used to recreate
the `NodeCollectionBase` during deserialization, and a `state` object which contains the data needed to restore
the `NodeCollectionBase`. It is up to the application developer to fill this state object with any nessesary
data needed to recreate the state of the `NodeCollectionBase`. An optional `options` object can also be supplied
containing any metadata for loading data (e.g. the number of API calls to fetch the needed data in parallel).
The contents returned from `serialize` is contained in the result of `getViewState`.

In addition to serialization, Reveal also needs to know how to recreate the custom `NodeCollectionBase` during
deserialization. This is done by calling the free-function `registerCustomNodeCollectionType` with the same `token`
defined by the custom `NodeCollectionBase` and a lambda function which instantiates and restore the state of
the `NodeCollectionBase`. The lambda function has two parameters: the `descriptor` containing the state and
options which should be applied to the `NodeCollectionBase` and the context containing an instance of
the [CogniteClient from the Cognite SDK](https://docs.cognite.com/dev/guides/sdk/js/) and the `Cognite3DModel`
which the `NodeCollectionBase` was originally applied to. It is up to the application developer how and if they
want to use the context and/or descriptor, but it is provided as a convinience.

An example of a simple custom `NodeCollectionBase` can be seen below.
For more information on creating a custom `NodeCollectionBase`, see [create custom node collections](cad-styling-custom).

```js
// import { IndexSet, NodeCollectionBase, registerCustomNodeCollectionType } from '@cognite/reveal';

class MyNodeCollection extends NodeCollectionBase {

isLoading = false;
_indexSet = new IndexSet();

constructor(model) {
// token used for serialization / deserialization
super('MyNodeCollection');

for (let i = 0; i < model.nodeCount / 2; i++) {
this._indexSet.add(i);
}
}

getIndexSet() {
return this._indexSet;
}

serialize() {
return {
token: this.classToken,
state: this._indexSet.toRangeArray()
}
}

clear() {
this._indexSet.clear();
this.notifyChanged();
}
}

// Register deserializer for type
registerCustomNodeCollectionType(
'MyNodeCollection',
(descriptor, context) => {
return Promise.resolve(new MyNodeCollection(context.model));
}
);
```
22 changes: 1 addition & 21 deletions documentation/docs/examples/cad-styling-custom.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,8 @@ be incrementally updated to avoid blocking the viewer.
# Simple, static node collection

```js runnable

// import { NodeCollectionBase, DefaultNodeAppearance } from '@cognite/reveal';

// Note! ES6 classes are not supported in this documentation, but
// the example below corresponds to the following:
/*
class MyNodeCollection extends NodeCollectionBase {
isLoading = false;

Expand All @@ -43,27 +39,11 @@ class MyNodeCollection extends NodeCollectionBase {
this._indexSet.clear();
this.notifyChanged();
}

serialize() { throw new Error('Not supported'); }
};
}

const myNodes = new MyNodeCollection(model);
model.setDefaultNodeAppearance(DefaultNodeAppearance.Ghosted);
model.assignStyledNodeCollection(myNodes, { renderGhosted: false, color: [40, 200, 20] } );
*/

const mySet = new NodeCollectionBase();
mySet.getIndexSet = () => {
const indexSet = new IndexSet();
for (let i = 0; i < model.nodeCount; i += 10) {
indexSet.add(i);
}
return indexSet;
};
mySet.clear = () => { throw new Error('Not supported'); }

model.setDefaultNodeAppearance(DefaultNodeAppearance.Ghosted);
model.assignStyledNodeCollection(mySet, { renderGhosted: false, color: [40, 200, 20] } );
```

See also [guide on (de)serializing node collections](cad-save-viewerstate#serializing-and-deserializing-custom-node-colletions).
Expand Down
1 change: 1 addition & 0 deletions documentation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"npm-to-yarn": "^1.0.1",
"react": "^16.8.4",
"react-dom": "^16.8.4",
"react-live": "maksnester/react-live#mn/disable-transpilation-options-dist",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dafuc?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😂

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah. It's the branch ofc. Nice!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@larsmoa Fair question. You can specify github repo#branch instead of the version number. In that case, during installation the package node_modules/react-live will be downloaded from github repo instead of NPM. That's a temporary hack until PR will be merged. I didn't want to create a fork of react-live under org and maintain it and publish it under new name. I just want my patch to work.

Once my referenced PR to react-live will be merged I'll update it here with new patched react-live version.

"styled-components": "^5.1.1",
"three": "0.125.2"
},
Expand Down
Loading