Skip to content

Commit

Permalink
feat(directions): improve the directions tool (#452)
Browse files Browse the repository at this point in the history
* fix(direction)Now get the first coord of line/poly

* fix(direction) handle search term subscription

* refactor(routing) handling search result and title

* refactor(direction) Coord rounded to 5 decimal

* feat(direction) keep stop's title on component change.

* fix(directions) Trigger and show route results on component change

* refactor(direction) show coordinates as string

* lint

* typo

* i18n(routing) Wrong language.

* refactor(directions) keep stop's title on component change

* refactor(directions) Stop interface
  • Loading branch information
pelord authored and mbarbeau committed Oct 4, 2019
1 parent 66da71a commit 2973ec5
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 119 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@ export class RoutingFormBindingDirective implements AfterViewInit {
) {}

ngAfterViewInit(): void {
const storedStopsCoordinates = this.routingFormService.getStopsCoordinates();
const storedStops = this.routingFormService.getStops();
if (
!storedStopsCoordinates &&
this.route &&
!storedStops && this.route &&
this.route.options.routingCoordKey
) {
this.route.queryParams.subscribe(params => {
Expand Down Expand Up @@ -61,22 +60,17 @@ export class RoutingFormBindingDirective implements AfterViewInit {
}
}
});
} else if (storedStopsCoordinates) {
for (let i = 0; i < storedStopsCoordinates.length; i++) {
if (i !== 0 && i !== storedStopsCoordinates.length - 1) {
} else if (storedStops) {
for (let i = 0; i < storedStops.length; i++) {
if (i !== 0 && i !== storedStops.length - 1) {
this.component.stops.insert(i, this.component.createStop());
}
if (storedStopsCoordinates[i] instanceof Array) {
this.component.addStopOverlay(storedStopsCoordinates[i], i);
this.component.stops
.at(i)
.patchValue({ stopCoordinates: storedStopsCoordinates[i] });
this.component.stops
.at(i)
.patchValue({ stopPoint: storedStopsCoordinates[i] });
this.component.handleLocationProposals(storedStopsCoordinates[i], i);
if (storedStops[i].stopCoordinates instanceof Array) {
this.component.addStopOverlay(storedStops[i].stopCoordinates, i);
this.component.stops.at(i).patchValue(storedStops[i] );
}
}
}
this.component.onFormChange();
}
}
171 changes: 75 additions & 96 deletions packages/geo/src/lib/routing/routing-form/routing-form.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,16 @@ export class RoutingFormComponent implements OnInit, AfterViewInit, OnDestroy {
public projection = 'EPSG:4326';
public currentStopIndex: number;
private routesQueries$$: Subscription[] = [];
private search$$: Subscription;

private stream$ = new Subject<string>();

public RoutingOverlayMarkerStyle: olstyle.Style;
public RoutingOverlayStyle: olstyle.Style;
public routingStopsOverlayDataSource: FeatureDataSource;
public routingRoutesOverlayDataSource: FeatureDataSource;
private stopsLayer;
private routesLayer;

public routesResults: Routing[] | Message[];
public activeRoute: Routing;
Expand All @@ -77,40 +80,13 @@ export class RoutingFormComponent implements OnInit, AfterViewInit, OnDestroy {

// https://stackoverflow.com/questions/46364852/create-input-fields-dynamically-in-angular-2

@Input()
get term() {
return this._term;
}
set term(value: string) {
this._term = value;
}
private _term = '';
@Input() term: string;

get debounce() {
return this._debounce;
}
set debounce(value: number) {
this._debounce = value;
}
private _debounce = 200;
@Input() debounce: number = 200;

@Input()
get length() {
return this._length;
}
set length(value: number) {
this._length = value;
}
private _length = 3;
@Input() length: number = 2;

@Input()
get map(): IgoMap {
return this._map;
}
set map(value: IgoMap) {
this._map = value;
}
private _map: IgoMap;
@Input() map: IgoMap;

@Output() submit: EventEmitter<any> = new EventEmitter();

Expand Down Expand Up @@ -138,14 +114,13 @@ export class RoutingFormComponent implements OnInit, AfterViewInit, OnDestroy {
this.unsubscribeRoutesQueries();
this.unlistenSingleClick();
this.queryService.queryEnabled = true;
const stopCoordinates = [];

this.stops.value.forEach(stop => {
stopCoordinates.push(stop.stopCoordinates);
});
this.writeStopsToFormService();
this.routingRoutesOverlayDataSource.ol.clear();
this.routingStopsOverlayDataSource.ol.clear();
this.routingFormService.setStopsCoordinates(stopCoordinates);
this.map.removeLayer(this.stopsLayer);
this.map.removeLayer(this.routesLayer);

}

ngOnInit() {
Expand All @@ -168,14 +143,14 @@ export class RoutingFormComponent implements OnInit, AfterViewInit, OnDestroy {
ngAfterViewInit(): void {
this.queryService.queryEnabled = false;
this.focusOnStop = false;
const stopsLayer = new VectorLayer({
this.stopsLayer = new VectorLayer({
title: 'routingStopOverlay',
zIndex: 999,
id: 'routingStops',
source: this.routingStopsOverlayDataSource,
showInLayerList: false
});
const routesLayer = new VectorLayer({
this.routesLayer = new VectorLayer({
title: 'routingRoutesOverlay',
zIndex: 999,
id: 'routingRoutes',
Expand All @@ -184,31 +159,31 @@ export class RoutingFormComponent implements OnInit, AfterViewInit, OnDestroy {
showInLayerList: false
});

this.map.addLayer(routesLayer);
this.map.addLayer(stopsLayer);
this.map.addLayer(this.routesLayer);
this.map.addLayer(this.stopsLayer);

let selectedStopFeature;

const selectStops = new olinteraction.Select({
layers: [stopsLayer.ol],
layers: [this.stopsLayer.ol],
condition: olcondition.pointerMove,
hitTolerance: 7
});

const translateStop = new olinteraction.Translate({
layers: [stopsLayer.ol],
layers: [this.stopsLayer.ol],
features: selectedStopFeature
});

// TODO: Check to disable pointermove IF a stop is already selected
const selectRouteHover = new olinteraction.Select({
layers: [routesLayer.ol],
layers: [this.routesLayer.ol],
condition: olcondition.pointerMove,
hitTolerance: 7
});

this.selectRoute = new olinteraction.Select({
layers: [routesLayer.ol],
layers: [this.routesLayer.ol],
hitTolerance: 7
});

Expand All @@ -235,7 +210,7 @@ export class RoutingFormComponent implements OnInit, AfterViewInit, OnDestroy {

this.routesQueries$$.push(
this.stopsForm.statusChanges
.pipe(debounceTime(this._debounce))
.pipe(debounceTime(this.debounce))
.subscribe(val => this.onFormChange())
);

Expand Down Expand Up @@ -277,7 +252,7 @@ export class RoutingFormComponent implements OnInit, AfterViewInit, OnDestroy {
this.routesQueries$$.push(
this.stream$
.pipe(
debounceTime(this._debounce),
debounceTime(this.debounce),
distinctUntilChanged()
)
.subscribe((term: string) => this.handleTermChanged(term))
Expand All @@ -286,6 +261,8 @@ export class RoutingFormComponent implements OnInit, AfterViewInit, OnDestroy {

handleLocationProposals(coordinates: [number, number], stopIndex: number) {
const groupedLocations = [];
const roundedCoordinates = [coordinates[0].toFixed(5), coordinates[1].toFixed(5)];
this.stops.at(stopIndex).patchValue({ stopPoint: roundedCoordinates.join(',') });
this.searchService
.reverseSearch(coordinates, { zoom: this.map.getZoom() })
.map(res =>
Expand Down Expand Up @@ -328,9 +305,24 @@ export class RoutingFormComponent implements OnInit, AfterViewInit, OnDestroy {
} else {
// Not moving the translated point Only to suggest value into the UI.
}
} else if (results[0].source.getId() === 'coordinatesreverse') {
this.stops.at(stopIndex).patchValue({
stopPoint: [
results[0].data.geometry.coordinates[0].toFixed(5),
results[0].data.geometry.coordinates[1].toFixed(5)
].join(',')
});
if (results[0].data.geometry.type === 'Point') {
this.stops.at(stopIndex).patchValue({
stopCoordinates:
results[0].data.geometry.coordinates
});
} else {
// Not moving the translated point Only to suggest value into the UI.
}
}
} else {
this.stops.at(stopIndex).patchValue({ stopPoint: coordinates });
this.stops.at(stopIndex).patchValue({ stopPoint: roundedCoordinates.join(',') });
this.stops.at(stopIndex).patchValue({ stopProposals: [] });
}
this.changeDetectorRefs.detectChanges();
Expand Down Expand Up @@ -384,15 +376,14 @@ export class RoutingFormComponent implements OnInit, AfterViewInit, OnDestroy {
return this.stopsForm.get('stops') as FormArray;
}

getStopsCoordinates(): [number, number][] {
const stopCoordinates = [];
private writeStopsToFormService() {
const stops = [];
this.stops.value.forEach(stop => {
if (stop.stopCoordinates instanceof Array) {
stopCoordinates.push(stop.stopCoordinates);
stops.push(stop);
}
});
this.routingFormService.setStopsCoordinates(stopCoordinates);
return stopCoordinates;
this.routingFormService.setStops(stops);
}

addStop(): void {
Expand Down Expand Up @@ -439,7 +430,8 @@ export class RoutingFormComponent implements OnInit, AfterViewInit, OnDestroy {
onFormChange() {
if (this.stopsForm.valid) {
this.routingRoutesOverlayDataSource.ol.clear();
const coords = this.getStopsCoordinates();
this.writeStopsToFormService();
const coords = this.routingFormService.getStopsCoordinates();
if (coords.length >= 2) {
this.getRoutes(coords);
} else {
Expand Down Expand Up @@ -923,30 +915,32 @@ export class RoutingFormComponent implements OnInit, AfterViewInit, OnDestroy {
private handleTermChanged(term: string) {
if (term !== undefined || term.length !== 0) {
const searchProposals = [];
if (this.search$$) {
this.search$$.unsubscribe();
}
const researches = this.searchService.search(term, {searchType: 'Feature'});
researches.map(res =>
this.routesQueries$$.push(
res.request.subscribe(results => {
results
.filter(r => r.data.geometry)
.forEach(element => {
if (
searchProposals.filter(r => r.source === element.source)
.length === 0
) {
searchProposals.push({
source: element.source,
meta: element.meta,
results: results.map(r => r.data)
});
}
});
this.stops
.at(this.currentStopIndex)
.patchValue({ stopProposals: searchProposals });
this.changeDetectorRefs.detectChanges();
})
)
this.search$$ =
res.request.subscribe(results => {
results
.filter(r => r.data.geometry)
.forEach(element => {
if (
searchProposals.filter(r => r.source === element.source)
.length === 0
) {
searchProposals.push({
source: element.source,
meta: element.meta,
results: results.map(r => r.data)
});
}
});
this.stops
.at(this.currentStopIndex)
.patchValue({ stopProposals: searchProposals });
this.changeDetectorRefs.detectChanges();
})
);
}
}
Expand Down Expand Up @@ -988,28 +982,13 @@ export class RoutingFormComponent implements OnInit, AfterViewInit, OnDestroy {
if (geom.type === 'Point') {
geomCoord = geom.coordinates;
} else if (geom.type.search('Line') >= 0) {
let coordArray = [];
if (geom.coordinates instanceof Array) {
// Middle segment of multilinestring
coordArray =
geom.coordinates[Math.floor(geom.coordinates.length / 2)];
} else {
coordArray = geom.coordinates;
}
// middle point of coords
geomCoord = coordArray[Math.floor(coordArray.length / 2)];
} else if (geom.type.search('Polygon') >= 0 && proposal.extent) {
const polygonExtent = proposal.extent;
const long =
polygonExtent[0] + (polygonExtent[2] - polygonExtent[0]) / 2;
const lat =
polygonExtent[1] + (polygonExtent[3] - polygonExtent[1]) / 2;
geomCoord = [long, lat];
} else if (geom.type.search('Polygon') >= 0 && !proposal.extent) {
const line = (new OlGeoJSON()).readFeatures(geom);
geomCoord = line[0].getGeometry().getFirstCoordinate();
geomCoord = [geomCoord[0], geomCoord[1]];
} else if (geom.type.search('Polygon') >= 0) {
const poly = (new OlGeoJSON()).readFeatures(geom);
// get the first feature of a multipolygon OR from the single feature of polygon.
geomCoord = poly[0].getGeometry().getInteriorPoints().getCoordinates() || poly.getGeometry().getInteriorPoints().getCoordinates();
geomCoord = [geomCoord[0][0], geomCoord[0][1]];
geomCoord = poly[0].getGeometry().getInteriorPoints().getCoordinates();
geomCoord = [geomCoord[0], geomCoord[1]];
}

if (geomCoord !== undefined) {
Expand Down
19 changes: 15 additions & 4 deletions packages/geo/src/lib/routing/routing-form/routing-form.service.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
import { Injectable } from '@angular/core';
import { Stop } from '../shared/routing.interface';

@Injectable()
export class RoutingFormService {
private stopsCoordinates: [number, number][];
private stops: Stop[];

constructor() {}

getStopsCoordinates(): [number, number][] {
return this.stopsCoordinates;
const stopsCoordinates = [];
if (this.stops) {
this.stops.forEach(stop => {
stopsCoordinates.push(stop.stopCoordinates);
});
}
return stopsCoordinates;
}

setStopsCoordinates(stopsCoordinates) {
this.stopsCoordinates = stopsCoordinates;
setStops(stops: Stop[]) {
this.stops = stops;
}

getStops() {
return this.stops;
}

}
7 changes: 7 additions & 0 deletions packages/geo/src/lib/routing/shared/routing.interface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { GeoJsonGeometryTypes } from 'geojson';
import { RoutingFormat, SourceRoutingType } from './routing.enum';

export interface Stop {
stopPoint?: string;
stopProposals?: [];
routingText?: string;
stopCoordinates?: [number, number];
}

export interface Routing {
id: string;
source: string;
Expand Down
Loading

0 comments on commit 2973ec5

Please sign in to comment.