From d0e0eee15a0f02a35121bf1758547e01ce22d22a Mon Sep 17 00:00:00 2001 From: expoonserver <devnull@localhost> Date: Tue, 17 Apr 2018 21:57:02 +0100 Subject: [PATCH] Add CaveView spinny caves view to each troggle cave page --- core/views_caves.py | 22 ++- templates/cave.html | 436 +++++++++++++++++++++++++++++++++++++++++++- urls.py | 1 + 3 files changed, 454 insertions(+), 5 deletions(-) diff --git a/core/views_caves.py b/core/views_caves.py index 2dcef5e..db3e52d 100644 --- a/core/views_caves.py +++ b/core/views_caves.py @@ -17,7 +17,7 @@ import re, urlparse from django.shortcuts import get_object_or_404 import settings -import Image, ImageDraw, ImageFont, string, os, sys +import Image, ImageDraw, ImageFont, string, os, sys, subprocess def getCave(cave_id): """Returns a cave object when given a cave name or number. It is used by views including cavehref, ent, and qm.""" @@ -58,12 +58,26 @@ def caveindex(request): caves1626.sort(caveCmp) return render_with_context(request,'caveindex.html', {'caves1623': caves1623, 'caves1626': caves1626, 'notablecaves':notablecaves, 'cavepage': True}) +def cave3d(request, cave_id): + cave = getCave(cave_id) + survexfilename = '/home/expo/loser/' + cave.survex_file + threedfilename = '/home/expo/expowebcache/3d/%s.3d' % cave_id + if True or os.path.getmtime(survexfilename) > os.path.getmtime(threedfilename): + subprocess.call(["cavern", "--output=%s" % threedfilename, survexfilename]) + test_file = open(threedfilename, 'rb') + response = HttpResponse(content=test_file, mimetype='application/3d')#mimetype is replaced by content_type for django 1.7 + response['Content-Disposition'] = 'attachment; filename=%s.3d' % cave_id + # response['X-Sendfile'] = "%s.3d" % cave_id + # It's usually a good idea to set the 'Content-Length' header too. + # You can also set any other required headers: Cache-Control, etc. + return response + def cave(request, cave_id='', offical_name=''): cave=getCave(cave_id) if cave.non_public and settings.PUBLIC_SITE and not request.user.is_authenticated(): - return render_with_context(request,'nonpublic.html', {'instance': cave, 'cavepage': True}) + return render_with_context(request,'nonpublic.html', {'instance': cave, 'cavepage': True, 'cave_id': cave_id}) else: - return render_with_context(request,'cave.html', {'settings': settings, 'cave': cave, 'cavepage': True}) + return render_with_context(request,'cave.html', {'settings': settings, 'cave': cave, 'cavepage': True, 'cave_id': cave_id}) def caveEntrance(request, slug): cave = Cave.objects.get(caveslug__slug = slug) @@ -202,7 +216,7 @@ def qm(request,cave_id,qm_id,year,grade=None): return HttpResponseRedirect(url) - + def ent(request, cave_id, ent_letter): cave = Cave.objects.filter(kataster_number = cave_id)[0] cave_and_ent = CaveAndEntrance.objects.filter(cave = cave).filter(entrance_letter = ent_letter)[0] diff --git a/templates/cave.html b/templates/cave.html index 5bd77f6..a8321a8 100644 --- a/templates/cave.html +++ b/templates/cave.html @@ -1,5 +1,438 @@ {% extends "cavebase.html" %} +{% block extraheaders %} +{% if cave.survex_file %} +<style> + + +div.cv-panel { + position: absolute; + top: 0; + left: 0; + z-index: 100; + background-color: rgba(50,50,50,0.5); + color: yellowgreen; + border: 1px solid black; + border-radius: 5px; +} + +div.cv-compass, div.cv-ahi { + position: absolute; + bottom: 95px; + right: 5px; + margin: 0; + padding-top: 2px; + /* border: 1px solid white; */ + text-align: center; + width: 78px; + height: 19px; + z-index: 50; + background-color: rgba(50,50,50,0.5); + background-color: black; + color: white; +} + +div.cv-ahi { + right: 95px; +} + +div.scale-legend { + position: absolute; + color: white; + background-color: black; + bottom: 30px; +} + +div.linear-scale { + position: absolute; + color: white; + background-color: black; + right: 30px; + width: 40px; + padding: 2px 0; + text-align: right; + border: 1px solid black; + font-size: 14px; +} + +div.linear-scale-caption { + position: absolute; + color: white; + background-color: black; + right: 5px; + width: 65px; + padding: 2px 0 5px 0; + text-align: left; + border: 1px solid black; + font-size: 14px; +} + +#min-div { + border-bottom: 1px solid white; +} + +#max-div { + border-top: 1px solid white; +} + +#angle-legend { + position: absolute; + width: 80px; + right: 5px; + bottom: 180px; + color: white; + background-color: black; + font-size: 14px; + text-align: center; +} + +#scene { + width: 100%; + height: 700px; + position: relative; +} + +#progress-bar { + position: absolute; + top: 55%; + height: 20px; + border: 1px solid white; + z-index: 100; +} + +#status-text { + position: absolute; + top: 50%; + height: 20px; + padding-left: 4px; + background-color: black; + color: white; + z-index: 100; +} + +#frame div.page ul { + list-style-type: none; + margin: 8px 0 0 0; + padding: 0; + width: 200px; + height: 100%; + cursor: default; + font-size: 12px; + overflow-y: auto; + overflow-x: hidden; +} + +#frame div.page li { + position: relative; + margin-left: 16px; + border-bottom: 1px solid #444444; +} + +#frame div.page li.selected { + color: #1ab4e5; +} + +#frame div.page li:hover { + color: yellow; +} + +#frame div.page div#ui-path { + font-size: 12px; + border-top: 1px solid grey; + border-bottom: 1px solid grey; + margin-top: 8px; + padding: 2px 0 2px 12px; +} + +#frame div.page div#ui-path span { + color: #1ab4e5; +} + +#frame div.page div.slide { + position: absolute; + top: 64px; + left: 0px; + height: auto; + margin-top:0; + bottom: 44px; + background-color: #222222; + transition: transform 0.25s ease-in; +} + +#frame div.slide-out { + border-right: 1px grey solid; + transform: translateX(-100%); +} + +#frame div.page div.descend-tree { + position: absolute; + top: 0px; + right: 0px; + margin: 0; + color: #1ab4e5; + z-index: 110; +} + +#frame { + position: absolute; + top: 0px; + left: 0px; + width: 240px; + height: 100%; + background-color: transparent; + transform: translateX(-200px); + transition: transform 0.25s ease-in; +} + +#frame.onscreen { + transform: none; + transition: transform 0.25s ease-out; +} + +#frame a.download { + border: 1px solid green; + display: block; + width: 180px; + box-sizing: border-box; + margin-top: 6px; + margin-bottom: 4px; + margin-left: 8px; + border: none; + border-bottom: 4px solid #1ab4e5; + color: #dddddd; + background-color: black; + padding-bottom: 4px; + box-shadow: 1px 1px 8px 0px #888888; + outline: nonlass="cavedisplay"e; + text-decoration: none; + text-align: center; +} + +#frame a.download:hover { + color: white; +} + +#frame a.download:active { + color: #dddddd; + border-bottom: 4px solid #0c536a; + box-shadow: none; + box-shadow: inset 1px 1px 8px 0px #888888; +} +#frame .tab { + position: absolute; + right: 0px;lass="cavedisplay" + width: 40px; + height: 40px; + box-sizing: border-box; + background-color: #444444; + border-left: 1px solid black; + background-position: center; + border-top: 1px solid black; +} + +#frame #close { + position: absolute; + right: 40px; + bottom: 0px; + width: 40px; + height: 40px; + box-sizing: border-box; + z-index: 150; + background-image: url(../images/ic_remove.png); + background-position: center; +} + +#icon_settings { + background-image: url(../images/ic_settings.png); +} + +#icon_terrain { + background-image: url(../images/ic_terrain.png); +} + +#icon_explore { + background-image: url(../images/ic_explore.png); +} + +#icon_info { + background-image: url(../images/ic_info.png); +} + +#icon_route { + background-image: url(../images/ic_route.png); +} + +#icon_help { + background-image: url(../images/ic_help.png); +} + +#frame div.toptab { + background-color: #222222; + border-left: none; + border-right: 1px solid grey; + border-top: 1px solid grey; +} + +#frame div.page { + position: absolute; + top: 0px; + bottom: 40px; + left: 0px; + width: 200px; + height: 100%; + color: white; + background-color: #222222; + padding: 0 4px; + box-sizing: border-box; + cursor: default; + padding-bottom: 40px; +} + +#frame div.page div.header { + margin: 16px 0px 8px 0px; + font-weight: bold; + height: 16px; + box-sizing: border-box; + padding-left: 2px; +} + +#frame div.page div.control { + margin: 2px 0 2px 0; + padding-top: 2px; +} + +#frame div.page label { + display: block; + border-top: 1px solid grey; + padding: 2px 0 2px 8px; + font-size: 12px; +} + +#frame div.page select { + display: block; + width: 180px; + box-sizing: border-box; + padding-top: 2px; + margin: 2px 0 4px 8px; +} + +#frame div.page select:empty { + background-color: #888888; +} + +#frame div.page button { + display: block; + width: 180px; + box-sizing: border-box; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 8px; + border: none; + border-bottom: 4px solid #1ab4e5; + color: #dddddd; + background-color: black; + padding-bottom: 4px; + box-shadow: 1px 1px 8px 0px #888888; + outline: none; +} + +#frame div.page button:hover { + color: white; +} + +#frame div.page button:active { + color: #dddddd; + border-bottom: 4px solid #0c536a; + box-shadow: none; + box-shadow: inset 1px 1px 8px 0px #888888; +} + +#frame div.page input[type="text"] { + display: block; + width: 180px; + box-sizing: border-box; + margin-top: 2px; + margin-left: 8px; +} + +#frame div.page input[type="checkbox"] { + position: absolute; + right: 0px; +} + +#frame div.page input[type="range"] { + display: block; + width: 180px; + margin-left: 8px; +} + +#frame dt, #frame dd { + font-size: 12px; +} + +#frame dt { + clear: both; + float: left; + padding-left: 16px; +} + +#frame dd { + margin-left: 40px; +} + +#frame p { + font-size: 12px; + line-height: 18px; +} + +div.station-info { + position: absolute; + border: 1px solid white; + background-color: #222222; + color: white; + padding: 4px; + z-index: 200; +} + + +.overlay-branding { + color: white; + margin: 4px; + position: absolute; + right: 0; + top: 0; +} +div#scene { + width: 100%; + height: 90%; } + +</style> + +<script type="text/javascript" src="/CaveView/js/CaveView.js" ></script> +<script type="text/javascript" src="/CaveView/lib/proj4.js" ></script> + + +<script type="text/javascript" > + + function onLoad () { + + // display the user interface - and a blank canvas + // the configuration object specifies the location of CaveView, surveys and terrain files + CV.UI.init( 'scene', { + home: '/javascript/CaveView/', + surveyDirectory: '/cave/3d/', + terrainDirectory: '/loser/surface/terrain/' + } ); + + // load a single survey to display + CV.UI.loadCave( '{% if cave.kataster_number %}{{ cave.kataster_number }}{% else %}{{ cave.unofficial_number }}{% endif %}.3d' ); + } + window.onload = onLoad; +</script> +{% endif %} +{% endblock %} + + {% load wiki_markup %} {% block content %} {% block contentheader %} @@ -131,7 +564,8 @@ {% endif %} {% if cave.survex_file %} <h2>Survex File</h2> - {{ cave.survex_file|safe }} + {{ cave.survex_file|safe }} <a href="{% if cave.kataster_number %}{% url cave3d cave.kataster_number %}{% else %}{% url cave3d cave.unofficial_number %}{% endif %}">3d file</a> + <div id='scene'></div> {% endif %} {% if cave.notes %} <h2>Notes</h2> diff --git a/urls.py b/urls.py index 48c9ea4..32084fd 100644 --- a/urls.py +++ b/urls.py @@ -56,6 +56,7 @@ actualurlpatterns = patterns('', #url(r'^cavedescription/(?P<cavedescription_name>[^/]+)/?$', views_caves.cave_description, name="cavedescription"), #url(r'^cavedescription/?$', object_list, {'queryset':CaveDescription.objects.all(),'template_name':'object_list.html'}, name="cavedescriptions"), #url(r'^cavehref/(.+)$', views_caves.cave, name="cave"),url(r'cave'), + url(r'^cave/3d/(?P<cave_id>[^/]+).3d$', views_caves.cave3d, name="cave3d"), # url(r'^jgtfile/(.*)$', view_surveys.jgtfile, name="jgtfile"), # url(r'^jgtuploadfile$', view_surveys.jgtuploadfile, name="jgtuploadfile"),