NX二次开发——矩形排料5(基于最低水平线+遗传算法排料策略实现)

本文主要是介绍NX二次开发——矩形排料5(基于最低水平线+遗传算法排料策略实现),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、概述

二、知识回顾

2.1适应度函数的确定

2.2基因编码

2.3遗传算法复制(选择)

2.4遗传算法交叉操作        通过交叉操作可以增加种群个体的多样性,既可以产生更多的优秀解。下面通过顺序编码方法进行改进(网上有很多方法)。注意这里直接用顺序编码方式会产生非法子代,不是结果不好,本文采取整数编码。

2.5遗传算法变异操作        从遗传算法的角度来看,解的进化主要是靠选择机制和交叉策略来完成,变异只是产生新个体的辅助方法,目的在于提高算法的局部搜索能力,避免陷入早熟。通过交叉算子和变异算子的相互配合,共同完成对搜索空间的全局搜索和局部搜索,从而使遗传算法能够良性的搜索以完成最优化问题的寻优过程,变异概率一般不能太大,本次取为0.05左右。

2.5.1位置交换变异

2.5.2旋转变异(基因正负号变化)

三、所用函数代码与运行结果

3.1所用函数代码

3.2运行结果

3.3结果分析


一、概述

        本文前三篇对矩形排料的理论知识已经做出了讲解,第四篇基于最低水平线搜索策略已经实现了NX基于最低水平线排料,这篇主要详细的记录一下基于最低水平线+遗传算法排料策略实现。

二、知识回顾

2.1适应度函数的确定

        上一篇矩形排料3已经对适应度函数进行了认识,这里我进行简单的叙述。参考“下台阶算法”提出了以板材利用率的大小表示适应度函数值的大小,板材利用率越高,适应度函数值越大,定义如下:

/******************************************************************************************
double			ratio         板材的利用率(适应度函数值)
double			usedArea	  需要排样矩形件的面积总和(*100单位转化)
double			width		  板材宽度
double			maxHigh       板材排料后最大使用高度,不包括使用完整后的板材
int				symbol		  板料个数标识
******************************************************************************************/
ratio = (usedArea * 100.0) / (width * (maxHigh + (symbol - 1)));
2.2基因编码

        用遗传算法解决实际问题时,必需先确定染色体的编码方法。编码就是将问题的解用一种代码来表示,从而将问题的状态空间与遭传算法的码空间相对应,这在很大程度上依赖于所要求解问题的性质。编码是应用遭传算法求解问题时的一个关键步骤 ,编码方法决定了染色体的排列形式,编码的好坏将直接影响到遭传算法的性能和效率。

       由于板材和零件都是矩形,为了使矩形排放时板材的利用率尽可能高,每个零件在具体排放时只能有横放和竖放两种方式。由于每个基因的编码可以为正或负,在本文中统一规定:矩形的编号为正表示矩形横排,即矩形的长边平行于X轴;矩形的编号为负表示矩形竖排,即矩形的长边平行于Y轴 。

        本文采用整数顺序编码方式:先将要排放的每个矩形都统一进行编号,矩形的编号可以为正或负,矩形编号的正负是根据矩形是横放还是竖放来决定的。一个矩形的编号对应一个基因的编码。设要排放的矩形总数为n,n个矩形的编号构成了一个染色体。种群中每条染色体的长度与待排矩形零件总数相同,染色体中每个基因的编码对应相应矩形的编号,所有基因编码的一个排列顺序构成了一个染色体。

        染色体{-2, 1 , 5 , 3 , -4}表示先排 2 号矩形,矩形竖排;接着排 1 号矩形,矩形横排;接下来横排矩形 5 ,然后横排矩形3 ,最后竖排矩形 4 ,如下图1所示:

图1基因编码

2.3遗传算法复制(选择)

        选择操作是为了保证个体的优良特性得以保存并能有效的遗传到下一代中,目的在于保留有效、优良基因,以保证解的质量,提高收敛速度。选择算子,就是依适应度大小,按照某种规则,从当前的种群中选择适应度高的个体遗传到下一代种群中同时淘汰那些适应度值低的个体。本次利用轮盘赌进行选择,其主要实现的思路如下:将种群中所有染色体编号,并根据各自适应值计算按比例分配的概率,依次计算染色体累加概率,产生(0,1)之间随机数,若其最多能大于序列中第m个值,则第m个染色体被随机选择。

  

        个体放入适应度越大,其被选中的概率越高,个体被选择的概率值可以看做在轮盘区间范围,每次轮盘赌算法都会在(0,1)之间产生一个随机数,通过随机数落在轮盘哪个区间来确定被选中个体。注意累计所占比例最后一定是1,如果不为1的话一定计算有误。

2.4遗传算法交叉操作
        通过交叉操作可以增加种群个体的多样性,既可以产生更多的优秀解。下面通过顺序编码方法进行改进(网上有很多方法)。注意这里直接用顺序编码方式会产生非法子代,不是结果不好,本文采取整数编码。

         根据交叉概率p_{i},选择 2个个体 x_{i}x_{j}进行交叉操作。随机选择一个交叉点,在交叉点处,交换 2个个体后半部分得到 2个新的个体x_{i}^{'}x_{j}^{'}, 如下图所示:注意这里数字前的负号只表示矩形是横放还是竖放(在考虑交叉时,看做标记即可)

61354279810

个体x_{i}

97568321410

个体x_{j}

61354321410

个体x_{i}^{'}

97568279810

个体x_{j}^{'}

        很显然,交叉操作可能产生非法个体,即个体中有重复的基因。所以必须对2个新个体的基因进行调整。

**1**找出个体x_{i}^{'}的重复基因1,3,4;个体x_{j}^{'}的重复基因9,7,8;

**2**将1,3,4与9,7,8以及其关联的负号对应交换,得到两个合法的新个体x_{i}^{''}x_{j}^{''},如下所示:

69758321410

个体x_{i}^{''}

13564279810

个体x_{j}^{''}

2.5遗传算法变异操作
        从遗传算法的角度来看,解的进化主要是靠选择机制和交叉策略来完成,变异只是产生新个体的辅助方法,目的在于提高算法的局部搜索能力,避免陷入早熟。通过交叉算子和变异算子的相互配合,共同完成对搜索空间的全局搜索和局部搜索,从而使遗传算法能够良性的搜索以完成最优化问题的寻优过程,变异概率一般不能太大,本次取为0.05左右。
2.5.1位置交换变异

        位置变异的思想是产生[1,n]之间的两个正整数随机数,num1、num2,将两个位置交换。例如:产生的随机数num1=2、num2=6

原染色体:

61354279810

变异后染色体:

62354179810

具体步骤:

**1**在要进行变异的个体中,随机选择2个基因位;

**2**将所选择 2个基因位上的基因值交换,得到 1个新个体。

2.5.2旋转变异(基因正负号变化)

 排列方式变异的思想是:第一步在[1,n]之间产生一个随机数num;第二步在[0,1]之间产生一个随机数 rand,若rand>0.5,刚将其排列方式进行改变,反之,不予理睬,这里所说的变是指排列时矩形是横放还是竖放。

例如:产生的随机数分别为num=5,rand=0.7。

原染色体:

61354279810

变异后染色体:

6135-4279810

三、所用函数代码与运行结果

3.1所用函数代码
//用户定义头文件
#include <atlbase.h>
#include <Windows.h>
#include <vector>
#include <algorithm>
#include "uf.h"
#include "uf_modl.h"
#include "uf_obj.h"
#include "uf_ui.h"
#include "uf_eval.h"
#include "uf_csys.h"
#include <numeric>
#include <algorithm>
#include <random>
#include <stdio.h>
#include <random>
#include <cmath>
#include <numeric>
#include <iostream>
#include <unordered_map>/*****************************************************************************************************
struct:			OutLine1			水平线类结构体
double			Origin				水平线起始x位置
double			End					水平线终止x位置
double			Height				水平线高度
******************************************************************************************************/
struct OutLine1
{double Origin;double End;double Height;// 有参数构造函数OutLine1(const double& origin, const double& end, const double&  height): Origin(origin), End(end), Height(height){}
};//用户定义
/*****************************************************************************************************
Function:		vector<vector<int>>				NXOpen_GA_RectangularLayout		初始化种群
input:			int								ProductsNum						每个染色体的尺寸大小	
input:			int								Population_size					种群大小
return:		vector<vector<int>>				Population						初始化种群后的数据
******************************************************************************************************/
vector<vector<int>> NXOpen_GA_RectangularLayout::Initial_population(int ProductsNum, int Population_size)
{。。。。。。
}/*****************************************************************************************************
Function:		void				initLineList1		初始化水平线集
input:			double				origin				水平线起始x位置
input:			double				end					水平线终止x位置
input:			double				height				水平线高度
input,output:	vector<OutLine1>	lineList			水平线集合
input,output:	OutLine1			lowestLine			最低水平线
input,output:	int					lowestLineIdx		水平线集合中的最低水平线所在位置的ID
******************************************************************************************************/
void NXOpen_GA_RectangularLayout::initLineList1(double origin, double end, double height, vector<OutLine1> &lineList, OutLine1 &lowestLine, int &lowestLineIdx)
{。。。。。。
}/*******************************************************************************************************************
Function:		void				findLowestLine1		找出最低水平线(如果最低水平线不止一条则选取最左边的那条)
input,output:	vector<OutLine1>	lineList			水平线集合
input,output:	OutLine1			lowestLine			最低水平线
input,output:	int					lowestLineIdx		水平线集合中的最低水平线所在位置的ID
*********************************************************************************************************************/
void NXOpen_GA_RectangularLayout::findLowestLine1(vector<OutLine1> lineList, int &lowestLineIdx, OutLine1 &lowestLine)
{。。。。。。
}/*******************************************************************************************************************
Function:		double				lineWidth1			获得放置矩形件的可用长度
input:			int					index				水平线集合中的最低水平线所在位置的ID
input:			OutLine1			lineList			水平线集合
return:		double				availableWidth		返回放置矩形件的可用长度
*********************************************************************************************************************/
double NXOpen_GA_RectangularLayout::lineWidth1(int index, vector<OutLine1> lineList)
{。。。。。。
}/*******************************************************************************************************************
Function:		double				lineHigh1			获得放置矩形件的可用高度
input:			int					index				水平线集合中的最低水平线所在位置的ID
input:			OutLine1			lineList			水平线集合
input,output:	double				containerHigh		板材的高度
return:		double				availableHigh		返回放置矩形件的可用高度
*********************************************************************************************************************/
double NXOpen_GA_RectangularLayout::lineHigh1(int index, vector<OutLine1> lineList, double containerHigh)
{。。。。。。
}/*******************************************************************************************************************
Function:		double				maxlineHigh1		水平线集合中最大的高度
input:			OutLine1			lineList			水平线集合
return:		double				maxlineHigh1		返回放置矩形件的可用高度
*********************************************************************************************************************/
double NXOpen_GA_RectangularLayout::maxlineHigh1(vector<OutLine1> lineList)
{。。。。。。
}/*******************************************************************************************************************************************
Function:		int						searchBySize1			获得候选物品的索引;根据长度搜索矩形件(找出宽度或高度小于目标长度的首个矩形件)
input:			double					targetWidth				放置矩形件的可用长度
input:			vector<vector<double>>	data					要放置的矩形物品列表
return:		int						candidateIdx			返回候选物品的索引
********************************************************************************************************************************************/
int NXOpen_GA_RectangularLayout::searchBySize1(double targetWidth, vector<vector<double>> data)
{。。。。。。
}/*******************************************************************************************************************************************
Function:		int						searchBySize2			获得候选物品的索引;根据长度搜索矩形件(找出宽度或高度小于目标长度的首个矩形件)
input:			double					targetWidth				放置矩形件的可用长度
input:			double					targetHigh				放置矩形件的可用高度
input:			vector<vector<double>>	data					要放置的矩形物品列表
return:		int						candidateIdx			返回候选物品的索引
********************************************************************************************************************************************/
int NXOpen_GA_RectangularLayout::searchBySize2(double targetWidth, double targetHigh, vector<vector<double>> data)
{。。。。。。
}/***********************************************************************************************************************************
Function:		vector<double>		rotateNew1			对于满足长度小于可用长度的矩形件进行旋转放置(宽度放不下时,对矩形件进行旋转)
input:			vector<double>		pro					要放置的矩形件
return:		vector<double>		temp				返回放置矩形件
*************************************************************************************************************************************/
vector<double> NXOpen_GA_RectangularLayout::rotateNew1(vector<double> pro)
{。。。。。。
}/***********************************************************************************************************************************
Function:		void				updateLineList			在水平线集合中更新最低水平线
input:			int					index					水平线集合中的最低水平线所在位置的ID
intput,output:	OutLine1			newLine					新的最低水平线
intput,output:	vector<OutLine1>	lineList				替换新的最低水平线后的水平线集合
*************************************************************************************************************************************/
void NXOpen_GA_RectangularLayout::updateLineList(int index, OutLine1& newLine, vector<OutLine1> &lineList)
{。。。。。。
}/***********************************************************************************************************************************
Function:		void				insertLineList			在水平线集合的最低水平线后插入新的最低水平线
input:			int					index					水平线集合中的最低水平线所在位置的ID
intput,output:	OutLine1			newLine					新的最低水平线
intput,output:	vector<OutLine1>	lineList				替换新的最低水平线后的水平线集合
*************************************************************************************************************************************/
void NXOpen_GA_RectangularLayout::insertLineList(int index, OutLine1& newLine, vector<OutLine1> &lineList)
{。。。。。。
}/**************************************************************************************************
Function:		void					packing			将候选物品排样
input,output:	vector<double>			pro				要放置的矩形件
intput:			int						lowestLineIdx	水平线集合中的最低水平线所在位置的ID
input,output:	OutLine1				lineList		水平线集合
input,output:	vector<vector<double>>	resultPos		排序后的矩形物品列表
intput:			OutLine1				lowestLine		最低水平线
***************************************************************************************************/
void NXOpen_GA_RectangularLayout::packing(vector<double> pro, int &lowestLineIdx, vector<OutLine1> &lineList, vector<vector<double>> &resultPos, OutLine1 lowestLine)
{。。。。。。
}/*****************************************************************************************************************
Function:		void					enhanceLine1	最低水平线宽度小于要排样矩形宽度,提升水平线
intput,output:	int						index			水平线集合中的最低水平线所在位置的ID
input,output:	vector<OutLine1>		lineList		水平线集合
input,output:  OutLine1				lowestLine		最低水平线
input:			double					containerHigh	板料高度
input:			double					containerWidth	板料宽度
input:			double					lingjianjuli	零件距离
input,output:	int						symbol			板料个数标识
******************************************************************************************************************/
void NXOpen_GA_RectangularLayout::enhanceLine1(int &index, vector<OutLine1> &lineList, double containerHigh, double containerWidth, double lingjianjuli, OutLine1 &lowestLine)
{。。。。。。
}/*****************************************************************************************************************
Function:		double					calHighLine1	计算板材的最大使用高度
intput:			vector<OutLine1>		lineList		水平线集合
return:		double					maxHigh			最大高度
******************************************************************************************************************/
double NXOpen_GA_RectangularLayout::calHighLine1(vector<OutLine1> lineList)
{。。。。。。
}/***********************************************************************************************************************************
Function:		double					calUsedRatio1	计算排料矩形件的总面积、板材的最低水平线高度,板材利用率1,板材利用率2
intput,output:	double					usedArea		排样矩形件的面积总和
input:			vector<vector<double>>	resultPos		排样矩形件信息集合
input:			double					width			板材宽度
input:			double					High			板料使用的最小高度,不包括使用完整后的板材
input:			vector<OutLine1>		lineList		水平线集合
input:			int						symbol			板料个数标识
intput,output:	double					ratio			板材利用率
************************************************************************************************************************************/
void NXOpen_GA_RectangularLayout::calUsedRatio1(double &usedArea, vector<vector<double>> resultPos, double width, double High, vector<OutLine1> lineList, int symbol, double &ratio)
{。。。。。。
}/**************************************************************************************************
Function:		void							Packing_main	将候选物品排样主函数(放置个体)
intput,output:	double							usedArea		排样矩形件的面积总和
intput,output:	double							ratio			板材利用率
intput,output:	double							MaxHeight		板料排放物品后达到的最大高度,不包括使用完整后的板材
input:			double							container_height板材高度
input:			double							container_width	板材宽度
input:			vector<vector<double>>			products		要排放的矩形物件集合
return:		vector<vector<vector<double>>>	resultPos		返回将多个板料候选物品排样数据集合
***************************************************************************************************/
vector<vector<vector<double>>> NXOpen_GA_RectangularLayout::Packing_main(double &usedArea,double &ratio, double&MaxHeight, double container_height, double container_width, vector<vector<double>> products)
{。。。。。。
}/*****************************************************************************************************************
Function:		vector<double>			Get_Fitness			获得适应度函数
input:			vector<vector<double>>	products			要排放的矩形物件集合
input:			double					container_height	板材高度
input:			double					container_width		板材宽度
intput:			vector<vector<int>>		Population			种群集合
return:		vector<double>			fitness				当代种群中的适应度函数值大小集合
******************************************************************************************************************/
vector<double> NXOpen_GA_RectangularLayout::Get_Fitness(vector<vector<double>> products, double container_height, double container_width, vector<vector<int>> Population)
{。。。。。。
}/*****************************************************************************************************************
Function:		void					Get_bestAndworst			获得当代最佳和最差个体索引
intput,output:	int						best_idx					当代最佳个体索引
intput,output:	double					worst_idx					当代最差个体索引
input:			vector<double>			fitness						当代适应度函数值集合
******************************************************************************************************************/ 
void NXOpen_GA_RectangularLayout::Get_bestAndworst(int &best_idx, int &worst_idx, vector<double> fitness)
{。。。。。。
}/*****************************************************************************************************************
Function:		void					select			遗传算法选择(复制)操作——轮盘赌思想
intput:		vector<vector<int>>		Population		种群集合
input:			vector<double>			fitness			当代适应度函数值集合
return:		vector<vector<int>>		Population		新的种群集合
******************************************************************************************************************/
vector<vector<int>> NXOpen_GA_RectangularLayout::select(vector<vector<int>> Population, vector<double> fitness)
{。。。。。。
}/*****************************************************************************************************************
Function:		vector<int>				randNum					随机产生1到n的数,一共n个,每个只出现一次
intput:		int 					number					需要产生的个数
return:		vector<vector<int>>		random_combination		产生随机数集合
******************************************************************************************************************/
vector<int> NXOpen_GA_RectangularLayout::randNum(int number)
{。。。。。。
}/*****************************************************************************************************************
Function:		int			getRandomNumber					随机产生一个在[main,max]区间内的正整数
intput:		int 		min								产生随机数的下限
intput:		int			max								产生随机数的上限
return:			int			RandomNumber					返回产生的随机数
******************************************************************************************************************/
int NXOpen_GA_RectangularLayout::getRandomNumber(int min, int max)
{。。。。。。
}/*****************************************************************************************************************
Function:		double			getRandomNumber					随机产生一个在[main,max]区间内的double类型
intput:		double 			min								产生随机数的下限
intput:		double			max								产生随机数的上限
return:			double			RandomNumber					返回产生的随机数
******************************************************************************************************************/
double NXOpen_GA_RectangularLayout::getRandomNumber(double min, double max)
{。。。。。。
}/*****************************************************************************************************************
Function:		void			findDuplicatePositions			查询两个vector中重复的元素并记录下其位置
intput:		vector<int> 	nums1							第一个vector
intput:		vector<int>		nums2							第二个vector
intput,output:	vector<int> 	Element							第一个与第二个重复数字集合
intput,output:	vector<int>		positions						第一个与第二个重复数字位置集合
******************************************************************************************************************/
void NXOpen_GA_RectangularLayout::findDuplicatePositions(vector<int> nums1, vector<int> nums2, vector<int> &Element, vector<int> &positions)
{。。。。。。
}/*****************************************************************************************************************
Function:		void			crossover_inner			两个个体进行交叉操作
intput,output:	vector<int> 	individual1				第一个个体
intput,output:	vector<int> 	individual2				第二个个体
intput:		int				position				要交叉的位置
******************************************************************************************************************/
void NXOpen_GA_RectangularLayout::crossover_inner(vector<int> &individual1, vector<int> &individual2, int position)
{。。。。。。
}/*****************************************************************************************************************
Function:		void					crossover			交叉操作
intput,output:	vector<vector<int>> 	Population			种群集合
intput:		double				 	PC					交叉概率	
******************************************************************************************************************/
void NXOpen_GA_RectangularLayout::crossover(vector<vector<int>> &Population, double PC)
{。。。。。。
}/*****************************************************************************************************************
Function:		void					mutation			变异操作
intput,output:	vector<vector<int>> 	Population			种群集合
intput:		double				 	PM					变异概率
******************************************************************************************************************/
void NXOpen_GA_RectangularLayout::mutation(vector<vector<int>> &Population, double PM)
{
。。。。。。
}/*****************************************************************************
Function:		void		print		打印输出信息
intput,output:	double		d			排样矩形件的面积总和
input:			bool		ISEnter		是否换行
注意:下边重载函数类似
******************************************************************************/
void NXOpen_GA_RectangularLayout::print(const double &d, bool ISEnter)
{char msg[50];sprintf(msg, "%f", d);logical response = 0;UF_UI_is_listing_window_open(&response);if (!response) UF_UI_open_listing_window();UF_UI_write_listing_window(msg);if (ISEnter) UF_UI_write_listing_window("\n");
}void NXOpen_GA_RectangularLayout::print(const char * msg, bool ISEnter)
{logical response = 0;UF_UI_is_listing_window_open(&response);if (!response) UF_UI_open_listing_window();UF_UI_write_listing_window(msg);if (ISEnter) UF_UI_write_listing_window("\n");
}void NXOpen_GA_RectangularLayout::print(const int &i, bool ISEnter)
{char msg[50];sprintf(msg, "%d", i);logical response = 0;UF_UI_is_listing_window_open(&response);if (!response) UF_UI_open_listing_window();UF_UI_write_listing_window(msg);if (ISEnter) UF_UI_write_listing_window("\n");
}
3.2运行结果

基于最低水平线算法+遗传算法的NX矩形排料-CSDN直播具体运行结果看下图所示:

动图太大上传不了,这里有视频链接,大家可以查看。

3.3结果分析

        有3.2运行结果效果图可以看出,遗传算法计算的并不是最好的,只是在有限的时间内进行相对最优的求解,与第四章中的基于最低水平线搜索策略相比总是给人的很差的感觉,这里值得说明的是,本次采用的是最低水平线法,由于相较于基于最低水平线搜索策略其存在弊端,所以避免不了,下一篇我想利用基于最低水平线搜索策略+遗传算法看一看效果。当然这里所说的效果不好只是相对的,因为我主要是思路是做一款支持设置零件间距离修改,和零件与板料间距离,以及超过最大板材高度后可以自动在另一个完整的板材上进行排料,为了效果明显,我故意设置其宽度和高度,实际的应用中并不是这样差,应该可以达到80%左右。

这篇关于NX二次开发——矩形排料5(基于最低水平线+遗传算法排料策略实现)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/921919

相关文章

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

通过SSH隧道实现通过远程服务器上外网

搭建隧道 autossh -M 0 -f -D 1080 -C -N user1@remotehost##验证隧道是否生效,查看1080端口是否启动netstat -tuln | grep 1080## 测试ssh 隧道是否生效curl -x socks5h://127.0.0.1:1080 -I http://www.github.com 将autossh 设置为服务,隧道开机启动

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料 基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 📚 前言 📑摘要 📑系统流程 📚 系统架构设计 📚 数据库设计 📚 系统功能的具体实现    💬 系统登录注册 系统登录 登录界面   用户添加  💬 抗疫列表展示模块     区域信息管理 添加物资详情 抗疫物资列表展示 抗疫物资申请 抗疫物资审核 ✒️ 源码实现 💖 源码获取 😁 联系方式 📚 前言 📑博客主页:

探索蓝牙协议的奥秘:用ESP32实现高质量蓝牙音频传输

蓝牙(Bluetooth)是一种短距离无线通信技术,广泛应用于各种电子设备之间的数据传输。自1994年由爱立信公司首次提出以来,蓝牙技术已经经历了多个版本的更新和改进。本文将详细介绍蓝牙协议,并通过一个具体的项目——使用ESP32实现蓝牙音频传输,来展示蓝牙协议的实际应用及其优点。 蓝牙协议概述 蓝牙协议栈 蓝牙协议栈是蓝牙技术的核心,定义了蓝牙设备之间如何进行通信。蓝牙协议

python实现最简单循环神经网络(RNNs)

Recurrent Neural Networks(RNNs) 的模型: 上图中红色部分是输入向量。文本、单词、数据都是输入,在网络里都以向量的形式进行表示。 绿色部分是隐藏向量。是加工处理过程。 蓝色部分是输出向量。 python代码表示如下: rnn = RNN()y = rnn.step(x) # x为输入向量,y为输出向量 RNNs神经网络由神经元组成, python

利用Frp实现内网穿透(docker实现)

文章目录 1、WSL子系统配置2、腾讯云服务器安装frps2.1、创建配置文件2.2 、创建frps容器 3、WSL2子系统Centos服务器安装frpc服务3.1、安装docker3.2、创建配置文件3.3 、创建frpc容器 4、WSL2子系统Centos服务器安装nginx服务 环境配置:一台公网服务器(腾讯云)、一台笔记本电脑、WSL子系统涉及知识:docker、Frp

基于 Java 实现的智能客服聊天工具模拟场景

服务端代码 import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;public class Serv