1

I'm working on a couple of basic math classes for performing line collisions in 2D.

Here is my python code:

collisions.py

import math

class Vector:
    def __init__(self, x, y):
        self._x = x
        self._y = y
        
    def __str__(self):
        return '(%d, %d)' %(self._x, self._y)
        
    def __add__(self, other):
        return Vector(self._x + other._x, self._y + other._y)
        
    def __sub__(self, other):
        return Vector(self._x - other._x, self._y - other._y)
    
    def __mul__(self, val):
        return Vector(self._x * val, self._y * val)
        
    # same as dot product
    #def __mul__ (self, other):
    #    return self.dot(other)
    
    # same as cross product
    #def __pow__(self, other):
    #    return self.cross(other)
    
    def x(self):
        return self._x
    
    def y(self):
        return self._y
    
    def cross(self, other):
        return (self._x * other._y - self._y * other._x)
    
    def dot(self, other):
        return (self._x * other._x + self._y * other._y)        
    
class Line:
    def __init__(self, p1, p2):
       self._p1 = p1
       self._p2 = p2
       
    def slope(self):
        if self._p1.x() == self._p2.x():
            if self._p1.y() == self._p2.y():
                return str("both points coincide") 
            else:
                if self._p1.y() < self._p2.y():
                    return float('inf')
                else:
                    return float('-inf')
        self._m = float((self._p2.y() - self._p1.y()) / (self._p2.x() - self._p1.x()))  
        return self._m
    
    def p1(self):
        return self._p1
        
    def p2(self):
        return self._p2
        
def LineIntersect(l1, l2):
    a = l1.p1()
    b = l1.p2()
    c = l2.p1()
    d = l2.p2()

    #r = l1.p2() - l1.p1()
    r = b - a
    #s = l2.p2() - l2.p1()
    s = d - c
    
    d = r.cross(s)
    #u = ((l2.p2.x() - l1.p1.x()) * r.y() - (l2.p2.y() - l1.p1.y()) * r.x()) / d
    u = ((c.x() - a.x()) * r.y() - (c.y() - a.y()) * r.x()) / d
    #t = ((l2.p2.x() - l1.p1.x()) * s.y() - (l2.p2.y() - l1.p1.y()) * s.x()) / d
    t = ((c.x() - a.x()) * s.y() - (c.y() - a.y()) * s.x()) / d
    
    if (0 <= u and u <= 1 and 0 <= t and t <= 1):
        return (a + t * r)
    else:
        return False;
        
l1 = Line(Vector(0, 0), Vector(3, 3))
l2 = Line(Vector(3, 0), Vector(0, 3))

intersected = LineIntersect(l1, l2)
print(intersected)

When I run this through Windows 7 command prompt using Python 3.7's interpreter via python collisions.py

It is generating this error message:

D:\Dev\Languages\Python\Projects\Test>python collisions.py
Traceback (most recent call last):
  File "collisions.py", line 88, in <module>
    intersected = LineIntersect(l1, l2)
  File "collisions.py", line 81, in LineIntersect
    return (a + t * r)
TypeError: unsupported operand type(s) for *: 'float' and 'Vector'

I'm more inclined with the C languages specifically C++... I've been learning Python for about a year now and I'm starting to get used to it, but things like this, I understand the error message, I just don't know how to resolve them... I'm used to a strongly typed and compiled language over an interpreted language like Python.

Here I'm assuming that I have the operator within the Vector class overloaded to be able to multiply vectors by scalars... Yet Python is yelling at me that it is an unsupported operand. What can I do to resolve this issue? As a side note if you notice any other potential bugs or issues with the code please don't hesitate to mention them in a comment. I'm still learning this language!

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59
  • 1
    You have to define `__rmul__` as only the right operand is a Vector. – Michael Butscher Jul 17 '20 at 00:03
  • @MichaelButscher hmm okay... Thank You... I didn't really know about `__rmul__`... I'm used to C/C++ operator overloading... – Francis Cugler Jul 17 '20 at 00:03
  • @MichaelButscher Okay, that worked by adding in the `__rmul__` however, my expected output should be (1.5, 1.5) and I'm getting (1,1)... I did modify my Vector and Line classes to return floats by wrapping their return values with the `float()` method... yet it is still producing (1,1)... I may have to ask a new question for this... – Francis Cugler Jul 17 '20 at 00:11
  • 1
    @MichaelButscher I fixed the output from above. When it dawned on me that the backend of Python is C, it took me back to the formatted string in C with `printf()`. I had changed `%d` to `%f`. When that worked, I then truncated it to `%.2f` instead. Now I'm getting `(1.50, 1.50)` as my output! I appreciate your help! I'm sort of new to Python and I'm getting the hang of it, but I don't use it all that often. I was scratching my head for about an hour on this one. When I searched, all I was getting was results on basic overloading and nothing was mentioning `__rmul__`. Kudos!!! – Francis Cugler Jul 17 '20 at 00:26

0 Answers0