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
Show file tree
Hide file tree
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
Expand Up @@ -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
Expand Up @@ -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>
Expand Down
6 changes: 6 additions & 0 deletions src/interaction/TrackData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Up @@ -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';
Expand All @@ -18,7 +17,6 @@ import {Point} from 'ol/geom';
export interface Options {
map: Map;
trackLayer: VectorLayer<VectorSource>
trackData: TrackData
style: StyleLike | FlatStyleLike

/**
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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);
Expand Down
9 changes: 2 additions & 7 deletions src/interaction/TrackInteractionModify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -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;
Expand Down Expand Up @@ -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>}
*/
Expand Down Expand Up @@ -106,8 +103,6 @@ export default class Modify extends PointerInteraction {
updateWhileAnimating: true,
updateWhileInteracting: true
});

this.trackData_ = options.trackData;
}


Expand Down Expand Up @@ -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_];
Expand Down
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';
Expand Down Expand Up @@ -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_;
Expand All @@ -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;
Expand All @@ -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,
Expand All @@ -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);
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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_();
Expand All @@ -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_();
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
};
Expand All @@ -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));
}
Expand All @@ -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);
}
Expand All @@ -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) {
Expand All @@ -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();
Expand Down