Skip to content

Commit

Permalink
Merge master into np/focus
Browse files Browse the repository at this point in the history
  • Loading branch information
cognite-bulldozer[bot] authored Jun 26, 2024
2 parents f27a15e + c437a3f commit eab52ae
Show file tree
Hide file tree
Showing 24 changed files with 375 additions and 81 deletions.
6 changes: 3 additions & 3 deletions react-components/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cognite/reveal-react-components",
"version": "0.50.0",
"version": "0.51.0",
"exports": {
".": {
"import": "./dist/index.js",
Expand Down Expand Up @@ -30,7 +30,7 @@
},
"peerDependencies": {
"@cognite/cogs.js": ">=9.84.3",
"@cognite/reveal": "4.15.0",
"@cognite/reveal": "4.15.1",
"react": ">=18",
"react-dom": ">=18",
"styled-components": ">=5"
Expand All @@ -44,7 +44,7 @@
"@cognite/cdf-i18n-utils": "^0.7.5",
"@cognite/cdf-utilities": "^3.6.0",
"@cognite/cogs.js": "^9.84.3",
"@cognite/reveal": "^4.15.0",
"@cognite/reveal": "^4.15.1",
"@cognite/sdk": "^9.13.0",
"@playwright/test": "^1.43.1",
"@storybook/addon-essentials": "^8.0.9",
Expand Down
5 changes: 2 additions & 3 deletions react-components/src/architecture/base/commands/BaseTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,7 @@ export abstract class BaseTool extends RenderTargetCommand {
event: PointerEvent | WheelEvent,
domainObjectPredicate?: (domainObject: DomainObject) => boolean
): Promise<AnyIntersection | undefined> {
const { renderTarget } = this;
const { viewer } = renderTarget;
const viewer = this.renderTarget.viewer;

const point = viewer.getPixelCoordinatesFromEvent(event);

Expand All @@ -155,7 +154,7 @@ export abstract class BaseTool extends RenderTargetCommand {
if (!(customObject instanceof ThreeView)) {
return false;
}
return domainObjectPredicate(customObject.domainObject);
return domainObjectPredicate(customObject.domainObject as DomainObject);
};
return await viewer.getAnyIntersectionFromPixel(point, { predicate });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import { CommandsUpdater } from '../reactUpdaters/CommandsUpdater';
import { Range3 } from '../utilities/geometry/Range3';
import { getBoundingBoxFromPlanes } from '../utilities/geometry/getBoundingBoxFromPlanes';
import { Changes } from '../domainObjectsHelpers/Changes';
import { type CogniteClient } from '@cognite/sdk/dist/src';
import { FdmSDK } from '../../../utilities/FdmSDK';

const DIRECTIONAL_LIGHT_NAME = 'DirectionalLight';

Expand All @@ -39,6 +41,8 @@ export class RevealRenderTarget {
// ==================================================

private readonly _viewer: Cognite3DViewer;
private readonly _sdk: CogniteClient;
private readonly _fdmSdk: FdmSDK;
private readonly _commandsController: CommandsController;
private readonly _rootDomainObject: RootDomainObject;
private _ambientLight: AmbientLight | undefined;
Expand All @@ -52,8 +56,10 @@ export class RevealRenderTarget {
// CONSTRUCTOR
// ==================================================

constructor(viewer: Cognite3DViewer) {
constructor(viewer: Cognite3DViewer, sdk: CogniteClient) {
this._viewer = viewer;
this._sdk = sdk;
this._fdmSdk = new FdmSDK(sdk);

const cameraManager = this.cameraManager;
if (!isFlexibleCameraManager(cameraManager)) {
Expand All @@ -77,6 +83,14 @@ export class RevealRenderTarget {
return this._viewer;
}

public get sdk(): CogniteClient {
return this._sdk;
}

public get fdmSdk(): FdmSDK {
return this._fdmSdk;
}

public get config(): BaseRevealConfig | undefined {
return this._config;
}
Expand Down
8 changes: 4 additions & 4 deletions react-components/src/architecture/base/views/BaseView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import { type DomainObjectChange } from '../domainObjectsHelpers/DomainObjectCha
* Represents the observer in the Observer pattern
* It provides common functionality for all types of views.
*/
export abstract class BaseView {
export abstract class BaseView<DomainObjectType extends DomainObject = DomainObject> {
// ==================================================
// INSTANCE FIELDS
// ==================================================

private _domainObject: DomainObject | undefined = undefined;
private _domainObject: DomainObjectType | undefined = undefined;

// ==================================================
// INSTANCE PROPERTIES
Expand All @@ -24,7 +24,7 @@ export abstract class BaseView {
return this._domainObject !== undefined;
}

public get domainObject(): DomainObject {
public get domainObject(): DomainObjectType {
if (this._domainObject === undefined) {
throw Error('The DomainObject is missing in the view');
}
Expand Down Expand Up @@ -92,7 +92,7 @@ export abstract class BaseView {
// INSTANCE METHODS
// ==================================================

public setDomainObject(domainObject: DomainObject): void {
public setDomainObject(domainObject: DomainObjectType): void {
this._domainObject = domainObject;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from '@cognite/reveal';
import { type DomainObjectIntersection } from '../domainObjectsHelpers/DomainObjectIntersection';
import { VisualDomainObject } from '../domainObjects/VisualDomainObject';
import { type DomainObject } from '../domainObjects/DomainObject';

/**
* Represents an abstract class for a Three.js view that renders an Object3D.
Expand All @@ -24,7 +25,10 @@ import { VisualDomainObject } from '../domainObjects/VisualDomainObject';
* - calculateBoundingBox() to calculate the bounding box if you don not relay on three.js.
*/

export abstract class GroupThreeView extends ThreeView implements ICustomObject {
export abstract class GroupThreeView<DomainObjectType extends DomainObject = DomainObject>
extends ThreeView<DomainObjectType>
implements ICustomObject
{
// ==================================================
// INSTANCE FIELDS
// ==================================================
Expand Down
6 changes: 4 additions & 2 deletions react-components/src/architecture/base/views/ThreeView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ import { type PerspectiveCamera, type Box3 } from 'three';
* It can for instance be a view that changes something on another view, dor instance texture on a surface or whatever.
* I just wanted to make it ready for some corner cases I have seen during a long time as 3D developer.
*/
export abstract class ThreeView extends BaseView {
export abstract class ThreeView<
DomainObjectType extends DomainObject = DomainObject
> extends BaseView<DomainObjectType> {
// ==================================================
// INSTANCE FIELDS
// ==================================================
Expand Down Expand Up @@ -112,7 +114,7 @@ export abstract class ThreeView extends BaseView {
this._boundingBox = undefined;
}

public attach(domainObject: DomainObject, renderTarget: RevealRenderTarget): void {
public attach(domainObject: DomainObjectType, renderTarget: RevealRenderTarget): void {
super.setDomainObject(domainObject);
this._renderTarget = renderTarget;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { ToggleMetricUnitsCommand } from '../../base/concreteCommands/ToggleMetr
import { MeasurementTool } from '../measurements/MeasurementTool';
import { ClipTool } from '../clipping/ClipTool';
import { KeyboardSpeedCommand } from '../../base/concreteCommands/KeyboardSpeedCommand';
import { ObservationsTool } from '../observationsDomainObject/ObservationsTool';

export class StoryBookConfig extends BaseRevealConfig {
// ==================================================
Expand All @@ -43,6 +44,7 @@ export class StoryBookConfig extends BaseRevealConfig {
new ExampleTool(),
new MeasurementTool(),
new ClipTool(),
new ObservationsTool(),
undefined,
new SetTerrainVisibleCommand(),
new UpdateTerrainCommand()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,11 @@ import {
import { type DomainObjectIntersection } from '../../base/domainObjectsHelpers/DomainObjectIntersection';
import { WHITE_COLOR } from '../../base/utilities/colors/colorExtensions';

export class ExampleView extends GroupThreeView {
export class ExampleView extends GroupThreeView<ExampleDomainObject> {
// ==================================================
// INSTANCE PROPERTIES
// ==================================================

public override get domainObject(): ExampleDomainObject {
return super.domainObject as ExampleDomainObject;
}

protected override get style(): ExampleRenderStyle {
return super.style as ExampleRenderStyle;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*!
* Copyright 2024 Cognite AS
*/
import { CDF_TO_VIEWER_TRANSFORMATION, type Overlay3D, Overlay3DCollection } from '@cognite/reveal';
import { OBSERVATION_SOURCE, type ObservationProperties, type Observation } from './models';
import { VisualDomainObject } from '../../base/domainObjects/VisualDomainObject';
import { type ThreeView } from '../../base/views/ThreeView';
import { ObservationsView } from './ObservationsView';
import { type TranslateKey } from '../../base/utilities/TranslateKey';
import { type FdmSDK, type InstanceFilter } from '../../../utilities/FdmSDK';
import { Vector3 } from 'three';
import { DEFAULT_OVERLAY_COLOR } from './constants';
import { Changes } from '../../base/domainObjectsHelpers/Changes';

export class ObservationsDomainObject extends VisualDomainObject {
private _selectedOverlay: Overlay3D<Observation> | undefined;

private readonly _collection = new Overlay3DCollection<Observation>([], {
defaultOverlayColor: DEFAULT_OVERLAY_COLOR
});

constructor(fdmSdk: FdmSDK) {
super();
void fetchObservations(fdmSdk).then((observations) => {
this.initializeCollection(observations);
this.notify(Changes.geometry);
});
}

public override get typeName(): TranslateKey {
return { fallback: ObservationsDomainObject.name };
}

protected override createThreeView(): ThreeView<ObservationsDomainObject> | undefined {
return new ObservationsView();
}

private initializeCollection(observations: Observation[]): void {
const observationOverlays = observations.map((observation) => {
const position = new Vector3(
observation.properties.positionX,
observation.properties.positionY,
observation.properties.positionZ
).applyMatrix4(CDF_TO_VIEWER_TRANSFORMATION);

return {
position,
content: observation
};
});

this._collection.addOverlays(observationOverlays);
}

public get overlayCollection(): Overlay3DCollection<Observation> {
return this._collection;
}

public getSelectedOverlay(): Overlay3D<Observation> | undefined {
return this._selectedOverlay;
}

public setSelectedOverlay(overlay: Overlay3D<Observation> | undefined): void {
this._selectedOverlay = overlay;
this.notify(Changes.selected);
}
}

async function fetchObservations(fdmSdk: FdmSDK): Promise<Observation[]> {
const observationsFilter: InstanceFilter = {};

const observationResult = await fdmSdk.filterAllInstances<ObservationProperties>(
observationsFilter,
'node',
OBSERVATION_SOURCE
);

return observationResult.instances;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*!
* Copyright 2024 Cognite AS
*/
import { type IconType } from '@cognite/cogs.js';
import { type TranslateKey } from '../../base/utilities/TranslateKey';
import { ObservationsDomainObject } from './ObservationsDomainObject';
import { BaseEditTool } from '../../base/commands/BaseEditTool';
import { type VisualDomainObject } from '../../base/domainObjects/VisualDomainObject';

export class ObservationsTool extends BaseEditTool {
public override get icon(): IconType {
return 'Location';
}

public override get tooltip(): TranslateKey {
return { fallback: 'Show observations' };
}

public override onActivate(): void {
let domainObject = this.getObservationsDomainObject();
if (domainObject === undefined) {
domainObject = new ObservationsDomainObject(this.renderTarget.fdmSdk);
this.renderTarget.rootDomainObject.addChild(domainObject);
}
domainObject.setVisibleInteractive(true, this.renderTarget);
}

public override onDeactivate(): void {
this.getObservationsDomainObject()?.setVisibleInteractive(false, this.renderTarget);
}

public override async onClick(event: PointerEvent): Promise<void> {
const intersection = await this.getIntersection(event);

const domainObject = this.getIntersectedSelectableDomainObject(intersection);
if (!(domainObject instanceof ObservationsDomainObject)) {
await super.onClick(event);
return;
}

const normalizedCoords = this.getNormalizedPixelCoordinates(event);

const intersectedOverlay = domainObject.overlayCollection.intersectOverlays(
normalizedCoords,
this.renderTarget.camera
);

domainObject.setSelectedOverlay(intersectedOverlay);
}

protected override canBeSelected(domainObject: VisualDomainObject): boolean {
return domainObject instanceof ObservationsDomainObject;
}

public getObservationsDomainObject(): ObservationsDomainObject | undefined {
return this.rootDomainObject.getDescendantByType(ObservationsDomainObject);
}
}
Loading

0 comments on commit eab52ae

Please sign in to comment.