截面测量架构设计
一、架构设计原则
- 数据与视图分离:测量数据模型独立于渲染逻辑
- 命令模式:所有交互操作封装为命令,支持撤销/重做
- 策略模式:不同测量算法作为可替换策略
- 观察者模式:视图间数据同步
- 工厂模式:几何元素和测量对象的创建
二、核心架构图
@startuml SectionMeasureArchitecture
skinparam packageStyle rectangle
skinparam shadowing false
package "表现层 Presentation" #LightBlue {
class View3DWidget {
- vtkRenderer* renderer3D
- vtkRenderWindow* renderWindow
--
+ updateSlicePlane()
+ highlightSliceRegion()
}
class View2DSliceWidget {
- vtkImageViewer2* imageViewer
- SliceLineInteractor* lineInteractor
--
+ onLinePositionChanged()
+ updateBoundingBox()
}
class View2DMeasureWidget {
- vtkRenderer* renderer2D
- InteractionStateMachine* stateMachine
- GeometryRenderer* geometryRenderer
--
+ handleMouseEvent()
+ renderGeometries()
+ renderMeasurements()
}
}
package "控制层 Controller" #LightGreen {
class SectionMeasureController {
- SectionDataModel* dataModel
- CommandManager* commandManager
--
+ executeCommand(Command*)
+ undo()
+ redo()
+ synchronizeViews()
}
class InteractionStateMachine {
- State currentState
- GeometryFactory* factory
--
+ handleEvent(MouseEvent)
+ transitionTo(State)
+ createGeometry()
}
class CommandManager {
- stack<Command*> undoStack
- stack<Command*> redoStack
--
+ execute(Command*)
+ undo()
+ redo()
}
}
package "业务逻辑层 Business Logic" #LightYellow {
package "几何元素 Geometry" {
abstract class GeometryElement {
# string id
# GeometryType type
# vector<Point2D> controlPoints
--
+ {abstract} validate()
+ {abstract} serialize()
+ {abstract} deserialize()
}
class Point2D {
- double x
- double y
}
class Line2D {
- Point2D startPoint
- Point2D endPoint
- double width
--
+ extractRegion()
}
class Circle2D {
- Point2D center
- double radius
- double ringWidth
--
+ extractRegion()
}
class TextAnnotation {
- string text
- Point2D position
}
}
package "测量对象 Measurement" {
abstract class MeasurementElement {
# string id
# MeasurementType type
# GeometryElement* source
# GeometryElement* target
# MeasurementStrategy* strategy
--
+ {abstract} calculate()
+ {abstract} serialize()
}
class PointToPointMeasure
class PointToLineMeasure
class LineToLineMeasure
class CircleToLineMeasure
class PointToCircleMeasure
class CircleToCircleMeasure
class AngleMeasure
class RadiusMeasure
}
package "测量策略 Strategy" {
interface MeasurementStrategy {
+ {abstract} calculate()
}
class VerticalDistanceStrategy
class HorizontalDistanceStrategy
class NearestDistanceStrategy
class CenterDistanceStrategy
class FarthestDistanceStrategy
}
package "工厂 Factory" {
class GeometryFactory {
+ createPoint2D()
+ createLine2D()
+ createCircle2D()
+ createTextAnnotation()
}
class MeasurementFactory {
+ createMeasurement(type, source, target, strategy)
}
}
}
package "数据层 Data" #LightCoral {
class SectionDataModel {
- vector<GeometryElement*> geometries
- vector<MeasurementElement*> measurements
- SlicePlaneData slicePlane
- BoundingBox boundingBox
--
+ addGeometry(GeometryElement*)
+ removeGeometry(id)
+ addMeasurement(MeasurementElement*)
+ removeMeasurement(id)
+ serialize()
+ deserialize()
}
class ObjectTreeAdapter {
+ syncToObjectTree()
+ syncFromObjectTree()
}
class DataSerializer {
+ serializeToJson()
+ deserializeFromJson()
+ serializeToXml()
+ deserializeFromXml()
}
}
package "渲染层 Rendering" #LightGray {
class GeometryRenderer {
- map<GeometryType, RenderStrategy*> renderStrategies
--
+ render(GeometryElement*)
+ highlight(GeometryElement*)
+ updateVisibility(id, visible)
}
class MeasurementRenderer {
- map<MeasurementType, RenderStrategy*> renderStrategies
--
+ render(MeasurementElement*)
+ updateAnnotation(id, value)
}
interface RenderStrategy {
+ {abstract} render(vtkRenderer*, Element*)
}
}
package "命令模式 Command" #Lavender {
abstract class Command {
# SectionDataModel* dataModel
--
+ {abstract} execute()
+ {abstract} undo()
}
class CreateGeometryCommand
class DeleteGeometryCommand
class CreateMeasurementCommand
class DeleteMeasurementCommand
}
package "数据提取层 Extraction" #LightCyan {
class RegionExtractor {
+ extractPointCloud(region)
+ extractCADMesh(region)
}
class PointCloudExtractor
class CADMeshExtractor
}
' 继承关系
GeometryElement <|-- Point2D
GeometryElement <|-- Line2D
GeometryElement <|-- Circle2D
GeometryElement <|-- TextAnnotation
MeasurementElement <|-- PointToPointMeasure
MeasurementElement <|-- PointToLineMeasure
MeasurementElement <|-- LineToLineMeasure
MeasurementElement <|-- CircleToLineMeasure
MeasurementElement <|-- PointToCircleMeasure
MeasurementElement <|-- CircleToCircleMeasure
MeasurementElement <|-- AngleMeasure
MeasurementElement <|-- RadiusMeasure
MeasurementStrategy <|.. VerticalDistanceStrategy
MeasurementStrategy <|.. HorizontalDistanceStrategy
MeasurementStrategy <|.. NearestDistanceStrategy
MeasurementStrategy <|.. CenterDistanceStrategy
MeasurementStrategy <|.. FarthestDistanceStrategy
Command <|-- CreateGeometryCommand
Command <|-- DeleteGeometryCommand
Command <|-- CreateMeasurementCommand
Command <|-- DeleteMeasurementCommand
' 组合/依赖关系
View3DWidget --> SectionMeasureController
View2DSliceWidget --> SectionMeasureController
View2DMeasureWidget --> SectionMeasureController
View2DMeasureWidget --> InteractionStateMachine
SectionMeasureController --> SectionDataModel
SectionMeasureController --> CommandManager
SectionMeasureController --> GeometryRenderer
SectionMeasureController --> MeasurementRenderer
InteractionStateMachine --> GeometryFactory
CommandManager --> Command
MeasurementElement --> MeasurementStrategy
MeasurementElement --> GeometryElement
SectionDataModel --> GeometryElement
SectionDataModel --> MeasurementElement
SectionDataModel --> ObjectTreeAdapter
SectionDataModel --> DataSerializer
GeometryRenderer --> RenderStrategy
MeasurementRenderer --> RenderStrategy
Line2D --> RegionExtractor
Circle2D --> RegionExtractor
RegionExtractor --> PointCloudExtractor
RegionExtractor --> CADMeshExtractor
@enduml
三、交互状态机设计
@startuml
[*] --> Idle
Idle --> CreatingLine : 选择创建线工具
Idle --> CreatingCircle : 选择创建圆工具
Idle --> CreatingPoint : 选择创建点工具
Idle --> CreatingMeasurement : 选择测量工具
state CreatingLine {
[*] --> WaitingFirstPoint
WaitingFirstPoint --> Dragging : 双击
Dragging --> WaitingSecondPoint : 拖动
WaitingSecondPoint --> Extracting : 双击
Extracting --> Completed : 提取完成
}
state CreatingCircle {
[*] --> WaitingFirstPoint
WaitingFirstPoint --> WaitingSecondPoint : 双击
WaitingSecondPoint --> DraggingRing : 双击
DraggingRing --> Extracting : 双击
Extracting --> Completed : 提取完成
}
state CreatingPoint {
[*] --> WaitingClick
WaitingClick --> Completed : 双击
}
state CreatingMeasurement {
[*] --> SelectingSource
SelectingSource --> SelectingTarget : 选择源几何
SelectingTarget --> SelectingStrategy : 选择目标几何
SelectingStrategy --> Calculating : 选择算法
Calculating --> Completed : 计算完成
}
CreatingLine --> Idle : 完成/取消
CreatingCircle --> Idle : 完成/取消
CreatingPoint --> Idle : 完成/取消
CreatingMeasurement --> Idle : 完成/取消
@enduml
四、数据流设计
@startuml
participant "View2DSlice" as V2DS
participant "Controller" as CTRL
participant "DataModel" as DM
participant "View3D" as V3D
participant "View2DMeasure" as V2DM
V2DS -> CTRL : onLinePositionChanged(newPosition)
activate CTRL
CTRL -> DM : updateSlicePlane(newPosition)
activate DM
DM -> DM : recalculateBoundingBox()
DM --> CTRL : slicePlaneUpdated event
deactivate DM
CTRL -> V3D : updateSlicePlane(planeData)
activate V3D
V3D -> V3D : renderSlicePlane()
V3D --> CTRL : rendered
deactivate V3D
CTRL -> V2DM : updateBoundingBox(boxData)
activate V2DM
V2DM -> V2DM : renderBoundingBox()
V2DM --> CTRL : rendered
deactivate V2DM
deactivate CTRL
@enduml
五、核心模块说明
5.1 表现层(Presentation Layer)
- View3DWidget:3D视口,显示切割平面和高亮区域
- View2DSliceWidget:2D切割线拖动视口,实时更新边界框
- View2DMeasureWidget:2D测量编辑视口,核心交互窗口
5.2 控制层(Controller Layer)
- SectionMeasureController:总控制器,协调三个视图的同步
- InteractionStateMachine:状态机,管理复杂的交互流程
- CommandManager:命令管理器,支持撤销/重做
5.3 业务逻辑层(Business Logic Layer)
- Geometry包:几何元素定义(点、线、圆、文本)
- Measurement包:测量对象定义(各种距离、角度测量)
- Strategy包:测量算法策略(垂直、水平、最近距离等)
- Factory包:对象创建工厂
5.4 数据层(Data Layer)
- SectionDataModel:核心数据模型,存储所有几何和测量数据
- ObjectTreeAdapter:与对象树的适配器
- DataSerializer:序列化/反序列化支持
5.5 渲染层(Rendering Layer)
- GeometryRenderer:几何元素渲染器
- MeasurementRenderer:测量结果渲染器
- RenderStrategy:渲染策略接口
5.6 命令模式(Command Pattern)
- 所有修改操作封装为命令
- 支持撤销/重做
- 便于操作历史记录
5.7 数据提取层(Extraction Layer)
- RegionExtractor:区域数据提取器
- PointCloudExtractor:点云提取
- CADMeshExtractor:CAD网格提取
六、扩展性设计
6.1 新增几何类型
- 继承
GeometryElement - 在
GeometryFactory中添加创建方法 - 实现对应的
RenderStrategy - 在状态机中添加新状态
6.2 新增测量类型
- 继承
MeasurementElement - 实现对应的
MeasurementStrategy - 在
MeasurementFactory中注册 - 实现对应的
RenderStrategy
6.3 新增测量算法
- 实现
MeasurementStrategy接口 - 在测量对象中注册策略
七、关键技术点
7.1 数据与渲染分离
- 数据模型独立于VTK渲染
- 渲染器只负责可视化,不持有业务数据
- 支持多种渲染后端切换
7.2 序列化设计
SectionData {
version: "1.0"
slicePlane: {...}
geometries: [
{id, type, data, ...},
...
]
measurements: [
{id, type, source, target, strategy, result, ...},
...
]
}截面测量架构设计说明
一、设计思路过程
1. 问题分析
- 三视图联动:3D视图、2D切割视图、2D测量视图需要数据同步
- 复杂交互:多步骤的几何创建流程(线、圆的创建需要3-6个步骤)
- 多样测量:10+种测量类型,每种有不同算法(3种距离算法)
- 数据持久化:需要序列化到对象树,支持恢复
2. 设计策略
按照”分离关注点”原则,将系统拆分为5层:
- 表现层:负责UI显示和用户输入
- 控制层:协调视图同步和业务流程
- 业务逻辑层:封装几何和测量的核心逻辑
- 数据层:管理数据存储和序列化
- 渲染层:独立的VTK渲染逻辑
3. 关键设计模式选择
- 命令模式:解决撤销/重做问题
- 状态机模式:解决复杂交互流程问题
- 策略模式:解决多算法切换问题
- 工厂模式:解决对象创建统一管理
- 观察者模式:解决视图间同步问题
二、架构核心说明
【表现层】三个独立视图
View3DWidget → 显示3D切割状态
View2DSliceWidget → 拖动切割线,触发数据更新
View2DMeasureWidget → 核心交互窗口,创建几何和测量职责:只负责显示和收集用户输入,不包含业务逻辑
【控制层】协调中枢
SectionMeasureController
├── 接收视图事件
├── 调用CommandManager执行命令
├── 同步三个视图的数据
└── 触发渲染更新
InteractionStateMachine
├── 管理创建几何的多步骤流程
├── 状态转换:空闲→等待第一点→拖动→等待第二点→提取→完成
└── 调用GeometryFactory创建对象
CommandManager
├── 执行命令并记录历史
├── 支持undo/redo
└── 所有数据修改都封装为命令【业务逻辑层】核心领域模型
1. 几何元素(Geometry)
GeometryElement(抽象基类)
├── Point2D → 2D点
├── Line2D → 线(带宽度,支持区域提取)
├── Circle2D → 圆环(支持区域提取)
└── TextAnnotation → 文本标注特点:
- 每个几何对象独立存在
- 提供序列化/反序列化接口
- Line2D和Circle2D支持区域提取(点云/CAD网格)
2. 测量对象(Measurement)
MeasurementElement(抽象基类)
├── PointToPointMeasure → 点到点(3种算法)
├── PointToLineMeasure → 点到线
├── LineToLineMeasure → 线到线
├── CircleToLineMeasure → 圆到线
├── PointToCircleMeasure → 点到圆(3种算法)
├── CircleToCircleMeasure → 圆到圆(3种算法)
├── AngleMeasure → 角度
└── RadiusMeasure → 半径特点:
- 持有源几何和目标几何的引用
- 使用策略模式注入测量算法
- calculate()方法返回测量结果
3. 测量策略(Strategy)
MeasurementStrategy(接口)
├── VerticalDistanceStrategy → 垂直距离
├── HorizontalDistanceStrategy → 水平距离
├── NearestDistanceStrategy → 最近距离
├── CenterDistanceStrategy → 圆心距离
└── FarthestDistanceStrategy → 最远距离优势:算法可替换,易扩展新算法
【数据层】数据管理中心
SectionDataModel
├── 存储所有几何元素(vector<GeometryElement*>)
├── 存储所有测量对象(vector<MeasurementElement*>)
├── 存储切割平面数据(SlicePlaneData)
├── 存储边界框数据(BoundingBox)
└── 提供序列化/反序列化接口
ObjectTreeAdapter
└── 双向同步对象树数据
DataSerializer
└── 支持JSON/XML等格式序列化核心:数据与渲染完全分离,数据模型不依赖VTK
【渲染层】可视化引擎
GeometryRenderer
├── 根据几何类型选择渲染策略
├── 渲染点、线、圆、文本
└── 支持高亮显示
MeasurementRenderer
├── 渲染测量结果(数值、标注线)
└── 动态更新测量值显示特点:
- 使用策略模式,每种几何/测量有独立渲染策略
- 只负责可视化,不修改数据
三、关键流程示例
流程1:创建线的完整过程
1. 用户点击"创建线"按钮
→ View2DMeasureWidget发送事件
→ InteractionStateMachine切换到"WaitingFirstPoint"状态
2. 用户双击第一点
→ 状态机切换到"Dragging"状态
→ 实时显示预览线
3. 用户拖动鼠标
→ 动态更新线的宽度区域
4. 用户双击第二点
→ 状态机切换到"Extracting"状态
→ 调用RegionExtractor提取点云/CAD网格
5. 提取完成
→ GeometryFactory创建Line2D对象
→ 封装为CreateGeometryCommand
→ CommandManager执行命令
→ SectionDataModel添加几何对象
→ GeometryRenderer渲染线和高亮区域
→ ObjectTreeAdapter同步到对象树流程2:视图联动
1. 用户在View2DSliceWidget拖动切割线
→ 触发onLinePositionChanged()事件
2. SectionMeasureController接收事件
→ 封装为ModifySlicePlaneCommand
→ 更新SectionDataModel中的slicePlane数据
→ 重新计算boundingBox
3. Controller同步三个视图
→ View3DWidget更新3D切割平面显示
→ View2DSliceWidget更新边界框显示
→ View2DMeasureWidget重新渲染截面内容五、技术要点总结
| 层次 | 核心职责 | 关键技术 |
|---|---|---|
| 表现层 | UI显示和输入 | Qt Widget + VTK Renderer |
| 控制层 | 流程协调 | 命令模式 + 状态机 |
| 业务逻辑层 | 领域模型 | 策略模式 + 工厂模式 |
| 数据层 | 数据管理 | 适配器模式 + 序列化 |
| 渲染层 | 可视化 | 策略模式 + VTK |
设计原则:单一职责、开闭原则、依赖倒置、接口隔离
作者:admin 创建时间:2025-12-11 10:39
最后编辑:admin 更新时间:2025-12-11 10:47
最后编辑:admin 更新时间:2025-12-11 10:47