diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2019-03-14 15:53:32 +0100 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2019-04-24 19:41:37 +0200 |
commit | b968ffd830d1040a4884202c670d81776eb2b9d8 (patch) | |
tree | d78744c7f581b5bde98906db2f116b118e0db323 | |
parent | beec28bb29076d6fa79b91f03d55658b534005a2 (diff) | |
download | Ishtar-b968ffd830d1040a4884202c670d81776eb2b9d8.tar.bz2 Ishtar-b968ffd830d1040a4884202c670d81776eb2b9d8.zip |
GIS: deduce precise point from polygon
-rw-r--r-- | archaeological_finds/tests.py | 90 | ||||
-rw-r--r-- | ishtar_common/models.py | 5 | ||||
-rw-r--r-- | ishtar_common/utils.py | 96 |
3 files changed, 147 insertions, 44 deletions
diff --git a/archaeological_finds/tests.py b/archaeological_finds/tests.py index a56c997eb..00a45ba6a 100644 --- a/archaeological_finds/tests.py +++ b/archaeological_finds/tests.py @@ -1596,6 +1596,18 @@ class GeomaticTest(FindInit, TestCase): self.assertEqual(base_find.point_source_item, unicode(models.BaseFind._meta.verbose_name)) + # re-save do not change sources + base_find.save() + base_find = models.BaseFind.objects.get(pk=base_find.pk) + self.assertIsNotNone(base_find.point) + self.assertIsNotNone(base_find.point_2d) + self.assertIsNotNone(base_find.x) + self.assertIsNotNone(base_find.y) + self.assertIsNotNone(base_find.z) + self.assertEqual(base_find.point_source, 'P') # precise + self.assertEqual(base_find.point_source_item, + unicode(models.BaseFind._meta.verbose_name)) + # form input base_find.x = 2 base_find.y = 3 @@ -1608,6 +1620,14 @@ class GeomaticTest(FindInit, TestCase): self.assertEqual(base_find.point_source, 'P') # precise self.assertEqual(base_find.point_source_item, unicode(models.BaseFind._meta.verbose_name)) + # re-save do not change sources + base_find.save() + base_find = models.BaseFind.objects.get(pk=base_find.pk) + self.assertIsNotNone(base_find.point_2d) + self.assertIsNotNone(base_find.point) + self.assertEqual(base_find.point_source, 'P') # precise + self.assertEqual(base_find.point_source_item, + unicode(models.BaseFind._meta.verbose_name)) # reinit base_find.x = None @@ -1637,7 +1657,24 @@ class GeomaticTest(FindInit, TestCase): cr = ContextRecord.objects.get(pk=base_find.context_record.pk) base_find = models.BaseFind.objects.get(pk=base_find.pk) base_find.save() - self.assertEqual(base_find.point_2d, cr.town.center) + base_find = models.BaseFind.objects.get(pk=base_find.pk) + bfp = GEOSGeometry(base_find.point_2d.ewkt) + bfp.transform(4326) + tp = GEOSGeometry(cr.town.center.ewkt) + tp.transform(4326) + self.assertTrue(bfp.distance(tp) < 0.0001) + self.assertEqual(base_find.multi_polygon, cr.town.limit) + self.assertEqual(base_find.point_source, 'T') # town + self.assertEqual(base_find.point_source_item, + unicode(ContextRecord._meta.verbose_name)) + # re-save do not change sources + base_find.save() + base_find = models.BaseFind.objects.get(pk=base_find.pk) + bfp = GEOSGeometry(base_find.point_2d.ewkt) + bfp.transform(4326) + tp = GEOSGeometry(cr.town.center.ewkt) + tp.transform(4326) + self.assertTrue(bfp.distance(tp) < 0.0001) self.assertEqual(base_find.multi_polygon, cr.town.limit) self.assertEqual(base_find.point_source, 'T') # town self.assertEqual(base_find.point_source_item, @@ -1658,4 +1695,55 @@ class GeomaticTest(FindInit, TestCase): self.assertEqual(base_find.point_source, 'P') # precise self.assertEqual(base_find.point_source_item, unicode(models.BaseFind._meta.verbose_name)) + # re-save do not change sources + base_find.save() + base_find = models.BaseFind.objects.get(pk=base_find.pk) + self.assertIsNotNone(base_find.point_2d) + self.assertIsNotNone(base_find.point) + self.assertEqual(base_find.point_2d.wkt, 'POINT (5 6)') + self.assertEqual(base_find.point_source, 'P') # precise + self.assertEqual(base_find.point_source_item, + unicode(models.BaseFind._meta.verbose_name)) + + def test_post_save_polygon(self): + find = self.finds[0] + base_find = find.base_finds.all()[0] + srs, __ = SpatialReferenceSystem.objects.get_or_create( + txt_idx='wgs84', defaults={"srid": 4326, "label": 'WGS84', + 'auth_name': 'EPSG'} + ) + + base_find = models.BaseFind.objects.get(pk=base_find.pk) + + # get centroid geom from poly + limit = 'MULTIPOLYGON(((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2)),' \ + '((6 3,9 2,9 4,6 3)))' + base_find.multi_polygon = 'SRID=4326;' + limit + base_find.point_source = None + base_find.point_2d = None + base_find.point = None + base_find.save() + + base_find = models.BaseFind.objects.get(pk=base_find.pk) + self.assertIsNotNone(base_find.point_2d) + self.assertEqual(base_find.point_source, 'M') # from multi polygon + # resaving do not change source + base_find.save() + base_find = models.BaseFind.objects.get(pk=base_find.pk) + self.assertIsNotNone(base_find.point_2d) + self.assertEqual(base_find.point_source, 'M') # from multi polygon + base_find = models.BaseFind.objects.get(pk=base_find.pk) + base_find.point_source = None + base_find.spatial_reference_system = srs + base_find.x = "42" + base_find.y = "3" + base_find.save() + base_find = models.BaseFind.objects.get(pk=base_find.pk) + self.assertEqual(base_find.point_2d.ewkt, "SRID=4326;POINT (42 3)") + self.assertEqual(base_find.point_source, 'P') + # resaving do not change source + base_find.save() + base_find = models.BaseFind.objects.get(pk=base_find.pk) + self.assertEqual(base_find.point_2d.ewkt, "SRID=4326;POINT (42 3)") + self.assertEqual(base_find.point_source, 'P') diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 57283e8f4..f802b434c 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -1671,7 +1671,10 @@ post_delete.connect(post_save_cache, sender=SpatialReferenceSystem) class GeoItem(models.Model): - GEO_SOURCE = ('T', _(u"Town")), ('P', _(u"Precise")) + GEO_SOURCE = ( + ('T', _(u"Town")), ('P', _(u"Precise")), + ('M', _("Polygon")) + ) # gis x = models.FloatField(_(u'X'), blank=True, null=True) diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py index 83627cafc..7a51936b1 100644 --- a/ishtar_common/utils.py +++ b/ishtar_common/utils.py @@ -497,8 +497,45 @@ def post_save_geo(sender, **kwargs): current_source = "default" if hasattr(instance.__class__, "_meta"): current_source = unicode(instance.__class__._meta.verbose_name) - if instance.point_source_item and \ - instance.point_source_item != current_source: # refetch + + profile = get_current_profile() + modified = False + + if hasattr(instance, 'multi_polygon'): + if instance.multi_polygon_source_item and \ + instance.multi_polygon_source_item != current_source: # refetch + instance.multi_polygon = None + instance.multi_polygon_source = None + + if instance.multi_polygon and not instance.multi_polygon_source: + # should be a db source + instance.multi_polygon_source = 'P' + instance.multi_polygon_source_item = current_source + modified = True + elif instance.multi_polygon_source != 'P': + precise_poly = instance.get_precise_polygons() + if precise_poly: + poly, source_item = precise_poly + instance.multi_polygon = poly + instance.multi_polygon_source = 'P' + instance.multi_polygon_source_item = source_item + modified = True + elif profile.use_town_for_geo: + poly = instance.get_town_polygons() + if poly: + poly, poly_source = poly + if poly != instance.multi_polygon: + instance.multi_polygon_source_item = poly_source + instance.multi_polygon_source = 'T' # town + try: + instance.multi_polygon = poly + modified = True + except TypeError: + print(instance, instance.pk) + + if (instance.point_source_item and + instance.point_source_item != current_source) or ( + instance.point_source == 'M' and modified): # refetch csrs = instance.spatial_reference_system if instance.x and instance.y: @@ -512,8 +549,6 @@ def post_save_geo(sender, **kwargs): point = instance.point point_2d = instance.point_2d - profile = get_current_profile() - modified = False if (point or point_2d) and instance.x is None and not \ instance.point_source: # db source @@ -579,13 +614,22 @@ def post_save_geo(sender, **kwargs): srs = get_srid_obj_from_point(point_2d) instance.spatial_reference_system = srs modified = True - - elif profile.use_town_for_geo: # try to get from parent - centroid = instance.get_town_centroid() - if centroid and centroid[0]: - instance.point_2d, instance.point_source_item = centroid + else: + centroid, source, point_source = None, None, None + if instance.multi_polygon and instance.multi_polygon_source == 'P': + source = current_source + centroid = instance.multi_polygon.centroid + point_source = 'M' + if not centroid and profile.use_town_for_geo: # try to get from + # parent + town_centroid = instance.get_town_centroid() + if town_centroid: + centroid, source = town_centroid + point_source = 'T' + if centroid: + instance.point_2d, instance.point_source_item = centroid, source instance.point = None - instance.point_source = 'T' + instance.point_source = point_source instance.x = instance.point_2d.x instance.y = instance.point_2d.y srs = get_srid_obj_from_point(instance.point_2d) @@ -597,38 +641,6 @@ def post_save_geo(sender, **kwargs): instance.point_source = None modified = True - if hasattr(instance, 'multi_polygon'): - if instance.multi_polygon_source_item and \ - instance.multi_polygon_source_item != current_source: # refetch - instance.multi_polygon = None - instance.multi_polygon_source = None - - if instance.multi_polygon and not instance.multi_polygon_source: - # should be a db source - instance.multi_polygon_source = 'P' - instance.multi_polygon_source_item = current_source - modified = True - elif instance.multi_polygon_source != 'P': - precise_poly = instance.get_precise_polygons() - if precise_poly: - poly, source_item = precise_poly - instance.multi_polygon = poly - instance.multi_polygon_source = 'P' - instance.multi_polygon_source_item = source_item - modified = True - elif profile.use_town_for_geo: - poly = instance.get_town_polygons() - if poly: - poly, poly_source = poly - if poly != instance.multi_polygon: - instance.multi_polygon_source_item = poly_source - instance.multi_polygon_source = 'T' # town - try: - instance.multi_polygon = poly - modified = True - except TypeError: - print(instance, instance.pk) - if modified: instance.skip_history_when_saving = True instance._post_saved_geo = True |