1package arcgismap23import (4 "strconv"5 "strings"6)78// The national enrichment. A state GIS viewer is usually a branded window9// onto federal datasets -- Colorado's water viewer credits the USGS10// Watershed Boundary Dataset and National Hydrography Dataset by name -- so11// the generic move is to ask the federal services directly, by any city's12// own bounding box, and every curated city gains the same layers without a13// line of per-city curation.14//15// Both services are plain ArcGIS MapServer query endpoints on16// hydro.nationalmap.gov. Field spellings differ per layer -- the WBD layers17// speak lowercase, the NHD waterbody layer uppercase -- and were verified18// against the live services, the same discipline every city table keeps.1920const (21 wbdServer = "https://hydro.nationalmap.gov/arcgis/rest/services/wbd/MapServer"22 nhdServer = "https://hydro.nationalmap.gov/arcgis/rest/services/nhd/MapServer"2324 // SlugSubwatersheds names the captured dataset the membership join25 // reads, so the join and the table cannot drift apart on a spelling.26 SlugSubwatersheds = "subwatersheds"27)2829// National is the enrichment every curated city receives: the watersheds30// its ground drains through, in two grains of the USGS hydrologic unit31// hierarchy, and the named streams and waterbodies that do the draining.32// A padded city window intersects a handful of hydrologic units and tens33// of named streams -- national extent, city-sized answers. Every national34// layer labels quiet: the hydrology is the city's context, not its35// headline, and a map flooded with creek names is a map about the wrong36// thing.37var National = []Dataset{38 {39 Slug: "watersheds", Title: "Watersheds",40 Server: wbdServer, Layer: 5,41 Geometry: "polygon",42 Keep: []string{"objectid", "huc10", "name"},43 IDOf: hucID("huc10"),44 ZoneOf: hucZone("huc10", "Watershed"),45 Label: "quiet",46 },47 {48 Slug: SlugSubwatersheds, Title: "Subwatersheds",49 Server: wbdServer, Layer: 6,50 Geometry: "polygon",51 Keep: []string{"objectid", "huc12", "name"},52 IDOf: hucID("huc12"),53 ZoneOf: hucZone("huc12", "Subwatershed"),54 Label: "quiet",55 },56 {57 Slug: "streams", Title: "Streams",58 Server: nhdServer, Layer: 6,59 Geometry: "line",60 Keep: []string{"OBJECTID", "gnis_name"},61 // Named flowlines only: the layer also carries every unnamed ditch62 // and culvert, which is noise to a reader and no loss to the map.63 Where: "gnis_name IS NOT NULL",64 ZoneOf: func(f Fields) ZoneKey {65 name := strings.TrimSpace(f["gnis_name"])66 if name == "" {67 return ZoneKey{}68 }69 return ZoneKey{Key: slugify(name), Title: name, Subtitle: "Stream"}70 },71 StrokeWidth: 10,72 Label: "quiet",73 Role: "water",74 },75 {76 Slug: "waterbodies", Title: "Waterbodies",77 Server: nhdServer, Layer: 12,78 Geometry: "polygon",79 Keep: []string{"OBJECTID", "GNIS_NAME"},80 // Every pond draws into the basemap; only the named ones earn a81 // zone anyone could search for.82 ZoneOf: func(f Fields) ZoneKey {83 name := strings.TrimSpace(f["GNIS_NAME"])84 if name == "" {85 return ZoneKey{}86 }87 return ZoneKey{Key: slugify(name), Title: name, Subtitle: "Waterbody"}88 },89 Label: "quiet",90 Role: "water",91 },92}9394// hucID reads the hydrologic unit code as the feature's identity: the code95// is nationally unique and survives upstream refreshes, where the layer's96// object ids are load artifacts that churn. A leading zero -- regions one97// through nine -- drops in the number without costing uniqueness.98func hucID(field string) func(Fields) (int64, bool) {99 return func(f Fields) (int64, bool) {100 code, err := strconv.ParseInt(f[field], 10, 64)101 return code, err == nil && code > 0102 }103}104105// hucZone folds a WBD layer into one zone per hydrologic unit, titled by106// the unit's own name with the code kept legible beside the grain.107func hucZone(field, grain string) func(Fields) ZoneKey {108 return func(f Fields) ZoneKey {109 code, name := strings.TrimSpace(f[field]), strings.TrimSpace(f["name"])110 if code == "" || name == "" {111 return ZoneKey{}112 }113 return ZoneKey{Key: code, Title: name, Subtitle: grain + " ยท HUC " + code}114 }115}