Repository: kivy/kivy

Issue:
Unpredictable behaviour of Vector.segment_intersection(v1, v2, v3, v4)
When I tried to put my fingers into kivy, I stumbled, while trying to improve the pong-tutorial, over this unpredictable behaviour of Vector.segment_intersection().
It seems to be somehow a floatingpoint error, yet it just appears with certain numerical vectors.
I created a "minimal" working example, trying some combinations, which reproduces the bug - using the template given.

https://gist.github.com/johannesmueller-fr/c32ab245a9fb81d8fb15
## <bountysource-plugin>

Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/8228916-unpredictable-behaviour-of-vector-segment_intersection-v1-v2-v3-v4?utm_campaign=plugin&utm_content=tracker%2F42681&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F42681&utm_medium=issues&utm_source=github).
</bountysource-plugin>



Discussion:
I looked into it more specifically by debugging another coordinate, which wasn't working,
therby two bugs became obvious:
- 1. vector.py: LINE 372: In the calculation of the denominator a floating-point rounding error can occur, which later prevents c4 to become true.
- 2. vector.py: LINE 380: In the calculation of c3 there is a bug: y2 <= py <= y2, which should be y2 <= py <= y1

I'm using the stable 1.8.0 version of kivy

Here my Debugging-Log to make you understand what I mean
https://gist.github.com/johannesmueller-fr/29dd2d6964a50c655324

**UPDATE:**
I forked your repository and cloned the current version to my HD, so here my updated bug description:
- 1: The floating-point rounding error introduced in LINE 378 (not 372) is not the trigger for the bug,
  it is the division done in LINE 382 and 383.
- 2: This Bug is already fixed in the newest version

The Bug is occuring on intersections with horizontal or vertical segments, if there occurs a floating-point rounding mistake before, some conditons of the form: n <= pc <= n will fail, since pc with rounding mistake doesn't equal n.
If you would round px and py to a certain number of decimals - say 5 - this could be avoided!

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.


Resolving patch:
diff --git a/kivy/vector.py b/kivy/vector.py
--- a/kivy/vector.py
+++ b/kivy/vector.py
@@ -369,9 +369,11 @@ def segment_intersection(v1, v2, v3, v4):
         >>> Vector.segment_intersection(a, b, c, d)
         [5, 5]
         '''
+
         # Yaaay! I love linear algebra applied within the realms of geometry.
         x1, x2, x3, x4 = float(v1[0]), float(v2[0]), float(v3[0]), float(v4[0])
         y1, y2, y3, y4 = float(v1[1]), float(v2[1]), float(v3[1]), float(v4[1])
+
         # This is mostly the same as the line_intersection
         u = (x1 * y2 - y1 * x2)
         v = (x3 * y4 - y3 * x4)
@@ -382,10 +384,10 @@ def segment_intersection(v1, v2, v3, v4):
         px = (u * (x3 - x4) - (x1 - x2) * v) / denom
         py = (u * (y3 - y4) - (y1 - y2) * v) / denom
         # Here are the new bits
-        c1 = (x1 <= px <= x2) or (x2 <= px <= x1)
-        c2 = (y1 <= py <= y2) or (y2 <= py <= y1)
-        c3 = (x3 <= px <= x4) or (x4 <= px <= x3)
-        c4 = (y3 <= py <= y4) or (y4 <= py <= y3)
+        c1 = (x1 <= px <= x2) or (x2 <= px <= x1) or (x1 == x2)
+        c2 = (y1 <= py <= y2) or (y2 <= py <= y1) or (y1 == y2)
+        c3 = (x3 <= px <= x4) or (x4 <= px <= x3) or (x3 == x4)
+        c4 = (y3 <= py <= y4) or (y4 <= py <= y3) or (y3 == y4)
 
         if (c1 and c2) and (c3 and c4):
             return Vector(px, py)


Test patch: