相比于上一篇中介绍的求凸包算法,本次介绍的扫描线线段求交算法的实现难度明显更高,实际上最终本人也未能完美的实现该算法,下面给出的版本经测试是存在一些问题的。
首先介绍一下扫描线算法的基本原理,具体内容的讲解可以参考下面的链接:
链接: link.
实现该算法的主要障碍在于对三种不同事件点的处理:线段上端点、线段下端点、线段交点。
下面介绍一下对于这三种事件点的处理方式:
在线段上端点需要在查询树种引入一条新的线段,故此需要找到该新线段的左右邻居,并检查新插入的线段与其左右邻居是否存在交点。
在线段的下端点需要在查询树种删除一条线段,并检查被删除的线段的左右邻居是否存在交点。
在交点处,需要进行两次相交检验,并交换两条交线的次序。
以下给出我自己实现的算法:
// An highlighted block
#include <iostream>
#include <vector>
#include <string>
#include <time.h>
#include <fstream>
#include <queue>
#include <map>
using namespace std;
double ERROR = 0.0001;
struct line;
struct Point
{
double x;
double y;
struct line* belong1;
struct line* belong2;
int index;//0:上端点,1:下端点,2:交点
bool operator()(Point* P1, Point* P2)
{
return P1->y < P2->y;
}
Point(double a = 0, double b = 0, line * c = nullptr, line* d = nullptr, int ind = 0) :x(a), y(b), belong1(c), belong2(d), index(ind){
};
};
struct line
{
Point* first;
Point* second;
};
class Cutline
{
public:
Cutline();
~Cutline();
void GetRandomLine(string outfile,int num);
void FindIntersection(string outfile);
void HandleEvent(Point* event);
Point* intersec(line* L1, line* L2);
bool IsNewPoint(Point*);
private:
priority_queue<Point*, vector<Point*>, Point>P;
map<double, line*>CurCutLine;
vector<line*>Line;
vector<Point*>intersectpoint;
bool issamepoint(Point* P1, Point* P2);
};
Cutline::Cutline()
{
}
Cutline::~Cutline()
{
}
bool Cutline::issamepoint(Point* P1, Point* P2)
{
if (fabs(P1->x - P2->x) < 0.1 && fabs(P1->y - P2->y) < 0.1) return true;//x坐标和y坐标同时都很相近
return false;
}
bool Cutline::IsNewPoint(Point*)
{
return 1;
}
Point* Cutline::intersec(line* L1, line* L2)
{
//计算交点坐标
double x1 = L1->first->x;
double y1 = L1