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 | 38e527b7695bfef471e5517edce90566b13583b4 (patch) | |
| tree | d78744c7f581b5bde98906db2f116b118e0db323 | |
| parent | 9858cf3f3201dbb08d5733e263e56e0675fff1c8 (diff) | |
| download | Ishtar-38e527b7695bfef471e5517edce90566b13583b4.tar.bz2 Ishtar-38e527b7695bfef471e5517edce90566b13583b4.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 | 
