diff --git a/react-components/src/components/Reveal3DResources/queryMappedData.ts b/react-components/src/components/Reveal3DResources/queryMappedData.ts index 8ab8b8e9457..c4358a4f592 100644 --- a/react-components/src/components/Reveal3DResources/queryMappedData.ts +++ b/react-components/src/components/Reveal3DResources/queryMappedData.ts @@ -3,7 +3,7 @@ */ import { type Cognite3DViewer, type PointerEventData, type CogniteCadModel } from '@cognite/reveal'; -import { type CogniteInternalId, type CogniteClient } from '@cognite/sdk'; +import { type CogniteInternalId, type CogniteClient, Node3D } from '@cognite/sdk'; import { type EdgeItem, type InspectResultList, @@ -12,13 +12,72 @@ import { type Source } from '../../utilities/FdmSDK'; import { type FdmAssetMappingsConfig } from '../../hooks/types'; -import { type NodeDataResult } from './types'; +import { FdmPropertyType, type NodeDataResult } from './types'; -async function getAncestorNodeIdsForTreeIndex( +export async function queryMappedData( + viewer: Cognite3DViewer, + cdfClient: CogniteClient, + fdmClient: FdmSDK, + fdmConfig: FdmAssetMappingsConfig, + clickEvent: PointerEventData +): Promise | undefined> { + const intersection = await viewer.getIntersectionFromPixel( + clickEvent.offsetX, + clickEvent.offsetY + ); + + if (intersection === null || intersection.type !== 'cad') { + return; + } + + const cadIntersection = intersection; + const model = cadIntersection.model; + + const ancestors = await getAncestorNodesForTreeIndex(cdfClient, model, cadIntersection.treeIndex); + + const mappings = await getMappingEdges( + fdmClient, + fdmConfig, + model, + ancestors.map((n) => n.id) + ); + + if (mappings.edges.length === 0) { + return; + } + + const selectedEdge = mappings.edges[0]; + const selectedNodeId = + selectedEdge.properties[fdmConfig.source.space][ + `${fdmConfig.source.externalId}/${fdmConfig.source.version}` + ].revisionNodeId; + const selectedNode = ancestors.find((n) => n.id === selectedNodeId); + const dataNode = selectedEdge.startNode; + + const inspectionResult = await inspectNode(fdmClient, dataNode); + + const dataView = + inspectionResult.items[0]?.inspectionResults.involvedViewsAndContainers?.views[0]; + + const nodeData = await filterNodeData(fdmClient, dataNode, dataView); + + if (nodeData === undefined) { + return undefined; + } + + return { + data: nodeData as FdmPropertyType, + view: dataView, + cadNode: selectedNode!, + model: cadIntersection.model + }; +} + +async function getAncestorNodesForTreeIndex( client: CogniteClient, model: CogniteCadModel, treeIndex: number -): Promise { +): Promise { const nodeId = await model.mapTreeIndexToNodeId(treeIndex); const ancestorNodes = await client.revisions3D.list3DNodeAncestors( @@ -27,7 +86,7 @@ async function getAncestorNodeIdsForTreeIndex( nodeId ); - return ancestorNodes.items.map((n) => n.id); + return ancestorNodes.items; } async function getMappingEdges( @@ -109,50 +168,3 @@ async function filterNodeData( `${dataView.externalId}/${dataView.version}` ]; } - -export async function queryMappedData( - viewer: Cognite3DViewer, - cdfClient: CogniteClient, - fdmClient: FdmSDK, - fdmConfig: FdmAssetMappingsConfig, - clickEvent: PointerEventData -): Promise | undefined> { - const intersection = await viewer.getIntersectionFromPixel( - clickEvent.offsetX, - clickEvent.offsetY - ); - - if (intersection === null || intersection.type !== 'cad') { - return; - } - - const cadIntersection = intersection; - const model = cadIntersection.model; - - const ancestorIds = await getAncestorNodeIdsForTreeIndex( - cdfClient, - model, - cadIntersection.treeIndex - ); - - const mappings = await getMappingEdges(fdmClient, fdmConfig, model, ancestorIds); - - if (mappings.edges.length === 0) { - return; - } - - const dataNode = mappings.edges[0].startNode; - - const inspectionResult = await inspectNode(fdmClient, dataNode); - - const dataView = - inspectionResult.items[0]?.inspectionResults.involvedViewsAndContainers?.views[0]; - - const nodeData = await filterNodeData(fdmClient, dataNode, dataView); - - if (nodeData === undefined) { - return undefined; - } - - return { data: nodeData as NodeType, view: dataView }; -} diff --git a/react-components/src/components/Reveal3DResources/types.ts b/react-components/src/components/Reveal3DResources/types.ts index 74a597c4e9f..ff400a7ea82 100644 --- a/react-components/src/components/Reveal3DResources/types.ts +++ b/react-components/src/components/Reveal3DResources/types.ts @@ -2,20 +2,25 @@ * Copyright 2023 Cognite AS */ -import { type AddModelOptions, type SupportedModelTypes } from '@cognite/reveal'; +import { CogniteCadModel, type AddModelOptions, type SupportedModelTypes } from '@cognite/reveal'; import { type Matrix4 } from 'three'; import { type Source } from '../../utilities/FdmSDK'; +import { Node3D } from '@cognite/sdk/dist/src'; export type AddImageCollection360Options = { siteId: string; }; +export type FdmPropertyType = Record>; + export type AddResourceOptions = AddReveal3DModelOptions | AddImageCollection360Options; export type AddReveal3DModelOptions = AddModelOptions & { transform?: Matrix4 }; export type TypedReveal3DModel = AddReveal3DModelOptions & { type: SupportedModelTypes | '' }; export type NodeDataResult = { - data: NodeType; + data: FdmPropertyType; view: Source; + cadNode: Node3D; + model: CogniteCadModel; }; diff --git a/react-components/stories/HighlightNode.stories.tsx b/react-components/stories/HighlightNode.stories.tsx index f3678384c25..61558eb6ac0 100644 --- a/react-components/stories/HighlightNode.stories.tsx +++ b/react-components/stories/HighlightNode.stories.tsx @@ -8,14 +8,25 @@ import { type FdmAssetMappingsConfig, RevealContainer, RevealToolbar, - useReveal + useReveal, + Reveal3DResources, + NodeDataResult, + Reveal3DResourcesProps, + AddResourceOptions } from '../src'; import { CogniteClient } from '@cognite/sdk'; import { Color, Matrix4 } from 'three'; import { type ReactElement, useEffect, useState } from 'react'; -import { type PointerEventData } from '@cognite/reveal'; +import { + CogniteCadModel, + DefaultNodeAppearance, + NodeIdNodeCollection, + TreeIndexNodeCollection, + type PointerEventData +} from '@cognite/reveal'; import { queryMappedData } from '../src/components/Reveal3DResources/queryMappedData'; import { useFdmSdk, useSDK } from '../src/components/RevealContainer/SDKProvider'; +import { createSdkByUrlToken } from './utilities/createSdkByUrlToken'; const DefaultFdmConfig: FdmAssetMappingsConfig = { source: { @@ -30,61 +41,67 @@ const DefaultFdmConfig: FdmAssetMappingsConfig = { const meta = { title: 'Example/HighlightNode', - component: CadModelContainer, + component: Reveal3DResources, tags: ['autodocs'] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; -const token = new URLSearchParams(window.location.search).get('token') ?? ''; -const sdk = new CogniteClient({ - appId: 'reveal.example', - baseUrl: 'https://greenfield.cognitedata.com', - project: '3d-test', - getToken: async () => await Promise.resolve(token) -}); +const sdk = createSdkByUrlToken(); export const Main: Story = { args: { - addModelOptions: { - modelId: 2551525377383868, - revisionId: 2143672450453400 - }, - transform: new Matrix4().makeTranslation(0, 10, 0) + resources: [ + { + modelId: 2551525377383868, + revisionId: 2143672450453400, + transform: new Matrix4().makeTranslation(-340, -480, 80) + } + ], + styling: {}, + fdmAssetMappingConfig: DefaultFdmConfig }, - render: ({ addModelOptions }) => ( - - - - - - ) + render: ({ resources, fdmAssetMappingConfig }) => { + return ( + + + + ); + } }; -const Querier = ({ fdmConfig }: { fdmConfig: FdmAssetMappingsConfig }): ReactElement => { +const StoryContent = ({ + resources, + fdmAssetMappingConfig +}: { + resources: AddResourceOptions[]; + fdmAssetMappingConfig: FdmAssetMappingsConfig; +}) => { const viewer = useReveal(); - const sdk = useSDK(); - const fdmClient = useFdmSdk(); - const [nodeData, setNodeData] = useState(undefined); + const [nodeData, setNodeData] = useState(); - useEffect(() => { - const queryAndSetData = (e: PointerEventData): void => { - void (async (e: PointerEventData): Promise => { - const nodeData = await queryMappedData(viewer, sdk, fdmClient, fdmConfig, e); - setNodeData(nodeData); - })(e); - }; + const callback = (nodeData: NodeDataResult) => { + setNodeData(nodeData.data); - viewer.on('click', (e: PointerEventData) => { - queryAndSetData(e); - }); + if (!(viewer.models[0] instanceof CogniteCadModel)) return; - return (): void => { - viewer.off('click', queryAndSetData); - }; - }, [viewer, sdk, fdmClient, fdmConfig]); + viewer.models[0].assignStyledNodeCollection( + new TreeIndexNodeCollection([nodeData.cadNode.treeIndex]), + DefaultNodeAppearance.Highlighted + ); + }; - return <>Clicked node content: {JSON.stringify(nodeData)}; + return ( + <> + + + NodeData is: {JSON.stringify(nodeData)} + + ); };