From a033c83cffe89624b727b0f8283f6b0c787b1fe5 Mon Sep 17 00:00:00 2001 From: mozzie Date: Mon, 23 Sep 2024 23:16:50 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9D=BF=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pages/Viewer/ModelViewer/AortaViewer.tsx | 33 +++++++++++++++++-- .../pages/Viewer/ModelViewer/aorta.config.ts | 12 +++---- .../src/pages/Viewer/ModelViewer/index.tsx | 1 + 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/apps/desktop/src/pages/Viewer/ModelViewer/AortaViewer.tsx b/apps/desktop/src/pages/Viewer/ModelViewer/AortaViewer.tsx index 20b158c..bca4387 100644 --- a/apps/desktop/src/pages/Viewer/ModelViewer/AortaViewer.tsx +++ b/apps/desktop/src/pages/Viewer/ModelViewer/AortaViewer.tsx @@ -4,10 +4,12 @@ import * as THREE from "three"; import useMultiResizeObserver from "../useMultiResizeObserver"; import { loadModels, SegmentMapping } from "./util"; import { InferStructuralEnum } from "./type"; +import { valveMapping } from "./aorta.config"; interface AortaViewerProps { SeriesInstanceUID: string; stlFiles: { fileName: string; data: ArrayBuffer }[]; + measurement: Record; } export const AortaViewer = (props: AortaViewerProps) => { @@ -18,7 +20,7 @@ export const AortaViewer = (props: AortaViewerProps) => { const controlsRef = useRef(); const groupRef = useRef(new THREE.Group()); const viewer3DContainer = useRef(null); - const { SeriesInstanceUID, stlFiles } = props; + const { SeriesInstanceUID, stlFiles, measurement } = props; // autosize useMultiResizeObserver([viewer3DContainer], () => { @@ -58,6 +60,31 @@ export const AortaViewer = (props: AortaViewerProps) => { }); }, [stlFiles]); + const initMeasurement = useCallback(() => { + for (const prop in measurement) { + if (prop in valveMapping) { + const pointArray = measurement[prop].points; + const curve = new THREE.CatmullRomCurve3( + pointArray.map((p) => new THREE.Vector3(p[0], p[1], p[2])) + ); + curve.curveType = "chordal"; // 曲线类型 + curve.closed = true; // 曲线是否闭合 + // 50等分获取曲线点数组 + const points = curve.getPoints(50); + const [r, g, b] = valveMapping[prop].color; + const line = new THREE.LineLoop( + new THREE.BufferGeometry().setFromPoints(points), + new THREE.LineBasicMaterial({ + color: new THREE.Color(r, g, b), + linewidth: 2, + }) + ); + line.name = valveMapping[prop].name; + groupRef.current.add(line); + } + } + }, [measurement]); + useEffect(() => { if (!SeriesInstanceUID || !canvasRef.current) return; @@ -69,11 +96,13 @@ export const AortaViewer = (props: AortaViewerProps) => { initControls(); initLights(); initScene(); + initMeasurement(); initSTLGroup(); + // 开始渲染循环 startRenderLoop(); } - }, [SeriesInstanceUID, initSTLGroup]); + }, [SeriesInstanceUID, initMeasurement, initSTLGroup]); // 初始化渲染器 const initRenderer = (width: number, height: number) => { diff --git a/apps/desktop/src/pages/Viewer/ModelViewer/aorta.config.ts b/apps/desktop/src/pages/Viewer/ModelViewer/aorta.config.ts index de12786..bb8cc21 100644 --- a/apps/desktop/src/pages/Viewer/ModelViewer/aorta.config.ts +++ b/apps/desktop/src/pages/Viewer/ModelViewer/aorta.config.ts @@ -96,27 +96,27 @@ export const Segments = [ * 瓣环配置映射 */ export const valveMapping = { - Annulus: { + annulus_plane: { color: [143 / 255, 6 / 255, 3 / 255], name: "瓣环平面", }, - LVOT: { + LVOT_plane: { color: [84 / 255, 187 / 255, 184 / 255], name: "左室流出道平面", }, - "Sinus Of Valsalva": { + SOV_plane: { color: [87 / 255, 231 / 255, 149 / 255], name: "瓦式窦", }, - "Sinotubular Junction": { + STJ_plane: { color: [213 / 255, 198 / 255, 117 / 255], name: "窦管交界", }, - "Ascending Aorta": { + cor_mid_plane: { color: [182 / 255, 113 / 255, 205 / 255], name: "瓣环上4cm平面", }, - "Actual Aorta": { + actual_aorta_plane: { color: [215 / 255, 136 / 255, 49 / 255], name: "升主动脉最宽处", }, diff --git a/apps/desktop/src/pages/Viewer/ModelViewer/index.tsx b/apps/desktop/src/pages/Viewer/ModelViewer/index.tsx index 3f34ccc..3943230 100644 --- a/apps/desktop/src/pages/Viewer/ModelViewer/index.tsx +++ b/apps/desktop/src/pages/Viewer/ModelViewer/index.tsx @@ -30,6 +30,7 @@ export const Model3DViewer = (props: Model3DViewerProps) => { )} {algAssets.module === InferStructuralEnum.PERI && (