关于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就是判断点是否在多边形内部算法,自己拿去用,自己改。