官方网站:https://www.roboticslibrary.org/
参考指南:https://www.roboticslibrary.org/tutorials/
rlPlanDemo文件夹
1、ConfigurationDelegate.cpp
//
// Copyright (c) 2009, Markus Rickert
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#include <QDoubleSpinBox>
#include <QModelIndex>
#include "ConfigurationDelegate.h"
#include "MainWindow.h"
ConfigurationDelegate::ConfigurationDelegate(QObject* parent) :
QItemDelegate(parent)
{
}
ConfigurationDelegate::~ConfigurationDelegate()
{
}
QWidget*
ConfigurationDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QDoubleSpinBox* editor = new QDoubleSpinBox(parent);
rl::math::Vector maximum = MainWindow::instance()->model->getMaximum();
rl::math::Vector minimum = MainWindow::instance()->model->getMinimum();
Eigen::Matrix<rl::math::Unit, Eigen::Dynamic, 1> qUnits = MainWindow::instance()->model->getPositionUnits();
if (rl::math::UNIT_RADIAN == qUnits(index.row()))
{
editor->setDecimals(2);
editor->setMinimum(minimum(index.row()) * rl::math::RAD2DEG);
editor->setMaximum(maximum(index.row()) * rl::math::RAD2DEG);
editor->setSingleStep(1.0f);
}
else
{
editor->setDecimals(4);
editor->setMinimum(minimum(index.row()));
editor->setMaximum(maximum(index.row()));
editor->setSingleStep(0.01f);
}
QObject::connect(editor, SIGNAL(valueChanged(double)), this, SLOT(valueChanged(double)));
return editor;
}
void
ConfigurationDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
QDoubleSpinBox* doubleSpinBox = static_cast<QDoubleSpinBox*>(editor);
doubleSpinBox->setValue(index.model()->data(index, Qt::EditRole).toDouble());
}
void
ConfigurationDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
QDoubleSpinBox* doubleSpinBox = static_cast<QDoubleSpinBox*>(editor);
doubleSpinBox->interpretText();
model->setData(index, doubleSpinBox->value(), Qt::EditRole);
}
void
ConfigurationDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
editor->setGeometry(option.rect);
}
void
ConfigurationDelegate::valueChanged(double d)
{
emit commitData(static_cast<QWidget*>(QObject::sender()));
}
头文件
系统头文件
include<> : 编译器直接从系统类库目录里查找头文件
- QDoubleSpinBox 浮点计数器控件
- QModelIndex 模型索引
建立起Data中数据的索引与View中数据的索引的映射关系。QModelIndex详解参考
自定义头文件
include “” : 默认从项目当前目录查找头文件,所谓项目当前目录,就是项目工程文件(*.vcxproj) 所在的目录
- ConfigurationDelegate.h
委托是Qt中的一种机制,委托提供了一种方便的方法来定制特定类型的数据的显示和编辑。委托可以用来定制Qt中各种视图组件中特定类型的数据的显示和编辑,使得开发人员能够更好地控制数据的外观和行为。使用委托可以使代码更具可重用性和灵活性。
Qt中的委托资料参考 - MainWindow.h
C++
C++中双冒号::
- 类作用域
- 命名空间作用域
- 全局作用域
C++中函数前~
取反的意思——析构函数
析构函数与构造函数相反:
当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。
C++语言:析构函数名也应与类名相同,只是在函数名前面加一个位取反符~,以区别于构造函数。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重载。如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数,它也不进行任何操作。所以许多简单的类中没有用显示的析构函数。
类和对象
QObject *parent、QWidget *parent
QObject *parent/QWidget *parent,当指定了parent后,Qt就会介入,在合适的时候调用对应的delete操作
Qt析构机制参考
QItemDelegate
Qt使用model/view 模式,一般来讲, model是数据,view把数据展示给用户,数据与界面的交互则通过delegagte来执行。
QItemDelegate类为模型中的数据项提供了显示和编辑的工具,从中派生创建自定义委托代理类。
函数
自定义委托函数
- createEditor函数:创建委托控件。可编辑输入
- setEditorData 函数:设置控件数据
QDoubleSpinBox:浮点计数器控件,接收输入的浮点数值
QDoubleSpinBox常用方法 - setModelData 函数:用户完成输入后,将数据储存到模型中
获取编辑的内容-设置到模型数据 - updateEditorGeometry函数:调整编辑器的位置和大小
更新控件位置大小 - valueChanged函数:当前值发生了改变,发射该信号
rl API(应用程序接口)
机器人库:
主要机器人领域的所有重要算法,包括运动学、动力学、轨迹生成和路径规划,都是可用的,并使用相同的符号和接口。
rl::math::Vector 正向运动学
2、ConfigurationModel.cpp
//
// Copyright (c) 2009, Markus Rickert
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#include "ConfigurationModel.h"
#include "MainWindow.h"
#include "Thread.h"
#include "Viewer.h"
ConfigurationModel::ConfigurationModel(QObject* parent) :
QAbstractTableModel(parent)
{
}
ConfigurationModel::~ConfigurationModel()
{
}
int
ConfigurationModel::columnCount(const QModelIndex& parent) const
{
return 1;
}
QVariant
ConfigurationModel::data(const QModelIndex& index, int role) const
{
if (nullptr == MainWindow::instance()->model)
{
return QVariant();
}
if (!index.isValid())
{
return QVariant();
}
switch (role)
{
case Qt::DisplayRole:
case Qt::EditRole:
{
Eigen::Matrix<rl::math::Unit, Eigen::Dynamic, 1> qUnits = MainWindow::instance()->model->getPositionUnits();
if (rl::math::UNIT_RADIAN == qUnits(index.row()))
{
return (*MainWindow::instance()->q)(index.row()) * rl::math::RAD2DEG;
}
else
{
return (*MainWindow::instance()->q)(index.row());
}
}
case Qt::TextAlignmentRole:
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
break;
default:
break;
}
return QVariant();
}
Qt::ItemFlags
ConfigurationModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
{
return Qt::NoItemFlags;
}
return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
}
QVariant
ConfigurationModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (Qt::DisplayRole == role && Qt::Vertical == orientation)
{
return QString::number(section);
}
return QVariant();
}
void
ConfigurationModel::invalidate()
{
this->beginResetModel();
this->endResetModel();
}
int
ConfigurationModel::rowCount(const QModelIndex& parent) const
{
if (nullptr == MainWindow::instance()->model)
{
return 0;
}
return MainWindow::instance()->model->getDofPosition();
}
bool
ConfigurationModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (nullptr == MainWindow::instance()->model)
{
return false;
}
if (MainWindow::instance()->thread->isRunning())
{
return false;
}
if (index.isValid() && Qt::EditRole == role)
{
Eigen::Matrix<rl::math::Unit, Eigen::Dynamic, 1> qUnits = MainWindow::instance()->model->getPositionUnits();
if (rl::math::UNIT_RADIAN == qUnits(index.row()))
{
(*MainWindow::instance()->q)(index.row()) = value.value<rl::math::Real>() * rl::math::DEG2RAD;
}
else
{
(*MainWindow::instance()->q)(index.row()) = value.value<rl::math::Real>();
}
MainWindow::instance()->viewer->drawConfiguration(*MainWindow::instance()->q);
emit dataChanged(index, index);
return true;
}
return false;
}
Model/View结构原理
Model/View结构原理参考1
Model/View结构原理参考2
实际数据Data与界面组件View之间通过Model通信,Model为视图组件提供数据接口——从原始数据Data中提取需要的部分在视图组件中显示和编辑。
Delegate委托代理功能使得用户可以编辑内容和定制界面。
Model类:定义了模型访问接口。负责访问数据集中的数据项;
Delegate类:负责视图中每个数据项的绘制与编辑;
View类:负责绘制总体外观并处理用户的交互命令。
QAbstractTableModel
QAbstractTableModel接口需要被继承后实现相关的函数后使用,将数据用二维表格显示:
C++
nullptr
指针空值
函数
三大接口
- int columnCount 表格列数
- int rowCount 表格行数
- QVariant data 根据模型索引当前数据 【最主要的】
columnCount()
获取列数:直接返回1。
注:固定的数据列表,而非动态加载的,需要调用 insertRows()、removeRows()、insertColumns() 和 removeColumns() 实现视图大小的调整。
data()
获取单元格数据。
两个参数:
1.QModelIndex 模型索引 :模型检索或修改数据,唯一确定一个数据项
2. role 角色
此处包含
- DisplayRole 显示
- EditRole 编辑
- TextAlignmentRole 对齐方式(右对齐/中心对齐)
用switch变换角色,然后返回任意类型的数据。
flag()
此处flag()函数只需要表达可编辑:单元格支持编辑操作,返回编辑后的数据。
headerData()
获取表头信息:
- Section 位置(行/列数)
- Orientation 方向(水平/垂直)
- Role
此处返回列表头信息。
invalidate()
刷新view:修改view的显示后调用invalidate()函数才能重新看到绘制的界面。
必须在UI线程中工作。
rowCount()
此处返回实际的行数。
setData()
可编辑的模型必须重写setData()函数。
dataChanged()信号
3、ConfigurationSpaceModel.cpp
向量空间模型
//
// Copyright (c) 2009, Markus Rickert
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#include "ConfigurationSpaceModel.h"
#include "ConfigurationSpaceScene.h"
#include "MainWindow.h"
#include "Thread.h"
#include "Viewer.h"
ConfigurationSpaceModel::ConfigurationSpaceModel(QObject* parent) :
QAbstractTableModel(parent),
configurationSpaceScene(nullptr)
{
}
ConfigurationSpaceModel::~ConfigurationSpaceModel()
{
}
int
ConfigurationSpaceModel::columnCount(const QModelIndex& parent) const
{
return 1;
}
QVariant
ConfigurationSpaceModel::data(const QModelIndex& index, int role) const
{
if (nullptr == this->configurationSpaceScene)
{
return QVariant();
}
if (nullptr == this->configurationSpaceScene->model)
{
return QVariant();
}
if (!index.isValid())
{
return QVariant();
}
switch (role)
{
case Qt::DisplayRole:
case Qt::EditRole:
switch (index.row())
{
case 0:
return static_cast<unsigned int>(this->configurationSpaceScene->axis0);
break;
case 1:
return static_cast<unsigned int>(this->configurationSpaceScene->axis1);
break;
case 2:
return this->configurationSpaceScene->delta0;
break;
case 3:
return this->configurationSpaceScene->delta1;
break;
default:
break;
}
break;
case Qt::TextAlignmentRole:
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
break;
default:
break;
}
return QVariant();
}
Qt::ItemFlags
ConfigurationSpaceModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
{
return Qt::NoItemFlags;
}
return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
}
QVariant
ConfigurationSpaceModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (nullptr == this->configurationSpaceScene)
{
return QVariant();
}
if (nullptr == this->configurationSpaceScene->model)
{
return QVariant();
}
if (Qt::DisplayRole == role && Qt::Vertical == orientation)
{
switch (section)
{
case 0:
return "axis0";
break;
case 1:
return "axis1";
break;
case 2:
return "delta0";
break;
case 3:
return "delta1";
break;
default:
break;
}
}
return QVariant();
}
void
ConfigurationSpaceModel::invalidate()
{
this->beginResetModel();
this->endResetModel();
}
int
ConfigurationSpaceModel::rowCount(const QModelIndex& parent) const
{
if (nullptr == this->configurationSpaceScene)
{
return 0;
}
if (nullptr == this->configurationSpaceScene->model)
{
return 0;
}
return 4;
}
bool
ConfigurationSpaceModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (nullptr == this->configurationSpaceScene)
{
return false;
}
if (nullptr == this->configurationSpaceScene->model)
{
return false;
}
if (MainWindow::instance()->thread->isRunning())
{
return false;
}
if (index.isValid() && Qt::EditRole == role)
{
switch (index.row())
{
case 0:
if (value.value<std::size_t>() < this->configurationSpaceScene->model->getDofPosition())
{
this->configurationSpaceScene->axis0 = value.value<std::size_t>();
}
else
{
return false;
}
break;
case 1:
if (value.value<std::size_t>() < this->configurationSpaceScene->model->getDofPosition())
{
this->configurationSpaceScene->axis1 = value.value<std::size_t>();
}
else
{
return false;
}
break;
case 2:
if (value.value<rl::math::Real>() > 0)
{
this->configurationSpaceScene->delta0 = value.value<rl::math::Real>();
}
else
{
return false;
}
break;
case 3:
if (value.value<rl::math::Real>() > 0)
{
this->configurationSpaceScene->delta1 = value.value<rl::math::Real>();
}
else
{
return false;
}
break;
default:
break;
}
this->configurationSpaceScene->init();
emit dataChanged(index, index);
return true;
}
return false;
}
C++
static_cast
static_cast为强制类型转换,具体形式为:
staic_cast<new_type>(expresstion)
注:static_cast不能将const类型进行转化(const_cast可以)
axis
方向:
axis=0时,表示纵轴,方向从上到下;
axis=1时,表示横轴,方向从左到右。
delta
δ函数也可以理解为(任意阶可微)函数序列的极限。
函数
columnCount()
返回1列
data()
可编辑数据时,根据这4行表头信息进行检索
flags()
单元格可编辑
headerData()
section标识第几行或者第几列,此处自定义表头:
在四行的表头分别返回"axis0"、“axis1”、“delta0”、“delta1”
invalidate()
刷新view,线程中进行
rowCount()
4行
setData()
根据实际的真实输入数据确定
4、ConfigurationDelegate.h
#ifndef CONFIGURATIONDELEGATE_H
#define CONFIGURATIONDELEGATE_H
#include <QItemDelegate>
class ConfigurationDelegate : public QItemDelegate
{
Q_OBJECT
public:
ConfigurationDelegate(QObject* parent = nullptr);
virtual ~ConfigurationDelegate();
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const;
void setEditorData(QWidget* editor, const QModelIndex& index) const;
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const;
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const;
public slots:
void valueChanged(double d);
protected:
private:
};
#endif // CONFIGURATIONDELEGATE_H
宏定义
#ifndef XX_H
#define XX_H
…
#endif
宏定义的作用
多个文件都包含同一个头文件时,容易造成编译混乱,加上ifndef/define/endif,就可以防止这种重定义错误。
虚析构函数 virtual ~
虚析构函数有无的输出区别
类的析构函数:释放内存资源
virtual的析构函数:实现多态,释放子类空间
当一个类被用作基类,把析构函数写成虚函数。
自定义委托函数
自定义委托函数同上。
5、 ConfigurationModel.h
#ifndef CONFIGURATIONMODEL_H
#define CONFIGURATIONMODEL_H
#include <QAbstractTableModel>
class ConfigurationModel : public QAbstractTableModel
{
public:
ConfigurationModel(QObject* parent = nullptr);
virtual ~ConfigurationModel();
int columnCount(const QModelIndex& parent = QModelIndex()) const;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
void invalidate();
int rowCount(const QModelIndex& parent = QModelIndex()) const;
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
protected:
private:
};
#endif // CONFIGURATIONMODEL_H
定义函数类型,函数含义见上一篇,ConfigurationSpaceModel.h同
从此处开始,先阅读.h文件,再贯穿.cpp文件,顺序改变
6、 ConfigurationSpaceScene.h
#ifndef CONFIGURATIONSPACESCENE_H
#define CONFIGURATIONSPACESCENE_H
#include <QGraphicsLineItem>
#include <QGraphicsScene>
#include <QLinkedList>
#include <rl/plan/Model.h>
#include <rl/plan/Viewer.h>
class ConfigurationSpaceThread;
class ConfigurationSpaceScene : public QGraphicsScene, public rl::plan::Viewer
{
Q_OBJECT
public:
ConfigurationSpaceScene(QObject* parent = nullptr);
virtual ~ConfigurationSpaceScene();
std::size_t axis0;
std::size_t axis1;
rl::math::Real delta0;
rl::math::Real delta1;
rl::plan::Model* model;
public slots:
void addCollision(const qreal& x, const qreal& y, const qreal& w, const qreal& h, const int& rgb);
void clear();
void drawConfiguration(const rl::math::Vector& q);
void drawConfigurationEdge(const rl::math::Vector& u, const rl::math::Vector& v, const bool& free = true);
void drawConfigurationPath(const rl::plan::VectorList& path);
void drawConfigurationVertex(const rl::math::Vector& q, const bool& free = true);
void drawLine(const rl::math::Vector& xyz0, const rl::math::Vector& xyz1);
void drawPoint(const rl::math::Vector& xyz);
void drawSphere(const rl::math::Vector& center, const rl::math::Real& radius);
void drawSweptVolume(const rl::plan::VectorList& path);
void drawWork(const rl::math::Transform& t);
void drawWorkEdge(const rl::math::Vector& u, const rl::math::Vector& v);
void drawWorkPath(const rl::plan::VectorList& path);
void drawWorkVertex(const rl::math::Vector& q);
void eval();
void init();
void reset();
void resetEdges();
void resetLines();
void resetPath();
void resetPoints();
void resetSpheres();
void resetVertices();
void showMessage(const std::string& message);
protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent);
void mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent);
private:
QLinkedList<QGraphicsLineItem*> edges;
QLinkedList<QGraphicsLineItem*> path;
QGraphicsRectItem* scene;
ConfigurationSpaceThread* thread;
signals:
void evalFinished();
};
#endif // CONFIGURATIONSPACESCENE_H
Include
QGraphicsLineItem
QGraphicsScene
管理QGraphicsItem的容器
QGraphicsScene继承自QObject,而不是QWidget,因此本身不可见
QLinkedList
基于迭代器访问的数据链表
QVector、Qlist、QlinkedList 类:用法比较
QlinkedList使用迭代器访问,而不是索引:
如果需要一个真实的链表,保证在列表中间插入常量时间,并将迭代器设置为项而不是索引,请使用QLinkedList.
C++
size_t
size_t 基本的与机器相关的无符号整数的C/C + +类型
7、 ConfigurationSpaceScene.cpp
Include
QGraphicsRectItem
QGraphicsRectItem
QGraphicsSceneMouseEvent
QGraphicsSceneMouseEvent 鼠标移动
函数
addCollision()
单独地向刚体添加碰撞对象,可以使用addCollision函数。
8、 ConfigurationSpaceThread.h
#ifndef CONFIGURATIONSPACETHREAD_H
#define CONFIGURATIONSPACETHREAD_H
#include <QThread>
#include <rl/plan/Model.h>
class ConfigurationSpaceThread : public QThread
{
Q_OBJECT
public:
ConfigurationSpaceThread(QObject* parent = nullptr);
virtual ~ConfigurationSpaceThread();
void run();
void stop();
std::size_t axis0;
std::size_t axis1;
rl::math::Real delta0;
rl::math::Real delta1;
rl::plan::Model* model;
protected:
private:
bool running;
signals:
void addCollision(const qreal& x, const qreal& y, const qreal& w, const qreal& h, const int& rgb);
};
#endif // CONFIGURATIONSPACETHREAD_H
Include
QThread
QThread 线程
9、 ConfigurationSpaceThread.cpp
#include <QMutexLocker>
#include <rl/plan/SimpleModel.h>
#include "ConfigurationSpaceThread.h"
#include "MainWindow.h"
ConfigurationSpaceThread::ConfigurationSpaceThread(QObject* parent) :
QThread(parent),
axis0(0),
axis1(1),
delta0(1.0f),
delta1(1.0f),
model(nullptr),
running(false)
{
}
ConfigurationSpaceThread::~ConfigurationSpaceThread()
{
}
void
ConfigurationSpaceThread::run()
{
QMutexLocker lock(&MainWindow::instance()->mutex);
this->running = true;
if (rl::plan::SimpleModel* model = dynamic_cast<rl::plan::SimpleModel*>(this->model))
{
rl::math::Vector maximum = model->getMaximum();
rl::math::Vector minimum = model->getMinimum();
rl::math::Real range0 = std::abs(maximum(this->axis0) - minimum(this->axis0));
rl::math::Real range1 = std::abs(maximum(this->axis1) - minimum(this->axis1));
rl::math::Real delta0 = range0 / std::ceil(range0 / this->delta0);
rl::math::Real delta1 = range1 / std::ceil(range1 / this->delta1);
std::size_t steps0 = static_cast<std::size_t>(std::ceil(range0 / delta0));
std::size_t steps1 = static_cast<std::size_t>(std::ceil(range1 / delta1));
rl::math::Vector q(*MainWindow::instance()->q);
for (std::size_t i = 0; i < steps1 + 1 && this->running; ++i)
{
q(this->axis1) = maximum(this->axis1) - i * delta1;
for (std::size_t j = 0; j < steps0 + 1 && this->running; ++j)
{
q(this->axis0) = minimum(this->axis0) + j * delta0;
model->setPosition(q);
model->updateFrames();
if (model->isColliding())
{
emit addCollision(
q(this->axis0),
q(this->axis1),
delta0,
delta1,
0
);
}
}
}
}
this->running = false;
}
void
ConfigurationSpaceThread::stop()
{
if (this->running)
{
this->running = false;
while (!this->isFinished())
{
QThread::usleep(0);
}
}
}
Include
QMuteLocker
QMutexLocker 互斥锁解锁
QMutexLocker创建时将传入的QMutex锁定,释放时将传入的QMutex解锁。
函数
run()
run()函数中实现线程任务.
10、 GraphicsView.h
#ifndef GRAPHICSVIEW_H
#define GRAPHICSVIEW_H
#include <QGraphicsView>
#include <QModelIndex>
class GraphicsView : public QGraphicsView
{
Q_OBJECT
public:
GraphicsView(QWidget* parent = nullptr);
virtual ~GraphicsView();
public slots:
void adjust();
void adjust(const QModelIndex&, const QModelIndex&);
protected:
virtual void resizeEvent(QResizeEvent* event);
private:
};
#endif // GRAPHICSVIEW_H
Include
QGraphicsView
QGraphicsView 视图窗口部件
将鼠标和按键事件场景化-使场景内容可视化
函数
槽函数
slots 槽函数
C++成员函数,很多的信号与之相关联,关联信号被发射时,槽就会被调用。
信号和槽是Qt特有的信息传输机制,让互不干扰的对象形成联系。
resizeEvent()
resizeEvent() 窗口大小、位置及其大小改变
adjust()
adjust() 自动识别调整
直接使用adjust()函数,进行界面的实时调整。
11、 GraphicsView.cpp
#include "GraphicsView.h"
GraphicsView::GraphicsView(QWidget* parent) :
QGraphicsView(parent)
{
}
GraphicsView::~GraphicsView()
{
}
void
GraphicsView::adjust()
{
this->fitInView(this->scene()->sceneRect(), Qt::KeepAspectRatio);
}
void
GraphicsView::adjust(const QModelIndex&, const QModelIndex&)
{
this->adjust();
}
void
GraphicsView::resizeEvent(QResizeEvent* event)
{
this->adjust();
}
函数
fitInView()
fitInView 适中view显示
视图中显示的内容较多时,出现横或竖的滚动条时,需要将视图中的元素适中显示时(即让滚动条因内容自动消失),通过计算出一个rect,调用fitInView函数即可。
12、 SoGradientBackground.h
#ifndef SOGRADIENTBACKGROUND_H
#define SOGRADIENTBACKGROUND_H
#include <Inventor/fields/SoSFColor.h>
#include <Inventor/nodes/SoNode.h>
class SoGradientBackground : public SoNode
{
SO_NODE_HEADER(SoGradientBackground);
public:
SoGradientBackground();
virtual SbBool affectsState() const;
static void exitClass();
virtual void GLRender(SoGLRenderAction* action);
static void initClass();
SoSFColor color0;
SoSFColor color1;
protected:
virtual ~SoGradientBackground();
private:
};
#endif // SOGRADIENTBACKGROUND_H
13、 SoGradientBackground.h
#ifdef WIN32
#include <windows.h>
#endif // WIN32
#ifdef __APPLE__
#include <OpenGL/gl.h>
#else // __APPLE__
#include <GL/gl.h>
#endif // __APPLE__
#include <Inventor/nodes/SoSubNode.h>
#include "SoGradientBackground.h"
SO_NODE_SOURCE(SoGradientBackground);
SoGradientBackground::SoGradientBackground() :
SoNode(),
color0(),
color1()
{
SO_NODE_CONSTRUCTOR(SoGradientBackground);
SO_NODE_ADD_FIELD(color0, (1.0f, 1.0f, 1.0f));
SO_NODE_ADD_FIELD(color1, (0.0f, 0.0f, 0.0f));
}
SoGradientBackground::~SoGradientBackground()
{
}
SbBool
SoGradientBackground::affectsState() const
{
return false;
}
void
SoGradientBackground::exitClass()
{
}
void
SoGradientBackground::GLRender(SoGLRenderAction* action)
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glColor3f(this->color0.getValue()[0], this->color0.getValue()[1], this->color0.getValue()[2]);
glVertex2f(1.0, 1.0);
glVertex2f(-1.0, 1.0);
glColor3f(this->color1.getValue()[0], this->color1.getValue()[1], this->color1.getValue()[2]);
glVertex2f(-1.0, -1.0);
glVertex2f(1.0, -1.0);
glEnd();
glPopAttrib();
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
void
SoGradientBackground::initClass()
{
SO_NODE_INIT_CLASS(SoGradientBackground, SoNode, "Node");
}
SoQt
引用使用了SoQt库