'Simplify a complex Polygon using the Douglas-Peucker algorithm
- NB This uses Python, better performance will be gained by doing
this direct from the database if you are using PostGIS:
ST_Simplify() is available as
db(query).select(table.the_geom.st_simplify(tolerance).st_astext().with_alias(\'wkt\')).first().wkt
db(query).select(table.the_geom.st_simplify(tolerance).st_asgeojson().with_alias(\'geojson\')).first().geojson
@param wkt: the WKT string to be simplified (usually coming from a gis_location record)
@param tolerance: how aggressive a simplification to perform
@param preserve_topology: whether the simplified geometry should be maintained
@param output: whether to output as WKT or GeoJSON format
@param precision: the number of decimal places to include in the output'

@staticmethod
def simplify(wkt, tolerance=None, preserve_topology=True, output='wkt', precision=None):

    from shapely.geometry import Point, LineString, Polygon, MultiPolygon
    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')
    try:
        shape = wkt_loads(wkt)
    except:
        wkt = (wkt[10] if wkt else wkt)
        current.log.error(('Invalid    Shape:    %s' % wkt))
        return None
    settings = current.deployment_settings
    if (not precision):
        precision = settings.get_gis_precision()
    if (tolerance is None):
        tolerance = settings.get_gis_simplify_tolerance()
    if tolerance:
        shape = shape.simplify(tolerance, preserve_topology)
    formatter = ('.%sf' % precision)
    def shrink_polygon(shape):
        '    Helper    Function    '
        points = shape.exterior.coords
        coords = []
        cappend = coords.append
        for point in points:
            x = float(format(point[0], formatter))
            y = float(format(point[1], formatter))
            cappend((x, y))
        return Polygon(LineString(coords))
    geom_type = shape.geom_type
    if (geom_type == 'MultiPolygon'):
        polygons = shape.geoms
        p = []
        pappend = p.append
        for polygon in polygons:
            pappend(shrink_polygon(polygon))
        shape = MultiPolygon([s for s in p])
    elif (geom_type == 'Polygon'):
        shape = shrink_polygon(shape)
    elif (geom_type == 'LineString'):
        points = shape.coords
        coords = []
        cappend = coords.append
        for point in points:
            x = float(format(point[0], formatter))
            y = float(format(point[1], formatter))
            cappend((x, y))
        shape = LineString(coords)
    elif (geom_type == 'Point'):
        x = float(format(shape.x, formatter))
        y = float(format(shape.y, formatter))
        shape = Point(x, y)
    else:
        current.log.info(('Cannot    yet    shrink    Geometry:    %s' % geom_type))
    if (output == 'wkt'):
        output = shape.to_wkt()
    elif (output == 'geojson'):
        from ..geojson import dumps
        output = dumps(shape, separators=SEPARATORS)
    return output
