Python 圆与线的交点 返回[] 否则:#可能有0个、1个或2个与线段的交点 交点=[ (cx+(大号d*dy+符号*(-1,如果dy Outside AC => Outside ... AJ => Intersects BJ => Intersects ... J

Python 圆与线的交点 返回[] 否则:#可能有0个、1个或2个与线段的交点 交点=[ (cx+(大号d*dy+符号*(-1,如果dy Outside AC => Outside ... AJ => Intersects BJ => Intersects ... J,python,geometry,computational-geometry,Python,Geometry,Computational Geometry,圆与线的交点 返回[] 否则:#可能有0个、1个或2个与线段的交点 交点=[ (cx+(大号d*dy+符号*(-1,如果dy Outside AC => Outside ... AJ => Intersects BJ => Intersects ... JJ => Inside from shapely.geometry import LineString from shapely.geometry import Point p = Point(5,5) c = p.buffer(3).bou

圆与线的交点 返回[] 否则:#可能有0个、1个或2个与线段的交点 交点=[ (cx+(大号d*dy+符号*(-1,如果dy<0,则为1)*dx*判别式**.5)/dr**2, cy+(-big_d*dx+符号*abs(dy)*判别式**.5)/dr**2) 对于登录((1,-1)如果dy<0,则为-1,否则为(-1,1)))#这确保了沿段的顺序正确 如果未满线:#如果仅考虑线段,则过滤掉不在线段内的交点 (席-P1X)/DX如果ABS(DX)>ABS(DY)EXY(Y-P1Y)/DY,对于交叉口中的席、彝
交点=[pt的交点,zip中的分形(交点,沿线段的分数)如果在我看来,0是圆的交点,而不是整条线,而不是两个给定点之间的线段。这就是你想要的吗?我能想到的唯一的优化是使用某种空间分区。例如四叉树。但是在计算这些方面有不平凡的成本,所以它。这取决于你的大问题,如果有用与否。@EmanuelePaolini,谢谢。我已经根据你的担忧修改了脚本。-可能相关。还有没有任何未解决的问题没有被发布的答案回答?是的……与定义乐趣相比,Shapely或SymPy等库计算交集的效率如何我自己想知道吗?这是我想知道的一个。Shaviy是基于GeOS()的,它是用C++构建的,比在Python中自己编写的任何东西都快得多。它也似乎是Python,但似乎有很多相当复杂的数学融入其中。实现自己可能需要大量的工作,并且可能不会像GeOS C++实现那样快。有时候,它只返回一个点,有时也会返回多个点。如何测试返回值以知道哪个是哪个?一条直线可以与一个圆相交0-2次。这就是为什么有时会得到一个单点或多点。假设为单点是一个pythonic,如果出现异常,则返回到多点。但我不知道要测试什么。@albrnick我认为您可以始终将其实例化为多点,并将其视为多点。只需结果并将其交给多点(结果)
def LineIntersectCircle(p,lsp,lep):
# p is the circle parameter, lsp and lep is the two end of the line
  x0,y0,r0 = p
  x1,y1 = lsp
  x2,y2 = esp
  if x1 == x2:
    if abs(r0) >= abs(x1 - x0):
        p1 = x1, y0 - sqrt(r0**2 - (x1-x0)**2)
        p2 = x1, y0 + sqrt(r0**2 - (x1-x0)**2)
        inp = [p1,p2]
        # select the points lie on the line segment
        inp = [p for p in inp if p[1]>=min(y1,y2) and p[1]<=max(y1,y2)]
    else:
        inp = []
  else:
    k = (y1 - y2)/(x1 - x2)
    b0 = y1 - k*x1
    a = k**2 + 1
    b = 2*k*(b0 - y0) - 2*x0
    c = (b0 - y0)**2 + x0**2 - r0**2
    delta = b**2 - 4*a*c
    if delta >= 0:
        p1x = (-b - sqrt(delta))/(2*a)
        p2x = (-b + sqrt(delta))/(2*a)
        p1y = k*x1 + b0
        p2y = k*x2 + b0
        inp = [[p1x,p1y],[p2x,p2y]]
        # select the points lie on the line segment
        inp = [p for p in inp if p[0]>=min(x1,x2) and p[0]<=max(x1,x2)]
    else:
        inp = []
  return inp
| | __|_|__ __|O|__ | | | | A |B| C __|_|__ D_|O|_E | | F |G| H AA => Outside AB => Outside AC => Outside ... AJ => Intersects BJ => Intersects ... JJ => Inside
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)
def circle_line_segment_intersection(circle_center, circle_radius, pt1, pt2, full_line=True, tangent_tol=1e-9):
    """ Find the points at which a circle intersects a line-segment.  This can happen at 0, 1, or 2 points.

    :param circle_center: The (x, y) location of the circle center
    :param circle_radius: The radius of the circle
    :param pt1: The (x, y) location of the first point of the segment
    :param pt2: The (x, y) location of the second point of the segment
    :param full_line: True to find intersections along full line - not just in the segment.  False will just return intersections within the segment.
    :param tangent_tol: Numerical tolerance at which we decide the intersections are close enough to consider it a tangent
    :return Sequence[Tuple[float, float]]: A list of length 0, 1, or 2, where each element is a point at which the circle intercepts a line segment.

    Note: We follow: http://mathworld.wolfram.com/Circle-LineIntersection.html
    """

    (p1x, p1y), (p2x, p2y), (cx, cy) = pt1, pt2, circle_center
    (x1, y1), (x2, y2) = (p1x - cx, p1y - cy), (p2x - cx, p2y - cy)
    dx, dy = (x2 - x1), (y2 - y1)
    dr = (dx ** 2 + dy ** 2)**.5
    big_d = x1 * y2 - x2 * y1
    discriminant = circle_radius ** 2 * dr ** 2 - big_d ** 2

    if discriminant < 0:  # No intersection between circle and line
        return []
    else:  # There may be 0, 1, or 2 intersections with the segment
        intersections = [
            (cx + (big_d * dy + sign * (-1 if dy < 0 else 1) * dx * discriminant**.5) / dr ** 2,
             cy + (-big_d * dx + sign * abs(dy) * discriminant**.5) / dr ** 2)
            for sign in ((1, -1) if dy < 0 else (-1, 1))]  # This makes sure the order along the segment is correct
        if not full_line:  # If only considering the segment, filter out intersections that do not fall within the segment
            fraction_along_segment = [(xi - p1x) / dx if abs(dx) > abs(dy) else (yi - p1y) / dy for xi, yi in intersections]
            intersections = [pt for pt, frac in zip(intersections, fraction_along_segment) if 0 <= frac <= 1]
        if len(intersections) == 2 and abs(discriminant) <= tangent_tol:  # If line is tangent to circle, return just one point (as both intersections have same location)
            return [intersections[0]]
        else:
            return intersections