diff --git a/src/c3nav/mapdata/utils/index.py b/src/c3nav/mapdata/utils/index.py new file mode 100644 index 00000000..28fb1dad --- /dev/null +++ b/src/c3nav/mapdata/utils/index.py @@ -0,0 +1,70 @@ +import operator +from functools import reduce + +from django.core import checks +from shapely import speedups + +if speedups.available: + speedups.enable() + + +try: + import rtree +except OSError: + rtree_index = False + + class Index: + def __init__(self): + self.objects = {} + + def insert(self, value, geometry): + self.objects[value] = geometry + + def delete(self, value): + self.objects.pop(value) + + def intersections(self, geometry): + return self.objects.values() +else: + rtree_index = True + + class Index: + def __init__(self): + self._index = rtree.index.Index() + self._bounds = {} + + def insert(self, value, geometry): + try: + geoms = geometry.geoms + except AttributeError: + self._bounds.setdefault(value, []).append(geometry.bounds) + self._index.insert(value, geometry.bounds) + else: + for geom in geoms: + self.insert(value, geom) + + def delete(self, value): + for bounds in self._bounds.pop(value): + self._index.delete(value, bounds) + + def intersections(self, geometry): + try: + geoms = geometry.geoms + except AttributeError: + return set(self._index.intersection(geometry.bounds)) + else: + return reduce(operator.__or__, (self.intersections(geom) for geom in geoms), set()) + + +@checks.register() +def check_svg_renderer(app_configs, **kwargs): + errors = [] + if not rtree_index: + errors.append( + checks.Warning( + 'The libspatialindex_c library is missing. This will drastically slow down c3nav rendering.', + obj='rtree.index.Index', + id='c3nav.mapdata.W001', + ) + ) + return errors diff --git a/src/c3nav/mapdata/utils/svg.py b/src/c3nav/mapdata/utils/svg.py index b36a8fd7..2ea9982f 100644 --- a/src/c3nav/mapdata/utils/svg.py +++ b/src/c3nav/mapdata/utils/svg.py @@ -6,7 +6,7 @@ from itertools import chain import numpy as np from django.conf import settings -from django.core.checks import Error, register +from django.core import checks from PIL import Image from shapely.affinity import translate from shapely.geometry import LineString, Polygon @@ -20,12 +20,12 @@ if settings.SVG_RENDERER == 'rsvg': from pgi.repository import Rsvg -@register() +@checks.register() def check_svg_renderer(app_configs, **kwargs): errors = [] if settings.SVG_RENDERER not in ('rsvg', 'rsvg-convert', 'inkscape'): errors.append( - Error( + checks.Error( 'Invalid SVG renderer: '+settings.SVG_RENDERER, obj='settings.SVG_RENDERER', id='c3nav.mapdata.E001', diff --git a/src/requirements/production.txt b/src/requirements/production.txt index 0c13e0ab..75c4723e 100644 --- a/src/requirements/production.txt +++ b/src/requirements/production.txt @@ -5,6 +5,7 @@ csscompressor djangorestframework>=3.6,<3.7 django-filter>=1.0,<1.1 shapely>=1.5,<1.6 +rtree>=0.8,<0.9 celery>=4.0,<4.1 requests>=2.17,<2.18 Pillow>=4.1,<4.2