OCCT 预览显示与永久显示设计哲学: 非破坏性编辑 (Non-destructive Editing) 设计模式

在现代三维建模和计算机辅助设计(CAD)领域,用户的每一次操作都可能涉及复杂且耗时的计算。如何为用户提供一个既能实时响应、又能确保数据安全的操作环境,是软件架构设计的核心挑战之一。预览与永久应用分离的机制,正是非破坏性编辑 (Non-destructive Editing) 这一核心设计模式的经典体现。

非破坏性编辑,顾名思义,是指在编辑过程中,用户的任何尝试性操作都不会立即、永久地改变或破坏原始数据。系统会提供一个临时的、可视化的结果反馈,直到用户明确确认,才会将该操作的结果固化到核心数据结构中。这种模式的精髓在于将 “探索过程”“最终决策” 彻底解耦。

一、 核心原则:计算与应用的解耦

这种设计模式的基础,是将一个完整的用户操作分解为两个独立但关联的阶段:

  1. 计算核心 (The Computation Core): 这是操作的“本质”。它负责根据给定的输入(如两个几何体)和规则(如布尔运算法则:并集、交集、差集)来生成一个结果。在OCCT中,这对应于 BRepAlgoAPI_Union (CreateBooleanUnion)、BRepAlgoAPI_Cut 等算法类。这些类的职责是纯粹的、单一的:执行计算,返回结果。它们不关心这个结果将被如何使用。

  2. 应用逻辑 (The Application Logic): 这是操作的“意图”。它决定了计算核心产生的结果将面临何种“命运”。这个阶段被进一步细分为两种截然不同的路径:

    • 预览 (Preview): 临时的、探索性的路径。
    • 应用 (Apply): 永久的、决策性的路径。

正是这种清晰的解耦,构成了非破坏性编辑的基石。

二、 实现的两大支柱:预览与应用
支柱一:预览 (previewBooleanOperation) —— 安全的“沙盒”

预览功能是用户与复杂操作交互的第一触点。它构建了一个零风险的探索环境,其关键特征如下:

  • 瞬时性与临时性: 预览创建的视觉对象(在OCCT中通常是一个 AIS_Shape 实例,如 m_operationPreviewAIS)独立于主场景数据之外。它像一个幽灵,只存在于当前的交互会话中,不被场景的持久化数据(如 TDocStd_Document)所记录。
  • 轻量级与高性能: 由于预览不涉及修改主场景图、不触发依赖更新、不记录撤销历史,它的创建和销毁成本极低。这保证了当用户快速切换操作类型或选择对象时,系统能够提供流畅、实时的视觉反馈。
  • 视觉引导: 预览的唯一目的是“显示”。它可以被赋予特殊的颜色、透明度或线框模式,以在视觉上与场景中的“真实”对象区分开来,明确地告诉用户:“这只是一个可能的结果,尚未成为现实。”

设计隐喻: 预览就像建筑师在一张描图纸(Tracing Paper)上覆盖于原始蓝图之上进行草图设计。他可以随意涂改、尝试各种方案,而不会弄脏底层的蓝图。

支柱二:应用 (applyBooleanOperation) —— 郑重的“承诺”

当用户对预览结果感到满意并点击“应用”或“确认”时,系统将执行一个截然不同的工作流。这是一个经过深思熟虑的、对数据进行永久性修改的过程。

  • 意图明确: “应用”操作是一个由用户主动发起的、不可逆的(在不使用撤销功能的前提下)决策点。
  • 场景修改: 它是唯一会修改核心数据结构的环节。计算结果(可能直接复用预览时缓存的结果)被正式添加到主场景中 (AddShapeToScene),成为一个“真实”的对象。
  • 生命周期管理: 此阶段需要根据预设规则处理原始输入对象,例如“删除工具对象”、“保留所有原始对象”或“隐藏原始对象”。
  • 集成事务与历史: 这是至关重要的一步。“应用”操作必须被封装在一个事务(Transaction)中,并被完整地记录到应用的撤销/重做 (Undo/Redo) 堆栈里。这确保了即便是永久性修改,也依然处在用户的掌控之中,可以被撤销。

设计隐喻: “应用”就像建筑师在对描图纸上的草图满意后,用墨水笔将最终设计正式描绘在原始蓝图上,并擦除掉之前的铅笔辅助线。这一笔是决定性的,但现代的“魔法橡皮”(撤销功能)让其依然有反悔的余地。

三、 共享的基石:统一的计算逻辑

预览和应用虽然在行为上天差地别,但它们共享同一个大脑——CreateBoolean... 等核心计算函数。这遵循了 “不要重复自己” (DRY - Don’t Repeat Yourself) 的黄金软件工程原则。

  • 一致性保证: 预览看到的结果和最终应用的结果在几何上是完全一致的,因为它们源自同一个算法。这避免了“预览一个样,应用另一个样”的灾难性bug。
  • 维护性超群: 如果未来需要优化布尔运算的性能或修复其算法缺陷,开发者只需要修改这一个共用的计算核心即可。预览和应用两个功能将自动受益,无需任何额外修改。
四、 为什么非破坏性编辑模式如此重要?

采用这种设计模式所带来的好处是全方位的:

  1. 赋能用户,鼓励创造: 它极大地降低了用户的心理负担。用户可以大胆地尝试任何复杂的操作,而不必担心灾难性的后果,从而释放了创造力和探索精神。
  2. 提升性能,优化体验: 将高频、探索性的预览操作与低频、高成本的场景修改操作分离开,确保了用户界面的流畅响应,这是“所见即所得” (WYSIWYG) 体验的关键。
  3. 构建健壮、清晰的系统架构: 基于“关注点分离” (Separation of Concerns) 和“单一职责原则” (Single Responsibility Principle),代码的模块化程度更高,逻辑更清晰,从而更易于测试、维护和扩展。

五、设计模式的核心:形状创建的复用与显示逻辑的分离

如果说“非破坏性编辑”是这项设计的哲学外衣,那么其技术内核可以精准地概括为:对“形状创建”这一核心计算的最大化复用,以及对“结果显示/应用”这一后续逻辑的彻底分离。

这不仅仅是一种好的实践,它是整个架构能够成立的根本。

1. 统一的“形状制造厂”——代码复用

设计的第一个关键点在于,无论是瞬时即逝的预览,还是永久固化的应用,它们生成最终几何体 (TopoDS_Shape) 的源头是完全相同的——都是对 CreateBooleanUnionCreateBooleanIntersectionCreateBooleanDifference 这一族核心函数的调用。

  • 保证一致性: 这种设计从根本上杜绝了“预览一个样,应用另一个样”的严重bug。用户在预览中所见,即为他最终所得,提供了坚实可靠的预期。
  • 提升可维护性: 布尔运算是几何建模中最复杂、最易出错的部分之一。将其封装成一个独立的、可信赖的“形状制造厂”,意味着任何针对该算法的优化或修复(例如,提升计算速度、处理奇异边界情况),都能自动地、安全地应用到所有依赖它的功能上,而无需改动上层的预览或应用代码。开发者只需维护这一个核心计算模块。
2. 两条独立的“流水线”——显示/应用逻辑分离

设计的第二个、也是更精妙的关键点在于,由“形状制造厂”生产出的同一个几何形状,会被送往两条职责完全不同、互相隔离的“处理流水线”:

  • 预览流水线 (previewBooleanOperation): 这条线的任务是 “快”“轻”。它接收形状后,立即将其包装在一个临时的、低成本的可视化对象(m_operationPreviewAIS)中,并直接呈现在屏幕上。它不关心主场景数据、不记录历史、不触发复杂的依赖更新。它的唯一使命就是以最小的系统开销,提供即时、瞬态的视觉反馈。一旦用户意图改变,整条线上的临时产物会被瞬间清除,为下一次预览让路。

  • 应用流水线 (applyBooleanOperation): 这条线的任务是 “稳”“全”。它同样接收那个形状,但会执行一系列“重量级”的正式工序:将其正式注册到主场景的数据结构中 (AddShapeToScene);根据规则处理输入对象的生命周期(保留或删除);最重要的是,将这整个操作封装成一个事务,完整地记录到撤销/重做 (Undo/Redo) 堆栈中。它的每一步都意味着对程序核心数据的永久性(尽管是可撤销的永久性)修改。

结论:算法与交互的解耦

这种设计的精髓在于实现了 “纯粹算法”与“应用交互”的完美解耦

  • “创建形状” 是一个纯粹的算法问题,它只关心输入和输出,因此应该被统一和复用
  • “如何处理这个被创建出的形状” 则是一个应用交互和场景管理的问题,应该根据上下文(是临时看看?还是永久保存?)进行分离和特化

这种清晰的界限划分,是构建出一个既能满足复杂几何计算需求,又能提供流畅、直观用户体验的专业图形软件的基石。
这并不仅仅是一种技术技巧,它是一种成熟的、以用户为中心的设计哲学——非破坏性编辑。它通过将计算、临时显示和永久应用这三个环节的巧妙分离与组合,成功地在用户体验的流畅性系统性能的高效性数据安全的稳健性之间找到了完美的平衡点。这一模式是所有专业级、交互式图形软件成功的基石,也是从“能用”到“好用”的必经之路。

你可能感兴趣的:(OCCT 预览显示与永久显示设计哲学: 非破坏性编辑 (Non-destructive Editing) 设计模式)