提交 2776b7b0 编写于 作者: M manjaro

Merge branch 'master' of git@codechina.csdn.net:coloreaglestdio/qtcpp_demo.git into master

# Conflicts:
#	floodfill_mdf/floodfill_mdf.cpp
...@@ -12,6 +12,10 @@ cpp_threadpool ...@@ -12,6 +12,10 @@ cpp_threadpool
functional助力C++11实现高度可重用接口-线程池例子 functional助力C++11实现高度可重用接口-线程池例子
https://goldenhawking.blog.csdn.net/article/details/51981905 https://goldenhawking.blog.csdn.net/article/details/51981905
floodfill_mdf
作业讲评-二值矩阵避障最短路径算法
https://goldenhawking.blog.csdn.net/article/details/109411787
nmcalc nmcalc
一种基于C++STL库的回溯排列组合枚举器 一种基于C++STL库的回溯排列组合枚举器
https://goldenhawking.blog.csdn.net/article/details/80037669 https://goldenhawking.blog.csdn.net/article/details/80037669
......
#include "demowidget.h"
#include <QPaintEvent>
#include <QPainter>
#include <QPen>
#include <QBrush>
const int rows = 64;
const int cols = 64;
int
startx = rand() % cols,
starty = rand() % rows;
int
endx = (startx + rand() % (cols-3) + 2) % cols,
endy = (starty + rand() % (rows-3) + 2) % rows;
std::vector<int> cx,cy,idx,rx,ry,ridx;
demoWidget::demoWidget(QWidget *parent) : QWidget(parent)
{
resize(640,640);
for (int i=0;i<rows;++i)
{
std::vector<char> v(cols,1);
v_mat.push_back(std::move(v));
}
}
void demoWidget::paintEvent(QPaintEvent * evt)
{
QPainter painter(this);
QPen pen (Qt::NoPen);
QBrush brush_valid(QColor(255,255,255));
QBrush brush_block(QColor(0,0,0));
QBrush brush_start(QColor(255,0,0));
QBrush brush_raw(QColor(0,128,0));
QBrush brush_end(QColor(0,0,255));
QPen pen_line (brush_start,2);
QPen pen_lineraw (brush_raw,3,Qt::DotLine);
painter.setPen(pen);
painter.setBrush(brush_valid);
QSize sz = size();
double dx = sz.width() * 1.0/(cols);
double dy = sz.height()* 1.0/(rows);
for (int i=0;i<rows;++i)
{
for (int j=0;j<cols;++j)
{
if (v_mat[i][j]==0)
painter.setBrush(brush_block);
else
painter.setBrush(brush_valid);
painter.drawRect(j * dx , i *dx,dx, dy);
}
}
painter.setBrush(brush_start);
painter.drawEllipse(startx * dx , starty *dx,dx, dy);
painter.setBrush(brush_end);
painter.drawEllipse(endx * dx , endy *dx,dx, dy);
if (ridx.size())
{
const int impsz = ridx.size();
painter.setPen(pen_lineraw);
for (int i=0;i<impsz-1;++i)
{
const int curx1 = rx[ridx[i]] * dx+ dx/2;
const int cury1 = ry[ridx[i]] * dy + dy/2;
const int curx2 = rx[ridx[i+1]] * dx + dx/2;
const int cury2 = ry[ridx[i+1]] * dy + dy/2;
painter.drawLine(curx1,cury1,curx2,cury2);
}
}
if (idx.size())
{
const int impsz = idx.size();
painter.setPen(pen_line);
for (int i=0;i<impsz-1;++i)
{
const int curx1 = cx[idx[i]] * dx+ dx/2;
const int cury1 = cy[idx[i]] * dy + dy/2;
const int curx2 = cx[idx[i+1]] * dx + dx/2;
const int cury2 = cy[idx[i+1]] * dy + dy/2;
painter.drawLine(curx1,cury1,curx2,cury2);
}
}
evt->accept();
}
void demoWidget::mousePressEvent(QMouseEvent * evt)
{
v_mat.clear();
for (int i=0;i<rows;++i)
{
std::vector<char> v_row(cols,1);
v_mat.push_back(std::move(v_row));
}
for (int i=0;i<128;++i)
{
v_mat[rand()%rows][rand()%cols] = 0;
}
startx = rand() % cols;
starty = rand() % rows;
endx = (startx + rand() % (cols-3) + 2) % cols;
endy = (starty + rand() % (rows-3) + 2) % rows;
v_mat[starty][startx] = 1;
v_mat[endy][endx] = 1;
//找路径,不归并
min_distance_find(v_mat, startx,starty, endx,endy, &rx,&ry,&ridx,false);
//找路径,做归并
min_distance_find(v_mat, startx,starty, endx,endy, &cx,&cy,&idx,true);
update();
}
#ifndef DEMOWIDGET_H
#define DEMOWIDGET_H
#include <QWidget>
#include <vector>
#include "floodfill_mdf.h"
class demoWidget : public QWidget
{
Q_OBJECT
public:
explicit demoWidget(QWidget *parent = nullptr);
protected:
//0,1联通矩阵,0是障碍,1是可通区域
std::vector<std::vector<char> > v_mat;
protected:
void paintEvent(QPaintEvent * evt) override;
void mousePressEvent(QMouseEvent * evt) override;
};
#endif // DEMOWIDGET_H
######################################################################
# Automatically generated by qmake (3.1) Sat Oct 31 14:03:29 2020
######################################################################
TEMPLATE = app
TARGET = floodfill_gui
INCLUDEPATH += .
QT += core gui widgets
# You can make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# Please consult the documentation of the deprecated API in order to know
# how to port your code away from it.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
# Input
SOURCES += floodfill_mdf.cpp \
demowidget.cpp \
gui_main.cpp
HEADERS += \
demowidget.h \
floodfill_mdf.h
#include <iostream> #include <iostream>
#include <vector>
#include <list> #include <list>
#include <set> #include <set>
#include <cstdlib> #include <cstdlib>
#include <cassert> #include <cassert>
#include <cstdio> #include <cstdio>
int min_distance_find( #include <ctime>
const std::vector<std::vector<char> > & v_mat , #include "floodfill_mdf.h"
const int startx, #ifndef QT_GUI_LIB
const int starty,
const int endx,
const int endy,
std::vector<int> *x,//着色点
std::vector<int> *y,
std::vector<int> *pidx//关键点
);
int main(int /*argc*/, char * /*argv*/[]) int main(int /*argc*/, char * /*argv*/[])
{ {
using namespace std; using namespace std;
...@@ -24,13 +15,13 @@ int main(int /*argc*/, char * /*argv*/[]) ...@@ -24,13 +15,13 @@ int main(int /*argc*/, char * /*argv*/[])
//0,1联通矩阵,0是障碍,1是可通区域 //0,1联通矩阵,0是障碍,1是可通区域
vector<vector<char> > v_mat; vector<vector<char> > v_mat;
const int rows = 24, cols=32; const int rows = 24, cols=39;
for (int i=0;i<rows;++i) for (int i=0;i<rows;++i)
{ {
vector<char> v_row; vector<char> v_row;
v_row.resize(cols,1); v_row.resize(cols,1);
if (rand()%rows<3) if (rand()%100<30)
for (int j=0;j<3;++j) for (int j=0;j<4;++j)
v_row[rand()%cols] = 0; v_row[rand()%cols] = 0;
v_mat.push_back(move(v_row)); v_mat.push_back(move(v_row));
} }
...@@ -80,7 +71,7 @@ int main(int /*argc*/, char * /*argv*/[]) ...@@ -80,7 +71,7 @@ int main(int /*argc*/, char * /*argv*/[])
else if (disp[i][j] >=2) else if (disp[i][j] >=2)
printf ("%02X",(unsigned int)(disp[i][j]-2) % 0xFFu); printf ("%02X",(unsigned int)(disp[i][j]-2) % 0xFFu);
else if (disp[i][j] == -1) else if (disp[i][j] == -1)
cout << ". "; cout << "[]";
else if (disp[i][j] == -2) else if (disp[i][j] == -2)
cout << "SS"; cout << "SS";
else if (disp[i][j] == -3) else if (disp[i][j] == -3)
...@@ -98,12 +89,21 @@ int main(int /*argc*/, char * /*argv*/[]) ...@@ -98,12 +89,21 @@ int main(int /*argc*/, char * /*argv*/[])
return 0; return 0;
} }
#endif
/*! /*!
* 反向着色 * \brief mdf_rev_fill 反向搜索,从终点处找起点
* */ * \param v_mat 障碍地形,1是平地,0是墙
* \param startx 开始位置x
* \param starty 开始位置y
* \param endx 结束位置x
* \param endy 结束位置y
* \param p_rev 保存搜索步长的v_mat等尺寸矩阵
* \return 能否找到起点
*/
bool mdf_rev_fill( bool mdf_rev_fill(
const std::vector<std::vector<char> > & v_mat , const std::vector<std::vector<char> > & v_mat ,
const int startx, const int startx,
...@@ -165,7 +165,15 @@ bool mdf_rev_fill( ...@@ -165,7 +165,15 @@ bool mdf_rev_fill(
}//end while (currX.size() && !arrival) }//end while (currX.size() && !arrival)
return arrival; return arrival;
} }
//最初路径 /*!
* \brief mdf_path_find 前向搜索路径
* \param v_rev 反向寻找后生成的距离矩阵
* \param startx 起点x
* \param starty 起点y
* \param cx 存储路径坐标的x向量
* \param cy 存储路径坐标的y向量
* \return 是否成功搜索生成路径
*/
bool mdf_path_find( bool mdf_path_find(
std::vector<std::vector<unsigned int> > & v_rev, std::vector<std::vector<unsigned int> > & v_rev,
const int startx, const int startx,
...@@ -216,7 +224,16 @@ bool mdf_path_find( ...@@ -216,7 +224,16 @@ bool mdf_path_find(
return (v==0); return (v==0);
} }
//路径合并 /*!
* \brief min_dis_opt 归并路径缩短距离
* \param v_mat 障碍地形,1是平地,0是墙
* \param rx 非最优路径x(直接搜索出来的)
* \param ry 非最优路径y(直接搜索出来的)
* \param cx 较优路径x
* \param cy 较优路径y
* \param pidx 关键waypoint下表(相对于cx,cy),连接两个下标的cx,cy的为直线。
* \return 优化后路径大小
*/
int min_dis_opt( int min_dis_opt(
const std::vector<std::vector<char> > & v_mat , const std::vector<std::vector<char> > & v_mat ,
const std::vector<int> & rx, const std::vector<int> & rx,
...@@ -234,7 +251,7 @@ int min_dis_opt( ...@@ -234,7 +251,7 @@ int min_dis_opt(
std::set<int> important ; std::set<int> important ;
int test_begin = 0; size_t test_begin = 0;
//本次最差的目标 //本次最差的目标
int opt_tar = test_begin + 2; int opt_tar = test_begin + 2;
important.insert(test_begin); important.insert(test_begin);
...@@ -252,7 +269,7 @@ int min_dis_opt( ...@@ -252,7 +269,7 @@ int min_dis_opt(
for (int i=0;i<maxp && good;++i) for (int i=0;i<maxp && good;++i)
{ {
//为不打擦边球,要求周围1格子也没有障碍才能优化。 //为不打擦边球,要求周围1格子也没有障碍才能优化。
for (int d = 0; d< 9 && good; ++d) for (int d = 0; d< 5 && good; ++d)
{ {
const int rev_dirt[9][2] = { const int rev_dirt[9][2] = {
{0,0}, {0,0},
...@@ -282,7 +299,7 @@ int min_dis_opt( ...@@ -282,7 +299,7 @@ int min_dis_opt(
{ {
important.insert(test_begin); important.insert(test_begin);
std::vector<int> newx, newy; std::vector<int> newx, newy;
for (int i=0;i<test_begin;++i) for (size_t i=0;i<test_begin;++i)
{ {
newx.push_back(lx[i]); newx.push_back(lx[i]);
newy.push_back(ly[i]); newy.push_back(ly[i]);
...@@ -338,7 +355,19 @@ int min_dis_opt( ...@@ -338,7 +355,19 @@ int min_dis_opt(
return cx->size(); return cx->size();
} }
/*!
* \brief min_distance_find 避障路径搜索函数
* \param v_mat 障碍地形,1是平地,0是墙
* \param startx 起点x
* \param starty 起点y
* \param endx 终点x
* \param endy 终点y
* \param x 路径x
* \param y 路径y
* \param pidx 关键waypoint下表(相对于cx,cy),连接两个下标的cx,cy的为直线。
* \param join 是否做直线归并优化。
* \return cx大小
*/
int min_distance_find( int min_distance_find(
const std::vector<std::vector<char> > & v_mat , const std::vector<std::vector<char> > & v_mat ,
const int startx, const int startx,
...@@ -347,18 +376,26 @@ int min_distance_find( ...@@ -347,18 +376,26 @@ int min_distance_find(
const int endy, const int endy,
std::vector<int> *x, std::vector<int> *x,
std::vector<int> *y, std::vector<int> *y,
std::vector<int> * pidx std::vector<int> * pidx,
bool join
) )
{ {
std::vector<std::vector<unsigned int> > v_rev ; std::vector<std::vector<unsigned int> > v_rev ;
if (!mdf_rev_fill(v_mat,startx,starty,endx,endy, &v_rev)) if (!mdf_rev_fill(v_mat,startx,starty,endx,endy, &v_rev))
return false; return false;
std::vector<int> cx,cy; std::vector<int> cx,cy;
if (!mdf_path_find(v_rev,startx,starty,&cx,&cy)) if (!mdf_path_find(v_rev,startx,starty,&cx,&cy))
return false; return false;
if (join)
return min_dis_opt(v_mat,cx,cy,x,y,pidx); return min_dis_opt(v_mat,cx,cy,x,y,pidx);
size_t sz = cx.size();
pidx->clear();
for (size_t i=0;i<sz;++i)
pidx->push_back(i);
*x = std::move(cx);
*y = std::move(cy);
return x->size();
} }
#ifndef FLOODFILL_MDF_H
#define FLOODFILL_MDF_H
#include <vector>
int min_distance_find(
const std::vector<std::vector<char> > & v_mat ,
const int startx,
const int starty,
const int endx,
const int endy,
std::vector<int> *x,//着色点
std::vector<int> *y,
std::vector<int> *pidx,//关键点
bool join = true
);
#endif // FLOODFILL_MDF_H
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
###################################################################### ######################################################################
TEMPLATE = app TEMPLATE = app
QT -= gui
TARGET = floodfill_mdf TARGET = floodfill_mdf
INCLUDEPATH += . INCLUDEPATH += .
CONFIG += console CONFIG += console
...@@ -16,3 +17,6 @@ CONFIG += console ...@@ -16,3 +17,6 @@ CONFIG += console
# Input # Input
SOURCES += floodfill_mdf.cpp SOURCES += floodfill_mdf.cpp
HEADERS += \
floodfill_mdf.h
#include "floodfill_mdf.h"
#include <QApplication>
#include <QWidget>
#include "demowidget.h"
int main(int argc , char * argv[])
{
QApplication app(argc,argv);
demoWidget wig;
wig.show();
return app.exec();
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册