ol 10.4.1-dev.1738789133545 → 10.4.1-dev.1739165709127

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.
@@ -31,40 +31,228 @@ import {getUid} from '../util.js';
31
31
  import PointerInteraction from './Pointer.js';
32
32
 
33
33
  /**
34
- * @typedef {Object} Result
35
- * @property {import("../coordinate.js").Coordinate|null} vertex Vertex.
36
- * @property {import("../pixel.js").Pixel|null} vertexPixel VertexPixel.
37
- * @property {import("../Feature.js").default|null} feature Feature.
38
- * @property {Array<import("../coordinate.js").Coordinate>|null} segment Segment, or `null` if snapped to a vertex.
34
+ * @typedef {Array<import("../coordinate.js").Coordinate>} Segment
35
+ * An array of two coordinates representing a line segment, or an array of one
36
+ * coordinate representing a point.
39
37
  */
40
38
 
41
39
  /**
42
40
  * @typedef {Object} SegmentData
43
41
  * @property {import("../Feature.js").default} feature Feature.
44
- * @property {Array<import("../coordinate.js").Coordinate>} segment Segment.
42
+ * @property {Segment} segment Segment.
45
43
  * @property {boolean} [isIntersection] Is intersection.
46
44
  */
47
45
 
46
+ /**
47
+ * @template {import("../geom/Geometry.js").default} [GeometryType=import("../geom/Geometry.js").default]
48
+ * @typedef {(geometry: GeometryType, projection?: import("../proj/Projection.js").default) => Array<Segment>} Segmenter
49
+ * A function taking a {@link module:ol/geom/Geometry~Geometry} as argument and returning an array of {@link Segment}s.
50
+ */
51
+
52
+ /**
53
+ * Each segmenter specified here will override the default segmenter for the
54
+ * corresponding geometry type. To exclude all geometries of a specific geometry type from being snapped to,
55
+ * set the segmenter to `null`.
56
+ * @typedef {Object} Segmenters
57
+ * @property {Segmenter<import("../geom/Point.js").default>|null} [Point] Point segmenter.
58
+ * @property {Segmenter<import("../geom/LineString.js").default>|null} [LineString] LineString segmenter.
59
+ * @property {Segmenter<import("../geom/Polygon.js").default>|null} [Polygon] Polygon segmenter.
60
+ * @property {Segmenter<import("../geom/Circle.js").default>|null} [Circle] Circle segmenter.
61
+ * @property {Segmenter<import("../geom/GeometryCollection.js").default>|null} [GeometryCollection] GeometryCollection segmenter.
62
+ * @property {Segmenter<import("../geom/MultiPoint.js").default>|null} [MultiPoint] MultiPoint segmenter.
63
+ * @property {Segmenter<import("../geom/MultiLineString.js").default>|null} [MultiLineString] MultiLineString segmenter.
64
+ * @property {Segmenter<import("../geom/MultiPolygon.js").default>|null} [MultiPolygon] MultiPolygon segmenter.
65
+ */
66
+
48
67
  /**
49
68
  * @typedef {Object} Options
50
69
  * @property {import("../Collection.js").default<import("../Feature.js").default>} [features] Snap to these features. Either this option or source should be provided.
70
+ * @property {import("../source/Vector.js").default} [source] Snap to features from this source. Either this option or features should be provided
51
71
  * @property {boolean} [edge=true] Snap to edges.
52
72
  * @property {boolean} [vertex=true] Snap to vertices.
53
73
  * @property {boolean} [intersection=false] Snap to intersections between segments.
54
74
  * @property {number} [pixelTolerance=10] Pixel tolerance for considering the pointer close enough to a segment or
55
75
  * vertex for snapping.
56
- * @property {import("../source/Vector.js").default} [source] Snap to features from this source. Either this option or features should be provided
76
+ * @property {Segmenters} [segmenters] Custom segmenters by {@link module:ol/geom/Geometry~Type}. By default, the
77
+ * following segmenters are used:
78
+ * - `Point`: A one-dimensional segment (e.g. `[[10, 20]]`) representing the point.
79
+ * - `LineString`: One two-dimensional segment (e.g. `[[10, 20], [30, 40]]`) for each segment of the linestring.
80
+ * - `Polygon`: One two-dimensional segment for each segment of the exterior ring and the interior rings.
81
+ * - `Circle`: One two-dimensional segment for each segment of a regular polygon with 32 points representing the circle circumference.
82
+ * - `GeometryCollection`: All segments of the contained geometries.
83
+ * - `MultiPoint`: One one-dimensional segment for each point.
84
+ * - `MultiLineString`: One two-dimensional segment for each segment of the linestrings.
85
+ * - `MultiPolygon`: One two-dimensional segment for each segment of the polygons.
57
86
  */
58
87
 
59
88
  /**
60
89
  * Information about the last snapped state.
61
90
  * @typedef {Object} SnappedInfo
62
91
  * @property {import("../coordinate.js").Coordinate|null} vertex - The snapped vertex.
63
- * @property {import("../coordinate.js").Coordinate|null} vertexPixel - The pixel of the snapped vertex.
92
+ * @property {import("../pixel.js").Pixel|null} vertexPixel - The pixel of the snapped vertex.
64
93
  * @property {import("../Feature.js").default|null} feature - The feature being snapped.
65
- * @property {Array<import("../coordinate.js").Coordinate>|null} segment - Segment, or `null` if snapped to a vertex.
94
+ * @property {Segment|null} segment - Segment, or `null` if snapped to a vertex.
66
95
  */
67
96
 
97
+ /***
98
+ * @type {Object<string, Segmenter>}
99
+ */
100
+ const GEOMETRY_SEGMENTERS = {
101
+ /**
102
+ * @param {import("../geom/Circle.js").default} geometry Geometry.
103
+ * @param {import("../proj/Projection.js").default} projection Projection.
104
+ * @return {Array<Segment>} Segments
105
+ */
106
+ Circle(geometry, projection) {
107
+ let circleGeometry = geometry;
108
+ const userProjection = getUserProjection();
109
+ if (userProjection) {
110
+ circleGeometry = circleGeometry
111
+ .clone()
112
+ .transform(userProjection, projection);
113
+ }
114
+ const polygon = fromCircle(circleGeometry);
115
+ if (userProjection) {
116
+ polygon.transform(projection, userProjection);
117
+ }
118
+ return GEOMETRY_SEGMENTERS.Polygon(polygon);
119
+ },
120
+
121
+ /**
122
+ * @param {import("../geom/GeometryCollection.js").default} geometry Geometry.
123
+ * @param {import("../proj/Projection.js").default} projection Projection.
124
+ * @return {Array<Segment>} Segments
125
+ */
126
+ GeometryCollection(geometry, projection) {
127
+ /** @type {Array<Array<Segment>>} */
128
+ const segments = [];
129
+ const geometries = geometry.getGeometriesArray();
130
+ for (let i = 0; i < geometries.length; ++i) {
131
+ const segmenter = GEOMETRY_SEGMENTERS[geometries[i].getType()];
132
+ if (segmenter) {
133
+ segments.push(segmenter(geometries[i], projection));
134
+ }
135
+ }
136
+ return segments.flat();
137
+ },
138
+
139
+ /**
140
+ * @param {import("../geom/LineString.js").default} geometry Geometry.
141
+ * @return {Array<Segment>} Segments
142
+ */
143
+ LineString(geometry) {
144
+ /** @type {Array<Segment>} */
145
+ const segments = [];
146
+ const coordinates = geometry.getFlatCoordinates();
147
+ const stride = geometry.getStride();
148
+ for (let i = 0, ii = coordinates.length - stride; i < ii; i += stride) {
149
+ segments.push([
150
+ coordinates.slice(i, i + 2),
151
+ coordinates.slice(i + stride, i + stride + 2),
152
+ ]);
153
+ }
154
+ return segments;
155
+ },
156
+
157
+ /**
158
+ * @param {import("../geom/MultiLineString.js").default} geometry Geometry.
159
+ * @return {Array<Segment>} Segments
160
+ */
161
+ MultiLineString(geometry) {
162
+ /** @type {Array<Segment>} */
163
+ const segments = [];
164
+ const coordinates = geometry.getFlatCoordinates();
165
+ const stride = geometry.getStride();
166
+ const ends = geometry.getEnds();
167
+ let offset = 0;
168
+ for (let i = 0, ii = ends.length; i < ii; ++i) {
169
+ const end = ends[i];
170
+ for (let j = offset, jj = end - stride; j < jj; j += stride) {
171
+ segments.push([
172
+ coordinates.slice(j, j + 2),
173
+ coordinates.slice(j + stride, j + stride + 2),
174
+ ]);
175
+ }
176
+ offset = end;
177
+ }
178
+ return segments;
179
+ },
180
+
181
+ /**
182
+ * @param {import("../geom/MultiPoint.js").default} geometry Geometry.
183
+ * @return {Array<Segment>} Segments
184
+ */
185
+ MultiPoint(geometry) {
186
+ /** @type {Array<Segment>} */
187
+ const segments = [];
188
+ const coordinates = geometry.getFlatCoordinates();
189
+ const stride = geometry.getStride();
190
+ for (let i = 0, ii = coordinates.length - stride; i < ii; i += stride) {
191
+ segments.push([coordinates.slice(i, i + 2)]);
192
+ }
193
+ return segments;
194
+ },
195
+
196
+ /**
197
+ * @param {import("../geom/MultiPolygon.js").default} geometry Geometry.
198
+ * @return {Array<Segment>} Segments
199
+ */
200
+ MultiPolygon(geometry) {
201
+ /** @type {Array<Segment>} */
202
+ const segments = [];
203
+ const coordinates = geometry.getFlatCoordinates();
204
+ const stride = geometry.getStride();
205
+ const endss = geometry.getEndss();
206
+ let offset = 0;
207
+ for (let i = 0, ii = endss.length; i < ii; ++i) {
208
+ const ends = endss[i];
209
+ for (let j = 0, jj = ends.length; j < jj; ++j) {
210
+ const end = ends[j];
211
+ for (let k = offset, kk = end - stride; k < kk; k += stride) {
212
+ segments.push([
213
+ coordinates.slice(k, k + 2),
214
+ coordinates.slice(k + stride, k + stride + 2),
215
+ ]);
216
+ }
217
+ offset = end;
218
+ }
219
+ }
220
+ return segments;
221
+ },
222
+
223
+ /**
224
+ * @param {import("../geom/Point.js").default} geometry Geometry.
225
+ * @return {Array<Segment>} Segments
226
+ */
227
+ Point(geometry) {
228
+ return [[geometry.getFlatCoordinates().slice(0, 2)]];
229
+ },
230
+
231
+ /**
232
+ * @param {import("../geom/Polygon.js").default} geometry Geometry.
233
+ * @return {Array<Segment>} Segments
234
+ */
235
+ Polygon(geometry) {
236
+ /** @type {Array<Segment>} */
237
+ const segments = [];
238
+ const coordinates = geometry.getFlatCoordinates();
239
+ const stride = geometry.getStride();
240
+ const ends = geometry.getEnds();
241
+ let offset = 0;
242
+ for (let i = 0, ii = ends.length; i < ii; ++i) {
243
+ const end = ends[i];
244
+ for (let j = offset, jj = end - stride; j < jj; j += stride) {
245
+ segments.push([
246
+ coordinates.slice(j, j + 2),
247
+ coordinates.slice(j + stride, j + stride + 2),
248
+ ]);
249
+ }
250
+ offset = end;
251
+ }
252
+ return segments;
253
+ },
254
+ };
255
+
68
256
  /**
69
257
  * @param {import("../source/Vector.js").VectorSourceEvent|import("../Collection.js").CollectionEvent<import("../Feature.js").default>} evt Event.
70
258
  * @return {import("../Feature.js").default|null} Feature.
@@ -246,21 +434,14 @@ class Snap extends PointerInteraction {
246
434
  this.snapped_ = null;
247
435
 
248
436
  /**
249
- * @const
437
+ * @type {Object<string, Segmenter>}
250
438
  * @private
251
- * @type {Object<string, function(Array<Array<import('../coordinate.js').Coordinate>>, import("../geom/Geometry.js").default): void>}
252
439
  */
253
- this.GEOMETRY_SEGMENTERS_ = {
254
- 'Point': this.segmentPointGeometry_.bind(this),
255
- 'LineString': this.segmentLineStringGeometry_.bind(this),
256
- 'LinearRing': this.segmentLineStringGeometry_.bind(this),
257
- 'Polygon': this.segmentPolygonGeometry_.bind(this),
258
- 'MultiPoint': this.segmentMultiPointGeometry_.bind(this),
259
- 'MultiLineString': this.segmentMultiLineStringGeometry_.bind(this),
260
- 'MultiPolygon': this.segmentMultiPolygonGeometry_.bind(this),
261
- 'GeometryCollection': this.segmentGeometryCollectionGeometry_.bind(this),
262
- 'Circle': this.segmentCircleGeometry_.bind(this),
263
- };
440
+ this.segmenters_ = Object.assign(
441
+ {},
442
+ GEOMETRY_SEGMENTERS,
443
+ options.segmenters,
444
+ );
264
445
  }
265
446
 
266
447
  /**
@@ -275,13 +456,14 @@ class Snap extends PointerInteraction {
275
456
  const feature_uid = getUid(feature);
276
457
  const geometry = feature.getGeometry();
277
458
  if (geometry) {
278
- const segmenter = this.GEOMETRY_SEGMENTERS_[geometry.getType()];
459
+ const segmenter = this.segmenters_[geometry.getType()];
279
460
  if (segmenter) {
280
461
  this.indexedFeaturesExtents_[feature_uid] =
281
462
  geometry.getExtent(createEmpty());
282
- const segments =
283
- /** @type {Array<Array<import('../coordinate.js').Coordinate>>} */ ([]);
284
- segmenter(segments, geometry);
463
+ const segments = segmenter(
464
+ geometry,
465
+ this.getMap().getView().getProjection(),
466
+ );
285
467
  let segmentCount = segments.length;
286
468
  for (let i = 0; i < segmentCount; ++i) {
287
469
  const segment = segments[i];
@@ -471,8 +653,9 @@ class Snap extends PointerInteraction {
471
653
  handleUpEvent(evt) {
472
654
  const featuresToUpdate = Object.values(this.pendingFeatures_);
473
655
  if (featuresToUpdate.length) {
474
- featuresToUpdate.forEach(this.updateFeature_.bind(this));
475
- this.pendingFeatures_ = {};
656
+ for (const feature of featuresToUpdate) {
657
+ this.updateFeature_(feature);
658
+ }
476
659
  }
477
660
  return false;
478
661
  }
@@ -517,9 +700,10 @@ class Snap extends PointerInteraction {
517
700
  setMap(map) {
518
701
  const currentMap = this.getMap();
519
702
  const keys = this.featuresListenerKeys_;
520
- const features = /** @type {Array<import("../Feature.js").default>} */ (
521
- this.getFeatures_()
522
- );
703
+ let features = this.getFeatures_();
704
+ if (!Array.isArray(features)) {
705
+ features = features.getArray();
706
+ }
523
707
 
524
708
  if (currentMap) {
525
709
  keys.forEach(unlistenByKey);
@@ -562,7 +746,9 @@ class Snap extends PointerInteraction {
562
746
  ),
563
747
  );
564
748
  }
565
- features.forEach((feature) => this.addFeature(feature));
749
+ for (const feature of features) {
750
+ this.addFeature(feature);
751
+ }
566
752
  }
567
753
  }
568
754
 
@@ -570,7 +756,7 @@ class Snap extends PointerInteraction {
570
756
  * @param {import("../pixel.js").Pixel} pixel Pixel
571
757
  * @param {import("../coordinate.js").Coordinate} pixelCoordinate Coordinate
572
758
  * @param {import("../Map.js").default} map Map.
573
- * @return {Result|null} Snap result
759
+ * @return {SnappedInfo|null} Snap result
574
760
  */
575
761
  snapTo(pixel, pixelCoordinate, map) {
576
762
  const projection = map.getView().getProjection();
@@ -624,7 +810,7 @@ class Snap extends PointerInteraction {
624
810
  for (let i = 0; i < segmentsLength; ++i) {
625
811
  const segmentData = segments[i];
626
812
  if (segmentData.feature.getGeometry().getType() !== 'Circle') {
627
- segmentData.segment.forEach((vertex) => {
813
+ for (const vertex of segmentData.segment) {
628
814
  const tempVertexCoord = fromUserCoordinate(vertex, projection);
629
815
  const delta = squaredDistance(projectedCoordinate, tempVertexCoord);
630
816
  if (delta < minSquaredDistance) {
@@ -633,7 +819,7 @@ class Snap extends PointerInteraction {
633
819
  closestFeature = segmentData.feature;
634
820
  isIntersection = segmentData.isIntersection;
635
821
  }
636
- });
822
+ }
637
823
  }
638
824
  }
639
825
  const result = getResult();
@@ -698,125 +884,6 @@ class Snap extends PointerInteraction {
698
884
  this.removeFeature(feature, false);
699
885
  this.addFeature(feature, false);
700
886
  }
701
-
702
- /**
703
- * @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
704
- * @param {import("../geom/Circle.js").default} geometry Geometry.
705
- * @private
706
- */
707
- segmentCircleGeometry_(segments, geometry) {
708
- const projection = this.getMap().getView().getProjection();
709
- let circleGeometry = geometry;
710
- const userProjection = getUserProjection();
711
- if (userProjection) {
712
- circleGeometry = circleGeometry
713
- .clone()
714
- .transform(userProjection, projection);
715
- }
716
- const polygon = fromCircle(circleGeometry);
717
- if (userProjection) {
718
- polygon.transform(projection, userProjection);
719
- }
720
- const coordinates = polygon.getCoordinates()[0];
721
- for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
722
- segments.push(coordinates.slice(i, i + 2));
723
- }
724
- }
725
-
726
- /**
727
- * @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
728
- * @param {import("../geom/GeometryCollection.js").default} geometry Geometry.
729
- * @private
730
- */
731
- segmentGeometryCollectionGeometry_(segments, geometry) {
732
- const geometries = geometry.getGeometriesArray();
733
- for (let i = 0; i < geometries.length; ++i) {
734
- const segmenter = this.GEOMETRY_SEGMENTERS_[geometries[i].getType()];
735
- if (segmenter) {
736
- segmenter(segments, geometries[i]);
737
- }
738
- }
739
- }
740
-
741
- /**
742
- * @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
743
- * @param {import("../geom/LineString.js").default} geometry Geometry.
744
- * @private
745
- */
746
- segmentLineStringGeometry_(segments, geometry) {
747
- const coordinates = geometry.getCoordinates();
748
- for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
749
- segments.push(coordinates.slice(i, i + 2));
750
- }
751
- }
752
-
753
- /**
754
- * @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
755
- * @param {import("../geom/MultiLineString.js").default} geometry Geometry.
756
- * @private
757
- */
758
- segmentMultiLineStringGeometry_(segments, geometry) {
759
- const lines = geometry.getCoordinates();
760
- for (let j = 0, jj = lines.length; j < jj; ++j) {
761
- const coordinates = lines[j];
762
- for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
763
- segments.push(coordinates.slice(i, i + 2));
764
- }
765
- }
766
- }
767
-
768
- /**
769
- * @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
770
- * @param {import("../geom/MultiPoint.js").default} geometry Geometry.
771
- * @private
772
- */
773
- segmentMultiPointGeometry_(segments, geometry) {
774
- geometry.getCoordinates().forEach((point) => {
775
- segments.push([point]);
776
- });
777
- }
778
-
779
- /**
780
- * @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
781
- * @param {import("../geom/MultiPolygon.js").default} geometry Geometry.
782
- * @private
783
- */
784
- segmentMultiPolygonGeometry_(segments, geometry) {
785
- const polygons = geometry.getCoordinates();
786
- for (let k = 0, kk = polygons.length; k < kk; ++k) {
787
- const rings = polygons[k];
788
- for (let j = 0, jj = rings.length; j < jj; ++j) {
789
- const coordinates = rings[j];
790
- for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
791
- segments.push(coordinates.slice(i, i + 2));
792
- }
793
- }
794
- }
795
- }
796
-
797
- /**
798
- * @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
799
- * @param {import("../geom/Point.js").default} geometry Geometry.
800
- * @private
801
- */
802
- segmentPointGeometry_(segments, geometry) {
803
- segments.push([geometry.getCoordinates()]);
804
- }
805
-
806
- /**
807
- * @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
808
- * @param {import("../geom/Polygon.js").default} geometry Geometry.
809
- * @private
810
- */
811
- segmentPolygonGeometry_(segments, geometry) {
812
- const rings = geometry.getCoordinates();
813
- for (let j = 0, jj = rings.length; j < jj; ++j) {
814
- const coordinates = rings[j];
815
- for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
816
- segments.push(coordinates.slice(i, i + 2));
817
- }
818
- }
819
- }
820
887
  }
821
888
 
822
889
  export default Snap;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ol",
3
- "version": "10.4.1-dev.1738789133545",
3
+ "version": "10.4.1-dev.1739165709127",
4
4
  "description": "OpenLayers mapping library",
5
5
  "keywords": [
6
6
  "map",
package/util.js CHANGED
@@ -33,4 +33,4 @@ export function getUid(obj) {
33
33
  * OpenLayers version.
34
34
  * @type {string}
35
35
  */
36
- export const VERSION = '10.4.1-dev.1738789133545';
36
+ export const VERSION = '10.4.1-dev.1739165709127';