SVD拟合直线、平面

SVD的原理、应用参考博客:奇异值分解(SVD)方法求解最小二乘问题的原理 - 一抹烟霞 - 博客园

SVD拟合直线:SVD的第一列就是直线的方向,直线位置点通过中心化测量点集得到

SVD拟合平面:SVD第一列向量与第二列向量的叉乘就是平面的 法向,平面的基点通过法向上的平移得到

具体步骤如下(以下代码使用了GSL数学库和opencascade模型库,且仅使用直线点集的中心点作为位置点):

	// 中心化测量点,并计算中心点作为拟合直线的位置。
		gp_Pnt location;
		const vector<gp_Pnt> points = Centralize(measuredPoints, location);

		// 创建矩阵。
		gsl_matrix* gslA = gsl_matrix_alloc(points.size(), 3);
		unique_ptr<gsl_matrix, function<void(gsl_matrix*)>> gslA_ForAutoDelete(gslA, GslMatrixDeleter);

		for (int i = 0; i < points.size(); i++) {
			gsl_matrix_set(gslA, i, 0, points[i].X());
			gsl_matrix_set(gslA, i, 1, points[i].Y());
			gsl_matrix_set(gslA, i, 2, points[i].Z());
		}

		// SVD分解。
		gsl_matrix* gslV = gsl_matrix_alloc(3, 3);
		unique_ptr<gsl_matrix, function<void(gsl_matrix*)>> gslV_ForAutoDelete(gslV, GslMatrixDeleter);

		gsl_vector* gslD = gsl_vector_alloc(3);
		unique_ptr<gsl_vector, function<void(gsl_vector*)>> gslD_ForAutoDelete(gslD, GslVectorDeleter);

		gsl_vector* work = gsl_vector_alloc(3);
		unique_ptr<gsl_vector, function<void(gsl_vector*)>> work_ForAutoDelete(work, GslVectorDeleter);

		int gsl_errno = gsl_linalg_SV_decomp(gslA, gslV, gslD, work);
		if (gsl_errno) {
			return nullptr;
		}

		// 第一个右奇异向量作为直线方向。
		gsl_vector* gslDirection = gsl_vector_alloc(3);
		unique_ptr<gsl_vector, function<void(gsl_vector*)>> gslDirection_ForAutoDelete(gslDirection, GslVectorDeleter);
		gsl_matrix_get_col(gslDirection, gslV, 0);

		gp_XYZ gpDirectinXYZ;
		GslFacility::Copy(gslDirection, gpDirectinXYZ);

		// 得到拟合直线。
		return make_shared<gp_Ax1>(location, gpDirectinXYZ);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值