# Helsinki 3D City Model - Data Documentation

## Overview

Helsinki maintains one of the world's most detailed open 3D city models, available through the Helsinki Region Infoshare (HRI) platform.

## Data Sources

### City Information Model (CityGML)
- **URL:** https://hri.fi/data/en_GB/dataset/helsingin-3d-kaupunkimalli
- **Format:** CityGML 2.0
- **Levels of Detail:**
  - **LoD1:** Extruded building footprints (flat roofs)
  - **LoD2:** Detailed roof structures (essential for solar analysis)
- **License:** CC BY 4.0

### Download Options
1. **Web Viewer:** https://kartta.hel.fi/3d/
2. **Stadi3D Tool:** Interactive download by area
3. **WFS API:** https://kartta.hel.fi/3d/citydb-wfs/wfs
4. **Bulk Download:** OBJ, 3MX files from HRI

## CityGML Building Attributes

Relevant attributes for solar potential:

| Attribute | Description | Use |
|-----------|-------------|-----|
| `gml:id` | Unique building ID | Reference |
| `bldg:measuredHeight` | Height in meters | Shading calc |
| `bldg:roofType` | Flat, gabled, etc. | Panel layout |
| `bldg:function` | Building use type | Consumption est. |
| `bldg:yearOfConstruction` | Build year | Roof condition |
| `bldg:RoofSurface` | Roof geometry | Solar analysis |
| `bldg:WallSurface` | Wall geometry | Shading |

## Roof Surface Geometry

LoD2 includes detailed roof surfaces:
```xml
<bldg:RoofSurface gml:id="roof_12345">
  <bldg:lod2MultiSurface>
    <gml:MultiSurface>
      <gml:surfaceMember>
        <gml:Polygon>
          <gml:exterior>
            <gml:LinearRing>
              <!-- Coordinates in ETRS-TM35FIN (EPSG:3067) -->
              <gml:posList>...</gml:posList>
            </gml:LinearRing>
          </gml:exterior>
        </gml:Polygon>
      </gml:surfaceMember>
    </gml:MultiSurface>
  </bldg:lod2MultiSurface>
</bldg:RoofSurface>
```

## Coordinate System

- **CRS:** ETRS-TM35FIN (EPSG:3067)
- **Height System:** N2000
- **Transform to WGS84:** Use proj4 or similar

```javascript
// EPSG:3067 to WGS84 conversion
const proj4 = require('proj4');
proj4.defs('EPSG:3067', '+proj=utm +zone=35 +ellps=GRS80 +units=m +no_defs');
const [lon, lat] = proj4('EPSG:3067', 'EPSG:4326', [easting, northing]);
```

## Calculating Roof Orientation & Tilt

From roof polygon vertices, calculate:

1. **Normal Vector:** Cross product of polygon edges
2. **Tilt Angle:** `acos(normal.z)` in degrees
3. **Azimuth:** `atan2(normal.y, normal.x)` converted to compass bearing

```typescript
function calculateRoofOrientation(vertices: number[][]): { azimuth: number; tilt: number } {
  // Get two edge vectors
  const v1 = subtract(vertices[1], vertices[0]);
  const v2 = subtract(vertices[2], vertices[0]);
  
  // Normal vector
  const normal = cross(v1, v2);
  normalize(normal);
  
  // Tilt from horizontal (0° = flat, 90° = vertical)
  const tilt = Math.acos(normal[2]) * (180 / Math.PI);
  
  // Azimuth (0° = North, 90° = East, etc.)
  let azimuth = Math.atan2(normal[0], normal[1]) * (180 / Math.PI);
  if (azimuth < 0) azimuth += 360;
  
  return { azimuth, tilt };
}
```

## WFS API Usage

Query buildings in an area:

```bash
# Get buildings in bounding box
curl "https://kartta.hel.fi/3d/citydb-wfs/wfs?service=WFS&version=2.0.0&request=GetFeature&typeNames=bldg:Building&bbox=385000,6672000,386000,6673000,EPSG:3067&outputFormat=application/gml+xml"
```

## Data Size Estimates

| Area | Buildings | File Size |
|------|-----------|-----------|
| 1 km² | ~500 | ~50 MB CityGML |
| Helsinki center | ~10,000 | ~1 GB |
| All Helsinki | ~90,000 | ~10 GB |

## Recommended Approach

For our application:
1. **Pre-process:** Convert CityGML to optimized format (SQLite + simplified geometry)
2. **Tile:** Split city into grid tiles for on-demand loading
3. **Cache:** Store processed buildings locally
4. **Simplify:** Use LoD1 for distant buildings, LoD2 for selected

## Attribution

When using this data, include:
> "Data source: City of Helsinki, 3D City Model, CC BY 4.0"
