Ejemplo n.º 1
0
 def reflect( self, x, y ):
     ''' Calculates reflection between two circles. Returns the resulting momentum vector. 
     Takes the position of the reflection point as argument.
     
     Test:
     >>> from data import circle
     >>> from data import vector2d
     >>> c1 = circle.Circle()
     >>> c1.position.x = -4
     >>> c1.position.y = 2
     >>> c1.radius = 2
     >>> c1.momentum = vector2d.Vector2d( 4, 2 )
     >>> c2 = circle.Circle()
     >>> c2.position.x = 0
     >>> c2.position.y = 2
     >>> c2.radius = 2
     >>> x = -2
     >>> y = 2
     >>> reflector = CircleCircleReflector( c1, c2 )
     >>> v = reflector.reflect( x, y )
     >>> print( '{0:.2f}, {1:.2f}'.format(v.x, v.y) )
     -4.00, 2.00
     '''
     
     # Move reflection point to origin.
     reflectionX = x - self._circle2.position.x
     reflectionY = y - self._circle2.position.y
     
     # Prepare comparison.
     epsilon = 0.001
     
     # Default values are used it the tangent line is vertical.
     pointX1 = reflectionX
     pointY1 = -1
     pointX2 = reflectionX
     pointY2 = 1
     
     # Calculate tangent line y = mx + b
     if not comparison.floatEqual( reflectionY, 0, epsilon ):
         # Tangent line is perpendicular to the radius, so it's slope m will be a negative reciprocal
         # of the slope of the line intersecting the reflection point.
         m = -(reflectionX / reflectionY)
             
         # Find b with the slope and the reflection point. Default value is used if tangent line is 
         # horizontal.
         b = reflectionY
         if not comparison.floatEqual( reflectionX, 0, epsilon ):
             b = reflectionY / (m * reflectionX)
         
         # Calculate tangent line points left and right of reflection point.
         pointX1 = reflectionX - 1
         pointY1 = m * pointX1 + b 
         pointX2 = reflectionX + 1
         pointY2 = m * pointX2 + b 
     
     # Calculate result.
     x, y = vector.reflectAtLine( self._circle1.momentum.x, self._circle1.momentum.y,
                                  pointX1, pointY1, pointX2, pointY2 )
     return vector2d.Vector2d( x, y )
Ejemplo n.º 2
0
    def reflect( self, x, y ):
        ''' Calculates reflection between two circles. Returns the resulting momentum vector. 
        Takes the position of the reflection point as argument.
        
        Test:
        >>> from data import circle
        >>> from data import rect
        >>> from data import vector2d
        >>> c = circle.Circle()
        >>> c.position.x = -4
        >>> c.position.y = 2
        >>> c.radius = 2
        >>> c.momentum = vector2d.Vector2d( 4, 2 )
        >>> r = rect.Rect()
        >>> r.position.x = 0
        >>> r.position.y = 2
        >>> r.width = 4
        >>> r.height = 4
        >>> x = -2
        >>> y = 2
        >>> reflector = CircleRectReflector( c, r )
        >>> v = reflector.reflect( x, y )
        >>> print( '{0:.2f}, {1:.2f}'.format(v.x, v.y) )
        -4.00, 2.00
        '''
        # Calculate values of all four points of the rectangle without rotation.
        heightHalf = self._rect.height * 0.5
        widthHalf = self._rect.width * 0.5
        xPlus = widthHalf
        xMinus = -widthHalf
        yPlus = heightHalf
        yMinus = -heightHalf

        # Rotate reflection point back and move to origin.
        rotatedX = rotation.rotateX( x - self._rect.position.x, 
                                     y - self._rect.position.y, 
                                     -self._rect.angle )
        rotatedY = rotation.rotateY( x - self._rect.position.x, 
                                     y - self._rect.position.y,
                                     -self._rect.angle )
        
        # Prepare comparison.
        pointX1 = 0
        pointY1 = 0
        pointX2 = 0
        pointY2 = 0
        
        left, up, right = range(3)
        dists = []
        dists.append( py.pointToLineDistance(rotatedX, rotatedY, xMinus, yMinus, xMinus, yPlus) )
        dists.append( py.pointToLineDistance(rotatedX, rotatedY, xMinus, yPlus,  xPlus,  yPlus) )
        dists.append( py.pointToLineDistance(rotatedX, rotatedY, xPlus,  yMinus, xPlus,  yPlus) )
        dists.append( py.pointToLineDistance(rotatedX, rotatedY, xMinus, yMinus, xPlus,  yMinus) )
        line = dists.index( min(dists) )

        # Left.
        if line is left:
            pointX1 = xMinus
            pointY1 = yMinus
            pointX2 = xMinus
            pointY2 = yPlus
        # Up.
        elif line is up:
            pointX1 = xMinus
            pointY1 = yPlus
            pointX2 = xPlus
            pointY2 = yPlus
        # Right.
        elif line is right:
            pointX1 = xPlus
            pointY1 = yMinus
            pointX2 = xPlus
            pointY2 = yPlus
        # Down.
        else:
            pointX1 = xMinus
            pointY1 = yMinus
            pointX2 = xPlus
            pointY2 = yMinus
            
        # Rotate line points.
        rotatedX1 = rotation.rotateX( pointX1, pointY1, self._rect.angle ) + self._rect.position.x
        rotatedY1 = rotation.rotateY( pointX1, pointY1, self._rect.angle ) + self._rect.position.y
        rotatedX2 = rotation.rotateX( pointX2, pointY2, self._rect.angle ) + self._rect.position.x
        rotatedY2 = rotation.rotateY( pointX2, pointY2, self._rect.angle ) + self._rect.position.y
        
        # Calculate result.
        x, y = vector.reflectAtLine( self._circle.momentum.x, self._circle.momentum.y,
                                     rotatedX1, rotatedY1, rotatedX2, rotatedY2 )
        return vector2d.Vector2d( x, y )