VTK解决曲面拟合问题

  1. 将问题简化为拟合二次曲面函数
    z = a x 2 + b y 2 + c x y + d x + e y + f z = ax^2 + by^2 + cxy + dx + ey + f z=ax2+by2+cxy+dx+ey+f
    写成矩阵乘法形式
    z = [ x 2 y 2 x y x y 1 ] [ a b c d e ] z = \begin{bmatrix} x^2 & y^2 & xy & x & y & 1 \end{bmatrix} \begin{bmatrix} a\\ b\\ c\\ d\\ e\\ \end{bmatrix} z=[x2y2xyxy1]abcde
    M = [ a b c d e ] M=\begin{bmatrix} a\\ b\\ c\\ d\\ e\\ \end{bmatrix} M=abcde, X = [ x 2 y 2 x y x y 1 ] X = \begin{bmatrix} x^2 & y^2 & xy & x & y & 1 \end{bmatrix} X=[x2y2xyxy1], Y = z Y=z Y=z
    M = Y X − 1 M=YX^{-1} M=YX1
  2. 最小二乘法求解线性方程组
#include <vtkMath.h>

namespace
{
	/* allocate memory for an nrow x ncol matrix */
	template <class TReal> TReal** create_matrix(long nrow, long ncol)
	{
		typedef TReal* TRealPointer;
		TReal** m = new TRealPointer[nrow];

		TReal* block = (TReal*)calloc(nrow * ncol, sizeof(TReal));
		m[0] = block;
		for (int row = 1; row < nrow; ++row)
		{
			m[row] = &block[row * ncol];
		}
		return m;
	}

	/* free a TReal matrix allocated with matrix() */
	template <class TReal> void free_matrix(TReal** m)
	{
		free(m[0]);
		delete[] m;
	}
} // namespace


int main(int, char*[])
{
	srand(42);
	// 拟合平面
	// z = ax^2 + by^2 + cxy + dx + ey + f
	// 等价于
	// Solve XM = Y;
	// [x^2 y^2 xy x y 1][a b c d e f].T = z
	int numberOfSamples = 50;
	int numberOfVariables = 6;
	double** x = create_matrix<double>(numberOfSamples, numberOfVariables);
	double** y = create_matrix<double>(numberOfSamples, 1);
	for (int i = 0; i < 50; i++)
	{
		// [a b c d e f] = [1,2,3,4,5,6]
		auto rx = rand() % 100;
		auto ry = rand() % 100;
		double noise = 1.0 / sqrt(6.28)*exp(-0.5*(rx*rx));
		x[i][0] = rx * rx;
		x[i][1] = ry * ry;
		x[i][2] = rx * ry;
		x[i][3] = rx;
		x[i][4] = ry;
		x[i][5] = 1;

		y[i][0] = rx * rx + 2 * ry * ry + 3 * rx * ry + 4 * rx + 5 * ry + 6 + noise;
	}


	double** m = create_matrix<double>(numberOfVariables, 1);
	vtkMath::SolveLeastSquares(numberOfSamples, x, numberOfVariables, y, 1, m);

	std::cout << "Solution is: "
		<< m[0][0] << " " << m[1][0] << " "
		<< m[2][0] << " " << m[3][0] << " "
		<< m[4][0] << " " << m[5][0] << std::endl;

	free_matrix(x);
	free_matrix(m);
	free_matrix(y);

	return EXIT_SUCCESS;
}

运行结果
在这里插入图片描述

[1]. https://kitware.github.io/vtk-examples/site/Cxx/Math/LeastSquares/
[2]. https://kitware.github.io/vtk-examples/site/Cxx/Math/HomogeneousLeastSquares/

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VTK(Visualization Toolkit)是一个用于科学可视化的开源软件库。要对曲面进行包围盒处理,可以使用VTK中的vtkPolyData类和vtkBoundingBox类。 首先,你需要将曲面数据加载到vtkPolyData对象中。可以使用VTK提供的各种读取器(如vtkPLYReader、vtkOBJReader等)来加载不同格式的曲面数据。 接下来,你可以通过vtkPolyData对象的GetBounds()方法获取曲面的边界框(bounding box),即一个六元素的浮点数组,表示边界框的最小和最大坐标值。 然后,你可以使用vtkBoundingBox类来操作边界框。该类提供了一些有用的方法,如ExpandBounds()用于扩展边界框,IntersectBox()用于计算边界框与另一个边界框的交集等。 以下是一个简单的示例代码: ```cpp #include <vtkPolyData.h> #include <vtkBoundingBox.h> #include <vtkPLYReader.h> int main() { // 加载曲面数据 vtkSmartPointer<vtkPLYReader> reader = vtkSmartPointer<vtkPLYReader>::New(); reader->SetFileName("surface.ply"); reader->Update(); // 获取曲面边界框 vtkSmartPointer<vtkPolyData> polyData = reader->GetOutput(); double bounds[6]; polyData->GetBounds(bounds); // 创建边界框对象 vtkBoundingBox boundingBox; boundingBox.SetBounds(bounds); // 扩展边界框 boundingBox.ExpandBounds(0.1); // 扩展10% // 获取扩展后的边界框 double expandedBounds[6]; boundingBox.GetBounds(expandedBounds); // 输出边界框坐标 for (int i = 0; i < 6; i++) { std::cout << expandedBounds[i] << " "; } std::cout << std::endl; return 0; } ``` 这段代码加载了一个PLY格式的曲面数据,并获取了其边界框。然后,使用vtkBoundingBox类对边界框进行了扩展,并输出了扩展后的边界框坐标。 需要注意的是,VTK还提供了其他更高级的包围盒处理功能,如obbtree、kdtree等,可以根据实际需求选择适合的方法进行曲面的包围盒处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值