等值线算法
对于二维的规则网格,本文以104*104格点大小数据做为说明,数据下载:http://yunpan.cn/ccB7Y36eLXk35 访问密码 00c3 ,Qcloud.txt为原始数据,re01.txt为01代码
一.算法如下:
1.在该层的数据网格中求出所有四个相邻的数据点构成的正方形;
2.判断四个数据点数据与阈值之间的关系,生成01代码;
3.由上步生成的代码按照下图的关系求出等值线与四个数据点之间的拓扑关系;
4.由拓扑关系用线性插值方法求出等值线与正方形的交点;
5.顺序连接等值线段,即得到等值线。
二.源代码如下:
头文件atest.h:
#ifndef ATEST_H
#define ATEST_H
#include <QtGui/QtGui>
#include "ui_atest.h"
#include <iostream>
#include <stdlib.h>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
class ATest : public QMainWindow,public Ui_ATestClass
{
Q_OBJECT
public:
ATest(QWidget *parent = 0, Qt::WFlags flags = 0);
~ATest();
private:
QString filename;
std::vector<float> result;//存放所有矩形插值得到的位置数据
bool drawtf;
void hookupsignals();
void paintEvent(QPaintEvent *);
private slots:
void filesearch();
void getParam();
};
#endif // ATEST_H
实现文件atest.cpp:
#include "atest.h"
using namespace std;
ATest::ATest(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
setupUi(this);
hookupsignals();
drawtf=false;
}
ATest::~ATest()
{
}
//*************************************
// 时 间: 2015/7/17 10:44
// 权 限: public
// 返 回: std::vector<std::string>
// 方法说明: 将string转化成字符串数组
//*************************************
std::vector<std::string> split(std::string str,std::string pattern)
{
std::string::size_type pos;
std::vector<std::string> result;
str+=pattern;//扩展字符串以方便操作
int size=str.size();
for(int i=0; i<size; i++)
{
pos=str.find(pattern,i);
if(pos<size)
{
std::string s=str.substr(i,pos-i);
result.push_back(s);
i=pos+pattern.size()-1;
}
}
return result;
}
//*************************************
// 时 间: 2015/7/18 21:22
// 权 限: public
// 返 回: float
// 方法说明: 返回最终的插值结果
//*************************************
float execute(float yuzhi,float vmin,float vmax,float locmin,float locmax)
{
float result=(locmax-locmin)*(yuzhi-vmin)/(vmax-vmin);
return result;
}
//*************************************
// 时 间: 2015/7/17 15:00
// 权 限: public
// 返 回: vector<float>
// 方法说明: 插值函数,返回插值得到的点的坐标
//*************************************
vector<float> interpolate(vector<int> flag,vector<float> data,vector<float> locate)
{
vector<float> result;
float t;
if(flag[0]==0)
{
if(flag[1]==0)
{
if(flag[2]==0)
{
if(flag[3]==0)//0000
{
}
else//0001
{
t=execute(data[4],data[2],data[3],locate[4],locate[6]);
result.push_back(locate[5]);
result.push_back(locate[4]+t);
t=execute(data[4],data[3],data[0],locate[7],locate[1]);
result.push_back(locate[7]+t);
result.push_back(locate[6]);
}
}
else
{
if(flag[3]==0)//0010
{
t=execute(data[4],data[1],data[2],locate[3],locate[5]);
result.push_back(locate[3]+t);
result.push_back(locate[2]);
t=execute(data[4],data[2],data[3],locate[4],locate[6]);
result.push_back(locate[5]);
result.push_back(locate[4]+t);
}
else//0011
{
t=execute(data[4],data[1],data[2],locate[3],locate[5]);
result.push_back(locate[3]+t);
result.push_back(locate[2]);
t=execute(data[4],data[3],data[0],locate[7],locate[1]);
result.push_back(locate[7]+t);
result.push_back(locate[6]);
}
}
}
else
{
if(flag[2]==0)
{
if(flag[3]==0)//0100
{
t=execute(data[4],data[0],data[1],locate[0],locate[2]);
result.push_back(locate[1]);
result.push_back(locate[0]+t);
t=execute(data[4],data[1],data[2],locate[3],locate[5]);
result.push_back(locate[3]+t);
result.push_back(locate[2]);
}
else//0101
{
t=execute(data[4],data[0],data[1],locate[0],locate[2]);
result.push_back(locate[1]);
result.push_back(locate[0]+t);
t=execute(data[4],data[3],data[0],locate[7],locate[1]);
result.push_back(locate[7]+t);
result.push_back(locate[6]);
t=execute(data[4],data[1],data[2],locate[3],locate[5]);
result.push_back(locate[3]+t);
result.push_back(locate[2]);
t=execute(data[4],data[2],data[3],locate[4],locate[6]);
result.push_back(locate[5]);
result.push_back(locate[4]+t);
}
}
else
{
if(flag[3]==0)//0110
{
t=execute(data[4],data[0],data[1],locate[0],locate[2]);
result.push_back(locate[1]);
result.push_back(locate[0]+t);
t=execute(data[4],data[2],data[3],locate[4],locate[6]);
result.push_back(locate[5]);
result.push_back(locate[4]+t);
}
else//0111
{
t=execute(data[4],data[0],data[1],locate[0],locate[2]);
result.push_back(locate[1]);
result.push_back(locate[0]+t);
t=execute(data[4],data[3],data[0],locate[7],locate[1]);
result.push_back(locate[7]+t);
result.push_back(locate[6]);
}
}
}
}
else
{
if(flag[1]==0)
{
if(flag[2]==0)
{
if(flag[3]==0)//1000
{
t=execute(data[4],data[0],data[1],locate[0],locate[2]);
result.push_back(locate[1]);
result.push_back(locate[0]+t);
t=execute(data[4],data[3],data[0],locate[7],locate[1]);
result.push_back(locate[7]+t);
result.push_back(locate[6]);
}
else//1001
{
t=execute(data[4],data[0],data[1],locate[0],locate[2]);
result.push_back(locate[1]);
result.push_back(locate[0]+t);
t=execute(data[4],data[2],data[3],locate[4],locate[6]);
result.push_back(locate[5]);
result.push_back(locate[4]+t);
}
}
else
{
if(flag[3]==0)//1010
{
t=execute(data[4],data[0],data[1],locate[0],locate[2]);
result.push_back(locate[1]);
result.push_back(locate[0]+t);
t=execute(data[4],data[1],data[2],locate[3],locate[5]);
result.push_back(locate[3]+t);
result.push_back(locate[2]);
t=execute(data[4],data[2],data[3],locate[4],locate[6]);
result.push_back(locate[5]);
result.push_back(locate[4]+t);
t=execute(data[4],data[3],data[0],locate[7],locate[1]);
result.push_back(locate[7]+t);
result.push_back(locate[6]);
}
else//1011
{
t=execute(data[4],data[0],data[1],locate[0],locate[2]);
result.push_back(locate[1]);
result.push_back(locate[0]+t);
t=execute(data[4],data[1],data[2],locate[3],locate[5]);
result.push_back(locate[3]+t);
result.push_back(locate[2]);
}
}
}
else
{
if(flag[2]==0)
{
if(flag[3]==0)//1100
{
t=execute(data[4],data[1],data[2],locate[3],locate[5]);
result.push_back(locate[3]+t);
result.push_back(locate[2]);
t=execute(data[4],data[3],data[0],locate[7],locate[1]);
result.push_back(locate[7]+t);
result.push_back(locate[6]);
}
else//1101
{
t=execute(data[4],data[1],data[2],locate[3],locate[5]);
result.push_back(locate[3]+t);
result.push_back(locate[2]);
t=execute(data[4],data[2],data[3],locate[4],locate[6]);
result.push_back(locate[5]);
result.push_back(locate[4]+t);
}
}
else
{
if(flag[3]==0)//1110
{
t=execute(data[4],data[2],data[3],locate[4],locate[6]);
result.push_back(locate[5]);
result.push_back(locate[4]+t);
t=execute(data[4],data[3],data[0],locate[7],locate[1]);
result.push_back(locate[7]+t);
result.push_back(locate[6]);
}
else//1111
{
}
}
}
}
return result;
}
//*************************************
// 时 间: 2015/7/17 10:44
// 权 限: private
// 返 回: void
// 方法说明: 连接信号槽函数
//*************************************
void ATest::hookupsignals()
{
connect(btnfilesearch,SIGNAL(clicked()),this,SLOT(filesearch()));
connect(btnContour,SIGNAL(clicked()),this,SLOT(getParam()));
}
//*************************************
// 时 间: 2015/7/17 10:44
// 权 限: private
// 返 回: void
// 方法说明: 文件查找
//*************************************
void ATest::filesearch()
{
QString dir=QFileDialog::getOpenFileName(this,
tr("文件路径"),
QDir::currentPath(),
"File (*.txt)");
if (!dir.isEmpty())
{
filename=dir;
//QMessageBox::about(this,tr("通知"),tr("文件读取成功!"));
}
else
{
QMessageBox::about(this,tr("警告"),tr("文件读取失败!"));
}
fileedit->setText(filename);
}
//*************************************
// 时 间: 2015/7/16 20:24
// 权 限: private
// 返 回: void
// 方法说明: 获取参数,读取文件,数据与阈值比较,1*36*104*104
//*************************************
void ATest::getParam()
{
float yuzhi=valueedit->text().toFloat(); //读取用户指定的阈值
ifstream infiles(filename.toStdString()); //打开将要读的文件
ofstream outfile("E:/Project/Data/re01.txt"); //打开将要写的文件
string datastr; //每一行数据读取到datastr中
vector<float> data; //存放所有数据
vector<int> data01; //存放所有数据的转换后的01代码
float pervalue; //每一个数据值,用来与阈值比较
int rowindex; //控制当前读取的行数
int n=0; //读取指定行数数据
rowindex=1; //控制读取高度
while(getline(infiles,datastr))
{
if (n>104*(rowindex-1)+1) //第一行和第二行不读取
{
vector<string> result=split(datastr,"\t");
for (vector<string>::const_iterator it=result.begin()+3;it!=result.end();it++)
{
pervalue=atof((*it).c_str()); //每一行中的每一个数据
if (pervalue<yuzhi) //数据与阈值比较
{
data01.push_back(0); //小,则为0
}
else
{
data01.push_back(1); //大,则为1
}
data.push_back(pervalue); //将每个数据存储起来
}
}
if (n>104*rowindex) //超过104行结束存储,因为105行意味着高度层为2
{
break;
}
n++;
}
infiles.close();
//将01代码数据存储起来
//产生列序号
for (int i=1;i<105;i++)
{
if (i<10)
{
outfile<<i<<" ";
}
else if(i<100)
{
outfile<<i<<" ";
}
else
{
outfile<<i;
}
}
outfile<<endl;
for (int i=0;i<104;i++)
{
for (int j=0;j<104;j++)
{
n=i*104+j;
outfile<<data01[n]<<" ";
}
outfile<<endl;
}
outfile.close();
//对数据进行处理,每四个数据处理一次,即一个矩形,数据和01代码以及位置都是按照矩形逆时针方向读取
vector<int> flag(4);//每个矩形对应的四个顶点的01代码
vector<float> datav(5);//0到3存储的是四个顶点对应的数据,4存放的是阈值
vector<float> locate(8);//四个顶点对应的坐标值(x,y)
vector<float> temp;//存放每个矩形插值得到的位置数据
int index;
for (int i=0;i<103;i++)//最后一行不需要处理
{
for (int j=0;j<103;j++)//最后一列不需要处理
{
index=i*104+j;
flag[0]=data01[index];
flag[1]=data01[index+104];
flag[2]=data01[index+105];
flag[3]=data01[index+1];
datav[0]=data[index];
datav[1]=data[index+104];
datav[2]=data[index+105];
datav[3]=data[index+1];
datav[4]=yuzhi; //存放阈值
locate[0]=i;
locate[1]=j;
locate[2]=i+1;
locate[3]=j;
locate[4]=i+1;
locate[5]=j+1;
locate[6]=i;
locate[7]=j+1;
temp=interpolate(flag,datav,locate);
for (int k=0;k<temp.size();k++)
{
result.push_back(temp[k]);
}
}
}
drawtf=true; //位置数据全部获取到,接下来绘制点位置,即连接点即可
}
void ATest::paintEvent(QPaintEvent *)
{
QPainter painter(this); //this为绘图设备,即表明在该部件上进行绘制
painter.setPen(QColor(0,0,0,20));
for (int i=0;i<104;i++)//最后一行不需要处理
{
for (int j=0;j<104;j++)//最后一列不需要处理
{
painter.drawLine(QPoint(i*7+250,j*7.5+25),QPoint(i*7+250,(j+1)*7.5+25));
painter.drawLine(QPoint(i*7+250,j*7.5+25),QPoint((i+1)*7+250,j*7.5+25));
}
}
painter.setPen(QColor(255,0,0));
if (drawtf==true)
{
for (int i=0;i<result.size()-4;i+=4)//每隔4个数据,即每隔2个点,每个点对应xy值
{
painter.drawLine(result[i]*7+250, result[i+1]*7.5+25, result[i+2]*7+250, result[i+3]*7.5+25);
}
}
}
四.结果
1.部分01代码图:
2.部分等值线图: