{"record":{"id":"5ee178e0e25afe17","repo":"3b1b/manim","slug":"lines-do-not-intersect","errorCode":null,"errorMessage":"Lines do not intersect","messagePattern":"Lines do not intersect","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"manimlib/utils/space_ops.py","lineNumber":286,"sourceCode":"\ndef line_intersection(\n    line1: Tuple[Vect3, Vect3],\n    line2: Tuple[Vect3, Vect3]\n) -> Vect3:\n    \"\"\"\n    return intersection point of two lines,\n    each defined with a pair of vectors determining\n    the end points\n    \"\"\"\n    x_diff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])\n    y_diff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1])\n\n    def det(a, b):\n        return a[0] * b[1] - a[1] * b[0]\n\n    div = det(x_diff, y_diff)\n    if div == 0:\n        raise Exception(\"Lines do not intersect\")\n    d = (det(*line1), det(*line2))\n    x = det(d, x_diff) / div\n    y = det(d, y_diff) / div\n    return np.array([x, y, 0])\n\n\ndef find_intersection(\n    p0: Vect3 | Vect3Array,\n    v0: Vect3 | Vect3Array,\n    p1: Vect3 | Vect3Array,\n    v1: Vect3 | Vect3Array,\n    threshold: float = 1e-5,\n) -> Vect3:\n    \"\"\"\n    Return the intersection of a line passing through p0 in direction v0\n    with one passing through p1 in direction v1.  (Or array of intersections\n    from arrays of such points/directions).\n","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/3b1b/manim/blob/dee01804d47b9f94402d71472674710dcac125b8/manimlib/utils/space_ops.py#L268-L304","documentation":"Raised by line_intersection (utils/space_ops.py:286) when the determinant of the direction differences (div) is zero, i.e. the two lines are parallel (or collinear) so there is no unique intersection point. The 2D cross-product formulation degenerates and the function refuses to divide by zero.","triggerScenarios":"line_intersection([p0, p0 + RIGHT], [p1, p1 + RIGHT]) with two horizontal lines; two segments sharing the same direction vector; numerically near-parallel lines where floating point rounds div to exactly 0.0.","commonSituations":"Computing intersections of grid lines or axes-aligned edges; geometry code assuming lines always cross; animations placing labels at line crossings that happen to be parallel in edge cases.","solutions":["Check direction vectors first: if np.cross(v0, v1) == 0 (or below a tolerance), handle the parallel case explicitly instead of calling line_intersection","Nudge one line's direction by a tiny epsilon only if approximate behavior is acceptable","Prefer find_intersection(p0, v0, p1, v1) which handles 3D/segment cases with a threshold, when appropriate to your inputs"],"exampleFix":"# before\npt = line_intersection([a, b], [c, d])  # parallel -> raises\n\n# after\nv0, v1 = b - a, d - c\nif abs(v0[0] * v1[1] - v0[1] * v1[0]) < 1e-9:\n    pt = None  # parallel: no intersection\nelse:\n    pt = line_intersection([a, b], [c, d])","handlingStrategy":"validation","validationCode":"def lines_intersect(l1, l2, tol=1e-9) -> bool:\n    d0 = (l1[1][0] - l1[0][0], l1[1][1] - l1[0][1])\n    d1 = (l2[1][0] - l2[0][0], l2[1][1] - l2[0][1])\n    return abs(d0[0] * d1[1] - d0[1] * d1[0]) > tol","typeGuard":null,"tryCatchPattern":"try:\n    pt = line_intersection(l1, l2)\nexcept Exception:\n    pt = None  # parallel or collinear lines","preventionTips":["Check the 2D cross product of direction vectors before calling line_intersection","Handle parallel/collinear as an explicit case in geometry code","Prefer find_intersection for 3D/segment workflows where applicable"],"tags":["manim","geometry","parallel-lines","math","degenerate-case"],"backgroundTag":null,"analyzedSha":"dee01804d47b9f94402d71472674710dcac125b8","analyzedAt":"2026-08-14T19:53:44.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}