《PCL点云库学习&VS2010(X64)》Part 10 PCL1.72(VTK6.2.0)选点操作
2016-06-21 20:31
465 查看
Part 10 PCL1.72(VTK6.2.0)选点操作
1、单点选取程序:
cpp:
编译运行:
注:使用shift键配合鼠标选点。
2、区域选点
编译运行:
注:使用x键配合鼠标左键选择区域,同时再按下x取消框选。
3、单点选择:
程序中对所以的鼠标点都会罗列在控制台中,和第一个有点差异
cpp:
*4、选点程序,没有标出点,注意,要输入三个数才能进行操作,如1 1 1,按C键可以显示信息
cpp:
5、整合到Qt+VTK的界面中的技巧:
参看博文
http://blog.csdn.net/hopedengxiwang/article/details/6940719,
http://stackoverflow.com/questions/14267895/error-with-callback-function?answertab=active#tab-top,
http://stackoverflow.com/questions/9596276/how-to-explain-callbacks-in-plain-english-how-are-they-different-from-calling-o:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
如何在类中封装回调函数(第一个链接)
我们知道回调函数只能是全局的或是静态的。
全局函数会破坏类的封装性,故不予采用。
而静态函数只能访问类的静态成员,不能访问类中非静态成员。
那么如何让静态函数访问类的非静态成员呢?
1).声明一静态函数a(),将类实例对象指针做为参数传入。如:
class A()
{
static void a(A *); //静态函数
void b(); //非静态函数
}
void A::a(A * pThis)
{
pThis->b(); //静态函数中调用非静态函数
}
2).回调函数中访问非静态成员
由于回调函数往往有固定定义,并不接受 A * pThis 参数
如:CALLBACK MyTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime);
【解决方案1】:本方案当遇到有多个类实例对象时会有问题。原因是pThis指针只能指向一个对象。
class A()
{
static void a(); //静态回调函数
void b(); //非静态函数
static A * pThis; //静态对象指针
}
A * A::pThis=NULL;
A::A() //构造函数中将this指针赋给pThis,使得回调函数能通过pThis指针访问本对象
{
pThis=this;
}
void A::a()
{
if (pThis==NULL) return;
pThis->b(); //回调函数中调用非静态函数
}
【解决方案2】:本方案解决多个类实例对象时方案1的问题。用映射表存所有对象地址,每个对象保存自己的ID号。
typedef CMap<UINT,UINT,A*,A*> CAMap;
class A()
{
static void a(); //静态回调函数
void b(); //非静态函数
int m_ID; //本对象在列表中的ID号
static int m_SID; //静态当前对象ID (需要时,将m_ID赋值给m_SID以起到调用本对象函数的功能)
static CAMap m_Map; //静态对象映射表
}
CAMap A::m_Map;
int A::m_SID=0;
A::A() //构造函数中将this指针赋给pThis,使得回调函数能通过pThis指针访问本对象
{
if(m_Map.IsEmpty())
{
m_ID=1;
}
else
{
m_ID=m_Map.GetCount()+1;
}
m_Map.SetAt( m_ID, this );
}
void A::a()
{
if (m_Map.IsEmpty()) return;
A * pThis=NULL;
if(m_Map.Lookup(m_SID,pThis))
{
pThis->b(); //回调函数中调用非静态函数
};
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
参考下,仔细琢磨一下,可以实现在Qt中的选点功能。
1、单点选取程序:
cpp:
#include <pcl/io/pcd_io.h> #include <pcl/point_cloud.h> #include <pcl/point_types.h> #include <pcl/visualization/pcl_visualizer.h> typedef pcl::PointXYZRGBA PointT; typedef pcl::PointCloud<PointT> PointCloudT; // Mutex: // boost::mutex cloud_mutex; struct callback_args{ // structure used to pass arguments to the callback function PointCloudT::Ptr clicked_points_3d; pcl::visualization::PCLVisualizer::Ptr viewerPtr; }; void pp_callback(const pcl::visualization::PointPickingEvent& event, void* args) { struct callback_args* data = (struct callback_args *)args; if (event.getPointIndex() == -1) return; PointT current_point; event.getPoint(current_point.x, current_point.y, current_point.z); data->clicked_points_3d->points.push_back(current_point); // Draw clicked points in red: pcl::visualization::PointCloudColorHandlerCustom<PointT> red(data->clicked_points_3d, 255, 0, 0); data->viewerPtr->removePointCloud("clicked_points"); data->viewerPtr->addPointCloud(data->clicked_points_3d, red, "clicked_points"); data->viewerPtr->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "clicked_points"); std::cout << current_point.x << " " << current_point.y << " " << current_point.z << std::endl; } void main() { std::string filename("bunny.pcd"); //visualizer pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>()); boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("viewer")); if (pcl::io::loadPCDFile(filename, *cloud)) { std::cerr << "ERROR: Cannot open file " << filename << "! Aborting..." << std::endl; return; } std::cout << cloud->points.size() << std::endl; //viewer->addPointCloud(cloud, "bunny"); cloud_mutex.lock(); // for not overwriting the point cloud // Display pointcloud: viewer->addPointCloud(cloud, "bunny"); viewer->setCameraPosition(0, 0, -2, 0, -1, 0, 0); // Add point picking callback to viewer: struct callback_args cb_args; PointCloudT::Ptr clicked_points_3d(new PointCloudT); cb_args.clicked_points_3d = clicked_points_3d; cb_args.viewerPtr = pcl::visualization::PCLVisualizer::Ptr(viewer); viewer->registerPointPickingCallback(pp_callback, (void*)&cb_args); std::cout << "Shift+click on three floor points, then press 'Q'..." << std::endl; // Spin until 'Q' is pressed: viewer->spin(); std::cout << "done." << std::endl; cloud_mutex.unlock(); while (!viewer->wasStopped()) { viewer->spinOnce(100); boost::this_thread::sleep(boost::posix_time::microseconds(100000)); } }
编译运行:
注:使用shift键配合鼠标选点。
2、区域选点
#include <pcl/io/pcd_io.h> #include <pcl/point_cloud.h> #include <pcl/point_types.h> #include <pcl/visualization/pcl_visualizer.h> #include <iostream> #include <vector> pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>()); boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("viewer")); pcl::PointCloud<pcl::PointXYZ>::Ptr clicked_points_3d(new pcl::PointCloud<pcl::PointXYZ>); int num = 0; void pp_callback(const pcl::visualization::AreaPickingEvent& event, void* args) { std::vector< int > indices; if (event.getPointsIndices(indices)==-1) return; for (int i = 0; i < indices.size(); ++i) { clicked_points_3d->points.push_back(cloud->points.at(indices[i])); } pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> red(clicked_points_3d, 255, 0, 0); std::stringstream ss; std::string cloudName; ss << num++; ss >> cloudName; cloudName += "_cloudName"; viewer->addPointCloud(clicked_points_3d, red, cloudName); viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, cloudName); } void main() { if (pcl::io::loadPCDFile("bunny.pcd", *cloud)) { std::cerr << "ERROR: Cannot open file " << std::endl; return; } viewer->addPointCloud(cloud, "bunny"); viewer->setCameraPosition(0, 0, -2, 0, -1, 0, 0); viewer->registerAreaPickingCallback(pp_callback, (void*)&cloud); while (!viewer->wasStopped()) { viewer->spinOnce(100); boost::this_thread::sleep(boost::posix_time::microseconds(100000)); } }
编译运行:
注:使用x键配合鼠标左键选择区域,同时再按下x取消框选。
3、单点选择:
程序中对所以的鼠标点都会罗列在控制台中,和第一个有点差异
cpp:
#include <pcl/io/pcd_io.h> #include <pcl/point_cloud.h> #include <pcl/point_types.h> #include <pcl/visualization/pcl_visualizer.h> typedef pcl::PointXYZRGBA PointT_XYZ; typedef pcl::PointCloud<PointT_XYZ> PointCloudT_XYZ; // Mutex: // boost::mutex cloud_mutex; struct callback_args{ // structure used to pass arguments to the callback function PointCloudT_XYZ::Ptr clicked_points_3d; pcl::visualization::PCLVisualizer::Ptr viewerPtr; }; void pp_callback(const pcl::visualization::PointPickingEvent& event, void* args) { struct callback_args* data = (struct callback_args *)args; std::cout << "Picking event active" << std::endl; PointT_XYZ current_point; if (event.getPointIndex() != -1) { float x, y, z; event.getPoint(current_point.x, current_point.y, current_point.z); //std::cout << x << ";" << y << ";" << z << std::endl; data->clicked_points_3d->points.push_back(current_point); } // Draw clicked points in red: pcl::visualization::PointCloudColorHandlerCustom<PointT_XYZ> red(data->clicked_points_3d, 255, 0, 0); data->viewerPtr->removePointCloud("clicked_points"); data->viewerPtr->addPointCloud(data->clicked_points_3d, red, "clicked_points"); data->viewerPtr->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "clicked_points"); std::cout << current_point.x << " " << current_point.y << " " << current_point.z << std::endl; } void main() { //visualizer pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>()); boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("viewer")); pcl::io::loadPCDFile("Bunny.pcd", *cloud); //viewer->addPointCloud(cloud, "bunny"); cloud_mutex.lock(); // for not overwriting the point cloud // Display pointcloud: viewer->addPointCloud(cloud, "bunny"); // Add point picking callback to viewer: struct callback_args cb_args; PointCloudT_XYZ::Ptr clicked_points_3d(new PointCloudT_XYZ); cb_args.clicked_points_3d = clicked_points_3d; cb_args.viewerPtr = pcl::visualization::PCLVisualizer::Ptr(viewer); viewer->registerPointPickingCallback(pp_callback, (void*)&cb_args); std::cout << "Shift+click on three floor points, then press 'Q'..." << std::endl; // Spin until 'Q' is pressed: viewer->spin(); std::cout << "done." << std::endl; cloud_mutex.unlock(); while (!viewer->wasStopped()) { viewer->spinOnce(100); boost::this_thread::sleep(boost::posix_time::microseconds(100000)); } }
*4、选点程序,没有标出点,注意,要输入三个数才能进行操作,如1 1 1,按C键可以显示信息
cpp:
#include <pcl/point_cloud.h> #include <pcl/PCLPointCloud2.h> #include <pcl/io/io.h> #include <pcl/io/pcd_io.h> #include <pcl/common/io.h> #include <pcl/io/ply_io.h> #include <pcl/io/vtk_lib_io.h> #include <pcl/visualization/pcl_visualizer.h> using namespace pcl; using namespace std; class pickPoints { public: pickPoints::pickPoints() { viewer.reset(new pcl::visualization::PCLVisualizer("Viewer", true)); viewer->registerPointPickingCallback(&pickPoints::pickCallback, *this); } ~pickPoints() {} void setInputCloud(PointCloud<PointXYZ>::Ptr cloud) { cloudTemp = cloud; } vector<float> getpoints() { return p; } void simpleViewer() { // Visualizer viewer->addPointCloud<pcl::PointXYZ>(cloudTemp, "Cloud"); viewer->resetCameraViewpoint("Cloud"); viewer->spin(); } protected: void pickCallback(const pcl::visualization::PointPickingEvent& event, void*) { if (event.getPointIndex() == -1) return; PointXYZ picked_point1, picked_point2; event.getPoints(picked_point1.x, picked_point1.y, picked_point1.z, picked_point2.x, picked_point2.y, picked_point2.z); p.push_back(picked_point1.x); // store points p.push_back(picked_point1.y); p.push_back(picked_point1.z); p.push_back(picked_point2.x); p.push_back(picked_point2.y); p.push_back(picked_point2.z); //cout<<"first selected point: "<<p[0]<<" "<<p[1]<<" "<<p[2]<<endl; //cout<<"second selected point: "<<p[3]<<" "<<p[4]<<" "<<p[5]<<endl; ////pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> red(p->clicked_points_3d, 255, 0, 0); ////data->viewerPtr->removePointCloud("clicked_points"); ////data->viewerPtr->addPointCloud(data->clicked_points_3d, red, "clicked_points"); ////data->viewerPtr->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "clicked_points"); ////std::cout << current_point.x << " " << current_point.y << " " << current_point.z << std::endl; } private: // Point cloud data PointCloud<pcl::PointXYZ>::Ptr cloudTemp; // The visualizer boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer; // The picked point vector<float> p; }; int main() { //LOAD; PointCloud<PointXYZ>::Ptr cloud(new PointCloud<PointXYZ>()); pcl::PolygonMesh mesh; pcl::io::loadPCDFile("Bunny.pcd", *cloud); //pcl::fromPCLPointCloud2(mesh.cloud, *cloud); pickPoints pickViewer; pickViewer.setInputCloud(cloud); // A pointer to a cloud pickViewer.simpleViewer(); vector<float> pointSelected; pointSelected = pickViewer.getpoints(); cout << pointSelected[0] << " " << pointSelected[1] << " " << pointSelected[2] << endl; cout << pointSelected[3] << " " << pointSelected[4] << " " << pointSelected[5] << endl; cin.get(); return 0; }
5、整合到Qt+VTK的界面中的技巧:
参看博文
http://blog.csdn.net/hopedengxiwang/article/details/6940719,
http://stackoverflow.com/questions/14267895/error-with-callback-function?answertab=active#tab-top,
http://stackoverflow.com/questions/9596276/how-to-explain-callbacks-in-plain-english-how-are-they-different-from-calling-o:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
如何在类中封装回调函数(第一个链接)
我们知道回调函数只能是全局的或是静态的。
全局函数会破坏类的封装性,故不予采用。
而静态函数只能访问类的静态成员,不能访问类中非静态成员。
那么如何让静态函数访问类的非静态成员呢?
1).声明一静态函数a(),将类实例对象指针做为参数传入。如:
class A()
{
static void a(A *); //静态函数
void b(); //非静态函数
}
void A::a(A * pThis)
{
pThis->b(); //静态函数中调用非静态函数
}
2).回调函数中访问非静态成员
由于回调函数往往有固定定义,并不接受 A * pThis 参数
如:CALLBACK MyTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime);
【解决方案1】:本方案当遇到有多个类实例对象时会有问题。原因是pThis指针只能指向一个对象。
class A()
{
static void a(); //静态回调函数
void b(); //非静态函数
static A * pThis; //静态对象指针
}
A * A::pThis=NULL;
A::A() //构造函数中将this指针赋给pThis,使得回调函数能通过pThis指针访问本对象
{
pThis=this;
}
void A::a()
{
if (pThis==NULL) return;
pThis->b(); //回调函数中调用非静态函数
}
【解决方案2】:本方案解决多个类实例对象时方案1的问题。用映射表存所有对象地址,每个对象保存自己的ID号。
typedef CMap<UINT,UINT,A*,A*> CAMap;
class A()
{
static void a(); //静态回调函数
void b(); //非静态函数
int m_ID; //本对象在列表中的ID号
static int m_SID; //静态当前对象ID (需要时,将m_ID赋值给m_SID以起到调用本对象函数的功能)
static CAMap m_Map; //静态对象映射表
}
CAMap A::m_Map;
int A::m_SID=0;
A::A() //构造函数中将this指针赋给pThis,使得回调函数能通过pThis指针访问本对象
{
if(m_Map.IsEmpty())
{
m_ID=1;
}
else
{
m_ID=m_Map.GetCount()+1;
}
m_Map.SetAt( m_ID, this );
}
void A::a()
{
if (m_Map.IsEmpty()) return;
A * pThis=NULL;
if(m_Map.Lookup(m_SID,pThis))
{
pThis->b(); //回调函数中调用非静态函数
};
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
参考下,仔细琢磨一下,可以实现在Qt中的选点功能。
相关文章推荐
- LeetCode 283. Move Zeroes
- 组件底部添加阴影
- shape的使用
- div布局
- js常见坑
- HDU 2892 (平面几何 圆和多边形面积交)
- 创建Widget窗口控件
- sqli_lab
- 48. spring boot单元测试restfull API【从零开始学Spring Boot】
- code1074 食物链
- 软件测试工程师必须要知道的9点
- javascript的Mixins
- PAT(乙级)1001. 害死人不偿命的(3n+1)猜想
- 【JS】DOM与BOM
- 解决linux命令行使用不了的情况
- ``` > **c#学习(一)** ```
- 上传jar包到私服(仅限于翼支付公司工作流程使用)和涉及的技术总结
- 【MySQL】笔记
- 如何将App从一个账号迁移到另一个账号?
- 创建快捷方式