import os import string import re #import settings import urllib.parse # from pathlib import Path from PIL import Image, ImageDraw, ImageFont from django.http import HttpResponse from django.shortcuts import render # from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned import troggle.settings as settings from troggle.core.models.caves import Entrance, Area, SurvexStation, Cave from troggle.core.views.caves import caveKey ''' Generates the prospecting guide document. Also produces the overlay of points on top of a prospecting_image map - to be deleted. I have tried to make this work with the version of PIL we have installed but something is missing still. ''' AREANAMES = [ #('', 'Location unclear'), ('1a', '1a – Plateau: around Top Camp'), ('1b', '1b – Western plateau near 182'), ('1c', '1c – Eastern plateau near 204 walk-in path'), ('1d', '1d – Further plateau around 76'), ('2a', '2a – Southern Schwarzmooskogel near 201 path and the Nipple'), ('2b', '2b – Eishöhle area'), ('2b or 4 (unclear)', '2b or 4 (unclear)'), ('2c', '2c – Kaninchenhöhle area'), ('2d', '2d – Steinbrückenhöhle area'), ('3', '3 – Bräuning Alm'), ('4', '4 – Kratzer valley'), ('5', '5 – Schwarzmoos-Wildensee'), ('6', '6 – Far plateau'), ('1626 or 6 (borderline)', '1626 or 6 (borderline)'), ('7', '7 – Egglgrube'), ('8a', '8a – Loser south face'), ('8b', '8b – Loser below Dimmelwand'), ('8c', '8c – Augst See'), ('8d', '8d – Loser-Hochganger ridge'), ('9', '9 – Gschwandt Alm'), ('10', '10 – Altaussee'), ('11', '11 – Augstbach') ] def prospecting(request): '''This produces the multipage 'prospecting guide' document, intended to be printed and carried into the field - in 1999. All the formatting and selection clverness is in the template file. ''' areas = [] for key, name in AREANAMES: a = Area.objects.get(short_name = key) # assumes unique caves = list(a.cave_set.all()) caves.sort(key=caveKey) 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) # These are the values for the url /prospecting/[mapcode].png maps = { # id left top right bottom zoom # G&K G&K G&K G&K factor "all": [33810.4, 85436.5, 38192.0, 81048.2, 0.35, "All"], "40": [36275.6, 82392.5, 36780.3, 81800.0, 3.0, "Eishöhle"], "76": [35440.0, 83220.0, 36090.0, 82670.0, 1.3, "Eislufthöhle"], "204": [36354.1, 84154.5, 37047.4, 83300, 3.0, "Steinbrückenhöhle"], "tc": [35230.0, 82690.0, 36110.0, 82100.0, 3.0, "Near Top Camp"], "grieß": [36000.0, 86300.0, 38320.0, 84400.0, 4.0, "Grießkogel Area"], } for n in list(maps.keys()): L, T, R, B, S, name = maps[n] W = (R-L)/2 H = (T-B)/2 for i in range(2): for j in range(2): maps["%s%i%i" % (n, i, j)] = [L + i * W, T - j * H, L + (i + 1) * W, T - (j + 1) * H, S, name] # Keys in the order in which we want the maps output mapcodes = ["all", "grieß","40", "76", "204", "tc"] # Field codes L = 0 T = 1 R = 2 B = 3 ZOOM = 4 DESC = 5 areacolours = { '1a' : '#00ffff', '1b' : '#ff00ff', '1c' : '#ffff00', '1d' : '#ffffff', '2a' : '#ff0000', '2b' : '#00ff00', '2c' : '#008800', '2d' : '#ff9900', '3' : '#880000', '4' : '#0000ff', '6' : '#000000', # doubles for surface fixed pts, and anything else '7' : '#808080' } for FONT in [ "/usr/share/fonts/truetype/freefont/FreeSans.ttf", "/usr/X11R6/lib/X11/fonts/truetype/arial.ttf", "/mnt/c/windows/fonts/arial.ttf", "C:\WINNT\Fonts\ARIAL.TTF" ]: if os.path.isfile(FONT): break TEXTSIZE = 16 CIRCLESIZE =8 LINEWIDTH = 2 myFont = ImageFont.truetype(FONT, TEXTSIZE) print(f' - myFont {myFont} {FONT} {TEXTSIZE}') def mungecoord(x, y, mapcode, img): # Top of Zinken is 73 1201 = dataset 34542 81967 # Top of Hinter is 1073 562 = dataset 36670 83317 # image is 1417 by 2201 # FACTOR1 = 1000.0 / (36670.0-34542.0) # FACTOR2 = (1201.0-562.0) / (83317 - 81967) # FACTOR = (FACTOR1 + FACTOR2)/2 # The factors aren't the same as the scanned map's at a slight angle. I # can't be bothered to fix this. Since we zero on the Hinter it makes # very little difference for caves in the areas round 76 or 204. # xoffset = (x - 36670)*FACTOR # yoffset = (y - 83317)*FACTOR # return (1073 + xoffset, 562 - yoffset) m = maps[mapcode] factorX, factorY = img.size[0] / (m[R] - m[L]), img.size[1] / (m[T] - m[B]) return ((x - m[L]) * factorX, (m[T] - y) * factorY) 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 # 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") # return response 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 = [] if name == "all": img = mainImage else: M = maps['all'] W, H = mainImage.size l = int((m[L] - M[L]) / (M[R] - M[L]) * W) t = int((m[T] - M[T]) / (M[B] - M[T]) * H) r = int((m[R] - M[L]) / (M[R] - M[L]) * W) b = int((m[B] - M[T]) / (M[B] - M[T]) * H) img = mainImage.crop((l, t, r, b)) w = int(round(m[ZOOM] * (m[R] - m[L]) / (M[R] - M[L]) * W)) h = int(round(m[ZOOM] * (m[B] - m[T]) / (M[B] - M[T]) * H)) img = img.resize((w, h), Image.BICUBIC) draw = ImageDraw.Draw(img) #draw.setfont(myFont) if name == "all": for maparea in list(maps.keys()): if maparea == "all": continue localm = maps[maparea] l,t = mungecoord(localm[L], localm[T], "all", img) r,b = mungecoord(localm[R], localm[B], "all", img) text = maparea + " map" 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"] ) 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) draw.line([r, t, r, b], fill='#777777', width=LINEWIDTH) draw.line([l, t, l+textlen, t], fill='#777777', width=LINEWIDTH) draw.line([l, t+TEXTSIZE+2, l+textlen, t+TEXTSIZE+2], fill='#777777', width=LINEWIDTH) 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) draw.line([10, TEXTSIZE*2, 10+m100, TEXTSIZE*2], fill='#000000', width=LINEWIDTH) draw.line([10+m100, TEXTSIZE * 3, 10+m100, TEXTSIZE*2], fill='#000000', width=LINEWIDTH) 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) 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 (35600.00, 82050.00, 50, "35"), # From Auer map (35650.00, 82025.00, 50, "44"), # From Auer map (36200.00, 82925.00, 50, "178"), # Calculated from bearings (35232.64, 82910.37, 25, "181"), # Calculated from bearings (35323.60, 81357.83, 50, "74") # From Auer map ]: (N,E,D) = list(map(float, (N, E, D))) maparea = Cave.objects.get(kataster_number = num).getArea().short_name lo = mungecoord(N-D, E+D, name, img) hi = mungecoord(N+D, E-D, name, img) lpos = mungecoord(N-D, E, name, img) draw.ellipse([lo,hi], outline="#000000") draw.ellipse([lo[0]+1, lo[1]+1, hi[0]-1, hi[1]-1], outline=areacolours[maparea]) 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") response = HttpResponse(content_type = "image/png") del draw img.save(response, "PNG") return response