图形算法库研发(四):OpenCASECADE的二维曲线求交算法验证

文章探讨了使用OpenCASCADE库进行二维圆的通用曲线求交功能的性能,发现对于明显不重合和接近重合情况下的处理存在问题,尤其是后者耗时较长。作者强调了优化空间,尤其是在处理接近重合时的算法改进需求。
摘要由CSDN通过智能技术生成

先从简单的入手,二维曲线求交。
读者也可以当个学习的Demo来用。
首先看看我们的对标产品实现的怎么样。
说明:整个测试过程中只测试用圆生成的通用曲线求交。之所以用圆是因为圆很直观;之所以只测试通用曲线求交,因为特殊曲线求交可以特殊实现(例如圆和圆求交),代码难度不大,不是技术难点,只是工作量问题。

先做一个普通测试:

#include <iostream>
#include <Geom2d_Circle.hxx>
#include <Geom2d_BSplineCurve.hxx>
#include <Geom2dAPI_InterCurveCurve.hxx>
#include <Geom2dConvert.hxx>
#include "prof.h"

int main()
{
	//定义两个圆
    Handle(Geom2d_Circle) circle1 = new Geom2d_Circle(gp_Ax2d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 100);
    Handle(Geom2d_Circle) circle2 = new Geom2d_Circle(gp_Ax2d(gp_Pnt2d(50, 0), gp_Dir2d(1, 0)), 100);
	//转成Nurbs,这样能测试通用曲线求交
    Handle(Geom2d_BSplineCurve) curve1 = Geom2dConvert::CurveToBSplineCurve(circle1);
    Handle(Geom2d_BSplineCurve) curve2 = Geom2dConvert::CurveToBSplineCurve(circle2);

	//运算1000次并计时,计时器代码贴到最后
    Stopwatch sw;
    sw.Resume();
    for (int i = 0; i < 1000; ++i) {
        Geom2dAPI_InterCurveCurve intCurveCurve(curve1, curve2);
    }
    sw.Suspend();
    Geom2dAPI_InterCurveCurve intCurveCurve(curve1, curve2);
    int point_count = intCurveCurve.NbPoints();
    int segment_count = intCurveCurve.NbSegments();

	//简单输出结果情况和1000次的时间。
    std::cout << point_count << "\n";
    std::cout << segment_count << "\n";
    std::cout << sw.GetTotalTime() << "\n";
}

运行结果:

2
0
0.065093

1000次用时0.065093秒,还是不错的。
再试试重合的情况:

//定义两个圆
    Handle(Geom2d_Circle) circle1 = new Geom2d_Circle(gp_Ax2d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 100);
    Handle(Geom2d_Circle) circle2 = new Geom2d_Circle(gp_Ax2d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 100);

运行结果:

2
1
3.08635

结果非常不理想,求出2个点和1段重合线,和我预期不太一致,用时方面这次1000次用了3.08635秒,算是非常慢了,可能OpenCASECADE有检测重合的算法,但即使有,每次求交都调重合监测,也不好。

最后测试一下接近重合

//定义两个圆
    Handle(Geom2d_Circle) circle1 = new Geom2d_Circle(gp_Ax2d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 100);
    Handle(Geom2d_Circle) circle2 = new Geom2d_Circle(gp_Ax2d(gp_Pnt2d(1, 0), gp_Dir2d(1, 0)), 100);

运行结果:

0
0
1.68328

接近重合情况还是很常见的,也是最容易出错的,可见OpenCASECADE表现的并不好,计算结果错误,没有找到交点,耗时也不少,1000次耗时1.68328秒。

总的来说,在求交很明显情况下,效率还是可以的;接近重合情况处理的很不好。
所以优化空间还是很大的!

附录:时间测量类

#include <chrono>

class Stopwatch {
public:
	Stopwatch() {
		m_is_running = false;
		Reset();
	}

	void Reset() {
		if (m_is_running) {
			throw;
		}
		m_total_count = 0;
		m_total_time = std::chrono::high_resolution_clock::now() - std::chrono::high_resolution_clock::now();
	}

	void Resume() {
		if (m_is_running) {
			throw;
		}
		m_is_running = true;
		m_start_time = std::chrono::high_resolution_clock::now();
	}

	void Suspend() {
		if (!m_is_running) {
			throw;
		}
		++m_total_count;
		m_total_time += std::chrono::high_resolution_clock::now() - m_start_time;
		m_is_running = false;
	}

	double GetTotalTime() {
		if (m_is_running) {
			throw;
		}
		return m_total_time.count() * 1E-9;
	}

	double GetTotalCount() {
		if (m_is_running) {
			throw;
		}
		return m_total_count;
	}
private:
	bool m_is_running;
	int m_total_count;
	std::chrono::steady_clock::time_point m_start_time;
	std::chrono::nanoseconds m_total_time;
};
  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值