123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- # -*- coding: utf-8 -*-
- from __future__ import unicode_literals
- from django.conf import settings
- from django.core.urlresolvers import reverse_lazy
- from django.http import HttpResponse, JsonResponse
- from django.shortcuts import render, get_object_or_404
- from django.utils.decorators import method_decorator
- from django.views.generic import CreateView, DetailView, RedirectView, ListView, TemplateView
- from django.views.decorators.csrf import ensure_csrf_cookie
- from django.contrib.auth.mixins import LoginRequiredMixin
- from .models import Point, Panorama, ReferencePoint
- from .forms import SelectReferencePointForm, CustomPointForm, PanoramaForm, ReferencePointForm
- class CelutzLoginMixin(LoginRequiredMixin):
- """Mixin that acts like LoginRequiredMixin if settings.LOGIN_REQUIRED is
- True, and does nothing otherwise. It allows to choose whether
- accessing celutz requires an account or is open to anybody.
- """
- login_url = '/admin/login/'
- def dispatch(self, request, *args, **kwargs):
- """Small hack: either call our parent (LoginRequiredMixin) or bypass it"""
- if settings.LOGIN_REQUIRED:
- return super(CelutzLoginMixin, self).dispatch(request, *args, **kwargs)
- else:
- return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
- class PanoramaUpload(CelutzLoginMixin, CreateView):
- model = Panorama
- fields = ('name', 'image', 'loop', 'latitude', 'longitude', 'ground_altitude', 'height_above_ground')
- template_name = "panorama/new.html"
- prefix = 'newpano'
- def get_success_url(self):
- return reverse_lazy("panorama:gen_tiles", kwargs={"pk": self.object.id})
- @method_decorator(ensure_csrf_cookie, name='dispatch')
- class PanoramaView(CelutzLoginMixin, DetailView):
- model = Panorama
- template_name = "panorama/view.html"
- context_object_name = "panorama"
- def get_context_data(self, **kwargs):
- context = super(PanoramaView, self).get_context_data(**kwargs)
- pano = context['panorama']
- context['panoramas'] = [p for p in Panorama.objects.all() if pano.great_circle_distance(p) <= settings.PANORAMA_MAX_DISTANCE]
- context['poi_list'] = [poi for poi in ReferencePoint.objects.all() if not hasattr(poi, 'panorama') and pano.great_circle_distance(poi) <= settings.PANORAMA_MAX_DISTANCE]
- return context
- class PanoramaGenTiles(CelutzLoginMixin, RedirectView):
- permanent = False
- pattern_name = "panorama:view_pano"
- def get_redirect_url(self, *args, **kwargs):
- pano = get_object_or_404(Panorama, pk=kwargs['pk'])
- pano.generate_tiles()
- return super(PanoramaGenTiles, self).get_redirect_url(*args, **kwargs)
- class MainView(CelutzLoginMixin, TemplateView):
- template_name = "panorama/main.html"
- def get_context_data(self, **kwargs):
- context = super(MainView, self).get_context_data(**kwargs)
- context['refpoints_form'] = SelectReferencePointForm
- context['custom_point_form'] = CustomPointForm
- context['newpanorama_form'] = PanoramaForm
- context['newrefpoint_form'] = ReferencePointForm
- context['panoramas'] = Panorama.objects.all()
- context['poi_list'] = [poi for poi in ReferencePoint.objects.all() if not hasattr(poi, 'panorama')]
- return context
- def compute_interesting_panoramas(self, point):
- """Compute all panoramas that see the given point, along with the distance
- and direction from each panorama towards the point. Returns a
- list of (panorama, distance, bearing, elevation) triples.
- """
- if isinstance(point, ReferencePoint):
- queryset = Panorama.objects.exclude(id=point.id)
- else:
- queryset = Panorama.objects
- l = [(pano, pano.line_distance(point), pano.bearing(point), pano.elevation(point))
- for pano in queryset.all() if pano.is_visible(point) and pano.great_circle_distance(point) <= settings.LOCATE_POINT_MAX_DISTANCE]
- # Sort by increasing distance
- return sorted(l, key=lambda x: x[1])
- class CreateReferencePoint(CelutzLoginMixin, CreateView):
- model = ReferencePoint
- fields = ('name', 'latitude', 'longitude', 'ground_altitude', 'height_above_ground')
- template_name = 'panorama/new-refpoint.html'
- prefix = 'newrefpoint'
- def get_success_url(self):
- return reverse_lazy("panorama:main")
- class LocateReferencePointView(MainView):
- """Displays a located reference point"""
- template_name = 'panorama/locate_point.html'
- def post(self, request, *args, **kwargs):
- context = self.get_context_data()
- form = SelectReferencePointForm(request.POST)
- if form.is_valid():
- point = form.cleaned_data['reference_point']
- context['located_panoramas'] = self.compute_interesting_panoramas(point)
- context['located_point_name'] = point.name
- context['located_point_lat'] = point.latitude
- context['located_point_lon'] = point.longitude
- return super(LocateReferencePointView, self).render_to_response(context)
- class LocateCustomPointView(MainView):
- """Displays a located custom GPS point"""
- template_name = 'panorama/locate_point.html'
- def post(self, request, *args, **kwargs):
- context = self.get_context_data()
- form = CustomPointForm(request.POST)
- if form.is_valid():
- point = Point(**form.cleaned_data)
- context['located_panoramas'] = self.compute_interesting_panoramas(point)
- context['located_point_lat'] = point.latitude
- context['located_point_lon'] = point.longitude
- return super(LocateCustomPointView, self).render_to_response(context)
|