From 3554dbbff006bb6dda80157f41f7bded03d66cbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Wed, 17 Jul 2024 09:16:24 +0200 Subject: [PATCH 1/9] chore: remove superfluous type --- .../src/components/Reveal3DResources/types.ts | 8 ++++---- react-components/src/index.ts | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/react-components/src/components/Reveal3DResources/types.ts b/react-components/src/components/Reveal3DResources/types.ts index 5fe66ba3c48..d94e75e93a2 100644 --- a/react-components/src/components/Reveal3DResources/types.ts +++ b/react-components/src/components/Reveal3DResources/types.ts @@ -61,13 +61,13 @@ export type AddResourceOptions = | AddPointCloudResourceOptions | AddImage360CollectionOptions; -export type Add3dResourceOptions = AddModelOptions & { transform?: Matrix4 }; - -export type AddPointCloudResourceOptions = Add3dResourceOptions & { +export type AddPointCloudResourceOptions = AddModelOptions & { + transform?: Matrix4; styling?: { default?: NodeAppearance; mapped?: NodeAppearance }; }; -export type AddCadResourceOptions = AddModelOptions & { transform?: Matrix4 } & { +export type AddCadResourceOptions = AddModelOptions & { + transform?: Matrix4; styling?: { default?: NodeAppearance; mapped?: NodeAppearance; diff --git a/react-components/src/index.ts b/react-components/src/index.ts index 5af7604702d..e5e054f9764 100644 --- a/react-components/src/index.ts +++ b/react-components/src/index.ts @@ -110,7 +110,6 @@ export { type AddImage360CollectionDatamodelsOptions, type AddImage360CollectionOptions, type AddResourceOptions, - type Add3dResourceOptions, type AddCadResourceOptions, type AddPointCloudResourceOptions } from './components/Reveal3DResources/types'; From cbd2cbbcea31216adb8f5cdbcf7c2938d6b70a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Wed, 17 Jul 2024 09:18:44 +0200 Subject: [PATCH 2/9] chore: bump to 0.54.0 --- react-components/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react-components/package.json b/react-components/package.json index c70b16d2a1e..9e65777e086 100644 --- a/react-components/package.json +++ b/react-components/package.json @@ -1,6 +1,6 @@ { "name": "@cognite/reveal-react-components", - "version": "0.53.0", + "version": "0.54.0", "exports": { ".": { "import": "./dist/index.js", From cf3686532ace79afe15d9d3cacbb8ae26126db50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Wed, 17 Jul 2024 10:45:26 +0200 Subject: [PATCH 3/9] chore: rewrite `isSameModel` to use new types --- .../Reveal3DResources/Reveal3DResources.tsx | 31 +++++---- .../Reveal3DResources/typeGuards.ts | 15 ++--- .../useCalculatePointCloudStyling.tsx | 4 +- .../useRemoveNonReferencedModels.ts | 11 ++-- react-components/src/utilities/isSameModel.ts | 66 +++++++++++++++---- 5 files changed, 86 insertions(+), 41 deletions(-) diff --git a/react-components/src/components/Reveal3DResources/Reveal3DResources.tsx b/react-components/src/components/Reveal3DResources/Reveal3DResources.tsx index 451d3ae961f..3a44d050e06 100644 --- a/react-components/src/components/Reveal3DResources/Reveal3DResources.tsx +++ b/react-components/src/components/Reveal3DResources/Reveal3DResources.tsx @@ -12,7 +12,9 @@ import { type AddResourceOptions, type Reveal3DResourcesProps, type CadModelOptions, - type PointCloudModelOptions + type PointCloudModelOptions, + type AddCadResourceOptions, + type AddPointCloudResourceOptions } from './types'; import { useCalculatePointCloudStyling } from './useCalculatePointCloudStyling'; import { @@ -26,7 +28,7 @@ import { isImage360AssetStylingGroup } from '../../utilities/StylingGroupUtils'; import { type ImageCollectionModelStyling } from '../Image360CollectionContainer/useApply360AnnotationStyling'; -import { is360ImageAddOptions, is3dResourceOptions } from './typeGuards'; +import { is360ImageAddOptions } from './typeGuards'; import { useRemoveNonReferencedModels } from './useRemoveNonReferencedModels'; import { useAssetMappedNodesForRevisions, @@ -208,16 +210,21 @@ async function getTypedModels( ): Promise { const errorFunction = onLoadFail ?? defaultLoadFailHandler; - const modelTypePromises = resources.filter(is3dResourceOptions).map(async (addModelOptions) => { - const type = await viewer - .determineModelType(addModelOptions.modelId, addModelOptions.revisionId) - .catch((error) => { - errorFunction(addModelOptions, error); - return ''; - }); - const typedModel = { ...addModelOptions, type }; - return typedModel; - }); + const modelTypePromises = resources + .filter( + (resource): resource is AddCadResourceOptions | AddPointCloudResourceOptions => + !is360ImageAddOptions(resource) + ) + .map(async (addModelOptions) => { + const type = await viewer + .determineModelType(addModelOptions.modelId, addModelOptions.revisionId) + .catch((error) => { + errorFunction(addModelOptions, error); + return ''; + }); + const typedModel = { ...addModelOptions, type }; + return typedModel; + }); const resourceLoadResults = await Promise.all(modelTypePromises); const successfullyLoadedResources = resourceLoadResults.filter( diff --git a/react-components/src/components/Reveal3DResources/typeGuards.ts b/react-components/src/components/Reveal3DResources/typeGuards.ts index fd50189d6b2..de7d2b195ba 100644 --- a/react-components/src/components/Reveal3DResources/typeGuards.ts +++ b/react-components/src/components/Reveal3DResources/typeGuards.ts @@ -5,21 +5,16 @@ import { type AddImage360CollectionEventsOptions, type AddImage360CollectionDatamodelsOptions, type AddImage360CollectionOptions, - type AddResourceOptions, - type Add3dResourceOptions + type AddResourceOptions } from './types'; export function is360ImageAddOptions( addOptions: AddResourceOptions ): addOptions is AddImage360CollectionOptions { - return !is3dResourceOptions(addOptions); -} - -export function is3dResourceOptions( - addOptions: AddResourceOptions -): addOptions is Add3dResourceOptions { - const modelOptions = addOptions as Add3dResourceOptions; - return modelOptions.modelId !== undefined && modelOptions.revisionId !== undefined; + return ( + is360ImageDataModelAddOptions(addOptions as AddImage360CollectionOptions) || + is360ImageEventsAddOptions(addOptions as AddImage360CollectionOptions) + ); } export function is360ImageDataModelAddOptions( diff --git a/react-components/src/components/Reveal3DResources/useCalculatePointCloudStyling.tsx b/react-components/src/components/Reveal3DResources/useCalculatePointCloudStyling.tsx index 26a816f0c0f..04c6e4b90f4 100644 --- a/react-components/src/components/Reveal3DResources/useCalculatePointCloudStyling.tsx +++ b/react-components/src/components/Reveal3DResources/useCalculatePointCloudStyling.tsx @@ -10,7 +10,7 @@ import { import { useMemo } from 'react'; import { type AnnotationIdStylingGroup } from '../PointCloudContainer/useApplyPointCloudStyling'; import { useQuery } from '@tanstack/react-query'; -import { isSame3dModel } from '../../utilities/isSameModel'; +import { isSameModel } from '../../utilities/isSameModel'; import { usePointCloudAnnotationMappingsForModels, usePointCloudAnnotationIdsForModels @@ -168,7 +168,7 @@ function groupStyleGroupByModel( return styleGroup.reduce((accumulatedGroups, currentGroup) => { const existingGroupWithModel = accumulatedGroups.find((group) => - isSame3dModel(group.model, currentGroup.model) + isSameModel(group.model, currentGroup.model) ); existingGroupWithModel?.styleGroups.push(...currentGroup.styleGroups); return accumulatedGroups; diff --git a/react-components/src/components/Reveal3DResources/useRemoveNonReferencedModels.ts b/react-components/src/components/Reveal3DResources/useRemoveNonReferencedModels.ts index 9d782065003..89539a44637 100644 --- a/react-components/src/components/Reveal3DResources/useRemoveNonReferencedModels.ts +++ b/react-components/src/components/Reveal3DResources/useRemoveNonReferencedModels.ts @@ -6,11 +6,10 @@ import { type AddResourceOptions } from './types'; import { is360ImageAddOptions, is360ImageDataModelAddOptions, - is360ImageEventsAddOptions, - is3dResourceOptions + is360ImageEventsAddOptions } from './typeGuards'; import { useEffect } from 'react'; -import { isSame3dModel } from '../../utilities/isSameModel'; +import { isSameModel } from '../../utilities/isSameModel'; export function useRemoveNonReferencedModels( addOptions: AddResourceOptions[], @@ -36,16 +35,16 @@ function findNonReferencedModels( viewer: Cognite3DViewer ): CogniteModel[] { const models = viewer.models; - const addOptionsSet = new Set(addOptions.filter(is3dResourceOptions)); + const addOptionsSet = new Set(addOptions.filter((model) => !is360ImageAddOptions(model))); return models.filter((model) => { const correspondingAddOptions = (() => { for (const options of addOptionsSet) { - if (!is3dResourceOptions(options)) { + if (is360ImageAddOptions(options)) { continue; } - const isSameModel = isSame3dModel(options, { + const isSameModel = isSameModel(options, { modelId: model.modelId, revisionId: model.revisionId, transform: model.getModelTransformation() diff --git a/react-components/src/utilities/isSameModel.ts b/react-components/src/utilities/isSameModel.ts index 1eebacc1116..b260d218141 100644 --- a/react-components/src/utilities/isSameModel.ts +++ b/react-components/src/utilities/isSameModel.ts @@ -3,10 +3,15 @@ */ import { type GeometryFilter } from '@cognite/reveal'; import { - type Add3dResourceOptions, + type AddImage360CollectionOptions, + type AddResourceOptions, type CadModelOptions } from '../components/Reveal3DResources/types'; import { Matrix4 } from 'three'; +import { + is360ImageAddOptions, + is360ImageEventsAddOptions +} from '../components/Reveal3DResources/typeGuards'; export function isSameCadModel(model0: CadModelOptions, model1: CadModelOptions): boolean { return ( @@ -43,12 +48,55 @@ function isSameGeometryFilter( ); } -export function isSame3dModel(model0: Add3dResourceOptions, model1: Add3dResourceOptions): boolean { - return ( - model0.modelId === model1.modelId && - model0.revisionId === model1.revisionId && - isSameTransform(model0.transform, model1.transform) - ); +export function isSameModel(model0: AddResourceOptions, model1: AddResourceOptions): boolean { + const isFirstImage360 = is360ImageAddOptions(model0); + const isSecondImage360 = is360ImageAddOptions(model1); + + if (isFirstImage360 !== isSecondImage360) { + return false; + } + + if (isFirstImage360 && isSecondImage360) { + return isSame360Collection(model0, model1); + } + + if (!isFirstImage360 && !isSecondImage360) { + return ( + model0.modelId === model1.modelId && + model0.revisionId === model1.revisionId && + isSameTransform(model0.transform, model1.transform) + ); + } + + return false; +} + +export function isSame360Collection( + collection0: AddImage360CollectionOptions, + collection1: AddImage360CollectionOptions +): boolean { + const isFirstEventsBased = is360ImageEventsAddOptions(collection0); + const isSecondEventsBased = is360ImageEventsAddOptions(collection1); + if (isFirstEventsBased !== isSecondEventsBased) { + return false; + } + + if (isFirstEventsBased && isSecondEventsBased) { + return ( + collection0.siteId === collection1.siteId && + isSameTransform(collection0.transform, collection1.transform) + ); + } + + if (!isFirstEventsBased && !isSecondEventsBased) { + return ( + collection0.externalId === collection1.externalId && + collection0.space === collection1.space && + isSameTransform(collection0.transform, collection1.transform) + ); + } + + return false; } const identity = new Matrix4(); @@ -64,7 +112,3 @@ function isSameTransform(m0: Matrix4 | undefined, m1: Matrix4 | undefined): bool return m0.equals(m1); } - -export function isSameModel(model1: CadModelOptions, model2: CadModelOptions): boolean { - return model1.modelId === model2.modelId && model1.revisionId === model2.revisionId; -} From 71c9306c4b67ed82c83c7f67f4b0a83ef780e408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Wed, 17 Jul 2024 10:45:40 +0200 Subject: [PATCH 4/9] test: add tests --- .../unit-tests/utilities/isSameModel.test.ts | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 react-components/tests/unit-tests/utilities/isSameModel.test.ts diff --git a/react-components/tests/unit-tests/utilities/isSameModel.test.ts b/react-components/tests/unit-tests/utilities/isSameModel.test.ts new file mode 100644 index 00000000000..be6111d13ff --- /dev/null +++ b/react-components/tests/unit-tests/utilities/isSameModel.test.ts @@ -0,0 +1,66 @@ +import { describe, expect, test, vi, beforeEach } from 'vitest'; + +import { Matrix4 } from 'three'; +import { isSameModel } from '../../../src/utilities/isSameModel'; +import { cloneDeep } from 'lodash'; + +describe(isSameModel.name, () => { + const model0 = { modelId: 1, revisionId: 2, transform: new Matrix4().makeRotationX(1) }; + const model1 = { modelId: 3, revisionId: 4, transform: new Matrix4().makeRotationY(2) }; + const model2 = { modelId: 1, revisionId: 2, transform: new Matrix4().makeRotationZ(3) }; + + const image360Event0 = { siteId: 'site0', transform: new Matrix4().makeRotationZ(3) }; + const image360Event1 = { siteId: 'site1', transform: new Matrix4().makeRotationX(4) }; + const image360Event2 = { siteId: 'site0', transform: new Matrix4().makeRotationZ(5) }; + + const image360Fdm0 = { + externalId: 'id0', + space: 'space0', + transform: new Matrix4().makeRotationY(5) + }; + const image360Fdm1 = { + externalId: 'id1', + space: 'space0', + transform: new Matrix4().makeRotationY(5) + }; + + test('returns true on equal model info', () => { + expect(isSameModel(model0, cloneDeep(model0))).toBeTruthy(); + }); + + test('returns false on unequal models', () => { + expect(isSameModel(model0, model1)).toBeFalsy(); + }); + + test('returns false on equal models with different transforms', () => { + expect(isSameModel(model0, model2)).toBeFalsy(); + }); + + test('returns false with CAD/PC vs 360', () => { + expect(isSameModel(model0, image360Event0)).toBeFalsy(); + }); + + test('returns true with equal 360 images', () => { + expect(isSameModel(image360Event0, cloneDeep(image360Event0))).toBeTruthy(); + }); + + test('returns false with unequal 360 images', () => { + expect(isSameModel(image360Event0, image360Event1)).toBeFalsy(); + }); + + test('returns false for equal 360 images with different transform', () => { + expect(isSameModel(image360Event0, image360Event2)).toBeFalsy(); + }); + + test('returns false wtih FDM vs events images', () => { + expect(isSameModel(image360Event0, image360Fdm0)).toBeFalsy(); + }); + + test('returns true for equal FDM images', () => { + expect(isSameModel(image360Fdm0, cloneDeep(image360Fdm0))).toBeTruthy(); + }); + + test('returns false for unequal FDM images', () => { + expect(isSameModel(image360Fdm0, image360Fdm1)).toBeFalsy(); + }); +}); From 9dd73bc327ec745a97c51f64b6e324aef0ad523e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Wed, 17 Jul 2024 10:51:25 +0200 Subject: [PATCH 5/9] chore: variable rename --- .../Reveal3DResources/useRemoveNonReferencedModels.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/react-components/src/components/Reveal3DResources/useRemoveNonReferencedModels.ts b/react-components/src/components/Reveal3DResources/useRemoveNonReferencedModels.ts index 89539a44637..414b8d55ae1 100644 --- a/react-components/src/components/Reveal3DResources/useRemoveNonReferencedModels.ts +++ b/react-components/src/components/Reveal3DResources/useRemoveNonReferencedModels.ts @@ -44,13 +44,13 @@ function findNonReferencedModels( continue; } - const isSameModel = isSameModel(options, { + const sameModel = isSameModel(options, { modelId: model.modelId, revisionId: model.revisionId, transform: model.getModelTransformation() }); - if (isSameModel) { + if (sameModel) { return options; } } From 96f133650f3eacaffd26de5439f63f8fc820c66d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Wed, 17 Jul 2024 11:57:59 +0200 Subject: [PATCH 6/9] chore: add missing changes --- react-components/stories/SearchHooks.stories.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/react-components/stories/SearchHooks.stories.tsx b/react-components/stories/SearchHooks.stories.tsx index 6764f1d4b76..ef94d796c82 100644 --- a/react-components/stories/SearchHooks.stories.tsx +++ b/react-components/stories/SearchHooks.stories.tsx @@ -9,7 +9,8 @@ import { type AddResourceOptions, type AddImage360CollectionOptions, RevealContext, - type Add3dResourceOptions + type AddCadResourceOptions, + type AddPointCloudResourceOptions } from '../src'; import { Color } from 'three'; import { type ReactElement, useState, useMemo, useEffect } from 'react'; @@ -36,6 +37,7 @@ import { import { isEqual } from 'lodash'; import { type NodeItem } from '../src/utilities/FdmSDK'; import { Button, Input } from '@cognite/cogs.js'; +import { is360ImageAddOptions } from '../src/components/Reveal3DResources/typeGuards'; const queryClient = new QueryClient(); const sdk = createSdkByUrlToken(); @@ -60,7 +62,8 @@ const StoryContent = ({ resources }: { resources: AddResourceOptions[] }): React >('fdmSearch'); const filteredResources = resources.filter( - (resource): resource is Add3dResourceOptions => 'modelId' in resource + (resource): resource is AddCadResourceOptions | AddPointCloudResourceOptions => + !is360ImageAddOptions(resource) ); const { data: searchData } = useSearchMappedEquipmentFDM( From 13c3283b24ba48527f9c67aa54bcd0fc874d5b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Wed, 17 Jul 2024 12:05:51 +0200 Subject: [PATCH 7/9] chore: add another change --- react-components/src/query/use3dScenes.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/react-components/src/query/use3dScenes.tsx b/react-components/src/query/use3dScenes.tsx index 2b6a5510d92..b95b8e4b568 100644 --- a/react-components/src/query/use3dScenes.tsx +++ b/react-components/src/query/use3dScenes.tsx @@ -19,7 +19,8 @@ import { Euler, MathUtils, Matrix4 } from 'three'; import { CDF_TO_VIEWER_TRANSFORMATION } from '@cognite/reveal'; import { type GroundPlane, type Skybox } from '../components/SceneContainer/sceneTypes'; import { - type Add3dResourceOptions, + AddCadResourceOptions, + AddPointCloudResourceOptions, type AddImage360CollectionDatamodelsOptions } from '../components/Reveal3DResources/types'; @@ -34,7 +35,7 @@ export type SceneData = { cameraEulerRotationX: number; cameraEulerRotationY: number; cameraEulerRotationZ: number; - cadModelOptions: Add3dResourceOptions[]; + cadModelOptions: (AddCadResourceOptions | AddPointCloudResourceOptions)[]; image360CollectionOptions: AddImage360CollectionDatamodelsOptions[]; groundPlanes: GroundPlane[]; skybox?: Skybox; From 7e1037d980a43174822720e5d20b5b28c1d845d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Wed, 17 Jul 2024 12:08:02 +0200 Subject: [PATCH 8/9] chore: delete unused file --- .../stories/utilities/is3DModelOptions.ts | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 react-components/stories/utilities/is3DModelOptions.ts diff --git a/react-components/stories/utilities/is3DModelOptions.ts b/react-components/stories/utilities/is3DModelOptions.ts deleted file mode 100644 index 24726cb8981..00000000000 --- a/react-components/stories/utilities/is3DModelOptions.ts +++ /dev/null @@ -1,13 +0,0 @@ -/*! - * Copyright 2023 Cognite AS - */ -import { type Add3dResourceOptions, type AddResourceOptions } from '../../src'; - -export function is3DModelOptions( - threeDResource: AddResourceOptions -): threeDResource is Add3dResourceOptions { - return ( - (threeDResource as Add3dResourceOptions).modelId !== undefined && - (threeDResource as Add3dResourceOptions).revisionId !== undefined - ); -} From 314ba7028b0b52cc22630fcb9d3588ca7f0435c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Wed, 17 Jul 2024 12:08:19 +0200 Subject: [PATCH 9/9] chore: lint fix --- react-components/src/query/use3dScenes.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/react-components/src/query/use3dScenes.tsx b/react-components/src/query/use3dScenes.tsx index b95b8e4b568..033900a3e9f 100644 --- a/react-components/src/query/use3dScenes.tsx +++ b/react-components/src/query/use3dScenes.tsx @@ -19,8 +19,8 @@ import { Euler, MathUtils, Matrix4 } from 'three'; import { CDF_TO_VIEWER_TRANSFORMATION } from '@cognite/reveal'; import { type GroundPlane, type Skybox } from '../components/SceneContainer/sceneTypes'; import { - AddCadResourceOptions, - AddPointCloudResourceOptions, + type AddCadResourceOptions, + type AddPointCloudResourceOptions, type AddImage360CollectionDatamodelsOptions } from '../components/Reveal3DResources/types'; @@ -35,7 +35,7 @@ export type SceneData = { cameraEulerRotationX: number; cameraEulerRotationY: number; cameraEulerRotationZ: number; - cadModelOptions: (AddCadResourceOptions | AddPointCloudResourceOptions)[]; + cadModelOptions: Array; image360CollectionOptions: AddImage360CollectionDatamodelsOptions[]; groundPlanes: GroundPlane[]; skybox?: Skybox;