本帖最后由 MFwxy 于 2020-7-9 06:51 编辑
遗产,估计续写不了了
Random.h#include<iostream>
#include<ctime>
#include<algorithm>
using namespace std;
class Random {
public:
Random(int a, int b);
Random();
int random();
int random(int a, int b);
double randomf(int a, int b);
private:
double random1();
int low;
int high;
};
sensor.h//#pragma once
#include<iostream>
#include<queue>
#include<Windows.h>
#include<Cstring>
using namespace std;
/*
定义sensor,行为是路由广播传输信息、采集周围环境信息,数值有广播半径、采集周期间隔
(看做整体的话还有个数)
sensor集 组织成数组,采集的数据包 用队列存储;
*/
//简易路由表。重要信息:https://blog.csdn.net/sinat_36118270/article/details/73850346
struct Lu_Youbiao
{
/*
终点的地址是255; 254作为保留。
通常的与是A电脑IP和B电脑子网掩码相与,B电脑IP与A电脑子网掩码相与。得到同一个网段就可以相通信
*/
int Network_Destination = 255;
//默认0--253;网络地址(目的地
int Netmask;
/*
默认0--253;
网络掩码(与网址计算得到目的网络地址,将某个IP地址划分成网络地址和主机地址两部分
简单来说就是用来区分子网络以及
*/
int Gateway;
/*
默认0--253;网关(途经地址
设置默认网关来将匹配错误的数据包回收
否则将直接丢弃数据
*/
int Interface;
//默认0--253;接口(到达网关的出口
int Metric;
//跃点数(高低代表到达目的地址的成本
int CC;
/*
自身地址,好像跟实际的地址有关,(可以同化成一个二维坐标来使用)暂时用整数表示坐标
int CC_x;
int CC_y;
*/
};
class sensor
{
public:
sensor(double ra = 5, double sp = 100,int i=254);
sensor(const sensor&s);
void data_collect(double data);//周期性采集,周期是span
void show();
double give();
void get(double ge);
bool is_empty();
void popout();
~sensor();
double span;//单位是ms毫秒
double x;
double y;
//位置参数,二维的,范围是屏幕之内;位置赋予方式是屏幕范围内的随机生成(想要保留一位小数的值)
double radius;//单位是m米
private:
//要在sensor里面保存路由表了,这玩意儿好像很难,那我先设置地址最多255的好了
Lu_Youbiao lyb;
//https://blog.csdn.net/zyboy2000/article/details/50528253
queue<double> databags;
//辅助生成随机数
};
Random.cpp#include<math.h>
#include<algorithm>
#include<iostream>
#include<ctime>
#include "Random.h"
Random::Random()
{
low = 0;
high = 1000;
srand((unsigned)clock());
}
Random::Random(int a, int b)
{
low = min(a, b);
high = max(a, b);
srand((unsigned)clock());
}
int Random::random(int a, int b)
{
int t = rand();
return a + t % (b - a) + 1;}
int Random::random()
{
return random(low, high);
}
double Random::random1() //0-1的随机数
{
double m = (double)random();
double n = (double)random();
if (m == 0 && n == 0)return 0;
else return (m < n) ? (m / n) : (n / m);
}
double Random::randomf(int a, int b)
{
return a + (b - a)*random1();
}
sensor.cpp//#pragma once
#include "sensor.h"
#include<iostream>
#include<stdlib.h>
#include<time.h>
#include<math.h>
#include <iomanip>
#include <windows.h>
#include"Random.h"
#define X 200
#define Y 120
using namespace std;
//#pragma comment(lib,"sensor.lib")
int hand = 0;
double xflag = 1;
double yflag = 1;
//拷贝构造
sensor::sensor(const sensor&s)
{
this->radius = s.radius;
this->span = s.span;
this->databags = s.databags;
this->x = s.x;
this->y = s.y;
this->lyb = s.lyb;
}
sensor::sensor(double ra, double sp,int i)
{
Random rdm;
radius = ra;
span = sp;
double x1;
x1 = rdm.randomf(0,X/10.0);
if (x + xflag * hand >= X)
{
//xflag=-1*rdm.randomf(0.2,0.8);
xflag = -1;
while (x >= X)
{
this->x = x1 + xflag * hand;
}
}
else if (x + xflag * hand <=0)
{
//xflag=1 * rdm.randomf(0.2, 0.8);
xflag = 1;
while (x <=0)
{
this->x = x1 + xflag * hand;
}
}
else
{
this->x = x1 + xflag * hand;
}
double y1;
y1 = rdm.randomf(0, Y/10.0);
if (0>=y+ yflag * hand)
{
//yflag = 1 * rdm.randomf(0.2, 0.8);
yflag = 1;
while (0>=y )
{
this->y = y1 + yflag * hand;
}
}
else if (y+ yflag * hand >=Y)
{
//yflag = -1 * rdm.randomf(0.2, 0.8);
yflag = -1;
while (y>=Y)
{
this->y = y1 + yflag * hand;
}
}
else
{
this->y = y1 + yflag * hand;
}
hand += int(0.8*(radius / sqrt(2)) );
cout << "x: " << x << " y: " << y << endl;
//这里实现了x,y的随机生成
/*
cout.setf(ios::fixed);
cout << fixed << setprecision(1) << x << " " << fixed << setprecision(1) << y << endl;
*/
lyb.CC = i;
}
//搜集数据
void sensor::data_collect(double data)
{
databags.push(data);
}
//展示重要数据(或参数)
void sensor::show()
{
queue<double>p;
p = databags;
while (!(p.empty()))
{
cout << p.front() << " ";
p.pop();
}
}
void sensor::get(double ge)
{
databags.push(ge);
}
double sensor::give()
{
double p = databags.front();
databags.pop();
return p;
}
bool sensor::is_empty()
{
return databags.empty();
}
void sensor::popout()
{
if(!(this->is_empty()))
databags.pop();
//cout << "\n数据弹出!" << endl;
}
sensor::~sensor()
{
}
main.cpp#include<cstdio>
#include<iostream>
#include<time.h>
#include "sensor.h"
#include<stdlib.h>
#include <windows.h>
#include<math.h>
#include <graphics.h>
#include"Random.h"
#define inf -1
#define X 1000
#define Y 600
// 极限范围是屏幕(电脑屏幕:1920×1080;控制台默认:80*25)
using namespace std;
int main()
{
/*
1要预知传感器总数目N(默认100),并且将传感器都存入一个数组当中。
如果没办法实现自定义类的数组的话就把数目作为一个内部的参数使用
采集和收集到的数据包队列要一个系统一个还是一个传感器一个呢?(作为优化可以区分一下数据来源以及数据未来去向)
*/
cout << "创建传感器基本数据(输入有效的相应半径与周期):" << endl;//八成是一样的,但是还是可以考虑优化一下
double a1, a2;
cin >> a1 >> a2;
cout << "传感器个数确定:(默认为100)" << endl;
int n_collector;
cin >> n_collector;
if (n_collector == NULL || n_collector <= 0)
{
n_collector = 100;
}
//cout << n_collector << endl;
sensor** col;
col = new sensor*[n_collector];
col[0] = new sensor(a1, a2, 0);
col[0]->x = 0;
col[0]->y = 0;
for (int i = 1; i < n_collector; i++)
{
col[i] = new sensor(a1, a2, i);
}
/****************************************************************************************************************************************************************/
/****************************************************************************************************************************************************************/
//返回的是存储好数据的队列,一个全部工作元件公用的队列,不可以轻易的销毁;
/*
周期性采集,广播范围也固定;
广播范围固定了之后,按照预定的范围先搜索可以交流的传感器
然后再考虑通过什么样的路径来让数据收集器能接收到
*/
//控制时间(来个控制采集周期运行的片段
int n_need, nd0; //一个是需求周期数,另一个是辅助用的
int aslp; //休眠用的计时
int slp = 0; //需要休眠与否0:不需要
cout << "请输入希望执行的周期总次数" << endl;
//这里输入需要执行的周期个数,优化的话可以考虑输入执行的总时间 然后经过计算得到执行的周期数
cin >> n_need;
n_need++;
nd0 = n_need + 1;
/*
疑点:
虽然使用的时候是一直执行...
但是这岂不是要用到多线程?
一直搜集数据到关闭,还要传输数据,以及终端要得到数据
考虑成优化的点吧
周期到了数据没收集全怎么办???还是说等待它磨磨蹭蹭收集完再说
*/
clock_t start, finish;
start = clock();
if (n_need > 0)
do
{
//这里按周期执行采集函数(可以考虑接口,先用随机数代替吧。)
for (int i = 0; i < n_collector; i++)
{
Random rdm;
double random_num = rdm.randomf(0,100000)/100; //用随机来模拟生成的数字,可以的话 加一下接收实际情况数据的接口
col[i]->data_collect(random_num);
finish = clock() - start;
if ((double(finish) / CLOCKS_PER_SEC - n_need * col[0]->span >= 0)) //严格检查|| (int(finish) % 1000 == 999)
{
cout << "周期结束!提前终止收集" << endl;
break;
}
else if (double(finish) / CLOCKS_PER_SEC > (nd0 - n_need)*col[0]->span)//一次全体采集没有完成一个周期是不是应该等待满一个周期
{
cout << "已完成 " << nd0 - n_need << " 个周期" << endl;
n_need--;
}
else
{
cout << "当前尚未完成周期。" << endl;
cout << double(finish) / CLOCKS_PER_SEC << " : " << (nd0 - n_need)*col[0]->span << endl;
}
}
//采集完成,休眠开始
aslp = 1000 * ((nd0 - n_need)*col[0]->span - double(finish) / CLOCKS_PER_SEC);
if (aslp > 0)
{
cout << "已完成一次采集,正在等待周期 " << nd0 - n_need << " 结束" << endl;
cout << double(finish) / CLOCKS_PER_SEC << " : " << (nd0 - n_need)*col[0]->span << endl;
cout << "休眠 " << aslp << endl;
Sleep(aslp/10); //休眠时间过长
finish += aslp;
if (int(finish) % 1000 == 999)
{
Sleep(1);
aslp++; //尊重形式
finish++;
}
cout << double(finish) / CLOCKS_PER_SEC << " : " << (nd0 - n_need)*col[0]->span << endl;
if (double(finish) / CLOCKS_PER_SEC >= (nd0 - n_need)*col[0]->span) //判定完成周期 (int(finish) % 10 == 9)
{
n_need--;
}
else
{
cout << "警告!休眠时间不足!" << endl;
cout << double(finish) / CLOCKS_PER_SEC << " : " << (nd0 - n_need)*col[0]->span << endl;
}
}
finish = clock() - start;
if (!(double(finish) / CLOCKS_PER_SEC - n_need * col[0]->span < 0)) //采集耗时检测严格程度不如等待耗时
cout << "采集结束!周期等待完成" << endl;
} while (double(finish) / CLOCKS_PER_SEC - n_need * col[0]->span < 0);
/****************************************************************************************************************************************************************/
/****************************************************************************************************************************************************************/
//cout << "与的正确用法" << endl;cout << (224 & 240) << " :" << (255 & 255) << endl;可以正式使用地址了(输入的网络地址和网络掩码相与后的结果必须等于网络地址
/*
所以应该建立一个数组,一个用自身路由表的地址寻找的数组;
这个数组要存储一个数据队列,或者甚至直接存储sensor;
数据收集器可以在数组里,也可以在外边;
路由算法默认dijkstra
*/
/*
所谓广播到:就是指两者距离小于广播半径,要让col[0]--col[n]挨个对比
默认终端收集器在(0,0)
如何路由由 Sensor 内保存的简单路由表来决定
大概分三种形式:
1.不知道连接状况直接摸黑前进;2.情况完全了解之后再考虑传输方式;3.了解和传输都随机应变
空想:
可以标明数据的来源以及目的地,就像快递那样;至于中转点怎么设置。
最简单的方法是多次实验的经验 or 把坐标靠中心的几个点和紧挨收集器的几个点设置成线路中转点
几个核心点之间形成一个干线,让其他末支的点连接到干线上就行了
*/
//嘤嘤嘤,实现了周期性还要记得广播半径也要考虑(用于路由传播交流)
//5路由方式???是什么?暂定为之前看到的迪杰斯特拉算法吧。
/*
跟路由方式息息相关的是之前得到的广播半径、位置,估计要画小地图来帮助理解
既然是人为投放的sensor,那么默认直接跟终端接收器相关的那个sensor是一定能找得到的吧。
个人理解的路由方式是 尽量高效的传输+尽量全面的搜集 吧
路由的时候还要接收其他sensor给予的数据,可能目的地和来源(可以仅考虑上一个?甚至是多个?也可能必须知道来源)
*/
/*
设计的是静态路由表(内容经现场情况决定后固定)
建立的时候从数据收集器开始往回溯源,因为数据是单向流动的(其实TCP/IP协议是需要双向的)
*/
/*
for (int i = 0; i < n_collector; i++)
{
col[i]->Lyb(n_collector);
}
*/
double **col_distance;//二维数组
col_distance = new double*[n_collector];
for (int i = 0; i < n_collector; i++)
{
col_distance[i] = new double[n_collector];
}
for (int j = 0; j < n_collector; j++)
{
for (int k = 0; k < n_collector; k++)
{
double dis;
dis = sqrt(pow((col[j]->x - col[k]->x), 2) + pow((col[j]->y - col[k]->y), 2));
if (dis > a1)
{
col_distance[j][k] = inf;
}
else
{
col_distance[j][k] = dis;
}
}
}
//到这里两传感器的距离有了。
//(0,0)是收集器最近的传感器1的位置,例子5432中能到达 2 , 3是孤立的了.输出效果是警告孤立出来的点,以及将数据按线路传送回收集器
//1.根据表格连接线路
int *road2home1 = new int[(n_collector + 1)*n_collector / 2] {0}; //num可能要加一
int n_r2h = 1;
road2home1[0] = 1;
for (int i = 0; i < n_collector; i++)
{
for (int k = i; k < n_collector; k++)
{
if (col_distance[i][k] > 0)
{
road2home1[n_r2h] = k + 1;
n_r2h++;
}
}
}
cout << "数据流向" << endl; //大概率有BUG
for (int i = 0; i < n_collector && road2home1[i] != NULL; i++)
{
if (i!=n_collector - 1 && road2home1[n_collector-1]!=0)
{
cout << road2home1[i] << " ";
}
else
{
cout << road2home1[i] << " ";
}
//可以加箭头,稍微麻烦
}
cout << endl;
//2.警示孤立的点
int *flag = new int[n_collector] {0};
int flag2 = 1;
for (int i = 0; i < n_collector; i++)
{
for (int k = 0; k < n_collector; k++)
{
if (i + 1 == road2home1[k])
{
flag2 = 0;
break;
}
}
if (flag2)
{
cout << i + 1 << "为孤立点!" << endl;
flag[i] = 1;
}
flag2 = 1;
}
//3.将数据传回收集器。到了1 直接输出就行了.
int num_r2l = 0;
for (int i = 0; i < n_collector; i++)
{
if (flag[i]) //数据无法达到的可以警示
{
cout << i + 1 << " 号信号丢失!" << endl;
}
else
{
col[0]->show(); //用输出模拟传入数据收集终端
while (!(col[0]->is_empty()))
{
col[0]->popout();
}
cout << " ---- ";
if (road2home1[i] != n_collector)
{
while (road2home1[i] > 0 && !(col[road2home1[i]]->is_empty()))
{
col[0]->get(col[road2home1[i]]->give());
}
}
cout << road2home1[i] << " 号数据到达终端!" << endl;
}
} //读数据时出错
/****************************************************************************************************************************************************************/
/****************************************************************************************************************************************************************/
//展示环节
/*
我理想的展示是
既能立刻显示出所需要的单个sensor的所有数据
也能将总的数据生成为一份excel,至少得是txt文本吧
*/
//#include "pch.h"
initgraph(X, Y); //画纸大小
//setcolor(WHITE);
cleardevice();
//这里想要把所有点画出,并且用另一种颜色画出半径
putpixel(col[0]->x, col[0]->y, WHITE);
int px, py;
for (int i = 0; i < 400; i++) {
if (i < 100) {
px = 200+col[0]->x + i;
py = col[0]->y+50;
}
else if (i < 200) {
px = 300 + col[0]->x;
py = col[0]->y + 50 + (i - 100);
}
else if (i < 300) {
px = 300 + col[0]->x - (i - 200);
py = 150+ col[0]->y;
}
else {
px = 200+col[0]->x;
py = 150+ col[0]->y - (i - 300);
}
putpixel(px, py, GREEN);
}
for (int i = 1; i < n_collector; i++)
{
//绘制点
putpixel(col[i]->x, col[i]->y, WHITE);
//绘制半径
double pi = 3.1415926;
for (int j = 0; j < 1000; j++) {
int x = col[i]->x + col[i]->radius * cos(j*pi / 500);
int y = col[i]->y + col[i]->radius * sin(j*pi / 500);
putpixel(x, y, BROWN);
}
}
for (int j = 0; j < n_collector; j++)
{
for (int k = 0; k < n_collector; k++)
{
double dis;
dis = sqrt(pow((col[j]->x - col[k]->x), 2) + pow((col[j]->y - col[k]->y), 2));
if (dis < a1 && dis>0)
{
if (!j)
setlinecolor(GREEN);
else
{
setlinecolor(YELLOW);
}
setlinestyle(PS_SOLID, 1);
line(col[j]->x, col[j]->y, col[k]->x, col[k]->y);
}
cout << "dis(" << dis << ")" << " : " << "rds(" << a1 << ")" << endl;
}
}
system("pause");
closegraph(); // 关闭绘图窗口
return 0;
}
|