Beispiel #1
0
    def to_svg(geometries, envelope=None, max_width=300, max_height=300):

        svg_top = '<svg xmlns="http://www.w3.org/2000/svg" ' \
            'xmlns:xlink="http://www.w3.org/1999/xlink" '

        if len(geometries) == 0:
            return svg_top + '/>'
        else:
            geometry = GeometryCollection(geometries)
            # Establish SVG canvas that will fit all the data + small space
            xmin, ymin, xmax, ymax = geometry.bounds
            if xmin == xmax and ymin == ymax:
                # This is a point; buffer using an arbitrary size
                xmin, ymin, xmax, ymax = geometry.buffer(1).bounds
            else:
                # Expand bounds by a fraction of the data ranges
                expand = 0.04  # or 4%, same as R plots
                widest_part = max([xmax - xmin, ymax - ymin])
                expand_amount = widest_part * expand
                xmin -= expand_amount
                ymin -= expand_amount
                xmax += expand_amount
                ymax += expand_amount
            dx = xmax - xmin
            dy = ymax - ymin
            width = min([max([100., dx]), max_width])
            height = min([max([100., dy]), max_height])
            try:
                scale_factor = max([dx, dy]) / max([width, height])
            except ZeroDivisionError:
                scale_factor = 1.

            view_box, transform = None, None
            if envelope:
                xxmin, yymin, xxmax, yymax = envelope.bounds
                view_box = "{} {} {} {}".format(xxmin, yymin, xxmax - xxmin,
                                                yymax - yymin)
                transform = "matrix(1,0,0,-1,0,{})".format(yymax + yymin)
            else:
                view_box = "{} {} {} {}".format(xmin, ymin, dx, dy)
                transform = "matrix(1,0,0,-1,0,{})".format(ymax + ymin)

            l = []
            for g in geometries:
                svg = g.svg(scale_factor)
                if hasattr(g, 'plot'):
                    xml = ElementTree.fromstring(svg)
                    for v in g.plot:
                        xml.set(v, g.plot[v])
                    svg = ElementTree.tostring(xml).decode()
                l.append(svg)

            body = '<g>' + ''.join(l) + '</g>'

            return ('{0} width="{2}" height="{3}" viewBox="{1}" '
                    'preserveAspectRatio="xMidYMid meet">'
                    '<g transform="{4}">{5}</g></svg>').format(
                        svg_top, view_box, width, height, transform, body)