在Python中,找到一条直线和一个圆相交的最有效方法是什么?
在Python中找到一条直线和一个圆的交点的最有效方法是什么?
问题的出现原因是,需要在Python中找到一条直线和一个圆的交点,但是希望能够以最高效的方式实现。为了解决这个问题,可以采取以下方法:
首先,可以将平面分为9个部分,这是一种低成本的空间划分方法。可以想象一下,如果线条只是触碰到圆的话,可以得到一个不太好的图示。在图示中,我们感兴趣的有8个区域,围绕着圆形。中间的正方形对于廉价测试来说没有太大用处,但是可以将一个边长为r/sqrt(2)
的正方形放置在圆内,使其四个角刚好触碰到圆。
接下来,给这些区域进行标记,如下所示:
A |B| C
__|_|__
D_|O|_E
| |
F |G| H
中间的正方形标记为J
。我们将在图示中显示的中心正方形中不属于J
的点集合称为Z
。用字母代码标记多边形的每个顶点。
现在我们可以快速看出:
AA => 外部
AB => 外部
AC => 外部
...
AJ => 交点
BJ => 交点
...
JJ => 内部
这可以转化为一个查找表。
因此,根据数据集的不同,可能可以节省大量的工作。然而,任何一个端点都需要进行测试。
文章标题:Python中寻找线段和圆相交点的最有效方法及原因
在解决计算线段和圆相交点的问题时,作者给出了一个解决方案。该解决方案可以计算圆与线段或由两个(x,y)点定义的线段的相交点,可以在线段上的任意一点计算相交点。代码使用了数学世界上给出的圆线相交的公式。代码经过测试并且可行,但作者对于一些变量的含义表示不清楚,并且代码中存在一些逻辑上的错误。
作者定义了一个名为“circle_line_segment_intersection”的函数,该函数接受圆心坐标,半径,线段的两个端点坐标作为输入。函数中使用了一些变量来计算相交点的坐标。在计算相交点的过程中,作者使用了一个列表推导式来生成相交点的坐标,并对相交点进行了一些过滤和排序的操作。
在代码的第一行,作者定义了一个变量“sign”。在列表推导式中,作者使用了“sign”来计算相交点的坐标。然而,在计算“sign”时,作者将“sign”乘以“dy”的符号,然后再将其乘以“dx”的符号。这样做的结果是“sign”始终为-1,并且dy的值从未被包含在计算中。这是代码中存在的一个逻辑错误。
除了逻辑错误之外,代码中还存在一些不易理解的地方。对于一些变量的含义和相互之间的关系,作者并未进行解释。这使得代码难以理解,并且难以进行几何推理。
在评论中,其他人也对代码中的一些问题进行了讨论。其中有人认为作者试图通过修改两个地方的代码来实现按照线段上的位置对相交点进行排序,但是这样的修改没有任何效果。还有人尝试对代码进行了改写,以便更清晰地理解代码的含义和逻辑。
虽然这段代码在实际运行中是有效的,但是其逻辑和含义并不清晰,难以进行推理和理解。在使用这段代码时,需要注意其中的逻辑错误,并进行适当的修改和调整。
在Python中找到一条直线和一个圆的交点,最高效的方法是什么?
问题的原因是,提问者希望找到一种理论上最快的方法来解决这个问题。但是如果想要快速解决,应该使用用C/C++编写的工具。
提问者推荐使用Shapely库来解决这个问题,并提供了一个使用该库的示例。Python中有许多几何库,这个问题的答案会列举其中一些。
from shapely.geometry import LineString from shapely.geometry import Point p = Point(5,5) c = p.buffer(3).boundary l = LineString([(0,0), (10, 10)]) i = c.intersection(l) print i.geoms[0].coords[0] (2.8786796564403576, 2.8786796564403576) print i.geoms[1].coords[0] (7.121320343559642, 7.121320343559642)
在Shapely中,圆是具有缓冲区域边界的点。这就是为什么使用`p.buffer(3).boundary`。
此外,交点`i`是一个几何形状的列表,这两个点在这种情况下都是点,所以需要从`i.geoms[]`中获取它们。
对于对这些库感兴趣的人,还有另一个Stackoverflow问题详细介绍了这些库。
编辑后的评论:
Shapely是基于GEOS(trac.osgeo.org/geos)的,它是用C++构建的,比你在Python中编写的任何代码都要快得多。SymPy似乎是基于mpmath(mpmath.org)的,mpmath似乎也是Python的,但似乎集成了很多复杂的数学。自己实现可能需要很多工作,并且可能不如GEOS C++实现快。
有关使用Shapely或SymPy等库计算交点的效率,与自己定义函数相比,效率如何?这是我想要知道的。
Shapely是基于GEOS(trac.osgeo.org/geos)的,它是用C++构建的,比你在Python中编写的任何代码都要快得多。SymPy似乎是基于mpmath(mpmath.org)的,mpmath似乎也是Python的,但似乎集成了很多复杂的数学。自己实现可能需要很多工作,并且可能不如GEOS C++实现快。
有时这将返回一个单一点,有时返回多个点。如何测试返回值以知道是哪个?
一条直线可以与一个圆相交0到2次。这就是为什么有时会得到一个单一点或多个点。Pythonic的做法是假设是单一点,如果引发异常,则回退到多点。但是我不知道你想要测试什么。
我想看看如何检测我得到的是哪个。结果是我可以使用isinstance()来检查类。(我希望对象本身有一个方法)
我认为你总是可以将其实例化为一个多点,并将其视为多点。只需将结果传递给`MultiPoint(result)`。
如果我将LineString的第一个点更改为(6,5)或(5,5),输出将出错,显示“'Point' object has no attribute 'geoms'”。这是否意味着直线必须从圆外开始和结束?你可以详细解释一下吗?
由于评论中有人问道:我在我的电脑上对Peter提出的原生Python函数和这个答案中提出的Shapely库进行了基准测试。Python耗时0.000019秒,Shapely耗时0.000101秒。在我的电脑上,原生Python实现要快5倍。这主要是因为创建Shapely对象的开销(约70毫秒),但原始的交点计算在Python中仍然比Shapely快约15毫秒。
感谢您的测试和结果。我认为应该注意的是,可以先创建Shapely对象,然后可以重复使用它们来检查交点,这样使用Shapely会更快。但对于一次性检查,原生Python可能更快。在几何数学中通常有许多需要考虑的边界情况。