From f8b613e0aaaff0cf6dde99d677bb9c5ae6b4d09d Mon Sep 17 00:00:00 2001 From: Philip Sargent Date: Sat, 17 Apr 2021 01:41:06 +0100 Subject: [PATCH] prospect and moving code to better places --- core/models/troggle.py | 2 +- core/views/caves.py | 7 +- core/views/prospect.py | 153 +++++++++++++++++++-------------------- parsers/survex.py | 49 +++++++++++-- templates/caveindex.html | 1 + urls.py | 4 +- 6 files changed, 129 insertions(+), 87 deletions(-) diff --git a/core/models/troggle.py b/core/models/troggle.py index f1f10be..c41e6f0 100644 --- a/core/models/troggle.py +++ b/core/models/troggle.py @@ -24,7 +24,7 @@ import troggle.core.models.survex from troggle.core.utils import get_process_memory """This file declares TroggleModel which inherits from django.db.models.Model -All TroggleModel subclasses inherit persistence in the django relational database. This is known as +All TroggleModel and models.Model subclasses inherit persistence in the django relational database. This is known as the django Object Relational Mapping (ORM). There are more subclasses define in models_caves.py models_survex.py etc. """ diff --git a/core/views/caves.py b/core/views/caves.py index dd621aa..2b97aac 100644 --- a/core/views/caves.py +++ b/core/views/caves.py @@ -354,7 +354,7 @@ def edit_cave(request, slug=None): }) @login_required_if_public -def editEntrance(request, caveslug, slug=None): +def edit_entrance(request, caveslug=None, slug=None): '''This is the form that edits the entrance data for a single entrance and writes out an XML file in the :expoweb: repo folder The format for the file being saved is in templates/dataformat/entrance.xml @@ -362,7 +362,10 @@ def editEntrance(request, caveslug, slug=None): It does save the data into into the database directly, not by parsing the file. ''' message = "" - cave = Cave.objects.get(caveslug__slug = caveslug) + if caveslug is not None: + cave = Cave.objects.get(caveslug__slug = caveslug) + else: + cave = Cave() if slug is not None: entrance = Entrance.objects.get(entranceslug__slug = slug) else: diff --git a/core/views/prospect.py b/core/views/prospect.py index f7e10aa..880c8d0 100644 --- a/core/views/prospect.py +++ b/core/views/prospect.py @@ -13,6 +13,7 @@ from django.shortcuts import render import troggle.settings as settings from troggle.core.models.caves import Entrance, Area, SurvexStation, Cave from troggle.core.views.caves import caveKey +from troggle.parsers.survex import MapLocations ''' Generates the prospecting guide document. @@ -61,49 +62,7 @@ def prospecting(request): areas.append((name, a, caves)) return render(request, 'prospecting.html', {"areas": areas}) -class MapLocations(object): - p = [ - ("laser.0_7", "BNase", "Reference", "Bräuning Nase laser point"), - ("226-96", "BZkn", "Reference", "Bräuning Zinken trig point"), - ("vd1","VD1","Reference", "VD1 survey point"), - ("laser.kt114_96","HSK","Reference", "Hinterer Schwarzmooskogel trig point"), - ("2000","Nipple","Reference", "Nipple (Weiße Warze)"), - ("3000","VSK","Reference", "Vorderer Schwarzmooskogel summit"), - ("topcamp", "OTC", "Reference", "Old Top Camp"), - ("laser.0", "LSR0", "Reference", "Laser Point 0"), - ("laser.0_1", "LSR1", "Reference", "Laser Point 0/1"), - ("laser.0_3", "LSR3", "Reference", "Laser Point 0/3"), - ("laser.0_5", "LSR5", "Reference", "Laser Point 0/5"), - ("225-96", "BAlm", "Reference", "Bräuning Alm trig point") - ] - def points(self): - for ent in Entrance.objects.all(): - if ent.best_station(): - try: - k = ent.caveandentrance_set.all()[0].cave - except: - message = " ! Failed to get Cave linked to Entrance:{} from:{} best:{}".format(ent.name, ent.filename, ent.best_station()) - DataIssue.objects.create(parser='entrances', message=message) - print(message) - raise - try: - areaName = k.getArea().short_name - except: - message = " ! Failed to get Area on cave '{}' linked to Entrance:{} from:{} best:{}".format(cave, ent.name, ent.filename, ent.best_station()) - DataIssue.objects.create(parser='entrances', message=message) - print(message) - raise - self.p.append((ent.best_station(), "%s-%s" % (areaName, str(ent)[5:]), ent.needs_surface_work(), str(ent))) - return self.p - - def __str__(self): - return "{} map locations".format(len(self.p)) - - - - - # Parameters for big map and zoomed subarea maps: # big map first (zoom factor ignored) @@ -143,6 +102,7 @@ R = 2 B = 3 ZOOM = 4 DESC = 5 +SIZE = 5 areacolours = { '1a' : '#00ffff', @@ -170,7 +130,7 @@ TEXTSIZE = 16 CIRCLESIZE =8 LINEWIDTH = 2 myFont = ImageFont.truetype(FONT, TEXTSIZE) -print(f' - myFont {myFont} {FONT} {TEXTSIZE}') +#print(f' - myFont {myFont} {FONT} {TEXTSIZE}') def mungecoord(x, y, mapcode, img): # Top of Zinken is 73 1201 = dataset 34542 81967 @@ -194,41 +154,24 @@ COL_TYPES = {True: "red", False: "#dddddd", "Reference": "#dddddd"} -def plot(surveypoint, number, point_type, label, mapcode, draw, img): - try: - ss = SurvexStation.objects.lookup(surveypoint) - E, N = ss.x, ss.y - shortnumber = number.replace("—","") - (x,y) = list(map(int, mungecoord(E, N, mapcode, img))) - imgmaps[maparea].append( [x-4, y-SIZE/2, x+4+draw.textsize(shortnumber)[0], y+SIZE/2, shortnumber, label] ) - draw.rectangle([(x+CIRCLESIZE, y-TEXTSIZE/2), (x+CIRCLESIZE*2+draw.textsize(shortnumber)[0], y+TEXTSIZE/2)], fill="#ffffff") - draw.text((x+CIRCLESIZE * 1.5,y-TEXTSIZE/2), shortnumber, fill="#000000") - draw.ellipse([(x-CIRCLESIZE,y-CIRCLESIZE),(x+CIRCLESIZE,y+CIRCLESIZE)], fill=COL_TYPES[point_type], outline="#000000") - except: - pass def prospecting_image(request, name): - # We should replace all this with something that exports an overlay for Google Maps and OpenStreetView + '''This draws map outlines on an existing map image. + But getting the entrances plotted is broken by later changes elsewhere in the system since this code was written. - # test = os.path.join(settings.EXPOFILES, "location_maps", "testmap.png") - # response = HttpResponse(content_type = "image/png") - # with Image.open(test) as im: - - # draw = ImageDraw.Draw(im) - # draw.line((0, 0) + im.size, fill=128) - # draw.line((0, im.size[1], im.size[0], 0), fill=128) - - # # write to stdout - # #im.save(sys.stdout, "PNG") - # img.save(response, "PNG") + SurvexStations are in x=latitude, y=longitude - these are what appear in essentials.gpx + Entrances are in northing, easting - # return response + which is why we can't simply plot all the Entrances... + + We should replace all this with something that exports an overlay for Google Maps and OpenStreetView + ''' mainImage = Image.open(os.path.join(settings.EXPOFILES, "location_maps", "pguidemap.jpg")) # if settings.PUBLIC_SITE and not request.user.is_authenticated: # mainImage = Image.new("RGB", mainImage.size, '#ffffff') m = maps[name] - #imgmaps = [] + imgmaps = [] if name == "all": img = mainImage else: @@ -255,7 +198,7 @@ def prospecting_image(request, name): textlen = draw.textsize(text)[0] + 3 draw.rectangle([l, t, l+textlen, t+TEXTSIZE+2], fill='#ffffff') draw.text((l+2, t+1), text, fill="#000000", font=myFont) - #imgmaps.append( [l, t, l+textlen, t+SIZE+2, "submap" + maparea, maparea + " subarea map"] ) + imgmaps.append( [l, t, l+textlen, t+SIZE+2, "submap" + maparea, maparea + " subarea map"] ) draw.line([l, t, r, t], fill='#777777', width=LINEWIDTH) draw.line([l, b, r, b], fill='#777777', width=LINEWIDTH) draw.line([l, t, l, b], fill='#777777', width=LINEWIDTH) @@ -265,6 +208,7 @@ def prospecting_image(request, name): draw.line([l, t, l, t+TEXTSIZE+2], fill='#777777', width=LINEWIDTH) draw.line([l+textlen, t, l+textlen, t+TEXTSIZE+2], fill='#777777', width=LINEWIDTH) #imgmaps[maparea] = [] + # Draw scale bar m100 = int(100 / (m[R] - m[L]) * img.size[0]) draw.line([10, TEXTSIZE*3, 10, TEXTSIZE*2], fill='#000000', width=LINEWIDTH) @@ -273,11 +217,8 @@ def prospecting_image(request, name): label = "100m" draw.text([10 + (m100 - draw.textsize(label)[0]) / 2, TEXTSIZE/2], label, fill='#000000', font=myFont) - ml = MapLocations() - for p in ml.points(): - surveypoint, number, point_type, label = p - plot(surveypoint, number, point_type, label, name, draw, img) - + # Draw the circles for known points + # Northing, Easting, Diameter - but N&E are swapped re database for (N, E, D, num) in [(35975.37, 83018.21, 100, "177"), # Calculated from bearings (35350.00, 81630.00, 50, "71"), # From Auer map (36025.00, 82475.00, 50, "146"), # From mystery map @@ -297,8 +238,66 @@ def prospecting_image(request, name): draw.ellipse([lo[0]+2, lo[1]+2, hi[0]-2, hi[1]-2], outline=areacolours[maparea]) draw.rectangle([lpos[0],lpos[1]-TEXTSIZE/2, lpos[0] + draw.textsize(name)[0], lpos[1]+TEXTSIZE/2], fill="#ffffff") draw.text((lpos[0], lpos[1]-TEXTSIZE/2), num, fill="#000000") + #print(f' CIRCLES - {num} {(N,E,D)}') + + # ml = MapLocations() + # for p in ml.points(): + # surveypoint, number, point_type, label = p + # print(f'{surveypoint}, {number}, {point_type}, {label}') + # plot(surveypoint, number, True, label, name, draw, img) + # print(f'{name},\n{draw},\n{img}') + + ents = Entrance.objects.all() # only has entrances and fixed points in it these days, + # but there are only 11 Entrances with northing, easting and a useable tag! + D = 50 + for e in ents: + try: + E, N = e.easting, e.northing + if e.tag_station: + st = e.tag_station + elif e.exact_station: + st = e.exact_station + elif e.exact_station: + st = e.exact_station + else: + # print(f' No tag - {e.name} ') + continue + if not e.northing: + continue + lo = mungecoord(N-D, E+D, st, img) + hi = mungecoord(N+D, E-D, st, img) + lpos = mungecoord(N-D, E, st, img) + + draw.ellipse([lo,hi], outline="#000000") + draw.ellipse([lo[0]+1, lo[1]+1, hi[0]-1, hi[1]-1], outline="#ffffff") + draw.ellipse([lo[0]+2, lo[1]+2, hi[0]-2, hi[1]-2], outline="#ffffff") + draw.rectangle([lpos[0],lpos[1]-TEXTSIZE/2, lpos[0] + draw.textsize(st)[0], lpos[1]+TEXTSIZE/2], fill="#ffffff") + draw.text((lpos[0], lpos[1]-TEXTSIZE/2), num, fill="#000000") + + # draw.ellipse([(x-CIRCLESIZE,y-CIRCLESIZE),(x+CIRCLESIZE,y+CIRCLESIZE)], fill="red", outline="blue") + # draw.rectangle([(x+CIRCLESIZE, y-TEXTSIZE/2), (x+CIRCLESIZE*2+draw.textsize(shortnumber)[0], y+TEXTSIZE/2)], fill="#ffffff") + # draw.text((x+CIRCLESIZE * 1.5,y-TEXTSIZE/2), shortnumber, fill="#000000") + #print(f' SUCCESS - {st} {(E, N)} ') + except: + #print(f' FAIL - {st} {(E, N)} ') + pass + response = HttpResponse(content_type = "image/png") del draw img.save(response, "PNG") - - return response \ No newline at end of file + return response + +# def plot(surveypoint, number, point_type, label, mapcode, draw, img): + # try: + # ss = SurvexStation.objects.lookup(surveypoint) + # E, N = ss.x, ss.y + # shortnumber = number.replace("—","") + # (x,y) = list(map(int, mungecoord(E, N, mapcode, img))) + # imgmaps[maparea].append( [x-4, y-SIZE/2, x+4+draw.textsize(shortnumber)[0], y+SIZE/2, shortnumber, label] ) + # draw.rectangle([(x+CIRCLESIZE, y-TEXTSIZE/2), (x+CIRCLESIZE*2+draw.textsize(shortnumber)[0], y+TEXTSIZE/2)], fill="#ffffff") + # draw.text((x+CIRCLESIZE * 1.5,y-TEXTSIZE/2), shortnumber, fill="#000000") + # draw.ellipse([(x-CIRCLESIZE,y-CIRCLESIZE),(x+CIRCLESIZE,y+CIRCLESIZE)], fill=COL_TYPES[point_type], outline="#000000") + # print(f' SUCCESS - YES {surveypoint}, {number}, {point_type}, {label}') + # except: + # print(f' - NO {surveypoint}, {number}, {point_type}, {label}') + # pass diff --git a/parsers/survex.py b/parsers/survex.py index af154b7..a073686 100644 --- a/parsers/survex.py +++ b/parsers/survex.py @@ -12,11 +12,10 @@ from django.utils.timezone import get_current_timezone from django.utils.timezone import make_aware import troggle.settings as settings -import troggle.core.models.caves as models_caves +from troggle.core.models.caves import Entrance, QM from troggle.core.utils import get_process_memory, chaosmonkey from troggle.parsers.people import GetPersonExpeditionNameLookup from troggle.parsers.logbooks import GetCaveLookup -from troggle.core.views.prospect import MapLocations from troggle.core.models.troggle import DataIssue, Expedition from troggle.core.models.survex import SurvexPersonRole, ScansFolder, SurvexDirectory, SurvexFile, SurvexBlock, SurvexStation @@ -32,6 +31,46 @@ debugprint = False # Turns on debug printout for just one *include file debugprinttrigger = "!" # debugprinttrigger = "caves-1623/40/old/EisSVH" +class MapLocations(object): + p = [ + ("laser.0_7", "BNase", "Reference", "Bräuning Nase laser point"), + ("226-96", "BZkn", "Reference", "Bräuning Zinken trig point"), + ("vd1","VD1","Reference", "VD1 survey point"), + ("laser.kt114_96","HSK","Reference", "Hinterer Schwarzmooskogel trig point"), + ("2000","Nipple","Reference", "Nipple (Weiße Warze)"), + ("3000","VSK","Reference", "Vorderer Schwarzmooskogel summit"), + ("topcamp", "OTC", "Reference", "Old Top Camp"), + ("laser.0", "LSR0", "Reference", "Laser Point 0"), + ("laser.0_1", "LSR1", "Reference", "Laser Point 0/1"), + ("laser.0_3", "LSR3", "Reference", "Laser Point 0/3"), + ("laser.0_5", "LSR5", "Reference", "Laser Point 0/5"), + ("225-96", "BAlm", "Reference", "Bräuning Alm trig point") + ] + def points(self): + for ent in Entrance.objects.all(): + if ent.best_station(): + try: + k = ent.caveandentrance_set.all()[0].cave + except: + message = " ! Failed to get Cave linked to Entrance:{} from:{} best:{}".format(ent.name, ent.filename, ent.best_station()) + DataIssue.objects.create(parser='entrances', message=message) + print(message) + raise + try: + areaName = k.getArea().short_name + except: + message = " ! Failed to get Area on cave '{}' linked to Entrance:{} from:{} best:{}".format(cave, ent.name, ent.filename, ent.best_station()) + DataIssue.objects.create(parser='entrances', message=message) + print(message) + raise + self.p.append((ent.best_station(), "%s-%s" % (areaName, str(ent)[5:]), ent.needs_surface_work(), str(ent))) + message = f" - {len(self.p)} entrances linked to caves." + print(message) + return self.p + + def __str__(self): + return "{} map locations".format(len(self.p)) + class SurvexLeg(): """No longer a models.Model subclass, so no longer a database table """ @@ -468,7 +507,7 @@ class LoadingSurvex(): # NB none of the SurveyStations are in the DB now, so if we want to link to aSurvexStation # we would have to create one. But that is not obligatory and no QMs loaded from CSVs have one try: - qm = models_caves.QM.objects.create(number=qm_no, + qm = QM.objects.create(number=qm_no, # nearest_station=a_survex_station_object, # can be null nearest_station_description=qm_resolve_station, nearest_station_name=qm_nearest, @@ -747,7 +786,7 @@ class LoadingSurvex(): path_match = re.search(r"caves-(\d\d\d\d)/(\d+|\d\d\d\d-?\w+-\d+)/", survexblock.survexfile.path) if path_match: pos_cave = '%s-%s' % (path_match.group(1), path_match.group(2)) - cave = models_caves.getCaveByReference(pos_cave) + cave = getCaveByReference(pos_cave) if cave: survexfile.cave = cave @@ -1369,5 +1408,5 @@ def LoadPositions(): print(message) DataIssue.objects.create(parser='survex', message=message) raise - print(" - {} SurvexStation entrances found.".format(found)) + print(" - {} SurvexStation entrances found.".format(found)) diff --git a/templates/caveindex.html b/templates/caveindex.html index b4c4ee3..d4443d4 100644 --- a/templates/caveindex.html +++ b/templates/caveindex.html @@ -28,6 +28,7 @@

New Cave
+ New Entrance
Cave Number Index - kept updated

1623

diff --git a/urls.py b/urls.py index 26eacbb..74e6737 100644 --- a/urls.py +++ b/urls.py @@ -120,8 +120,8 @@ trogglepatterns = [ url(r'^(?P162\d)(?P.*)$', cavepage, name="cavepage"), # shorthand /1623/264 BUT url links may break # Entrances - url(r'^entrance/(?P[^/]+)/(?P[^/]+)/edit/', caves.editEntrance, name = "editentrance"), - url(r'^entrance/new/(?P[^/]+)/', caves.editEntrance, name = "newentrance"), # NOT WORKING + url(r'^entrance/new/$', caves.edit_entrance, name = "newentrance"), + url(r'^entrance/(?P[^/]+)/(?P[^/]+)/edit/', caves.edit_entrance, name = "editentrance"), url(r'^statistics/?$', statistics.stats, name="stats"),