Skip to content
🔵Entwurf (gut)62%
Vollständigkeit:
80%
Korrektheit:
75%
⏳ Noch nicht geprüft

Data Structure ​

Overview ​

This document describes the complete data structure of the municipalities system in p2d2. It includes TypeScript interfaces, OSM data structures, GeoJSON formats, and helper functions for managing municipalities data.

TypeScript Interfaces ​

KommuneData Interface ​

typescript
// src/utils/kommune-utils.ts
export interface KommuneData {
  slug: string;
  title: string;
  osmAdminLevels?: number[];
  wp_name: string;
  osm_refinement?: string;
  colorStripe: string;
  map: {
    center: [number, number];
    zoom: number;
    projection: string;
    extent?: [number, number, number, number];
    extra?: Record<string, any>;
  };
  order?: number;
  icon?: string;
}

Field Documentation:

FieldTypeDescriptionExample
slugstringUnique municipality identifier"koeln", "bonn"
titlestringDisplay name of municipality"Cologne", "Bonn"
osmAdminLevelsnumber[]OSM Administrative Levels[6, 9, 10]
wp_namestringWikipedia article name"de-Köln"
osm_refinementstringOSM query refinement"boundary=administrative"
colorStripestringColor code for UI"#FF6900"
map.center[number, number]Map center [lon, lat][6.9603, 50.9375]
map.zoomnumberZoom level11
map.projectionstringCoordinate system"EPSG:25832"
map.extent[number, number, number, number]Map extent[6.8, 50.8, 7.2, 51.1]
map.extraRecord<string, any>Additional configuration{}
ordernumberSorting order10
iconstringIcon identifier"city"

OSM Polygon Interfaces ​

typescript
// src/types/admin-polygon.ts
export interface OSMPolygonFeature extends GeoJSON.Feature {
  id: number;
  properties: {
    name: string;
    admin_level: number;
    wikipedia?: string;
    wikidata?: string;
    type: string;
    timestamp: string;
    version: number;
    changeset: number;
    user: string;
    uid: number;
  };
  geometry: GeoJSON.Geometry;
}

export interface OSMPolygonCollection extends GeoJSON.FeatureCollection {
  features: OSMPolygonFeature[];
}

OSMPolygonFeature Properties:

PropertyTypeDescriptionExample
idnumberOSM element ID123456789
properties.namestringElement name"Cologne"
properties.admin_levelnumberAdmin level7
properties.wikipediastringWikipedia reference"de:Köln"
properties.wikidatastringWikidata reference"Q365"
properties.typestringElement type"boundary"
properties.timestampstringModification timestamp"2023-10-15T14:30:00Z"
properties.versionnumberVersion number5
properties.changesetnumberChangeset ID98765432
properties.userstringContributor name"osm_user"
properties.uidnumberContributor ID12345

Overpass API Response ​

typescript
export interface OverpassResponse {
  version: number;
  generator: string;
  osm3s: {
    timestamp_osm_base: string;
    copyright: string;
  };
  elements: Array<{
    type: "node" | "way" | "relation";
    id: number;
    tags?: Record<string, string>;
    geometry?: Array<{ lat: number; lon: number }>;
    members?: Array<{
      type: "node" | "way" | "relation";
      ref: number;
      role: string;
      geometry?: Array<{ lat: number; lon: number }>;
    }>;
  }>;
}

Overpass Element Structure:

FieldTypeDescription
type"node" | "way" | "relation"OSM element type
idnumberOSM element ID
tagsRecord<string, string>OSM tags (key-value pairs)
geometryArray<{lat, lon}>Geographic coordinates (only for nodes)
membersArray<Member>Relation members (only for relations)

Sync Interfaces ​

typescript
export interface SyncOptions {
  dryRun?: boolean;
  verbose?: boolean;
  force?: boolean;
  delayMs?: number;
}

export interface SyncResult {
  success: boolean;
  kommuneSlug: string;
  adminLevel: number;
  polygonsFound: number;
  polygonsInserted: number;
  error?: string;
  durationMs: number;
}

export interface WFSTTransactionResult {
  success: boolean;
  transactionId?: string;
  insertedCount?: number;
  error?: string;
  response?: Response;
}

export interface KommuneSyncStatus {
  slug: string;
  title: string;
  hasOSMData: boolean;
  adminLevels: number[];
  lastSync?: Date;
  polygonCount: number;
  status: "pending" | "synced" | "error" | "not_found";
}

OSM Data Structures ​

OSM Element Types ​

Node:

  • Single point with coordinates
  • Used for POIs (Points of Interest)

Way:

  • Line string or closed area
  • Used for roads, buildings, boundaries

Relation:

  • Collection of nodes, ways, and other relations
  • Used for complex structures like administrative boundaries

OSM Tags for Administrative Boundaries ​

Typical Tags:

json
{
  "boundary": "administrative",
  "admin_level": "7",
  "name": "Cologne",
  "wikipedia": "de:Köln",
  "wikidata": "Q365",
  "type": "boundary"
}

Important Boundary Tags:

  • boundary=administrative - Administrative boundary
  • admin_level=2-10 - Administrative level
  • name=* - Official name
  • wikipedia=* - Wikipedia reference
  • wikidata=* - Wikidata reference

GeoJSON Format ​

Feature Structure ​

json
{
  "type": "Feature",
  "id": 123456789,
  "properties": {
    "name": "Cologne",
    "admin_level": 7,
    "wikipedia": "de:Köln",
    "type": "boundary",
    "timestamp": "2023-10-15T14:30:00Z",
    "version": 5,
    "changeset": 98765432,
    "user": "osm_user",
    "uid": 12345
  },
  "geometry": {
    "type": "Polygon",
    "coordinates": [
      [
        [6.9112, 50.8756],
        [6.9115, 50.8758],
        [6.9120, 50.8760],
        [6.9112, 50.8756]
      ]
    ]
  }
}

FeatureCollection Structure ​

json
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "id": 123456789,
      "properties": { ... },
      "geometry": { ... }
    },
    {
      "type": "Feature",
      "id": 123456790,
      "properties": { ... },
      "geometry": { ... }
    }
  ]
}

Helper Functions ​

Kommune Utils ​

typescript
// src/utils/kommune-utils.ts

// Central configuration for default municipality
export const DEFAULT_KOMMUNE_SLUG = "koeln";

// Loads all municipalities from the collection
export async function getAllKommunen(): Promise<KommuneData[]> {
  const col = await loadCollection();
  return col
    .map(
      (k) =>
        ({
          slug: k.slug,
          title: k.data.title,
          osmAdminLevels: k.data.osmAdminLevels,
          wp_name: k.data.wp_name,
          osm_refinement: k.data.osm_refinement,
          colorStripe: k.data.colorStripe || "#FF6900",
          map: {
            center: k.data.map?.center || [0, 0],
            zoom: k.data.map?.zoom || 11,
            projection: k.data.map?.projection || "EPSG:3857",
            extent: k.data.map?.extent,
            extra: k.data.map?.extra,
          },
          order: k.data.order,
          icon: k.data.icon,
        }) as KommuneData,
    )
    .sort((a, b) => (a.order ?? 999) - (b.order ?? 999));
}

// Gets a specific municipality by slug
export async function getKommuneBySlug(
  slug: string,
): Promise<KommuneData | null> {
  const kommunen = await getAllKommunen();
  return kommunen.find((k) => k.slug === slug) || null;
}

// Checks if a municipality has valid OSM data
export function hasValidOSMData(kommune: KommuneData): boolean {
  return (
    !!kommune.wp_name &&
    !!kommune.osmAdminLevels &&
    kommune.osmAdminLevels.length > 0 &&
    !!kommune.map?.center
  );
}

// Gets municipalities ready for sync
export async function getKommunenReadyForSync(): Promise<KommuneData[]> {
  const kommunen = await getAllKommunen();
  return kommunen.filter(hasValidOSMData);
}

Function Documentation ​

getAllKommunen()

  • Purpose: Loads all municipalities from the content collection
  • Return: Promise<KommuneData[]>
  • Sorting: By order field (default: 999)
  • Fallbacks: Default values for missing map configuration

getKommuneBySlug(slug: string)

  • Parameter: slug - Unique municipality identifier
  • Return: Promise<KommuneData | null>
  • Usage: For detail views of individual municipalities

hasValidOSMData(kommune: KommuneData)

  • Parameter: kommune - Municipality data object
  • Return: boolean
  • Checks:
    • wp_name present
    • osmAdminLevels not empty
    • map.center present

getKommunenReadyForSync()

  • Purpose: Filters municipalities suitable for OSM sync
  • Return: Promise<KommuneData[]>
  • Usage: Before synchronization with OSM data

Data Flow Diagram ​

Simplified Representation ​

Content Collection → KommuneData → OSM Query → GeoJSON → WFS Service
     (Markdown)     (Interface)   (Overpass)    (Format)   (Geoserver)

Detailed Process ​

  1. Data Source: Markdown files in src/content/kommunen/
  2. Validation: Zod schema in content.config.ts
  3. Transformation: getAllKommunen() creates KommuneData[]
  4. OSM Query: Uses wp_name and osmAdminLevels for Overpass query
  5. GeoJSON Conversion: OSM data transformed to GeoJSON
  6. WFS Transaction: GeoJSON sent to Geoserver

Example Data ​

Complete Municipality Data ​

typescript
const koelnData: KommuneData = {
  slug: "koeln",
  title: "Cologne",
  osmAdminLevels: [6, 9, 10],
  wp_name: "de-Köln",
  osm_refinement: "boundary=administrative",
  colorStripe: "#FF6900",
  map: {
    center: [6.9603, 50.9375],
    zoom: 11,
    projection: "EPSG:25832",
    extent: [6.8, 50.8, 7.2, 51.1]
  },
  order: 10
};

OSM Overpass Query ​

xml
[out:json][timeout:25];
(
  relation["boundary"="administrative"]["admin_level"=7]["wikipedia"="de:Köln"];
);
out body;
>;
out skel qt;

GeoJSON Feature ​

json
{
  "type": "Feature",
  "id": 123456789,
  "properties": {
    "name": "Cologne",
    "admin_level": 7,
    "wikipedia": "de:Köln",
    "type": "boundary"
  },
  "geometry": {
    "type": "Polygon",
    "coordinates": [[...]]
  }
}

Best Practices ​

Data Consistency ​

  1. Consistent Naming: Use consistent slugs and titles
  2. Coordinate System: Always WGS84 for map.center
  3. Color Coding: Use the standard color palette
  4. OSM Levels: Only specify relevant administrative levels

Performance Optimizations ​

  1. Lazy Loading: Load municipality data only when needed
  2. Caching: Cache collection queries
  3. Validation: Validate frontmatter before build-time
  4. Tree Shaking: Only retrieve required fields

Extensibility ​

The data structures are modular and can be easily extended:

typescript
// Example extension
interface ExtendedKommuneData extends KommuneData {
  population?: number;
  area?: number;
  website?: string;
  contact?: {
    email: string;
    phone: string;
  };
}

The well-defined data structures form the foundation for a robust and extensible municipalities management system in p2d2.