生活中处处面临着狗血的选择,如果你是个很吸引人的青年,你会发现身边有很多选择,但做出选择往往是很难的。
而且大家有时候只能看,不能选,因为不会选,选错了你就完蛋了。
如果这时候你会选了,选对了,就不用一个人过节了。
好,那么今天讲一下究竟怎么选,怎么选才能得到你想要的。
(大家准备好鸡蛋)
其实点云的选择问题并不难。
只是大家有时候没有好好钻。
笔者基于QGLVewer简单做了一下点云的读取、显示、还有框选。(别扔脸,哎...哎...)
那么工程的代码采用的是QtainRibbon风格的QT界面,也是非常给力的。所有代码分享到置顶博客的网盘中了。大家自行去下载即可,名字叫NinRibbonCloud。我就不往CSDN上弄了,太麻烦了,还收你积分,有空我会好好研究GitHub的用法。。。。
https://me.csdn.net/qq_30547073 博客在这里。
废话不多说。
首先我们会看到QGLVewer的官方例子里面,有一个MultSelect,它在上面那个图里面。对,这就是原始的例子。我们要改成自己想要的。
首先是object。主要绘制就绘制这个object,右边两行注释是原有的,我改成绘制点云了。
constrant 是用来约束相机的类,由于我们选完了之后还要让选择后的点云发生变化,比如说旋转,那么我们就用这个来控制。
这张图片刚好能装下所有的代码。
那么重头戏还是在如何调用上。
新建一个类,继承自QGLVewer
#pragma once
#include "QGLViewer/qglviewer.h"
#include "object.h"
#include"../ExampleBase.h"
#include"MasterHeader.h"
class Example_MultiSelectViewer : public QGLViewer, public ExampleBase
{
public:
Example_MultiSelectViewer(QMainWindow *parent = 0);
void do_ClearSet();//清除所有当前的物体咯
void do_ReloadSet();//重新加载所有当前物体咯
void do_LoadCloud(VertexPositionColor* Cloudptr, int num);
protected:
virtual void draw();
virtual void init();
virtual QString helpString() const;
// Selection functions
virtual void drawWithNames();
virtual void endSelection(const QPoint &);
// Mouse events functions
virtual void mousePressEvent(QMouseEvent *e);
virtual void mouseMoveEvent(QMouseEvent *e);
virtual void mouseReleaseEvent(QMouseEvent *e);
virtual void TriggerOn() override;//=========继承的====
private:
void startManipulation();
void drawSelectionRectangle() const;
void addIdToSelection(int id);
void removeIdFromSelection(int id);
// Current rectangular selection
QRect rectangle_;
// Different selection modes
enum SelectionMode { NONE, ADD, REMOVE };
SelectionMode selectionMode_;
QList
QList
};
然后是相应的CPP:
整个的代码大致的流程是,上来构造函数初始化的时加载了所有的Object,就是绘制出来的那些小球。然后当你按住Shift的时候,就会启用selectmode = true;这时候拖动鼠标就会绘制出一个框框来。然后当你松手的时候就会调用mouseRelease以及select函数。所选择的东西的Index全部保存在私有的QList中。然后代码内将所有selectList中的点绘制成另一种颜色。也是很有趣的。
不过这样写的缺点是,加载的点过多的时候就会很卡,想必是因为调用了过多次glBegin的问题。这一点应该是可以修改的。我们在最后还放了几个结果。
/****************************************************************************
#include "Example_multiSelect.h"
#include "manipulatedFrameSetConstraint.h"
#include
#include
using namespace qglviewer;
Example_MultiSelectViewer::Example_MultiSelectViewer(QMainWindow *parent) :ExampleBase(parent)
{
do_ReloadSet();
}
//确认不会报错
void Example_MultiSelectViewer::do_ClearSet()
{
selectionMode_ = NONE;
objects_.clear();
selection_.clear();
update();
}
void Example_MultiSelectViewer::do_ReloadSet()
{
do_ClearSet();
selectionMode_ = NONE;
// Fill the scene with objects positionned on a regular grid.
// Consider increasing selectBufferSize() if you use more objects.
const int nb = 10;
for (int i = -nb; i <= nb; ++i)
{
for (int j = -nb; j <= nb; ++j)
{
Object *o = new Object();
o->frame.setPosition(Vec(i / float(nb), j / float(nb), 0.0));
objects_.append(o);
}
}
update();
}
void Example_MultiSelectViewer::do_LoadCloud(VertexPositionColor* Cloudptr, int num)
{
do_ClearSet();
setSelectBufferSize(num);
selectionMode_ = NONE;
for (int i = 0; i < num; i++)
{
if (i % 20 != 0)continue;
VertexPositionColor pt = Cloudptr[i];
Object *o = new Object();
o->frame.setPosition(Vec(pt.x, pt.y, pt.z));
objects_.append(o);
}
/*camera()->setPosition(qglviewer::Vec(5, 5, 5));
camera()->lookAt(qglviewer::Vec(0, 0, 0));*/
update();
}
void Example_MultiSelectViewer::init()
{
// A ManipulatedFrameSetConstraint will apply displacements to the selection
setManipulatedFrame(new qglviewer::ManipulatedFrame());
manipulatedFrame()->setConstraint(new ManipulatedFrameSetConstraint());
// Used to display semi-transparent relection rectangle
glBlendFunc(GL_ONE, GL_ONE);
restoreStateFromFile();
// help();
}
void Example_MultiSelectViewer::draw() {
// Draws selected objects only.
glColor3f(0.9f, 0.3f, 0.3f);
for (QList
end = selection_.end();
it != end; ++it)
objects_.at(*it)->draw();
// Draws all the objects. Selected ones are not repainted because of GL depth
// test.
glColor3f(0.8f, 0.8f, 0.8f);
for (int i = 0; i < int(objects_.size()); i++)
objects_.at(i)->draw();
// Draws manipulatedFrame (the set's rotation center)
if (manipulatedFrame()->isManipulated()) {
glPushMatrix();
glMultMatrixd(manipulatedFrame()->matrix());
drawAxis(0.5);
glPopMatrix();
}
// Draws rectangular selection area. Could be done in postDraw() instead.
if (selectionMode_ != NONE)
drawSelectionRectangle();
}
void Example_MultiSelectViewer::mousePressEvent(QMouseEvent *e) {
// Start selection. Mode is ADD with Shift key and TOGGLE with Alt key.
rectangle_ = QRect(e->pos(), e->pos());
if ((e->button() == Qt::LeftButton) && (e->modifiers() == Qt::ShiftModifier))
selectionMode_ = ADD;
else if ((e->button() == Qt::LeftButton) &&
(e->modifiers() == Qt::AltModifier))
selectionMode_ = REMOVE;
else
{
if (e->modifiers() == Qt::ControlModifier)
startManipulation();
QGLViewer::mousePressEvent(e);
}
}
void Example_MultiSelectViewer::mouseMoveEvent(QMouseEvent *e) {
if (selectionMode_ != NONE)
{
// Updates rectangle_ coordinates and redraws rectangle
rectangle_.setBottomRight(e->pos());
update();
}
else
QGLViewer::mouseMoveEvent(e);
}
void Example_MultiSelectViewer::mouseReleaseEvent(QMouseEvent *e) {
if (selectionMode_ != NONE) {
// Actual selection on the rectangular area.
// Possibly swap left/right and top/bottom to make rectangle_ valid.
rectangle_ = rectangle_.normalized();
// Define selection window dimensions
setSelectRegionWidth(rectangle_.width());
setSelectRegionHeight(rectangle_.height());
// Compute rectangle center and perform selection
select(rectangle_.center());
// Update display to show new selected objects
update();
} else
QGLViewer::mouseReleaseEvent(e);
}
void Example_MultiSelectViewer::drawWithNames() {
for (int i = 0; i < int(objects_.size()); i++) {
glPushName(i);
objects_.at(i)->draw();
glPopName();
}
}
void Example_MultiSelectViewer::endSelection(const QPoint &) {
// Flush GL buffers
glFlush();
// Get the number of objects that were seen through the pick matrix frustum.
// Reset GL_RENDER mode.
GLint nbHits = glRenderMode(GL_RENDER);
if (nbHits > 0) {
// Interpret results : each object created 4 values in the selectBuffer().
// (selectBuffer())[4*i+3] is the id pushed on the stack.
for (int i = 0; i < nbHits; ++i)
switch (selectionMode_) {
case ADD:
addIdToSelection((selectBuffer())[4 * i + 3]);
break;
case REMOVE:
removeIdFromSelection((selectBuffer())[4 * i + 3]);
break;
default:
break;
}
}
selectionMode_ = NONE;
}
void Example_MultiSelectViewer::startManipulation() {
Vec averagePosition;
ManipulatedFrameSetConstraint *mfsc =
(ManipulatedFrameSetConstraint *)(manipulatedFrame()->constraint());
mfsc->clearSet();
for (QList
end = selection_.end();
it != end; ++it) {
mfsc->addObjectToSet(objects_[*it]);
averagePosition += objects_[*it]->frame.position();
}
if (selection_.size() > 0)
manipulatedFrame()->setPosition(averagePosition / selection_.size());
}
// S e l e c t i o n t o o l s
void Example_MultiSelectViewer::addIdToSelection(int id) {
if (!selection_.contains(id))
selection_.push_back(id);
}
void Example_MultiSelectViewer::removeIdFromSelection(int id) { selection_.removeAll(id); }
void Example_MultiSelectViewer::drawSelectionRectangle() const {
startScreenCoordinatesSystem();
glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
glColor4f(0.0, 0.0, 0.3f, 0.3f);
glBegin(GL_QUADS);
glVertex2i(rectangle_.left(), rectangle_.top());
glVertex2i(rectangle_.right(), rectangle_.top());
glVertex2i(rectangle_.right(), rectangle_.bottom());
glVertex2i(rectangle_.left(), rectangle_.bottom());
glEnd();
glLineWidth(2.0);
glColor4f(0.4f, 0.4f, 0.5f, 0.5f);
glBegin(GL_LINE_LOOP);
glVertex2i(rectangle_.left(), rectangle_.top());
glVertex2i(rectangle_.right(), rectangle_.top());
glVertex2i(rectangle_.right(), rectangle_.bottom());
glVertex2i(rectangle_.left(), rectangle_.bottom());
glEnd();
glDisable(GL_BLEND);
glEnable(GL_LIGHTING);
stopScreenCoordinatesSystem();
}
void Example_MultiSelectViewer::TriggerOn()//=========继承的====
{
if (m_patrentWin != 0)
{
m_patrentWin->setCentralWidget(this);
}
}
没错,启动软件的时候首先Logo必须要帅!!
读取点云,不用说了,然后兔子进来,我们按住shift框选。
这样我们选择了兔子的屁股之后,拉开一段距离,兔子就被分开了。