improve _create_geometry performance by replacing affine_transform with numpy

This commit is contained in:
Laura Klünder 2017-10-20 11:55:17 +02:00
parent 1b3fab8993
commit bf7ba02065

View file

@ -4,10 +4,11 @@ import re
import subprocess import subprocess
from itertools import chain from itertools import chain
import numpy as np
from django.conf import settings from django.conf import settings
from django.core.checks import Error, register from django.core.checks import Error, register
from PIL import Image from PIL import Image
from shapely.affinity import affine_transform, translate from shapely.affinity import translate
from shapely.geometry import LineString, Polygon from shapely.geometry import LineString, Polygon
from shapely.ops import unary_union from shapely.ops import unary_union
@ -135,12 +136,17 @@ class SVGImage:
def _geometry_to_svg(self, geom): def _geometry_to_svg(self, geom):
if isinstance(geom, Polygon): if isinstance(geom, Polygon):
return ('<path d="' + return ('<path d="' +
' '.join((('M %.1f %.1f L'+(' %.1f %.1f'*(len(ring.coords)-1))) % tuple(ring.ctypes)) ' '.join((('M %.1f %.1f L'+(' %.1f %.1f'*(len(ring.coords)-1))) %
tuple((np.array(ring)
* np.array((self.scale, -self.scale))
+ np.array((-self.left*self.scale, self.top*self.scale))).flatten()))
for ring in chain((geom.exterior,), geom.interiors)) for ring in chain((geom.exterior,), geom.interiors))
+ '"/>').replace('.0 ', ' ') + '"/>').replace('.0 ', ' ')
if isinstance(geom, LineString): if isinstance(geom, LineString):
return (('<path d="M %.1f %.1f L'+(' %.1f %.1f'*(geom.coords-1))+'"/>') % return (('<path d="M %.1f %.1f L'+(' %.1f %.1f'*(geom.coords-1))+'"/>') %
tuple(geom.ctypes)).replace('.0 ', ' ') tuple((np.array(geom)
* np.array((self.scale, -self.scale))
+ np.array((-self.left*self.scale, self.top*self.scale))).flatten())).replace('.0 ', ' ')
try: try:
geoms = geom.geoms geoms = geom.geoms
except AttributeError: except AttributeError:
@ -149,15 +155,7 @@ class SVGImage:
def _create_geometry(self, geometry, attribs='', tag='g'): def _create_geometry(self, geometry, attribs='', tag='g'):
# convert a shapely geometry into an svg xml element # convert a shapely geometry into an svg xml element
return '<'+tag+attribs+'>'+self._geometry_to_svg( return '<'+tag+attribs+'>'+self._geometry_to_svg(geometry)+'</'+tag+'>'
# scale and move the object into position, this is equivalent to:
# geometry = translate(geometry, xoff=0-self.left, yoff=0-self.bottom)
# geometry = scale(geometry, xfact=1, yfact=-1, origin=(self.width / 2, self.height / 2))
# geometry = scale(geometry, xfact=self.scale, yfact=self.scale, origin=(0, 0))
affine_transform(geometry, (self.scale, 0.0,
0.0, -self.scale,
-(self.left) * self.scale, (self.top) * self.scale))
)+'</'+tag+'>'
def register_clip_path(self, geometry): def register_clip_path(self, geometry):
defid = 'clip'+str(self.clip_path_i) defid = 'clip'+str(self.clip_path_i)