# -*- coding: iso-8859-1 -*-
#
# quakepy/QPPolygon.py
# $Id: QPPolygon.py 184 2009-03-31 22:16:25Z fab $
#
# The QuakePy package
# http://www.quakepy.org
#

############################################################################
#    Copyright (C) 2007-2009 by Fabian Euchner and Danijel Schorlemmer     #
#    fabian@fabian-euchner.de                                              #
#                                                                          #
#    This program is free software; you can redistribute it and#or modify  #
#    it under the terms of the GNU General Public License as published by  #
#    the Free Software Foundation; either version 2 of the License, or     #
#    (at your option) any later version.                                   #
#                                                                          #
#    This program is distributed in the hope that it will be useful,       #
#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
#    GNU General Public License for more details.                          #
#                                                                          #
#    You should have received a copy of the GNU General Public License     #
#    along with this program; if not, write to the                         #
#    Free Software Foundation, Inc.,                                       #
#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
############################################################################

"""
The QuakePy package
http://www.quakepy.org
"""

__version__  = '$Id: QPPolygon.py 184 2009-03-31 22:16:25Z fab $'
__revision__ = '$Revision: 184 $'
__author__   = "Fabian Euchner <fabian@fabian-euchner.de>, Danijel Schorlemmer <ds@usc.edu>"
__license__  = "GPL"

from shapely.geometry import Polygon, Point

from QPUtils import *

class QPPolygon( object ):
    """
    QuakePy: QPPolygon

    QPPolygon implements a 2-dim polygon, using the Shapely package
    """
    EPSILON = 10e-9

    # Shapely polygon object
    polygon = None
    
    # polygon vertices
    vertices = []

    # polygon extent
    extent = {}

    def __init__( self, vertices, **kwargs ):
        """
        vertices can be either filename or stream from which data is read (2-column ASCII, lon | lat),
        or iterable of two components, e.g.
        [ [,], [,], ... ] or ( (,), (,), ... )
        """
        if isinstance( vertices, ( list, tuple ) ):
            self.vertices = vertices
        else:
            try:
                input = getQPDataSource( vertices, **kwargs )
            except:
                raise IOError, "QPPolygon - cannot open data stream from %s" % vertices
                
            for line in input:

                if len( line.strip() ) > 0:
                    v = line.split()
                    self.vertices.append( [ float(v[0]), float(v[1]) ] )

        if len( self.vertices ) > 0:
            self.polygon = Polygon( self.vertices )
            self.getExtent()

    def getExtent( self ):
        
        # Determine extent of polygon bounding box
        self.extent = { 'lonMin': self.polygon.bounds[0],
                        'lonMax': self.polygon.bounds[2],
                        'latMin': self.polygon.bounds[1],
                        'latMax': self.polygon.bounds[3] }
        
    def isInside( self, fX, fY ):
        """
        check if point( fX, fY ) is truly inside polygon (not on boundary)
        'true'  if inside
        'false' if outside or on boundary
        """

        if self.polygon.contains( Point( fX, fY ) ):
            return True
        else:
            return False

    def isInsideOrOnBoundary( self, fX, fY ):
        """
        check if point( fX, fY ) is inside polygon or on boundary
        'true'  if inside or on boundary
        'false' if outside
        """

        if self.isInside( fX, fY ) or self.isOnBoundary( fX, fY ):
            return True
        else:
            return False

    def isOnBoundary( self, fX, fY ):

        if self.polygon.boundary.contains( Point( fX, fY ) ):
            return True
        else:
            return False
        