Skip to content

Commit d1af18a

Browse files
committed
wip: add multi line support
1 parent 523fd2d commit d1af18a

File tree

7 files changed

+52
-30
lines changed

7 files changed

+52
-30
lines changed

demos/simple/demo.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ function main() {
124124
}
125125
trackManager.addPOI(poiOverlay, onAddListener)
126126
});
127+
128+
document.querySelector('#createNewPart').addEventListener('click', () => {
129+
trackManager.createNewPart();
130+
});
127131
}
128132

129133
main();

demos/simple/simple.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
<button id="poiCancel">Cancel</button>
5757
<button id="poiSave">Save</button>
5858
</div>
59+
<br />
60+
<a href="#" id="createNewPart">Add a new line string</a>
5961
</div>
6062
<div id="map"></div>
6163
</main>

src/interaction/TrackData.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ export default class TrackData {
119119
point.set('type', 'controlPoint');
120120
console.assert(index >= 0 && index <= this.controlPoints.length);
121121
// add new control point
122+
point.set('trackData', this);
122123
this.controlPoints.splice(index, 0, point);
123124

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

369370
return segment;
370371
}
372+
373+
374+
export function trackData(controlPoint: Feature<Point>): TrackData {
375+
return controlPoint.get('trackData') as TrackData;
376+
}

src/interaction/TrackInteraction.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {FALSE} from 'ol/functions';
88
import type {Feature, Map, MapBrowserEvent} from 'ol';
99
import VectorLayer from 'ol/layer/Vector';
1010
import VectorSource from 'ol/source/Vector';
11-
import TrackData from './TrackData';
1211
import type {StyleLike} from 'ol/style/Style';
1312
import type {FlatStyleLike} from 'ol/style/flat';
1413
import type {Pixel} from 'ol/pixel';
@@ -18,7 +17,6 @@ import {Point} from 'ol/geom';
1817
export interface Options {
1918
map: Map;
2019
trackLayer: VectorLayer<VectorSource>
21-
trackData: TrackData
2220
style: StyleLike | FlatStyleLike
2321

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

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

148145
this.drawTrack_ = this.createDrawInteraction(source);
149-
this.modifyTrack_ = this.createModifyInteraction(options.trackData, source, options.style, options.hitTolerance);
146+
this.modifyTrack_ = this.createModifyInteraction(source, options.style, options.hitTolerance);
150147
this.deletePoint_ = this.createSelectInteraction(options.trackLayer);
151148

152149
this.setActive(false);

src/interaction/TrackInteractionModify.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ import LineString from 'ol/geom/LineString.js';
66
import Point from 'ol/geom/Point.js';
77
import Event from 'ol/events/Event.js';
88
import {Geometry} from 'ol/geom';
9-
import TrackData from './TrackData';
109
import {Map, MapBrowserEvent} from 'ol';
1110
import type {StyleLike} from 'ol/style/Style.js';
1211
import type {FlatStyleLike} from 'ol/style/flat.js';
1312
import type {Pixel} from 'ol/pixel.js';
14-
import type {FeatureType} from './TrackData.js';
13+
import {trackData, type FeatureType} from './TrackData.js';
1514

1615
export class ModifyEvent extends Event {
1716

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

3332
export interface Options {
3433
source: VectorSource<FeatureLike>;
35-
trackData: TrackData;
3634
style: StyleLike | FlatStyleLike;
3735
condition: (mbe: MapBrowserEvent<UIEvent>) => boolean;
3836
addControlPointCondition: (mbe: MapBrowserEvent<UIEvent>) => boolean;
@@ -65,7 +63,6 @@ export default class Modify extends PointerInteraction {
6563
});
6664
private overlay_: VectorLayer<VectorSource<Feature>>;
6765
private lastPixel_ = [0, 0];
68-
private trackData_: Options['trackData'];
6966
/**
7067
* @type {Feature<Point>}
7168
*/
@@ -106,8 +103,6 @@ export default class Modify extends PointerInteraction {
106103
updateWhileAnimating: true,
107104
updateWhileInteracting: true
108105
});
109-
110-
this.trackData_ = options.trackData;
111106
}
112107

113108

@@ -231,7 +226,7 @@ export default class Modify extends PointerInteraction {
231226
// we create a 3 points linestring, doubled if end points clicked
232227
console.assert(this.feature_.getGeometry().getType() === 'Point', this.feature_.getProperties());
233228
const f = this.feature_ as Feature<Point>;
234-
const {before, after} = this.trackData_.getAdjacentSegments(f);
229+
const {before, after} = trackData(f).getAdjacentSegments(f);
235230
if (!before && !after) {
236231
// single point case
237232
this.involvedFeatures_ = [this.feature_];

src/interaction/TrackManager.ts

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Feature from 'ol/Feature.js';
22
import Point from 'ol/geom/Point.js';
33

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

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

9799
this.router_ = options.router;
98100
this.profiler_ = options.profiler;
101+
102+
this.createNewPart();
103+
99104
this.updater_ = new TrackUpdater({
100105
profiler: this.profiler_,
101106
router: this.router_,
102-
trackData: this.trackData_
103107
});
104108

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

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

177181
if (type === 'POI') {
182+
// FIXME: check this
178183
this.trackData_.updatePOIIndexes();
179184
this.onTrackChanged_();
180185
} else if (type === 'controlPoint') {
181186
const feature = event.feature as Feature<Point>;
182187
await this.updater_.updateAdjacentSegmentsGeometries(feature, this.snapping);
183188
this.updater_.changeAdjacentSegmentsStyling(feature, '');
184189
await this.updater_.computeAdjacentSegmentsProfile(feature);
190+
// FIXME: check this
185191
this.trackData_.updatePOIIndexes();
186192
this.onTrackChanged_();
187193
} else if (type === 'segment') {
188194
const feature = event.feature as Feature<LineString>;
195+
// FIXME: check this
189196
const indexOfSegment = this.trackData_.getSegments().indexOf(feature);
190197

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

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

367375
/**
368376
*/
369377
clear() {
378+
// FIXME: check this
370379
if (this.trackData_.hasData()) {
371380
this.clearInternal_()
372381
this.onTrackChanged_();
@@ -386,6 +395,7 @@ export default class TrackManager<POIMeta> {
386395
}
387396

388397
async restoreFeatures(features: Feature<Point|LineString>[]): Promise<void> {
398+
// FIXME: check this
389399
this.clearInternal_();
390400
await this.restoreFeaturesInternal_(features);
391401
this.onTrackChanged_();
@@ -444,6 +454,7 @@ export default class TrackManager<POIMeta> {
444454
* Delete a POI and notify track change listeners.
445455
*/
446456
deletePOI(index: number) {
457+
// FIXME: check this
447458
const poi = this.trackData_.getPOIs().find(feature => feature.get('index') === index);
448459
const feature = this.source_.getFeatures().find(feature => feature.get('type') === 'POI' && feature.get('index') === index);
449460
this.source_.removeFeature(feature);
@@ -568,4 +579,11 @@ export default class TrackManager<POIMeta> {
568579
this.source_.changed();
569580
this.shadowTrackLayer_.getSource().changed();
570581
}
571-
}
582+
583+
// Add a new line string and set it add the "current" line string
584+
createNewPart() {
585+
this.trackData_ = new TrackData();
586+
587+
this.parts.push(this.trackData_);
588+
}
589+
}

src/interaction/TrackUpdater.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import type Point from 'ol/geom/Point.js';
22
import type Feature from 'ol/Feature.js';
3-
import type TrackData from './TrackData';
43
import type {Router} from '../router/index';
54
import type {Profiler} from '../profiler/index';
65
import {equals} from 'ol/coordinate';
6+
import { trackData } from './TrackData';
77

88
type TrackUpdaterOptions = {
9-
trackData: TrackData;
109
router: Router;
1110
profiler: Profiler;
1211
};
@@ -16,20 +15,18 @@ type TrackUpdaterOptions = {
1615
* Drive the chosen router to update the segment geometries.
1716
*/
1817
export default class TrackUpdater {
19-
private trackData: TrackData;
2018
private profiler: Profiler;
2119
private router: Router;
2220

2321
constructor(options: TrackUpdaterOptions) {
24-
this.trackData = options.trackData;
2522
this.profiler = options.profiler;
2623
this.router = options.router;
2724
}
2825

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

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

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

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

0 commit comments

Comments
 (0)