Skip to content

wip: add multi line support #211

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions demos/simple/demo.js
Original file line number Diff line number Diff line change
@@ -124,6 +124,10 @@ function main() {
}
trackManager.addPOI(poiOverlay, onAddListener)
});

document.querySelector('#createNewPart').addEventListener('click', () => {
trackManager.createNewPart();
});
}

main();
2 changes: 2 additions & 0 deletions demos/simple/simple.html
Original file line number Diff line number Diff line change
@@ -56,6 +56,8 @@
<button id="poiCancel">Cancel</button>
<button id="poiSave">Save</button>
</div>
<br />
<a href="#" id="createNewPart">Add a new line string</a>
</div>
<div id="map"></div>
</main>
6 changes: 6 additions & 0 deletions src/interaction/TrackData.ts
Original file line number Diff line number Diff line change
@@ -119,6 +119,7 @@ export default class TrackData {
point.set('type', 'controlPoint');
console.assert(index >= 0 && index <= this.controlPoints.length);
// add new control point
point.set('trackData', this);
this.controlPoints.splice(index, 0, point);

// remove segment
@@ -368,3 +369,8 @@ function createStraightSegment(featureFrom: Feature<Point>, featureTo: Feature<P

return segment;
}


export function trackData(controlPoint: Feature<Point>): TrackData {
return controlPoint.get('trackData') as TrackData;
}
7 changes: 2 additions & 5 deletions src/interaction/TrackInteraction.ts
Original file line number Diff line number Diff line change
@@ -8,7 +8,6 @@ import {FALSE} from 'ol/functions';
import type {Feature, Map, MapBrowserEvent} from 'ol';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import TrackData from './TrackData';
import type {StyleLike} from 'ol/style/Style';
import type {FlatStyleLike} from 'ol/style/flat';
import type {Pixel} from 'ol/pixel';
@@ -18,7 +17,6 @@ import {Point} from 'ol/geom';
export interface Options {
map: Map;
trackLayer: VectorLayer<VectorSource>
trackData: TrackData
style: StyleLike | FlatStyleLike

/**
@@ -86,9 +84,8 @@ export default class TrackInteraction extends Interaction {
return draw;
}

createModifyInteraction(trackData: TrackData, source: VectorSource, style: StyleLike | FlatStyleLike, hitTolerance: number): Modify {
createModifyInteraction(source: VectorSource, style: StyleLike | FlatStyleLike, hitTolerance: number): Modify {
const modify = new Modify({
trackData: trackData,
source: source,
style: style,
condition: (event) => !this.deleteCondition_(event),
@@ -146,7 +143,7 @@ export default class TrackInteraction extends Interaction {
source.on('removefeature', () => requestAnimationFrame(() => this.modifyTrack_.updateSketchFeature()));

this.drawTrack_ = this.createDrawInteraction(source);
this.modifyTrack_ = this.createModifyInteraction(options.trackData, source, options.style, options.hitTolerance);
this.modifyTrack_ = this.createModifyInteraction(source, options.style, options.hitTolerance);
this.deletePoint_ = this.createSelectInteraction(options.trackLayer);

this.setActive(false);
9 changes: 2 additions & 7 deletions src/interaction/TrackInteractionModify.ts
Original file line number Diff line number Diff line change
@@ -6,12 +6,11 @@ import LineString from 'ol/geom/LineString.js';
import Point from 'ol/geom/Point.js';
import Event from 'ol/events/Event.js';
import {Geometry} from 'ol/geom';
import TrackData from './TrackData';
import {Map, MapBrowserEvent} from 'ol';
import type {StyleLike} from 'ol/style/Style.js';
import type {FlatStyleLike} from 'ol/style/flat.js';
import type {Pixel} from 'ol/pixel.js';
import type {FeatureType} from './TrackData.js';
import {trackData, type FeatureType} from './TrackData.js';

export class ModifyEvent extends Event {

@@ -32,7 +31,6 @@ export class ModifyEvent extends Event {

export interface Options {
source: VectorSource<FeatureLike>;
trackData: TrackData;
style: StyleLike | FlatStyleLike;
condition: (mbe: MapBrowserEvent<UIEvent>) => boolean;
addControlPointCondition: (mbe: MapBrowserEvent<UIEvent>) => boolean;
@@ -65,7 +63,6 @@ export default class Modify extends PointerInteraction {
});
private overlay_: VectorLayer<VectorSource<Feature>>;
private lastPixel_ = [0, 0];
private trackData_: Options['trackData'];
/**
* @type {Feature<Point>}
*/
@@ -106,8 +103,6 @@ export default class Modify extends PointerInteraction {
updateWhileAnimating: true,
updateWhileInteracting: true
});

this.trackData_ = options.trackData;
}


@@ -231,7 +226,7 @@ export default class Modify extends PointerInteraction {
// we create a 3 points linestring, doubled if end points clicked
console.assert(this.feature_.getGeometry().getType() === 'Point', this.feature_.getProperties());
const f = this.feature_ as Feature<Point>;
const {before, after} = this.trackData_.getAdjacentSegments(f);
const {before, after} = trackData(f).getAdjacentSegments(f);
if (!before && !after) {
// single point case
this.involvedFeatures_ = [this.feature_];
34 changes: 26 additions & 8 deletions src/interaction/TrackManager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Feature from 'ol/Feature.js';
import Point from 'ol/geom/Point.js';

import TrackData from './TrackData';
import TrackData, { trackData } from './TrackData';
import TrackUpdater from './TrackUpdater';
import TrackInteraction from './TrackInteraction';
import HistoryManager from './HistoryManager';
@@ -73,7 +73,8 @@ export default class TrackManager<POIMeta> {
private trackChangeEventListeners_: Function[] = [];
// eslint-disable-next-line @typescript-eslint/ban-types
private trackHoverEventListeners_: Function[] = [];
private trackData_ = new TrackData();
// the data for the current line
private trackData_: TrackData;
private router_: Router;
get router(): Router {
return this.router_;
@@ -85,6 +86,7 @@ export default class TrackManager<POIMeta> {
private updater_: TrackUpdater;
private interaction_: TrackInteraction;
private historyManager_ = new HistoryManager<Feature<Point|LineString>[]>();
parts: TrackData[] = [];

constructor(options: Options) {
this.map_ = options.map;
@@ -96,15 +98,16 @@ export default class TrackManager<POIMeta> {

this.router_ = options.router;
this.profiler_ = options.profiler;

this.createNewPart();

this.updater_ = new TrackUpdater({
profiler: this.profiler_,
router: this.router_,
trackData: this.trackData_
});

this.interaction_ = new TrackInteraction({
style: options.style,
trackData: this.trackData_,
trackLayer: this.trackLayer_,
map: this.map_,
deleteCondition: options.deleteCondition,
@@ -131,6 +134,7 @@ export default class TrackManager<POIMeta> {
if (!this.snapping) {
feature.set('snapped', false);
}
// this is what we want: the new point is added to the current line
const {pointFrom, pointTo, segment} = this.trackData_.pushControlPoint(feature);
if (segment) {
this.source_.addFeature(segment);
@@ -142,7 +146,7 @@ export default class TrackManager<POIMeta> {
}
});


// FIXME: check this
const debouncedMapToProfileUpdater = debounce(
(coordinate: Coordinate, hover: boolean) => {
if (hover && this.trackData_.getSegments().length > 0) {
@@ -175,17 +179,20 @@ export default class TrackManager<POIMeta> {
const type = event.feature.get('type') as FeatureType;

if (type === 'POI') {
// FIXME: check this
this.trackData_.updatePOIIndexes();
this.onTrackChanged_();
} else if (type === 'controlPoint') {
const feature = event.feature as Feature<Point>;
await this.updater_.updateAdjacentSegmentsGeometries(feature, this.snapping);
this.updater_.changeAdjacentSegmentsStyling(feature, '');
await this.updater_.computeAdjacentSegmentsProfile(feature);
// FIXME: check this
this.trackData_.updatePOIIndexes();
this.onTrackChanged_();
} else if (type === 'segment') {
const feature = event.feature as Feature<LineString>;
// FIXME: check this
const indexOfSegment = this.trackData_.getSegments().indexOf(feature);

console.assert(indexOfSegment >= 0);
@@ -218,12 +225,12 @@ export default class TrackManager<POIMeta> {
console.assert(selected.getGeometry().getType() === 'Point');
const type = selected.get('type') as FeatureType;
if (type === 'POI') {
this.trackData_.deletePOI(selected);
trackData(selected).deletePOI(selected);
this.source_.removeFeature(selected);
this.onTrackChanged_();
} else {
// control point
const {deleted, pointBefore, pointAfter, newSegment} = this.trackData_.deleteControlPoint(selected);
const {deleted, pointBefore, pointAfter, newSegment} = trackData(selected).deleteControlPoint(selected);

// remove deleted features from source
deleted.forEach(f => this.source_.removeFeature(f));
@@ -362,11 +369,13 @@ export default class TrackManager<POIMeta> {
private clearInternal_() {
this.source_.clear();
this.trackData_.clear();
// FIXME: remove all parts ?
}

/**
*/
clear() {
// FIXME: check this
if (this.trackData_.hasData()) {
this.clearInternal_()
this.onTrackChanged_();
@@ -386,6 +395,7 @@ export default class TrackManager<POIMeta> {
}

async restoreFeatures(features: Feature<Point|LineString>[]): Promise<void> {
// FIXME: check this
this.clearInternal_();
await this.restoreFeaturesInternal_(features);
this.onTrackChanged_();
@@ -444,6 +454,7 @@ export default class TrackManager<POIMeta> {
* Delete a POI and notify track change listeners.
*/
deletePOI(index: number) {
// FIXME: check this
const poi = this.trackData_.getPOIs().find(feature => feature.get('index') === index);
const feature = this.source_.getFeatures().find(feature => feature.get('type') === 'POI' && feature.get('index') === index);
this.source_.removeFeature(feature);
@@ -568,4 +579,11 @@ export default class TrackManager<POIMeta> {
this.source_.changed();
this.shadowTrackLayer_.getSource().changed();
}
}

// Add a new line string and set it add the "current" line string
createNewPart() {
this.trackData_ = new TrackData();

this.parts.push(this.trackData_);
}
}
20 changes: 10 additions & 10 deletions src/interaction/TrackUpdater.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import type Point from 'ol/geom/Point.js';
import type Feature from 'ol/Feature.js';
import type TrackData from './TrackData';
import type {Router} from '../router/index';
import type {Profiler} from '../profiler/index';
import {equals} from 'ol/coordinate';
import { trackData } from './TrackData';

type TrackUpdaterOptions = {
trackData: TrackData;
router: Router;
profiler: Profiler;
};
@@ -16,20 +15,18 @@ type TrackUpdaterOptions = {
* Drive the chosen router to update the segment geometries.
*/
export default class TrackUpdater {
private trackData: TrackData;
private profiler: Profiler;
private router: Router;

constructor(options: TrackUpdaterOptions) {
this.trackData = options.trackData;
this.profiler = options.profiler;
this.router = options.router;
}

computeAdjacentSegmentsProfile(modifiedControlPoint: Feature<Point>): Promise<any> {
const promises = [];
if (modifiedControlPoint) {
const {before, after} = this.trackData.getAdjacentSegments(modifiedControlPoint);
const {before, after} = trackData(modifiedControlPoint).getAdjacentSegments(modifiedControlPoint);
if (before) {
promises.push(this.profiler.computeProfile(before));
}
@@ -42,7 +39,7 @@ export default class TrackUpdater {

changeAdjacentSegmentsStyling(modifiedControlPoint: Feature<Point>, subtype: string) {
if (modifiedControlPoint) {
const {before, after} = this.trackData.getAdjacentSegments(modifiedControlPoint);
const {before, after} = trackData(modifiedControlPoint).getAdjacentSegments(modifiedControlPoint);
if (before) {
before.set('subtype', subtype);
}
@@ -54,9 +51,9 @@ export default class TrackUpdater {

async updateAdjacentSegmentsGeometries(modifiedControlPoint: Feature<Point>, snapping: boolean): Promise<any> {
if (modifiedControlPoint) {
const {before, after} = this.trackData.getAdjacentSegments(modifiedControlPoint);
const pointFrom = this.trackData.getControlPointBefore(modifiedControlPoint);
const pointTo = this.trackData.getControlPointAfter(modifiedControlPoint);
const {before, after} = trackData(modifiedControlPoint).getAdjacentSegments(modifiedControlPoint);
const pointFrom = trackData(modifiedControlPoint).getControlPointBefore(modifiedControlPoint);
const pointTo = trackData(modifiedControlPoint).getControlPointAfter(modifiedControlPoint);
modifiedControlPoint.set('snapped', snapping ? undefined : false);
const geometryUpdates = [];
if (before) {
@@ -83,7 +80,10 @@ export default class TrackUpdater {

// If needed, equalize the control point, the segment before and after to all share the same coordinate.
equalizeCoordinates(controlPoint: Feature<Point>) {
const {before, after} = this.trackData.getAdjacentSegments(controlPoint);
if (!controlPoint) {
return;
}
const {before, after} = trackData(controlPoint).getAdjacentSegments(controlPoint);
if (before && after) {
const firstCoordinate = before.getGeometry().getLastCoordinate();
const lastCoordinate = after.getGeometry().getFirstCoordinate();