等值线算法(转载)

等值线算法

对于二维的规则网格,本文以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.部分等值线图:

     

posted @ 2017-03-16 21:58  Vae永Silence  阅读(5715)  评论(2编辑  收藏  举报