Last active
July 6, 2024 14:10
-
-
Save danj2k/374776c005929d4b0de9108f89db6b5f to your computer and use it in GitHub Desktop.
BBC BASIC program to draw a map of Great Britain
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
REM Requires GXR (or BBC Master) for flood fill | |
ON ERROR VDU23,1,1,0;0;0;0;:END | |
MODE 1 | |
REM Swap yellow for green | |
VDU19,2,2,0,0,0 | |
REM Define dither patterns | |
VDU23,12,1,0,0,1,1,0,0,1 | |
VDU23,13,2,0,0,2,2,0,0,2 | |
VDU23,14,1,2,2,1,1,2,2,1 | |
REM Country outlines | |
GCOL 0,3 | |
FOR P% = 1 TO 5 | |
F% = 1 | |
READ X%, Y% | |
REPEAT | |
IF F% = 1 THEN MOVE (X%*4)+230, (Y%*8)+100 ELSE DRAW (X%*4)+230, (Y%*8)+100 | |
IF F% = 1 THEN F% = 0 | |
READ X%, Y% | |
UNTIL X% < 0 | |
NEXT P% | |
REM Flood fill | |
FOR C% = 1 TO 3 | |
READ P% | |
FOR Q% = 1 TO P% | |
READ X%, Y% | |
IF Q% = 1 THEN A% = X%: B% = Y% | |
GCOL 16*C%,0 | |
PLOT &85,(X%*4)+230, (Y%*8)+100 | |
NEXT Q% | |
REM Labels | |
A% = (A%*4)+230: B% = (B%*8)+100 | |
IF C% = 1 THEN B% = 96: A% = A% - 112: L$ = "England" | |
IF C% = 2 THEN B% = 984: A% = A% - 128: L$ = "Scotland" | |
IF C% = 3 THEN A% = A% - 304: B% = B% + 16: L$ = "Wales" | |
VDU 5 | |
MOVE A%, B% | |
GCOL 0,3 | |
PRINT L$; | |
VDU 4 | |
NEXT C% | |
REM Turn cursor off | |
VDU23,1,0;0;0;0; | |
REPEAT UNTIL FALSE | |
REM Data for England | |
DATA 125, 55, 127, 54, 129, 54, 131, 53, 132, 51, 134, 51, 136, 50, 138, 50, 136, 49, 136, 47, 142, 44, 136, 44, 134, 45, 132, 45, 134, 45, 138, 43 | |
DATA 140, 43, 144, 41, 146, 37, 144, 37, 140, 35, 142, 36, 144, 36, 142, 36, 144, 36, 146, 35, 148, 35, 150, 36, 154, 36, 156, 37, 158, 36, 164, 36 | |
DATA 166, 35, 168, 35, 170, 34, 171, 32, 171, 30, 169, 26, 167, 26, 165, 25, 163, 25, 164, 23, 162, 23, 160, 22, 158, 22, 157, 20, 159, 21, 161, 21 | |
DATA 159, 21, 155, 19, 153, 19, 155, 19, 157, 18, 167, 18, 167, 16, 163, 14, 161, 14, 157, 12, 153, 12, 151, 11, 147, 11, 145, 10, 143, 10, 141, 11 | |
DATA 131, 11, 129, 10, 119, 10, 117, 11, 115, 10, 107, 10, 103, 8, 99, 8, 97, 9, 97, 7, 93, 9, 91, 9, 89, 10, 87, 10, 85, 9, 77, 9 | |
DATA 76, 7, 76, 5, 74, 5, 72, 4, 70, 4, 68, 5, 66, 5, 64, 6, 62, 5, 60, 6, 58, 6, 56, 5, 52, 5, 50, 4, 48, 4, 46, 3 | |
DATA 45, 1, 43, 1, 42, 3, 38, 3, 36, 2, 34, 2, 35, 4, 41, 4, 43, 5, 45, 5, 46, 7, 48, 7, 50, 8, 52, 8, 56, 10, 57, 12 | |
DATA 59, 13, 63, 13, 63, 15, 65, 15, 67, 16, 77, 16, 79, 15, 83, 15, 87, 17, 84, 17, 86, 18, 88, 18, 90, 19, 92, 19, 92, 21, 93, 23 | |
DATA 89, 23, 87, 24, 85, 24, 84, 26, 86, 27, 87, 29, 83, 29, 87, 31, 85, 31, 86, 33, 84, 34, 88, 36, 90, 36, 92, 35, 90, 36, 89, 38 | |
DATA 87, 38, 83, 40, 82, 42, 84, 41, 86, 41, 85, 43, 86, 45, 86, 47, 90, 49, 82, 49, 81, 51, 77, 53, 77, 55, 79, 56, 80, 58, 82, 59 | |
DATA 86, 59, 90, 61, 92, 61, 100, 65, 102, 65, 100, 66, 101, 68, 103, 68, 105, 69, 111, 66, 112, 64, 112, 62, 114, 61, 116, 57, 120, 55, 124, 55 | |
DATA 125, 55, -1, -1 | |
DATA 117, 10, 121, 10, 120, 8, 116, 8, 114, 9, 112, 9, 114, 9, 116, 10, 117, 10, -1, -1 | |
REM Data for Scotland | |
DATA 45, 85, 49, 85, 47, 85, 46, 87, 48, 87, 50, 86, 48, 87, 46, 87, 48, 88, 50, 88, 44, 88, 43, 90, 45, 91, 47, 90, 49, 90, 47, 90 | |
DATA 45, 91, 47, 92, 45, 92, 45, 94, 47, 94, 49, 95, 51, 94, 55, 94, 51, 96, 53, 96, 53, 98, 59, 98, 57, 98, 55, 99, 57, 100, 57, 102 | |
DATA 59, 103, 61, 102, 63, 102, 62, 100, 66, 102, 68, 101, 66, 101, 70, 101, 72, 102, 84, 102, 86, 103, 88, 103, 88, 101, 87, 99, 85, 99, 81, 97 | |
DATA 79, 97, 75, 95, 73, 95, 73, 93, 71, 93, 69, 94, 71, 93, 77, 93, 75, 93, 73, 92, 71, 92, 69, 91, 67, 91, 73, 91, 71, 91, 70, 89 | |
DATA 68, 89, 70, 89, 72, 90, 76, 90, 78, 91, 80, 91, 82, 92, 84, 92, 86, 91, 106, 91, 108, 90, 108, 88, 106, 88, 104, 87, 101, 81, 99, 81 | |
DATA 97, 80, 96, 78, 94, 78, 92, 77, 88, 77, 86, 76, 84, 76, 88, 76, 90, 77, 92, 77, 91, 75, 95, 75, 93, 74, 89, 74, 87, 73, 85, 73 | |
DATA 83, 72, 77, 72, 83, 72, 85, 71, 89, 71, 91, 72, 95, 72, 97, 71, 101, 71, 103, 70, 103, 68, 101, 68, 99, 67, 101, 66, 91, 61, 89, 61 | |
DATA 85, 59, 79, 59, 77, 58, 73, 58, 71, 57, 69, 57, 67, 58, 65, 58, 64, 56, 62, 56, 58, 58, 54, 58, 55, 56, 51, 58, 51, 60, 53, 60 | |
DATA 54, 62, 56, 62, 57, 64, 61, 66, 57, 68, 57, 70, 59, 71, 61, 71, 59, 72, 57, 72, 58, 74, 60, 74, 58, 74, 56, 70, 54, 70, 53, 72 | |
DATA 51, 71, 49, 71, 50, 73, 52, 73, 56, 75, 54, 75, 48, 72, 48, 70, 50, 70, 48, 69, 47, 67, 45, 66, 46, 64, 42, 64, 42, 66, 43, 68 | |
DATA 47, 70, 45, 69, 44, 71, 46, 71, 44, 71, 46, 72, 44, 72, 46, 73, 46, 75, 48, 75, 46, 75, 50, 77, 54, 77, 50, 77, 48, 78, 52, 78 | |
DATA 50, 78, 51, 80, 55, 80, 53, 80, 54, 82, 52, 82, 54, 82, 46, 78, 42, 78, 40, 79, 42, 80, 46, 80, 36, 80, 38, 81, 42, 81, 44, 82 | |
DATA 42, 82, 43, 84, 45, 84, 45, 85, -1, -1 | |
REM Data for Wales | |
DATA 81, 41, 83, 40, 85, 40, 89, 38, 89, 36, 91, 36, 87, 36, 85, 35, 86, 33, 85, 31, 87, 31, 85, 30, 83, 30, 85, 29, 87, 29, 86, 27 | |
DATA 84, 27, 84, 25, 86, 24, 88, 24, 90, 23, 92, 23, 92, 21, 91, 19, 85, 19, 83, 18, 81, 18, 79, 17, 77, 18, 75, 18, 71, 20, 65, 20 | |
DATA 63, 19, 63, 21, 61, 21, 59, 22, 55, 22, 51, 20, 49, 20, 51, 21, 49, 22, 45, 22, 47, 22, 46, 24, 44, 23, 48, 25, 52, 25, 54, 26 | |
DATA 56, 26, 58, 27, 62, 27, 64, 28, 66, 28, 67, 30, 67, 34, 65, 35, 61, 35, 59, 34, 55, 34, 59, 36, 61, 36, 69, 40, 79, 40, 81, 41 | |
DATA 81, 41, -1, -1 | |
DATA 62, 42, 66, 40, 68, 40, 64, 38, 62, 38, 60, 39, 58, 39, 59, 41, 61, 41, 62, 42, -1, -1 | |
REM Flood fill points for England | |
DATA 2 | |
DATA 115, 33 | |
DATA 117, 9 | |
REM Flood fill points for Scotland | |
DATA 1 | |
DATA 70, 79 | |
REM Flood fill points for Wales | |
DATA 2 | |
DATA 76, 28 | |
DATA 63, 40 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Python program to generate the data for the BBC Micro map drawing | |
import fiona | |
import math | |
import os | |
from rdp import rdp | |
from polylabel import polylabel | |
geo_data = [] | |
# Download the Boundary-Line™ GeoPackage from Ordnance Survey at https://osdatahub.os.uk/downloads/open/BoundaryLine | |
with fiona.open('bdline_gb.gpkg', layer='country_region') as layer: | |
minx, miny, maxx, maxy = layer.bounds | |
width = maxx - minx | |
height = maxy - miny | |
aspect = width/height | |
xscale = 320 * aspect | |
sorted_layer = sorted(layer, key=lambda x: x.properties['Hectares'], reverse=True) # reverse sort by land area | |
total_pcount = 0 | |
for feature in sorted_layer[:3]: # biggest 3 areas will be the 3 countries of Great Britain | |
scaled_coords = [] | |
for polygon in feature.geometry['coordinates']: | |
ring = polygon[0] # first ring is exterior ring | |
polygon_coords = [] | |
oldx = -999 | |
oldy = -999 | |
first = True | |
for c in ring: | |
x, y = c | |
scaled_x = int(math.ceil((x - minx)*xscale/(maxx - minx))) | |
scaled_y = int(math.ceil((y - miny)*128/(maxy - miny))) | |
if first: | |
first_x = scaled_x | |
first_y = scaled_y | |
first = False | |
if abs(oldx-scaled_x)>1 or abs(oldy-scaled_y)>1: | |
polygon_coords.append([scaled_x, scaled_y]) | |
oldx = scaled_x | |
oldy = scaled_y | |
polygon_coords = rdp(polygon_coords) | |
if len(polygon_coords) > 1: | |
scaled_coords.extend(polygon_coords) | |
scaled_coords.append([first_x,first_y]) | |
scaled_coords.append([-1,-1]) | |
total_pcount = total_pcount + 1 | |
geo_data.append({ "name": feature.properties['Name'], "coordinates": scaled_coords }) | |
minx = 999 | |
miny = 999 | |
maxx = -999 | |
maxy = -999 | |
fill_block = "" | |
for g in geo_data: | |
line = "REM Data for " + g['name'] | |
print(line) | |
scaled_coords = g['coordinates'] | |
line = "DATA " | |
thislinecount = 0 | |
for c in scaled_coords: | |
x, y = c | |
if x == -1 or y == -1: | |
thislinecount = 15 | |
if thislinecount < 15: | |
line = line + str(x) + ", " + str(y) + ", " | |
thislinecount = thislinecount + 1 | |
else: | |
line = line + str(x) + ", " + str(y) | |
thislinecount = 0 | |
print(line) | |
line = "DATA " | |
if x > maxx: | |
maxx = x | |
if y > maxy: | |
maxy = y | |
if x < minx and x > -1: | |
minx = x | |
if y < miny and y > -1: | |
miny = y | |
if thislinecount > 0: | |
print(line) | |
line = "REM Flood fill points for " + g['name'] | |
fill_block = fill_block + line + os.linesep | |
polygon_coords = [] | |
pcount = 0 | |
fill_line = "" | |
first = True | |
for c in scaled_coords: | |
x, y = c | |
if x == -1 or y == -1: | |
fill_point = polylabel([polygon_coords]) | |
fill_x, fill_y = fill_point | |
if not first: | |
fill_line = fill_line + os.linesep | |
else: | |
first = False | |
fill_line = fill_line + "DATA " + str(math.ceil(fill_x)) + ", " + str(math.ceil(fill_y)) | |
polygon_coords = [] | |
pcount = pcount + 1 | |
else: | |
polygon_coords.append([x, y]) | |
line = "DATA " + str(pcount) + os.linesep | |
fill_block = fill_block + line + fill_line + os.linesep | |
print(fill_block) | |
print("Number of polygons: " + str(total_pcount)) | |
print("Bounds: " + str(minx) + ", " + str(miny) + " - " + str(maxx) + ", " + str(maxy)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Python program to draw a map of Great Britain | |
import fiona | |
import math | |
import os | |
from rdp import rdp | |
from polylabel import polylabel | |
from graphics import * # graphics.py | |
geo_data = [] | |
# Download the Boundary-Line™ GeoPackage from Ordnance Survey at https://osdatahub.os.uk/downloads/open/BoundaryLine | |
with fiona.open('bdline_gb.gpkg', layer='country_region') as layer: | |
minx, miny, maxx, maxy = layer.bounds | |
width = maxx - minx | |
height = maxy - miny | |
aspect = width/height | |
xscale = 320 * aspect | |
sorted_layer = sorted(layer, key=lambda x: x.properties['Hectares'], reverse=True) # reverse sort by land area | |
total_pcount = 0 | |
for feature in sorted_layer[:3]: # biggest 3 areas will be the 3 countries of Great Britain | |
scaled_coords = [] | |
for polygon in feature.geometry['coordinates']: | |
ring = polygon[0] # first ring is exterior ring | |
polygon_coords = [] | |
oldx = -999 | |
oldy = -999 | |
first = True | |
for c in ring: | |
x, y = c | |
scaled_x = int(math.ceil((x - minx)*xscale/(maxx - minx))) | |
scaled_y = int(math.ceil((y - miny)*128/(maxy - miny))) | |
if first: | |
first_x = scaled_x | |
first_y = scaled_y | |
first = False | |
if abs(oldx-scaled_x)>1 or abs(oldy-scaled_y)>1: | |
polygon_coords.append([scaled_x, scaled_y]) | |
oldx = scaled_x | |
oldy = scaled_y | |
polygon_coords = rdp(polygon_coords) | |
if len(polygon_coords) > 1: | |
scaled_coords.extend(polygon_coords) | |
scaled_coords.append([first_x,first_y]) | |
scaled_coords.append([-1,-1]) | |
total_pcount = total_pcount + 1 | |
geo_data.append({ "name": feature.properties['Name'], "coordinates": scaled_coords }) | |
win = GraphWin(title = "Map of Great Britain", width = 640, height = 512) | |
win.setCoords(0,0,639,511) | |
win.setBackground("black") | |
country_colours = ["red", "green", "yellow"] | |
for g in geo_data: | |
scaled_coords = g['coordinates'] | |
polygon_coords = [] | |
polygon_points = [] | |
this_colour = country_colours.pop(0) | |
first = True | |
for c in scaled_coords: | |
x, y = c | |
if x == -1 or y == -1: | |
aPolygon = Polygon(polygon_points) | |
aPolygon.setFill(this_colour) | |
aPolygon.setOutline("white") | |
aPolygon.setWidth(3) | |
aPolygon.draw(win) | |
if first: | |
label_coords = polylabel([polygon_coords]) | |
label_x, label_y = label_coords | |
if g['name'] == "England": | |
label_y = 48 | |
if g['name'] == "Scotland": | |
label_y = 492 | |
if g['name'] == "Wales": | |
label_x = label_x - 114 | |
label_point = Point(label_x, label_y) | |
label = Text(label_point, g['name']) | |
label.setFace("courier") | |
label.setStyle("bold") | |
label.setSize(18) | |
label.setTextColor("white") | |
label.draw(win) | |
first = False | |
polygon_coords = [] | |
polygon_points = [] | |
else: | |
polygon_points.append(Point((x*2)+115,(y*4)+50)) | |
polygon_coords.append([(x*2)+115,(y*4)+50]) | |
clickPoint = win.getMouse() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment