Initial commit

This commit is contained in:
Chandler Swift 2024-11-26 20:41:37 -06:00
commit 73ea6a9413
Signed by: chandlerswift
GPG key ID: A851D929D52FB93F
26 changed files with 58556 additions and 0 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
use nix;

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
data/plats.geojson

2
Makefile Normal file
View file

@ -0,0 +1,2 @@
plats.json: scripts/get_plats.py
./scripts/get_plats.py data/plats.geojson

304
data/data.json Normal file
View file

@ -0,0 +1,304 @@
{
"stands": [
{
"name": "Fridge",
"image": "fridge.jpg",
"type": "barrel",
"view": [
"fridge1.jpg",
"fridge2.jpg",
"fridge3.jpg"
],
"location": [
47.49304852,
-93.39113721000001
],
"attributes": {
"Year Established": "2010",
"Description": "Formerly \"Alan's Barrel\" (located where Alan's castle is now). Originally built (probably 1970s or 1980s) by some combination of Alan, Vernon, and Irving from old windmills. Moved to the driveway in 2010 when Alan's castle was built. Shortly thereafter, the southeast leg was hit with the brushmower, rendering it unusable, and replaced with a refrigerator. The large hole in the barrel was the result of an accidental discharge of Alan's .44 Magnum pistol."
}
},
{
"name": "Tupperware",
"image": "tupperware.jpg",
"type": "castle",
"view": [
"tupperware1.jpg",
"tupperware2.jpg",
"tupperware3.jpg"
],
"location": [
47.49564466,
-93.39410528
],
"attributes": {
"Year Established": "2017",
"Description": "Stand and platform purchased new at a steep discount from RMI in Little Falls (https://rotomoldinginc.com/). Dave and Celine installed and assembled in a separate late-September trip. This stand replaced a post stand that had stood in this location for several years; \"For a few years, every single time I went out there, I saw a deer!\" \u2014Dave Swift. The shooting lane to the north of the stand was naturally free of trees, which made construction of a new shooting lane very straightforward. This location was especially desirable because it was our only stand placed in the NW 40."
}
},
{
"name": "Castle",
"image": "castle.jpg",
"type": "castle",
"view": [
"castle1.jpg",
"castle2.jpg",
"castle3.jpg",
"castle4.jpg"
],
"location": [
47.49585212,
-93.39130727000001
],
"attributes": {
"Year Established": "Late 70s/early 80s",
"Description": "This stand was built and originally occupied largely by Irving, and was the first enclosed stand on the property. The stand was assessed as healthy in September 2006, and was discovered on the ground that November. A new castle was built on the original base in 2007. The original wooden base was replaced with a metal base of Tim's design in 2023."
}
},
{
"name": "Ladder",
"image": "ladder.jpg",
"type": "tree",
"view": [
"ladder1.jpg",
"ladder2.jpg",
"ladder3.jpg"
],
"attributes": {
"Year Established": "\"Predates me, I think\" —Dave",
"Description": ""
},
"location": [
47.49670328333334,
-93.38847981333333
]
},
{
"name": "Alan's",
"image": "alans.jpg",
"type": "castle",
"view": [
"alans1.jpg",
"alans2.jpg",
"alans3.jpg"
],
"attributes": {
"Year Established": "1970s (TODO)",
"Description": "Half-wall platform in 2010; enclosed stands built 2012 Zack Larson"
},
"location": [
47.49460865,
-93.39097404
]
},
{
"name": "East Barrel",
"image": "eastbarrel.jpg",
"type": "barrel",
"view": [
"eastbarrel1.jpg",
"eastbarrel2.jpg",
"eastbarrel3.jpg",
"eastbarrel4.jpg"
],
"attributes": {
"Year Established": "",
"Description": "70s or 80s, repurposed windmill stand?"
},
"location": [
47.49519986,
-93.387005555
]
},
{
"name": "Iron Castle",
"image": "ironcastle.jpg",
"type": "castle",
"view": [
"ironcastle1.jpg",
"ironcastle2.jpg"
],
"attributes": {
"Year Established": "1990s?",
"Description": "Also \"Iron tree\". Lawrence Deer Club's second castle, after The Castle. A successor to the Mile-high stand, purchased from Fleet Farm for $400. Installed further west than the original stand to stay on our property. Camo paint job by Paul Adams."
},
"location": [
47.494131005,
-93.38646539500002
]
},
{
"name": "Mile-high stand (TODO: rename)",
"image": "irontree.jpg",
"type": "tree",
"view": [
"irontree1.jpg",
"irontree2.jpg"
],
"attributes": {
"Year Established": "",
"Description": "Occasionally also \"Iron tree\" (as opposed to \"Iron Castle\"). Current location is maybe 8 feet lower than historic height. Likely the location for Scott's famous thirteen-shot kill. Almost always Richard's hunting spot of choice. As he aged (perhaps around when he turned 70 years old in 1994), an easier-to-climb stand was needed, so the Iron Castle was installed as a successor. TODO: whose stand is this? Dad thinks maybe Kim?"
},
"location": [
47.49430932,
-93.38599909000001
]
},
{
"name": "Three-Legged Barrel",
"image": "threeleggedbarrel.jpg",
"type": "barrel",
"view": [
"threeleggedbarrel1.jpg",
"threeleggedbarrel2.jpg",
"threeleggedbarrel3.jpg"
],
"stories": [
"Dave: That stand has never been particularly productive. I only ever saw one deer out of that stand -- a decent buck. The deer was to the east, so I needed to take a left-handed shot…and the rifle went \"click\" because I hadn't fully closed the breech. The deer ran off. A few moments later, a shot from the north: Paul Adams had gotten the deer."
],
"attributes": {
"Year Established": "",
"Description": "70s or 80s, not windmill parts. Maybe built by Alan? Originally not well-liked because of instability. 2023 barrel replaced and ladder flipped upside down/steps on barrel for easier climbing."
},
"location": [
47.49214061,
-93.38710683000001
]
},
{
"name": "Hummock",
"image": "hummock.jpg",
"type": "tree",
"active": false,
"view": [
"hummock1.jpg",
"hummock2.jpg"
],
"attributes": {
"Year Established": "",
"Description": "\"Prolific\" --Dave -- a good view of a lake to the south, and a bog to the east. "
},
"location": [
47.49135555555556,
-93.38455972222224
]
},
{
"name": "Sofa",
"image": "sofa.jpg",
"type": "tree",
"view": [
"sofa1.jpg",
"sofa2.jpg",
"sofa3.jpg",
"sofa4.jpg"
],
"attributes": {
"Year Established": "1990ish, shortly before Dave's first year",
"Description": "Alternately \"couch\" or \"davenport\". Shooting lanes went in either 2005 or 2006 (per Google Earth historic imagery), shortly after JBS' predecessors logged the area. Major rebuild in 2023, after half of tree above fork fell over. New ladder made out of square steel tubing from GSL batting cage, installed in 2020."
},
"location": [
47.49022563,
-93.38653060000001
]
},
{
"name": "Ridge",
"image": "ridge.jpg",
"type": "tree",
"view": [
"ridge1.jpg",
"ridge2.jpg"
],
"attributes": {
"Year Established": "TODO",
"Description": "John Graupmann's metal two-person stand. Installed 2015-2017 (before 2018 logging completed). Path rerouted after logging."
},
"location": [
47.48936904,
-93.38791247
]
},
{
"name": "Point",
"image": "point.jpg",
"type": "castle",
"view": [
"point1.jpg",
"point2.jpg",
"point3.jpg"
],
"attributes": {
"Year Established": "2008",
"Description": "Originally \"South Castle\". Post stand in 2008, half-wall stand in 2009, castle in 2012. Many deer were seen from the post, so decided to put up a permanent stand. The first morning of half-wall stand, 8 deer seen before 8:30 (including 8pt buck). Next day, another buck 7:30am. New ladder (with Sofa) 2020(?)"
},
"location": [
47.48888177333333,
-93.38977630333333
]
}
],
"fruit-trees_comment": "Dave attempted planting two fruit trees 2008 between Alan's stand and castle. Neither made it a year.",
"fruit-trees": [
{
"type": "Honeycrisp",
"location": [],
"attributes": {
"Year Planted": 2019,
"_TODO": "#TODO",
"Description": ""
}
},
{
"type": "Honeycrisp",
"location": [],
"attributes": {
"Year Planted": 2019,
"_TODO": "#TODO",
"Description": ""
}
},
{
"type": "Honeycrisp",
"location": [],
"attributes": {
"Year Planted": 2019,
"_TODO": "#TODO",
"Description": ""
}
},
{
"type": "Honeycrisp",
"location": [],
"attributes": {
"Year Planted": 2019,
"_TODO": "#TODO",
"Description": ""
}
}
],
"buildings": [
"shack built around 1980, put up over a weekend. Old one pushed over and burned. New cabin was reshingled once, floors rebuilt in 2006, moved to new foundation in 2019, eaves 2020, steel siding, new windows, and porch 2021-2022, steel roof added 2024 for $16500.",
"outhouse built by Irving pre-1992 (when Dad started coming up; relatively new then), replaced older outhouse, which was 6 ft further north",
""
],
"deer": [
"TODO",
{
"date": "2023-11-11 17:00:00",
"hunter": "Chris Lemke",
"animal": "9pt buck",
"stand": "Sofa",
"notes": "Tracked after dark during a snowstorm",
"_photo": null
},
{
"date": "2023-11-11 17:00:00",
"hunter": "Chris Lemke",
"animal": "9pt buck",
"stand": "Sofa",
"notes": "Tracked after dark during a snowstorm",
"_photo": null
}
]
}

8
data/track.geojson Normal file

File diff suppressed because one or more lines are too long

24
index.html Normal file
View file

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lawrence Deer Club</title>
<style>
body * {
text-align: center;
}
#links a {
padding: 2em;
}
</style>
</head>
<body>
<p id="welcome">welcome to the</p>
<h1>Lawrence Deer Club</h1>
<div id="links">
<a href="/map.html">map</a>
<a href="/trailcams">trail cams</a>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
leaflet/images/layers.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

14419
leaflet/leaflet-src.esm.js Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

14512
leaflet/leaflet-src.js Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

661
leaflet/leaflet.css Normal file
View file

@ -0,0 +1,661 @@
/* required styles */
.leaflet-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-container,
.leaflet-pane > svg,
.leaflet-pane > canvas,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
position: absolute;
left: 0;
top: 0;
}
.leaflet-container {
overflow: hidden;
}
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
-webkit-user-drag: none;
}
/* Prevents IE11 from highlighting tiles in blue */
.leaflet-tile::selection {
background: transparent;
}
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
.leaflet-safari .leaflet-tile {
image-rendering: -webkit-optimize-contrast;
}
/* hack that prevents hw layers "stretching" when loading new tiles */
.leaflet-safari .leaflet-tile-container {
width: 1600px;
height: 1600px;
-webkit-transform-origin: 0 0;
}
.leaflet-marker-icon,
.leaflet-marker-shadow {
display: block;
}
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container .leaflet-overlay-pane svg {
max-width: none !important;
max-height: none !important;
}
.leaflet-container .leaflet-marker-pane img,
.leaflet-container .leaflet-shadow-pane img,
.leaflet-container .leaflet-tile-pane img,
.leaflet-container img.leaflet-image-layer,
.leaflet-container .leaflet-tile {
max-width: none !important;
max-height: none !important;
width: auto;
padding: 0;
}
.leaflet-container img.leaflet-tile {
/* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */
mix-blend-mode: plus-lighter;
}
.leaflet-container.leaflet-touch-zoom {
-ms-touch-action: pan-x pan-y;
touch-action: pan-x pan-y;
}
.leaflet-container.leaflet-touch-drag {
-ms-touch-action: pinch-zoom;
/* Fallback for FF which doesn't support pinch-zoom */
touch-action: none;
touch-action: pinch-zoom;
}
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
-ms-touch-action: none;
touch-action: none;
}
.leaflet-container {
-webkit-tap-highlight-color: transparent;
}
.leaflet-container a {
-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
}
.leaflet-tile {
filter: inherit;
visibility: hidden;
}
.leaflet-tile-loaded {
visibility: inherit;
}
.leaflet-zoom-box {
width: 0;
height: 0;
-moz-box-sizing: border-box;
box-sizing: border-box;
z-index: 800;
}
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
.leaflet-overlay-pane svg {
-moz-user-select: none;
}
.leaflet-pane { z-index: 400; }
.leaflet-tile-pane { z-index: 200; }
.leaflet-overlay-pane { z-index: 400; }
.leaflet-shadow-pane { z-index: 500; }
.leaflet-marker-pane { z-index: 600; }
.leaflet-tooltip-pane { z-index: 650; }
.leaflet-popup-pane { z-index: 700; }
.leaflet-map-pane canvas { z-index: 100; }
.leaflet-map-pane svg { z-index: 200; }
.leaflet-vml-shape {
width: 1px;
height: 1px;
}
.lvml {
behavior: url(#default#VML);
display: inline-block;
position: absolute;
}
/* control positioning */
.leaflet-control {
position: relative;
z-index: 800;
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
.leaflet-top,
.leaflet-bottom {
position: absolute;
z-index: 1000;
pointer-events: none;
}
.leaflet-top {
top: 0;
}
.leaflet-right {
right: 0;
}
.leaflet-bottom {
bottom: 0;
}
.leaflet-left {
left: 0;
}
.leaflet-control {
float: left;
clear: both;
}
.leaflet-right .leaflet-control {
float: right;
}
.leaflet-top .leaflet-control {
margin-top: 10px;
}
.leaflet-bottom .leaflet-control {
margin-bottom: 10px;
}
.leaflet-left .leaflet-control {
margin-left: 10px;
}
.leaflet-right .leaflet-control {
margin-right: 10px;
}
/* zoom and fade animations */
.leaflet-fade-anim .leaflet-popup {
opacity: 0;
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
opacity: 1;
}
.leaflet-zoom-animated {
-webkit-transform-origin: 0 0;
-ms-transform-origin: 0 0;
transform-origin: 0 0;
}
svg.leaflet-zoom-animated {
will-change: transform;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
}
.leaflet-zoom-anim .leaflet-tile,
.leaflet-pan-anim .leaflet-tile {
-webkit-transition: none;
-moz-transition: none;
transition: none;
}
.leaflet-zoom-anim .leaflet-zoom-hide {
visibility: hidden;
}
/* cursors */
.leaflet-interactive {
cursor: pointer;
}
.leaflet-grab {
cursor: -webkit-grab;
cursor: -moz-grab;
cursor: grab;
}
.leaflet-crosshair,
.leaflet-crosshair .leaflet-interactive {
cursor: crosshair;
}
.leaflet-popup-pane,
.leaflet-control {
cursor: auto;
}
.leaflet-dragging .leaflet-grab,
.leaflet-dragging .leaflet-grab .leaflet-interactive,
.leaflet-dragging .leaflet-marker-draggable {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
cursor: grabbing;
}
/* marker & overlays interactivity */
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-image-layer,
.leaflet-pane > svg path,
.leaflet-tile-container {
pointer-events: none;
}
.leaflet-marker-icon.leaflet-interactive,
.leaflet-image-layer.leaflet-interactive,
.leaflet-pane > svg path.leaflet-interactive,
svg.leaflet-image-layer.leaflet-interactive path {
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
/* visual tweaks */
.leaflet-container {
background: #ddd;
outline-offset: 1px;
}
.leaflet-container a {
color: #0078A8;
}
.leaflet-zoom-box {
border: 2px dotted #38f;
background: rgba(255,255,255,0.5);
}
/* general typography */
.leaflet-container {
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
font-size: 12px;
font-size: 0.75rem;
line-height: 1.5;
}
/* general toolbar styles */
.leaflet-bar {
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
border-radius: 4px;
}
.leaflet-bar a {
background-color: #fff;
border-bottom: 1px solid #ccc;
width: 26px;
height: 26px;
line-height: 26px;
display: block;
text-align: center;
text-decoration: none;
color: black;
}
.leaflet-bar a,
.leaflet-control-layers-toggle {
background-position: 50% 50%;
background-repeat: no-repeat;
display: block;
}
.leaflet-bar a:hover,
.leaflet-bar a:focus {
background-color: #f4f4f4;
}
.leaflet-bar a:first-child {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.leaflet-bar a:last-child {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom: none;
}
.leaflet-bar a.leaflet-disabled {
cursor: default;
background-color: #f4f4f4;
color: #bbb;
}
.leaflet-touch .leaflet-bar a {
width: 30px;
height: 30px;
line-height: 30px;
}
.leaflet-touch .leaflet-bar a:first-child {
border-top-left-radius: 2px;
border-top-right-radius: 2px;
}
.leaflet-touch .leaflet-bar a:last-child {
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
}
/* zoom control */
.leaflet-control-zoom-in,
.leaflet-control-zoom-out {
font: bold 18px 'Lucida Console', Monaco, monospace;
text-indent: 1px;
}
.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
font-size: 22px;
}
/* layers control */
.leaflet-control-layers {
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
background: #fff;
border-radius: 5px;
}
.leaflet-control-layers-toggle {
background-image: url(images/layers.png);
width: 36px;
height: 36px;
}
.leaflet-retina .leaflet-control-layers-toggle {
background-image: url(images/layers-2x.png);
background-size: 26px 26px;
}
.leaflet-touch .leaflet-control-layers-toggle {
width: 44px;
height: 44px;
}
.leaflet-control-layers .leaflet-control-layers-list,
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
display: none;
}
.leaflet-control-layers-expanded .leaflet-control-layers-list {
display: block;
position: relative;
}
.leaflet-control-layers-expanded {
padding: 6px 10px 6px 6px;
color: #333;
background: #fff;
}
.leaflet-control-layers-scrollbar {
overflow-y: scroll;
overflow-x: hidden;
padding-right: 5px;
}
.leaflet-control-layers-selector {
margin-top: 2px;
position: relative;
top: 1px;
}
.leaflet-control-layers label {
display: block;
font-size: 13px;
font-size: 1.08333em;
}
.leaflet-control-layers-separator {
height: 0;
border-top: 1px solid #ddd;
margin: 5px -10px 5px -6px;
}
/* Default icon URLs */
.leaflet-default-icon-path { /* used only in path-guessing heuristic, see L.Icon.Default */
background-image: url(images/marker-icon.png);
}
/* attribution and scale controls */
.leaflet-container .leaflet-control-attribution {
background: #fff;
background: rgba(255, 255, 255, 0.8);
margin: 0;
}
.leaflet-control-attribution,
.leaflet-control-scale-line {
padding: 0 5px;
color: #333;
line-height: 1.4;
}
.leaflet-control-attribution a {
text-decoration: none;
}
.leaflet-control-attribution a:hover,
.leaflet-control-attribution a:focus {
text-decoration: underline;
}
.leaflet-attribution-flag {
display: inline !important;
vertical-align: baseline !important;
width: 1em;
height: 0.6669em;
}
.leaflet-left .leaflet-control-scale {
margin-left: 5px;
}
.leaflet-bottom .leaflet-control-scale {
margin-bottom: 5px;
}
.leaflet-control-scale-line {
border: 2px solid #777;
border-top: none;
line-height: 1.1;
padding: 2px 5px 1px;
white-space: nowrap;
-moz-box-sizing: border-box;
box-sizing: border-box;
background: rgba(255, 255, 255, 0.8);
text-shadow: 1px 1px #fff;
}
.leaflet-control-scale-line:not(:first-child) {
border-top: 2px solid #777;
border-bottom: none;
margin-top: -2px;
}
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
border-bottom: 2px solid #777;
}
.leaflet-touch .leaflet-control-attribution,
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
box-shadow: none;
}
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
border: 2px solid rgba(0,0,0,0.2);
background-clip: padding-box;
}
/* popup */
.leaflet-popup {
position: absolute;
text-align: center;
margin-bottom: 20px;
}
.leaflet-popup-content-wrapper {
padding: 1px;
text-align: left;
border-radius: 12px;
}
.leaflet-popup-content {
margin: 13px 24px 13px 20px;
line-height: 1.3;
font-size: 13px;
font-size: 1.08333em;
min-height: 1px;
}
.leaflet-popup-content p {
margin: 17px 0;
margin: 1.3em 0;
}
.leaflet-popup-tip-container {
width: 40px;
height: 20px;
position: absolute;
left: 50%;
margin-top: -1px;
margin-left: -20px;
overflow: hidden;
pointer-events: none;
}
.leaflet-popup-tip {
width: 17px;
height: 17px;
padding: 1px;
margin: -10px auto 0;
pointer-events: auto;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
background: white;
color: #333;
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
}
.leaflet-container a.leaflet-popup-close-button {
position: absolute;
top: 0;
right: 0;
border: none;
text-align: center;
width: 24px;
height: 24px;
font: 16px/24px Tahoma, Verdana, sans-serif;
color: #757575;
text-decoration: none;
background: transparent;
}
.leaflet-container a.leaflet-popup-close-button:hover,
.leaflet-container a.leaflet-popup-close-button:focus {
color: #585858;
}
.leaflet-popup-scrolled {
overflow: auto;
}
.leaflet-oldie .leaflet-popup-content-wrapper {
-ms-zoom: 1;
}
.leaflet-oldie .leaflet-popup-tip {
width: 24px;
margin: 0 auto;
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
}
.leaflet-oldie .leaflet-control-zoom,
.leaflet-oldie .leaflet-control-layers,
.leaflet-oldie .leaflet-popup-content-wrapper,
.leaflet-oldie .leaflet-popup-tip {
border: 1px solid #999;
}
/* div icon */
.leaflet-div-icon {
background: #fff;
border: 1px solid #666;
}
/* Tooltip */
/* Base styles for the element that has a tooltip */
.leaflet-tooltip {
position: absolute;
padding: 6px;
background-color: #fff;
border: 1px solid #fff;
border-radius: 3px;
color: #222;
white-space: nowrap;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
pointer-events: none;
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}
.leaflet-tooltip.leaflet-interactive {
cursor: pointer;
pointer-events: auto;
}
.leaflet-tooltip-top:before,
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
position: absolute;
pointer-events: none;
border: 6px solid transparent;
background: transparent;
content: "";
}
/* Directions */
.leaflet-tooltip-bottom {
margin-top: 6px;
}
.leaflet-tooltip-top {
margin-top: -6px;
}
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-top:before {
left: 50%;
margin-left: -6px;
}
.leaflet-tooltip-top:before {
bottom: 0;
margin-bottom: -12px;
border-top-color: #fff;
}
.leaflet-tooltip-bottom:before {
top: 0;
margin-top: -12px;
margin-left: -6px;
border-bottom-color: #fff;
}
.leaflet-tooltip-left {
margin-left: -6px;
}
.leaflet-tooltip-right {
margin-left: 6px;
}
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
top: 50%;
margin-top: -6px;
}
.leaflet-tooltip-left:before {
right: 0;
margin-right: -12px;
border-left-color: #fff;
}
.leaflet-tooltip-right:before {
left: 0;
margin-left: -12px;
border-right-color: #fff;
}
/* Printing */
@media print {
/* Prevent printers from removing background-images of controls. */
.leaflet-control {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
}

6
leaflet/leaflet.js Normal file

File diff suppressed because one or more lines are too long

1
leaflet/leaflet.js.map Normal file

File diff suppressed because one or more lines are too long

82
map.html Normal file
View file

@ -0,0 +1,82 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lawrence Deer Club Maps</title>
<link rel="stylesheet" href="/leaflet/leaflet.css" />
<script src="/leaflet/leaflet.js"></script>
<style>
html, body {
margin: 0;
padding: 0;
}
#map {
height: 100vh;
width: 100vw;
}
div.popup dt {
font-weight: bold;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
(async function() {
const map = L.map('map').setView([94.505, -0.09], 13);
// L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
// maxZoom: 19,
// attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
// }).addTo(map);
// Make these requests in parallel
const track_req_promise = fetch('data/track.geojson');
const plats_req_promise = fetch('data/plats.geojson');
const data_req_promise = fetch('data/data.json');
const track_req = await track_req_promise;
const plats_req = await plats_req_promise;
const data_req = await data_req_promise;
const track = await track_req.json();
const plats = await plats_req.json();
const data = await data_req.json();
L.geoJSON(track, {
}).bindPopup(function (layer) {
return layer.feature.properties.description;
}).addTo(map);
L.geoJSON(plats, {
}).bindPopup(function (layer) {
return layer.feature.properties.TAO_NAME;
}).addTo(map);
for (let stand of data.stands) {
if (stand.location) {
const marker = L.marker(stand.location).addTo(map);
const popupContentWrapper = document.createElement('div');
popupContentWrapper.classList.add('popup');
let attributesString = '<dl>';
for (let [attribute, value] of Object.entries(stand.attributes)) {
attributesString += `<dt>${attribute}</dt><dd>${value}</dd>`;
}
attributesString += '</dl>';
popupContentWrapper.innerHTML = `
<h2>${stand.name}</h2>
<img style="width: min(80vw, 300px);" src="images/${stand.image}">
${attributesString}
`;
marker.bindPopup(popupContentWrapper);
}
}
map.fitBounds([
[47.4865,-93.4068],
[47.4992,-93.3746],
]);
})();
</script>
</body>
</html>

3985
resources/deercamp-op9.gpx Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

10158
resources/deercamp-op9b.gpx Normal file

File diff suppressed because it is too large Load diff

4150
resources/deercamp.gpx Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,31 @@
#!/usr/bin/env nix-shell
#!nix-shell --quiet -p nix-eval-jobs -p nix -p python3 -p python3Packages.pillow -i python
import json
import os
from PIL import Image
from PIL.ExifTags import TAGS
# https://stackoverflow.com/a/78462781
GPSINFO_TAG = next(
tag for tag, name in TAGS.items() if name == "GPSInfo"
)
def decimal_coords(coords, ref):
decimal_degrees = float(coords[0]) + float(coords[1]) / 60 + float(coords[2]) / 3600
if ref == "S" or ref =='W' :
decimal_degrees = -1 * decimal_degrees
return decimal_degrees
with open('data/data.json') as f:
data = json.loads(f.read())
for i, stand in enumerate(data['stands']):
lats = []
lons = []
for view_image in stand['view']:
im = Image.open(os.path.join('images', view_image))
gpsinfo = im.getexif().get_ifd(GPSINFO_TAG)
lats.append(decimal_coords(gpsinfo[2], gpsinfo[1]))
lons.append(decimal_coords(gpsinfo[4], gpsinfo[3]))
data['stands'][i]['location'] = [sum(lats)/len(lats), sum(lons)/len(lons)] # TODO: round
print(json.dumps(data, indent=4))

40
scripts/get_plats.py Executable file
View file

@ -0,0 +1,40 @@
#!/usr/bin/env nix-shell
#!nix-shell --quiet -p python3 -p python3Packages.requests -i python
import json
import sys
import requests
if len(sys.argv) != 2:
raise "Wrong number of args. Use: `get_plats.py out_file.json`"
URL = "https://maps-test.co.itasca.mn.us/ArcGIS/rest/services/WAB_Maps/PublicOperationLayers/MapServer/30/query"
params={
"f": "geojson",
"returnGeometry": "true",
"spatialRel": "esriSpatialRelIntersects",
# {"xmin":-10397214.368951382,"ymin":6023763.834217183,"xmax":-10397185.705065776,"ymax":6023792.498102792,"spatialReference":{"wkid":102100}}
# {"xmin":-10395523.199700572,"ymin":6021824.244624444,"xmax":-10395465.871929357,"ymax":6021881.572395659,"spatialReference":{"wkid":102100}}
"geometry": json.dumps({
# "xmin": -10397313.413735004,
# "ymin": 6024888.239059315,
# "xmax": -10395148.64317237,
# "ymax": 6021777.960551391,
"xmin": -10397214.368951382,
"xmax": -10395465.871929357,
"ymin": 6021824.244624444,
"ymax": 6023792.498102792,
"spatialReference": {
"wkid": '102100'
},
}),
"geometryType": "esriGeometryEnvelope",
"inSR": "102100",
"outFields": "TAO_NAME",
"outSR": "EPSG:4326"
}
with open(sys.argv[1], 'w') as f:
f.write(requests.get(URL, params=params).text)

11
shell.nix Normal file
View file

@ -0,0 +1,11 @@
let
# nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/tarball/nixos-24.05";
pkgs = import <nixpkgs> { config = {}; overlays = []; };
in
pkgs.mkShell {
buildInputs = with pkgs; [
gnumake
gdal
];
}