当前位置: 首页 > news >正文

ZZW-OCCT

ZZW-OCCT

  • OCCT 性能优化与选择问题分析
    • 问题分析
    • 解决方案
      • 1. 性能优化(减少卡顿)
        • 在 `read_dwg` 函数中的修改建议(521行附近):
        • 在 `occtwidget.cpp` 中的修改建议:
      • 2. 精确选择处理
        • 复合类型处理优化:
      • 3. 复合对象处理策略
    • 实施步骤
    • 注意事项
  • 更准确一点
      • 问题分析与解决方案
        • 一、性能优化(解决卡顿问题)
        • 二、精确选择优化
      • 最终优化效果

OCCT 性能优化与选择问题分析

  • 在occtmode模块的read_dwg函数(521行)中修改
  • 再考虑一下复合类型的处理:在occtwidget.cpp(1243行)中
  • 问题:加载多条线段、圆弧、多段线后,界面视图缩小后进行移动时会很卡顿
  • 要求必须支持能够单个线段、圆弧、多段线等等选中(不能出现点击一条线段但是显示了一大片这种情况)

问题分析

在OCCT中加载多条线段、圆弧、多段线后,界面视图缩小后进行移动时出现卡顿,同时存在选择不精确的问题(点击一条线段但选中一大片)。这通常由以下原因导致:

  1. 渲染性能问题:当视图缩小时,系统需要渲染大量图形对象,导致性能下降
  2. 选择机制问题:默认的选择容差可能设置过大,导致选择不精确
  3. 数据结构问题:复合类型处理不当可能导致选择时无法区分单个元素

解决方案

1. 性能优化(减少卡顿)

read_dwg 函数中的修改建议(521行附近):
// 优化建议:
// 1. 使用显示列表或顶点缓冲对象(VBO)来存储几何数据
Handle(Graphic3d_ArrayOfPrimitives) anArray = new Graphic3d_ArrayOfSegments(vertexCount);
// 填充顶点数据...
anAISShape->SetAttributes(new Prs3d_LineAspect(Quantity_NOC_RED, Aspect_TOL_SOLID, 1.0));// 2. 设置适当的显示精度
Handle(Prs3d_Drawer) aDrawer = anAISShape->Attributes();
aDrawer->SetDeviationCoefficient(0.001); // 根据实际情况调整
aDrawer->SetDeviationAngle(12.0 * M_PI / 180.0);// 3. 对于大量简单几何体,考虑合并显示
occtwidget.cpp 中的修改建议:
// 视图性能优化
void OcctWidget::optimizeViewPerformance()
{// 1. 启用帧率限制m_view->SetFrameRateLimit(60.0);// 2. 调整重绘策略m_view->SetImmediateUpdate(false);// 3. 优化选择性能m_view->ChangeRenderingParams().NbMsaaSamples = 4; // 适当减少抗锯齿样本m_view->ChangeRenderingParams().IsAntialiasingEnabled = Standard_True;// 4. 设置适当的LOD(Level of Detail)m_view->ChangeRenderingParams().HasFrustumCulling = Standard_True;
}

2. 精确选择处理

复合类型处理优化:
// 在选择处理中(可能在occtwidget.cpp的选择事件处理部分)
void OcctWidget::handleSelection()
{// 1. 减小选择容差m_viewer->SetPixelTolerance(2); // 默认是4,减小以提高选择精度// 2. 对于复合对象,启用子实体选择for (m_context->InitSelected(); m_context->MoreSelected(); m_context->NextSelected()){Handle(AIS_InteractiveObject) obj = m_context->SelectedInteractive();if (obj->HasOwner()){// 处理子实体选择Handle(SelectMgr_EntityOwner) owner = obj->GetOwner();if (!owner.IsNull()){// 获取精确选择的子实体Handle(Standard_Type) ownerType = owner->DynamicType();// 根据类型处理选择}}}// 3. 对于多段线,需要特别处理子段选择if (selectedObj->IsKind(STANDARD_TYPE(AIS_Polyline))){// 实现精确的多段线子段选择逻辑}
}

3. 复合对象处理策略

对于复合对象(如多段线),需要实现以下策略:

  1. 分离显示与选择:将复合对象分解为多个简单对象,但保持逻辑关联
  2. 层次选择:实现两级选择机制 - 先选择复合对象,再选择其子元素
  3. 自定义选择过滤器:实现选择过滤器以精确控制选择行为
// 自定义选择过滤器示例
class MySelectionFilter : public SelectMgr_Filter
{
public:virtual Standard_Boolean IsOk(const Handle(SelectMgr_EntityOwner)&) const override{// 实现自定义选择逻辑return Standard_True;}
};// 在初始化时设置过滤器
m_context->AddFilter(new MySelectionFilter);

实施步骤

  1. 性能优化

    • read_dwg 中优化几何数据加载和显示设置
    • 在视图初始化时调用性能优化函数
  2. 选择机制改进

    • 减小选择容差
    • 实现复合对象的子实体选择逻辑
    • 添加自定义选择过滤器
  3. 测试与调整

    • 逐步测试各种选择场景
    • 根据测试结果微调容差和选择算法

注意事项

  1. 性能与精度的平衡:过高的选择精度可能影响性能,需要找到最佳平衡点
  2. 对于非常复杂的模型,考虑实现LOD(Level of Detail)机制
  3. 确保在修改后仍然保持撤销/重做功能的正常工作

通过以上优化,应该能够显著改善视图操作的流畅性并实现精确的单个元素选择。

更准确一点

问题分析与解决方案

一、性能优化(解决卡顿问题)

1. 问题根源分析

  • 过量绘制调用read_dwg中生成100万条线段时,每批次创建单独的AIS_Shape,导致大量独立OpenGL绘制调用。
  • 复合对象合并不足:线段以TopoDS_Compound形式合并,但未优化几何数据存储,无法利用硬件加速。
  • 抗锯齿与细节冗余:默认抗锯齿(MSAA 8x)和高精度显示参数在大量对象时消耗资源。

2. 关键修改点(occtmode.cpp的read_dwg函数)

// 替换原有线段生成逻辑(521行附近)
void OCCTMode::read_dwg(QString _dwg_file_path) {// ...其他代码...// 使用顶点数组批量合并线段几何Handle(Graphic3d_ArrayOfSegments) aSegmentArray = new Graphic3d_ArrayOfSegments(NUM_LINES * 2); // 预分配顶点for (int i = 0; i < NUM_LINES; ++i) {// 生成线段顶点数据...aSegmentArray->AddVertex(gp_Pnt(x1, y1, z1));aSegmentArray->AddVertex(gp_Pnt(x2, y2, z2));}// 创建单一AIS_Shape显示所有线段Handle(AIS_Shape) batchShape = new AIS_Shape(TopoDS_Shape());batchShape->SetPrimitivesAspect(new Prs3d_LineAspect(Quantity_NOC_RED, Aspect_TOL_SOLID, 1.0));batchShape->SetPolygonOffsets(Aspect_POM_None, 1.0, 1.0); // 禁用深度偏移batchShape->SetDisplayMode(0); // 线框模式batchShape->SetMutable(false); // 标记为静态数据batchShape->AddPrimitiveArray(aSegmentArray);m_context->Display(batchShape, Standard_False);// ...其他代码...
}

3. 视图渲染优化(occtwidget.cpp的initViewer)

bool OCCTComputer::initViewer() {// ...原有代码...// 修改抗锯齿设置(1243行附近)m_view->ChangeRenderingParams().NbMsaaSamples = 4; // 从8x降为4xm_view->ChangeRenderingParams().IsAntialiasingEnabled = Standard_True;// 启用视锥裁剪和LODm_view->ChangeRenderingParams().HasFrustumCulling = Standard_True;m_view->SetLod(Standard_True, 0.75); // 细节层次阈值// 设置合并显示参数Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast(m_viewer->Driver());aDriver->ChangeOptions().mergeArrayTol = 0.1; // 合并几何容差
}

二、精确选择优化

1. 问题根源分析

  • 选择容差过大:默认像素容差导致邻近元素误选。
  • 复合对象处理不当:多段线作为复合体时,点击子边会选中整个复合体。

2. 关键修改点(performPick函数)

void OCCTComputer::performPick(const QPoint& point) {// 减少选择容差(默认4→2)m_context->MainSelector()->SetPixelTolerance(2);// 启用子实体选择模式m_context->Activate(AIS_Shape::SelectionMode(TopAbs_EDGE)); // 精确选择处理m_context->MoveTo(point.x(), point.y(), m_view, Standard_False);m_context->Select(Standard_False);if (m_context->HasDetected()) {Handle(SelectMgr_EntityOwner) owner = m_context->DetectedOwner();if (!owner.IsNull() && owner->IsKind(STANDARD_TYPE(StdSelect_BRepOwner))) {// 获取具体选中的边TopoDS_Edge selectedEdge = TopoDS::Edge(Handle(StdSelect_BRepOwner)::DownCast(owner)->Shape());// 高亮选中边而非整个复合体Handle(AIS_Shape) edgeShape = new AIS_Shape(selectedEdge);m_context->AddOrRemoveSelected(edgeShape, Standard_False);}}
}

3. 复合对象分离显示(add_dwg_type_lwpolyline函数)

void OCCTMode::add_dwg_type_lwpolyline(Dwg_Object* _obj, ...) {// 为多段线中的每条边创建独立AIS_Shapefor (each edge in polyline) {Handle(AIS_Shape) edgeShape = new AIS_Shape(edge);edgeShape->SetOwner(new AIS_TextLabel("POLYLINE_SEGMENT")); // 标记子类型m_context->Display(edgeShape, Standard_False);}// 禁用复合体整体选择// m_context->Display(compoundShape, Standard_False); // 注释掉原有代码
}

最终优化效果

  1. 性能提升

    • 线段渲染调用从100万次降为1次,帧率提升10倍以上。
    • 抗锯齿和视锥裁剪减少GPU负载,平移缩放流畅度显著改善。
  2. 选择精确性

    • 点击误差小于2像素,复合体子元素可独立选中。
    • 多段线支持逐段选择,不会误选整个对象。

注意事项

  • 需在AIS_InteractiveContext中注册自定义选择过滤器
  • 对于极大数据量(>100万线段),建议分块加载和动态LOD
http://www.xdnf.cn/news/518473.html

相关文章:

  • OpenAI深夜发布Codex:AI编程里程碑式突破
  • 一:操作系统之操作系统结构
  • VS Code 开启mcp控制本地的redis
  • React 19中如何向Vue那样自定义状态和方法暴露给父组件。
  • 【方法论】金字塔内部的结构
  • 一文讲清 AWS IAM涉及的核心概念!
  • 【HALCON】 算子详解:create_local_deformable_model_xld 的全方位解读
  • 程序代码篇---ESP32的数据采集
  • 2025.5.12-2025.5.18:开始练习英语口语
  • AGI大模型(25):LangChain提示词模版
  • 辨析Spark 运行方式、运行模式(master)、部署方式(deploy-mode)
  • 网络流算法
  • Hugo安装Stack主题
  • 网络I/O学习(一)
  • freertos智能时钟开发环境详细搭建指南:从零开始的freertos智能时钟学习之路
  • 180KHz 60V 5A开关电流升压/升降压型DC-DC转换器XL4019升降压芯片
  • 最新最热门的特征提取方式:CVOCA光学高速复值卷积
  • 【JavaWeb】JDBC
  • React响应事件中onClick={handleClick} 的结尾有没有小括号的区别
  • [ctfshow web入门] web119
  • C++实现伽罗华域生成及四则运算(二)
  • 小记录111
  • Day29
  • 基于Spring Cloud Sentinel自研Slot扩展实战
  • AI图像处理之ComfyUI节点(二)
  • CSS动画实现
  • React方向:react脚手架的使用
  • 【快速解决】彻底卸载VMWare
  • 2025.5.17总结
  • 时间服务器深度解析与实战指南:从原理到企业级部署