def test_latestupdate_delete(self): for i in range(10): PathFactory.create() t1 = dbnow() self.assertTrue(t1 > Path.latest_updated()) (Path.objects.all()[0]).delete() self.assertFalse(t1 > Path.latest_updated())
def test_elevation(self): # Create a simple fake DEM conn = connections[DEFAULT_DB_ALIAS] cur = conn.cursor() cur.execute('CREATE TABLE mnt (rid serial primary key, rast raster)') cur.execute('INSERT INTO mnt (rast) VALUES (ST_MakeEmptyRaster(3, 3, 0, 3, 1, -1, 0, 0, %s))', [settings.SRID]) cur.execute('UPDATE mnt SET rast = ST_AddBand(rast, \'16BSI\')') for x in range(1, 4): for y in range(1, 4): cur.execute('UPDATE mnt SET rast = ST_SetValue(rast, %s, %s, %s::float)', [x, y, x+y]) conn.commit_unless_managed() # Create a geometry and check elevation-based indicators p = Path(geom=LineString((1.5,1.5,0), (2.5,1.5,0), (1.5,2.5,0))) self.assertEqual(p.ascent, 0) self.assertEqual(p.descent, 0) self.assertEqual(p.min_elevation, 0) self.assertEqual(p.max_elevation, 0) p.save() self.assertEqual(p.ascent, 1) self.assertEqual(p.descent, -2) self.assertEqual(p.min_elevation, 3) self.assertEqual(p.max_elevation, 5) # Check elevation profile profile = p.get_elevation_profile() self.assertEqual(len(profile), 3) self.assertEqual(profile[0][0], 0.0) self.assertEqual(profile[0][1], 4) self.assertTrue(1.4 < profile[1][0] < 1.5) self.assertEqual(profile[1][1], 5) self.assertTrue(3.8 < profile[2][0] < 3.9) self.assertEqual(profile[2][1], 3)
class ElevationTest(TestCase): def setUp(self): # Create a simple fake DEM conn = connections[DEFAULT_DB_ALIAS] cur = conn.cursor() cur.execute('CREATE TABLE mnt (rid serial primary key, rast raster)') cur.execute('INSERT INTO mnt (rast) VALUES (ST_MakeEmptyRaster(3, 3, 0, 3, 1, -1, 0, 0, %s))', [settings.SRID]) cur.execute('UPDATE mnt SET rast = ST_AddBand(rast, \'16BSI\')') for x in range(1, 4): for y in range(1, 4): cur.execute('UPDATE mnt SET rast = ST_SetValue(rast, %s, %s, %s::float)', [x, y, x+y]) conn.commit_unless_managed() self.path = Path(geom=LineString((1.5,1.5,0), (2.5,1.5,0), (1.5,2.5,0))) self.path.save() def tearDown(self): conn = connections[DEFAULT_DB_ALIAS] cur = conn.cursor() self.path.delete() cur.execute('DROP TABLE mnt;') def test_elevation_path(self): p = self.path self.assertEqual(p.ascent, 1) self.assertEqual(p.descent, -2) self.assertEqual(p.min_elevation, 3) self.assertEqual(p.max_elevation, 5) # Check elevation profile profile = p.get_elevation_profile() self.assertEqual(len(profile), 4) # minimum possible (since p.length < sampling resolution) self.assertEqual(profile[0][0], 0.0) self.assertEqual(profile[0][3], 4) self.assertTrue(2.4 < profile[-1][0] < 2.5) # p.geom.length self.assertEqual(profile[-1][3], 3) def test_elevation_topology_line(self): topo = TopologyFactory.create(no_path=True) topo.add_path(self.path, start=0.2, end=0.7) topo.save() self.assertEqual(topo.ascent, 0) self.assertEqual(topo.descent, 0) self.assertEqual(topo.min_elevation, 4) self.assertEqual(topo.max_elevation, 5) def test_elevation_topology_point(self): topo = TopologyFactory.create(no_path=True) topo.add_path(self.path, start=0.5, end=0.5) topo.save() self.assertEqual(topo.ascent, 0) self.assertEqual(topo.descent, 0) self.assertEqual(topo.min_elevation, 5) self.assertEqual(topo.max_elevation, 5)
def test_elevation_topology_point(self): p = Path(geom=LineString((1.5,1.5,0), (2.5,1.5,0), (1.5,2.5,0))) p.save() topo = TopologyFactory.create(no_path=True) topo.add_path(p, start=0.5, end=0.5) topo.save() self.assertEqual(topo.ascent, 0) self.assertEqual(topo.descent, 0) self.assertEqual(topo.min_elevation, 5) self.assertEqual(topo.max_elevation, 5)
def test_paths_bystructure(self): user = UserFactory() p1 = PathFactory() p2 = PathFactory(structure=Structure.objects.create(name="other")) self.assertEqual(user.profile.structure, p1.structure) self.assertNotEqual(user.profile.structure, p2.structure) self.assertEqual(len(Structure.objects.all()), 2) self.assertEqual(len(Path.objects.all()), 2) self.assertEqual( Path.in_structure.for_user(user)[0], Path.for_user(user)[0]) self.assertTrue(p1 in Path.in_structure.for_user(user)) self.assertFalse(p2 in Path.in_structure.for_user(user)) # Change user structure on-the-fly profile = user.profile profile.structure = p2.structure profile.save() self.assertEqual(user.profile.structure.name, "other") self.assertFalse(p1 in Path.in_structure.for_user(user)) self.assertTrue(p2 in Path.in_structure.for_user(user))
def test_point_geom_3d(self): """ + / \ / X \ + + """ p1 = PathFactory.create(geom=LineString((0, 0, 1000), (4, 4, 2000))) p2 = PathFactory.create(geom=LineString((4, 4, 2000), (8, 0, 0))) poi = Point(3, 1, srid=settings.SRID) position, distance = Path.interpolate(p1, poi) self.assertTrue(almostequal(0.5, position)) self.assertTrue(almostequal(-1.414, distance)) # Verify that deserializing this, we obtain the same original coordinates # (use lat/lng as in forms) poi.transform(settings.API_SRID) poitopo = Topology.deserialize({'lat': poi.y, 'lng': poi.x}) # Computed topology properties match original interpolation self.assertTrue(almostequal(0.5, poitopo.aggregations.all()[0].start_position)) self.assertTrue(almostequal(-1.414, poitopo.offset)) # Resulting geometry self.assertTrue(almostequal(3, poitopo.geom.x)) self.assertTrue(almostequal(1, poitopo.geom.y)) self.assertTrue(almostequal(0, poitopo.geom.z))
def test_point_geom_3d(self): """ + / \ / X \ + + """ p1 = PathFactory.create(geom=LineString((0, 0), (4, 4))) PathFactory.create(geom=LineString((4, 4), (8, 0))) poi = Point(3, 1, srid=settings.SRID) position, distance = Path.interpolate(p1, poi) self.assertAlmostEqual(0.5, position, places=6) self.assertAlmostEqual(-1.414, distance, places=2) # Verify that deserializing this, we obtain the same original coordinates # (use lat/lng as in forms) poi.transform(settings.API_SRID) poitopo = Topology.deserialize({'lat': poi.y, 'lng': poi.x}) # Computed topology properties match original interpolation self.assertAlmostEqual(0.5, poitopo.aggregations.all()[0].start_position, places=6) self.assertAlmostEqual(-1.414, poitopo.offset, places=2) # Resulting geometry self.assertAlmostEqual(3, poitopo.geom.x, places=6) self.assertAlmostEqual(1, poitopo.geom.y, places=6)
def setUp(self): # Create a simple fake DEM conn = connections[DEFAULT_DB_ALIAS] cur = conn.cursor() cur.execute('CREATE TABLE mnt (rid serial primary key, rast raster)') cur.execute( 'INSERT INTO mnt (rast) VALUES (ST_MakeEmptyRaster(3, 3, 0, 3, 1, -1, 0, 0, %s))', [settings.SRID]) cur.execute('UPDATE mnt SET rast = ST_AddBand(rast, \'16BSI\')') for x in range(1, 4): for y in range(1, 4): cur.execute( 'UPDATE mnt SET rast = ST_SetValue(rast, %s, %s, %s::float)', [x, y, x + y]) conn.commit_unless_managed() self.path = Path( geom=LineString((1.5, 1.5, 0), (2.5, 1.5, 0), (1.5, 2.5, 0))) self.path.save()
def clean_geom(self): pk = self.instance.pk if self.instance and self.instance.pk else -1 geom = self.cleaned_data['geom'] if geom is None: raise forms.ValidationError(_("Invalid snapped geometry.")) if not geom.simple: raise forms.ValidationError(_("Geometry is not simple.")) if not Path.check_path_not_overlap(geom, pk): raise forms.ValidationError(_("Geometry overlaps another.")) return geom
def test_elevation_path(self): # Create a geometry and check elevation-based indicators p = Path(geom=LineString((1.5,1.5,0), (2.5,1.5,0), (1.5,2.5,0))) self.assertEqual(p.ascent, 0) self.assertEqual(p.descent, 0) self.assertEqual(p.min_elevation, 0) self.assertEqual(p.max_elevation, 0) p.save() self.assertEqual(p.ascent, 1) self.assertEqual(p.descent, -2) self.assertEqual(p.min_elevation, 3) self.assertEqual(p.max_elevation, 5) # Check elevation profile profile = p.get_elevation_profile() self.assertEqual(len(profile), 4) # minimum possible (since p.length < sampling resolution) self.assertEqual(profile[0][0], 0.0) self.assertEqual(profile[0][3], 4) self.assertTrue(2.4 < profile[-1][0] < 2.5) # p.geom.length self.assertEqual(profile[-1][3], 3)
def test_topology_linked_to_not_draft(self): path_draft = PathFactory.create(name="draft", geom='LINESTRING(0 0, 1 0, 2 0)', draft=True) path_draft.save() path_normal = PathFactory.create(name="normal", geom='LINESTRING(0 3, 1 3, 2 3)', draft=False) path_normal.save() point = Point(0, 0, srid=settings.SRID) closest = Path.closest(point) self.assertEqual(point.wkt, 'POINT (0 0)') self.assertEqual(closest, path_normal)
def setUp(self): # Create a simple fake DEM conn = connections[DEFAULT_DB_ALIAS] cur = conn.cursor() cur.execute('CREATE TABLE mnt (rid serial primary key, rast raster)') cur.execute('INSERT INTO mnt (rast) VALUES (ST_MakeEmptyRaster(3, 3, 0, 3, 1, -1, 0, 0, %s))', [settings.SRID]) cur.execute('UPDATE mnt SET rast = ST_AddBand(rast, \'16BSI\')') for x in range(1, 4): for y in range(1, 4): cur.execute('UPDATE mnt SET rast = ST_SetValue(rast, %s, %s, %s::float)', [x, y, x+y]) conn.commit_unless_managed() self.path = Path(geom=LineString((1.5,1.5,0), (2.5,1.5,0), (1.5,2.5,0))) self.path.save()
def test_structure(structure, stake): user = self.userfactory(password='******') p = user.profile p.structure = structure p.save() success = self.client.login(username=user.username, password='******') self.assertTrue(success) response = self.client.get(Path.get_add_url()) self.assertEqual(response.status_code, 200) self.assertTrue('form' in response.context) form = response.context['form'] self.assertTrue('stake' in form.fields) stakefield = form.fields['stake'] self.assertTrue((stake.pk, unicode(stake)) in stakefield.choices) self.client.logout()
def test_deserialize_point(self): PathFactory.create() # Take a point p = Point(2, 1, 0, srid=settings.SRID) p.transform(settings.API_SRID) closest = Path.closest(p) # Check closest path self.assertEqual(closest.geom.coords, ((1.0, 1.0, 0.0), (2.0, 2.0, 0.0))) # The point has same x as first point of path, and y to 0 : topology = Topology.deserialize('{"lng": %s, "lat": %s}' % (p.x, p.y)) self.assertAlmostEqual(topology.offset, -0.7071, 3) self.assertEqual(len(topology.paths.all()), 1) pagg = topology.aggregations.get() self.assertTrue(almostequal(pagg.start_position, 0.5)) self.assertTrue(almostequal(pagg.end_position, 0.5))
def test_structurerelated_filter_with_none(self): s1 = StructureFactory.create() s2 = StructureFactory.create() st0 = StakeFactory.create(structure=None) st1 = StakeFactory.create(structure=s1) st2 = StakeFactory.create(structure=s2) user = self.userfactory(password='******') p = user.profile p.structure = s1 p.save() success = self.client.login(username=user.username, password='******') self.assertTrue(success) response = self.client.get(Path.get_add_url()) self.assertEqual(response.status_code, 200) self.assertTrue('form' in response.context) form = response.context['form'] self.assertTrue('stake' in form.fields) stakefield = form.fields['stake'] self.assertTrue((st0.pk, unicode(st0)) in stakefield.choices) self.assertTrue((st1.pk, unicode(st1)) in stakefield.choices) self.assertFalse((st2.pk, unicode(st2)) in stakefield.choices)
def test_paths_bystructure(self): user = UserFactory() p1 = PathFactory() p2 = PathFactory(structure=Structure.objects.create(name="other")) self.assertEqual(user.profile.structure, p1.structure) self.assertNotEqual(user.profile.structure, p2.structure) self.assertEqual(len(Structure.objects.all()), 2) self.assertEqual(len(Path.objects.all()), 2) self.assertEqual(Path.in_structure.for_user(user)[0], Path.for_user(user)[0]) self.assertTrue(p1 in Path.in_structure.for_user(user)) self.assertFalse(p2 in Path.in_structure.for_user(user)) # Change user structure on-the-fly profile = user.profile profile.structure = p2.structure profile.save() self.assertEqual(user.profile.structure.name, "other") self.assertFalse(p1 in Path.in_structure.for_user(user)) self.assertTrue(p2 in Path.in_structure.for_user(user))
@classmethod def path_infrastructures(cls, path): return cls.objects.existing().filter( aggregations__path=path).distinct('pk') @classmethod def topology_infrastructures(cls, topology): return cls.overlapping(topology) @classmethod def published_topology_infrastructure(cls, topology): return cls.topology_infrastructures(topology).filter(published=True) Path.add_property('infrastructures', lambda self: Infrastructure.path_infrastructures(self), _(u"Infrastructures")) Topology.add_property( 'infrastructures', lambda self: Infrastructure.topology_infrastructures(self), _(u"Infrastructures")) Topology.add_property('published_infrastructures', Infrastructure.published_topology_infrastructure, _(u"Published Infrastructures")) class SignageGISManager(gismodels.GeoManager): """ Overide default typology mixin manager, and filter by type. """ def get_queryset(self): return super(SignageGISManager, self).get_queryset().filter( type__type=INFRASTRUCTURE_TYPES.SIGNAGE)
def test_snap_not_saved(self): p = Path() with self.assertRaisesRegex(ValueError, "Cannot compute snap on unsaved path"): p.snap(Point(0, 0))
def test_latest_updated_bypass_invisible(self): self.assertEqual(Path.latest_updated(), self.path.date_update)
class ElevationTest(TestCase): def setUp(self): # Create a simple fake DEM conn = connections[DEFAULT_DB_ALIAS] cur = conn.cursor() cur.execute('CREATE TABLE mnt (rid serial primary key, rast raster)') cur.execute( 'INSERT INTO mnt (rast) VALUES (ST_MakeEmptyRaster(3, 3, 0, 3, 1, -1, 0, 0, %s))', [settings.SRID]) cur.execute('UPDATE mnt SET rast = ST_AddBand(rast, \'16BSI\')') for x in range(1, 4): for y in range(1, 4): cur.execute( 'UPDATE mnt SET rast = ST_SetValue(rast, %s, %s, %s::float)', [x, y, x + y]) conn.commit_unless_managed() self.path = Path( geom=LineString((1.5, 1.5, 0), (2.5, 1.5, 0), (1.5, 2.5, 0))) self.path.save() def tearDown(self): conn = connections[DEFAULT_DB_ALIAS] cur = conn.cursor() self.path.delete() cur.execute('DROP TABLE mnt;') def test_elevation_path(self): p = self.path self.assertEqual(p.ascent, 1) self.assertEqual(p.descent, -2) self.assertEqual(p.min_elevation, 3) self.assertEqual(p.max_elevation, 5) # Check elevation profile profile = p.get_elevation_profile() self.assertEqual( len(profile), 4) # minimum possible (since p.length < sampling resolution) self.assertEqual(profile[0][0], 0.0) self.assertEqual(profile[0][3], 4) self.assertTrue(2.4 < profile[-1][0] < 2.5) # p.geom.length self.assertEqual(profile[-1][3], 3) def test_elevation_topology_line(self): topo = TopologyFactory.create(no_path=True) topo.add_path(self.path, start=0.2, end=0.7) topo.save() self.assertEqual(topo.ascent, 0) self.assertEqual(topo.descent, 0) self.assertEqual(topo.min_elevation, 4) self.assertEqual(topo.max_elevation, 5) def test_elevation_topology_point(self): topo = TopologyFactory.create(no_path=True) topo.add_path(self.path, start=0.5, end=0.5) topo.save() self.assertEqual(topo.ascent, 0) self.assertEqual(topo.descent, 0) self.assertEqual(topo.min_elevation, 5) self.assertEqual(topo.max_elevation, 5)
@property def geomtransform(self): geom = self.topo_object.geom return geom.transform(settings.API_SRID, clone=True) @property def lat_value(self): return self.geomtransform.x @property def lng_value(self): return self.geomtransform.y Path.add_property('signages', lambda self: Signage.path_signages(self), _(u"Signages")) Topology.add_property('signages', lambda self: Signage.topology_signages(self), _(u"Signages")) Topology.add_property('published_signages', lambda self: Signage.published_topology_signages(self), _(u"Published Signages")) class Direction(models.Model): label = models.CharField(db_column="etiquette", max_length=128) class Meta: db_table = 's_b_direction' verbose_name = _(u"Direction") verbose_name_plural = _(u"Directions") def __unicode__(self): return self.label
def save(self, *args, **kwargs): if self.pk is not None and kwargs.get('update_fields', None) is None: field_names = set() for field in self._meta.concrete_fields: if not field.primary_key and not hasattr(field, 'through'): field_names.add(field.attname) old_trek = Trek.objects.get(pk=self.pk) if self.geom is not None and old_trek.geom.equals_exact(self.geom, tolerance=0.00001): field_names.remove('geom') if self.geom_3d is not None and old_trek.geom_3d.equals_exact(self.geom_3d, tolerance=0.00001): field_names.remove('geom_3d') return super(Trek, self).save(update_fields=field_names, *args, **kwargs) super(Trek, self).save(*args, **kwargs) Path.add_property('treks', Trek.path_treks, _(u"Treks")) Topology.add_property('treks', Trek.topology_treks, _(u"Treks")) if settings.HIDE_PUBLISHED_TREKS_IN_TOPOLOGIES: Topology.add_property('published_treks', lambda self: [], _(u"Published treks")) else: Topology.add_property('published_treks', lambda self: intersecting(Trek, self).filter(published=True), _(u"Published treks")) Intervention.add_property('treks', lambda self: self.topology.treks if self.topology else [], _(u"Treks")) Project.add_property('treks', lambda self: self.edges_by_attr('treks'), _(u"Treks")) tourism_models.TouristicContent.add_property('treks', lambda self: intersecting(Trek, self), _(u"Treks")) tourism_models.TouristicContent.add_property('published_treks', lambda self: intersecting(Trek, self).filter(published=True), _(u"Published treks")) tourism_models.TouristicEvent.add_property('treks', lambda self: intersecting(Trek, self), _(u"Treks")) tourism_models.TouristicEvent.add_property('published_treks', lambda self: intersecting(Trek, self).filter(published=True), _(u"Published treks")) class TrekRelationshipManager(models.Manager): use_for_related_fields = True
@property def geomtransform(self): geom = self.topo_object.geom return geom.transform(settings.API_SRID, clone=True) @property def lat_value(self): return self.geomtransform.x @property def lng_value(self): return self.geomtransform.y Path.add_property('signages', lambda self: Signage.path_signages(self), _("Signages")) Topology.add_property('signages', Signage.topology_signages, _("Signages")) Topology.add_property('published_signages', lambda self: Signage.published_topology_signages(self), _("Published Signages")) class Direction(models.Model): label = models.CharField(db_column="etiquette", max_length=128) class Meta: db_table = 's_b_direction' verbose_name = _("Direction") verbose_name_plural = _("Directions") def __str__(self):
def test_link_closest_visible_path(self): """ Topology must be linked to the closest visible path only """ path_visible = Path(name="visible", geom='LINESTRING(0 0, 1 0, 2 0)', visible=True) path_visible.save() path_unvisible = Path(name="unvisible", geom='LINESTRING(0 3, 1 3, 2 3)', visible=False) path_unvisible.save() # default manager see 1 path self.assertEqual(Path.objects.count(), 1) # custom manager see 2 paths self.assertEqual(Path.include_invisible.count(), 2) # create topo on visible path topology = Topology._topologypoint(0, 0, None) topology.save() # because FK and M2M are used with default manager only, others tests are in SQL conn = connections[DEFAULT_DB_ALIAS] cur = conn.cursor() cur.execute(""" SELECT t.id as id_path, et.topo_object_id as id_topology, t.visible as visible FROM core_pathaggregation et JOIN core_path t ON et.path_id=t.id WHERE et.topo_object_id={topo_id} """.format(topo_id=topology.pk)) datas = dictfetchall(cur) # topo must be linked to visible path self.assertIn(topology.pk, [ele['id_topology'] for ele in datas], "{}".format(datas)) self.assertIn(path_visible.pk, [ele['id_path'] for ele in datas], "{}".format(datas)) self.assertNotIn(path_unvisible.pk, [ele['id_path'] for ele in datas], "{}".format(datas)) # new topo on invible path topology = Topology._topologypoint(0, 3, None) topology.save() cur.execute(""" SELECT t.id as id_path, et.topo_object_id as id_topology, t.visible as visible FROM core_pathaggregation et JOIN core_path t ON et.path_id=t.id WHERE et.topo_object_id={topo_id} """.format(topo_id=topology.pk)) datas = dictfetchall(cur) self.assertIn(topology.pk, [ele['id_topology'] for ele in datas], "{}".format(datas)) self.assertIn(path_visible.pk, [ele['id_path'] for ele in datas], "{}".format(datas)) self.assertNotIn(path_unvisible.pk, [ele['id_path'] for ele in datas], "{}".format(datas)) cur.close()
def test_link_closest_visible_path(self): """ Topology must be linked to the closest visible path only """ path_visible = Path(name="visible", geom='LINESTRING(0 0, 1 0, 2 0)', visible=True) path_visible.save() path_unvisible = Path(name="unvisible", geom='LINESTRING(0 3, 1 3, 2 3)', visible=False) path_unvisible.save() # default manager see 1 path self.assertEqual(Path.objects.count(), 1) # custom manager see 2 paths self.assertEqual(Path.include_invisible.count(), 2) # create topo on visible path topology = TopologyHelper._topologypoint(0, 0, None).reload() # because FK and M2M are used with default manager only, others tests are in SQL conn = connections[DEFAULT_DB_ALIAS] cur = conn.cursor() cur.execute( """ SELECT t.id as id_path, et.evenement as id_topology, t.visible as visible FROM e_r_evenement_troncon et JOIN l_t_troncon t ON et.troncon=t.id WHERE et.evenement={topo_id} """.format(topo_id=topology.pk)) datas = dictfetchall(cur) # topo must be linked to visible path self.assertIn(topology.pk, [ele['id_topology'] for ele in datas], u"{}".format(datas)) self.assertIn(path_visible.pk, [ele['id_path'] for ele in datas], u"{}".format(datas)) self.assertNotIn(path_unvisible.pk, [ele['id_path'] for ele in datas], u"{}".format(datas)) # new topo on invible path topology = TopologyHelper._topologypoint(0, 3, None).reload() cur.execute( """ SELECT t.id as id_path, et.evenement as id_topology, t.visible as visible FROM e_r_evenement_troncon et JOIN l_t_troncon t ON et.troncon=t.id WHERE et.evenement={topo_id} """.format(topo_id=topology.pk)) datas = dictfetchall(cur) self.assertIn(topology.pk, [ele['id_topology'] for ele in datas], u"{}".format(datas)) self.assertIn(path_visible.pk, [ele['id_path'] for ele in datas], u"{}".format(datas)) self.assertNotIn(path_unvisible.pk, [ele['id_path'] for ele in datas], u"{}".format(datas)) cur.close()
@classmethod def path_area_edges(cls, path): return cls.objects.existing()\ .select_related('restricted_area')\ .select_related('restricted_area__area_type')\ .filter(aggregations__path=path).distinct('pk') @classmethod def topology_area_edges(cls, topology): return cls.overlapping(topology)\ .select_related('restricted_area')\ .select_related('restricted_area__area_type') if settings.TREKKING_TOPOLOGY_ENABLED: Path.add_property('area_edges', RestrictedAreaEdge.path_area_edges, _("Restricted area edges")) Path.add_property( 'areas', lambda self: uniquify( map(attrgetter('restricted_area'), self.area_edges)), _("Restricted areas")) Path.add_property( 'published_areas', lambda self: [area for area in self.areas if area.published], _("Published areas")) Topology.add_property('area_edges', RestrictedAreaEdge.topology_area_edges, _("Restricted area edges")) Topology.add_property( 'areas', lambda self: uniquify(intersecting(RestrictedArea, self)) if self.ispoint() else uniquify( map(attrgetter('restricted_area'), self.area_edges)), _("Restricted areas"))
aggregations__path=path).distinct('pk') else: area = path.geom.buffer( settings.TREK_INFRASTRUCTURE_INTERSECTION_MARGIN) return cls.objects.existing().filter(geom__intersects=area) @classmethod def topology_infrastructures(cls, topology): if settings.TREKKING_TOPOLOGY_ENABLED: qs = cls.overlapping(topology) else: area = topology.geom.buffer( settings.TREK_INFRASTRUCTURE_INTERSECTION_MARGIN) qs = cls.objects.existing().filter(geom__intersects=area) return qs @classmethod def published_topology_infrastructure(cls, topology): return cls.topology_infrastructures(topology).filter(published=True) Path.add_property('infrastructures', lambda self: Infrastructure.path_infrastructures(self), _("Infrastructures")) Topology.add_property('infrastructures', Infrastructure.topology_infrastructures, _("Infrastructures")) Topology.add_property('published_infrastructures', Infrastructure.published_topology_infrastructure, _("Published Infrastructures"))
in_structure = InfrastructureStructureManager() class Meta: proxy = True verbose_name = _(u"Infrastructure") verbose_name_plural = _(u"Infrastructures") @classmethod def path_infrastructures(cls, path): return cls.objects.filter(aggregations__path=path).distinct('pk') @classmethod def topology_infrastructures(cls, topology): return cls.objects.filter(aggregations__path__in=topology.paths.all()).distinct('pk') Path.add_property('infrastructures', lambda self: Infrastructure.path_infrastructures(self)) Topology.add_property('infrastructures', lambda self: Infrastructure.topology_infrastructures(self)) class SignageGISManager(gismodels.GeoManager): """ Overide default typology mixin manager, and filter by type. """ def get_query_set(self): return super(SignageGISManager, self).get_query_set().filter(type__type=INFRASTRUCTURE_TYPES.SIGNAGE) class SignageStructureManager(StructureRelatedManager): """ Overide default structure related manager, and filter by type. """ def get_query_set(self): return super(SignageStructureManager, self).get_query_set().filter(type__type=INFRASTRUCTURE_TYPES.SIGNAGE)
class Meta: proxy = True verbose_name = _(u"Infrastructure") verbose_name_plural = _(u"Infrastructures") @classmethod def path_infrastructures(cls, path): return cls.objects.existing().filter(aggregations__path=path).distinct("pk") @classmethod def topology_infrastructures(cls, topology): return cls.overlapping(topology) Path.add_property("infrastructures", lambda self: Infrastructure.path_infrastructures(self), _(u"Infrastructures")) Topology.add_property( "infrastructures", lambda self: Infrastructure.topology_infrastructures(self), _(u"Infrastructures") ) class SignageGISManager(gismodels.GeoManager): """ Overide default typology mixin manager, and filter by type. """ def get_queryset(self): return super(SignageGISManager, self).get_queryset().filter(type__type=INFRASTRUCTURE_TYPES.SIGNAGE) class SignageStructureManager(StructureRelatedManager): """ Overide default structure related manager, and filter by type. """
def __unicode__(self): return u"%s (%s)" % (self.name, self.date) @classmethod def path_interventions(cls, path): return cls.objects.existing().filter(topology__aggregations__path=path) @classmethod def topology_interventions(cls, topology): topos = Topology.overlapping(topology).values_list('pk', flat=True) return cls.objects.existing().filter(topology__in=topos).distinct('pk') Path.add_property('interventions', lambda self: Intervention.path_interventions(self), _(u"Interventions")) Topology.add_property('interventions', lambda self: Intervention.topology_interventions(self), _(u"Interventions")) class InterventionStatus(StructureOrNoneRelated): status = models.CharField(verbose_name=_(u"Status"), max_length=128, db_column='status') class Meta: db_table = 'm_b_suivi' verbose_name = _(u"Intervention's status")
self.physical_type ) @property def physical_type_csv_display(self): return unicode(self.physical_type) @classmethod def path_physicals(cls, path): return cls.objects.select_related('physical_type').filter(aggregations__path=path).distinct('pk') @classmethod def topology_physicals(cls, topology): return cls.overlapping(topology).select_related('physical_type') Path.add_property('physical_edges', PhysicalEdge.path_physicals) Topology.add_property('physical_edges', PhysicalEdge.topology_physicals) Intervention.add_property('physical_edges', lambda self: self.topology.physical_edges if self.topology else []) Project.add_property('physical_edges', lambda self: self.edges_by_attr('physical_edges')) class LandType(StructureRelated): name = models.CharField(max_length=128, db_column='foncier', verbose_name=_(u"Name")) right_of_way = models.BooleanField(db_column='droit_de_passage', verbose_name=_(u"Right of way")) class Meta: db_table = 'f_b_foncier' verbose_name = _(u"Land type") verbose_name_plural = _(u"Land types") ordering = ['name']
def test_path_form_is_not_valid_if_no_geometry_provided(self): self.login() data = self.get_good_data() data['geom'] = '' response = self.client.post(Path.get_add_url(), data) self.assertEqual(response.status_code, 200)
return all_years class Infrastructure(MapEntityMixin, BaseInfrastructure): """ An infrastructure in the park, which is not of type SIGNAGE """ type = models.ForeignKey(InfrastructureType, db_column='type', verbose_name=_("Type")) objects = BaseInfrastructure.get_manager_cls(InfrastructureGISManager)() class Meta: db_table = 'a_t_infrastructure' verbose_name = _(u"Infrastructure") verbose_name_plural = _(u"Infrastructures") @classmethod def path_infrastructures(cls, path): return cls.objects.existing().filter(aggregations__path=path).distinct('pk') @classmethod def topology_infrastructures(cls, topology): return cls.overlapping(topology) @classmethod def published_topology_infrastructure(cls, topology): return cls.topology_infrastructures(topology).filter(published=True) Path.add_property('infrastructures', lambda self: Infrastructure.path_infrastructures(self), _(u"Infrastructures")) Topology.add_property('infrastructures', lambda self: Infrastructure.topology_infrastructures(self), _(u"Infrastructures")) Topology.add_property('published_infrastructures', Infrastructure.published_topology_infrastructure, _(u"Published Infrastructures"))
return trekking_tags.duration(self.duration) def __unicode__(self): return u"%s (%s - %s)" % (self.name, self.departure, self.arrival) @classmethod def path_treks(cls, path): return cls.objects.existing().filter( aggregations__path=path).distinct('pk') @classmethod def topology_treks(cls, topology): return cls.overlapping(topology) Path.add_property('treks', Trek.path_treks) Topology.add_property('treks', Trek.topology_treks) Intervention.add_property( 'treks', lambda self: self.topology.treks if self.topology else []) Project.add_property('treks', lambda self: self.edges_by_attr('treks')) class TrekRelationshipManager(models.Manager): use_for_related_fields = True def get_query_set(self): # Select treks foreign keys by default qs = super(TrekRelationshipManager, self).get_query_set().select_related('trek_a', 'trek_b') # Exclude deleted treks return qs.exclude(trek_a__deleted=True).exclude(trek_b__deleted=True)
def path_treks(cls, path): treks = cls.objects.existing().filter(aggregations__path=path) # The following part prevents conflict with default trek ordering # ProgrammingError: SELECT DISTINCT ON expressions must match initial ORDER BY expressions return treks.order_by('topo_object').distinct('topo_object') @classmethod def topology_treks(cls, topology): if settings.TREKKING_TOPOLOGY_ENABLED: qs = cls.overlapping(topology) else: area = topology.geom.buffer(settings.TREK_POI_INTERSECTION_MARGIN) qs = cls.objects.filter(geom__intersects=area) return qs Path.add_property('treks', Trek.path_treks) Topology.add_property('treks', Trek.topology_treks) Intervention.add_property('treks', lambda self: self.topology.treks if self.topology else []) Project.add_property('treks', lambda self: self.edges_by_attr('treks')) class TrekRelationshipManager(models.Manager): use_for_related_fields = True def get_queryset(self): # Select treks foreign keys by default qs = super(TrekRelationshipManager, self).get_queryset().select_related('trek_a', 'trek_b') # Exclude deleted treks return qs.exclude(trek_a__deleted=True).exclude(trek_b__deleted=True)
def is_publishable(self): return self.is_complete() and self.has_geom_valid() def __unicode__(self): return u"%s (%s - %s)" % (self.name, self.departure, self.arrival) @classmethod def path_treks(cls, path): return cls.objects.existing().filter(aggregations__path=path).distinct('pk') @classmethod def topology_treks(cls, topology): return cls.objects.existing().filter(aggregations__path__in=topology.paths.all()).distinct('pk') Path.add_property('treks', lambda self: Trek.path_treks(self)) Topology.add_property('treks', lambda self: Trek.topology_treks(self)) Intervention.add_property('treks', lambda self: self.topology.treks if self.topology else []) Project.add_property('treks', lambda self: self.edges_by_attr('treks')) class TrekRelationshipManager(models.Manager): use_for_related_fields = True def get_query_set(self): # Select treks foreign keys by default qs = super(TrekRelationshipManager, self).get_query_set().select_related('trek_a', 'trek_b') # Exclude deleted treks return qs.exclude(trek_a__deleted=True).exclude(trek_b__deleted=True)
return [o for o, _o in self.ORIENTATION_CHOICES if o in orientation] # Sorting @property def super_wind(self): "Return wind of itself and its descendants" wind = set( sum( self.get_descendants(include_self=True).values_list('wind', flat=True), [])) return [o for o, _o in self.ORIENTATION_CHOICES if o in wind] # Sorting Path.add_property('sites', lambda self: intersecting(Site, self), _("Sites")) Topology.add_property('sites', lambda self: intersecting(Site, self), _("Sites")) TouristicContent.add_property('sites', lambda self: intersecting(Site, self), _("Sites")) TouristicEvent.add_property('sites', lambda self: intersecting(Site, self), _("Sites")) Site.add_property('sites', lambda self: intersecting(Site, self), _("Sites")) Site.add_property('treks', lambda self: intersecting(Trek, self), _("Treks")) Site.add_property('pois', lambda self: intersecting(POI, self), _("POIs")) Site.add_property('trails', lambda self: intersecting(Trail, self), _("Trails")) Site.add_property('infrastructures', lambda self: intersecting(Infrastructure, self), _("Infrastructures"))
@classmethod def path_area_edges(cls, path): return cls.objects.existing()\ .select_related('restricted_area')\ .select_related('restricted_area__area_type')\ .filter(aggregations__path=path).distinct('pk') @classmethod def topology_area_edges(cls, topology): return cls.overlapping(topology)\ .select_related('restricted_area')\ .select_related('restricted_area__area_type') if settings.TREKKING_TOPOLOGY_ENABLED: Path.add_property('area_edges', RestrictedAreaEdge.path_area_edges) Path.add_property('areas', lambda self: uniquify(map(attrgetter('restricted_area'), self.area_edges))) Topology.add_property('area_edges', RestrictedAreaEdge.topology_area_edges) Topology.add_property('areas', lambda self: uniquify(map(attrgetter('restricted_area'), self.area_edges))) Intervention.add_property('area_edges', lambda self: self.topology.area_edges if self.topology else []) Intervention.add_property('areas', lambda self: self.topology.areas if self.topology else []) Project.add_property('area_edges', lambda self: self.edges_by_attr('area_edges')) Project.add_property('areas', lambda self: uniquify(map(attrgetter('restricted_area'), self.area_edges))) else: Topology.add_property('areas', lambda self: intersecting(RestrictedArea, self)) TouristicContent.add_property('areas', lambda self: intersecting(RestrictedArea, self)) TouristicEvent.add_property('areas', lambda self: intersecting(RestrictedArea, self)) class City(models.Model):
self.physical_type ) @property def physical_type_csv_display(self): return unicode(self.physical_type) @classmethod def path_physicals(cls, path): return cls.objects.existing().select_related('physical_type').filter(aggregations__path=path).distinct('pk') @classmethod def topology_physicals(cls, topology): return cls.overlapping(topology).select_related('physical_type') Path.add_property('physical_edges', PhysicalEdge.path_physicals, _(u"Physical edges")) Topology.add_property('physical_edges', PhysicalEdge.topology_physicals, _(u"Physical edges")) Intervention.add_property('physical_edges', lambda self: self.topology.physical_edges if self.topology else [], _(u"Physical edges")) Project.add_property('physical_edges', lambda self: self.edges_by_attr('physical_edges'), _(u"Physical edges")) class LandType(StructureRelated): name = models.CharField(max_length=128, db_column='foncier', verbose_name=_(u"Name")) right_of_way = models.BooleanField(db_column='droit_de_passage', verbose_name=_(u"Right of way")) class Meta: db_table = 'f_b_foncier' verbose_name = _(u"Land type") verbose_name_plural = _(u"Land types") ordering = ['name']
@classmethod def path_area_edges(cls, path): return cls.objects.existing()\ .select_related('restricted_area')\ .select_related('restricted_area__area_type')\ .filter(aggregations__path=path).distinct('pk') @classmethod def topology_area_edges(cls, topology): return cls.overlapping(topology)\ .select_related('restricted_area')\ .select_related('restricted_area__area_type') if settings.TREKKING_TOPOLOGY_ENABLED: Path.add_property('area_edges', RestrictedAreaEdge.path_area_edges, _("Restricted area edges")) Path.add_property('areas', lambda self: uniquify(map(attrgetter('restricted_area'), self.area_edges)), _("Restricted areas")) Topology.add_property('area_edges', RestrictedAreaEdge.topology_area_edges, _("Restricted area edges")) Topology.add_property('areas', lambda self: uniquify( intersecting(RestrictedArea, self)) if self.ispoint() else uniquify( map(attrgetter('restricted_area'), self.area_edges)), _("Restricted areas")) Intervention.add_property('area_edges', lambda self: self.topology.area_edges if self.topology else [], _("Restricted area edges")) Intervention.add_property('areas', lambda self: self.topology.areas if self.topology else [], _("Restricted areas")) Project.add_property('area_edges', lambda self: self.edges_by_attr('area_edges'), _("Restricted area edges")) Project.add_property('areas', lambda self: uniquify(map(attrgetter('restricted_area'), self.area_edges)), _("Restricted areas")) else: Topology.add_property('areas', lambda self: uniquify(intersecting(RestrictedArea, self, distance=0)),
def test_interpolate_not_saved(self): p = Path() with self.assertRaisesRegex( ValueError, "Cannot compute interpolation on unsaved path"): p.interpolate(Point(0, 0))
def physical_type_csv_display(self): return unicode(self.physical_type) @property def display(self): return u'<a data-pk="%s" href="%s" >%s</a>' % (self.pk, self.get_detail_url(), self.physical_type) @classmethod def path_physicals(cls, path): return cls.objects.select_related('physical_type').filter(aggregations__path=path).distinct('pk') @classmethod def topology_physicals(cls, topology): return cls.objects.select_related('physical_type').filter(aggregations__path__in=topology.paths.all()).distinct('pk') Path.add_property('physical_edges', PhysicalEdge.path_physicals) Topology.add_property('physical_edges', PhysicalEdge.topology_physicals) Intervention.add_property('physical_edges', lambda self: self.topology.physical_edges if self.topology else []) Project.add_property('physical_edges', lambda self: self.edges_by_attr('physical_edges')) class LandType(StructureRelated): name = models.CharField(max_length=128, db_column='foncier', verbose_name=_(u"Name")) right_of_way = models.BooleanField(db_column='droit_de_passage', verbose_name=_(u"Right of way")) class Meta: db_table = 'f_b_foncier' verbose_name = _(u"Land type") verbose_name_plural = _(u"Land types") ordering = ['name']
return unicode(self.name) def __unicode__(self): return u"%s (%s)" % (self.name, self.date) @classmethod def path_interventions(cls, path): return cls.objects.existing().filter(topology__aggregations__path=path) @classmethod def topology_interventions(cls, topology): topos = Topology.overlapping(topology).values_list('pk', flat=True) return cls.objects.existing().filter(topology__in=topos).distinct('pk') Path.add_property('interventions', lambda self: Intervention.path_interventions(self), _(u"Interventions")) Topology.add_property('interventions', lambda self: Intervention.topology_interventions(self), _(u"Interventions")) class InterventionStatus(StructureOrNoneRelated): status = models.CharField(verbose_name=_(u"Status"), max_length=128, db_column='status') class Meta: db_table = 'm_b_suivi' verbose_name = _(u"Intervention's status") verbose_name_plural = _(u"Intervention's statuses") ordering = ['id'] def __unicode__(self): if self.structure:
settings.LEAFLET_CONFIG['TILES'][0][0], ] if settings.SHOW_SENSITIVE_AREAS_ON_MAP_SCREENSHOT: maplayers.append(ugettext(u"Sensitive area")) if settings.SHOW_POIS_ON_MAP_SCREENSHOT: maplayers.append(ugettext(u"POIs")) if settings.SHOW_SERVICES_ON_MAP_SCREENSHOT: maplayers.append(ugettext(u"Services")) if settings.SHOW_SIGNAGES_ON_MAP_SCREENSHOT: maplayers.append(ugettext(u"Signages")) if settings.SHOW_INFRASTRUCTURES_ON_MAP_SCREENSHOT: maplayers.append(ugettext(u"Infrastructures")) return {"maplayers": maplayers} Path.add_property('treks', Trek.path_treks, _(u"Treks")) Topology.add_property('treks', Trek.topology_treks, _(u"Treks")) if settings.HIDE_PUBLISHED_TREKS_IN_TOPOLOGIES: Topology.add_property('published_treks', lambda self: [], _(u"Published treks")) else: Topology.add_property('published_treks', lambda self: intersecting(Trek, self).filter(published=True), _(u"Published treks")) Intervention.add_property('treks', lambda self: self.topology.treks if self.topology else [], _(u"Treks")) Project.add_property('treks', lambda self: self.edges_by_attr('treks'), _(u"Treks")) tourism_models.TouristicContent.add_property('treks', lambda self: intersecting(Trek, self), _(u"Treks")) tourism_models.TouristicContent.add_property('published_treks', lambda self: intersecting(Trek, self).filter(published=True), _(u"Published treks")) tourism_models.TouristicEvent.add_property('treks', lambda self: intersecting(Trek, self), _(u"Treks")) tourism_models.TouristicEvent.add_property('published_treks', lambda self: intersecting(Trek, self).filter(published=True), _(u"Published treks")) class TrekRelationshipManager(models.Manager): use_for_related_fields = True
def duration_pretty(self): return trekking_tags.duration(self.duration) def __unicode__(self): return u"%s (%s - %s)" % (self.name, self.departure, self.arrival) @classmethod def path_treks(cls, path): return cls.objects.existing().filter(aggregations__path=path).distinct("pk") @classmethod def topology_treks(cls, topology): return cls.overlapping(topology) Path.add_property("treks", Trek.path_treks) Topology.add_property("treks", Trek.topology_treks) Intervention.add_property("treks", lambda self: self.topology.treks if self.topology else []) Project.add_property("treks", lambda self: self.edges_by_attr("treks")) class TrekRelationshipManager(models.Manager): use_for_related_fields = True def get_query_set(self): # Select treks foreign keys by default qs = super(TrekRelationshipManager, self).get_query_set().select_related("trek_a", "trek_b") # Exclude deleted treks return qs.exclude(trek_a__deleted=True).exclude(trek_b__deleted=True)
@property def display(self): return u'<a data-pk="%s" href="%s" >%s</a>' % ( self.pk, self.get_detail_url(), self.physical_type) @classmethod def path_physicals(cls, path): return cls.objects.select_related('physical_type').filter( aggregations__path=path).distinct('pk') @classmethod def topology_physicals(cls, topology): return cls.overlapping(topology).select_related('physical_type') Path.add_property('physical_edges', PhysicalEdge.path_physicals) Topology.add_property('physical_edges', PhysicalEdge.topology_physicals) Intervention.add_property( 'physical_edges', lambda self: self.topology.physical_edges if self.topology else []) Project.add_property('physical_edges', lambda self: self.edges_by_attr('physical_edges')) class LandType(StructureRelated): name = models.CharField(max_length=128, db_column='foncier', verbose_name=_(u"Name")) right_of_way = models.BooleanField(db_column='droit_de_passage', verbose_name=_(u"Right of way"))
@property def physical_type_csv_display(self): return unicode(self.physical_type) @classmethod def path_physicals(cls, path): return cls.objects.existing().select_related('physical_type').filter( aggregations__path=path).distinct('pk') @classmethod def topology_physicals(cls, topology): return cls.overlapping(topology).select_related('physical_type') Path.add_property('physical_edges', PhysicalEdge.path_physicals, _(u"Physical edges")) Topology.add_property('physical_edges', PhysicalEdge.topology_physicals, _(u"Physical edges")) Intervention.add_property( 'physical_edges', lambda self: self.topology.physical_edges if self.topology else [], _(u"Physical edges")) Project.add_property('physical_edges', lambda self: self.edges_by_attr('physical_edges'), _(u"Physical edges")) class LandType(StructureOrNoneRelated): name = models.CharField(max_length=128, db_column='foncier', verbose_name=_(u"Name")) right_of_way = models.BooleanField(default=False,
@property def physical_type_csv_display(self): return unicode(self.physical_type) @classmethod def path_physicals(cls, path): return cls.objects.select_related('physical_type').filter( aggregations__path=path).distinct('pk') @classmethod def topology_physicals(cls, topology): return cls.overlapping(topology).select_related('physical_type') Path.add_property('physical_edges', PhysicalEdge.path_physicals) Topology.add_property('physical_edges', PhysicalEdge.topology_physicals) Intervention.add_property( 'physical_edges', lambda self: self.topology.physical_edges if self.topology else []) Project.add_property('physical_edges', lambda self: self.edges_by_attr('physical_edges')) class LandType(StructureRelated): name = models.CharField(max_length=128, db_column='foncier', verbose_name=_(u"Name")) right_of_way = models.BooleanField(db_column='droit_de_passage', verbose_name=_(u"Right of way"))