Compare commits

...

4 commits

6 changed files with 115 additions and 18 deletions

1
.gitignore vendored
View file

@ -7,5 +7,6 @@ layers/survey-markers/states.js
layers/tjx/data/chains.js layers/tjx/data/chains.js
layers/crop-history/data/counties.js layers/crop-history/data/counties.js
layers/mn-sales-tax/data/history.js layers/mn-sales-tax/data/history.js
layers/airports/data/types.js
.direnv .direnv
venv venv

52
layers/airports/get_data.py Executable file
View file

@ -0,0 +1,52 @@
#!/usr/bin/env python
import csv
import io
import json
import urllib.request
index_imports = []
resp = urllib.request.urlopen("https://davidmegginson.github.io/ourairports-data/airports.csv")
airports = list(csv.DictReader(io.TextIOWrapper(resp)))
types = set([a['type'] for a in airports])
for airport_type in types:
geojson = {
"type": "FeatureCollection",
"features": [],
}
for airport in airports:
if airport['type'] == airport_type:
f = {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [float(airport['longitude_deg']), float(airport['latitude_deg'])]
},
"properties": {
"ID": airport['ident'],
"Name": airport['name'],
"City": airport['municipality'],
"Country": airport['iso_country'],
"Region": airport['iso_region'],
"Elevation (ft)": airport['elevation_ft'],
}
}
if airport['wikipedia_link']:
f['properties']['Wikipedia'] = airport['wikipedia_link']
if airport['home_link']:
f['properties']['Website'] = airport['home_link']
geojson['features'].append(f)
with open(f'data/{airport_type}.geojson', 'w') as f:
f.write(json.dumps(geojson))
with open("data/types.js", 'w') as f:
for airport_type in types:
f.write(f"import {airport_type} from './{airport_type}.geojson?url';\n")
f.write('\nexport default {\n')
for airport_type in types:
f.write(f" {airport_type}: {airport_type},\n")
f.write("};\n")

40
layers/airports/index.js Normal file
View file

@ -0,0 +1,40 @@
import GeoJSON from 'ol/format/GeoJSON.js';
import VectorLayer from 'ol/layer/Vector.js';
import VectorSource from 'ol/source/Vector.js';
import types from './data/types.js';
import { Circle, Fill, Stroke, Style } from 'ol/style.js';
const layers = {
name: "Airports",
layers: [],
};
for (let [name, url] of Object.entries(types)) {
const layer = new VectorLayer({
source: new VectorSource({
url,
format: new GeoJSON,
}),
style: new Style({
image: new Circle({
radius: name == 'large_airport' ? 10 : name == "small_airport" ? 3 : 5,
fill: new Fill({
color: 'rgba(255,255,255,0.4)',
}),
stroke: new Stroke({
color: 'red',
width: name == 'large_airport' ? 4 : 2,
}),
}),
}),
});
layers.layers.push({
name,
layer,
});
}
export default layers;

View file

@ -5,24 +5,15 @@ import {Style} from 'ol/style.js';
import Icon from 'ol/style/Icon.js'; import Icon from 'ol/style/Icon.js';
import pinURL from '/layers/chandler/pin.svg?url'; // TODO: remove `?url`? import pinURL from '/layers/chandler/pin.svg?url'; // TODO: remove `?url`?
import { Feature } from 'ol'; import { Collection, Feature } from 'ol';
import { Point } from 'ol/geom'; import { Point } from 'ol/geom';
import { fromLonLat } from 'ol/proj'; import { fromLonLat } from 'ol/proj';
const res = await fetch("https://whereis.chandlerswift.com/api/0/last"); let features = new Collection();
const locs = await res.json();
const loc = locs[0];
let feature = new Feature({
geometry: new Point(fromLonLat([loc.lon, loc.lat])),
...loc
});
const vectorLayer = new VectorLayer({ const vectorLayer = new VectorLayer({
source: new VectorSource({ source: new VectorSource({
features: [ features,
feature,
]
}), }),
style: new Style({ style: new Style({
image: new Icon({ image: new Icon({
@ -32,12 +23,23 @@ const vectorLayer = new VectorLayer({
}), }),
}); });
setInterval(async function(){ async function refresh(){
const res = await fetch("https://whereis.chandlerswift.com/api/0/last"); const res = await fetch("https://whereis.chandlerswift.com/api/0/last");
const locs = await res.json(); const locs = await res.json();
const loc = locs[0]; const loc = locs[0];
feature.setProperties(loc); // TODO: this won't remove a property if it was in a previous response but not this one // TODO: I could probably just `features[0] = …` but I'm not sure if that causes problems with re-rendering features
feature.getGeometry().setCoordinates(fromLonLat([loc.lon, loc.lat])); if (features.getLength() == 0) {
}, 10 * 1000); features.push(new Feature({
geometry: new Point(fromLonLat([loc.lon, loc.lat])),
...loc
}));
} else {
features.item(0).setProperties(loc); // TODO: this won't remove a property if it was in a previous response but not this one
features.item(0).getGeometry().setCoordinates(fromLonLat([loc.lon, loc.lat]));
}
}
refresh();
setInterval(refresh, 10 * 1000);
export default vectorLayer; export default vectorLayer;

View file

@ -26,6 +26,7 @@ import upsServiceAreas from './ups/index.js';
import fccTowersLayer from './fcc/towers/layer.js'; import fccTowersLayer from './fcc/towers/layer.js';
import mnSalesTaxLayers from './mn-sales-tax/index.js'; import mnSalesTaxLayers from './mn-sales-tax/index.js';
import versatilesLayers from './versatiles.js'; import versatilesLayers from './versatiles.js';
import airports from './airports/index.js';
const layerCategories = [ const layerCategories = [
{ // Base maps { // Base maps
@ -118,6 +119,7 @@ const layerCategories = [
tjx, tjx,
cropHistory, cropHistory,
mnSalesTaxLayers, mnSalesTaxLayers,
airports,
]; ];
export default layerCategories; export default layerCategories;

View file

@ -43,7 +43,7 @@ const visitedStatesLists = {
'SD', 'SD',
'TN', 'TN',
'TX', 'TX',
// 'UT', 'UT',
'VA', 'VA',
'VT', 'VT',
'WA', 'WA',
@ -95,7 +95,7 @@ const visitedStatesLists = {
'SD', 'SD',
'TN', 'TN',
'TX', 'TX',
// 'UT', 'UT',
'VA', 'VA',
// 'VT', // 'VT',
'WA', 'WA',