calculate better representative point for geometries
This commit is contained in:
parent
94a23454a1
commit
fd74ca3258
2 changed files with 11 additions and 5 deletions
|
@ -4,9 +4,10 @@ from collections import OrderedDict
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from shapely.geometry import Point, mapping
|
from shapely.geometry import LineString, Point, mapping
|
||||||
|
|
||||||
from c3nav.mapdata.models.base import SerializableMixin
|
from c3nav.mapdata.models.base import SerializableMixin
|
||||||
|
from c3nav.mapdata.utils.geometry import assert_multilinestring
|
||||||
from c3nav.mapdata.utils.json import format_geojson
|
from c3nav.mapdata.utils.json import format_geojson
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,8 +63,13 @@ class GeometryMixin(SerializableMixin):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def centroid(self):
|
def point(self):
|
||||||
return self.geometry.centroid
|
c = self.geometry.centroid
|
||||||
|
x1, y1, x2, y2 = self.geometry.bounds
|
||||||
|
lines = (tuple(assert_multilinestring(LineString(((x1, c.y), (x2, c.y))).intersection(self.geometry))) +
|
||||||
|
tuple(assert_multilinestring(LineString(((c.x, y1), (c.x, y2))).intersection(self.geometry))))
|
||||||
|
return min(lines, key=lambda line: (line.distance(c), line.length),
|
||||||
|
default=self.geometry.representative_point).centroid
|
||||||
|
|
||||||
def serialize(self, **kwargs):
|
def serialize(self, **kwargs):
|
||||||
result = super().serialize(**kwargs)
|
result = super().serialize(**kwargs)
|
||||||
|
@ -76,7 +82,7 @@ class GeometryMixin(SerializableMixin):
|
||||||
if geometry:
|
if geometry:
|
||||||
result['geometry'] = format_geojson(mapping(self.geometry), round=False)
|
result['geometry'] = format_geojson(mapping(self.geometry), round=False)
|
||||||
if simple_geometry:
|
if simple_geometry:
|
||||||
result['point'] = (self.level_id, ) + tuple(round(i, 2) for i in self.centroid.coords[0])
|
result['point'] = (self.level_id, ) + tuple(round(i, 2) for i in self.point.coords[0])
|
||||||
if not isinstance(self.geometry, Point):
|
if not isinstance(self.geometry, Point):
|
||||||
result['bounds'] = ((int(math.floor(self.minx)), int(math.floor(self.miny))),
|
result['bounds'] = ((int(math.floor(self.minx)), int(math.floor(self.miny))),
|
||||||
(int(math.ceil(self.maxx)), int(math.ceil(self.maxy))))
|
(int(math.ceil(self.maxx)), int(math.ceil(self.maxy))))
|
||||||
|
|
|
@ -77,7 +77,7 @@ def locations_for_request(request) -> Mapping[int, LocationSlug]:
|
||||||
obj.subtitle, obj.order
|
obj.subtitle, obj.order
|
||||||
if isinstance(obj, GeometryMixin):
|
if isinstance(obj, GeometryMixin):
|
||||||
# noinspection PyStatementEffect
|
# noinspection PyStatementEffect
|
||||||
obj.centroid
|
obj.point
|
||||||
|
|
||||||
cache.set(cache_key, locations, 300)
|
cache.set(cache_key, locations, 300)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue