ol 10.6.2-dev.1753992384159 → 10.6.2-dev.1754054564182
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Collection.d.ts +1 -1
- package/Collection.js +4 -4
- package/dist/ol.js +1 -1
- package/dist/ol.js.map +1 -1
- package/interaction/Draw.d.ts +3 -62
- package/interaction/Draw.d.ts.map +1 -1
- package/interaction/Draw.js +12 -387
- package/interaction/Modify.d.ts +93 -59
- package/interaction/Modify.d.ts.map +1 -1
- package/interaction/Modify.js +486 -94
- package/interaction/tracing.d.ts +103 -0
- package/interaction/tracing.d.ts.map +1 -0
- package/interaction/tracing.js +409 -0
- package/package.json +1 -1
- package/util.js +1 -1
package/interaction/Modify.js
CHANGED
|
@@ -18,6 +18,7 @@ import EventType from '../events/EventType.js';
|
|
|
18
18
|
import {
|
|
19
19
|
altKeyOnly,
|
|
20
20
|
always,
|
|
21
|
+
never,
|
|
21
22
|
primaryAction,
|
|
22
23
|
singleClick,
|
|
23
24
|
} from '../events/condition.js';
|
|
@@ -42,6 +43,11 @@ import RBush from '../structs/RBush.js';
|
|
|
42
43
|
import {createEditingStyle} from '../style/Style.js';
|
|
43
44
|
import {getUid} from '../util.js';
|
|
44
45
|
import PointerInteraction from './Pointer.js';
|
|
46
|
+
import {
|
|
47
|
+
getCoordinate,
|
|
48
|
+
getTraceTargetUpdate,
|
|
49
|
+
getTraceTargets,
|
|
50
|
+
} from './tracing.js';
|
|
45
51
|
|
|
46
52
|
/**
|
|
47
53
|
* The segment index assigned to a circle's center when
|
|
@@ -130,12 +136,36 @@ const ModifyEventType = {
|
|
|
130
136
|
* @property {Collection<Feature>} [features]
|
|
131
137
|
* The features the interaction works on. If a feature collection is not
|
|
132
138
|
* provided, a vector source must be provided with the `source` option.
|
|
139
|
+
* @property {boolean|import("../events/condition.js").Condition} [trace=false] Trace a portion of another geometry.
|
|
140
|
+
* Tracing starts when two neighboring vertices are dragged onto a trace target, without any other modification in between..
|
|
141
|
+
* @property {VectorSource} [traceSource] Source for features to trace. If tracing is active and a `traceSource` is
|
|
142
|
+
* not provided, the interaction's `source` will be used. Tracing requires that the interaction is configured with
|
|
143
|
+
* either a `traceSource` or a `source`.
|
|
133
144
|
* @property {boolean} [wrapX=false] Wrap the world horizontally on the sketch
|
|
134
145
|
* overlay.
|
|
135
146
|
* @property {boolean} [snapToPointer=!hitDetection] The vertex, point or segment being modified snaps to the
|
|
136
147
|
* pointer coordinate when clicked within the `pixelTolerance`.
|
|
137
148
|
*/
|
|
138
149
|
|
|
150
|
+
function getCoordinatesArray(coordinates, geometryType, depth) {
|
|
151
|
+
let coordinatesArray;
|
|
152
|
+
switch (geometryType) {
|
|
153
|
+
case 'LineString':
|
|
154
|
+
coordinatesArray = coordinates;
|
|
155
|
+
break;
|
|
156
|
+
case 'MultiLineString':
|
|
157
|
+
case 'Polygon':
|
|
158
|
+
coordinatesArray = coordinates[depth[0]];
|
|
159
|
+
break;
|
|
160
|
+
case 'MultiPolygon':
|
|
161
|
+
coordinatesArray = coordinates[depth[1]][depth[0]];
|
|
162
|
+
break;
|
|
163
|
+
default:
|
|
164
|
+
// pass
|
|
165
|
+
}
|
|
166
|
+
return coordinatesArray;
|
|
167
|
+
}
|
|
168
|
+
|
|
139
169
|
/**
|
|
140
170
|
* @classdesc
|
|
141
171
|
* Events emitted by {@link module:ol/interaction/Modify~Modify} instances are
|
|
@@ -270,10 +300,10 @@ class Modify extends PointerInteraction {
|
|
|
270
300
|
this.vertexSegments_ = null;
|
|
271
301
|
|
|
272
302
|
/**
|
|
273
|
-
* @type {import("../
|
|
303
|
+
* @type {import("../coordinate.js").Coordinate}
|
|
274
304
|
* @private
|
|
275
305
|
*/
|
|
276
|
-
this.
|
|
306
|
+
this.lastCoordinate_ = [0, 0];
|
|
277
307
|
|
|
278
308
|
/**
|
|
279
309
|
* Tracks if the next `singleclick` event should be ignored to prevent
|
|
@@ -344,15 +374,15 @@ class Modify extends PointerInteraction {
|
|
|
344
374
|
* @type {!Object<string, function(Feature, import("../geom/Geometry.js").default): void>}
|
|
345
375
|
*/
|
|
346
376
|
this.SEGMENT_WRITERS_ = {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
377
|
+
Point: this.writePointGeometry_.bind(this),
|
|
378
|
+
LineString: this.writeLineStringGeometry_.bind(this),
|
|
379
|
+
LinearRing: this.writeLineStringGeometry_.bind(this),
|
|
380
|
+
Polygon: this.writePolygonGeometry_.bind(this),
|
|
381
|
+
MultiPoint: this.writeMultiPointGeometry_.bind(this),
|
|
382
|
+
MultiLineString: this.writeMultiLineStringGeometry_.bind(this),
|
|
383
|
+
MultiPolygon: this.writeMultiPolygonGeometry_.bind(this),
|
|
384
|
+
Circle: this.writeCircleGeometry_.bind(this),
|
|
385
|
+
GeometryCollection: this.writeGeometryCollectionGeometry_.bind(this),
|
|
356
386
|
};
|
|
357
387
|
|
|
358
388
|
/**
|
|
@@ -361,6 +391,31 @@ class Modify extends PointerInteraction {
|
|
|
361
391
|
*/
|
|
362
392
|
this.source_ = null;
|
|
363
393
|
|
|
394
|
+
/**
|
|
395
|
+
* @type {VectorSource|null}
|
|
396
|
+
* @private
|
|
397
|
+
*/
|
|
398
|
+
this.traceSource_ = options.traceSource || options.source || null;
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* @type {import("../events/condition.js").Condition}
|
|
402
|
+
* @private
|
|
403
|
+
*/
|
|
404
|
+
this.traceCondition_;
|
|
405
|
+
this.setTrace(options.trace || false);
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* @type {import('./tracing.js').TraceState}
|
|
409
|
+
* @private
|
|
410
|
+
*/
|
|
411
|
+
this.traceState_ = {active: false};
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* @type {Array<DragSegment>|null}
|
|
415
|
+
* @private
|
|
416
|
+
*/
|
|
417
|
+
this.traceSegments_ = null;
|
|
418
|
+
|
|
364
419
|
/**
|
|
365
420
|
* @type {boolean|import("../layer/BaseVector").default}
|
|
366
421
|
* @private
|
|
@@ -430,6 +485,24 @@ class Modify extends PointerInteraction {
|
|
|
430
485
|
: options.snapToPointer;
|
|
431
486
|
}
|
|
432
487
|
|
|
488
|
+
/**
|
|
489
|
+
* Toggle tracing mode or set a tracing condition.
|
|
490
|
+
*
|
|
491
|
+
* @param {boolean|import("../events/condition.js").Condition} trace A boolean to toggle tracing mode or an event
|
|
492
|
+
* condition that will be checked when a feature is clicked to determine if tracing should be active.
|
|
493
|
+
*/
|
|
494
|
+
setTrace(trace) {
|
|
495
|
+
let condition;
|
|
496
|
+
if (!trace) {
|
|
497
|
+
condition = never;
|
|
498
|
+
} else if (trace === true) {
|
|
499
|
+
condition = always;
|
|
500
|
+
} else {
|
|
501
|
+
condition = trace;
|
|
502
|
+
}
|
|
503
|
+
this.traceCondition_ = condition;
|
|
504
|
+
}
|
|
505
|
+
|
|
433
506
|
/**
|
|
434
507
|
* @param {Feature} feature Feature.
|
|
435
508
|
* @private
|
|
@@ -444,7 +517,7 @@ class Modify extends PointerInteraction {
|
|
|
444
517
|
}
|
|
445
518
|
const map = this.getMap();
|
|
446
519
|
if (map && map.isRendered() && this.getActive()) {
|
|
447
|
-
this.handlePointerAtPixel_(
|
|
520
|
+
this.handlePointerAtPixel_(this.lastCoordinate_);
|
|
448
521
|
}
|
|
449
522
|
feature.addEventListener(EventType.CHANGE, this.boundHandleFeatureChange_);
|
|
450
523
|
}
|
|
@@ -878,6 +951,11 @@ class Modify extends PointerInteraction {
|
|
|
878
951
|
return super.handleEvent(mapBrowserEvent) && !handled;
|
|
879
952
|
}
|
|
880
953
|
|
|
954
|
+
/**
|
|
955
|
+
* @param {import("../coordinate.js").Coordinate} pixelCoordinate Pixel coordinate.
|
|
956
|
+
* @return {Array<SegmentData>|undefined} Insert vertices and update drag segments.
|
|
957
|
+
* @private
|
|
958
|
+
*/
|
|
881
959
|
findInsertVerticesAndUpdateDragSegments_(pixelCoordinate) {
|
|
882
960
|
this.handlePointerAtPixel_(pixelCoordinate);
|
|
883
961
|
this.dragSegments_.length = 0;
|
|
@@ -888,8 +966,9 @@ class Modify extends PointerInteraction {
|
|
|
888
966
|
}
|
|
889
967
|
|
|
890
968
|
const projection = this.getMap().getView().getProjection();
|
|
969
|
+
/** @type {Array<SegmentData>} */
|
|
891
970
|
const insertVertices = [];
|
|
892
|
-
const vertex =
|
|
971
|
+
const vertex = this.vertexFeature_.getGeometry().getCoordinates();
|
|
893
972
|
const vertexExtent = boundingExtent([vertex]);
|
|
894
973
|
const segmentDataMatches = this.rBush_.getInExtent(vertexExtent);
|
|
895
974
|
const componentSegments = {};
|
|
@@ -974,6 +1053,370 @@ class Modify extends PointerInteraction {
|
|
|
974
1053
|
return insertVertices;
|
|
975
1054
|
}
|
|
976
1055
|
|
|
1056
|
+
/**
|
|
1057
|
+
* @private
|
|
1058
|
+
*/
|
|
1059
|
+
deactivateTrace_() {
|
|
1060
|
+
this.traceState_ = {active: false};
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
/**
|
|
1064
|
+
* Update the trace.
|
|
1065
|
+
* @param {import("../MapBrowserEvent.js").default} event Event.
|
|
1066
|
+
* @private
|
|
1067
|
+
*/
|
|
1068
|
+
updateTrace_(event) {
|
|
1069
|
+
const traceState = this.traceState_;
|
|
1070
|
+
if (!traceState.active) {
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
if (traceState.targetIndex === -1) {
|
|
1075
|
+
// check if we are ready to pick a target
|
|
1076
|
+
const startPx = event.map.getPixelFromCoordinate(traceState.startCoord);
|
|
1077
|
+
if (coordinateDistance(startPx, event.pixel) < this.pixelTolerance_) {
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
const updatedTraceTarget = getTraceTargetUpdate(
|
|
1083
|
+
event.coordinate,
|
|
1084
|
+
traceState,
|
|
1085
|
+
event.map,
|
|
1086
|
+
this.pixelTolerance_,
|
|
1087
|
+
);
|
|
1088
|
+
|
|
1089
|
+
if (
|
|
1090
|
+
traceState.targetIndex === -1 &&
|
|
1091
|
+
Math.sqrt(updatedTraceTarget.closestTargetDistance) /
|
|
1092
|
+
event.map.getView().getResolution() >
|
|
1093
|
+
this.pixelTolerance_
|
|
1094
|
+
) {
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
if (traceState.targetIndex !== updatedTraceTarget.index) {
|
|
1099
|
+
// target changed
|
|
1100
|
+
if (traceState.targetIndex !== -1) {
|
|
1101
|
+
// remove points added during previous trace
|
|
1102
|
+
const oldTarget = traceState.targets[traceState.targetIndex];
|
|
1103
|
+
this.removeTracedCoordinates_(oldTarget.startIndex, oldTarget.endIndex);
|
|
1104
|
+
} else {
|
|
1105
|
+
for (const traceSegment of this.traceSegments_) {
|
|
1106
|
+
const segmentData = traceSegment[0];
|
|
1107
|
+
const geometry = segmentData.geometry;
|
|
1108
|
+
const index = traceSegment[1];
|
|
1109
|
+
const coordinates = geometry.getCoordinates();
|
|
1110
|
+
const coordinatesArray = getCoordinatesArray(
|
|
1111
|
+
coordinates,
|
|
1112
|
+
geometry.getType(),
|
|
1113
|
+
segmentData.depth,
|
|
1114
|
+
);
|
|
1115
|
+
coordinatesArray.splice(segmentData.index + index, 1);
|
|
1116
|
+
geometry.setCoordinates(coordinates);
|
|
1117
|
+
if (index === 0) {
|
|
1118
|
+
segmentData.index -= 1;
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
// add points for the new target
|
|
1123
|
+
const newTarget = traceState.targets[updatedTraceTarget.index];
|
|
1124
|
+
this.addTracedCoordinates_(
|
|
1125
|
+
newTarget,
|
|
1126
|
+
newTarget.startIndex,
|
|
1127
|
+
updatedTraceTarget.endIndex,
|
|
1128
|
+
);
|
|
1129
|
+
} else {
|
|
1130
|
+
// target stayed the same
|
|
1131
|
+
const target = traceState.targets[traceState.targetIndex];
|
|
1132
|
+
this.addOrRemoveTracedCoordinates_(target, updatedTraceTarget.endIndex);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
// modify the state with updated info
|
|
1136
|
+
traceState.targetIndex = updatedTraceTarget.index;
|
|
1137
|
+
const target = traceState.targets[traceState.targetIndex];
|
|
1138
|
+
target.endIndex = updatedTraceTarget.endIndex;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
getTraceCandidates_(event) {
|
|
1142
|
+
const map = this.getMap();
|
|
1143
|
+
const tolerance = this.pixelTolerance_;
|
|
1144
|
+
const lowerLeft = map.getCoordinateFromPixel([
|
|
1145
|
+
event.pixel[0] - tolerance,
|
|
1146
|
+
event.pixel[1] + tolerance,
|
|
1147
|
+
]);
|
|
1148
|
+
const upperRight = map.getCoordinateFromPixel([
|
|
1149
|
+
event.pixel[0] + tolerance,
|
|
1150
|
+
event.pixel[1] - tolerance,
|
|
1151
|
+
]);
|
|
1152
|
+
const extent = boundingExtent([lowerLeft, upperRight]);
|
|
1153
|
+
const features = this.traceSource_.getFeaturesInExtent(extent);
|
|
1154
|
+
return features;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
/**
|
|
1158
|
+
* Activate or deactivate trace state based on a browser event.
|
|
1159
|
+
* @param {import("../MapBrowserEvent.js").default} event Event.
|
|
1160
|
+
* @private
|
|
1161
|
+
*/
|
|
1162
|
+
toggleTraceState_(event) {
|
|
1163
|
+
if (!this.traceSource_ || !this.traceCondition_(event)) {
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
if (this.traceState_.active) {
|
|
1168
|
+
this.deactivateTrace_();
|
|
1169
|
+
this.traceSegments_ = null;
|
|
1170
|
+
return;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
const features = this.getTraceCandidates_(event);
|
|
1174
|
+
if (features.length === 0) {
|
|
1175
|
+
return;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
const targets = getTraceTargets(event.coordinate, features);
|
|
1179
|
+
if (targets.length) {
|
|
1180
|
+
this.traceState_ = {
|
|
1181
|
+
active: true,
|
|
1182
|
+
startCoord: event.coordinate.slice(),
|
|
1183
|
+
targets: targets,
|
|
1184
|
+
targetIndex: -1,
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
/**
|
|
1190
|
+
* @param {import('./tracing.js').TraceTarget} target The trace target.
|
|
1191
|
+
* @param {number} endIndex The new end index of the trace.
|
|
1192
|
+
* @private
|
|
1193
|
+
*/
|
|
1194
|
+
addOrRemoveTracedCoordinates_(target, endIndex) {
|
|
1195
|
+
// three cases to handle:
|
|
1196
|
+
// 1. traced in the same direction and points need adding
|
|
1197
|
+
// 2. traced in the same direction and points need removing
|
|
1198
|
+
// 3. traced in a new direction
|
|
1199
|
+
const previouslyForward = target.startIndex <= target.endIndex;
|
|
1200
|
+
const currentlyForward = target.startIndex <= endIndex;
|
|
1201
|
+
if (previouslyForward === currentlyForward) {
|
|
1202
|
+
// same direction
|
|
1203
|
+
if (
|
|
1204
|
+
(previouslyForward && endIndex > target.endIndex) ||
|
|
1205
|
+
(!previouslyForward && endIndex < target.endIndex)
|
|
1206
|
+
) {
|
|
1207
|
+
// case 1 - add new points
|
|
1208
|
+
this.addTracedCoordinates_(target, target.endIndex, endIndex);
|
|
1209
|
+
} else if (
|
|
1210
|
+
(previouslyForward && endIndex < target.endIndex) ||
|
|
1211
|
+
(!previouslyForward && endIndex > target.endIndex)
|
|
1212
|
+
) {
|
|
1213
|
+
// case 2 - remove old points
|
|
1214
|
+
this.removeTracedCoordinates_(endIndex, target.endIndex);
|
|
1215
|
+
}
|
|
1216
|
+
} else {
|
|
1217
|
+
// case 3 - remove old points, add new points
|
|
1218
|
+
this.removeTracedCoordinates_(target.startIndex, target.endIndex);
|
|
1219
|
+
this.addTracedCoordinates_(target, target.startIndex, endIndex);
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
/**
|
|
1224
|
+
* @param {number} fromIndex The start index.
|
|
1225
|
+
* @param {number} toIndex The end index.
|
|
1226
|
+
* @private
|
|
1227
|
+
*/
|
|
1228
|
+
removeTracedCoordinates_(fromIndex, toIndex) {
|
|
1229
|
+
if (fromIndex === toIndex) {
|
|
1230
|
+
return;
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
let remove = 0;
|
|
1234
|
+
if (fromIndex < toIndex) {
|
|
1235
|
+
const start = Math.ceil(fromIndex);
|
|
1236
|
+
let end = Math.floor(toIndex);
|
|
1237
|
+
if (end === toIndex) {
|
|
1238
|
+
end -= 1;
|
|
1239
|
+
}
|
|
1240
|
+
remove = end - start + 1;
|
|
1241
|
+
} else {
|
|
1242
|
+
const start = Math.floor(fromIndex);
|
|
1243
|
+
let end = Math.ceil(toIndex);
|
|
1244
|
+
if (end === toIndex) {
|
|
1245
|
+
end += 1;
|
|
1246
|
+
}
|
|
1247
|
+
remove = start - end + 1;
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
if (remove > 0) {
|
|
1251
|
+
for (const traceSegment of this.traceSegments_) {
|
|
1252
|
+
const segmentData = traceSegment[0];
|
|
1253
|
+
const geometry = segmentData.geometry;
|
|
1254
|
+
const index = traceSegment[1];
|
|
1255
|
+
let removeIndex = traceSegment[0].index + 1;
|
|
1256
|
+
if (index === 1) {
|
|
1257
|
+
removeIndex -= remove;
|
|
1258
|
+
}
|
|
1259
|
+
const coordinates = geometry.getCoordinates();
|
|
1260
|
+
const coordinatesArray = getCoordinatesArray(
|
|
1261
|
+
coordinates,
|
|
1262
|
+
geometry.getType(),
|
|
1263
|
+
segmentData.depth,
|
|
1264
|
+
);
|
|
1265
|
+
coordinatesArray.splice(removeIndex, remove);
|
|
1266
|
+
geometry.setCoordinates(coordinates);
|
|
1267
|
+
if (index === 1) {
|
|
1268
|
+
segmentData.index -= remove;
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
/**
|
|
1275
|
+
* @param {import('./tracing.js').TraceTarget} target The trace target.
|
|
1276
|
+
* @param {number} fromIndex The start index.
|
|
1277
|
+
* @param {number} toIndex The end index.
|
|
1278
|
+
* @private
|
|
1279
|
+
*/
|
|
1280
|
+
addTracedCoordinates_(target, fromIndex, toIndex) {
|
|
1281
|
+
if (fromIndex === toIndex) {
|
|
1282
|
+
return;
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
const newCoordinates = [];
|
|
1286
|
+
if (fromIndex < toIndex) {
|
|
1287
|
+
// forward trace
|
|
1288
|
+
const start = Math.ceil(fromIndex);
|
|
1289
|
+
let end = Math.floor(toIndex);
|
|
1290
|
+
if (end === toIndex) {
|
|
1291
|
+
// if end is snapped to a vertex, it will be added later
|
|
1292
|
+
end -= 1;
|
|
1293
|
+
}
|
|
1294
|
+
for (let i = start; i <= end; ++i) {
|
|
1295
|
+
newCoordinates.push(getCoordinate(target.coordinates, i));
|
|
1296
|
+
}
|
|
1297
|
+
} else {
|
|
1298
|
+
// reverse trace
|
|
1299
|
+
const start = Math.floor(fromIndex);
|
|
1300
|
+
let end = Math.ceil(toIndex);
|
|
1301
|
+
if (end === toIndex) {
|
|
1302
|
+
end += 1;
|
|
1303
|
+
}
|
|
1304
|
+
for (let i = start; i >= end; --i) {
|
|
1305
|
+
newCoordinates.push(getCoordinate(target.coordinates, i));
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
if (newCoordinates.length) {
|
|
1310
|
+
for (const traceSegment of this.traceSegments_) {
|
|
1311
|
+
const segmentData = traceSegment[0];
|
|
1312
|
+
const geometry = segmentData.geometry;
|
|
1313
|
+
const index = traceSegment[1];
|
|
1314
|
+
const insertIndex = segmentData.index + 1;
|
|
1315
|
+
if (index === 0) {
|
|
1316
|
+
newCoordinates.reverse();
|
|
1317
|
+
}
|
|
1318
|
+
const coordinates = geometry.getCoordinates();
|
|
1319
|
+
const coordinatesArray = getCoordinatesArray(
|
|
1320
|
+
coordinates,
|
|
1321
|
+
geometry.getType(),
|
|
1322
|
+
segmentData.depth,
|
|
1323
|
+
);
|
|
1324
|
+
coordinatesArray.splice(insertIndex, 0, ...newCoordinates);
|
|
1325
|
+
geometry.setCoordinates(coordinates);
|
|
1326
|
+
if (index === 1) {
|
|
1327
|
+
segmentData.index += newCoordinates.length;
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
/**
|
|
1334
|
+
* @param {import('../coordinate.js').Coordinate} vertex Vertex.
|
|
1335
|
+
* @param {DragSegment} dragSegment Drag segment.
|
|
1336
|
+
*/
|
|
1337
|
+
updateGeometry_(vertex, dragSegment) {
|
|
1338
|
+
const segmentData = dragSegment[0];
|
|
1339
|
+
const depth = segmentData.depth;
|
|
1340
|
+
let coordinates;
|
|
1341
|
+
const segment = segmentData.segment;
|
|
1342
|
+
const geometry = segmentData.geometry;
|
|
1343
|
+
const index = dragSegment[1];
|
|
1344
|
+
|
|
1345
|
+
while (vertex.length < geometry.getStride()) {
|
|
1346
|
+
vertex.push(segment[index][vertex.length]);
|
|
1347
|
+
}
|
|
1348
|
+
switch (geometry.getType()) {
|
|
1349
|
+
case 'Point':
|
|
1350
|
+
coordinates = vertex;
|
|
1351
|
+
segment[0] = vertex;
|
|
1352
|
+
segment[1] = vertex;
|
|
1353
|
+
break;
|
|
1354
|
+
case 'MultiPoint':
|
|
1355
|
+
coordinates = geometry.getCoordinates();
|
|
1356
|
+
coordinates[segmentData.index] = vertex;
|
|
1357
|
+
segment[0] = vertex;
|
|
1358
|
+
segment[1] = vertex;
|
|
1359
|
+
break;
|
|
1360
|
+
case 'LineString':
|
|
1361
|
+
coordinates = geometry.getCoordinates();
|
|
1362
|
+
coordinates[segmentData.index + index] = vertex;
|
|
1363
|
+
segment[index] = vertex;
|
|
1364
|
+
break;
|
|
1365
|
+
case 'MultiLineString':
|
|
1366
|
+
coordinates = geometry.getCoordinates();
|
|
1367
|
+
coordinates[depth[0]][segmentData.index + index] = vertex;
|
|
1368
|
+
segment[index] = vertex;
|
|
1369
|
+
break;
|
|
1370
|
+
case 'Polygon':
|
|
1371
|
+
coordinates = geometry.getCoordinates();
|
|
1372
|
+
coordinates[depth[0]][segmentData.index + index] = vertex;
|
|
1373
|
+
segment[index] = vertex;
|
|
1374
|
+
break;
|
|
1375
|
+
case 'MultiPolygon':
|
|
1376
|
+
coordinates = geometry.getCoordinates();
|
|
1377
|
+
coordinates[depth[1]][depth[0]][segmentData.index + index] = vertex;
|
|
1378
|
+
segment[index] = vertex;
|
|
1379
|
+
break;
|
|
1380
|
+
case 'Circle':
|
|
1381
|
+
const circle = /** @type {import("../geom/Circle.js").default} */ (
|
|
1382
|
+
geometry
|
|
1383
|
+
);
|
|
1384
|
+
segment[0] = vertex;
|
|
1385
|
+
segment[1] = vertex;
|
|
1386
|
+
if (segmentData.index === CIRCLE_CENTER_INDEX) {
|
|
1387
|
+
this.changingFeature_ = true;
|
|
1388
|
+
circle.setCenter(vertex);
|
|
1389
|
+
this.changingFeature_ = false;
|
|
1390
|
+
} else {
|
|
1391
|
+
// We're dragging the circle's circumference:
|
|
1392
|
+
this.changingFeature_ = true;
|
|
1393
|
+
const projection = this.getMap().getView().getProjection();
|
|
1394
|
+
let radius = coordinateDistance(
|
|
1395
|
+
fromUserCoordinate(circle.getCenter(), projection),
|
|
1396
|
+
fromUserCoordinate(vertex, projection),
|
|
1397
|
+
);
|
|
1398
|
+
const userProjection = getUserProjection();
|
|
1399
|
+
if (userProjection) {
|
|
1400
|
+
const circleGeometry = circle
|
|
1401
|
+
.clone()
|
|
1402
|
+
.transform(userProjection, projection);
|
|
1403
|
+
circleGeometry.setRadius(radius);
|
|
1404
|
+
radius = circleGeometry
|
|
1405
|
+
.transform(projection, userProjection)
|
|
1406
|
+
.getRadius();
|
|
1407
|
+
}
|
|
1408
|
+
circle.setRadius(radius);
|
|
1409
|
+
this.changingFeature_ = false;
|
|
1410
|
+
}
|
|
1411
|
+
break;
|
|
1412
|
+
default:
|
|
1413
|
+
// pass
|
|
1414
|
+
}
|
|
1415
|
+
if (coordinates) {
|
|
1416
|
+
this.setGeometryCoordinates_(geometry, coordinates);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
|
|
977
1420
|
/**
|
|
978
1421
|
* Handle pointer drag events.
|
|
979
1422
|
* @param {import("../MapBrowserEvent.js").default} evt Event.
|
|
@@ -992,6 +1435,26 @@ class Modify extends PointerInteraction {
|
|
|
992
1435
|
];
|
|
993
1436
|
const features = [];
|
|
994
1437
|
const geometries = [];
|
|
1438
|
+
const startTraceCoord =
|
|
1439
|
+
this.traceState_.active && !this.traceSegments_
|
|
1440
|
+
? this.traceState_.startCoord
|
|
1441
|
+
: null;
|
|
1442
|
+
if (startTraceCoord) {
|
|
1443
|
+
this.traceSegments_ = [];
|
|
1444
|
+
for (const dragSegment of this.dragSegments_) {
|
|
1445
|
+
const segmentData = dragSegment[0];
|
|
1446
|
+
const eligibleForTracing =
|
|
1447
|
+
coordinateDistance(
|
|
1448
|
+
closestOnSegment(startTraceCoord, segmentData.segment),
|
|
1449
|
+
startTraceCoord,
|
|
1450
|
+
) /
|
|
1451
|
+
evt.map.getView().getResolution() <
|
|
1452
|
+
1;
|
|
1453
|
+
if (eligibleForTracing) {
|
|
1454
|
+
this.traceSegments_.push(dragSegment);
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
995
1458
|
for (let i = 0, ii = this.dragSegments_.length; i < ii; ++i) {
|
|
996
1459
|
const dragSegment = this.dragSegments_[i];
|
|
997
1460
|
const segmentData = dragSegment[0];
|
|
@@ -1003,87 +1466,10 @@ class Modify extends PointerInteraction {
|
|
|
1003
1466
|
if (!geometries.includes(geometry)) {
|
|
1004
1467
|
geometries.push(geometry);
|
|
1005
1468
|
}
|
|
1006
|
-
const depth = segmentData.depth;
|
|
1007
|
-
let coordinates;
|
|
1008
|
-
const segment = segmentData.segment;
|
|
1009
|
-
const index = dragSegment[1];
|
|
1010
|
-
|
|
1011
|
-
while (vertex.length < geometry.getStride()) {
|
|
1012
|
-
vertex.push(segment[index][vertex.length]);
|
|
1013
|
-
}
|
|
1014
1469
|
|
|
1015
|
-
|
|
1016
|
-
case 'Point':
|
|
1017
|
-
coordinates = vertex;
|
|
1018
|
-
segment[0] = vertex;
|
|
1019
|
-
segment[1] = vertex;
|
|
1020
|
-
break;
|
|
1021
|
-
case 'MultiPoint':
|
|
1022
|
-
coordinates = geometry.getCoordinates();
|
|
1023
|
-
coordinates[segmentData.index] = vertex;
|
|
1024
|
-
segment[0] = vertex;
|
|
1025
|
-
segment[1] = vertex;
|
|
1026
|
-
break;
|
|
1027
|
-
case 'LineString':
|
|
1028
|
-
coordinates = geometry.getCoordinates();
|
|
1029
|
-
coordinates[segmentData.index + index] = vertex;
|
|
1030
|
-
segment[index] = vertex;
|
|
1031
|
-
break;
|
|
1032
|
-
case 'MultiLineString':
|
|
1033
|
-
coordinates = geometry.getCoordinates();
|
|
1034
|
-
coordinates[depth[0]][segmentData.index + index] = vertex;
|
|
1035
|
-
segment[index] = vertex;
|
|
1036
|
-
break;
|
|
1037
|
-
case 'Polygon':
|
|
1038
|
-
coordinates = geometry.getCoordinates();
|
|
1039
|
-
coordinates[depth[0]][segmentData.index + index] = vertex;
|
|
1040
|
-
segment[index] = vertex;
|
|
1041
|
-
break;
|
|
1042
|
-
case 'MultiPolygon':
|
|
1043
|
-
coordinates = geometry.getCoordinates();
|
|
1044
|
-
coordinates[depth[1]][depth[0]][segmentData.index + index] = vertex;
|
|
1045
|
-
segment[index] = vertex;
|
|
1046
|
-
break;
|
|
1047
|
-
case 'Circle':
|
|
1048
|
-
const circle = /** @type {import("../geom/Circle.js").default} */ (
|
|
1049
|
-
geometry
|
|
1050
|
-
);
|
|
1051
|
-
segment[0] = vertex;
|
|
1052
|
-
segment[1] = vertex;
|
|
1053
|
-
if (segmentData.index === CIRCLE_CENTER_INDEX) {
|
|
1054
|
-
this.changingFeature_ = true;
|
|
1055
|
-
circle.setCenter(vertex);
|
|
1056
|
-
this.changingFeature_ = false;
|
|
1057
|
-
} else {
|
|
1058
|
-
// We're dragging the circle's circumference:
|
|
1059
|
-
this.changingFeature_ = true;
|
|
1060
|
-
const projection = evt.map.getView().getProjection();
|
|
1061
|
-
let radius = coordinateDistance(
|
|
1062
|
-
fromUserCoordinate(circle.getCenter(), projection),
|
|
1063
|
-
fromUserCoordinate(vertex, projection),
|
|
1064
|
-
);
|
|
1065
|
-
const userProjection = getUserProjection();
|
|
1066
|
-
if (userProjection) {
|
|
1067
|
-
const circleGeometry = circle
|
|
1068
|
-
.clone()
|
|
1069
|
-
.transform(userProjection, projection);
|
|
1070
|
-
circleGeometry.setRadius(radius);
|
|
1071
|
-
radius = circleGeometry
|
|
1072
|
-
.transform(projection, userProjection)
|
|
1073
|
-
.getRadius();
|
|
1074
|
-
}
|
|
1075
|
-
circle.setRadius(radius);
|
|
1076
|
-
this.changingFeature_ = false;
|
|
1077
|
-
}
|
|
1078
|
-
break;
|
|
1079
|
-
default:
|
|
1080
|
-
// pass
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
if (coordinates) {
|
|
1084
|
-
this.setGeometryCoordinates_(geometry, coordinates);
|
|
1085
|
-
}
|
|
1470
|
+
this.updateGeometry_(vertex, dragSegment);
|
|
1086
1471
|
}
|
|
1472
|
+
this.updateTrace_(evt);
|
|
1087
1473
|
this.createOrUpdateVertexFeature_(vertex, features, geometries, true);
|
|
1088
1474
|
}
|
|
1089
1475
|
|
|
@@ -1161,6 +1547,7 @@ class Modify extends PointerInteraction {
|
|
|
1161
1547
|
}
|
|
1162
1548
|
}
|
|
1163
1549
|
if (this.featuresBeingModified_) {
|
|
1550
|
+
this.toggleTraceState_(evt);
|
|
1164
1551
|
this.dispatchEvent(
|
|
1165
1552
|
new ModifyEvent(
|
|
1166
1553
|
ModifyEventType.MODIFYEND,
|
|
@@ -1178,8 +1565,8 @@ class Modify extends PointerInteraction {
|
|
|
1178
1565
|
* @private
|
|
1179
1566
|
*/
|
|
1180
1567
|
handlePointerMove_(evt) {
|
|
1181
|
-
this.
|
|
1182
|
-
this.handlePointerAtPixel_(
|
|
1568
|
+
this.lastCoordinate_ = evt.coordinate;
|
|
1569
|
+
this.handlePointerAtPixel_(this.lastCoordinate_);
|
|
1183
1570
|
}
|
|
1184
1571
|
|
|
1185
1572
|
/**
|
|
@@ -1409,6 +1796,11 @@ class Modify extends PointerInteraction {
|
|
|
1409
1796
|
return true;
|
|
1410
1797
|
}
|
|
1411
1798
|
|
|
1799
|
+
/**
|
|
1800
|
+
* @param {import("../coordinate.js").Coordinate} coordinate The coordinate.
|
|
1801
|
+
* @return {import("../coordinate.js").Coordinate} The updated pointer coordinate.
|
|
1802
|
+
* @private
|
|
1803
|
+
*/
|
|
1412
1804
|
updatePointer_(coordinate) {
|
|
1413
1805
|
if (coordinate) {
|
|
1414
1806
|
this.findInsertVerticesAndUpdateDragSegments_(coordinate);
|