'Returns a gluon.sql.Rows of Features within a Polygon.
The Polygon can be either a WKT string or the ID of a record in the
gis_location table
Currently unused.
@ToDo: Optimise to not use try/except'

def get_features_in_polygon(self, location, tablename=None, category=None):

    from shapely.geos import ReadingError
    from shapely.wkt import loads as wkt_loads
    try:
        from shapely import speedups
        speedups.enable()
    except:
        current.log.info('S3GIS', 'Upgrade    Shapely    for    Performance    enhancements')
    db = current.db
    s3db = current.s3db
    locations = s3db.gis_location
    try:
        location_id = int(location)
        location = db((locations.id == location_id)).select(locations.wkt, locations.lon_min, locations.lon_max, locations.lat_min, locations.lat_max, limitby=(0, 1)).first()
        if location:
            wkt = location.wkt
            if (wkt and (wkt.startswith('POLYGON') or wkt.startswith('MULTIPOLYGON'))):
                lon_min = location.lon_min
                lon_max = location.lon_max
                lat_min = location.lat_min
                lat_max = location.lat_max
            else:
                current.log.error("Location    searched    within    isn't    a    Polygon!")
                return None
    except:
        wkt = location
        if (wkt.startswith('POLYGON') or wkt.startswith('MULTIPOLYGON')):
            lon_min = None
        else:
            current.log.error("This    isn't    a    Polygon!")
            return None
    try:
        polygon = wkt_loads(wkt)
    except:
        current.log.error('Invalid    Polygon!')
        return None
    table = s3db[tablename]
    if ('location_id' not in table.fields()):
        current.log.error("This    table    doesn't    have    a    location_id!")
        return None
    query = (table.location_id == locations.id)
    if ('deleted' in table.fields):
        query &= (table.deleted == False)
    features = db(query).select(locations.wkt, locations.lat, locations.lon, table.ALL)
    output = Rows()
    if (lon_min is None):
        for row in features:
            _location = row.gis_location
            wkt = _location.wkt
            if (wkt is None):
                lat = _location.lat
                lon = _location.lon
                if ((lat is not None) and (lon is not None)):
                    wkt = self.latlon_to_wkt(lat, lon)
                else:
                    continue
            try:
                shape = wkt_loads(wkt)
                if shape.intersects(polygon):
                    output.records.append(row)
            except ReadingError:
                current.log.error('Error    reading    wkt    of    location    with    id', value=row.id)
    else:
        def in_bbox(row):
            _location = row.gis_location
            return ((((_location.lon > lon_min) & (_location.lon < lon_max)) & (_location.lat > lat_min)) & (_location.lat < lat_max))
        for row in features.find((lambda row: in_bbox(row))):
            _location = row.gis_location
            wkt = _location.wkt
            if (wkt is None):
                lat = _location.lat
                lon = _location.lon
                if ((lat is not None) and (lon is not None)):
                    wkt = self.latlon_to_wkt(lat, lon)
                else:
                    continue
            try:
                shape = wkt_loads(wkt)
                if shape.intersects(polygon):
                    output.records.append(row)
            except ReadingError:
                current.log.error('Error    reading    wkt    of    location    with    id', value=row.id)
    return output
