我有一组直线(形式为y = mx + B的线性函数)(共120条!),如果我把它们都画出来,它们就分割了R^2平面,这些直线不一定经过原点。
要找到由一组这样的行创建的所有分区,最有效的方法是什么?就我个人而言,我很难想出任何方法,更不用说有效的方法了。为了更清楚起见,我包括了以下只有4行的图像:x1c 0d1x
分区的一个例子是集合{(x,y)| -30x+28<= y && 60x+2 <= y <= 90x+7}
,它是由第一象限中的红、黄和绿色线创建的分区。另一个例子是{(x,y)|y <= -30x+28 && 5x+3 <= y <= 60x+2}
,它是第一象限中由蓝、红和绿线包围的三角形。{(x,y)|5x+3 <= y <= -30x+28}
是一个 non 分区的例子,它是由上面的绿色线和下面的蓝线围成的集合。这不是一个分区,因为它包含了几个分区(例如上面的第二个集合),或者与它重叠。然而,集合{(x,y)|5x+3 <= y <= -30x+28 && 90x+7 <= y}
是一个分区。
所需的输出将是此类集合的完整列表:{(x,y)|y <= -30x+28 && 5x+3 <= y <= 60x+2},{(x,y)| -30x+28<= y && 60x+2 <= y <= 90x+7}...
等。当然,它们不必以这种表示法给出。
我不知道如何解决这个问题,因此,不幸的是,我不能提供太多我所尝试的方法。理想情况下,我想用R,Python,Mathematica或MATLAB来做这件事,但在这一点上,我对任何选择都持开放态度。
**EDIT:**由于似乎有一个符号的问题,我将澄清一点。它足以简单地得到一个点的条件列表,这样所有满足该条件的点将精确地定义一个分区。例如,一个长的交集列表,将是很好的:y <= 5x+3 && y >= 90x+7 && y<= -30x+28
是一个很好的定义分区的输出。当然,期望的输出是这样的分区的完整列表(如上所定义)。
5条答案
按热度按时间hmae6n7t1#
求分区的数量遵循以下公式(当没有3条或更多的线相交于同一点时--这一假设贯穿于本文):
一个解释是here,另一个解释是there。
所需的输出将是此类集合的完整列表:
{(x,y)|y <= -30x+28 && 5x+3 <= y <= 60x+2}, {(x,y)| -30x+28<= y && 60x+2 <= y <= 90x+7}...
等...当然,它们不必用这种表示法给出。这里缺少精确的符号是一个障碍。
下面是我的信封尝试的背面。如你所见,可以根据它们与每一行的相对位置来识别编号区域。
有5个空集,如果行顺序发生变化,则空集将不相同。
它可能会更容易划分平面上的一组点与线,试图确定哪个点属于哪个集;在这种情况下,探索
2^n
可能的分区并返回它们的内容将是很容易的。(比试图找到一个好的符号来标识抽象集要容易)这并没有完全回答你的问题,但可能是一个很好的起点,有人能够/愿意进一步推动这一点。
这里有一个关于partitioning a set of points with two lines in the plane.的说明,这是一个不同的问题,但它的一些方法可能是有用的。
其他方法:
识别由线段形成的多边形,计算船体,确定点是否在该凸包中。
kd3sttzy2#
下面是Mathematica中的一个解决方案。该方法包括找到直线的交点、线段和分割,同时跟踪这些点连接到哪些直线上。
qnakjoqk3#
完整的Matlab解决方案。120行7021个分区,在0.4秒内完成原始计算(绘图+2秒)。
最后一次。
第一次
bejyjqdl4#
EDIT New solution, using itertools. Old solution below. Using the python package
itertools
, I believe this solution is faster than the original. However, it is still extremely slow and is not feasible beyond about 20-ish lines. For 120 lines, none of these will terminate.OLD SOLUTION
Here's what ended up working for me, in python:
For the above example, this outputs:
The code is extremely simple and the output is exactly as desired.
The idea is basically that each line divides the plane into two halves, and so the loop (which iterates over the set of lines) intersects each partition already found with each half and adds the two new partitions to the set, while removing the original, in-intersected partition. The result doesn't always give the simplest possible condition (some of the conditions may be redundant), but they do give a complete description of each partition.
While this solution works, with 120 lines, it is pretty slow. I'd be interested in seeing if there are more efficient ways to accomplish this, using this method or otherwise.
mxg2im7a5#
到目前为止所建议的方法的另一种方法是使用三角形。
从一组三角形开始(可能包含无穷远的点),它们的并集是一个覆盖整个平面的多边形。例如,您可以开始使用作为算法输入的前两条直线分割平面所得到的四个三角形,或者使用由原点O、OX轴的正边和240度并且也从O开始的两条半线。
现在,对于每一条作为输入的线,您都要查找它所穿过的三角形,对于每一个三角形,您都要在与线的交点处将其截断,并将其替换为三个三角形(或者在退化的情况下是两个)覆盖相同区域的新三角形。然后你必须找到那些旧的相交三角形是其一部分的多边形,并且用两个多边形来替换其中的每一个,这两个多边形是根据它们所在的线的边来分割它所包含的三角形而得到的。
使用三角形的好处是它使计算更容易,你可以把它放到一些索引数据结构中,比如k-d树,这样可以更快地计算哪些多边形被某条线切割,你可以用一个复杂度为O(NlogN)的算法来结束,其中N是形成平面划分的多边形的数量。