# History map geography: U.S. counties and southern Canada

`public/data/mls-counties.json` is shared by the MLS and USL history tools and generated by `node scripts/build-mls-counties.mjs`. The build downloads version-pinned U.S. geography and build libraries, validates their SHA-256 digests, and runs the libraries in an isolated JavaScript context. It also reads the committed, full-region Canadian source snapshot described in [Canadian census-division sources](./canada-census-divisions-2021-sources.md). No GIS library is shipped to the browser and no package installation is required. Node.js 20+ and internet access are needed to regenerate the artifact.

## Sources and scope

- [U.S. Atlas v3.0.1](https://github.com/topojson/us-atlas/tree/v3.0.1) redistributes the U.S. Census Bureau's **2017** cartographic boundaries, generalized at 1:10 million scale. The [unprojected county TopoJSON](https://cdn.jsdelivr.net/npm/us-atlas@3.0.1/counties-10m.json) is the sole U.S. geometry and county-name input. Its SHA-256 digest is `145aaf5d1433352a6a1d8e86b5f149c7c653f9171baf14aaf75ee66575def1b0`.
- Original Census boundary source: [2017 cartographic county shapefile](https://www2.census.gov/geo/tiger/GENZ2017/shp/cb_2017_us_county_500k.zip). Atlas documents its redistribution and simplification in its [README](https://github.com/topojson/us-atlas#readme).
- State names come from Atlas. State FIPS prefixes and postal abbreviations follow the [Census geographic code lists](https://www.census.gov/library/reference/code-lists/ansi.html).
- Coverage: **3,142 counties and county equivalents across the 50 states and Washington, DC**. This includes Alaska's 29 county equivalents and Hawaii's five counties as represented in 2017. Puerto Rico and other territories are excluded explicitly.
- All MLS and USL seasons use the **same 2017 U.S. geography** so differences in the visualization reflect teams changing, not county boundary changes. The map does not reconstruct historical counties or incorporate later county-equivalent changes. County names are source labels and may omit a legal suffix such as County or Parish.
- Southern Canada uses **2021 census divisions** from Statistics Canada's generalized cartographic boundary service. The complete source includes all 293 divisions; only divisions with a visible projected area of at least 0.3 square SVG units inside the cropped view are included in the interactive atlas. This small display threshold omits effectively invisible edge fragments. Canadian IDs use the `CA-` prefix and counts are separate from U.S. counties. This is a view of southern Canada, not complete Canadian coverage.

## Geometry and distances

[D3 geoAlbersUsa](https://d3js.org/d3-geo/conic#geoAlbersUsa) creates the displayed contiguous-U.S. map and Alaska/Hawaii insets. The viewBox remains `0 0 1000 630`. The original U.S. fit is reduced to **94%** around the bottom-center `[500,555]`, giving U.S. bounds of approximately x=98.29–901.71, y=85–555. Canada uses the identical mainland `geoAlbers` scale and translation, clipped to `[20,55]` through `[980,555]`. This reserves a compact northern strip without making the canvas taller or fitting the whole of Canada. The northern latitude varies with longitude because the crop is in projected display space.

Each record has two different positions:

- `centroid: [longitude, latitude]` is the [spherical geographic centroid](https://d3js.org/d3-geo/math#geoCentroid) of its unprojected polygon, rounded to six decimal places. This is the position to use for great-circle/haversine distance calculations. Alaska is measured at its true geographic location, including islands across the antimeridian, before display projection.
- `labelPoint: [x,y]` is the [projected area centroid](https://d3js.org/d3-geo/path#path_centroid) for placing display labels. It is in SVG units and **must not** be used to determine the closest club.

`area` is the spherical polygon area in **steradians**, useful for area-weighted territory labels. It is not county population or projected screen area. County centers are geometric approximations from generalized land polygons, not Census population centers or official internal points. Distance from a county center to the selected club location describes straight-line proximity only; it does not establish driving distance, fandom, exclusive territory, or where every resident is closest.

The JSON contains one compact SVG `path` per county, a single internal `stateBorders` path, and a merged `nationOutline` path. A `canada` object adds visible `divisions`, province borders, a country outline, the 2021 boundary year, source SHA-256 and crop extent. Canadian records include `country: "CA"` and `clipped` flags. SVG coordinates are rounded to one decimal place, geographic centroids to six, and area to twelve. Outline paths use the same topology as their regions. Alaska's display scale and position differ from the mainland; the inset does not alter the geographic centroid or spherical area.

For Canadian divisions, the distance centroid and spherical area are calculated on the **complete cleaned source geometry before clipping**. Only the drawing and display label point are clipped. This preserves one consistent geographic center for each division even when only its southern portion is visible. The source notes document the small degenerate island components removed after simplification. Canadian clubs prefer Canadian territory when placing their crests; U.S. clubs prefer U.S. territory. Placement and collision spacing never change geographic assignments.

The builder validates county and state counts, unique FIPS identifiers, finite paths/coordinates/areas, Alaska/Hawaii counts, all 293 Canadian input divisions and the presence of Greater Vancouver, Toronto and Montréal in the output. Re-running against the pinned resources produces the same output. Run `npm run test:history-canada` for expanded-coverage checks and unchanged U.S. centroid/ownership checks.

## Display neighbors

Each region's sorted `neighbors` array contains other visible region IDs. These symmetric links support distinguishing similarly colored neighboring club territories. They do not alter region ownership, geographic centroids, distances, counts, boundaries or team colors.

Within the U.S., neighbors share an exact source topology arc; corner-only contact does not count. Canadian source topology supplies the initial Canadian graph, and a shared boundary must have more than 0.2 SVG units visible inside the crop. Some touching Canadian divisions use different coordinate sequences along their generalized boundaries. Missing Canadian display neighbors are repaired where boundary segments run alongside one another within **0.25 SVG unit**, for at least **1 SVG unit of combined boundary length**. Toronto's boundaries with York and Durham exercise this case.

The U.S. and Canadian datasets come from independent sources. Their international seam uses the same visible-segment criterion with a **0.75 SVG unit** tolerance. Segment directions must differ by no more than approximately 32 degrees, and both ends and the middle of their overlapping run must remain within the tolerance. These narrow display tolerances can bridge a small simplification gap or a narrow water channel; they describe visual neighboring regions rather than an authoritative legal land-adjacency dataset. Large water gaps and corner-only contact do not qualify.

Artificial closure segments along the Canadian crop frame are excluded from seam comparisons. Alaska and Hawaii retain their own source-topology neighbors and are excluded from international seam comparisons, so the inset layout cannot create false neighbors. All original geometry fields remain unchanged. The builder checks corner-only contact, a narrow seam, separated polygons and crop-frame exclusion; `test:history-canada` checks graph symmetry, real border fixtures, the Toronto seam repairs and a digest of every pre-existing atlas field.

## Data interface

```ts
type CountyMap = {
  width: 1000;
  height: 630;
  boundaryYear: 2017;
  source: string;
  sourceSha256: string;
  projection: { type: 'geoAlbersUsa'; scale: number; translate: [number, number] };
  counties: Array<{
    id: string; // five-character FIPS including leading zero
    name: string;
    state: string; // two-letter USPS abbreviation
    stateName: string;
    centroid: [number, number]; // longitude, latitude (degrees)
    labelPoint: [number, number]; // display x, y
    area: number; // spherical steradians
    path: string;
    neighbors: string[]; // sorted visible region IDs; display adjacency only
  }>;
  stateBorders: string;
  nationOutline: string;
  canada: {
    boundaryYear: 2021;
    source: string; // local full-region GeoJSON snapshot
    sourceSha256: string;
    clipExtent: [[number, number], [number, number]]; // projected SVG bounds
    divisions: Array<{
      id: `CA-${string}`; // CA- plus the four-character CDUID
      name: string;
      state: string; // two-letter province/territory postal abbreviation
      stateName: string;
      country: 'CA';
      centroid: [number, number]; // full-region longitude, latitude (degrees)
      labelPoint: [number, number]; // clipped display x, y
      area: number; // full-region spherical steradians
      path: string; // clipped SVG geometry
      clipped: boolean;
      neighbors: string[]; // may include U.S. FIPS across the visible border
    }>;
    provinceBorders: string;
    outline: string;
  };
};
```

## Attribution and licenses

Suggested public credit: **U.S. county geometry: U.S. Census Bureau (2017), via U.S. Atlas. Canadian census divisions: Statistics Canada (2021), adapted and cropped.** See the Canadian source notes for the applicable Open Government Licence attribution and modifications.

U.S. Atlas v3.0.1 is distributed under the [ISC license](https://cdn.jsdelivr.net/npm/us-atlas@3.0.1/LICENSE), reproduced below. The generator fetches but does not redistribute D3 Array 3.2.4, D3 Geo 3.1.1, TopoJSON Client 3.1.0 and TopoJSON Server 3.0.1. Their license notices are available in the respective packages: [d3-array](https://cdn.jsdelivr.net/npm/d3-array@3.2.4/LICENSE), [d3-geo](https://cdn.jsdelivr.net/npm/d3-geo@3.1.1/LICENSE), [topojson-client](https://cdn.jsdelivr.net/npm/topojson-client@3.1.0/LICENSE), [topojson-server](https://cdn.jsdelivr.net/npm/topojson-server@3.0.1/LICENSE).

```text
Copyright 2013-2019 Michael Bostock

Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
```
