等值线算法

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

时间: 2024-10-16 21:06:03

等值线算法的相关文章

osg,vtk,ogre的区别

osg使用过一年,阅读过一部分源代码,vtk也断续使用过三四年了,ogre研究的比较深入,基本上比较熟悉它的整体结构,说说个人的看法 vtk是一个算法库,里面包括了很多挺不错的算法,如果做有限元云图,等值线,特别是医疗方面的算法,有很大的参加价值,我曾经把它的等值线算法提取出来 一个类就可以实现,主要函数就三四个,而且同时实现了云图,等值线,比网上的追踪算法要简单许多,它是一种栅格算法,国外的的维基百科有介绍,但是维基百科上的介绍和vtk的也不完全一样,虽然思路是一致的.vtk的渲染效率应该不是

等高线生成算法(转载)

等高线生成算法 输入:离散的采样点坐标和高度值(x_0,y_0,value_0),(x_1,y_1,value_1)......(x_n, y_n, value_n) 输出:等高线图,如下所示 wiki上的Marching squares算法对此有很好的说明,我也是按照wiki上面的步骤来实现这个算法的,下面对该算法的步骤进行简要说明. 输入参数: 1.点的集合(x_0,y_0,value_0),(x_1,y_1,value_1)......(x_n, y_n, value_n) ; 2.高度值

2nd Class_监督学习_线性回归算法

感谢博临天下,笔记太好,我就直接搬过来再添加了.http://www.cnblogs.com/fanyabo/p/4060498.html 一.引言 本材料参考Andrew Ng大神的机器学习课程 http://cs229.stanford.edu,以及斯坦福无监督学习UFLDL tutorial http://ufldl.stanford.edu/wiki/index.php/UFLDL_Tutorial 机器学习中的回归问题属于有监督学习的范畴.回归问题的目标是给定D维输入变量x,并且每一个

图像数据到网格数据-1——MarchingCubes算法

原文:http://blog.csdn.net/u013339596/article/details/19167907 概述 之前的博文已经完整的介绍了三维图像数据和三角形网格数据.在实际应用中,利用遥感硬件或者各种探测仪器,可以获得表征现实世界中物体的三维图像.比如利用CT机扫描人体得到人体断层扫描图像,就是一个表征人体内部组织器官形状的一个三维图像.其中的感兴趣的组织器官通过体素的颜色和背景加以区别.如下图的人体足骨扫描图像.医生通过观察这样的图像可以分析病人足骨的特征,从而对症下药. 这类

WebGIS中等值线前端生成绘制简析

文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 等值线是GIS制图中常见的功能,一般有两种思路:一种是先进行插值生成等值面栅格图,然后将等值面提取成等值线:另一种是进行插值后,直接再根据算法进行插值点连接生成一条尽量闭合以及平滑的曲线. 在进行插值中,有很多算法可以选择,各种算法中也会有不同的参数需要调试,并且更具实际情况,比如地理环境因素等进行微调,最后建模.这里我们要讨论的是忽略一切外在因素,只根据坐标

经典排序算法 - 冒泡排序Bubble sort

 原文出自于 http://www.cnblogs.com/kkun/archive/2011/11/23/bubble_sort.html 经典排序算法 - 冒泡排序Bubble sort 原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, 这样一趟过去后,最大或最小的数字被交换到了最后一位, 然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子 例子为从小到大排序, 原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 | 第一趟排序(外循环) 第

转载:DenseNet算法详解

原文连接:http://blog.csdn.net/u014380165/article/details/75142664 参考连接:http://blog.csdn.net/u012938704/article/details/53468483 本文这里仅当学习笔记使用,具体细节建议前往原文细度. 论文:Densely Connected Convolutional Networks 论文链接:https://arxiv.org/pdf/1608.06993.pdf 代码的github链接:h

基于位置信息的聚类算法介绍及模型选择

百度百科 聚类:将物理或抽象对象的集合分成由类似的对象组成的多个类的过程被称为聚类.由聚类所生成的簇是一组数据对象的集合,这些对象与同一个簇中的对象彼此相似,与其他簇中的对象相异."物以类聚,人以群分",在自然科学和社会科学中,存在着大量的分类问题.聚类分析又称群分析,它是研究(样品或指标)分类问题的一种统计分析方法.聚类分析起源于分类学,但是聚类不等于分类.聚类与分类的不同在于,聚类所要求划分的类是未知的. 分类和聚类算法一直以来都是数据挖掘,机器学习领域的热门课题,因此产生了众多的

密码算法详解——AES

0 AES简介 美国国家标准技术研究所在2001年发布了高级加密标准(AES).AES是一个对称分组密码算法,旨在取代DES成为广泛使用的标准. 根据使用的密码长度,AES最常见的有3种方案,用以适应不同的场景要求,分别是AES-128.AES-192和AES-256.本文主要对AES-128进行介绍,另外两种的思路基本一样,只是轮数会适当增加. 1 算法流程 AES加解密的流程图如下: AES加密过程涉及到4种操作:字节替代(SubBytes).行移位(ShiftRows).列混淆(MixCo