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

Coordinate & CRS Utilities ​

Status: ✅ Fully documented

Overview ​

The crs.ts module provides comprehensive functions for coordinate transformation, projection management, and CRS switching in the p2d2 application. It is based on proj4 and OpenLayers for precise geographical calculations.

Main Functions ​

1. Projection Management ​

Supported Projections ​

typescript
// Standard projections
export const defaultCRS = "EPSG:3857";  // Web Mercator
export const wgs84 = "EPSG:4326";       // WGS84 Geographic

// Predefined UTM projections
const predefinedUtmDefs: Record<string, string> = {
  "EPSG:25832": "+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs",
  "EPSG:25833": "+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"
};

Register UTM Projections ​

typescript
/**
 * Registers a UTM projection dynamically
 * @param crs - EPSG code (e.g., "EPSG:25832")
 * @returns boolean - Success of registration
 */
export function registerUtm(crs: string): boolean

// Example
registerUtm("EPSG:25832"); // UTM Zone 32 for Germany

2. Validation Functions ​

Coordinate Validation ​

typescript
/**
 * Validates WGS84 coordinates [longitude, latitude]
 * @param coord - Coordinate to validate
 * @returns boolean - Validity of the coordinate
 */
export function isValidWgs84Coordinate(coord: any): boolean

// Example
isValidWgs84Coordinate([6.95, 50.94]); // ✅ true
isValidWgs84Coordinate([200, 50.94]);  // ❌ false (Longitude out of -180..180 range)

Extent Validation ​

typescript
/**
 * Validates WGS84 extent [minLon, minLat, maxLon, maxLat]
 * @param extent - Extent to validate
 * @returns boolean - Validity of the extent
 */
export function isValidWgs84Extent(extent: any): boolean

// Example
isValidWgs84Extent([6.8, 50.8, 7.1, 51.1]); // ✅ true
isValidWgs84Extent([6.8, 50.8, 5.0, 51.1]); // ❌ false (minLon > maxLon)

3. Transformation Functions ​

Coordinate Transformation ​

typescript
/**
 * Transforms coordinates from WGS84 to the target projection
 * @param center - WGS84 coordinate [lon, lat]
 * @param targetEpsg - Target projection (e.g., "EPSG:3857")
 * @returns number[] | null - Transformed coordinate
 */
export function transformCenterFromWgs84(
  center: number[], 
  targetEpsg: string
): number[] | null

// Example
const webMercatorCoord = transformCenterFromWgs84(
  [6.95, 50.94], 
  "EPSG:3857"
); // → [773592.4, 6574806.8]

Extent Transformation ​

typescript
/**
 * Transforms extent from WGS84 to the target projection
 * @param extent - WGS84 extent [minLon, minLat, maxLon, maxLat]
 * @param targetEpsg - Target projection
 * @returns number[] | null - Transformed extent
 */
export function transformExtentFromWgs84(
  extent: number[], 
  targetEpsg: string
): number[] | null

// Example
const cologneExtent = [6.8, 50.8, 7.1, 51.1];
const utmExtent = transformExtentFromWgs84(cologneExtent, "EPSG:25832");

4. Map View Management ​

Projection Change Preserving Scale ​

typescript
/**
 * Switches to the new projection while preserving the current scale
 * @param map - OpenLayers Map instance
 * @param targetEpsg - Target projection
 * @param animate - Enable animation (default: true)
 * @returns boolean - Success of the switch
 */
export function toNewViewPreservingScale(
  map: Map, 
  targetEpsg: string, 
  animate: boolean = true
): boolean

// Example
import { Map } from "ol";

const map = new Map({ /* Configuration */ });
const success = toNewViewPreservingScale(map, "EPSG:25832", true);

Practical Usage ​

Complete CRS Integration ​

typescript
import { 
  registerUtm, 
  transformCenterFromWgs84, 
  toNewViewPreservingScale 
} from '../utils/crs';
import { Map, View } from 'ol';

// 1. Register projection
registerUtm("EPSG:25832");

// 2. Transform coordinates
const center = [6.95, 50.94]; // Cologne in WGS84
const utmCenter = transformCenterFromWgs84(center, "EPSG:25832");

// 3. Initialize map with UTM projection
const map = new Map({
  view: new View({
    projection: "EPSG:25832",
    center: utmCenter,
    zoom: 12
  })
});

// 4. Perform projection switch
toNewViewPreservingScale(map, "EPSG:3857");

Error Handling ​

typescript
import { logger } from '../utils/logger';

try {
  const result = transformCenterFromWgs84([6.95, 50.94], "EPSG:25832");
  if (!result) {
    throw new Error("Coordinate transformation failed");
  }
  // Successful transformation
  console.log("Transformed coordinate:", result);
} catch (error) {
  logger.error("CRS Error:", error);
  // Fallback: Use Web Mercator
  const fallback = transformCenterFromWgs84([6.95, 50.94], "EPSG:3857");
}

Configuration ​

UTM Zones for Germany ​

typescript
// Important UTM zones for German municipalities
const germanUtmZones = {
  "EPSG:25832": "UTM Zone 32N (West and Central Germany)",
  "EPSG:25833": "UTM Zone 33N (East Germany)",
  "EPSG:31466": "Gauss-Krüger Zone 2",
  "EPSG:31467": "Gauss-Krüger Zone 3"
};

// Automatic registration
Object.keys(germanUtmZones).forEach(zone => {
  registerUtm(zone);
});

Projection Detection ​

typescript
/**
 * Checks if CRS is a UTM projection
 * @param crs - EPSG code
 * @returns boolean - True for UTM projections
 */
export function isUtm(crs: string): boolean

// Example
isUtm("EPSG:25832"); // ✅ true
isUtm("EPSG:3857");  // ❌ false

Performance Optimizations ​

1. Caching of Projections ​

typescript
// Projections are registered only once
const registeredProjections = new Set<string>();

function registerUtm(crs: string): boolean {
  if (registeredProjections.has(crs)) {
    return true; // Already registered
  }
  // ... Registration logic
  registeredProjections.add(crs);
}

2. Efficient Transformations ​

typescript
// Batch transformation for multiple coordinates
function transformMultipleCoordinates(
  coordinates: number[][], 
  targetEpsg: string
): (number[] | null)[] {
  return coordinates.map(coord => 
    transformCenterFromWgs84(coord, targetEpsg)
  );
}

Error Handling and Debugging ​

Common Error Scenarios ​

typescript
// 1. Invalid coordinates
const invalidCoord = [200, 100]; // Outside valid range
const result = transformCenterFromWgs84(invalidCoord, "EPSG:3857");
// → null (with warning in console)

// 2. Unregistered projection
const unknownCrs = "EPSG:99999";
const success = registerUtm(unknownCrs);
// → false (Projection cannot be registered)

// 3. Network error with proj4
// → Fallback to Web Mercator

Debugging Aids ​

typescript
// Extended logging for development
if (process.env.NODE_ENV === 'development') {
  console.log('[CRS-Debug]', {
    currentProjection: view.getProjection()?.getCode(),
    targetProjection: targetEpsg,
    transformationResult: result
  });
}

Dependencies ​

External Libraries ​

  • proj4 - Coordinate transformations
  • OpenLayers - Map and projection integration

Internal Dependencies ​

  • ../utils/logger - Consistent logging infrastructure
  • ../config/map-config - Standard configurations

Best Practices ​

1. Projection Choice ​

typescript
// ✅ Correct - Region-specific projections
const regionalCrs = getRegionalCrs(kommune.slug); // EPSG:25832 for Cologne

// ❌ Avoid - Always Web Mercator
const alwaysWebMercator = "EPSG:3857"; // Not optimal for all regions

2. Error Handling ​

typescript
// ✅ Correct - Explicit validation
if (!isValidWgs84Coordinate(center)) {
  throw new Error("Invalid coordinates for transformation");
}

// ❌ Avoid - Implicit assumptions
const result = transformCenterFromWgs84(center, targetEpsg); // No validation

3. Performance ​

typescript
// ✅ Correct - Use caching
const cachedTransformation = transformCenterFromWgs84(center, "EPSG:25832");

// ❌ Avoid - Repeated transformations
for (let i = 0; i < 1000; i++) {
  transformCenterFromWgs84(center, "EPSG:25832"); // Inefficient
}

These utilities form the basis for precise geographical calculations in p2d2 and ensure consistent coordinate transformations across all modules. ​