卫星系统算法课程设计 - 第五部分 us多边形分割

关于us多边形分割方法。 想想这一题和上一题有什么区别,一看,发现上一题是个矩形区域(数字上的矩形,画图上的矩形,算面积用的还是微积分) 我很烦恼,这么复杂的多边形。,怎么分。 上网搜一搜地图一看,卧槽包含us本土的矩形不就是经度230-290,纬度25-50。所以就已经能分割了! 离终点还差个:给定多边形点的集合,算某一点是否在这个多边形内的算法。不会的话上百度搜就有了 将230-290,25-50自己爱咋分咋分 然后遍历分好的矩形,如果4个点都在多边形内,写入文件,我写入的是:经度 纬度 矩形的边长。 然后对于4点都不在里头的,不管。部分在里面,入栈。 然后经典的while(栈不为空)。 问题迎刃而解。

while栈不为空,取栈顶,弹出。然后一样判断四个点,如果都在,写入文件,都不在不管部分在,继续分。当然你得限制分割的最小矩形,我分的最小矩形是0.3125°

写好的文件就是组成美国的矩形的集合。在qt中声明Square* us。构造函数us=new Square[自己看文件有多少个矩形]然后和上一题一模一样,直接开始copy!

为什么用栈:四叉树,树的遍历用最多的就是深度优先吧,这里的栈就是深度优先遍历。就是便利四叉树的每个节点(如果它的父亲节点是部分在卫星内)

接下来放代码,你别管是怎么实现的,用就完事了。

vs创建个c++项目,把us多边形点的文件放进去

#include<iostream>
#include<cmath>
#include<fstream>
#include<stack>
#include<vector>
using namespace std;

double area = 0;

//方格类,把经度230 - 290 纬度25 - 50  分割为棱长为5的正方形
struct FangGe
{
	double longitude;
	double latitude;
	double realsize;
	bool isHavePoint;
	FangGe& operator=(const FangGe& p)
	{
		this->longitude = p.longitude;
		this->latitude = p.latitude;
		this->realsize = p.realsize;
		isHavePoint = p.isHavePoint;
		return *this;
	}
	FangGe()
	{
		this->longitude = 0;
		this->latitude = 0;
		this->realsize = 0;
		isHavePoint = false;
	}
	FangGe(double log, double lat, double real)
	{
		this->longitude = log;
		this->latitude = lat;
		this->realsize = real;
		isHavePoint = false;
	}
};

//5行12列
FangGe f[5][12];

bool Pnpoly(double log, double lat);


stack<FangGe> stF;//保存有点的
//stack对应使用函数


//初始化方格
void Initf()
{
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 12; j++)
		{
			f[i][j].latitude = (double)25 + (double)i * (double)5;
			f[i][j].longitude = (double)230 + (double)j * (double)5;
			f[i][j].realsize = 5;
		}
	}
	
	ofstream ofs;
	ofs.open("divide.txt");
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 12; j++)
		{
			ofs << f[i][j].longitude <<"       " << f[i][j].latitude << "       ";
		}
		ofs << endl;
	}
	ofs.close();
	
	
}


double PI = 3.141592654;
//积分公式,x0 - x1为经度,,y0 - y1是纬度
double jifen(double x0, double y0, double x1, double y1)
{
	double S = (cos(y0*PI/180) - cos(y1 * PI / 180)) * ((x1 * PI / 180) - (x0 * PI / 180));
	return S;
}

double Verx[3369];
double Very[3369];


//判断点是否在美国内
bool isCover(double log, double lat)
{
	int i, j;
	bool c = false;
	for (i = 0, j = 3369 - 1; i < 3369; j = i++)
	{
		if (((Very[i] > lat) != (Very[j] > lat)) && (log < (Verx[j] * Verx[i]) * (lat - Very[i]) / (Very[j] - Very[i]) + Verx[i]))
		{
			c = !c;
		}
	}
	return c;
}

bool isCover2(double log, double lat)
{
	int nCorss = 0;
	for (int i = 0; i < 3369; i++)
	{
		double Currentx = Verx[i], Currenty = Very[i];
		double Nextx = Verx[(i + 1) % 3369], Nexty = Very[(i + 1) % 3369];
		if (Nexty == Currenty)
		{
			continue;
		}
		if (lat < min(Currenty, Nexty))
		{
			continue;
		}
		if (lat >= max(Currenty, Nexty))
		{
			continue;
		}
		double x = (double)(lat - Currenty) * (double)(Nextx - Currentx) / (double)(Nexty - Currenty) + Currentx;
		if (x > log)
		{
			nCorss++;
		}
	}
	return (nCorss % 2 == 1);
}

int test(double log, double lat,double *x,double *y,int size)
{
	int i, j, c = 0;
	for (i = 0, j = size - 1; i < size; j = i++)
	{
		if (((y[i] > lat) != (y[j] > lat)) && (log < (x[j] * x[i]) * (lat - y[i]) / (y[j] - y[i]) + x[i]))
		{
			c = !c;
		}
	}
	return c;
}

//读入每一点的坐标值
void read()
{
	ifstream ifs;
	ifs.open("us.txt");
	if (!ifs)
	{
		cout << "读取失败" << endl;
		return;
	}
	for (int i = 0; i < 3369; i++)
	{
		ifs >> Verx[i] >> Very[i];
	}
	ifs.close();
}



void write()
{
	ofstream ofs;
	ofs.open("us.txt");
	if (!ofs)
	{
		cout << "读取失败" << endl;
		return;
	}
	for (int i = 0; i < 3369; i++)
	{
		ofs << Verx[i] << "      " << Very[i] << endl;
	}
	ofs.close();
}


//判断是否有点在方个内,判断3369个点
//方格[0][0]的坐标是的经度为230,纬度为25,其对应的范围是230 - 235, 25 - 30的方格
//该函数的目的是,将所有有点的方格进行标记。

void Judge()
{
	//简单来说就是判断是否有点在该方格内,我们找出这些方格
	//那如何分别美国中的方格和完全不在美国中的方格呢?
	//答案是我不知道,但是我可以使用肉眼观察好吧
	//判断一个点是否在方格内,用点的y坐标与方格的下方与上方判断,用点的x坐标与方格的左边与右边判断
	ofstream ofs;
	ofs.open("fangGe.txt");
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 12; j++)
		{
			//如果经度在范围内,接着判断y是否在范围内
				//经度大于等于方格的左边经度,同时又小于等于方格的右边经度
				//开始取点
			bool c1 = isCover2(f[i][j].longitude, f[i][j].latitude);
			bool c2 = isCover2(f[i][j].longitude + f[i][j].realsize, f[i][j].latitude);
			bool c3 = isCover2(f[i][j].longitude, f[i][j].latitude + f[i][j].realsize);
			bool c4 = isCover2(f[i][j].longitude + f[i][j].realsize, f[i][j].latitude + f[i][j].realsize);
			//都在内部,输出点到里面
			if (c1 && c2 && c3 && c4)
			{
				double log = f[i][j].longitude;
				double lat = f[i][j].latitude;
				double d = f[i][j].realsize / (double)2;//划分棱长
				FangGe f1(log, lat, d);
				FangGe f2(log + d, lat, d);
				FangGe f3(log, lat + d, d);
				FangGe f4(log + d, lat + d, d);
				stack<FangGe> s;
				s.push(f1);
				s.push(f2);
				s.push(f3);
				s.push(f4);
				while (!s.empty())
				{
					FangGe f = s.top();
					s.pop();
					double d = f.realsize / (double)2;
					ofs << f.longitude << "    " << f.latitude << "    " << d << endl;
					ofs << (f.longitude + d) << "    " << f.latitude << "    " << d << endl;
					ofs << f.longitude << "    " << (f.latitude + d) << "    " << d << endl;
					ofs << (f.longitude + d) << "    " << (f.latitude + d) << "    " << d << endl;
					area += jifen(f.longitude, f.latitude, f.longitude + d, f.latitude + d);
					area += jifen(f.longitude + d, f.latitude, f.longitude + d + d, f.latitude + d);
					area += jifen(f.longitude, f.latitude +d, f.longitude + d, f.latitude + d +d);
					area += jifen(f.longitude +d, f.latitude +d, f.longitude + d +d, f.latitude + d +d);
				}
				/*
				int num = 0;
				while (num < 2)
				{
					double d = f[i][j].realsize / ((double)2 * (double(num) + (double)1));//划分棱长
					if (num == 1)
					{
						ofs << f[i][j].longitude << "    " << f[i][j].latitude << "    " << d << endl;
						ofs << (f[i][j].longitude + d) << "    " << f[i][j].latitude << "    " << d << endl;
						ofs << f[i][j].longitude << "    " << (f[i][j].latitude + d) << "    " << d << endl;
						ofs << (f[i][j].longitude + d) << "    " << (f[i][j].latitude + d) << "    " << d << endl;
					}
					num++;
				}
				*/
			}
			else if (!c1 && !c2 && !c3 && !c4)
			{
				int s = 0;//不处理这里只是做个标记,方便的代码阅读
			}
			else
			{
				//说明有部分在里头,先分割,再压入栈中
				double log = f[i][j].longitude;
				double lat = f[i][j].latitude;
				double d = f[i][j].realsize / (double)2;//划分棱长
				FangGe f1(log, lat, d);
				FangGe f2(log + d, lat, d);
				FangGe f3(log, lat + d, d);
				FangGe f4(log + d, lat + d, d);
				//将这个方格进行划分
				//stF.push(f[i][j]);
				stF.push(f1);
				stF.push(f2);
				stF.push(f3);
				stF.push(f4);
			}
		}
	}
	ofs.close();
	/*
	ofstream ofs;
	ofs.open("havePoint.txt");
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 12; j++)
		{
			if (f[i][j].isHavePoint)
			{
				ofs << i << "      " << j << endl;
			}
		}
	}
	ofs.close();
	*/
}
void sidake()
{
	ofstream ofs;
	ofs.open("fangGe2.txt");
	//5 2.5 1.25  0.625 0.3125
	while (!stF.empty())
	{
		FangGe temp = stF.top();
		stF.pop();
		//将此方格判断
		bool c1 = isCover2(temp.longitude, temp.latitude);
		bool c2 = isCover2(temp.longitude + temp.realsize, temp.latitude);
		bool c3 = isCover2(temp.longitude, temp.latitude + temp.realsize);
		bool c4 = isCover2(temp.longitude + temp.realsize, temp.latitude + temp.realsize);
		//都在内部,输出点到里面
		if (c1 && c2 && c3 && c4)
		{
			if (temp.realsize > 1.25)
			{
				//说明有部分在里头,先分割,再压入栈中
				double log = temp.longitude;
				double lat = temp.latitude;
				double d = temp.realsize / (double)2;//划分棱长
				FangGe f1(log, lat, d);
				FangGe f2(log + d, lat, d);
				FangGe f3(log, lat + d, d);
				FangGe f4(log + d, lat + d, d);
				//将这个方格进行划分
				//stF.push(f[i][j]);
				stF.push(f1);
				stF.push(f2);
				stF.push(f3);
				stF.push(f4);
			}
			else
			{
				double d = temp.realsize / (double)2;//划分棱长
				ofs << temp.longitude << "    " << temp.latitude << "    " << temp.realsize << endl;
				area += jifen(temp.longitude, temp.latitude, temp.longitude + d, temp.latitude + d);
			}
			
		}
		else if (!c1 && !c2 && !c3 && !c4)
		{
			int s = 0;//不处理这里只是做个标记,方便的代码阅读
		}
		else
		{
			if (temp.realsize > 0.15625)
			{
				//说明有部分在里头,先分割,再压入栈中
				double log = temp.longitude;
				double lat = temp.latitude;
				double d = temp.realsize / (double)2;//划分棱长
				FangGe f1(log, lat, d);
				FangGe f2(log + d, lat, d);
				FangGe f3(log, lat + d, d);
				FangGe f4(log + d, lat + d, d);
				//将这个方格进行划分
				//stF.push(f[i][j]);
				stF.push(f1);
				stF.push(f2);
				stF.push(f3);
				stF.push(f4);
			}
		}
	}
}

int main()
{
	double x = jifen(75, 0, 135, 55);
	double x = jifen(0, 0, 360, 180);
    cout << x << endl;
	read();
	Initf();//初始化方格
	Judge();
	sidake();
	write();
	
	bool c = isCover2(240, 35);
	if (c)
	{
		cout << "内";
	}
	else
	{
		cout << "wai";
	}
	
	cout.precision(8);
	cout << area;
	return 0;
}

如果你们做的是其他的多边形也不要怕,方法我已经给出了,里面的isCover2就是判断点是否在多边形内部算法,自己拿去用,自己改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值