简体   繁体   English

多边形与直线之间的交点

[英]Intersection between a polygon and a line in shapely

I am trying to find the intersections between circular polygons and a line and then merge the results. 我试图找到圆形多边形和一条线之间的交点,然后合并结果。

I would expect all the intersections to belong to the line and also their union, but it is not what I see. 我希望所有的交叉点都属于该线,也属于它们的并集,但这不是我所看到的。

Here an example: 这里是一个例子:

from shapely.geometry import LineString, Point

line = LineString([(2, 5), (2.1, 1)])  # slightly oblique line

point1 = Point(2.5, 3)

int1 = line.intersection(point1.buffer(1))
int2 = line.intersection(point1.buffer(1.3))

union = int1.union(int2)

print union.length
print int2.length

results: 结果:

4.22183534925 4.22183534925

2.43702622444 2.43702622444

since int2 contains int1 I would expect their union to be exactly int2. 因为int2包含int1,所以我希望它们的并集恰好是int2。 I would expect also the union to be just a LineString, but instead it is a MultiLineString composed by 4 lines. 我希望联盟也只是一个LineString,而是由4行组成的MultiLineString。

If I plot the union lines I see how their are really close each other but not on the same line. 如果我绘制联合线,我会看到它们如何真正彼此靠近,但不在同一条线上。

I think it is something to do with the resolution of the shapely objects values. 我认为这与形状对象值的分辨率有关。

Any suggestion how to merge "almost parallel" lines into one? 有什么建议如何将“几乎平行”的线合并为一条? Or do you suggest any other solution to this problem? 或您是否建议其他解决此问题的方法?

As far as I know, there is no shapely built-in function to do what you need. 据我所知,没有内置的内置函数可以执行所需的操作。 Besides, as you noticed, ther are some round errors that you need to address. 此外,正如您所注意到的,还有一些您需要解决的舍入错误 Fortunately, there are some shapely functions that can help you to implement a short solution: 幸运的是,有一些匀称的功能可以帮助您实现一个简短的解决方案:

  1. The project method of a LineString that takes a point and gives you the distance from the first point of the line to the closest point of the line to the given point. LineString的project方法,该方法采用一个点,并提供从线的第一个点到该线的最接近点到给定点的距离。
  2. The interpolate method of a LineString that given a distance, it gives you the point that is in the LineString with that distance from the first point of the line. 给定距离的LineString的interpolate方法,它会为您提供LineString中的点,该点与直线的第一个点具有该距离。

I will assume you know what line is inside the other, as in the example. 我会假设你知道什么是线路上的其他 ,如示例。 If this is the case, what you can do is to projet the points of the shorter line into the longer line, and then sort those points considering their distance to the first point of the line. 如果是这种情况,您可以做的是将短线的点投射到较长的线中,然后考虑到它们与线的第一点的距离对这些点进行排序。

With the following code, 使用以下代码,

from shapely.geometry import LineString, Point
from shapely.ops import linemerge

def getProyection(aline, point_coords):
    return aline.interpolate(aline.project(Point(point_coords)))

def mergeInside(aline, inside_line):
    mline_tups = [(aline.project(Point(p)), p) for p in aline.coords]
    mline_tups.extend([ (aline.project(Point(p)), getProyection(aline, p))
                                    for p in inside_line.coords])
    mline_tups.sort()
    return LineString([p for _, p in mline_tups])

line = LineString([(2, 5), (2.1, 1)])  # slightly oblique line
point1 = Point(2.5, 3)
int1 = line.intersection(point1.buffer(1))
int2 = line.intersection(point1.buffer(1.3))
merged_line = mergeInside(int2, int1)

print(int1)
print(int2)
print(merged_line)

I get: 我得到:

LINESTRING (2.02796158358983 3.881536656406788, 2.072567874421353 2.097285023145893)
LINESTRING (2.019819096605441 4.207236135782384, 2.080725721869193 1.770971125232286)
LINESTRING (2.019819096605441 4.207236135782384, 2.027961583589831 3.881536656406788, 2.072567874421353 2.097285023145893, 2.080725721869193 1.770971125232286)

Since I am mainly interested in the length of the union rather then its exact vertices I have found another way to measure it. 由于我主要对联合的长度感兴趣,而不是对联合的确切顶点感兴趣,因此我找到了另一种方法来对其进行度量。

from shapely.geometry import LineString, Point

line = LineString([(2, 5), (2.1, 1)])  # slightly oblique line

point1 = Point(2.5, 3)

int1 = line.intersection(point1.buffer(1))
int2 = line.intersection(point1.buffer(1.3))

line_not_intersected = line.difference(point1.buffer(1))
line_not_intersected = line_not_intersected.difference(point1.buffer(1.3))

print line.length - line_not_intersected.length
print int2.length

and it gives the expected result: 它给出了预期的结果:

2.43702622444 2.43702622444

2.43702622444 2.43702622444

Interesting, and annoying at the same time, if I get the union as 如果我得到工会的话,有趣而烦人的同时

union = line.difference(line_not_intersected)

union is a LineString, but its length is not the same as the difference of the lengths of the two lines. union是一个LineString,但是它的长度与两行长度的差不同。

print line.length - line_not_intersected.length
print union.length

2.43702622444 2.43702622444

4.00124980475 4.00124980475

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM