def test_wkt_writer_precision(self): wkt_w = WKTWriter() self.assertIsNone(wkt_w.precision) self.assertEqual( wkt_w.write(Point(1.0 / 3, 2.0 / 3)), b"POINT (0.3333333333333333 0.6666666666666666)", ) wkt_w.precision = 1 self.assertEqual(wkt_w.precision, 1) self.assertEqual(wkt_w.write(Point(1.0 / 3, 2.0 / 3)), b"POINT (0.3 0.7)") wkt_w.precision = 0 self.assertEqual(wkt_w.precision, 0) self.assertEqual(wkt_w.write(Point(1.0 / 3, 2.0 / 3)), b"POINT (0 1)") wkt_w.precision = None self.assertIsNone(wkt_w.precision) self.assertEqual( wkt_w.write(Point(1.0 / 3, 2.0 / 3)), b"POINT (0.3333333333333333 0.6666666666666666)", ) with self.assertRaisesMessage( AttributeError, "WKT output rounding precision must be "): wkt_w.precision = "potato"
def modeldiff_delete(r): obj, model = get_current_object_from_db(r) geom_field = model.Modeldiff.geom_field geom_precision = model.Modeldiff.geom_precision old_data = json.loads(r.old_data) ok_to_apply = True fields = list(old_data.keys()) current = get_object_values(obj, model) for k in old_data: current_value = current.get(k) if k == geom_field: # early check to detect precision errors if not current_value == old_data[k]: # recreate the geometry and the wkt back again geom = GEOSGeometry(old_data[k]) wkt_w = WKTWriter(precision=geom_precision) old_data[k] = wkt_w.write(geom) if not str(current_value) == str(old_data[k]): ok_to_apply = False r.fields = fields if ok_to_apply: obj._modeldiff_ignore = True obj.delete() r.applied = True r.save()
def _pre_delete(self, modeldiff_class, sender, **kwargs): instance = kwargs['instance'] # see if we need to create a modeldiff to track the object deletion if hasattr(instance, '_modeldiff_ignore'): del instance._modeldiff_ignore return fields = sender.Modeldiff.fields diff = modeldiff_class() diff.applied = True diff.model_name = sender.Modeldiff.model_name diff.key = settings.MODELDIFF_KEY diff.username = self._get_username(instance) diff.model_id = instance.pk diff.action = 'delete' unique_field = getattr(sender.Modeldiff, 'unique_field', None) if unique_field: diff.unique_id = getattr(instance, unique_field) # get original object in database original = sender.objects.get(pk=instance.pk) # save old values old_values_temp = model_to_dict(original, fields=sender.Modeldiff.fields) old_values = {} for k in fields: old_value = old_values_temp[k] # Override DateField and DateTimeField if isinstance(old_value, datetime.datetime): old_value = old_value.strftime("%Y-%m-%d %H:%M:%S.%f%z") else: if isinstance(old_value, datetime.date): old_value = old_value.strftime("%Y-%m-%d") old_values[k] = old_value if modeldiff_class == Geomodeldiff: geom_field = sender.Modeldiff.geom_field geom_precision = sender.Modeldiff.geom_precision wkt_w = WKTWriter(precision=geom_precision) # save geometry geom = getattr(instance, geom_field) diff.the_geom = geom if geom: old_values[geom_field] = wkt_w.write(geom).decode('utf8') else: old_values[geom_field] = None diff.old_data = json.dumps(old_values) diff.save() if hasattr(sender.Modeldiff, 'parent_field'): getattr(instance, sender.Modeldiff.parent_field).save()
def load_kml(verbose=True): """ Recorre la carpeta/data/kml --> introduce en la BD los linestrings de los KML https://medium.com/@kitcharoenpoolperm/geodjango-import-data-from-kml-file-de110dba1f60 """ # Ruta al archivo que queremos introducir en la BD BikeLanes kml_file = os.path.abspath( os.path.join(os.path.dirname(__file__), 'data', 'kml', 'bidegorris.kml'), ) # Reading Data by DataSource ds = DataSource(kml_file) # Writes the Well-Known Text representation of a Geometry. wkt_w = WKTWriter() # Iterating Over Layers for layer in ds: for feat in layer: if (feat.geom.geom_type.name.startswith('Line')): # Get the feature geometry. geom = feat.geom # get the feature property property = get_feat_property(feat) if (len(geom.coords) >= 2): # Make a GEOSGeometry object lstring = GEOSGeometry(wkt_w.write(geom.geos), srid=4326) lstring.transform(3035) dist = lstring.length line = BikeLane.objects.create( name=property['name'], distance=dist, lstring=lstring, # ST_Buffer() --> Poligonizamos los bidegorris a una anchura de 10m # https://www.usna.edu/Users/oceano/pguth/md_help/html/approx_equivalents.htm#:~:text=0.00001%C2%B0%20%3D%201.11%20m poly=lstring.buffer(10, quadsegs=8)) logger.info(line)
def test02_wktwriter(self): # Creating a WKTWriter instance, testing its ptr property. wkt_w = WKTWriter() self.assertRaises(TypeError, wkt_w._set_ptr, WKTReader.ptr_type()) ref = GEOSGeometry('POINT (5 23)') ref_wkt = 'POINT (5.0000000000000000 23.0000000000000000)' self.assertEqual(ref_wkt, wkt_w.write(ref).decode())
def test_wktwriter_constructor_arguments(self): wkt_w = WKTWriter(dim=3, trim=True, precision=3) ref = GEOSGeometry('POINT (5.34562 23 1.5)') if geos_version_tuple() > (3, 10): ref_wkt = 'POINT Z (5.346 23 1.5)' else: ref_wkt = 'POINT Z (5.35 23 1.5)' self.assertEqual(ref_wkt, wkt_w.write(ref).decode())
def geoElement(self): wkt = WKTWriter() if self.poly: return wkt.write(self.poly) elif self.point: return wkt.write(self.point) else: return None
def test02_wktwriter(self): # Creating a WKTWriter instance, testing its ptr property. wkt_w = WKTWriter() with self.assertRaises(TypeError): wkt_w.ptr = WKTReader.ptr_type() ref = GEOSGeometry("POINT (5 23)") ref_wkt = "POINT (5.0000000000000000 23.0000000000000000)" self.assertEqual(ref_wkt, wkt_w.write(ref).decode())
def test_create_pois_receives_geometries(self): geom1 = b'POINT (-1.3630867 -5.9835847)' geom2 = b'POINT (-1.3630872 -5.9835842)' with patch.object(Command, 'create_poi') as mocked: self.cmd.handle(point_layer=self.filename, verbosity=0) call1 = mocked.call_args_list[0][0] call2 = mocked.call_args_list[1][0] self.assertEqual(WKTWriter(precision=7).write(call1[0]), geom1) self.assertEqual(WKTWriter(precision=7).write(call2[0]), geom2)
def get_object_values(obj, model): geom_field = model.Modeldiff.geom_field geom_precision = model.Modeldiff.geom_precision values = model_to_dict(obj) geom = getattr(obj, geom_field) if geom: wkt_w = WKTWriter(precision=geom_precision) values[geom_field] = wkt_w.write(geom) return values
def _force_2d(geom): """ https://groups.google.com/d/msg/django-users/7c1NZ76UwRU/xEAir0dUCQAJ """ wkt_w = WKTWriter() wkt_w.outdim = 2 geom_3d = GEOSGeometry(geom.wkt) temp = wkt_w.write(geom_3d) geom_2d = GEOSGeometry(temp) if geom_2d and isinstance(geom_2d, Polygon) is True: geom_2d = MultiPolygon(geom_2d) return geom_2d
def pre_save(self, model_instance, add): if not getattr(model_instance, self.attname): try: wkt_writer = WKTWriter(precision=self.precision) value = GEOSGeometry(wkt_writer.write(getattr(model_instance, self.field_name).simplify(self.simplify, preserve_topology=True))) if not isinstance(value, MultiPolygon): value = MultiPolygon(value) setattr(model_instance, self.attname, value) return value except: pass return super(CachedMultiPolygonField, self).pre_save(model_instance, add)
def test_regulatory_sensitive_area_shape(self): filename = os.path.join(os.path.dirname(__file__), 'data', 'species_regu.shp') call_command( 'import', 'geotrek.sensitivity.parsers.RegulatorySensitiveAreaShapeParser', filename, verbosity=0) self.assertEqual(SensitiveArea.objects.count(), 0) SportPracticeFactory(name="sport") call_command( 'import', 'geotrek.sensitivity.parsers.RegulatorySensitiveAreaShapeParser', filename, verbosity=0) area = SensitiveArea.objects.first() self.assertEqual(str(area.species), "Nom") self.assertTrue(area.species.period10) self.assertTrue(area.species.period11) self.assertTrue(area.species.period12) self.assertFalse(area.species.period08) self.assertEqual(area.species.radius, 23) self.assertEqual(area.species.url, "http://test.com") self.assertEqual(area.contact, "Contact") self.assertEqual(area.description, "Test UTF8 éêè") self.assertEqual( WKTWriter(precision=7).write(area.geom), b'POLYGON ((' b'929315.3613369 6483309.4435054, 929200.3539448 6483204.0200627, ' b'928404.8861499 6482494.8078118, 928194.0392645 6482082.6979903, ' b'927925.6886830 6481210.5586006, 927676.5060003 6481287.2301953, ' b'927772.3454936 6481498.0770807, 927887.3528857 6481900.6029529, ' b'928184.4553151 6482600.2312545, 928625.3169846 6483520.2903908, ' b'929162.0181475 6483664.0496309, 929315.3613369 6483309.4435054' b'))')
def test_cli(self): filename = os.path.join(os.path.dirname(__file__), 'data', 'species.shp') call_command( 'import', 'geotrek.sensitivity.parsers.SpeciesSensitiveAreaShapeParser', filename, verbosity=0) self.assertEqual(SensitiveArea.objects.count(), 0) species = SpeciesFactory(name="Aigle royal") call_command( 'import', 'geotrek.sensitivity.parsers.SpeciesSensitiveAreaShapeParser', filename, verbosity=0) area = SensitiveArea.objects.first() self.assertEqual(area.species, species) self.assertEqual(area.contact, "Contact") self.assertEqual(area.description, "Test UTF8 éêè") self.assertEqual( WKTWriter(precision=7).write(area.geom), b'POLYGON ((' b'929315.3613369 6483309.4435054, 929200.3539448 6483204.0200627, ' b'928404.8861499 6482494.8078118, 928194.0392645 6482082.6979903, ' b'927925.6886830 6481210.5586006, 927676.5060003 6481287.2301953, ' b'927772.3454936 6481498.0770807, 927887.3528857 6481900.6029529, ' b'928184.4553151 6482600.2312545, 928625.3169846 6483520.2903908, ' b'929162.0181475 6483664.0496309, 929315.3613369 6483309.4435054' b'))')
def test_good_data(self): filename = os.path.join(os.path.dirname(__file__), 'data', 'city.shp') call_command('import', 'geotrek.zoning.parsers.CityParser', filename, verbosity=0) city = City.objects.get() self.assertEqual(city.code, "99999") self.assertEqual(city.name, "Trifouilli-les-Oies") self.assertEqual(WKTWriter(precision=4).write(city.geom), WKT)
def modeldiff_update(r): obj, model = get_current_object_from_db(r) geom_field = model.Modeldiff.geom_field geom_precision = model.Modeldiff.geom_precision old_data = json.loads(r.old_data) ok_to_apply = True fields = list(old_data.keys()) current = get_object_values(obj, model) for k in old_data: current_value = current.get(k) if k == geom_field: # early check to detect precision errors if not current_value == old_data[k]: # recreate the geometry and the wkt back again geom = GEOSGeometry(old_data[k]) wkt_w = WKTWriter(precision=geom_precision) old_data[k] = wkt_w.write(geom) if not str(current_value) == str(old_data[k]): ok_to_apply = False r.fields = fields if ok_to_apply: fields = get_fields(r) or list(old_data.keys()) new_data = json.loads(r.new_data) for k in set(fields) & set(new_data.keys()): field = model._meta.get_field(k) if isinstance(field, ForeignKey): if new_data[k]: # TODO: support multiple to_fields kwargs = {field.to_fields[0]: new_data[k]} value = field.related_model.objects.get(**kwargs) else: value = None else: value = new_data[k] setattr(obj, k, value) save_object(obj) r.applied = True r.save()
def _parse_columns(self, dataframe): ''' parse the columns of the input dataframe to match the data type of the fields ''' dataframe = dataframe.copy() error_occured = False for column in dataframe.columns: _meta = self.Meta.model._meta field_name = self.field_map.get(column, None) if field_name is None or isinstance(field_name, Reference): continue field = _meta.get_field(field_name) if (isinstance(field, PointField) or isinstance(field, PolygonField) or isinstance(field, MultiPolygonField)): self.wkt_w = WKTWriter(dim=2) dataframe['wkt'] = dataframe['wkt'].apply(self._parse_wkt) types = dataframe['wkt'].apply(type) str_idx = types == str error_idx = dataframe.index[str_idx] error_msg = _('Invalid geometry') self.error_mask.set_error(error_idx, 'wkt', error_msg) if len(error_idx) > 0: error_occured = _('Invalid geometries') elif (isinstance(field, IntegerField) or isinstance(field, FloatField) or isinstance(field, DecimalField) or isinstance(field, BooleanField)): # set predefined nan-values to nan dataframe[column] = dataframe[column].replace( self.nan_values, np.NaN) # parse the values (which are not nan) not_na = dataframe[column].notna() entries = dataframe[column].loc[not_na] if isinstance(field, IntegerField): entries = entries.apply(self._parse_int) error_msg = _('Integer expected: number without decimals') elif (isinstance(field, FloatField) or isinstance(field, DecimalField)): entries = entries.apply(self._parse_float) error_msg = _('Float expected: number with or without ' 'decimals; use either "," or "." as decimal-' 'seperators, no thousand-seperators allowed') elif isinstance(field, BooleanField): entries = entries.apply(self._parse_bool) error_msg = _('Boolean expected ("true" or "false")') # nan is used to determine parsing errors error_idx = entries[entries.isna()].index if len(error_idx) > 0: error_occured = _('Number format errors') # set the error message in the error matrix at these positions self.error_mask.set_error(error_idx, column, error_msg) # overwrite values in dataframe with parsed ones dataframe.loc[not_na, column] = entries if error_occured: self.error_mask.add_message(error_occured) return dataframe
def test_wkt_writer_trim(self): wkt_w = WKTWriter() self.assertFalse(wkt_w.trim) self.assertEqual(wkt_w.write(Point(1, 1)), b'POINT (1.0000000000000000 1.0000000000000000)') wkt_w.trim = True self.assertTrue(wkt_w.trim) self.assertEqual(wkt_w.write(Point(1, 1)), b'POINT (1 1)') self.assertEqual(wkt_w.write(Point(1.1, 1)), b'POINT (1.1 1)') self.assertEqual(wkt_w.write(Point(1. / 3, 1)), b'POINT (0.3333333333333333 1)') wkt_w.trim = False self.assertFalse(wkt_w.trim) self.assertEqual(wkt_w.write(Point(1, 1)), b'POINT (1.0000000000000000 1.0000000000000000)')
def to_representation(self, value): if isinstance(value, dict) or value is None: return value new_value = copy.copy(value) new_value = new_value.buffer(0.5) # Use Douglas-Peucker to simplify geom (one vertex 0.2m) for large polygons if new_value.num_coords > 1000: new_value = new_value.simplify(0.2, preserve_topology=False) new_value.transform(4326) wkt_w = WKTWriter() # number of decimals wkt_w.precision = 6 if new_value.area > 0: return wkt_w.write(new_value).decode() return 'POLYGON EMPTY'
def test_wkt_writer_precision(self): wkt_w = WKTWriter() self.assertEqual(wkt_w.precision, None) self.assertEqual(wkt_w.write(Point(1. / 3, 2. / 3)), b'POINT (0.3333333333333333 0.6666666666666666)') wkt_w.precision = 1 self.assertEqual(wkt_w.precision, 1) self.assertEqual(wkt_w.write(Point(1. / 3, 2. / 3)), b'POINT (0.3 0.7)') wkt_w.precision = 0 self.assertEqual(wkt_w.precision, 0) self.assertEqual(wkt_w.write(Point(1. / 3, 2. / 3)), b'POINT (0 1)') wkt_w.precision = None self.assertEqual(wkt_w.precision, None) self.assertEqual(wkt_w.write(Point(1. / 3, 2. / 3)), b'POINT (0.3333333333333333 0.6666666666666666)') with self.assertRaisesMessage(AttributeError, 'WKT output rounding precision must be '): wkt_w.precision = 'potato'
def test_geo_creation_diff_exists(self): diff = Geomodeldiff.objects.all().order_by('-id')[:1][0] self.assertEqual(diff.action, 'add') self.assertEqual(diff.model_id, self.persongeo.id) self.assertEqual(diff.model_name, 'modeldiff.PersonGeoModel') self.assertEqual(diff.old_data, '') self.assertEqual( json.loads(diff.new_data), { 'name': 'Foo', 'surname': 'Doe', 'birthdate': '2007-12-05', 'updated_at': '2015-01-07 22:00:10.292032+0000', 'the_geom': 'POINT (0.00000000 0.00000000)' }) wkt_w = WKTWriter(precision=8) self.assertEqual(wkt_w.write(diff.the_geom), b'POINT (0.00000000 0.00000000)')
def test_wkt_writer_precision(self): wkt_w = WKTWriter() self.assertIsNone(wkt_w.precision) self.assertEqual(wkt_w.write(Point(1. / 3, 2. / 3)), b'POINT (0.3333333333333333 0.6666666666666666)') wkt_w.precision = 1 self.assertEqual(wkt_w.precision, 1) self.assertEqual(wkt_w.write(Point(1. / 3, 2. / 3)), b'POINT (0.3 0.7)') wkt_w.precision = 0 self.assertEqual(wkt_w.precision, 0) self.assertEqual(wkt_w.write(Point(1. / 3, 2. / 3)), b'POINT (0 1)') wkt_w.precision = None self.assertIsNone(wkt_w.precision) self.assertEqual(wkt_w.write(Point(1. / 3, 2. / 3)), b'POINT (0.3333333333333333 0.6666666666666666)') with self.assertRaisesMessage(AttributeError, 'WKT output rounding precision must be '): wkt_w.precision = 'potato'
def test_create(self): filename = os.path.join(os.path.dirname(__file__), 'data', 'trek.shp') call_command('import', 'geotrek.trekking.parsers.TrekParser', filename, verbosity=0) trek = Trek.objects.all().last() self.assertEqual(trek.name, "Balade") self.assertEqual(trek.difficulty, self.difficulty) self.assertEqual(trek.route, self.route) self.assertQuerysetEqual(trek.themes.all(), [repr(t) for t in self.themes], ordered=False) self.assertEqual(WKTWriter(precision=4).write(trek.geom), WKT)
def convert_geometry(config, geometry): """Converts the user requested geometry into the format supported by the ogcapi process services""" # This is configured for a single implementation to be more flexible would require parsing the process description, # and attempting to map the values to the correct schema type. area = config.get("area") config["inputs"]["geometry"] = {"format": area["type"]} if area["type"] == "wkt": config["inputs"]["geometry"]["input"] = WKTWriter().write( geometry).decode() if area["type"] == "geojson": config["inputs"]["geometry"]["input"] = { "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": json.loads(geometry.geojson) }], } if area["type"] == "bbox": config["inputs"]["geometry"]["input"] = list(geometry.extent) return config
def save(self, *args, **kwargs): # see if we need to save the object (real = True) # or should generate a Modeldiff (real = False) ignore = kwargs.get('modeldiff_ignore', False) if ignore: # call original handler kwargs.pop('modeldiff_ignore') super(SaveGeomodeldiffMixin, self).save(*args, **kwargs) return fields = self.Modeldiff.fields geom_field = self.Modeldiff.geom_field geom_precision = self.Modeldiff.geom_precision diff = Geomodeldiff() diff.applied = True diff.model_name = self.Modeldiff.model_name diff.key = settings.MODELDIFF_KEY if hasattr(self, 'username'): diff.username = self.username else: try: diff.username = GlobalRequest().user.username except Exception: pass unique_field = getattr(self.Modeldiff, 'unique_field', None) if unique_field: diff.unique_id = getattr(self, unique_field) original = None if self.pk: # get original object in database try: original = self.__class__.objects.get(pk=self.pk) except Exception: pass wkt_w = WKTWriter(precision=geom_precision) if original: diff.model_id = self.pk diff.action = 'update' # compare original and current (self) old_values = {} new_values = {} old_values_temp = model_to_dict(original, fields=self.Modeldiff.fields) new_values_temp = model_to_dict(self, fields=self.Modeldiff.fields) for k in fields: old_value = old_values_temp[k] new_value = new_values_temp[k] # Override DateField and DateTimeField if isinstance(new_value, datetime.datetime): new_value = new_value.strftime("%Y-%m-%d %H:%M:%S.%f%z") else: if isinstance(new_value, datetime.date): new_value = new_value.strftime("%Y-%m-%d") if isinstance(old_value, datetime.datetime): old_value = old_value.strftime("%Y-%m-%d %H:%M:%S.%f%z") else: if isinstance(old_value, datetime.date): old_value = old_value.strftime("%Y-%m-%d") old_values[k] = old_value if old_value != new_value: new_values[k] = new_value # save original geometry geom = getattr(original, geom_field) if geom: old_values[geom_field] = wkt_w.write(geom).decode('utf8') else: old_values[geom_field] = None # compare original and new geometry new_geom = getattr(self, geom_field) diff.the_geom = new_geom if new_geom: new_geom_value = wkt_w.write(new_geom).decode('utf8') else: new_geom_value = None if not new_geom_value == old_values[geom_field]: new_values[geom_field] = new_geom_value diff.old_data = json.dumps(old_values) diff.new_data = json.dumps(new_values) diff.save() else: diff.action = 'add' # save all new values new_values_temp = model_to_dict(self, fields=self.Modeldiff.fields) new_values = {} for k in fields: new_value = new_values_temp[k] # Override DateField and DateTimeField if isinstance(new_value, datetime.datetime): new_value = new_value.strftime("%Y-%m-%d %H:%M:%S.%f%z") else: if isinstance(new_value, datetime.date): new_value = new_value.strftime("%Y-%m-%d") new_values[k] = new_value new_geom = getattr(self, geom_field) diff.the_geom = new_geom if new_geom: new_values[geom_field] = wkt_w.write(new_geom).decode('utf8') diff.new_data = json.dumps(new_values) diff.save() super(SaveGeomodeldiffMixin, self).save(*args, **kwargs) if diff.model_id is None and self.pk: diff.model_id = self.pk diff.save() if hasattr(self.Modeldiff, 'parent_field'): getattr(self, self.Modeldiff.parent_field).save()
def _strip_z_values(features): for feature in features: writer = WKTWriter() writer.outdim = 2 # force features into 2 dimensions feature.multipolygon = GEOSGeometry(writer.write(feature.multipolygon)) return features
def convert_3d_to_2d(self, shape_3d): wkt_w = WKTWriter() wkt_w.outdim = 2 temp = wkt_w.write(shape_3d) return GEOSGeometry(temp)
def test_wktwriter_constructor_arguments(self): wkt_w = WKTWriter(dim=3, trim=True, precision=3) ref = GEOSGeometry('POINT (5.34562 23 1.5)') ref_wkt = 'POINT Z (5.35 23 1.5)' self.assertEqual(ref_wkt, wkt_w.write(ref).decode())
def delete_deprecated(self, *args, **kwargs): # pragma: no cover real = kwargs.get('real', False) if real: # call original handler kwargs.pop('real') super(SaveGeomodeldiffMixin, self).delete(*args, **kwargs) return fields = self.Modeldiff.fields geom_field = self.Modeldiff.geom_field geom_precision = self.Modeldiff.geom_precision diff = Geomodeldiff() diff.model_name = self.Modeldiff.model_name if hasattr(self, 'username'): diff.username = self.username else: try: diff.username = GlobalRequest().user.username except Exception: pass if self.pk: diff.model_id = self.pk diff.action = 'delete' # get original object in database original = self.__class__.objects.get(pk=self.pk) # save old values old_values_temp = model_to_dict(original, fields=self.Modeldiff.fields) old_values = {} for k in fields: old_value = old_values_temp[k] # Override DateField and DateTimeField if isinstance(old_value, datetime.datetime): old_value = old_value.strftime("%Y-%m-%d %H:%M:%S.%f%z") else: if isinstance(old_value, datetime.date): old_value = old_value.strftime("%Y-%m-%d") old_values[k] = old_value # save geometry geom = getattr(self, geom_field) diff.the_geom = geom wkt_w = WKTWriter(precision=geom_precision) if geom: old_values[geom_field] = wkt_w.write(geom).decode('utf8') else: old_values[geom_field] = None diff.old_data = json.dumps(old_values) diff.save() super(SaveGeomodeldiffMixin, self).delete(*args, **kwargs) if hasattr(self.Modeldiff, 'parent_field'): getattr(self, self.Modeldiff.parent_field).save()
def getPath(request): data = request.get_full_path().split('?')[1] result = data.replace("%20", " ") namePair = result.split(" ") firstName = namePair[0] lastName = namePair[1] person = Vulnerable.objects.filter(first_name=firstName, last_name=lastName).first() wkt_w = WKTWriter() loc_activities = LostActivity.objects.prefetch_related( 'location', 'person').filter(person=person, category="Location").order_by('time') j = 0 # for the table summary. Group all similar location activities in order currlocation = None currentplace = None startDate = None processed = [] journeys = [ [] ] # list of lists of separate journey dicts to then add to ordered dict of features for template to draw feature_fences = [] # list of lists of locations to add for l in loc_activities: if not startDate: startDate = l.time.date() # current point pnt = Point(float(l.locLon), float(l.locLat), srid=3857) # see if activity in geofence but needs to be updated in database (new geofence created recently) if not l.location: fence_loc = Location.objects.filter(fence__contains=pnt) if fence_loc: l.location = fence_loc[0] l.update() prior = {} prior['name'] = None prior['act_type'] = None if len(journeys[j]) > 0: prior = journeys[j][-1] # if hit a known location add nearest boundary points too if l.location: # for the processed table groupings (append each place travelled to in order) if l.location != currlocation: processed.append({ "time": str(l.time), "location": l.location, "person": l.person, "activity_type": str(l.activity_type) }) currentplace = l currlocation = l.location # add the ENTRY boundary point then the location if str(l.location.name): # if has name then at known geofence # went from location to location if (prior['act_type'] == "geo_fence" or prior['act_type'] == "exit place") and prior['name'] != l.location.name: # use centroids as point to point reference a = prior['feature'].lstrip('b') prior['feature'] = a[1:-1] last_cnt = GEOSGeometry(prior['feature']).centroid wkt_feat = wkt_w.write(last_cnt) a = str(wkt_feat) b = a.lstrip('b') wkt_feat = b[1:-1] to_add = point_map_record(str(l.location.name), wkt_feat, last_cnt, l, "exit place") journeys[j].append(to_add) # start next journey journeys.append([]) j += 1 # add entry point curr_cnt = l.location.fence.centroid wkt_feat = curr_cnt.wkt to_add = point_map_record(str(l.location.name), wkt_feat, curr_cnt, l, "enter location") journeys[j].append(to_add) # entered new location after a travel point # get entry point based on last recorded location elif prior['name'] and prior['name'] != l.location.name: last_pnt = Point(float(prior['locLon']), float(prior['locLat']), srid=3857) boundary = l.location.fence.boundary opt_dist = boundary.project(last_pnt) # get point on boundary at that distance entry = boundary.interpolate(opt_dist) wkt_feat = wkt_w.write(entry) a = str(wkt_feat) b = a.lstrip('b') wkt_feat = b[1:-1] to_add = point_map_record(str(l.location.name), wkt_feat, entry, l, "enter location") journeys[j].append(to_add) # add current location even if stayed in same location wkt_fence = wkt_w.write(l.location.fence) to_add = geofence_record(l, wkt_fence, True) journeys[j].append(to_add) # just travel point else: # for the table count travel as no location currlocation = None currentplace = None # may need exit point from last location to this current point if prior['act_type'] == "geo_fence": a = prior['feature'] b = a.lstrip('b') prior['feature'] = b[1:-1] boundary = GEOSGeometry(prior['feature']).boundary opt_dist = boundary.project(pnt) exitpnt = boundary.interpolate(opt_dist) wkt_feat = wkt_w.write(exitpnt) a = str(wkt_feat) b = a.lstrip('b') wkt_feat = b[1:-1] to_add = point_map_record(str(prior['name']), wkt_feat, exitpnt, l, "exit place") journeys[j].append(to_add) # start next journey after exit journeys.append([]) j += 1 wkt_feat = wkt_w.write(pnt) a = str(wkt_feat) b = a.lstrip('b') wkt_feat = b[1:-1] reg_point = point_map_record("journey: " + str(j), wkt_feat, pnt, l, "moving") journeys[j].append(reg_point) # get additional known locations details for this person or their friends' homes fences = list(Location.objects.filter(person=person)) for f in fences: wkt_fence = wkt_w.write(f.fence) to_add = geofence_record(f, wkt_fence, False) feature_fences.append([to_add]) return Response(journeys)