Note
!!!大家别抄作业哦!!!
这代码结构是很糟糕的,会被发现的
Feb, 2022
==================================================================================================
本人GIS学生一枚,在课堂上听了左转算法,动手实践了下,大部分内容都来自本人实验报告。先说说左转算法原理吧!
==================================================================================================
1, 选择顶点,遵循着根据结点编号从小到大的顺序选取。
2, 选取起始边,选择方位角最小的边作为起始边,其次选取使用过一次的边作为起始边。
3, 选取后续边,若当前边的方位角不是与该结点有关边的方位角最大的边,则逆时针选取与当前边夹角最小的边作为后续边(体现左转原则),否则(即使方位角最大边),则选取方位角最小的边作为后续边。
4, 回到原点,构建一个多边形。
备注:一条边有两方向,可作为两条边使用。
==================================================================================================
其中很折腾人的一个问题是在多边形拓扑中存在岛的问题,一下是岛的检测和解决思路
1, 计算多边形面积,面积为负的是岛。并形成正多边形几何和负多边形集合。
2, 依次从正多边形集合中取出一个多边形,对应的遍历所有负多边形,如果包含(首先要负多边形面积(绝对值)小于正多边形的面积,其次,判断两个最小外界矩形是否相交,如果相交,则取负多边形上任意一点判断是否位于正多边形内部,是,则包含,否则,不包含),则将二者复合为复杂多边形,并从负多边形集合中删除该负多边形。
3, 步骤2中,若负多边形集合中个数为1时(只剩下最大的边界负多边形),则结束,或者若正多边形都遍历结束,则结束。
==================================================================================================
具体的实现流程:
1, 基于左转算法进行,左转算法具体思路详见同期实验报告9.GIS算法实验报告_多边形拓扑。.gen文件读取参考第5周的方法并稍作修改,使其能够根据用户指定输入读取文件,而无需通过修改代码实现读取不同文件的功能。下面具体描述如何将左转算法转换为计算机程序的过程。
2, 预备知识:区分节点,结点的关系。在左转算法中,节点定义为与其相关点数目有且只有两个的点,显然节点只会出现在弧端的中间,不可能存在弧端的首尾。结点则是节点的补充,定义为关联点的数目至少有三个的点。在算法中,将节点作为基类,也就是说节点包含结点,再从中筛选出结点。
3, 定义几个数据结构:点,线,面。其关系与几何中的相似。
4, 获取节点。通过读取.gen文件获取点与点之间的关系,以线段为依托。初始化节点数据结构,遍历每条线段上的每个点,并根据改点去文件中匹配,获取其前后点,也就是步骤2中所说的关联点。遍历完成后,即获得了节点信息,并通过判断节点的关联点的数量,确定哪些为结点。
5, 完善结点。通过结点的关联点搜寻其所在的弧端,知道遇到另一个结点为止。
6, 构建多边形。根据左转算法的内涵:确定选择起始点方式的优先性(方位角最小的,相反边被使用过一次的),确定选择后续边方式的优先性(若当前边为目标结点的方位角最大的边的相反边,则后续边为该结点的方位角最小的边,否则,按逆时针规则选取)。
7,岛的监测。对于到的情况,本算法不同于左转算法,是根据已建立的数据结构来监测岛存在的。在步骤4,5构建节点和结点时,对关联点只有两个的点要做进一步处理:初始化一个岛链数据结构,可理解为边,给该节点定义一个初始方向,及从该节点的两个关联点钟选择一个点作为tobuild,判断tobuild是否为节点,是则将该节点写入岛链的数据结构中,并选择tobuild的另一个节点(一个节点已处理了)作为下次判断的tobuild;若判断结果为否,销毁岛链数据结构,完成对该点的监测,不可能为岛。形成岛链的条件是,tobuild的点与岛链的起始点相匹配。
// TurnLeft.cpp : 定义控制台应用程序的入口点。
//
//点分为点,节点,结点三种:
//点具有点必须具备的位置信息(x,y),POINT
//节点是在点的基础上拓展的,附加与其相关联的点信息,可通过附加点的数量判断是否为结点,NODE
//结点是具有3个及以上的附加点的点,NODE_ARC
#include "stdafx.h"
#include "math.h"
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <gl/glut.h>
#include <vector>
#pragma comment(lib,"glut32.lib")
using namespace std;
#define Length 22
#define pi 3.1415926
//点结构体
typedef struct POINT{
double x;
double y;
}point;
//节点结构体
typedef struct NODE{
point centre;
vector<point> points;
}node;
//arc,边由首尾结点及若干各个中间节点组成组成,含方向性
typedef struct ARC{
int id; //弧端编号
vector<point> points;
bool used;
}arc;
//node-arc,结点-边的关系
typedef struct NODE_ARC{
int id; //结点编号
vector<arc> index; //根据方位角从小到大排列与结点有关的边
}node_arc;
//polygon-arc
typedef struct POLYGON_ARC{
int polygonid;
vector<arc> index; //弧端的矢量存储
}polygon_arc;
//gen struct
typedef struct VectorLine{
int id;
double **location;
}vectorline;
//传入结构体变量和存储信息的数组
double **createlocation(int n)
{
//开辟动态数组
double **location = (double **)malloc(sizeof(double*)*n);
for (int j = 0; j