【计算几何02】Bentley Ottmann 的线段交点算法

12 篇文章 3 订阅
订阅专栏

Line Intersection using Bentley Ottmann Algorithm Tutorials & Notes | Math | HackerEarth

目录

一、说明

二、问题描述

2.1 直线段限定在水平和垂直

2.2 将问题复杂化线条不垂直的交点

三、相关实验代码

四、测试代码说明

五、python包

5.1 安装  Developer

5.2 测试代码


一、说明

        在计算几何中,Bentley-Ottmann 算法是一种扫描线算法,用于列出一组线段中的所有交叉点,即它找到线段的交点(或简称为交点)。它扩展了 Shamos–Hoey 算法。用于测试一组线段是否有任何交叉点。对于包含的输入n 个线段与,k 个交叉点(或交叉路口),Bentley–Ottmann 算法需要时间 O(  (N+k)log⁡N )

二、问题描述

        给定一组 N 条线段(2*N 点),你需要找到这些线段之间的所有交点。
        也许,您首先想到的是一种天真的方法来检查所有线段对是否相交。但是你知道这不是一个好方法,因为如果我们的交叉点较少,它会包含不必要的计算。其次,它会以未排序的顺序给出交叉点。所以,我们需要一些替代方法来解决这个问题。

2.1 直线段限定在水平和垂直

        我们可以使用线扫描技术解决这个问题。但是在解决这个问题之前,首先让我们只考虑水平和垂直线段。

        问题:给定N条水平线段和垂直线段,我们需要找到水平线段和垂直线段的所有交点。在这里,我们不会考虑重合的端点相交。
        方法:继续我们的事件和活动集的概念,让我们首先为这个问题定义它们。在这里,我们将考虑三种类型的事件:水平线段的开始、水平线段的结束和垂直线段。我们的活动集包含所有被扫描线切割的水平线段(按 y 坐标排序)。

        虚线是扫描线,黑线是给定的水平线和垂直线,红线是任意时刻与扫描线相交的水平线。
我们的算法如下:
        1. 当我们击中水平线段的起点时,我们将线(在我们的实现中,我们将插入起点)插入到我们的集合中。
        2. 当我们击中水平线段的终点时,我们从集合中移除线段(实现中线段的起点)。
        3. 当我们碰到一条垂直线时,我们检查集合中位于垂直线段起始和结束 y 坐标之间的所有线段,即,如果垂直线段由 (x1,y1) 和 (x1) 表示,y2), 我们检查位于 (y1,y2) 范围内的水平线段。
这就完成了我们的算法。那么,让我们跳到实现部分:

#define x second
#define y first
typedef pair<int,int >point;
struct event 
{
    point p1,p2;
    int type;
    event() {};
    event(point p1,point p2, int type) : p1(p1), p2(p2),type(type) {};  //initialization of event
};
int n,e;
event events[MAX];
bool compare(event a, event b) 
{ 
    return a.p1.x<b.p1.x; 
}
set<point >s;
void hv_intersection()
{
    for (int i=0;i<e;++i)
        {
                event c = events[i];
                if (c.type==0) s.insert(c.p1);//insert starting point of line segment into set
                else if (c.type==1) s.erase(c.p2);//remove starting point of line segment from set, equivalent to removing line segment
                else
                {
                        for (typeof(s.begin()) it=s.lower_bound(make_pair(c.p1.y,-1));it!=s.end() && it->y<=c.p2.y; it++) // Range search
                                printf("%d, %d\n", events[i].p1.x, it->y);//intersections
                }
        }
}
int main () 
{
    scanf("%d", &n);
    int p1x,p1y,p2x,p2y;
        for (int i=0;i<n;++i) 
        {
                scanf("%d %d %d %d", &p1x, &p1y,&p2x, &p2y);
        if(p1x==p2x)                //if vertical line, one event with type=2
        {
            events[e++]=event(make_pair(p1y,p1x),make_pair(p2y,p2x),2);
        }
        else                    //if horizontal line, two events one for starting point and one for ending point
        {
            //store both starting points and ending points
            events[e++]=event(make_pair(p1y,p1x),make_pair(p2y,p2x),0);
            //store both ending and starting points, note the order in the second, this is because we sort on p1, so ending points first, then we remove a line when we hit its ending point , so we need its starting point for removal of line
            events[e++]=event(make_pair(p2y,p2x),make_pair(p1y,p1x),1);
        }
        }
    sort(events, events+e,compare);//on x coordinate
    hv_intersection();
    return 0;
}

        复杂度分析:所有对事件的操作(insert,erase, lower_bound)都需要O(log(N))
时间,内循环运行 k 次,其中 k 是交叉点的数量。因此,上述算法的复杂度为O(Nlog(N)+k)
所以,下一个想到的问题是如果 k 是O(N*2),所以在那种情况下我们的算法运行缓慢。这是对的,但想想如果我们有路口,然后我们得到相当大的加速。其次,如果我们只需要交叉点的数量而不是交叉点本身会怎么样。然后我们可以找到交叉点的数量使用二叉树结构的时间(通过将子树的大小存储在子树的根中)。

2.2 将问题复杂化线条不垂直的交点

        让我们回到我们的问题,线条不一定是垂直或水平的。在那种情况下该怎么办?

       A: 首先,让我们列出算法中的假设:
        1.没有垂直线段。
        2. 没有两条线段在它们的端点处相交。
        3. 没有三个(或更多)路段有共同的交叉点。
        4.线段的所有端点和所有交点具有不同的x坐标。
        5. 没有两个段重叠。

      B :主要相交性判别原理:
        1. 两条线相交,它们必须彼此相邻。因此,我们将只检查相邻线是否相交。
        2. 当两条线段相交时,它们改变位置,即相交前在下方的线在上方,另一条线在下方。

      C在开始算法之前,首先让我们定义事件和活动集

        扫描线算法的Events

        事件:线段的端点、交点。(我们会在找到它们时插入交点)。在这里,我们将使用优先级队列作为我们的数据结构,因为由于交叉点的动态插入和删除,预排序将不起作用。让我们用 PQ 表示优先级队列

        扫描线算法的Active Set

        在任何时候,活动集都包含被扫描线切割的线段,按 y 坐标排序。让我们用 SL 表示这个活动集。伪代码:

   Initialize PQ = all segment endpoints;
    Initialize SL to be empty;
    Initialize output intersection list IL to be empty;

    While (PQ is nonempty) {
        Let E = the next event from PQ;
        If (E is a left endpoint) {
            Let segE = segment of E;
            Add segE to SL;
            Let segA = the segment Above segE in SL;
            Let segB = the segment Below segE in SL;
            If (I = Intersect( segB with segA) exists) 
                Delete I from PQ;
            If (I = Intersect( segE with segA) exists) 
                Insert I into PQ;
            If (I = Intersect( segE with segB) exists) 
                Insert I into PQ;
        }
        Else If (E is a right endpoint) {
            Let segE = segment of E;
            Let segA = the segment Above segE in SL;
            Let segB = the segment Below segE in SL;
            Delete segE from SL;
            If (I = Intersect( segA with segB) exists)  
                    Insert I into PQ;
        }
        Else {  // E is an intersection event
            Add intersect point of E to the output list IL;
            Let segE1 above segE2 be intersecting segments of E in SL;
            Swap their positions so that segE2 is now above segE1;
            Let segA = the segment above segE2 in SL;
            Let segB = the segment below segE1 in SL;
            If (I = Intersect( segE1 with segA) exists) 
                Delete I from PQ;
            If (I = Intersect( segE2 with segB) exists) 
                Delete I from PQ;
            If (I = Intersect(segE2 with segA) exists)
                    Insert I into PQ;
            If (I = Intersect(segE1 with segB) exists) 
                    Insert I into PQ;
        }
        remove E from PQ;
    }
    return IL;
}

        那是 Bentley Ottmann 算法,用于在给定 N 条线段时找到所有交叉点。让我们看一下图像以更好地理解它。

 算法详解:

      1)输入线段:( P(x,y),P1(x,y))循环输入全部线段用PP1表示。

      2)对所有的线段端点(包括P和P1)按照x坐标排序,上图排序结果是:

         PQ =   【 A,B,C,D,B1,D1,A1,C1】

      3)我们提取 PQ 中的最小值并将其作为我们的事件。所以,我们知道这个事件可能是左端点、右端点或交点。如图:扫描线对PQ扫描,扫到A

         A进入队列,(A是第一个点) 

        List = 【A】                  表示唯一线段是A为起始点。

  • 1  扫描线继续扫描PQ,找到B,比较A与扫描线交点W和B的y坐标,y(Wa)>y(B),表明A线段在B点上方,所以:

        List = 【A,B】

  • 2  继续扫描PQ序列,读出C点,因为y(C)<y(Wb)<y(Wa),因此,C线段在最下方,

        List = 【A,B,C】

  • 3 继续扫描PQ序列,读出D点,此时,扫描线对应的交点按照y排序是是Wa,Wc,Wb,D

所以: List = 【A,C,B,D】 

        可以观察到,线序从【A,B,C】跳转到 List = 【A,C,B,D】 其中B和C产生一个逆序,因此,B和C有一个交点。(求出该交点保存)

  • 4 继续扫描,看到B1点,因为B1点是个后端点,所以删除与之相对应的线段B:于是

List = 【A,C, D】

  • 5 继续扫描,看到D1点,因为D1点是个后端点,所以删除与之相对应的线段D:计算扫描交点顺序:    y(Wc) >y(Wa) 

        List = 【C,A】这里产生一个逆序,所以A和C两个线段必然相交,求出交点并保存。

  • 6 继续扫描,看到A1点,因为A1点是个后端点,所以删除与之相对应的线段:计算扫描交点顺序:  Wc > Wa 

        List = 【C 】 。

  • 7 继续扫描,看到C1点,因为C1点是个后端点,所以删除与之相对应的线段:List = 【  】 。

        算法结束。

三、相关实验代码

# lsi.py
# Implementation of the Bentley-Ottmann algorithm, described in deBerg et al, ch. 2.
# See README for more information.
# Author: Sam Lichtenberg
# Email: splichte@princeton.edu
# Date: 09/02/2013 

from Q import Q
from T import T
from helper import *

# "close enough" for floating point
ev = 0.00000001

# how much lower to get the x of a segment, to determine which of a set of segments is the farthest right/left
lower_check = 100

# gets the point on a segment at a lower y value.
def getNextPoint(p, seg, y_lower):
	p1 = seg[0]
	p2 = seg[1]
	if (p1[0]-p2[0])==0:
		return (p[0]+10, p[1])
	slope = float(p1[1]-p2[1])/(p1[0]-p2[0])
	if slope==0:
		return (p1[0], p[1]-y_lower)
	y = p[1]-y_lower
	x = p1[0]-(p1[1]-y)/slope
	return (x, y)

"""
for each event point:
	U_p = segments that have p as an upper endpoint
	C_p = segments that contain p
	L_p = segments that have p as a lower endpoint
"""
def handle_event_point(p, segs, q, t, intersections):
	rightmost = (float("-inf"), 0)
	rightmost_seg = None
	leftmost = (float("inf"), 0) 
	leftmost_seg = None

	U_p = segs
	(C_p, L_p) = t.contain_p(p)
	merge_all = U_p+C_p+L_p
	if len(merge_all) > 1:
		intersections[p] = []
		for s in merge_all:
			intersections[p].append(s) 
	merge_CL = C_p+L_p
	merge_UC = U_p+C_p
	for s in merge_CL:
		# deletes at a point slightly above (to break ties) - where seg is located in tree
		# above intersection point
		t.delete(p, s)
	# put segments into T based on where they are at y-val just below p[1]
	for s in merge_UC:
		n = getNextPoint(p, s, lower_check) 
		if n[0] > rightmost[0]:
			rightmost = n 
			rightmost_seg = s
		if n[0] < leftmost[0]:
			leftmost = n
			leftmost_seg = s
		t.insert(p, s)

	# means only L_p -> check newly-neighbored segments
	if len(merge_UC) == 0:
		neighbors = (t.get_left_neighbor(p), t.get_right_neighbor(p))
		if neighbors[0] and neighbors[1]:
			find_new_event(neighbors[0].value, neighbors[1].value, p, q)
			
	# of newly inserted pts, find possible intersections to left and right
	else:
		left_neighbor = t.get_left_neighbor(p)
		if left_neighbor:
			find_new_event(left_neighbor.value, leftmost_seg, p, q)
		right_neighbor = t.get_right_neighbor(p)
		if right_neighbor:
			find_new_event(right_neighbor.value, rightmost_seg, p, q)

def find_new_event(s1, s2, p, q):
	i = intersect(s1, s2)
	if i:
		if compare_by_y(i, p) == 1:
			if not q.find(i):
				q.insert(i, [])
	
# segment is in ((x, y), (x, y)) form
# first pt in a segment should have higher y-val - this is handled in function
def intersection(S):
	s0 = S[0]
	if s0[1][1] > s0[0][1]:
		s0 = (s0[1], s0[0])
	q = Q(s0[0], [s0])
	q.insert(s0[1], [])
	intersections = {}
	for s in S[1:]:
		if s[1][1] > s[0][1]:
			s = (s[1], s[0])
		q.insert(s[0], [s])
		q.insert(s[1], [])
	t = T()
	while q.key:
		p, segs = q.get_and_del_min()
		handle_event_point(p, segs, q, t, intersections)
	return intersections

# Test.py
# Test file for lsi.
# Author: Sam Lichtenberg
# Email: splichte@princeton.edu
# Date: 09/02/2013

from lsi import intersection
import random
import time, sys
from helper import *

ev = 0.00000001

def scale(i):
	return float(i)

use_file = None
try:
	use_file = sys.argv[2]
except:
	pass

if not use_file:
	S = [] 
	for i in range(int(sys.argv[1])):
		p1 = (scale(random.randint(0, 1000)), scale(random.randint(0, 1000)))
		p2 = (scale(random.randint(0, 1000)), scale(random.randint(0, 1000)))
		s = (p1, p2)
		S.append(s)
	f = open('input', 'w')
	f.write(str(S))
	f.close()

else:
	f = open(sys.argv[2], 'r')
	S = eval(f.read())

intersections = []
seen = []
vs = False
hs = False
es = False
now = time.time()
for seg1 in S:
	if approx_equal(seg1[0][0], seg1[1][0], ev):
		print 'VERTICAL SEG'
		print ''
		print ''
		vs = True
	if approx_equal(seg1[0][1], seg1[1][1], ev):
		print 'HORIZONTAL SEG'
		print ''
		print ''
		hs = True
	for seg2 in S:
		if seg1 is not seg2 and segs_equal(seg1, seg2):
			print 'EQUAL SEGS'
			print ''
			print ''
			es = True
		if seg1 is not seg2 and (seg2, seg1) not in seen:
			i = intersect(seg1, seg2)
			if i:
				intersections.append((i, [seg1, seg2]))
		#		xpts = [seg1[0][0], seg1[1][0], seg2[0][0], seg2[1][0]]
		#		xpts = sorted(xpts)
		#		if (i[0] <= xpts[2] and i[0] >= xpts[1]:
		#			intersections.append((i, [seg1, seg2]))
				seen.append((seg1, seg2))
later = time.time()
n2time = later-now
print "Line sweep results:"
now = time.time()
lsinters = intersection(S)
inters = []
for k, v in lsinters.iteritems():
	#print '{0}: {1}'.format(k, v)
	inters.append(k)
#	inters.append(v)
later = time.time()
print 'TIME ELAPSED: {0}'.format(later-now)
print "N^2 comparison results:"
pts_seen = []
highestseen = 0
for i in intersections:
	seen_already = False
	seen = 0
	for p in pts_seen:
		if approx_equal(i[0][0], p[0], ev) and approx_equal(i[0][1], p[1], ev):
			seen += 1
			seen_already = True
	if seen > highestseen:
		highestseen = seen
	if not seen_already:
		pts_seen.append(i[0])
	in_k = False
	for k in inters:
		if approx_equal(k[0], i[0][0], ev) and approx_equal(k[1], i[0][1], ev):
			in_k = True
	if in_k == False:
		print 'Not in K: {0}: {1}'.format(i[0], i[1])
#	print i
print highestseen
print 'TIME ELAPSED: {0}'.format(n2time)
#print 'Missing from line sweep but in N^2:'
#for i in seen:
#	matched = False
print len(lsinters)
print len(pts_seen)
if len(lsinters) != len(pts_seen):
	print 'uh oh!'

四、测试代码说明

for more information.

Usage:

from lsi import intersection

# S is a list of tuples of the form: ((x,y), (x,y))
i = intersection(S)

This function returns a dictionary of intersection points (keys) and a list of their associated segments (values).


Currently, this implementation does not handle horizontal/vertical line segments. This will be changed shortly!

A test file is available. It compares the running time of the algorithm to that of a brute-force O(N^2) comparison. It also generates a specified number of random input segments--you can set the precision and range by editing the file.

Email at: splichte@princeton.edu

五、关于使用python包

5.1 安装

python -m pip install --upgrade bentley_ottmann

5.2 最新开发包安装

1、从 GitHub 存储库下载最新版本

git clone https://github.com/lycantropos/bentley_ottmann.git
cd bentley_ottmann

2、安装依赖包

python -m pip install -r requirements.txt

3、正式安装

python setup.py install

5.3 测试代码

Usage
With segments

>>> from ground.base import get_context
>>> context = get_context()
>>> Point, Segment = context.point_cls, context.segment_cls
>>> unit_segments = [Segment(Point(0, 0), Point(1, 0)), 
...                  Segment(Point(0, 0), Point(0, 1))]
we can check if they intersect

>>> from bentley_ottmann.planar import segments_intersect
>>> segments_intersect(unit_segments)
True
With contours

>>> Contour = context.contour_cls
>>> triangle = Contour([Point(0, 0), Point(1, 0), Point(0, 1)])
>>> degenerate_triangle = Contour([Point(0, 0), Point(2, 0), Point(1, 0)])
we can check if they are self-intersecting or not

>>> from bentley_ottmann.planar import contour_self_intersects
>>> contour_self_intersects(triangle)
False
>>> contour_self_intersects(degenerate_triangle)
True

多边形之间相交求交点算法_计算几何-线段集的所有交点
weixin_39779528的博客
12-06 1178
问题描述给定N条线段,计算这些线段彼此之间的所有交点Bentley Ottmann Algorithm算法的前提假设:a) 不存在两条线段的终点和交点有相同的x坐标;b) 不存在多于两条的线段相交于一点;c) 不存在两条线段完全相互重叠;关键的观察结论:a) 两条相交的线段必然是相邻近的;b) 两条线段相交后,会交换位置,在上面的线段在经过交点后,会到另一条线段的下面;扫描线算法的Events所...
计算几何——n条线段求交Bentley-Ottmann算法可视化实现
derbi123123的博客
06-04 4814
算法原理:我们对所有左右端点进行X坐标的排序,放入priority queue(优先队列)结构的事件队列中, 每个端点的结构体: 每个
bentley_ottmann:搜索线段和多边形边缘相交(正确的Bentley-Ottmann和Shamos-Huey算法实现)
03-26
bentley_ottmann 在下面的内容中, python是python3.5或pypy3.5或任何更高版本( python3.6 , pypy3.6等等)的别名。 安装 安装最新的pip和setuptools软件包版本 python -m pip install --upgrade pip setuptools 用户 从PyPI存储库下载并安装最新的稳定版本: python -m pip install --upgrade bentley_ottmann 开发者 从GitHub存储库下载最新版本 git clone https://github.com/lycantropos/bentley_ottmann.git cd bentley_ottmann 安装依赖项 python -m pip install --force-reinstall -r requirements.t
计算几何——线段求交
yfdyyy的专栏
11-21 1709
计算几何线段求交 数据结构:AVLTree 方法:扫描线法
Bentley-Ottmann算法:求N条线段交点
weixin_45716328的博客
08-19 2437
使用Bentley-Ottmann算法,求N条线段交点Bentley-Ottmann算法案例,Bentley-Ottmann算法例子,Bentley-Ottmann算法流程
SegmentIntersections.jl:用Julia编写的Bentley-Ottmann算法的实现
03-26
SegmentIntersections.jl 该程序包实现了两种算法,用于计算一组有限线段之间的交点。 蛮力算法,其中测试每个段与所有其他段的相交。 因此,该算法的缩放比例为O(N ^ 2)。 对于许多点应该可以更好地扩展。 但是,在许多情况下,蛮力表现更好。 这也可能是因为BO算法需要一些内存优化。 完整的K图的交点需要调试,可能是公差误差。 局限性 该算法完全忽略水平和垂直线段。 将来可能会实施。
线段相交算法——平面扫描
Avan_Lau的专栏
09-03 1万+
在老外网站看到的完整介绍,很详细,原文链接:http://geomalgorithms.com/a09-_intersect-3.html Sometimes an application needs to find the set of intersection points for a collection of many line segments. Often these appli
几何求交(一):直线和直线的交点
主要研究图形学相关领域
06-08 6338
几何求交:直线和直线的交点
1016 - 计算几何之直线与线段的交 - Segments(POJ 3304)
Faithfully-xly的博客
10-16 130
传送门   题意 虽然题目是给了什么投影啊,什么奇奇怪怪的东西 但实际上也就是给你 n 条线段,询问是否存在一条直线能经过所有的线段 数据范围:n&lt;=100   分析 这个数据范围有点友好啊…… 我们先来想一个问题 若存在一条直线使其能穿过所有的线段,那我们一定可以将这条线段进行一定角度的旋转,然后使其恰好被卡在某两条线段的端点之间 也就是说若我们能够找到被某两个线段端...
计算机图形学-X扫描线
qq_43535469的博客
06-10 1933
什么是X扫描线算法 用一条扫描线穿过多边形 计算扫描线与多边形的相交区间 再用要求的颜色显示这些区间的像素 完成填充工作 解决共享顶点问题 原则: 若共享顶点的两条边分别落在扫描线的两边 交点只算一个 若共享顶点的两遍在扫描线的同一边 交点算作0个或者2个 如上图 如果 检查共享顶点两条边的另外两个端点的y值 例如图中y=7处的蓝线 共享顶点另外两条边的端点分别是1和12 一个在共享顶点上面一个在下面 这个点就算一个 例如y=5处的蓝线 共享顶点的另外两条边的端点分别是1和1 这该交点算作零个 y=1的应
Algorithm-bentley-ottmann.zip
09-17
Algorithm-bentley-ottmann.zip,简单的Java实现宾利OTMMN扫描线算法列出一组线段中的所有交叉点,算法是为计算机程序高效、彻底地完成任务而创建的一组详细的准则。
bentley-ottman:Bentley-Ottman扫行算法在js中的实现
05-06
本特利-奥特曼扫斗绳 这是适用于Node.js和浏览器的Bentley-Ottman掠过线算法实现。 它找到一组2D线段中的所有交点,在内部使用平衡的avl树。 var findIntersections = require ( 'bentley-ottman-sweepline' ) ; var segments = [ [ [ 0 , 1 ] , [ 3 , 1 ] ] , [ [ 2 , 0 ] , [ 2 , 2 ] ] ] console . log ( findIntersections ( segments ) ) ; 细分可追溯性 JavaScript中提供了该算法的几种实现方式,请参见。 这既不是最快的,也不是最可靠的(众所周知,它会因多个笛卡尔相交而失败;这显然可以通过一点点TLC来解决)。 综上所述,该特定实现是唯一提供段可追溯性的实现。 也就是说,您
Bentley_Ottman_Algorithm:Bentley Ottman算法
05-03
描述Bentley Ottman算法src.applet Java小程序src.sample Java应用程序参考
isect_segments-bentley_ottmann:BentleyOttmann扫掠线实现(用于查找一组线段中的所有交点
05-14
这是Bentley-Ottmann扫掠线算法的单文件Python3实现,用于列出一组线段中的所有交点。 它旨在可移植且自成一体(移至其他较低级的语言,如C&C ++)。 测试用例显示了来自14,880个路段的所有73,002个交叉点。 动机...
扫描线算法-求线段交点数量
chivalry
09-19 7776
将所有线段的左右端点以X坐标升序放入顶点优先队列中,然后初始化扫描线链表(查找二叉树) 依次取出顶点优先队列中的点, 1 左端点:将其线段插入到扫描线链表中,按照y的升序排列链表,找到在此线段上面相邻和下面相邻的线段,并依次计算此线段与其上面线段交点,和此线段与其下面线段交点,如果有交点,并且顶点队列中没有出现过,插入到顶点优先队列中; 2 右端点:将其线段从扫描线队列中删除,计算此线段
计算几何学:线段求交扫描线算法(改进版)
weixin_44800504的博客
07-10 1812
在上一篇博客中我初步实现了扫描线求交算法,但是经检验,法线存在不少的交点是不能够被检测到的。本周我对于上一篇博客中实现的算法进行了详细的分析,找到了算法失效的原因,并实现了改进版,在新的改进版中没有致命的逻辑错误,但是因为我使用的是浮点数,并且在处理过程中引入了一些误差,在某些非常特殊的情况下,算法可能会失效,但在大部分情况下算法都是能准确的找出交点的。 首先分析以下上一篇博客中实现的算法失效原因进行分析: 该扫描线算法需要两个数据结构:优先队列和搜索树。搜索树中储存目前和扫描线相交的所有线段,并且这些线段
计算几何-求线段交点算法和代码(C++语言)
热门推荐
wei的专栏
06-08 1万+
原文地址:计算几何-求线段交点算法和代码(C++语言) 问题描述:已知两条线段P1P2和Q1Q2,判断P1P2和Q1Q2是否相交,若相交,求出交点。 两条线段的位置关系可以分为三类:有重合部分、无重合部分但有交点、无交点算法核心 算法的步骤如下: 1.快速排斥实验。 设以线段P1P2为对角线的矩形为R,设以线段Q1Q2为对角线的矩形为T,如果R和T不相交,则两线段不相交。 所...
线段交点"的几种算法(js实现,完整版)
诸葛苍穹
07-18 9864
“求线段交点”是一种非常基础的几何计算, 在很多游戏中都会被使用到. 下面我就现学现卖的把最近才学会的一些”求线段交点”的算法说一说, 希望对大家有所帮助. 本文讲的内容都很初级, 主要是面向和我一样的初学者, 所以请各位算法帝们轻拍啊 嘎嘎 引用 已知线段1(a,b) 和线段2(c,d) ,其中a b c d为端点, 求线段交点p .(平行或共线视作不相交)算法一: 求两条线段所在直线的
N条线段求交的扫描线算法
lihaidong的博客
03-06 3801
转载自:http://johnhany.net/2013/11/sweep-algorithm-for-segments-intersection/ N条线段求交的扫描线算法 在对图进行计算时,很常用的一个操作就是求若干条线段交点,比如对图的叠加、截窗,需要频繁地计算线段交点,如果求交算法效率很低,上层的算法再优秀也表现不出好的性能。 先考虑一个很简单...
bentley-ottmann和扫描线算法
最新发布
10-27
Bentley-Ottmann算法和扫描线算法都是计算机科学领域中的几何算法,主要用于解决平面上的几何问题。 Bentley-Ottmann算法是一种用于求解线段交点问题的算法。它使用了扫描线的概念,通过扫描线从上到下遍历平面上的线段,并将其投影到水平的事件点序列上。在扫描线的过程中,通过维护一个有序的事件点集合以及一个有序的线段交点集合来找到所有的线段交点。该算法的时间复杂度为O((n+k) log n),其中n为线段的数量,k为交点的数量。 扫描线算法是一种通过扫描线的方式来解决一些几何问题的算法。其基本思想是将平面划分为许多水平的扫描线,并在每条扫描线上进行计算。算法从上到下按扫描线依次处理每个图形对象,记录下与当前扫描线相交的图形边界,并根据需要更新一些数据结构来保存相关信息。在处理完所有图形对象后,可以得到所需要的结果。扫描线算法主要应用于计算几何、计算机图形学等领域中的问题,例如求解多边形交集、寻找包含某一点的图形等。由于其简洁高效的特点,扫描线算法在计算机图形学中的应用非常广泛。 综上所述,Bentley-Ottmann算法和扫描线算法都是用于解决平面上几何问题的算法Bentley-Ottmann算法主要用于求解线段交点问题,而扫描线算法适用于处理一些特定的几何问题。这两种算法都是在计算几何和计算机图形学等领域中非常有用的工具。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • Ubuntu系统如何连接WiFi 84269
  • Ubuntu知识: 文件压缩和解压?(zip指令) 60866
  • 【机器学习】了解 AUC - ROC 曲线 34216
  • halcon知识:常见三种模板匹配方法总结 32656
  • 【Python知识】可视化函数plt.scatter 29327

分类专栏

  • AI原理和python实现 付费 125篇
  • 3D图形渲染和OpenGL编程 付费 61篇
  • ROS1和ROS2高级编程 付费 213篇
  • Halcon高级应用 付费 44篇
  • Halcon中级实践 付费 44篇
  • NLP到ChatGPT专题 付费 205篇
  • 时间序列和数据分析 付费 69篇
  • Pytorch和深度学习 付费 40篇
  • 深度学习专栏 付费 146篇
  • 数学建模 付费 49篇
  • BOOST C++ 付费 126篇
  • 强化学习和对抗网络 付费 50篇
  • 人工智能综合 付费 676篇
  • 数字图形和图像处理 付费 43篇
  • 扩散模型 6篇
  • 博弈论 2篇
  • OpenGL和3D游戏渲染 31篇
  • 人工智能 184篇
  • 统计学模型 14篇
  • 概率模型 10篇
  • 计算机图形学 1篇
  • AI数学原理 5篇
  • GNN-图形网络 9篇
  • 基础代数模型 7篇
  • 大数据分析 2篇
  • 控制论 6篇
  • 数据分析 9篇
  • RNN 2篇
  • 深度学习 13篇
  • 最优规划问题 1篇
  • 强化学习 6篇
  • 自然语言大模型 7篇
  • 对抗网络 11篇
  • 傅里叶分析 10篇
  • 杂文和仓储 1篇
  • 神经网络 3篇
  • 机器学习专栏 6篇
  • TensorFlow_2.14 12篇
  • javascript 2篇
  • 卡尔曼滤波 2篇
  • 量子计算 2篇
  • NLP高级和ChatGPT 48篇
  • Qt5和python实验 36篇
  • 未分类文章 17篇
  • 网上信息挖掘 12篇
  • 神经网络建模 2篇
  • 机器学习 25篇
  • python指南和应用 115篇
  • OpenCV 4篇
  • 深度学习和计算机视觉 37篇
  • 数学视野 22篇
  • 几何建模专栏 6篇
  • 通用双曲几何 10篇
  • 计算几何 12篇
  • 射影几何和slam基础 19篇
  • 语音处理 16篇
  • 基础理论 52篇
  • 操作系统和协议 17篇
  • 模式识别 10篇
  • 时间序列 11篇
  • 统计学习法 22篇
  • 精算师之路 9篇
  • 贝叶斯理论 8篇
  • 几何模型 1篇
  • Halcon资料汇编 45篇
  • python-pygame 2篇
  • 语音编程 9篇
  • 环境配置 31篇
  • ROS资源和工业机器人 5篇
  • sklearn专栏 4篇
  • docker 34篇
  • Ubuntu 27篇
  • AI相关安装-程序出错改出 2篇
  • C#栏目 28篇
  • 树莓派 3篇
  • UI界面和数据可视化 43篇
  • PyQt5-6零基础学习和实践
  • pytorch 3篇

最新评论

  • 从GAN到WGAN(01/2)

    ha_lydms: 博主文章写的十分细致,结构严谨。感谢博主分享,期待博主持续输出好文,同时也希望可以来我博客指导我一番。

  • 基于相位的运动放大:如何检测和放大难以察觉的运动(02/2)

    无水先生: 不留能留联系方法,避免骚扰。

  • 基于相位的运动放大:如何检测和放大难以察觉的运动(02/2)

    顺天.: 你好 有偿咨询 能加个联系方式吗

  • 【OpenGL4.6】VS2022安装OpenGL4.6的全过程

    无水先生: 共有三个有用东西:窗口界面(glfw:选64位) GL库:不需要安装oengl32.lib。 glad:选64位

  • 【OpenGL4.6】VS2022安装OpenGL4.6的全过程

    懒回顾,半缘君: glfw32位的和64位的选哪个?网上有说32位的更稳定

您愿意向朋友推荐“博客详情页”吗?

  • 强烈不推荐
  • 不推荐
  • 一般般
  • 推荐
  • 强烈推荐
提交

最新文章

  • 序列到序列模型中的注意力机制
  • 什么是隐马尔可夫模型?
  • 探索序列到序列模型:了解编码器和解码器架构的强大功能
2024
06月 33篇
05月 51篇
04月 61篇
03月 70篇
02月 61篇
01月 70篇
2023年963篇
2022年441篇
2021年111篇
2020年5篇

目录

目录

分类专栏

目录

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无水先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或 充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值

两个鬼故事吉尔吉斯人生辰八字在线起名软件的邓的男孩起名给姓潘的起名大全龙凤胎起小名一男一女入地无门女孩起什么名建国大业观后感500字传奇符号名字牛肉店起什么名好赛文奥特曼国语版超级黑道学生化工软件丫丫视频直播女总裁的全能兵王在线免费起名网免费取名胖胖服饰工商注册个体工商户起名姓廖起名亲戚计算器烧烤店怎么起名字好演艺公司起什么名字好民办教育机构起名贵族天使之恋免费得起名字软件莛字起名的寓意梦回大清txt名典姓名网孟姓令字辈男孩起名大全保安服务公司起名大全少年生前被连续抽血16次?多部门介入两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”淀粉肠小王子日销售额涨超10倍高中生被打伤下体休学 邯郸通报单亲妈妈陷入热恋 14岁儿子报警何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言张家界的山上“长”满了韩国人?男孩8年未见母亲被告知被遗忘中国拥有亿元资产的家庭达13.3万户19岁小伙救下5人后溺亡 多方发声315晚会后胖东来又人满为患了张立群任西安交通大学校长“重生之我在北大当嫡校长”男子被猫抓伤后确诊“猫抓病”测试车高速逃费 小米:已补缴周杰伦一审败诉网易网友洛杉矶偶遇贾玲今日春分倪萍分享减重40斤方法七年后宇文玥被薅头发捞上岸许家印被限制高消费萧美琴窜访捷克 外交部回应联合利华开始重组专访95后高颜值猪保姆胖东来员工每周单休无小长假男子被流浪猫绊倒 投喂者赔24万小米汽车超级工厂正式揭幕黑马情侣提车了西双版纳热带植物园回应蜉蝣大爆发当地回应沈阳致3死车祸车主疑毒驾恒大被罚41.75亿到底怎么缴妈妈回应孩子在校撞护栏坠楼外国人感慨凌晨的中国很安全杨倩无缘巴黎奥运校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变王树国卸任西安交大校长 师生送别手机成瘾是影响睡眠质量重要因素国产伟哥去年销售近13亿阿根廷将发行1万与2万面值的纸币兔狲“狲大娘”因病死亡遭遇山火的松茸之乡“开封王婆”爆火:促成四五十对奥巴马现身唐宁街 黑色着装引猜测考生莫言也上北大硕士复试名单了德国打算提及普京时仅用姓名天水麻辣烫把捣辣椒大爷累坏了

两个鬼故事 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化