列出空间中的圆面上的点

列出空间中的圆面上的点

问题: 在一个世界坐标系中,已知空间一圆面区域的圆心位置和法向量,求该圆面上的点在世界坐标系下的表示,点集合。

思路:
1、先以世界坐标系原点为圆的圆心,根据给定的圆半径在x-o-y平面上将圆面上的点都写出来,一个点集合(齐次坐标的表示形式!!!),为了后面坐标点的空间变换计算。
2、根据空间中圆心坐标和法向量,求出齐次旋转变换矩阵,将原点处的点集的店经过齐次变换得到空间中的点集。

具体实现:

  • 第一个的问题描述类似这个连接力说的。【算法】大量格点数中给定一个点,画半径为R的圆,得到圆中各个格点的坐标
    关于这个有两个想法:
    1、以x y,从圆的最小到最大边界,循环把圆上的点加入到点集合中。ps:我取点都取整数点

    % matlab实现
    function pointset = circle_regionfill(r)
        x = [];
        y = [];
        for i = -r:0.1:r
            value = sqrt(r^2-i^2);
            value = round(value);
            for j = -value:1:value
               x = [x j];
               y = [y i];
            end
        end
        point_size = size(x,2);
        z = zeros(1,point_size);
        m = ones(1,point_size);
        pointset = zeros(point_size,4);
        pointset(:,1) = x';
        pointset(:,2) = y';
        pointset(:,3) = z';
        pointset(:,4) = m';
    end
    

    2、另外一个想根据平面上任意的点距离圆心小于等于半径的点在圆内和圆上,其他的不在的去掉。所以确定一个以该圆为内接圆的正方形区域,遍历每个点并把不在圆内的点去除。,但是这段写的太乱了,Eigen事先不确定数组大小,虽然有什么动态的,也是必须在执行时候给定row col,我现在感觉这种是不是用 列表啥的好些。还有移除某行的方法,先记在这儿 Eigen学习——Eigen Matrix删除矩阵某一行或某一列

    // eigen_test.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <iostream>
    #include <Eigen\Dense>
    
    using namespace std;
    using namespace Eigen;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	double r;
    	r = 2.5;
    	//向下取整,要整数点
    	r = floor(r);
    	//圆外接正方形共有几个点
    	int row;
    	row = pow((r * 2 + 1), 2);
    	//定义点集,行表示共有几个点,列是x y坐标
    	MatrixXd posset_square(row, 2);
    	//把圆外接正方形的点赋值到矩阵中
    	int k;
    	k = 0;
    	for (int i = -r; i < r+1; i++)
    	{
    		for (int j = -r; j < r+1; j++)
    		{
    			posset_square(k, 0) = i;
    			posset_square(k, 1) = j;
    			k++;
    		}
    	}
    	cout << posset_square << endl;
    	cout << "\n" << endl;
    	//依次判断属于圆内的点存入新矩阵
    	Matrix<double, Dynamic, 2> posset_circle;
    	/*posset_circle = MatrixXd::Zero(1, 2);*/
    	int m;
    	m = 0;
    	for (int i = 0; i < posset_square.rows(); i++)
    	{
    		double distance = sqrt(pow(posset_square(i, 0), 2) + pow(posset_square(i, 1), 2));
    		if (distance <= r)
    		{
    			posset_circle.conservativeResize(m+1, 2);  //一定注意这样调用这个改变矩阵大小的函数,Resize()函数会使原来数据丢失。
    			posset_circle(m, 0) = posset_square(i, 0);
    			//cout << posset_square(i, 0);
    			posset_circle(m, 1) = posset_square(i, 1);
    			//cout << posset_square(i, 1);
    			m++;
    		}
    	}
    	MatrixXd posset3, posset4;
    	posset3 = MatrixXd::Zero(posset_circle.rows(), 1);
    	posset4 = MatrixXd::Constant(posset_circle.rows(), 1, 1);
    	MatrixXd mat(posset_circle.rows(),4);   //N行4列的齐次坐标点集,N代表共有多少个点
    	mat << posset_circle, posset3, posset4;
    
    	cout << posset_circle << endl;
    	cout << mat << endl;
    	system("pause");
    
    }	
    

上面多个矩阵分快赋值参考

  • 第二个问题,首先计算中间的齐次变换矩阵。

现在已知空间中的两个点,O1和O2,根据其组成的向量V2,和世界坐标系Z轴方向的向量V1,求空间平面坐标系和世界坐标系的齐次变换矩阵。
在这里插入图片描述
首先需要了解刚体空间变换的一些知识和实现方法。如一些介绍链接里说的,对于刚体空间变换的描述有(欧拉角、旋转变换矩阵、轴-角、四元数等方式可以表示)。
我们需要求出以空间中圆心为原点,圆面法向为Z轴方向的坐标系和世界坐标系的齐次旋转变换矩阵4X4。(旋转矩阵3X3加平移的值拓展可得到齐次旋转变换矩阵)
方法:

  • 求出两坐标系的轴-角表示(空间刚体的任意变换可以看成初始刚体绕空间一轴旋转theta角):
    空间两个向量V1,和V2 点乘可求旋转角 叉乘可求空间旋转轴。
  • 根据已知的轴-角,由旋转变换通式(),写成齐次不安换矩阵的形式。
#include "stdafx.h"
#include <iostream>
#include <Eigen\Dense>

#include <vtkAutoInit.h>
//定义几个宏
VTK_MODULE_INIT(vtkRenderingOpenGL)
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);

#include <vtkSmartPointer.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkInteractorStyleTrackballCamera.h>

#include <vtkVertexGlyphFilter.h>
#include <vtkElevationFilter.h>


using namespace std;
using namespace Eigen;

int _tmain(int argc, _TCHAR* argv[])
{
	double r;
	r = 19.5;
	//向下取整,要整数点
	r = floor(r);
	//圆外接正方形共有几个点
	int row;
	row = pow((r * 2 + 1), 2);
	//定义点集,行表示共有几个点,列是x y坐标
	MatrixXd posset_square(row, 2);
	//把圆外接正方形的点赋值到矩阵中
	int k;
	k = 0;
	for (int i = -r; i < r+1; i++)
	{
		for (int j = -r; j < r+1; j++)
		{
			posset_square(k, 0) = i;
			posset_square(k, 1) = j;
			k++;
		}
	}
	//cout << posset_square << endl;
	//cout << "\n" << endl;
	//依次判断属于圆内的点存入新矩阵
	Matrix<double, Dynamic, 2> posset_circle;
	posset_circle = MatrixXd::Zero(1, 2);
	int m;
	m = 0;
	for (int i = 0; i < posset_square.rows(); i++)
	{
		double distance = sqrt(pow(posset_square(i, 0), 2) + pow(posset_square(i, 1), 2));
		if (distance <= r)
		{
			posset_circle.conservativeResize(m+1, 2);
			posset_circle(m, 0) = posset_square(i, 0);
			//cout << posset_square(i, 0);
			posset_circle(m, 1) = posset_square(i, 1);
			//cout << posset_square(i, 1);
			m++;
		}
	}
	MatrixXd posset3, posset4;
	posset3 = MatrixXd::Zero(posset_circle.rows(), 1);
	posset4 = MatrixXd::Constant(posset_circle.rows(), 1, 1);
	MatrixXd mat(posset_circle.rows(),4);   //N行4列的齐次坐标点集,N代表共有多少个点
	mat << posset_circle, posset3, posset4;

	//cout << posset_circle << endl;
	//cout << mat << endl;

	//求齐次变换矩阵

	//两个点坐标定义
	Vector3d o1, o2;
	o1 << 120, 200, 85;
	o2 << 185, 260, 85;
	//两个向量定义
	Vector3d v1, v2, v;
	v1 << 0, 0, 1;
	v2 = o2 - o1;
	/*cout << v2 << endl;*/
	v2.normalize(); //向量归一化
	/*cout << v2 << endl;*/

	//通过向量点乘获得两向量夹角
	double cos_theta, theta; 
	cos_theta = (v1.dot(v2) / (v1.norm()*v2.norm()));
	theta = acos(cos_theta);
	//通过向量叉乘获得变换绕的空间轴的向量表示
	v = v1.cross(v2);
	v.normalize();
	
	//根据轴角和旋转变换通式写出坐标变换矩阵
	MatrixXd T(4, 4);
	double Vers;
	Vers = 1 - cos(theta);
	T << v(0)*v(0)*Vers + cos(theta), v(1)*v(0)*Vers - v(2)*sin(theta), v(2)*v(0)*Vers + v(1)*sin(theta), o1(0),
		 v(0)*v(1)*Vers + v(2)*sin(theta), v(1)*v(1)*Vers + cos(theta), v(2)*v(1)*Vers - v(0)*sin(theta), o1(1),
		 v(0)*v(2)*Vers - v(1)*sin(theta), v(1)*v(2)*Vers + v(0)*sin(theta), v(2)*v(2)*Vers + cos(theta), o1(2),
		 0, 0, 0, 1;
	//cout << T << endl;

	MatrixXd posset_tran(mat.rows(),mat.cols());
	posset_tran = T*mat.transpose();
	/*cout << posset_tran << endl;*/
	//利用VTK显示看看
	vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
	for (int i = 0; i < mat.rows(); i++)
	{
		points->InsertNextPoint(posset_tran(0, i), posset_tran(1, i), posset_tran(2, i));
		points->InsertNextPoint(mat(i, 0), mat(i, 1), mat(i, 2));
	}
	vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
	polydata->SetPoints(points);
	vtkSmartPointer<vtkVertexGlyphFilter> glyphFilter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
	glyphFilter->SetInputData(polydata);
	glyphFilter->Update();

	//vtkElevationFilter *elevationFilter = vtkElevationFilter::New();
	//elevationFilter->SetInputConnection(glyphFilter->GetOutputPort());
	//elevationFilter->SetLowPoint(0, 0, low_z);
	//elevationFilter->SetHighPoint(0, 0, high_z);

	vtkSmartPointer<vtkPolyDataMapper> mapper =	vtkSmartPointer<vtkPolyDataMapper>::New();
	mapper->SetInputConnection(glyphFilter->GetOutputPort());

	vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
	actor->SetMapper(mapper);

	vtkSmartPointer<vtkRenderer> renderer =	vtkSmartPointer<vtkRenderer>::New();
	renderer->AddActor(actor);
	renderer->SetBackground(.3, .6, .3);

	vtkSmartPointer<vtkRenderWindow> renderWindow =	vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);

	vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();

	vtkSmartPointer<vtkRenderWindowInteractor> renderwindIt = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderwindIt->SetRenderWindow(renderWindow);
	renderwindIt->SetInteractorStyle(style);

	renderWindow->Render();
	renderwindIt->Start();

	system("pause");

}

显示:
VTK根据三维坐标点集生成点云
vtk实战(九)—读取三维点坐标2

显示的程序也在上面那块儿了。

在这里插入图片描述

发布了14 篇原创文章 · 获赞 2 · 访问量 671

猜你喜欢

转载自blog.csdn.net/weixin_42040046/article/details/103292905