Introduce a geographic AreaProfile API used by native minting and keep the U.S.-coverage source pack explicit. Add worldwide selection regressions and a World selector to the optional Workbench surface.
- commit
- dcda883d8255089451e3a6f16d151521d4e1f02a
- parent
- ce13336a32da1df3c3dd02d18f06c4ebab6a48b3
- author
- Dami <dami.etoile@gmail.com>
| M | docs/ | 11 | +++-- |
| M | internal/ | 10 | ++-- |
| M | internal/ | 68 | +++++++++++++++++++----------- |
| M | internal/ | 6 | +- |
| M | internal/ | 4 | ++ |
| M | internal/ | 2 | +- |
| M | internal/ | 10 | ++-- |
| M | internal/ | 14 | +++--- |
@@ -1,9 +1,12 @@
1-# Arbitrary U.S. area review gate1+# Arbitrary Earth area + U.S. source-pack review gate22 33 This gate proves that `Sample Region` is a parameter, not a fixture. A creator4-draws any bounded area in the United States, accepts the nationwide defaults,5-and receives one native `.atlas` that renders its raster and semantic features6-with the network disabled.4+draws any bounded Web Mercator area on Earth. The geographic selection is not5+coupled to source coverage. For the full-data acceptance demo, the creator6+chooses an area inside the built-in USGS/TIGER pack's stated U.S. coverage and7+receives one native `.atlas` that renders its raster and semantic features with8+the network disabled. A selection outside that coverage is still a valid9+project; sources may truthfully return empty results.710 811 ## Default source profile912 @@ -49,7 +49,7 @@ func NewNativeMinter(options NativeMinterOptions) (*NativeMinter, error) {
4949 5050 // Default is the neutral, immediately valid starting request.5151 func (m *NativeMinter) Default() minting.Request {52- profile := DefaultUSAreaProfile()52+ profile := DefaultAreaProfile()5353 return minting.Request{5454 Title: "My Atlas", Bounds: profile.Bounds, DetailZoom: profile.DetailZoom,5555 Topo: profile.IncludeTopo, Roads: profile.IncludeRoads,@@ -128,12 +128,12 @@ func nextMintRevision(descriptors []vnext.Descriptor, slug string) int {
128128 return revision129129 }130130 131-func mintProject(request minting.Request) (Project, USAreaSummary, error) {131+func mintProject(request minting.Request) (Project, AreaSummary, error) {132132 id := mintSlug(request.Title)133133 if err := vnext.ValidSlug(id); err != nil {134- return Project{}, USAreaSummary{}, fmt.Errorf("Atlas name: %w", err)134+ return Project{}, AreaSummary{}, fmt.Errorf("Atlas name: %w", err)135135 }136- profile := DefaultUSAreaProfile()136+ profile := DefaultAreaProfile()137137 profile.ID, profile.Title = id, strings.TrimSpace(request.Title)138138 profile.Bounds, profile.DetailZoom = request.Bounds, request.DetailZoom139139 profile.IncludeTopo, profile.IncludeRoads = request.Topo, request.Roads@@ -159,7 +159,7 @@ func mintProject(request minting.Request) (Project, USAreaSummary, error) {
159159 if request.CountyColor != "" {160160 profile.Presentation.CountyColor = request.CountyColor161161 }162- return NewUSAreaProject(profile)162+ return NewAreaProject(profile)163163 }164164 165165 func mintSlug(title string) string {@@ -20,9 +20,10 @@ const (
2020 maxExportSize = int64(4096)2121 )2222 23-// USAreaProfile is the compact authoring choice behind the Workbench's24-// nationwide default. Bounds are WGS84 west, south, east, north coordinates.25-type USAreaProfile struct {23+// AreaProfile combines an arbitrary geographic selection with the built-in24+// official U.S. source pack. Bounds are WGS84 west, south, east, north25+// coordinates; they are not restricted to the pack's coverage.26+type AreaProfile struct {2627 ID string2728 Title string2829 Bounds [4]float64@@ -31,20 +32,20 @@ type USAreaProfile struct {
3132 IncludeRoads bool3233 IncludeHydro bool3334 IncludeCounties bool34- Presentation USAreaPresentation35+ Presentation AreaPresentation3536 }3637 37-// USAreaPresentation is the creator-owned layer, label, ordering, and color38+// AreaPresentation is the creator-owned layer, label, ordering, and color3839 // choice that is compiled into the Atlas presentation and legend.39-type USAreaPresentation struct {40+type AreaPresentation struct {4041 RoadLabel, HydroLabel, CountyLabel string4142 RoadColor, HydroColor, HydroFill, CountyColor string4243 RoadVisible, HydroVisible, CountyVisible bool4344 RoadOrder, HydroOrder, CountyOrder int644445 }4546 46-// USAreaSummary is the cost preview shown before a manifest is installed.47-type USAreaSummary struct {47+// AreaSummary is the cost preview shown before a manifest is installed.48+type AreaSummary struct {4849 OriginX int644950 OriginY int645051 SourceZoom int@@ -54,14 +55,20 @@ type USAreaSummary struct {
5455 EstimatedBytes int645556 }5657 57-// DefaultUSAreaProfile selects all official nationwide source families.58-func DefaultUSAreaProfile() USAreaProfile {59- return USAreaProfile{58+// Deprecated compatibility aliases. New code should name the geographic59+// selection separately from the U.S.-coverage source pack.60+type USAreaProfile = AreaProfile61+type USAreaPresentation = AreaPresentation62+type USAreaSummary = AreaSummary63+64+// DefaultAreaProfile selects the built-in official U.S.-coverage source pack.65+func DefaultAreaProfile() AreaProfile {66+ return AreaProfile{6067 ID: "sample-region", Title: "Sample Region",6168 Bounds: [4]float64{-105.1, 39.6, -104.9, 39.8},6269 DetailZoom: 12, IncludeTopo: true, IncludeRoads: true,6370 IncludeHydro: true, IncludeCounties: true,64- Presentation: USAreaPresentation{71+ Presentation: AreaPresentation{6572 RoadLabel: "Roads", HydroLabel: "Water", CountyLabel: "Counties",6673 RoadColor: "#b45f3c", HydroColor: "#4b8db8", HydroFill: "#b9d9ea", CountyColor: "#766b5b",6774 RoadVisible: true, HydroVisible: true, CountyVisible: true,@@ -70,18 +77,23 @@ func DefaultUSAreaProfile() USAreaProfile {
7077 }7178 }7279 73-// NewUSAreaProject turns one bounded U.S. region selection into a complete portable74-// project. Captures and artifacts remain outside the manifest.75-func NewUSAreaProject(profile USAreaProfile) (Project, USAreaSummary, error) {80+// DefaultUSAreaProfile is kept for callers that name the bundled source pack.81+// Deprecated: use DefaultAreaProfile.82+func DefaultUSAreaProfile() USAreaProfile { return DefaultAreaProfile() }83+84+// NewAreaProject turns one arbitrary Web Mercator region selection into a85+// complete portable project using the selected source families. Captures and86+// artifacts remain outside the manifest.87+func NewAreaProject(profile AreaProfile) (Project, AreaSummary, error) {7688 window, err := usTileWindow(profile.Bounds, profile.DetailZoom)7789 if err != nil {78- return Project{}, USAreaSummary{}, err90+ return Project{}, AreaSummary{}, err7991 }8092 if !profile.IncludeTopo && !profile.IncludeRoads && !profile.IncludeHydro && !profile.IncludeCounties {81- return Project{}, USAreaSummary{}, fmt.Errorf("select at least one nationwide source")93+ return Project{}, AreaSummary{}, fmt.Errorf("select at least one source")8294 }8395 if err := validateUSPresentation(profile); err != nil {84- return Project{}, USAreaSummary{}, err96+ return Project{}, AreaSummary{}, err8597 }8698 project := usProjectBase(window, profile.DetailZoom, profile.ID, profile.Title)8799 if profile.IncludeTopo {@@ -97,12 +109,18 @@ func NewUSAreaProject(profile USAreaProfile) (Project, USAreaSummary, error) {
97109 addCounties(&project, window.transform, profile.Presentation)98110 }99111 if err := project.Validate(); err != nil {100- return Project{}, USAreaSummary{}, fmt.Errorf("validate U.S. area project: %w", err)112+ return Project{}, AreaSummary{}, fmt.Errorf("validate area project: %w", err)101113 }102114 return project, summarizeUSProject(project, window), nil103115 }104116 105-func validateUSPresentation(profile USAreaProfile) error {117+// NewUSAreaProject is kept for callers that name the bundled source pack.118+// Deprecated: use NewAreaProject.119+func NewUSAreaProject(profile USAreaProfile) (Project, USAreaSummary, error) {120+ return NewAreaProject(profile)121+}122+123+func validateUSPresentation(profile AreaProfile) error {106124 choices := []struct {107125 enabled bool108126 label string@@ -272,7 +290,7 @@ func floatList(values [4]float64) string {
272290 strconv.FormatFloat(values[2], 'f', 6, 64) + "," + strconv.FormatFloat(values[3], 'f', 6, 64)273291 }274292 275-func addRoads(project *Project, transform CoordinateTransform, presentation USAreaPresentation) {293+func addRoads(project *Project, transform CoordinateTransform, presentation AreaPresentation) {276294 project.FeatureSets = append(project.FeatureSets, FeatureSetContract{277295 ID: "roads", Title: "Roads", SemanticType: "transportation", Geometry: "path",278296 Properties: []PropertyContract{{ID: "name", Name: "Name", Type: "string", Optional: true}, {ID: "class", Name: "Class", Type: "string", Optional: true}, {ID: "route-type", Name: "Route type", Type: "string", Optional: true}},@@ -288,7 +306,7 @@ func addRoads(project *Project, transform CoordinateTransform, presentation USAr
288306 project.Presentation.Layers = append(project.Presentation.Layers, Layer{ID: "roads", FeatureSet: "roads", Style: "roads", Label: presentation.RoadLabel, Group: "Transportation", LabelPolicy: "quiet", Visible: presentation.RoadVisible, Order: presentation.RoadOrder, MaxZoom: 32})289307 }290308 291-func addHydro(project *Project, transform CoordinateTransform, presentation USAreaPresentation) {309+func addHydro(project *Project, transform CoordinateTransform, presentation AreaPresentation) {292310 project.FeatureSets = append(project.FeatureSets,293311 FeatureSetContract{ID: "waterways", Title: "Waterways", SemanticType: "hydrography", Geometry: "path", Properties: commonTigerProperties()},294312 FeatureSetContract{ID: "water-bodies", Title: "Water bodies", SemanticType: "hydrography", Geometry: "area", Properties: append(commonTigerProperties(), PropertyContract{ID: "water-area", Name: "Water area", Type: "int64", Optional: true})},@@ -304,7 +322,7 @@ func addHydro(project *Project, transform CoordinateTransform, presentation USAr
304322 )305323 }306324 307-func addCounties(project *Project, transform CoordinateTransform, presentation USAreaPresentation) {325+func addCounties(project *Project, transform CoordinateTransform, presentation AreaPresentation) {308326 project.FeatureSets = append(project.FeatureSets, FeatureSetContract{309327 ID: "jurisdictions", Title: "Counties", SemanticType: "jurisdiction", Geometry: "area",310328 Properties: []PropertyContract{{ID: "name", Name: "Name", Type: "string"}, {ID: "land-area", Name: "Land area", Type: "int64", Optional: true}, {ID: "water-area", Name: "Water area", Type: "int64", Optional: true}},@@ -334,7 +352,7 @@ func tigerSource(id, locator, set, family string, transform CoordinateTransform)
334352 }335353 }336354 337-func summarizeUSProject(project Project, window usWindow) USAreaSummary {355+func summarizeUSProject(project Project, window usWindow) AreaSummary {338356 tiles := (int64(1)<<(2*(window.maxZoom+1)) - 1) / 3339357 estimated := int64(0)340358 for _, source := range project.Sources {@@ -343,7 +361,7 @@ func summarizeUSProject(project Project, window usWindow) USAreaSummary {
343361 for _, raster := range project.Rasters {344362 estimated += raster.EstimateBytes345363 }346- return USAreaSummary{364+ return AreaSummary{347365 OriginX: window.originX, OriginY: window.originY, SourceZoom: int(project.Target.CoordinateSpace.SourceZoom),348366 PixelSize: window.pixels, RasterTiles: tiles, CaptureRequests: len(project.Sources) + len(project.Rasters), EstimatedBytes: estimated,349367 }@@ -142,15 +142,15 @@ func TestUSAreaProjectSupportsAlaskaAndHawaii(t *testing.T) {
142142 }143143 }144144 145-func TestUSAreaProjectSelectionIsGeographicRatherThanSourceBounded(t *testing.T) {145+func TestAreaProjectSelectionIsGeographicRatherThanSourceBounded(t *testing.T) {146146 for name, bounds := range map[string][4]float64{147147 "Paris": {2.28, 48.82, 2.42, 48.91},148148 "Sydney": {151.14, -33.92, 151.26, -33.82},149149 } {150150 t.Run(name, func(t *testing.T) {151- profile := DefaultUSAreaProfile()151+ profile := DefaultAreaProfile()152152 profile.Bounds, profile.DetailZoom = bounds, 11153- if _, _, err := NewUSAreaProject(profile); err != nil {153+ if _, _, err := NewAreaProject(profile); err != nil {154154 t.Fatalf("an arbitrary geographic selection was coupled to source coverage: %v", err)155155 }156156 })@@ -23,6 +23,10 @@ const tileY = (latitude, count) => {
2323 const latitudeAtTile = (tile, count) => Math.atan(Math.sinh(Math.PI * (1 - 2 * tile / count))) * 180 / Math.PI;2424 2525 const mapRegions = {26+ world: {27+ extent: [-180, -85.051128, 180, 85.051128], initial: [-105.1, 39.6, -104.9, 39.8], zoom: 12,28+ outline: [],29+ },2630 conus: {2731 extent: [-125, 24, -66, 50], initial: [-105.1, 39.6, -104.9, 39.8], zoom: 12,2832 outline: [[-124, 48], [-124, 42], [-122, 38], [-117, 33], [-111, 32], [-106, 31], [-103, 29], [-97, 26], [-82, 25], [-80, 27], [-81, 31], [-75, 35], [-67, 45], [-75, 45], [-83, 46], [-95, 49], [-112, 49]],@@ -125,7 +125,7 @@ func TestProjectPageMakesTheNativeBuildGraphVisible(t *testing.T) {
125125 "Sample Region", "One manifest → one native volume", "sample-features", "geojson",126126 "0 / 1 requests", "feature sources", "semantic sets", "presentation layers",127127 "Build native Atlas", "Portable manifest", "Sample Region contributors",128- "Choose a U.S. area", "USGS Topo", "TIGER roads", "TIGER hydro", "TIGER counties",128+ "Choose any Earth area", "World", "U.S. source coverage", "USGS Topo", "TIGER roads", "TIGER hydro", "TIGER counties",129129 "Typed FeatureSets", "Compiled Atlas truth")130130 if response, _ := get(t, server, "/operations"); response.StatusCode != http.StatusNotFound {131131 t.Errorf("retired operations route answered %d", response.StatusCode)@@ -11,9 +11,9 @@
1111 <section class="card area-authoring" aria-labelledby="area-authoring-title">1212 <header class="authoring-head">1313 <div>14- <p class="eyebrow">Nationwide source profile</p>15- <h2 id="area-authoring-title">Choose a U.S. area</h2>16- <p class="dim">One bounded region becomes the single manifest below. The label stays neutral: Sample Region.</p>14+ <p class="eyebrow">Geographic selection · U.S. source coverage</p>15+ <h2 id="area-authoring-title">Choose any Earth area</h2>16+ <p class="dim">The boundary may be anywhere on Earth. The bundled USGS/TIGER pack only promises data inside its stated U.S. coverage.</p>1717 </div>1818 <ol class="authoring-flow" aria-label="Authoring flow">1919 <li class="active">Area</li><li>Sources</li><li>Contracts</li><li>Build</li><li>Compiled preview</li>@@ -26,7 +26,7 @@
2626 <div class="area-map-toolbar">2727 <label>Region2828 <select data-map-region>29- <option value="conus">Lower 48</option><option value="alaska">Alaska</option><option value="hawaii">Hawaii</option><option value="puerto-rico">Puerto Rico</option>29+ <option value="world">World</option><option value="conus">Lower 48</option><option value="alaska">Alaska</option><option value="hawaii">Hawaii</option><option value="puerto-rico">Puerto Rico</option>3030 </select>3131 </label>3232 <span>Drag to draw · aligned source window is outlined</span>@@ -42,7 +42,7 @@
4242 </fieldset>4343 4444 <fieldset class="source-picker">45- <legend>Official nationwide sources</legend>45+ <legend>Official sources · U.S. coverage</legend>4646 <label class="source-choice topo"><input type="checkbox" name="topo" value="true" checked><span><b>USGS Topo</b><small>raster · public domain</small></span></label>4747 <label class="source-choice roads"><input type="checkbox" name="roads" value="true" checked><span><b>TIGER roads</b><small>paths · typed class</small></span></label>4848 <label class="source-choice hydro"><input type="checkbox" name="hydro" value="true" checked><span><b>TIGER hydro</b><small>paths + areas</small></span></label>@@ -26,7 +26,7 @@ func (w *Workbench) handleProjectUSArea(rw http.ResponseWriter, request *http.Re
2626 http.Error(rw, err.Error(), http.StatusBadRequest)2727 return2828 }29- project, _, err := authoring.NewUSAreaProject(profile)29+ project, _, err := authoring.NewAreaProject(profile)3030 if err != nil {3131 http.Error(rw, err.Error(), http.StatusBadRequest)3232 return@@ -43,8 +43,8 @@ func (w *Workbench) handleProjectUSArea(rw http.ResponseWriter, request *http.Re
4343 http.Redirect(rw, request, "/project?notice=Official+U.S.+profile+installed", http.StatusSeeOther)4444 }4545 46-func usAreaProfileFromForm(request *http.Request) (authoring.USAreaProfile, error) {47- profile := authoring.DefaultUSAreaProfile()46+func usAreaProfileFromForm(request *http.Request) (authoring.AreaProfile, error) {47+ profile := authoring.DefaultAreaProfile()4848 fields := []struct {4949 name string5050 at int@@ -54,13 +54,13 @@ func usAreaProfileFromForm(request *http.Request) (authoring.USAreaProfile, erro
5454 for _, field := range fields {5555 value, err := strconv.ParseFloat(request.FormValue(field.name), 64)5656 if err != nil {57- return authoring.USAreaProfile{}, fmt.Errorf("%s coordinate is invalid", field.name)57+ return authoring.AreaProfile{}, fmt.Errorf("%s coordinate is invalid", field.name)5858 }5959 profile.Bounds[field.at] = value6060 }6161 detail, err := strconv.Atoi(request.FormValue("detail"))6262 if err != nil {63- return authoring.USAreaProfile{}, fmt.Errorf("detail zoom is invalid")63+ return authoring.AreaProfile{}, fmt.Errorf("detail zoom is invalid")6464 }6565 profile.DetailZoom = detail6666 profile.IncludeTopo = request.FormValue("topo") == "true"@@ -68,12 +68,12 @@ func usAreaProfileFromForm(request *http.Request) (authoring.USAreaProfile, erro
6868 profile.IncludeHydro = request.FormValue("hydro") == "true"6969 profile.IncludeCounties = request.FormValue("counties") == "true"7070 if err := presentationFromForm(request, &profile.Presentation); err != nil {71- return authoring.USAreaProfile{}, err71+ return authoring.AreaProfile{}, err7272 }7373 return profile, nil7474 }7575 76-func presentationFromForm(request *http.Request, presentation *authoring.USAreaPresentation) error {76+func presentationFromForm(request *http.Request, presentation *authoring.AreaPresentation) error {7777 presentation.RoadLabel = request.FormValue("road-label")7878 presentation.HydroLabel = request.FormValue("hydro-label")7979 presentation.CountyLabel = request.FormValue("county-label")