Search code examples
pythonsympycomputational-geometry

Sympy errors - geometry bug


I'm writing a program that will take two L-shaped figures with long sides 1.

L figure is looking like this:enter image description here

Here is my code:

    from sympy import *
    from sympy.geometry import *
    import math


    fi=acos(2/sqrt(5))
    fi2=asin(2/sqrt(5))

    class L:
      def __init__(self, alfa, x, y):
        self.alfa = alfa
        self.A = Point(x,y)
        self.B = Point(x+cos(alfa),y+sin(alfa))
        self.C = Point(x+(sqrt(5)/2)*cos(alfa+fi),y+(sqrt(5)/2)*sin(alfa+fi))
        self.D = Point(x+(sqrt(2)/2)*cos(alfa+45),y+(sqrt(2)/2)*sin(alfa+45))
        self.E = Point(x+(sqrt(5)/2)*cos(alfa+fi2),y+(sqrt(5)/2)*sin(alfa+fi2))
        self.F = Point(x+cos(90+alfa),y+sin(alfa+90))
        self.P = Polygon(self.A, self.B, self.C, self.D, self.E, self.F)


    def inter(a=L(0,0,0), b=L(0,0,0)):
        t=false
        for i in range(len((a.P).vertices)):
          if((b.P.encloses_point((a.P).vertices[i]))==true):
            t=true
            print("wrong:", i,"th vertex of 1st polygon")
            print("(",(a.P).vertices[i].x,",",(a.P).vertices[i].y,")")
            for j in range(len(b.P.vertices)):
              print("(", b.P.vertices[j].x,", ", b.P.vertices[j].y,")")
            break
        for i in range(len((b.P).vertices)):
          if((a.P.encloses_point((b.P).vertices[i]))==true):
            t=true
            break
        return t


    print(inter(L(0,0,0),L(0,1,0)))

This code looks well to me, but I'm having a bug. This code returns that that two L's have intersection. To make thing clear to reader, this is how that L's look:

o

So, C is not in the second L, here is output of my code:

wrong 2th vertex of 1st polygon
( 1 , 1/2 )
( 1 ,  0 )
( 2 ,  0 )
( 2 ,  1/2 )
( sqrt(2)*cos(45)/2 + 1 ,  sqrt(2)*sin(45)/2 )
( 3/2 ,  1 )
( cos(90) + 1 ,  sin(90) )
True

Also by the documentation(https://docs.sympy.org/latest/modules/geometry/polygons.html), point on the border of polygon is consider false. So point C hace to return false, but program returns true. When I try simpler code it works fine:

    >>> a=Polygon((1,0),(2,0),(2,1),(1,1))
    >>> a.encloses_point(Point(1,1/2))
    False

I'm out of ideas what went wrong. What happened with function encloses_point? Can someone help?

Thanks in advance


Solution

  • An intersection is comprised of points in common. SymPy does not compute areas in common as mentioned here. While a Point on the border is not in a Polygon, a Point is considered a valid intersection entity:

    >>> from sympy import Triangle
    >>> Triangle((0,0),(1,1),(0,1)).intersection(Triangle((0,0),(-1,-1),(0,-1)))
    [Point2D(0, 0)]
    

    In your case this is the logical problem but it is not the actual problem. You think you are dealing with an L shaped polygon but you aren't. SymPy trig functions interpret their arguments in radians but I suspect you think you are working with degrees (cos(90) != 0 but cos(rad(90)) = 0 where rad is imported from sympy.geometry.polygon). (1, 1/2) is in the polygon you defined...just not in the one you think you are dealing with. :-)