Merge branch 'osrm' into 'master'

Osrm

See merge request streetmap1/ts-streetmap!4
This commit is contained in:
Janis Meister
2022-01-26 13:38:21 +00:00
34 changed files with 639 additions and 156 deletions

View File

@@ -1,10 +1,9 @@
header{
background-color: rgb(37, 37, 37);
height: 50px;
font-size: 15pt;
color:white;
font-weight: bold;
background-color: rgb(37, 37, 37);
height: 50px;
font-size: 15pt;
color:white;
font-weight: bold;
}
header p{
@@ -13,8 +12,3 @@ header p{
display:block;
float:right;
}
#map{
width: 100%;
height: 100%;
}

View File

@@ -1,6 +1,7 @@
<header>
<app-search></app-search>
<app-search (emitter)="onSearchResponse($event)"></app-search>
<p>{{title}}</p>
</header>
<div id="map" class="map"></div>
<app-map #mapRef></app-map>
<app-route-list #routeListRef></app-route-list>

View File

@@ -1,75 +1,25 @@
import { Component, AfterViewInit, ElementRef, ViewChild} from '@angular/core';
import { Component, ViewChild, } from '@angular/core';
import { Osrm } from './interfaces/osrm';
import { MapComponent } from './map/map.component';
import { RouteListComponent } from './route-list/route-list.component';
import { defaults as defaultControls } from 'ol/control';
import { fromLonLat } from 'ol/proj';
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import XYZ from 'ol/source/XYZ';
import ZoomToExtent from 'ol/control/ZoomToExtent';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css', '../../node_modules/ol/ol.css']
})
export class AppComponent implements AfterViewInit {
export class AppComponent {
title = "Street Map";
map: Map;
@ViewChild('mapRef') mapCompopnent!: MapComponent;
@ViewChild('routeListRef') routeListCompopnent!: RouteListComponent;
@ViewChild("inputautocompleteList") autocompleteList: ElementRef;
constructor() { }
updateAutoCompleteList(): void{
this.autocompleteList.nativeElement.innerHTML = "Fsd";
}
// Gets called in "app.component.html" when an input changes its value
getValue(valueFrom:string, valueTo:string): void{
console.log("From " + valueFrom + " to " + valueTo);
/*
this.nominatimService.sendQueryRequest(valueFrom)
.subscribe((response: Nominatim[]) => console.log(response));*/
}
ngOnInit() {
}
ngAfterViewInit() {
this.map = new Map({
target: 'map',
layers: [
new TileLayer({
source: new XYZ({
url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'
})
})
],
view: new View({
projection: 'EPSG:3857',
center: fromLonLat([8, 52]),
zoom: 2
}),
controls: defaultControls().extend([
new ZoomToExtent({
extent: [
813079.7791264898, 5929220.284081122,
848966.9639063801, 5936863.986909639
]
})
])
});
setTimeout(() => this.map.updateSize(), 200);
}
onSearchResponse($event: Osrm): void {
this.mapCompopnent.drawPath($event);
this.routeListCompopnent.updateSidebar($event);
}
}

View File

@@ -3,11 +3,15 @@ import { BrowserModule } from '@angular/platform-browser';
import {HttpClientModule} from '@angular/common/http';
import { AppComponent } from './app.component';
import { SearchComponent } from './search/search.component';
import { MapComponent } from './map/map.component';
import { RouteListComponent } from './route-list/route-list.component';
@NgModule({
declarations: [
AppComponent,
SearchComponent,
MapComponent,
RouteListComponent,
],
imports: [
BrowserModule,

View File

@@ -0,0 +1,29 @@
interface OpenLayersGeometry{
coordinates: Array<Array<number>>;
type?: string;
}
interface OpenLayersProperties{
ECO_NAME?: string;
BIOME_NAME?: string;
REALM?: string;
NNH?: string;
NNH_NAME?: string;
COLOR?: string;
COLOR_BIO?: string;
COLOR_NNH?: string;
}
interface OpenLayersFeature{
type: string;
geometry: OpenLayersGeometry;
id: number;
properties: OpenLayersProperties;
}
export interface OpenLayersGeoJSON{
type: string;
features: Array<OpenLayersFeature>;
geometry: OpenLayersGeometry;
properties: OpenLayersProperties;
}

View File

@@ -0,0 +1,47 @@
interface OsrmWaypoint{
hint?: string;
distance?: number;
location?: Array<number>;
name?: string;
}
interface OsrmManeuver{
type?: string;
modifier?: string;
}
export interface OsrmStep{
driving_side?: string;
duration?: number;
distance?: number;
name?: string;
maneuver?: OsrmManeuver;
}
interface OsrmLeg{
steps?: Array<OsrmStep>;
weight?: number;
distance?: number;
summary?: string;
duration?: number;
}
interface OsrmGeometry{
type: GeometryType;
coordinates?: Array<Array<number>>;
}
enum GeometryType {
LINE_STRING = "LineString"
}
interface OsrmRoute{
legs: Array<OsrmLeg>;
geometry: OsrmGeometry;
}
export interface Osrm{
code?: string;
waypoints?: Array<OsrmWaypoint>;
routes: Array<OsrmRoute>;
}

View File

@@ -15,6 +15,9 @@ interface PhotonProperties{
type?: string;
postcode?: string;
city?: string;
housenumber?: number;
street?: string;
state?: string;
}
export interface Photon{
@@ -26,4 +29,4 @@ export interface Photon{
export interface PhotonFeatureCollection{
features?: Array<Photon>;
type?: string;
}
}

View File

@@ -0,0 +1,6 @@
#map{
width: 100%;
height: 100%;
}

View File

@@ -0,0 +1 @@
<div id="map" class="map"></div>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MapComponent } from './map.component';
describe('MapComponent', () => {
let component: MapComponent;
let fixture: ComponentFixture<MapComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MapComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(MapComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,89 @@
import { Component, AfterViewInit } from '@angular/core';
import { defaults as defaultControls } from 'ol/control';
import { fromLonLat, transform } from 'ol/proj';
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import XYZ from 'ol/source/XYZ';
import ZoomToExtent from 'ol/control/ZoomToExtent';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import LineString from 'ol/geom/LineString';
import { Osrm, OsrmStep } from '../interfaces/osrm';
import { Feature } from 'ol';
import Geometry from 'ol/geom/Geometry';
@Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.css']
})
export class MapComponent implements AfterViewInit {
constructor() { }
map: Map;
ngAfterViewInit() {
this.map = new Map({
target: 'map',
layers: [
new TileLayer({
source: new XYZ({
url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'
})
})
],
view: new View({
projection: 'EPSG:3857',
center: fromLonLat([8, 52]),
zoom: 2
}),
controls: defaultControls().extend([
new ZoomToExtent({
extent: [
813079.7791264898, 5929220.284081122,
848966.9639063801, 5936863.986909639
]
})
])
});
setTimeout(() => this.map.updateSize(), 200);
}
drawPath(osrm: Osrm): void{
console.log(osrm) //https://routing.openstreetmap.de/routed-bike/route/v1/driving/8.6042708,53.5151533;13.6887164,51.0491468?overview=false&alternatives=true&steps=true
const coordinates = osrm.routes[0].geometry.coordinates || [];
const f_coordinates: Array<Array<number>> = []
coordinates.forEach(coordinate =>
{
f_coordinates.push(transform(coordinate, 'EPSG:4326', 'EPSG:3857'))
}
);
const lineString: LineString = new LineString(f_coordinates);
const feature: Feature<Geometry> = new Feature({ geometry: lineString });
const vectorSource = new VectorSource({ features: [ feature ]});
const vectorLayer = new VectorLayer({
source: vectorSource,
});
this.map.addLayer(vectorLayer);
// this.features = new GeoJSON().readFeatures(new openLayersGeoJSON())
/*
this.vectorLayer = new VectorLayer({
background: '#1a2b39',
source: new VectorSource({
url: 'http://router.project-osrm.org/route/v1/driving/-1.8744130630953275,52.45318441573963;-1.879401971863028,52.451059431849615;-1.8783612747652496,52.44962092302177;-1.882395317123648,52.44969938835112;-1.8824275036318268,52.452046744809195;-1.8794663448793851,52.45332825709778;-1.8898840446932288,52.454230523991356?overview=full&steps=true&geometries=geojson',
format: new GeoJSON({dataProjection: 'EPSG:4326', featureProjection: "EPSG:3857" }),
})
});
this.map.addLayer(this.vectorLayer);*/
}
}

View File

@@ -0,0 +1,50 @@
.osrm-route-container{
position: absolute;
right: 0;
width:300px;
margin-top: 50px;
background-color: rgba(27, 27, 27, 0.801);
top:0;
bottom: 0;
color: white;
overflow-y: scroll;
}
.osrm-route-container h4{
text-align: center;
line-height: 30px;
letter-spacing: 1px;
padding-top: 0px;
margin-top: 2px;
}
.route-list{
width: 100%;
display: block;
font-weight: bold;
text-align: left;
}
.route-list .route-list-item{
width: 100%;
display: block;
border-top: 1px solid rgba(255, 255, 255, 0.418);
padding-top: 5px;
padding-bottom: 5px;
}
.route-list .route-list-item div{
width: 100%;
/*background-image: url('/assets/images/turn-left.svg');*/
background-repeat: no-repeat;
background-size: 35px 35px;
background-position:5px 10px;
}
.route-list .route-list-item div p{
display: inline-block;
text-transform: capitalize;
padding-left: 50px;
}

View File

@@ -0,0 +1,18 @@
<div class="osrm-route-container">
<h4>Your Route Steps</h4>
<div class="route-list">
<div *ngFor="let step of this.routeSteps" class="route-list-item" >
<!--Fork-->
<div *ngIf="step.maneuver?.type != 'fork'" style="background-image: url('/assets/images/{{step.maneuver?.modifier }}.svg');">
<p>{{step.maneuver?.type }} {{step.maneuver?.modifier }} <br> {{step.name }}</p>
</div>
<!--Not Fork-->
<div *ngIf="step.maneuver?.type == 'fork'" style="background-image: url('/assets/images/{{step.maneuver?.type }}-{{step.maneuver?.modifier }}.svg');">
<p>{{step.maneuver?.type }} {{step.maneuver?.modifier }} <br> {{step.name }}</p>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RouteListComponent } from './route-list.component';
describe('RouteListComponent', () => {
let component: RouteListComponent;
let fixture: ComponentFixture<RouteListComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ RouteListComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(RouteListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,22 @@
import { Component, OnInit } from '@angular/core';
import { Osrm, OsrmStep } from '../interfaces/osrm';
@Component({
selector: 'app-route-list',
templateUrl: './route-list.component.html',
styleUrls: ['./route-list.component.css']
})
export class RouteListComponent implements OnInit {
routeSteps: Array<OsrmStep> = []
constructor() { }
ngOnInit(): void {
}
updateSidebar(osrm: Osrm): void{
console.log("updateSidebar")
if(osrm.routes[0].legs[0].steps){
this.routeSteps = osrm.routes[0].legs[0].steps;
}
}
}

View File

@@ -1,11 +1,3 @@
#inputFrom:focus + .autocomplete-items-from{
visibility:visible;
}
#inputTo:focus + .autocomplete-items-to{
visibility:visible;
}
.searchField{
display:block;
float:left;
@@ -22,6 +14,7 @@
font-weight: bold;
font-family: 'Roboto';
padding: 5px;
width: 350px;
}
.autocomplete {
@@ -29,9 +22,9 @@
display: inline-block;
color: black;
}
.autocomplete-items {
visibility: visible; /* without debugging it should be display:none */
/*display: block; */
position: absolute;
border: 1px solid #d4d4d4;
border-bottom: none;
@@ -41,27 +34,57 @@
top: 100%;
left: 0;
right: 0;
width: 210px;
width: 350px;
margin-left: 30px;
margin-top: 5px;
}
.autocomplete-items div {
padding: 10px;
font-weight: normal;
font-size: 11pt;
cursor: pointer;
background-color: #fff;
border-bottom: 1px solid #d4d4d4;
background-color: #fff;
border-bottom: 1px solid #d4d4d4;
}
.autocomplete-items div label{
cursor: pointer;
}
/*when hovering an item:*/
.autocomplete-items div:hover {
background-color: #e9e9e9;
background-color: #e9e9e9;
}
/*when navigating through the items using the arrow keys:*/
.autocomplete-active {
background-color: DodgerBlue !important;
color: #ffffff;
}
background-color: DodgerBlue !important;
color: #ffffff;
}
button{
padding-left: 10px;
padding-right: 10px;
padding-top: 5px;
padding-bottom: 5px;
border-radius: 0;
border: 0;
background-color: transparent;
color: white;
font-size: 13pt;
font-weight: bold;
}
.routeBtn{
background-color: #28a745;
margin-top: 9px;
margin-left: 10px;
border-radius: 3px;
transition: 0.1s;
transition-timing-function: linear;
cursor:pointer;
}
.routeBtn:hover{
background-color: #55c56f;
}

View File

@@ -1,29 +1,33 @@
<div class="searchField">
<div id="coordinates">
<input *ngIf="photonItemsFrom[0]" hidden id="longFromInput" value="{{ longFrom }}">
<input *ngIf="photonItemsFrom[0]" hidden id="latFromInput" value="{{ latFrom }}">
<input *ngIf="photonItemsTo[0]" hidden id="longToInput" value="{{ longTo}}">
<input *ngIf="photonItemsTo[0]" hidden id="latToInput" value="{{ latTo }}">
</div>
<div class="searchField">
<div class="autocomplete">
<input #inputFrom (change)="getValue(inputFrom.value, inputTo.value)" type="text" name="inputFrom" id="inputFrom" placeholder="From" value="{{ inputFromValue }}">
<input #inputFrom (click)="getValue(inputFrom.value, true)" (change)="getValue(inputFrom.value, true)" type="text" name="inputFrom" id="inputFrom" placeholder="From" value="{{ inputFromValue }}">
<div #inputautocompleteList class="autocomplete-items autocomplete-items-from">
<div *ngFor="let item of nominatimItemsFrom" >
{{ item.display_name }}
<input type="hidden" value="{{ item.display_name }}">
</div>
<!-- PHOTON -->
<div *ngFor="let item of photonItemsFrom"
(click)="selectPhoton(true, item)">
{{ item.properties.name }} {{item.properties.postcode}} {{item.properties.city}} {{item.properties.countrycode}}
</div>
(click)="selectPhoton(true, item);" >
<!--IF TYPE == STREET-->
<label *ngIf="item.properties.type == 'street'">
{{ item.properties.name }} {{item.properties.housenumber}}<br>
{{item.properties.postcode}} {{item.properties.city}} {{item.properties.country}}
</label>
<label *ngIf="item.properties.type != 'street'">
{{ item.properties.name }} <br>
{{item.properties.street}} {{item.properties.housenumber}} {{item.properties.postcode}} {{item.properties.city}} {{item.properties.countrycode}}
</label>
</div>
</div>
</div>
<div class="autocomplete" id="autocompleteTo">
<input #inputTo (change)="getValue(inputFrom.value, inputTo.value)" type="text" name="inputTo" id="inputTo" placeholder="To" value="{{ inputToValue }}">
<input #inputTo (click)="getValue(inputTo.value, false)" (change)="getValue(inputTo.value, false)" type="text" name="inputTo" id="inputTo" placeholder="To" value="{{ inputToValue }}">
<div #inputautocompleteList class="autocomplete-items autocomplete-items-to">
<div *ngFor="let item of nominatimItemsTo" >
@@ -33,10 +37,20 @@
<div *ngFor="let item of photonItemsTo"
(click)="selectPhoton(false, item)">
{{ item.properties.name }} {{item.properties.postcode}} {{item.properties.city}} {{item.properties.countrycode}}
<input type="hidden" value="{{ item.properties?.name }}">
<!--IF TYPE == STREET-->
<label *ngIf="item.properties.type == 'street'">
{{ item.properties.name }} {{item.properties.housenumber}}<br>
{{item.properties.postcode}} {{item.properties.city}} {{item.properties.country}}
</label>
<label *ngIf="item.properties.type != 'street'">
{{ item.properties.name }} <br>
{{item.properties.street}} {{item.properties.housenumber}} {{item.properties.postcode}} {{item.properties.city}} {{item.properties.countrycode}}
</label>
</div>
</div>
</div>
</div>
</div>
<button class="routeBtn" (click)="getRoute()">Route</button>

View File

@@ -1,8 +1,11 @@
import { Component, OnInit, ElementRef, ViewChild} from '@angular/core';
import { Component, ElementRef, Output, ViewChild } from '@angular/core';
import { Nominatim } from '../interfaces/nominatim';
import { NominatimService } from '../nominatim.service';
import { NominatimService } from '../services/nominatim.service';
import { Photon, PhotonFeatureCollection } from '../interfaces/photon';
import { PhotonService } from '../photon.service';
import { PhotonService } from '../services/photon.service';
import { OsrmService } from '../services/osrm.service';
import { Osrm } from '../interfaces/osrm';
import { EventEmitter } from '@angular/core';
@Component({
selector: 'app-search',
@@ -10,7 +13,7 @@ import { PhotonService } from '../photon.service';
styleUrls: ['./search.component.css']
})
export class SearchComponent implements OnInit {
export class SearchComponent{
@ViewChild("inputautocompleteList") autocompleteList: ElementRef;
nominatimItemsFrom: Nominatim[] = [];
@@ -30,38 +33,58 @@ export class SearchComponent implements OnInit {
selectedPhotonFrom: Photon;
selectedPhotonTo: Photon;
constructor(private nominatimService: NominatimService, private photonService: PhotonService) { }
@Output() emitter = new EventEmitter<Osrm>();
constructor(
private nominatimService: NominatimService,
private photonService: PhotonService,
private osrmService: OsrmService,
) { }
getFormattedPhotonValue(p: Photon): string{
let formatted: string = "";
if(p.properties.name){
formatted += " " + p.properties.name;
}
if(p.properties.housenumber){
formatted += " " + p.properties.housenumber;
}
if(p.properties.postcode){
formatted += " " + p.properties.postcode;
}
if(p.properties.city){
formatted += " " + p.properties.city;
}
if(p.properties.countrycode){
formatted += " " + p.properties.countrycode;
}
return formatted;
}
selectPhoton(isFrom: boolean, p: Photon): void{
if(isFrom){
this.selectedPhotonFrom = p;
this.longFrom = <number> p.geometry?.coordinates[0];
this.latFrom = <number> p.geometry?.coordinates[1];
this.inputFromValue = <string> p.properties.name
if(p.properties.postcode){
this.inputFromValue += " " + p.properties.postcode;
}
if(p.properties.city){
this.inputFromValue += " " + p.properties.city;
}
if(p.properties.countrycode){
this.inputFromValue += " " + p.properties.countrycode;
}
this.inputFromValue = <string> p.properties.name;
this.inputFromValue = this.getFormattedPhotonValue(p);
this.photonItemsFrom = [];
}else{
this.selectedPhotonTo = p;
this.longTo = <number>p.geometry?.coordinates[0];
this.latTo = <number>p.geometry?.coordinates[1];
this.inputToValue = <string> p.properties.name + " " + p.properties.countrycode;
this.inputToValue = this.getFormattedPhotonValue(p);
this.photonItemsTo = [];
}
}
// Gets called in "app.component.html" when an input changes its value
getValue(valueFrom:string, valueTo:string): void{
console.log("From " + valueFrom + " to " + valueTo);
getValue(value:string, isFrom: boolean): void{
//this.updateAutoCompleteList([{display_name: 'Hallo'}, {display_name: 'Test2'}], [{display_name: 'Halload'}, {display_name: 'Test4'}]);
/*
@@ -71,24 +94,33 @@ export class SearchComponent implements OnInit {
this.nominatimService.sendQueryRequest(valueTo)
.subscribe((response: Nominatim[]) => this.nominatimItemsTo = response);
*/
this.photonItemsFrom = [];
this.photonItemsTo = [];
this.photonService.sendQueryRequest(valueFrom)
this.photonService.sendQueryRequest(value)
.subscribe((response: PhotonFeatureCollection) => response.features?.forEach(feature => {
this.photonItemsFrom.push(feature);
this.longFrom = <number>this.photonItemsFrom[0].geometry?.coordinates![0];
this.latFrom = <number>this.photonItemsFrom[0].geometry?.coordinates![1];
}));
this.photonService.sendQueryRequest(valueTo)
.subscribe((response: PhotonFeatureCollection) => response.features?.forEach(feature => {
this.photonItemsTo.push(feature);
this.longTo = <number>this.photonItemsTo[0].geometry?.coordinates![0];
this.latTo = <number>this.photonItemsTo[0].geometry?.coordinates![1];
if(isFrom){
this.photonItemsFrom.push(feature);
this.longFrom = <number>this.photonItemsFrom[0].geometry?.coordinates![0];
this.latFrom = <number>this.photonItemsFrom[0].geometry?.coordinates![1];
}else{
this.photonItemsTo.push(feature);
this.longTo = <number>this.photonItemsFrom[0].geometry?.coordinates![0];
this.latTo = <number>this.photonItemsFrom[0].geometry?.coordinates![1];
}
}));
}
ngOnInit(): void {
}
getRoute(): void{
this.osrmService.sendQueryRequest(this.longFrom, this.latFrom, this.longTo, this.latTo)
.subscribe((response: Osrm) => {
this.emitter.emit(response);
/*
this.mapComponent.updateSidebar(response);
this.mapComponent.drawPath(response);
*/
}
);
}
}

View File

@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Nominatim } from './interfaces/nominatim';
import { Nominatim } from '../interfaces/nominatim';
import { Observable } from 'rxjs';
@Injectable({
@@ -12,7 +12,7 @@ export class NominatimService{
constructor(private http: HttpClient) { }
// sends a query request to Nominatim and gets response (https://nominatim.org/release-docs/develop/api/Search/)
sendQueryRequest(q: string): Observable<Nominatim[]> {
sendQueryRequest(q: string): Observable<Nominatim[]> {
return this.http.get<Nominatim[]>("https://nominatim.openstreetmap.org/search.php?format=jsonv2&q=" + q);
}
}
}

View File

@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { OpenLayersService } from './open-layers.service';
describe('OpenLayersService', () => {
let service: OpenLayersService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(OpenLayersService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@@ -0,0 +1,11 @@
import { Injectable } from '@angular/core';
import { OpenLayersGeoJSON } from './interfaces/openlayersGeojson';
@Injectable({
providedIn: 'root'
})
export class OpenLayersService {
constructor() { }
}

View File

@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { OsrmService } from './osrm.service';
describe('OsrmService', () => {
let service: OsrmService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(OsrmService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@@ -0,0 +1,19 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Osrm } from '../interfaces/osrm';
@Injectable({
providedIn: 'root'
})
// http://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?overview=false&steps=true&geometries=geojson
export class OsrmService{
constructor(private http: HttpClient) { }
// sends a query request to Osrm and gets response (http://project-osrm.org/docs/v5.24.0/api/?language=cURL#table-service)
sendQueryRequest(longFrom: number, latFrom: number, longTo: number, latTo: number): Observable<Osrm> {
console.log("https://routing.openstreetmap.de/routed-bike/route/v1/driving/" + longFrom + "," + latFrom + ";" + longTo + "," + latTo + "?overview=full&alternatives=false&steps=true&geometries=geojson")
return this.http.get<Osrm>("https://routing.openstreetmap.de/routed-bike/route/v1/driving/" + longFrom + "," + latFrom + ";" + longTo + "," + latTo + "?overview=full&alternatives=false&steps=true&geometries=geojson");
}
}

View File

@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Photon, PhotonFeatureCollection } from './interfaces/photon';
import { PhotonFeatureCollection } from '../interfaces/photon';
import { Observable } from 'rxjs';
@Injectable({
@@ -12,7 +12,7 @@ export class PhotonService{
constructor(private http: HttpClient) { }
// sends a query request to Photon and gets response (https://photon.komoot.io/)
sendQueryRequest(q: string): Observable<PhotonFeatureCollection> {
return this.http.get<PhotonFeatureCollection>("https://photon.komoot.io/api/?q=" + q + "&limit=10");
sendQueryRequest(q: string): Observable<PhotonFeatureCollection> {
return this.http.get<PhotonFeatureCollection>("https://photon.komoot.io/api/?q=" + q + "&limit=10&zoom=12");
}
}
}

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g>
<path fill="#fff" d="M454,122.1l7.8,3.6l22.2,25.6c3.8,4.3,3.3,10.9-1,14.7l-0.1,0.1l-70.3,59.3c-40.7,37.5-62.4,91.3-59.2,146.6l0.2,123.1
c0,5.6-4.5,10.1-10.1,10.1h-34.4c-5.6,0-10.1-4.5-10.1-10.1l0-118.7c-4.7-72.5,23.8-143.1,77.5-192l70.9-59.8L454,122.1 M454,115.3
c-4.1,0-8,1.4-11.1,4L372,179.1c-55.1,50.5-84.5,123.2-79.9,197.8v118.1c0,9.3,7.6,16.9,16.9,16.9h34.4c9.4,0,16.9-7.6,16.9-16.9v0
l-0.2-123.1c-3.2-53.3,17.6-105.2,56.8-141.4l70.2-59.3c7.3-6.1,8.2-17,2.1-24.3l-0.1-0.2L467,121.2
C463.8,117.4,459,115.3,454,115.3L454,115.3z M279.6,179.1l-83.9-70.8c-5.9-3.2-8.1-10.7-4.9-16.6c1.6-2.8,4.2-5,7.3-5.9
l100.6-46.1c6.3-3.8,8.3-11.9,4.5-18.1c-2.4-4-6.8-6.4-11.4-6.4L18.6,0l53.9,268.3c1,7.2,7.6,12.3,14.8,11.3
c4.6-0.6,8.6-3.6,10.4-8l31.3-106.2c0.9-6.7,7.1-11.3,13.8-10.3c3.2,0.5,6.1,2.2,8,4.8l83.6,70.5c39.2,36.3,60,88.2,56.8,141.4
L291.2,495c0,9.4,7.6,17,16.9,17h0h34.4c9.3,0,16.9-7.6,16.9-16.9V376.9C364.1,302.3,334.7,229.6,279.6,179.1z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g>
<path fill="#fff" d="M144.1,6.4c5.3,0,9.5,4.3,9.5,9.5v480.2c0,5.3-4.3,9.5-9.5,9.5h-32.2c-5.3,0-9.5-4.3-9.5-9.5V15.9c0-5.3,4.3-9.5,9.5-9.5
H144.1 M144.1,0h-32.2C103.1,0,96,7.1,96,15.9v480.2c0,8.8,7.1,15.9,15.9,15.9h32.2c8.8,0,15.9-7.1,15.9-15.9V15.9
C160,7.1,152.9,0,144.1,0z M96.5,385.4v110.8c0,8.8,7.1,15.9,15.9,15.9h32.2c8.8,0,15.9-7.1,15.9-15.9v0l-0.1-115.4
c-3-50,16.5-98.6,53.3-132.6l78.3-66.1c3.8-5.1,11-6.1,16-2.3c2.4,1.8,4,4.5,4.5,7.5l29.4,99.5c2.7,6.3,9.9,9.3,16.2,6.6
c4-1.7,6.9-5.4,7.5-9.8L416,32L159.8,46.4c-6.8-0.1-12.4,5.4-12.5,12.3c0,4.4,2.2,8.5,6,10.7l94.4,43.2c6.1,1.8,9.5,8.1,7.8,14.2
c-0.9,2.9-2.8,5.4-5.5,6.8L171.3,200C119.6,247.3,92.1,315.4,96.5,385.4z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g>
<path fill="#fff" d="M287.8,127.8l0.3,0c106.2,1.2,191.7,87.9,191.4,194.1v126.1h-0.1l0.1,48c0,8.8-7.1,15.9-15.8,15.9h0h-32.2
c-8.8,0-15.9-7.1-15.9-15.9V322c0.3-71-56.5-129-127.5-130.2h-63.9c-6.2-1.3-12.3,2.6-13.6,8.7c-0.6,3-0.1,6.1,1.6,8.6l42.9,94.4
c2.1,6.5-1.4,13.5-7.9,15.6c-4.2,1.3-8.7,0.4-12-2.5L32.4,160.4L235.3,3.1c5.1-4.5,12.9-4,17.4,1.1c2.9,3.3,3.8,7.9,2.5,12
l-42.9,94.3c-3.4,5.3-1.9,12.4,3.4,15.8c2.6,1.6,5.7,2.2,8.6,1.5L287.8,127.8"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 818 B

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g>
<path fill="#fff" d="M223.8,191.8C152.8,193,96,251,96.3,322v174.2c0,8.8-7.1,15.9-15.9,15.9H48.3c-8.8,0-15.9-7.1-15.9-15.9v0l0.1-48.1h-0.1
V322c-0.2-106.3,85.2-192.9,191.4-194.1l0.3-0.1v0.1h63.5c6.2,1.3,12.3-2.6,13.6-8.7c0.7-3,0.1-6.1-1.5-8.6l-42.9-94.3
c-2.1-6.5,1.4-13.5,7.9-15.6c4.2-1.4,8.7-0.4,12,2.5l202.9,157.3L276.7,316.6c-5.1,4.5-12.9,4-17.4-1.1c-2.9-3.3-3.8-7.8-2.5-12
l42.9-94.3c3.4-5.3,1.9-12.4-3.4-15.8c-2.6-1.6-5.7-2.2-8.6-1.5H223.8z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 821 B

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g>
<path fill="#fff" d="M426.2,376.9v118.1c0,9.3-7.6,16.9-16.9,16.9h-34.4c-9.4,0-16.9-7.6-16.9-16.9v0l0.1-123.1c3.2-53.3-17.6-105.2-56.8-141.4
l-83.6-70.5c-4-5.4-11.7-6.5-17.1-2.5c-2.6,1.9-4.3,4.8-4.8,8l-31.3,106.2c-2.8,6.7-10.6,9.9-17.3,7c-4.3-1.8-7.3-5.8-7.9-10.4
L85.3,0l273.2,15.4c7.3-0.1,13.3,5.8,13.3,13.1c0,4.7-2.4,9-6.4,11.4L264.8,85.9c-6.5,1.9-10.2,8.7-8.3,15.2c0.9,3.1,3,5.7,5.9,7.3
l83.9,70.8C401.5,229.6,430.8,302.3,426.2,376.9z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 814 B

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g>
<path fill="#fff" d="M165.7,179.1l83.9-70.8c5.9-3.2,8.1-10.7,4.9-16.6c-1.5-2.8-4.2-5-7.3-5.9L146.5,39.8c-6.2-3.8-8.3-11.9-4.5-18.1
c2.4-4,6.8-6.4,11.4-6.4L426.7,0l-54,268.3c-1,7.2-7.6,12.3-14.8,11.3c-4.6-0.6-8.6-3.6-10.4-8l-31.4-106.2
c-1-6.7-7.1-11.3-13.8-10.3c-3.2,0.5-6.1,2.2-8,4.8l-83.6,70.5c-39.2,36.3-60.1,88.2-56.8,141.4L154,495c0,9.4-7.6,17-16.9,17h0
h-34.3c-9.3,0-16.9-7.6-16.9-16.9V376.9C81.2,302.3,110.5,229.6,165.7,179.1z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 809 B

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g>
<path fill="#fff" d="M399.8,222.9l-94.5-43c-5.3-3.4-12.4-1.9-15.8,3.5c-1.6,2.5-2.2,5.7-1.5,8.6v303.9c0,8.9-7.2,16.1-16.1,16.1h-31.8
c-8.9,0-16.1-7.2-16.1-16.1V192c1.4-6.2-2.5-12.3-8.7-13.6c-3-0.7-6.1-0.1-8.6,1.5l-94.5,43c-6.5,2.1-13.5-1.4-15.6-7.9
c-1.4-4.2-0.4-8.7,2.5-12L256,0l156.9,203c4.5,5.1,4,12.9-1.1,17.5C408.6,223.3,404,224.3,399.8,222.9z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 721 B

View File

@@ -14,5 +14,11 @@ body {
top:0;
bottom:0;
right:0;
left:0;
left:0;
overflow: hidden;
background-color: rgb(37, 37, 37);
}
button{
outline: 0;
}