diff --git a/src/app/app.ts b/src/app/app.ts
index 2198e1e..5723740 100644
--- a/src/app/app.ts
+++ b/src/app/app.ts
@@ -1,11 +1,11 @@
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { Header } from './header/header';
-import { Map } from './map/map';
+import { OSMMap } from './map/map';
@Component({
selector: 'app-root',
- imports: [RouterOutlet, Header, Map],
+ imports: [RouterOutlet, Header, OSMMap],
templateUrl: './app.html',
styleUrl: './app.scss',
})
diff --git a/src/app/map/geojson.ts b/src/app/map/geojson.ts
index 4dec1c9..5435e85 100644
--- a/src/app/map/geojson.ts
+++ b/src/app/map/geojson.ts
@@ -4,8 +4,8 @@ import * as G from 'geojson';
export const buildingSytle = {
color: '#d62305', // Red border
weight: 2, // Border width
- fillColor: '#d62305', // Red fill
- fillOpacity: 0.1, // Semi-transparent fill
+ fillColor: '#d4caca', // Red fill
+ fillOpacity: 1, // Semi-transparent fill
};
// Example GeoJSON data
@@ -28,9 +28,8 @@ export const buildings: G.FeatureCollection = {
{
type: 'Feature',
properties: {
- name: 'Gebäude E',
+ name: 'E',
building: 'university',
- center: [8.39007, 49.015],
},
geometry: {
type: 'Polygon',
@@ -48,9 +47,8 @@ export const buildings: G.FeatureCollection = {
{
type: 'Feature',
properties: {
- name: 'Gebäude F',
+ name: 'F',
building: 'university',
- center: [8.3901208597194, 49.0156137375335],
},
geometry: {
type: 'Polygon',
diff --git a/src/app/map/map.html b/src/app/map/map.html
index 7778e6a..6395a5a 100644
--- a/src/app/map/map.html
+++ b/src/app/map/map.html
@@ -1,15 +1,8 @@
- @if (!isFullscreen && details) {
-
-
{{ details.name }}
-
{{ details.building }}
-
- }
diff --git a/src/app/map/map.scss b/src/app/map/map.scss
index eff4b78..352eacb 100644
--- a/src/app/map/map.scss
+++ b/src/app/map/map.scss
@@ -4,6 +4,7 @@
position: absolute;
top: 54px;
height: calc(100vh - 54px);
+ width: 100%;
}
.map-fullscreen {
diff --git a/src/app/map/map.ts b/src/app/map/map.ts
index 24f41d1..e8df937 100644
--- a/src/app/map/map.ts
+++ b/src/app/map/map.ts
@@ -1,6 +1,7 @@
import { Component, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { LeafletModule } from '@bluehalo/ngx-leaflet';
+import { center } from '@turf/turf';
import { Overpass } from '../overpass';
import * as L from 'leaflet';
@@ -13,12 +14,11 @@ import * as E from './geojson';
templateUrl: './map.html',
styleUrl: './map.scss',
})
-export class Map {
- private centerLocation = { lat: 49.015514096207895, lng: 8.391567600294243 };
+export class OSMMap {
+ private buildingLayer?: L.LayerGroup;
protected readonly title = signal('HKA-OSM');
map?: L.Map;
- details?: D.Details;
isFullscreen = true;
@@ -33,7 +33,7 @@ export class Map {
options: L.MapOptions = {
layers: [this.osm],
zoom: 18, // Zoom level
- center: L.latLng(this.centerLocation.lat, this.centerLocation.lng),
+ center: this.getCenter(), // Center of the map
maxBounds: L.latLngBounds(
L.latLng(49.014442, 8.387954), // Southwest corner
L.latLng(49.017847, 8.395448), // Northeast corner
@@ -51,7 +51,6 @@ export class Map {
this.map = map;
this.layerControl.addTo(this.map);
this.loadBuildings().addTo(this.map);
- this.queryBuildings();
console.log('Map is ready');
}
@@ -63,23 +62,14 @@ export class Map {
click: (e) => {
this.isFullscreen = !this.isFullscreen;
if (!this.isFullscreen) {
- this.map?.setView(
- L.latLng(feature.properties.center[1], feature.properties.center[0]),
- 20,
- );
- //FIXME: Disable dragging and keyboard interactions when in fullscreen mode
- this.map?.dragging.disable() &&
- this.map?.keyboard.disable() &&
- this.map?.scrollWheelZoom.disable();
- this.details = new D.Details(feature.properties.name, feature.properties.building);
+ this.map?.setView(this.getCenter(feature.geometry), 20);
+ this.buildingLayer = this.queryBuildings(feature.properties.name);
+ this.buildingLayer.addTo(this.map!);
} else {
- this.map?.setView(L.latLng(this.centerLocation.lat, this.centerLocation.lng), 18);
-
- //FIXME: Enable dragging and keyboard interactions when in fullscreen mode
- this.map?.dragging.enable() &&
- this.map?.keyboard.enable() &&
- this.map?.scrollWheelZoom.enable();
- this.details = undefined;
+ this.map?.setView(this.getCenter(), 18);
+ if (this.buildingLayer) {
+ this.map?.removeLayer(this.buildingLayer);
+ }
}
console.log('Set isFullscreen to:', this.isFullscreen);
console.log('Clicked on feature:', feature.properties?.name);
@@ -95,10 +85,49 @@ export class Map {
});
}
- queryBuildings() {
- this.overpass.fetchBuildings('E').subscribe((data) => {
+ queryBuildings(building_name: string) {
+ // Get the building name from the feature properties and query the Overpass API for detailed building data,
+ // including indoor features.
+
+ // Create a new LayerGroup to hold the building polygons
+ const resultingLayer = new L.LayerGroup();
+ this.overpass.fetchBuildings(building_name).subscribe((data) => {
console.log('Fetched building data from Overpass API:', data);
- // Here you would typically process the data and add it to the map
+
+ // Create a mapping of node IDs to their coordinates
+ const nodes: Map = new Map();
+ data.elements.forEach((element: any) => {
+ if (element.type === 'node') {
+ nodes.set(element.id, new L.LatLng(element.lat, element.lon));
+ }
+ });
+
+ // Process ways and create polygons
+ // TODO: Change to features, to also add the meta data of the building, e.g. the name of the room
+ data.elements.forEach((element: any) => {
+ if (element.type === 'way') {
+ const coordinates: L.LatLng[] = [];
+ element.nodes.forEach((nodeId: number) => {
+ coordinates.push(nodes.get(nodeId)!);
+ });
+ L.polygon(coordinates, { color: '#999999', fillColor: '#e0e0e0', fillOpacity: 1 }).addTo(
+ resultingLayer,
+ );
+ }
+ });
});
+ return resultingLayer;
+ }
+
+ private getCenter(feature?: any): L.LatLng {
+ // Calculate the center of the feature using Turf.js, or use a default center if no feature is provided.
+ let centerPoint: number[] = [];
+ if (feature) {
+ centerPoint = center(feature).geometry.coordinates.reverse();
+ } else {
+ centerPoint = [49.015514096207895, 8.391567600294243];
+ }
+ const result = new L.LatLng(centerPoint[0], centerPoint[1]);
+ return result;
}
}
diff --git a/src/app/overpass.ts b/src/app/overpass.ts
index e03812b..fb39c74 100644
--- a/src/app/overpass.ts
+++ b/src/app/overpass.ts
@@ -1,6 +1,25 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
+export interface OverpassElementNode {
+ type: 'node';
+ id: number;
+ lat: number;
+ lon: number;
+}
+
+export interface OverpassElementWay {
+ type: 'way';
+ id: number;
+ geometry?: Array<{ lat: number; lon: number }>;
+}
+
+export type OverpassElement = OverpassElementNode | OverpassElementWay;
+
+export interface OverpassResponse {
+ elements: OverpassElement[];
+}
+
@Injectable({
providedIn: 'root',
})
@@ -13,7 +32,7 @@ export class Overpass {
const header = { 'Content-Type': 'text/plain' };
const query = `
[out:json][timeout:25];
- nwr["name"="${building_name}"](49.014442, 8.387954, 49.017847, 8.395448)->.building;
+ nwr["building"]["operator"="Hochschule Karlsruhe"]["name"="${building_name}"](49.014442, 8.387954, 49.017847, 8.395448)->.building;
(
nwr["indoor"="room"](area.building);
);
@@ -21,6 +40,6 @@ export class Overpass {
out body;
`;
- return this.http.post(this.apiUrl, query, { headers: header });
+ return this.http.post(this.apiUrl, query, { headers: header });
}
}