From 6472d9acd759199489bd49e14dca9c4c64591033 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Bachin Krishnarao Date: Mon, 1 Dec 2025 15:13:57 -0800 Subject: [PATCH 1/6] Added geographic_area feature type with functional and cultural sub-types --- .../divisions/geographic_area/bad-class.yaml | 16 + .../geographic_area/bad-geometry-type.yaml | 15 + .../geographic_area/bad-subtype.yaml | 15 + .../colloquial-functional-mismatch.yaml | 16 + .../missing-class-cultural.yaml | 15 + .../missing-class-functional.yaml | 15 + .../geographic_area/negative-population.yaml | 17 + .../postal-cultural-mismatch.yaml | 16 + .../reference/divisions/geographic_area.mdx | 114 +++++ .../cultural_colloquial_bay_area.yaml | 48 ++ .../cultural_colloquial_east_asia.yaml | 48 ++ .../cultural_colloquial_new_england.yaml | 45 ++ .../cultural_colloquial_south_florida.yaml | 41 ++ .../cultural_colloquial_wine_country.yaml | 36 ++ .../functional_metro_area.yaml | 47 ++ .../functional_postal_zip_code.yaml | 38 ++ .../pyproject.toml | 3 +- .../src/overture/schema/divisions/__init__.py | 3 +- .../divisions/geographic_area/__init__.py | 6 + .../schema/divisions/geographic_area/enums.py | 37 ++ .../divisions/geographic_area/models.py | 102 ++++ .../geographic_area_baseline_schema.json | 468 ++++++++++++++++++ ...st_geographic_area_json_schema_baseline.py | 32 ++ schema/defs.yaml | 1 + schema/divisions/geographic_area.yaml | 99 ++++ schema/schema.yaml | 8 + 26 files changed, 1299 insertions(+), 2 deletions(-) create mode 100644 counterexamples/divisions/geographic_area/bad-class.yaml create mode 100644 counterexamples/divisions/geographic_area/bad-geometry-type.yaml create mode 100644 counterexamples/divisions/geographic_area/bad-subtype.yaml create mode 100644 counterexamples/divisions/geographic_area/colloquial-functional-mismatch.yaml create mode 100644 counterexamples/divisions/geographic_area/missing-class-cultural.yaml create mode 100644 counterexamples/divisions/geographic_area/missing-class-functional.yaml create mode 100644 counterexamples/divisions/geographic_area/negative-population.yaml create mode 100644 counterexamples/divisions/geographic_area/postal-cultural-mismatch.yaml create mode 100644 docs/schema/reference/divisions/geographic_area.mdx create mode 100644 examples/divisions/geographic_area/cultural_colloquial_bay_area.yaml create mode 100644 examples/divisions/geographic_area/cultural_colloquial_east_asia.yaml create mode 100644 examples/divisions/geographic_area/cultural_colloquial_new_england.yaml create mode 100644 examples/divisions/geographic_area/cultural_colloquial_south_florida.yaml create mode 100644 examples/divisions/geographic_area/cultural_colloquial_wine_country.yaml create mode 100644 examples/divisions/geographic_area/functional_metro_area.yaml create mode 100644 examples/divisions/geographic_area/functional_postal_zip_code.yaml create mode 100644 packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/__init__.py create mode 100644 packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/enums.py create mode 100644 packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/models.py create mode 100644 packages/overture-schema-divisions-theme/tests/geographic_area_baseline_schema.json create mode 100644 packages/overture-schema-divisions-theme/tests/test_geographic_area_json_schema_baseline.py create mode 100644 schema/divisions/geographic_area.yaml diff --git a/counterexamples/divisions/geographic_area/bad-class.yaml b/counterexamples/divisions/geographic_area/bad-class.yaml new file mode 100644 index 000000000..caa7728b7 --- /dev/null +++ b/counterexamples/divisions/geographic_area/bad-class.yaml @@ -0,0 +1,16 @@ +--- +id: counterexample:geography:bad-class +type: Feature +geometry: + type: Polygon + coordinates: [[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]] +properties: + theme: divisions + type: geographic_area + version: 0 + subtype: cultural + class: regional + names: + primary: A cultural geography with an invalid class. + ext_expected_errors: + - "value must be one of 'colloquial', 'postal'" diff --git a/counterexamples/divisions/geographic_area/bad-geometry-type.yaml b/counterexamples/divisions/geographic_area/bad-geometry-type.yaml new file mode 100644 index 000000000..01f101a73 --- /dev/null +++ b/counterexamples/divisions/geographic_area/bad-geometry-type.yaml @@ -0,0 +1,15 @@ +--- +id: counterexample:geography:bad-geometry +type: Feature +geometry: + type: Point + coordinates: [0, 0] +properties: + theme: divisions + type: geographic_area + version: 0 + subtype: functional + names: + primary: A geography with invalid Point geometry (must be Polygon or MultiPolygon). + ext_expected_errors: + - "geometry type must be Polygon or MultiPolygon" diff --git a/counterexamples/divisions/geographic_area/bad-subtype.yaml b/counterexamples/divisions/geographic_area/bad-subtype.yaml new file mode 100644 index 000000000..5b4aa5241 --- /dev/null +++ b/counterexamples/divisions/geographic_area/bad-subtype.yaml @@ -0,0 +1,15 @@ +--- +id: counterexample:geography:bad-subtype +type: Feature +geometry: + type: Polygon + coordinates: [[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]] +properties: + theme: divisions + type: geographic_area + version: 0 + subtype: administrative + names: + primary: A geography with an invalid subtype. + ext_expected_errors: + - "value must be one of 'functional', 'cultural'" diff --git a/counterexamples/divisions/geographic_area/colloquial-functional-mismatch.yaml b/counterexamples/divisions/geographic_area/colloquial-functional-mismatch.yaml new file mode 100644 index 000000000..f9d6084e3 --- /dev/null +++ b/counterexamples/divisions/geographic_area/colloquial-functional-mismatch.yaml @@ -0,0 +1,16 @@ +--- +id: counterexample:geography:colloquial-functional-mismatch +type: Feature +geometry: + type: Polygon + coordinates: [[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]] +properties: + theme: divisions + type: geographic_area + version: 0 + subtype: functional + class: colloquial + names: + primary: A functional geography with colloquial class (only allowed for cultural). + ext_expected_errors: + - "colloquial class is only allowed for cultural subtype" diff --git a/counterexamples/divisions/geographic_area/missing-class-cultural.yaml b/counterexamples/divisions/geographic_area/missing-class-cultural.yaml new file mode 100644 index 000000000..bb71f845b --- /dev/null +++ b/counterexamples/divisions/geographic_area/missing-class-cultural.yaml @@ -0,0 +1,15 @@ +--- +id: counterexample:geography:missing-class +type: Feature +geometry: + type: Polygon + coordinates: [[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]] +properties: + theme: divisions + type: geographic_area + version: 0 + subtype: cultural + names: + primary: A geography missing required class property. + ext_expected_errors: + - "required property 'class' is missing" diff --git a/counterexamples/divisions/geographic_area/missing-class-functional.yaml b/counterexamples/divisions/geographic_area/missing-class-functional.yaml new file mode 100644 index 000000000..6eec90fe5 --- /dev/null +++ b/counterexamples/divisions/geographic_area/missing-class-functional.yaml @@ -0,0 +1,15 @@ +--- +id: counterexample:geography:missing-class-functional +type: Feature +geometry: + type: Polygon + coordinates: [[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]] +properties: + theme: divisions + type: geographic_area + version: 0 + subtype: functional + names: + primary: A functional geography missing required class property. + ext_expected_errors: + - "required property 'class' is missing" diff --git a/counterexamples/divisions/geographic_area/negative-population.yaml b/counterexamples/divisions/geographic_area/negative-population.yaml new file mode 100644 index 000000000..da37a8848 --- /dev/null +++ b/counterexamples/divisions/geographic_area/negative-population.yaml @@ -0,0 +1,17 @@ +--- +id: counterexample:geography:negative-population +type: Feature +geometry: + type: Polygon + coordinates: [[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]] +properties: + theme: divisions + type: geographic_area + version: 0 + subtype: cultural + class: colloquial + names: + primary: A geography with negative population. + population: -1000 + ext_expected_errors: + - "population must be greater than or equal to 0" diff --git a/counterexamples/divisions/geographic_area/postal-cultural-mismatch.yaml b/counterexamples/divisions/geographic_area/postal-cultural-mismatch.yaml new file mode 100644 index 000000000..5105c9dbb --- /dev/null +++ b/counterexamples/divisions/geographic_area/postal-cultural-mismatch.yaml @@ -0,0 +1,16 @@ +--- +id: counterexample:geography:postal-cultural-mismatch +type: Feature +geometry: + type: Polygon + coordinates: [[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]] +properties: + theme: divisions + type: geographic_area + version: 0 + subtype: cultural + class: postal + names: + primary: A cultural geography with postal class (only allowed for functional). + ext_expected_errors: + - "postal class is only allowed for functional subtype" diff --git a/docs/schema/reference/divisions/geographic_area.mdx b/docs/schema/reference/divisions/geographic_area.mdx new file mode 100644 index 000000000..8055d4f7a --- /dev/null +++ b/docs/schema/reference/divisions/geographic_area.mdx @@ -0,0 +1,114 @@ +--- +title: geographic_area +--- + +import CodeBlock from '@theme/CodeBlock'; +import JSONSchemaViewer from "@theme/JSONSchemaViewer"; +import generateResolverOptions from "@site/src/components/shared-libs/generateResolverOptions" +import yamlLoad from "@site/src/components/yamlLoad" +import divisions_geographic_area_schema from '!!raw-loader!@site/docs/_schema/divisions/geographic_area.yaml'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import geographic_area_example_cultural_bay_area from '!!raw-loader!@site/docs/_examples/divisions/geographic_area/cultural_colloquial_bay_area.yaml'; +import geographic_area_example_cultural_wine_country from '!!raw-loader!@site/docs/_examples/divisions/geographic_area/cultural_colloquial_wine_country.yaml'; +import geographic_area_example_functional_zip from '!!raw-loader!@site/docs/_examples/divisions/geographic_area/functional_postal_zip_code.yaml'; + + +# Geographic area + +A geographic area is a functional or cultural region that may span across multiple administrative divisions. These regions capture areas defined by shared characteristics, usage patterns, or cultural identity rather than formal administrative boundaries. + + + + + + + + + + + + + + + + + +
Geometry TypePolygon or MultiPolygon
Themedivisions
Typegeographic_area
+ +## Subtypes + +Geographic areas are categorized into two main subtypes: + + + + + + + + + + +
subtypefunctional
+ +Functional regions are defined by functional characteristics or usage patterns, such as metropolitan areas, economic zones, or postal code regions. These areas serve specific operational or administrative purposes. + +**Classes:** +- `postal` - Postal code regions used for mail delivery and routing (e.g., US ZIP codes, UK postcodes, Canadian postal codes) + +
+ + + + + + + + + +
subtypecultural
+ +Cultural regions are defined by cultural identity, colloquial usage, or shared cultural characteristics. These areas reflect how people commonly refer to regions in everyday language. + +**Classes:** +- `colloquial` - Colloquial regions are informal, culturally defined, or commonly referenced areas that do not correspond to official administrative boundaries. Unlike countries, states, counties, or cities—whose boundaries are legally defined—colloquial regions evolve from cultural, historical, economic, or linguistic identity. Examples include South Florida, East Asia, and California Wine Country. + +
+
+ +## Properties + +Key properties of geographic areas include: + +- **names** - Primary name and optional translations +- **subtype** - Either `functional` or `cultural` +- **class** - Required classification (e.g., `colloquial` for cultural, `postal` for functional) +- **associated_division_ids** - Optional list of division IDs that make up the geographic area +- **population** - Optional population count if inferable +- **cartography** - Cartographic hints including prominence for map display +- **wikidata** - Optional Wikidata ID reference + +## Schema + + + + + + + {divisions_geographic_area_schema} + + + +## Examples + + + + { JSON.stringify(yamlLoad(geographic_area_example_cultural_bay_area), null, 2) } + + + { JSON.stringify(yamlLoad(geographic_area_example_cultural_wine_country), null, 2) } + + + { JSON.stringify(yamlLoad(geographic_area_example_functional_zip), null, 2) } + + diff --git a/examples/divisions/geographic_area/cultural_colloquial_bay_area.yaml b/examples/divisions/geographic_area/cultural_colloquial_bay_area.yaml new file mode 100644 index 000000000..f74797b7f --- /dev/null +++ b/examples/divisions/geographic_area/cultural_colloquial_bay_area.yaml @@ -0,0 +1,48 @@ +--- +id: example:geography:cultural:bay_area +type: Feature +geometry: + type: Polygon + coordinates: [ + [ + [-123.0, 37.3], + [-121.5, 37.3], + [-121.5, 38.5], + [-123.0, 38.5], + [-123.0, 37.3] + ] + ] +bbox: [-123.0, 37.3, -121.5, 38.5] +properties: + theme: divisions + type: geographic_area + version: 0 + subtype: cultural + class: colloquial + names: + primary: San Francisco Bay Area + common: + en: Bay Area + es: Área de la Bahía + zh: 舊金山灣區 + cartography: + prominence: 75 + min_zoom: 6 + max_zoom: 12 + associated_division_ids: + - example:division:locality:san_francisco + - example:division:locality:oakland + - example:division:locality:san_jose + - example:division:county:alameda + - example:division:county:contra_costa + - example:division:county:marin + - example:division:county:san_francisco + - example:division:county:san_mateo + - example:division:county:santa_clara + population: 7753000 + wikidata: Q213205 + sources: + - property: "" + dataset: OpenStreetMap + record_id: relation/111968 + update_time: "2023-11-15T10:20:30Z" diff --git a/examples/divisions/geographic_area/cultural_colloquial_east_asia.yaml b/examples/divisions/geographic_area/cultural_colloquial_east_asia.yaml new file mode 100644 index 000000000..7f82dd68f --- /dev/null +++ b/examples/divisions/geographic_area/cultural_colloquial_east_asia.yaml @@ -0,0 +1,48 @@ +--- +id: example:geography:cultural:east_asia +type: Feature +geometry: + type: Polygon + coordinates: [ + [ + [100.0, 20.0], + [145.0, 20.0], + [145.0, 50.0], + [100.0, 50.0], + [100.0, 20.0] + ] + ] +bbox: [100.0, 20.0, 145.0, 50.0] +properties: + theme: divisions + type: geographic_area + version: 0 + subtype: cultural + class: colloquial + names: + primary: East Asia + common: + en: East Asia + es: Asia Oriental + fr: Asie de l'Est + zh: 東亞 + zh-Hans: 东亚 + ja: 東アジア + ko: 동아시아 + cartography: + prominence: 85 + min_zoom: 3 + max_zoom: 8 + associated_division_ids: + - example:division:country:cn + - example:division:country:jp + - example:division:country:kr + - example:division:country:kp + - example:division:country:mn + - example:division:country:tw + population: 1677000000 + wikidata: Q27231 + sources: + - property: "" + dataset: OpenStreetMap + record_id: relation/345678 diff --git a/examples/divisions/geographic_area/cultural_colloquial_new_england.yaml b/examples/divisions/geographic_area/cultural_colloquial_new_england.yaml new file mode 100644 index 000000000..d1ba0f030 --- /dev/null +++ b/examples/divisions/geographic_area/cultural_colloquial_new_england.yaml @@ -0,0 +1,45 @@ +--- +id: example:geography:cultural:new_england +type: Feature +geometry: + type: Polygon + coordinates: [ + [ + [-73.5, 41.0], + [-69.5, 41.0], + [-69.5, 47.5], + [-73.5, 47.5], + [-73.5, 41.0] + ] + ] +bbox: [-73.5, 41.0, -69.5, 47.5] +properties: + theme: divisions + type: geographic_area + version: 0 + subtype: cultural + class: colloquial + names: + primary: New England + common: + en: New England + es: Nueva Inglaterra + fr: Nouvelle-Angleterre + pt: Nova Inglaterra + cartography: + prominence: 70 + min_zoom: 5 + max_zoom: 10 + associated_division_ids: + - example:division:region:connecticut + - example:division:region:maine + - example:division:region:massachusetts + - example:division:region:new_hampshire + - example:division:region:rhode_island + - example:division:region:vermont + population: 15116205 + wikidata: Q18389 + sources: + - property: "" + dataset: OpenStreetMap + record_id: relation/60759 diff --git a/examples/divisions/geographic_area/cultural_colloquial_south_florida.yaml b/examples/divisions/geographic_area/cultural_colloquial_south_florida.yaml new file mode 100644 index 000000000..4d08ad037 --- /dev/null +++ b/examples/divisions/geographic_area/cultural_colloquial_south_florida.yaml @@ -0,0 +1,41 @@ +--- +id: example:geography:cultural:south_florida +type: Feature +geometry: + type: Polygon + coordinates: [ + [ + [-81.5, 25.0], + [-79.8, 25.0], + [-79.8, 27.0], + [-81.5, 27.0], + [-81.5, 25.0] + ] + ] +bbox: [-81.5, 25.0, -79.8, 27.0] +properties: + theme: divisions + type: geographic_area + version: 0 + subtype: cultural + class: colloquial + names: + primary: South Florida + common: + en: South Florida + es: Sur de Florida + cartography: + prominence: 65 + min_zoom: 7 + max_zoom: 11 + associated_division_ids: + - example:division:county:miami_dade + - example:division:county:broward + - example:division:county:palm_beach + - example:division:county:monroe + population: 6198782 + wikidata: Q1352730 + sources: + - property: "" + dataset: OpenStreetMap + record_id: relation/234567 diff --git a/examples/divisions/geographic_area/cultural_colloquial_wine_country.yaml b/examples/divisions/geographic_area/cultural_colloquial_wine_country.yaml new file mode 100644 index 000000000..1d36209f2 --- /dev/null +++ b/examples/divisions/geographic_area/cultural_colloquial_wine_country.yaml @@ -0,0 +1,36 @@ +--- +id: example:geography:cultural:california_wine_country +type: Feature +geometry: + type: Polygon + coordinates: [ + [ + [-123.5, 38.0], + [-122.0, 38.0], + [-122.0, 39.0], + [-123.5, 39.0], + [-123.5, 38.0] + ] + ] +bbox: [-123.5, 38.0, -122.0, 39.0] +properties: + theme: divisions + type: geographic_area + version: 0 + subtype: cultural + class: colloquial + names: + primary: California Wine Country + common: + en: Wine Country + es: Región Vinícola de California + cartography: + prominence: 50 + min_zoom: 8 + max_zoom: 13 + wikidata: Q3303756 + sources: + - property: "" + dataset: OpenStreetMap + record_id: relation/123456 + update_time: "2023-09-10T08:15:00Z" diff --git a/examples/divisions/geographic_area/functional_metro_area.yaml b/examples/divisions/geographic_area/functional_metro_area.yaml new file mode 100644 index 000000000..a4fc2c52b --- /dev/null +++ b/examples/divisions/geographic_area/functional_metro_area.yaml @@ -0,0 +1,47 @@ +--- +id: example:geography:functional:metro_area_tokyo +type: Feature +geometry: + type: Polygon + coordinates: [ + [ + [139.0, 35.0], + [140.5, 35.0], + [140.5, 36.5], + [139.0, 36.5], + [139.0, 35.0] + ] + ] +bbox: [139.0, 35.0, 140.5, 36.5] +properties: + theme: divisions + type: geographic_area + version: 0 + subtype: functional + names: + primary: Tokyo Metropolitan Area + common: + en: Greater Tokyo Area + ja: 東京大都市圏 + ja-Latn: Tōkyō Daitoshi-ken + cartography: + prominence: 90 + min_zoom: 4 + max_zoom: 11 + associated_division_ids: + - example:division:locality:tokyo + - example:division:locality:yokohama + - example:division:locality:kawasaki + - example:division:locality:saitama + - example:division:locality:chiba + - example:division:region:tokyo_prefecture + - example:division:region:kanagawa_prefecture + - example:division:region:saitama_prefecture + - example:division:region:chiba_prefecture + population: 37400000 + wikidata: Q208403 + sources: + - property: "" + dataset: OpenStreetMap + record_id: relation/1543125 + update_time: "2023-10-20T14:35:00Z" diff --git a/examples/divisions/geographic_area/functional_postal_zip_code.yaml b/examples/divisions/geographic_area/functional_postal_zip_code.yaml new file mode 100644 index 000000000..45df1a5ea --- /dev/null +++ b/examples/divisions/geographic_area/functional_postal_zip_code.yaml @@ -0,0 +1,38 @@ +--- +id: example:geography:functional:us_zip_90210 +type: Feature +geometry: + type: Polygon + coordinates: [ + [ + [-118.416, 34.088], + [-118.396, 34.088], + [-118.396, 34.108], + [-118.416, 34.108], + [-118.416, 34.088] + ] + ] +bbox: [-118.416, 34.088, -118.396, 34.108] +properties: + theme: divisions + type: geographic_area + version: 0 + subtype: functional + class: postal + names: + primary: "90210" + common: + en: Beverly Hills ZIP Code + cartography: + prominence: 30 + min_zoom: 11 + max_zoom: 15 + associated_division_ids: + - example:division:locality:beverly_hills + population: 21733 + wikidata: Q3271856 + sources: + - property: "" + dataset: US Census Bureau + record_id: ZCTA5/90210 + update_time: "2023-08-15T12:00:00Z" diff --git a/packages/overture-schema-divisions-theme/pyproject.toml b/packages/overture-schema-divisions-theme/pyproject.toml index e56b1df6a..565e30ba4 100644 --- a/packages/overture-schema-divisions-theme/pyproject.toml +++ b/packages/overture-schema-divisions-theme/pyproject.toml @@ -4,7 +4,7 @@ dependencies = [ "overture-schema-system", "pydantic>=2.0", ] -description = "Overture Maps divisions theme shared structures, division, division area and division boundary types" +description = "Overture Maps divisions theme shared structures, division, division area, division boundary, and geographic area types" dynamic = ["version"] license = "MIT" name = "overture-schema-divisions-theme" @@ -29,3 +29,4 @@ packages = ["src/overture"] "overture:divisions:division" = "overture.schema.divisions:Division" "overture:divisions:division_area" = "overture.schema.divisions:DivisionArea" "overture:divisions:division_boundary" = "overture.schema.divisions:DivisionBoundary" +"overture:divisions:geographic_area" = "overture.schema.divisions:GeographicArea" diff --git a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/__init__.py b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/__init__.py index ea08ff2e5..7b3cc025a 100644 --- a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/__init__.py +++ b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/__init__.py @@ -9,5 +9,6 @@ from .division import Division from .division_area import DivisionArea from .division_boundary import DivisionBoundary +from .geographic_area import GeographicArea -__all__ = ["Division", "DivisionArea", "DivisionBoundary"] +__all__ = ["Division", "DivisionArea", "DivisionBoundary", "GeographicArea"] diff --git a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/__init__.py b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/__init__.py new file mode 100644 index 000000000..2a19485b6 --- /dev/null +++ b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/__init__.py @@ -0,0 +1,6 @@ +"""Geographic area feature type.""" + +from .enums import GeographicAreaClass, GeographicAreaSubtype +from .models import GeographicArea + +__all__ = ["GeographicArea", "GeographicAreaClass", "GeographicAreaSubtype"] diff --git a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/enums.py b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/enums.py new file mode 100644 index 000000000..8cca330c0 --- /dev/null +++ b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/enums.py @@ -0,0 +1,37 @@ +"""Geography enums for Overture Maps divisions theme.""" + +from enum import Enum + + +class GeographicAreaSubtype(str, Enum): + """ + The type of geographic area feature. + + - functional: Regions defined by functional characteristics or usage patterns + (e.g., metropolitan areas, economic zones). + + - cultural: Regions defined by cultural identity, colloquial usage, or shared + cultural characteristics (e.g., "the Bay Area", "New England", "Silicon Valley"). + """ + + FUNCTIONAL = "functional" + CULTURAL = "cultural" + + +class GeographicAreaClass(str, Enum): + """ + Classification of the geographic area feature. + """ + + # Colloquial regions are informal, culturally defined, or commonly referenced areas + # that do not correspond to official administrative boundaries. Unlike countries, + # states, counties, or cities—whose boundaries are legally defined—colloquial regions + # evolve from cultural, historical, economic, or linguistic identity. + # Examples include South Florida, East Asia, and California Wine Country. + # Only applicable to cultural subtype. + COLLOQUIAL = "colloquial" + + # Postal code regions used for mail delivery and routing. + # Examples include US ZIP codes, UK postcodes, and Canadian postal codes. + # Only applicable to functional subtype. + POSTAL = "postal" diff --git a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/models.py b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/models.py new file mode 100644 index 000000000..99fbd5cbc --- /dev/null +++ b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/models.py @@ -0,0 +1,102 @@ +"""Geography models for Overture Maps divisions theme.""" + +from typing import Annotated, Literal + +from pydantic import ConfigDict, Field, model_validator + +from overture.schema.core import OvertureFeature +from overture.schema.core.cartography import CartographicallyHinted +from overture.schema.core.names import Named, Names +from overture.schema.system.field_constraint import UniqueItemsConstraint +from overture.schema.system.primitive import ( + Geometry, + GeometryType, + GeometryTypeConstraint, + int32, +) +from overture.schema.system.ref import Id, Reference, Relationship + +from ..division.models import Division +from .enums import GeographicAreaClass, GeographicAreaSubtype + + +class GeographicArea( + OvertureFeature[Literal["divisions"], Literal["geographic_area"]], + Named, + CartographicallyHinted, +): + """Geographic area features represent functional or cultural regions that may span across + multiple administrative divisions. + + These regions capture areas defined by shared characteristics, usage patterns, or + cultural identity rather than formal administrative boundaries. + + Examples include metropolitan areas (functional) or colloquial regions like "the Bay + Area" or "New England" (cultural). + """ + + model_config = ConfigDict(title="geographic_area") + + # Core + geometry: Annotated[ + Geometry, + GeometryTypeConstraint(GeometryType.POLYGON, GeometryType.MULTI_POLYGON), + Field( + description="Geography geometry MUST be a Polygon or MultiPolygon as defined by GeoJSON schema. The geometry is constructed from associated divisions or available sources.", + ), + ] + + # Required + + names: Names + subtype: Annotated[ + GeographicAreaSubtype, + Field( + description="""The type of geography feature. + +- functional: Regions defined by functional characteristics or usage patterns (e.g., metropolitan areas, economic zones). + +- cultural: Regions defined by cultural identity, colloquial usage, or shared cultural characteristics (e.g., "the Bay Area", "New England", "Silicon Valley").""" + ), + ] + + class_: Annotated[ + GeographicAreaClass, + Field( + alias="class", + description="Classification of the geography feature. Colloquial class is only allowed for cultural subtype. Postal class is only allowed for functional subtype.", + ), + ] + + # Optional + + associated_division_ids: Annotated[ + list[Id] | None, + UniqueItemsConstraint(), + Field( + description="Optional list of division IDs representing the set of divisions that make up this geography region. This property links the geography to the underlying administrative divisions it encompasses or relates to. May be null if the region cannot be precisely mapped to specific administrative divisions.", + min_length=1, + ), + Reference(Relationship.BOUNDARY_OF, Division), + ] = None + + population: Annotated[ + int32 | None, + Field( + description="Optional population represented in the region, if inferable from associated divisions or available sources.", + ge=0, + ), + ] = None + + @model_validator(mode="after") + def validate_class_rules(self) -> "GeographicArea": + """Validate class field rules.""" + # Colloquial class only allowed for cultural subtype + if self.class_ == GeographicAreaClass.COLLOQUIAL and self.subtype != GeographicAreaSubtype.CULTURAL: + raise ValueError("colloquial class is only allowed for cultural subtype") + + # Postal class only allowed for functional subtype + if self.class_ == GeographicAreaClass.POSTAL and self.subtype != GeographicAreaSubtype.FUNCTIONAL: + raise ValueError("postal class is only allowed for functional subtype") + + return self diff --git a/packages/overture-schema-divisions-theme/tests/geographic_area_baseline_schema.json b/packages/overture-schema-divisions-theme/tests/geographic_area_baseline_schema.json new file mode 100644 index 000000000..50ed49dc5 --- /dev/null +++ b/packages/overture-schema-divisions-theme/tests/geographic_area_baseline_schema.json @@ -0,0 +1,468 @@ +{ + "$defs": { + "CartographicHints": { + "additionalProperties": false, + "description": "Cartographic hints for optimal use of Overture features in map-making.", + "properties": { + "max_zoom": { + "description": "Recommended maximum tile zoom level in which this feature should be displayed.\n\nIt is recommended that the feature be hidden at zoom levels above this value.\n\nZoom levels follow the Slippy Maps convention, documented in the following\nreferences:\n- https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames\n- https://www.maptiler.com/google-maps-coordinates-tile-bounds-projection", + "maximum": 23, + "minimum": 0, + "title": "Max Zoom", + "type": "integer" + }, + "min_zoom": { + "description": "Recommended minimum tile zoom level in which this feature should be displayed.\n\nIt is recommended that the feature be hidden at zoom levels below this value.\n\nZoom levels follow the Slippy Maps convention, documented in the following\nreferences:\n- https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames\n- https://www.maptiler.com/google-maps-coordinates-tile-bounds-projection", + "maximum": 23, + "minimum": 0, + "title": "Min Zoom", + "type": "integer" + }, + "prominence": { + "description": "Subjective scale of feature significance or importance, with 1 being the least, and\n100 being the most, significant.\n\nThis value can be used to help drive decisions about how and when to display a\nfeature, and how to treat it relative to neighboring features.\n\nWhen populated by Overture, this value is derived from various factors including,\nbut not limited to: feature and subtype, population, and capital status.", + "maximum": 100, + "minimum": 1, + "title": "Prominence", + "type": "integer" + }, + "sort_key": { + "description": "Integer indicating the recommended order in which to draw features.\n\nFeatures with a lower number should be drawn \"in front\" of features with a higher\nnumber.", + "maximum": 255, + "minimum": 0, + "title": "Sort Key", + "type": "integer" + } + }, + "title": "CartographicHints", + "type": "object" + }, + "GeographicAreaClass": { + "description": "Classification of the geographic area feature.", + "enum": [ + "colloquial", + "postal" + ], + "title": "GeographicAreaClass", + "type": "string" + }, + "GeographicAreaSubtype": { + "description": "The type of geographic area feature.\n\n- functional: Regions defined by functional characteristics or usage patterns\n (e.g., metropolitan areas, economic zones).\n\n- cultural: Regions defined by cultural identity, colloquial usage, or shared\n cultural characteristics (e.g., \"the Bay Area\", \"New England\", \"Silicon Valley\").", + "enum": [ + "functional", + "cultural" + ], + "title": "GeographicAreaSubtype", + "type": "string" + }, + "NameRule": { + "additionalProperties": false, + "description": "A rule that can be evaluated to determine the name in advanced scenarios.\n\nName rules are used for cases where the primary name is not sufficient; the common name is not\nthe right fit for the use case and another variant is needed; or where the name only applies in\ncertain specific circumstances.\n\nExamples might include:\n- An official, alternate, or short name.\n- A name that only applies to part of a linear path like a road segment (geometric range\n scoping).\n- A name that only applies to the left or right side of a linear path like a road segment (side\n scoping).\n- A name that is only accepted by some political perspectives.", + "properties": { + "between": { + "description": "The linearly-referenced sub-segment of the geometry, specified as a range (pair) of percentage displacements from the start of the geometry, that the containing NameRule applies to.", + "items": { + "maximum": 1.0, + "minimum": 0.0, + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "title": "Between", + "type": "array" + }, + "language": { + "description": "The language in which the name `value` is specified, if known, as an IETF BCP 47\nlanguage tag.", + "pattern": "^(?:(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}?)|(?:[A-Za-z]{4,8}))(?:-[A-Za-z]{4})?(?:-[A-Za-z]{2}|[0-9]{3})?(?:-(?:[A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*(?:-[A-WY-Za-wy-z0-9](?:-[A-Za-z0-9]{2,8})+)*$", + "title": "Language", + "type": "string" + }, + "perspectives": { + "$ref": "#/$defs/Perspectives", + "description": "Political perspectives from which a named feature is viewed." + }, + "side": { + "$ref": "#/$defs/Side", + "description": "The side, either left or right, that the containing NameRule applies to." + }, + "value": { + "description": "The actual name value.", + "minLength": 1, + "pattern": "^(\\S.*)?\\S$", + "title": "Value", + "type": "string" + }, + "variant": { + "$ref": "#/$defs/NameVariant", + "description": "The name variant for this name rule." + } + }, + "required": [ + "value", + "variant" + ], + "title": "NameRule", + "type": "object" + }, + "NameVariant": { + "description": "Name variant used in a `NameRule`.", + "enum": [ + "common", + "official", + "alternate", + "short" + ], + "title": "NameVariant", + "type": "string" + }, + "Names": { + "additionalProperties": false, + "description": "Multilingual names container.", + "properties": { + "common": { + "additionalProperties": false, + "patternProperties": { + "^(?:(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}?)|(?:[A-Za-z]{4,8}))(?:-[A-Za-z]{4})?(?:-[A-Za-z]{2}|[0-9]{3})?(?:-(?:[A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*(?:-[A-WY-Za-wy-z0-9](?:-[A-Za-z0-9]{2,8})+)*$": { + "description": "String with no leading/trailing whitespace", + "pattern": "^(\\S.*)?\\S$", + "type": "string" + } + }, + "propertyNames": { + "description": "IETF BCP-47 language tag" + }, + "title": "Common", + "type": "object" + }, + "primary": { + "description": "The most commonly used name.", + "minLength": 1, + "pattern": "^(\\S.*)?\\S$", + "title": "Primary", + "type": "string" + }, + "rules": { + "description": "Rules for names that cannot be specified in the simple common names property. These rules can cover other name variants such as official, alternate, and short; and they can optionally include geometric scoping (linear referencing) and side-of-road scoping for complex cases.", + "items": { + "$ref": "#/$defs/NameRule" + }, + "title": "Rules", + "type": "array" + } + }, + "required": [ + "primary" + ], + "title": "Names", + "type": "object" + }, + "PerspectiveMode": { + "description": "Perspective mode for disputed names.", + "enum": [ + "accepted_by", + "disputed_by" + ], + "title": "PerspectiveMode", + "type": "string" + }, + "Perspectives": { + "additionalProperties": false, + "description": "Political perspectives container.", + "properties": { + "countries": { + "description": "Countries holding the given mode of perspective.", + "items": { + "description": "ISO 3166-1 alpha-2 country code", + "maxLength": 2, + "minLength": 2, + "pattern": "^[A-Z]{2}$", + "type": "string" + }, + "minItems": 1, + "title": "Countries", + "type": "array", + "uniqueItems": true + }, + "mode": { + "$ref": "#/$defs/PerspectiveMode", + "description": "Whether the perspective holder accepts or disputes this name." + } + }, + "required": [ + "mode", + "countries" + ], + "title": "Perspectives", + "type": "object" + }, + "Side": { + "description": "The side, left or right, on which something appears relative to a facing or heading direction\n(*e.g.*, the side of a road relative to the road orientation), or relative to the direction of\ntravel of a person or vehicle.", + "enum": [ + "left", + "right" + ], + "title": "Side", + "type": "string" + }, + "SourceItem": { + "additionalProperties": false, + "description": "Specifies the source of the data used for a feature or one of its properties.", + "properties": { + "between": { + "description": "The linearly-referenced sub-segment of the geometry, specified as a range (pair) of percentage displacements from the start of the geometry, that the containing SourceItem applies to.", + "items": { + "maximum": 1.0, + "minimum": 0.0, + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "title": "Between", + "type": "array" + }, + "confidence": { + "description": "Confidence value from the source dataset.\n\nThis is a value between 0.0 and 1.0 and is particularly relevant for ML-derived data.", + "maximum": 1.0, + "minimum": 0.0, + "title": "Confidence", + "type": "number" + }, + "dataset": { + "description": "Name of the dataset where the source data can be found.", + "title": "Dataset", + "type": "string" + }, + "license": { + "description": "Source data license name.\n\nThis should be a valid SPDX license identifier when available.\n\nIf omitted, contact the data provider for more license information.", + "pattern": "^(\\S.*)?\\S$", + "title": "License", + "type": "string" + }, + "property": { + "description": "A JSON Pointer identifying the property (field) that this source information applies to.\n\nThe root document value `\"\"` indicates that this source information applies to the\nentire feature, excepting properties (fields) for which a dedicated source information\nrecord exists.\n\nAny other JSON Pointer apart from `\"\"` indicates that this source record provides\ndedicated source information for the property at the path in the JSON Pointer. As an\nexample, the value `\"/names/common/en\"` indicates that the source information applies to\nthe English common name of a named feature, while the value `\"/geometry\"` indicates that\nit applies to the feature geometry.", + "title": "Property", + "type": "string" + }, + "record_id": { + "description": "Identifies the specific record within the source dataset where the source data can\nbe found.\n\nThe format of record identifiers is dataset-specific.", + "title": "Record Id", + "type": "string" + }, + "update_time": { + "description": "Last update time of the source data record.", + "format": "date-time", + "title": "Update Time", + "type": "string" + } + }, + "required": [ + "property", + "dataset" + ], + "title": "SourceItem", + "type": "object" + } + }, + "additionalProperties": false, + "description": "Geographic area features represent functional or cultural regions that may span across\nmultiple administrative divisions.\n\nThese regions capture areas defined by shared characteristics, usage patterns, or\ncultural identity rather than formal administrative boundaries.\n\nExamples include metropolitan areas (functional) or colloquial regions like \"the Bay\nArea\" or \"New England\" (cultural).", + "properties": { + "bbox": { + "description": "An optional bounding box for the feature", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "title": "Bbox", + "type": "array" + }, + "geometry": { + "description": "Geography geometry MUST be a Polygon or MultiPolygon as defined by GeoJSON schema. The geometry is constructed from associated divisions or available sources.", + "oneOf": [ + { + "properties": { + "bbox": { + "items": { + "type": "number" + }, + "minItems": 4, + "type": "array" + }, + "coordinates": { + "items": { + "items": { + "items": { + "items": { + "type": "number" + }, + "maxItems": 3, + "minItems": 2, + "type": "array" + }, + "minItems": 4, + "type": "array" + }, + "minItems": 1, + "type": "array" + }, + "minItems": 1, + "type": "array" + }, + "type": { + "const": "MultiPolygon", + "type": "string" + } + }, + "required": [ + "type", + "coordinates" + ], + "type": "object" + }, + { + "properties": { + "bbox": { + "items": { + "type": "number" + }, + "minItems": 4, + "type": "array" + }, + "coordinates": { + "items": { + "items": { + "items": { + "type": "number" + }, + "maxItems": 3, + "minItems": 2, + "type": "array" + }, + "minItems": 4, + "type": "array" + }, + "minItems": 1, + "type": "array" + }, + "type": { + "const": "Polygon", + "type": "string" + } + }, + "required": [ + "type", + "coordinates" + ], + "type": "object" + } + ], + "title": "Geometry" + }, + "id": { + "description": "A feature ID. This may be an ID associated with the Global Entity Reference System (GERS) if\u2014and-only-if the feature represents an entity that is part of GERS.", + "minLength": 1, + "pattern": "^\\S+$", + "title": "Id", + "type": "string" + }, + "properties": { + "additionalProperties": false, + "not": { + "required": [ + "id", + "bbox", + "geometry" + ] + }, + "patternProperties": { + "^ext_.*$": { + "description": "Additional top-level properties are allowed if prefixed by `ext_`.\n\nThis feature is a on a deprecation path and will be removed once the schema is\nfully migrated to Pydantic." + } + }, + "properties": { + "associated_division_ids": { + "description": "Optional list of division IDs representing the set of divisions that make up this geography region. This property links the geography to the underlying administrative divisions it encompasses or relates to. May be null if the region cannot be precisely mapped to specific administrative divisions.", + "items": { + "description": "A unique identifier", + "minLength": 1, + "pattern": "^\\S+$", + "type": "string" + }, + "minLength": 1, + "title": "Associated Division Ids", + "type": "array", + "uniqueItems": true + }, + "cartography": { + "$ref": "#/$defs/CartographicHints", + "title": "cartography" + }, + "class": { + "$ref": "#/$defs/GeographicAreaClass", + "description": "Classification of the geography feature. Colloquial class is only allowed for cultural subtype. Postal class is only allowed for functional subtype." + }, + "names": { + "$ref": "#/$defs/Names" + }, + "population": { + "description": "Optional population represented in the region, if inferable from associated divisions or available sources.", + "maximum": 2147483647, + "minimum": 0, + "title": "Population", + "type": "integer" + }, + "sources": { + "description": "Information about the source data used to assemble the feature.", + "items": { + "$ref": "#/$defs/SourceItem" + }, + "minItems": 1, + "title": "Sources", + "type": "array", + "uniqueItems": true + }, + "subtype": { + "$ref": "#/$defs/GeographicAreaSubtype", + "description": "The type of geography feature.\n \n- functional: Regions defined by functional characteristics or usage patterns (e.g., metropolitan areas, economic zones).\n\n- cultural: Regions defined by cultural identity, colloquial usage, or shared cultural characteristics (e.g., \"the Bay Area\", \"New England\", \"Silicon Valley\")." + }, + "theme": { + "const": "divisions", + "title": "Theme", + "type": "string" + }, + "type": { + "const": "geographic_area", + "title": "Type", + "type": "string" + }, + "version": { + "description": "", + "maximum": 2147483647, + "minimum": 0, + "title": "Version", + "type": "integer" + } + }, + "required": [ + "names", + "theme", + "type", + "version", + "subtype", + "class" + ], + "type": "object" + }, + "type": { + "const": "Feature", + "type": "string" + } + }, + "required": [ + "type", + "id", + "geometry", + "properties" + ], + "title": "geographic_area", + "type": "object" +} \ No newline at end of file diff --git a/packages/overture-schema-divisions-theme/tests/test_geographic_area_json_schema_baseline.py b/packages/overture-schema-divisions-theme/tests/test_geographic_area_json_schema_baseline.py new file mode 100644 index 000000000..6687d9faf --- /dev/null +++ b/packages/overture-schema-divisions-theme/tests/test_geographic_area_json_schema_baseline.py @@ -0,0 +1,32 @@ +"""Baseline JSON Schema tests for geographic area type.""" + +import json +import os + +from overture.schema.divisions import GeographicArea +from overture.schema.system.json_schema import json_schema + + +def test_geographic_area_json_schema_baseline() -> None: + """Test that GeographicArea generates consistent JSON Schema (baseline comparison).""" + schema = json_schema(GeographicArea) + + # Path to baseline file + baseline_file = os.path.join( + os.path.dirname(__file__), "geographic_area_baseline_schema.json" + ) + + # If baseline doesn't exist, create it + if not os.path.exists(baseline_file): + with open(baseline_file, "w") as f: + json.dump(schema, f, indent=2, sort_keys=True) + + # Load baseline and compare + with open(baseline_file) as f: + baseline_schema = json.load(f) + + # Compare the generated schema with the baseline + assert schema == baseline_schema, ( + "Generated JSON Schema differs from baseline. " + "If this change is intentional, delete the baseline file to regenerate it." + ) diff --git a/schema/defs.yaml b/schema/defs.yaml index a20de9047..551aa59bd 100644 --- a/schema/defs.yaml +++ b/schema/defs.yaml @@ -90,6 +90,7 @@ description: Common schema definitions shared by all themes - division - division_area - division_boundary + - geographic_area - infrastructure - land - land_cover diff --git a/schema/divisions/geographic_area.yaml b/schema/divisions/geographic_area.yaml new file mode 100644 index 000000000..905cd19aa --- /dev/null +++ b/schema/divisions/geographic_area.yaml @@ -0,0 +1,99 @@ +--- +"$schema": https://json-schema.org/draft/2020-12/schema +title: geographic_area +description: + Geographic area features represent functional or cultural regions that may + span across multiple administrative divisions. These regions capture + areas defined by shared characteristics, usage patterns, or cultural + identity rather than formal administrative boundaries. + + Examples include metropolitan areas (functional) or colloquial regions + like "the Bay Area" or "New England" (cultural). +type: object +properties: # JSON Schema: Top-level object properties. + id: { "$ref": ../defs.yaml#/$defs/propertyDefinitions/id } + geometry: + description: + Geography geometry MUST be a Polygon or MultiPolygon as defined + by GeoJSON schema. The geometry is constructed from associated + divisions or available sources. + unevaluatedProperties: false + oneOf: + - "$ref": https://geojson.org/schema/Polygon.json + - "$ref": https://geojson.org/schema/MultiPolygon.json + properties: # GeoJSON: top-level object 'properties' property. + unevaluatedProperties: false + required: [names, subtype, class] + allOf: + - "$ref": ../defs.yaml#/$defs/propertyContainers/overtureFeaturePropertiesContainer + - "$ref": ../defs.yaml#/$defs/propertyContainers/namesContainer + - "$ref": ../defs.yaml#/$defs/propertyContainers/cartographyContainer + - if: + properties: + class: { const: colloquial } + then: + properties: + subtype: { const: cultural } + - if: + properties: + class: { const: postal } + then: + properties: + subtype: { const: functional } + properties: # JSON Schema: properties within GeoJSON top-level object 'properties' property + subtype: + description: + The type of geography feature. + + - functional: Regions defined by functional characteristics or + usage patterns (e.g., metropolitan areas, economic zones). + + - cultural: Regions defined by cultural identity, colloquial + usage, or shared cultural characteristics (e.g., "the Bay Area", + "New England", "Silicon Valley"). + type: string + enum: + - functional # Region defined by functional characteristics + # or usage patterns. + + - cultural # Region defined by cultural identity or + # colloquial usage. + class: + description: + Classification of the geography feature. + + - colloquial: Colloquial regions are informal, culturally defined, + or commonly referenced areas that do not correspond to official + administrative boundaries. Unlike countries, states, counties, or + cities—whose boundaries are legally defined—colloquial regions + evolve from cultural, historical, economic, or linguistic identity. + Examples include South Florida, East Asia, and California Wine Country. + Only applicable to cultural subtype. + + - postal: Postal code regions used for mail delivery and routing. + Examples include US ZIP codes, UK postcodes, and Canadian postal codes. + Only applicable to functional subtype. + type: string + enum: + - colloquial # Informal, culturally defined regions without + # official administrative boundaries. + + - postal # Postal code regions for mail delivery. + associated_division_ids: + description: + Optional list of division IDs representing the set of divisions + that make up this geography region. This property links the + geography to the underlying administrative divisions it + encompasses or relates to. May be null if the region cannot be + precisely mapped to specific administrative divisions. + type: array + minItems: 1 + uniqueItems: true + items: { "$ref": "../defs.yaml#/$defs/propertyDefinitions/id" } + population: + description: + Optional population represented in the region, if inferable from + associated divisions or available sources. + type: integer + minimum: 0 + wikidata: { "$ref": "../defs.yaml#/$defs/propertyDefinitions/wikidata" } diff --git a/schema/schema.yaml b/schema/schema.yaml index df59e6529..b01e56649 100644 --- a/schema/schema.yaml +++ b/schema/schema.yaml @@ -106,6 +106,14 @@ oneOf: type: { enum: [division_area] } then: { "$ref": divisions/division_area.yaml } else: { propertyNames: false } + - if: + properties: + properties: + properties: + theme: { enum: [divisions] } + type: { enum: [geographic_area] } + then: { "$ref": divisions/geographic_area.yaml } + else: { propertyNames: false } - if: properties: properties: From 6c208a6db9f8cfc99ccbd1e1c759872597840a4f Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Bachin Krishnarao Date: Mon, 1 Dec 2025 16:44:48 -0800 Subject: [PATCH 2/6] Added docs --- .../reference/divisions/geographic_area.mdx | 13 ++++--- schema/divisions/geographic_area.yaml | 34 +++++++++---------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/docs/schema/reference/divisions/geographic_area.mdx b/docs/schema/reference/divisions/geographic_area.mdx index 8055d4f7a..433565fef 100644 --- a/docs/schema/reference/divisions/geographic_area.mdx +++ b/docs/schema/reference/divisions/geographic_area.mdx @@ -53,9 +53,10 @@ Geographic areas are categorized into two main subtypes: Functional regions are defined by functional characteristics or usage patterns, such as metropolitan areas, economic zones, or postal code regions. These areas serve specific operational or administrative purposes. -**Classes:** -- `postal` - Postal code regions used for mail delivery and routing (e.g., US ZIP codes, UK postcodes, Canadian postal codes) - +

Classes:

+ @@ -70,8 +71,10 @@ Functional regions are defined by functional characteristics or usage patterns, Cultural regions are defined by cultural identity, colloquial usage, or shared cultural characteristics. These areas reflect how people commonly refer to regions in everyday language. -**Classes:** -- `colloquial` - Colloquial regions are informal, culturally defined, or commonly referenced areas that do not correspond to official administrative boundaries. Unlike countries, states, counties, or cities—whose boundaries are legally defined—colloquial regions evolve from cultural, historical, economic, or linguistic identity. Examples include South Florida, East Asia, and California Wine Country. +

Classes:

+
    +
  • colloquial - Colloquial regions are informal, culturally defined, or commonly referenced areas that do not correspond to official administrative boundaries. Unlike countries, states, counties, or cities—whose boundaries are legally defined—colloquial regions evolve from cultural, historical, economic, or linguistic identity. Examples include South Florida, East Asia, and California Wine Country.
  • +
diff --git a/schema/divisions/geographic_area.yaml b/schema/divisions/geographic_area.yaml index 905cd19aa..918aa8cf6 100644 --- a/schema/divisions/geographic_area.yaml +++ b/schema/divisions/geographic_area.yaml @@ -42,15 +42,15 @@ properties: # JSON Schema: Top-level object properties. subtype: { const: functional } properties: # JSON Schema: properties within GeoJSON top-level object 'properties' property subtype: - description: + description: >- The type of geography feature. - - functional: Regions defined by functional characteristics or - usage patterns (e.g., metropolitan areas, economic zones). + functional: Regions defined by functional characteristics or + usage patterns (e.g., metropolitan areas, economic zones). - - cultural: Regions defined by cultural identity, colloquial - usage, or shared cultural characteristics (e.g., "the Bay Area", - "New England", "Silicon Valley"). + cultural: Regions defined by cultural identity, colloquial + usage, or shared cultural characteristics (e.g., "the Bay Area", + "New England", "Silicon Valley"). type: string enum: - functional # Region defined by functional characteristics @@ -59,20 +59,20 @@ properties: # JSON Schema: Top-level object properties. - cultural # Region defined by cultural identity or # colloquial usage. class: - description: + description: >- Classification of the geography feature. - - colloquial: Colloquial regions are informal, culturally defined, - or commonly referenced areas that do not correspond to official - administrative boundaries. Unlike countries, states, counties, or - cities—whose boundaries are legally defined—colloquial regions - evolve from cultural, historical, economic, or linguistic identity. - Examples include South Florida, East Asia, and California Wine Country. - Only applicable to cultural subtype. + colloquial: Colloquial regions are informal, culturally defined, + or commonly referenced areas that do not correspond to official + administrative boundaries. Unlike countries, states, counties, or + cities—whose boundaries are legally defined—colloquial regions + evolve from cultural, historical, economic, or linguistic identity. + Examples include South Florida, East Asia, and California Wine Country. + Only applicable to cultural subtype. - - postal: Postal code regions used for mail delivery and routing. - Examples include US ZIP codes, UK postcodes, and Canadian postal codes. - Only applicable to functional subtype. + postal: Postal code regions used for mail delivery and routing. + Examples include US ZIP codes, UK postcodes, and Canadian postal codes. + Only applicable to functional subtype. type: string enum: - colloquial # Informal, culturally defined regions without From b2a39ac1367f4cc00d941dd26ca25ad4edf1b1a0 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Bachin Krishnarao Date: Mon, 1 Dec 2025 19:06:41 -0800 Subject: [PATCH 3/6] Fix examples and counterexamples for geographic_area --- .../geographic_area/bad-geometry-type.yaml | 4 +- .../geographic_area/bad-subtype.yaml | 1 + .../colloquial-functional-mismatch.yaml | 2 +- .../missing-class-cultural.yaml | 2 +- .../missing-class-functional.yaml | 2 +- .../geographic_area/negative-population.yaml | 2 +- .../postal-cultural-mismatch.yaml | 2 +- .../functional_metro_area.yaml | 47 ------------------- 8 files changed, 9 insertions(+), 53 deletions(-) delete mode 100644 examples/divisions/geographic_area/functional_metro_area.yaml diff --git a/counterexamples/divisions/geographic_area/bad-geometry-type.yaml b/counterexamples/divisions/geographic_area/bad-geometry-type.yaml index 01f101a73..d8dda06cb 100644 --- a/counterexamples/divisions/geographic_area/bad-geometry-type.yaml +++ b/counterexamples/divisions/geographic_area/bad-geometry-type.yaml @@ -9,7 +9,9 @@ properties: type: geographic_area version: 0 subtype: functional + class: postal names: primary: A geography with invalid Point geometry (must be Polygon or MultiPolygon). ext_expected_errors: - - "geometry type must be Polygon or MultiPolygon" + - "/properties/type/enum]: value must be 'Polygon'" + - "/properties/type/enum]: value must be 'MultiPolygon'" diff --git a/counterexamples/divisions/geographic_area/bad-subtype.yaml b/counterexamples/divisions/geographic_area/bad-subtype.yaml index 5b4aa5241..591b4402d 100644 --- a/counterexamples/divisions/geographic_area/bad-subtype.yaml +++ b/counterexamples/divisions/geographic_area/bad-subtype.yaml @@ -9,6 +9,7 @@ properties: type: geographic_area version: 0 subtype: administrative + class: colloquial names: primary: A geography with an invalid subtype. ext_expected_errors: diff --git a/counterexamples/divisions/geographic_area/colloquial-functional-mismatch.yaml b/counterexamples/divisions/geographic_area/colloquial-functional-mismatch.yaml index f9d6084e3..d066c9955 100644 --- a/counterexamples/divisions/geographic_area/colloquial-functional-mismatch.yaml +++ b/counterexamples/divisions/geographic_area/colloquial-functional-mismatch.yaml @@ -13,4 +13,4 @@ properties: names: primary: A functional geography with colloquial class (only allowed for cultural). ext_expected_errors: - - "colloquial class is only allowed for cultural subtype" + - "value must be 'cultural'" diff --git a/counterexamples/divisions/geographic_area/missing-class-cultural.yaml b/counterexamples/divisions/geographic_area/missing-class-cultural.yaml index bb71f845b..51900edfd 100644 --- a/counterexamples/divisions/geographic_area/missing-class-cultural.yaml +++ b/counterexamples/divisions/geographic_area/missing-class-cultural.yaml @@ -12,4 +12,4 @@ properties: names: primary: A geography missing required class property. ext_expected_errors: - - "required property 'class' is missing" + - "missing property 'class'" diff --git a/counterexamples/divisions/geographic_area/missing-class-functional.yaml b/counterexamples/divisions/geographic_area/missing-class-functional.yaml index 6eec90fe5..b759395dd 100644 --- a/counterexamples/divisions/geographic_area/missing-class-functional.yaml +++ b/counterexamples/divisions/geographic_area/missing-class-functional.yaml @@ -12,4 +12,4 @@ properties: names: primary: A functional geography missing required class property. ext_expected_errors: - - "required property 'class' is missing" + - "missing property 'class'" diff --git a/counterexamples/divisions/geographic_area/negative-population.yaml b/counterexamples/divisions/geographic_area/negative-population.yaml index da37a8848..09e3f9bca 100644 --- a/counterexamples/divisions/geographic_area/negative-population.yaml +++ b/counterexamples/divisions/geographic_area/negative-population.yaml @@ -14,4 +14,4 @@ properties: primary: A geography with negative population. population: -1000 ext_expected_errors: - - "population must be greater than or equal to 0" + - "minimum: got -1,000, want 0" diff --git a/counterexamples/divisions/geographic_area/postal-cultural-mismatch.yaml b/counterexamples/divisions/geographic_area/postal-cultural-mismatch.yaml index 5105c9dbb..60998a533 100644 --- a/counterexamples/divisions/geographic_area/postal-cultural-mismatch.yaml +++ b/counterexamples/divisions/geographic_area/postal-cultural-mismatch.yaml @@ -13,4 +13,4 @@ properties: names: primary: A cultural geography with postal class (only allowed for functional). ext_expected_errors: - - "postal class is only allowed for functional subtype" + - "value must be 'functional'" diff --git a/examples/divisions/geographic_area/functional_metro_area.yaml b/examples/divisions/geographic_area/functional_metro_area.yaml deleted file mode 100644 index a4fc2c52b..000000000 --- a/examples/divisions/geographic_area/functional_metro_area.yaml +++ /dev/null @@ -1,47 +0,0 @@ ---- -id: example:geography:functional:metro_area_tokyo -type: Feature -geometry: - type: Polygon - coordinates: [ - [ - [139.0, 35.0], - [140.5, 35.0], - [140.5, 36.5], - [139.0, 36.5], - [139.0, 35.0] - ] - ] -bbox: [139.0, 35.0, 140.5, 36.5] -properties: - theme: divisions - type: geographic_area - version: 0 - subtype: functional - names: - primary: Tokyo Metropolitan Area - common: - en: Greater Tokyo Area - ja: 東京大都市圏 - ja-Latn: Tōkyō Daitoshi-ken - cartography: - prominence: 90 - min_zoom: 4 - max_zoom: 11 - associated_division_ids: - - example:division:locality:tokyo - - example:division:locality:yokohama - - example:division:locality:kawasaki - - example:division:locality:saitama - - example:division:locality:chiba - - example:division:region:tokyo_prefecture - - example:division:region:kanagawa_prefecture - - example:division:region:saitama_prefecture - - example:division:region:chiba_prefecture - population: 37400000 - wikidata: Q208403 - sources: - - property: "" - dataset: OpenStreetMap - record_id: relation/1543125 - update_time: "2023-10-20T14:35:00Z" From d7d2abf66d7316380687b5310a50efc9c2c98b72 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Bachin Krishnarao Date: Mon, 1 Dec 2025 19:15:07 -0800 Subject: [PATCH 4/6] Updated comments --- docs/schema/reference/divisions/geographic_area.mdx | 2 +- .../overture/schema/divisions/geographic_area/enums.py | 4 ++-- .../schema/divisions/geographic_area/models.py | 8 ++++---- schema/divisions/geographic_area.yaml | 10 +++++----- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/schema/reference/divisions/geographic_area.mdx b/docs/schema/reference/divisions/geographic_area.mdx index 433565fef..d0c85b49b 100644 --- a/docs/schema/reference/divisions/geographic_area.mdx +++ b/docs/schema/reference/divisions/geographic_area.mdx @@ -51,7 +51,7 @@ Geographic areas are categorized into two main subtypes: -Functional regions are defined by functional characteristics or usage patterns, such as metropolitan areas, economic zones, or postal code regions. These areas serve specific operational or administrative purposes. +Functional regions are defined by functional characteristics or usage patterns, such as postal code regions or economic zones. These areas serve specific operational or administrative purposes.

Classes:

    diff --git a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/enums.py b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/enums.py index 8cca330c0..3a0977fea 100644 --- a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/enums.py +++ b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/enums.py @@ -8,10 +8,10 @@ class GeographicAreaSubtype(str, Enum): The type of geographic area feature. - functional: Regions defined by functional characteristics or usage patterns - (e.g., metropolitan areas, economic zones). + (e.g., postal codes, economic zones). - cultural: Regions defined by cultural identity, colloquial usage, or shared - cultural characteristics (e.g., "the Bay Area", "New England", "Silicon Valley"). + cultural characteristics (e.g., "East Asia", "California Wine Country"). """ FUNCTIONAL = "functional" diff --git a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/models.py b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/models.py index 99fbd5cbc..c9601dbc0 100644 --- a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/models.py +++ b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/models.py @@ -31,8 +31,8 @@ class GeographicArea( These regions capture areas defined by shared characteristics, usage patterns, or cultural identity rather than formal administrative boundaries. - Examples include metropolitan areas (functional) or colloquial regions like "the Bay - Area" or "New England" (cultural). + Examples include postal code regions (functional) or colloquial regions like "East Asia" + or "California Wine Country" (cultural). """ model_config = ConfigDict(title="geographic_area") @@ -54,9 +54,9 @@ class GeographicArea( Field( description="""The type of geography feature. -- functional: Regions defined by functional characteristics or usage patterns (e.g., metropolitan areas, economic zones). +- functional: Regions defined by functional characteristics or usage patterns (e.g., postal codes, economic zones). -- cultural: Regions defined by cultural identity, colloquial usage, or shared cultural characteristics (e.g., "the Bay Area", "New England", "Silicon Valley").""" +- cultural: Regions defined by cultural identity, colloquial usage, or shared cultural characteristics (e.g., "East Asia", "California Wine Country").""" ), ] diff --git a/schema/divisions/geographic_area.yaml b/schema/divisions/geographic_area.yaml index 918aa8cf6..1b0447a1e 100644 --- a/schema/divisions/geographic_area.yaml +++ b/schema/divisions/geographic_area.yaml @@ -7,8 +7,8 @@ description: areas defined by shared characteristics, usage patterns, or cultural identity rather than formal administrative boundaries. - Examples include metropolitan areas (functional) or colloquial regions - like "the Bay Area" or "New England" (cultural). + Examples include postal code regions (functional) or colloquial regions + like "East Asia" or "California Wine Country" (cultural). type: object properties: # JSON Schema: Top-level object properties. id: { "$ref": ../defs.yaml#/$defs/propertyDefinitions/id } @@ -46,11 +46,11 @@ properties: # JSON Schema: Top-level object properties. The type of geography feature. functional: Regions defined by functional characteristics or - usage patterns (e.g., metropolitan areas, economic zones). + usage patterns (e.g., postal codes, economic zones). cultural: Regions defined by cultural identity, colloquial - usage, or shared cultural characteristics (e.g., "the Bay Area", - "New England", "Silicon Valley"). + usage, or shared cultural characteristics (e.g., "East Asia", + "California Wine Country"). type: string enum: - functional # Region defined by functional characteristics From 9a89b360e558de8e010283296d3ba834c35e6825 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Bachin Krishnarao Date: Mon, 1 Dec 2025 19:49:45 -0800 Subject: [PATCH 5/6] Formatted the new files --- .../schema/divisions/geographic_area/enums.py | 4 ++-- .../schema/divisions/geographic_area/models.py | 14 ++++++++++---- .../tests/geographic_area_baseline_schema.json | 6 +++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/enums.py b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/enums.py index 3a0977fea..3c8b7ea33 100644 --- a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/enums.py +++ b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/enums.py @@ -6,10 +6,10 @@ class GeographicAreaSubtype(str, Enum): """ The type of geographic area feature. - + - functional: Regions defined by functional characteristics or usage patterns (e.g., postal codes, economic zones). - + - cultural: Regions defined by cultural identity, colloquial usage, or shared cultural characteristics (e.g., "East Asia", "California Wine Country"). """ diff --git a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/models.py b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/models.py index c9601dbc0..cd0792768 100644 --- a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/models.py +++ b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/models.py @@ -92,11 +92,17 @@ class GeographicArea( def validate_class_rules(self) -> "GeographicArea": """Validate class field rules.""" # Colloquial class only allowed for cultural subtype - if self.class_ == GeographicAreaClass.COLLOQUIAL and self.subtype != GeographicAreaSubtype.CULTURAL: + if ( + self.class_ == GeographicAreaClass.COLLOQUIAL + and self.subtype != GeographicAreaSubtype.CULTURAL + ): raise ValueError("colloquial class is only allowed for cultural subtype") - + # Postal class only allowed for functional subtype - if self.class_ == GeographicAreaClass.POSTAL and self.subtype != GeographicAreaSubtype.FUNCTIONAL: + if ( + self.class_ == GeographicAreaClass.POSTAL + and self.subtype != GeographicAreaSubtype.FUNCTIONAL + ): raise ValueError("postal class is only allowed for functional subtype") - + return self diff --git a/packages/overture-schema-divisions-theme/tests/geographic_area_baseline_schema.json b/packages/overture-schema-divisions-theme/tests/geographic_area_baseline_schema.json index 50ed49dc5..84c7015d2 100644 --- a/packages/overture-schema-divisions-theme/tests/geographic_area_baseline_schema.json +++ b/packages/overture-schema-divisions-theme/tests/geographic_area_baseline_schema.json @@ -46,7 +46,7 @@ "type": "string" }, "GeographicAreaSubtype": { - "description": "The type of geographic area feature.\n\n- functional: Regions defined by functional characteristics or usage patterns\n (e.g., metropolitan areas, economic zones).\n\n- cultural: Regions defined by cultural identity, colloquial usage, or shared\n cultural characteristics (e.g., \"the Bay Area\", \"New England\", \"Silicon Valley\").", + "description": "The type of geographic area feature.\n\n- functional: Regions defined by functional characteristics or usage patterns\n (e.g., postal codes, economic zones).\n\n- cultural: Regions defined by cultural identity, colloquial usage, or shared\n cultural characteristics (e.g., \"East Asia\", \"California Wine Country\").", "enum": [ "functional", "cultural" @@ -263,7 +263,7 @@ } }, "additionalProperties": false, - "description": "Geographic area features represent functional or cultural regions that may span across\nmultiple administrative divisions.\n\nThese regions capture areas defined by shared characteristics, usage patterns, or\ncultural identity rather than formal administrative boundaries.\n\nExamples include metropolitan areas (functional) or colloquial regions like \"the Bay\nArea\" or \"New England\" (cultural).", + "description": "Geographic area features represent functional or cultural regions that may span across\nmultiple administrative divisions.\n\nThese regions capture areas defined by shared characteristics, usage patterns, or\ncultural identity rather than formal administrative boundaries.\n\nExamples include postal code regions (functional) or colloquial regions like \"East Asia\"\nor \"California Wine Country\" (cultural).", "properties": { "bbox": { "description": "An optional bounding box for the feature", @@ -422,7 +422,7 @@ }, "subtype": { "$ref": "#/$defs/GeographicAreaSubtype", - "description": "The type of geography feature.\n \n- functional: Regions defined by functional characteristics or usage patterns (e.g., metropolitan areas, economic zones).\n\n- cultural: Regions defined by cultural identity, colloquial usage, or shared cultural characteristics (e.g., \"the Bay Area\", \"New England\", \"Silicon Valley\")." + "description": "The type of geography feature.\n \n- functional: Regions defined by functional characteristics or usage patterns (e.g., postal codes, economic zones).\n\n- cultural: Regions defined by cultural identity, colloquial usage, or shared cultural characteristics (e.g., \"East Asia\", \"California Wine Country\")." }, "theme": { "const": "divisions", From 34f23eaa59e31fedb07864d07ec7076f8c24554f Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Bachin Krishnarao Date: Mon, 1 Dec 2025 20:16:32 -0800 Subject: [PATCH 6/6] Fixed geographic_area models.py --- .../src/overture/schema/divisions/geographic_area/models.py | 2 +- .../tests/geographic_area_baseline_schema.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/models.py b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/models.py index cd0792768..51096c94b 100644 --- a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/models.py +++ b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/geographic_area/models.py @@ -53,7 +53,7 @@ class GeographicArea( GeographicAreaSubtype, Field( description="""The type of geography feature. - + - functional: Regions defined by functional characteristics or usage patterns (e.g., postal codes, economic zones). - cultural: Regions defined by cultural identity, colloquial usage, or shared cultural characteristics (e.g., "East Asia", "California Wine Country").""" diff --git a/packages/overture-schema-divisions-theme/tests/geographic_area_baseline_schema.json b/packages/overture-schema-divisions-theme/tests/geographic_area_baseline_schema.json index 84c7015d2..d5b22bcb2 100644 --- a/packages/overture-schema-divisions-theme/tests/geographic_area_baseline_schema.json +++ b/packages/overture-schema-divisions-theme/tests/geographic_area_baseline_schema.json @@ -422,7 +422,7 @@ }, "subtype": { "$ref": "#/$defs/GeographicAreaSubtype", - "description": "The type of geography feature.\n \n- functional: Regions defined by functional characteristics or usage patterns (e.g., postal codes, economic zones).\n\n- cultural: Regions defined by cultural identity, colloquial usage, or shared cultural characteristics (e.g., \"East Asia\", \"California Wine Country\")." + "description": "The type of geography feature.\n\n- functional: Regions defined by functional characteristics or usage patterns (e.g., postal codes, economic zones).\n\n- cultural: Regions defined by cultural identity, colloquial usage, or shared cultural characteristics (e.g., \"East Asia\", \"California Wine Country\")." }, "theme": { "const": "divisions",