1
1
import { Style , Stroke } from 'ol/style' ;
2
- import { Point , LineString , Polygon , MultiPoint } from 'ol/geom' ;
2
+ import { Point , LineString , Polygon , MultiPoint , Circle } from 'ol/geom' ;
3
3
import Feature from 'ol/Feature' ;
4
4
import Vector from 'ol/layer/Vector' ;
5
5
import VectorSource from 'ol/source/Vector' ;
6
6
import { Pointer , Snap } from 'ol/interaction' ;
7
7
import { OverlayOp } from 'jsts/org/locationtech/jts/operation/overlay' ;
8
+ import { getUid } from 'ol/util' ;
8
9
import Control from './control' ;
9
10
import cadSVG from '../../img/cad.svg' ;
10
11
import { SnapEvent , SnapEventType } from '../event' ;
@@ -143,7 +144,7 @@ class CadControl extends Control {
143
144
* @type {Function }
144
145
* @private
145
146
*/
146
- this . filter = options . filter || null ;
147
+ this . filter = options . filter || ( ( ) => true ) ;
147
148
148
149
/**
149
150
* Interaction for snapping
@@ -246,47 +247,33 @@ class CadControl extends Control {
246
247
* to a given coordinate.
247
248
* @private
248
249
* @param {ol.Coordinate } coordinate Coordinate.
249
- * @param {Number } numFeatures Number of features to search.
250
+ * @param {Number } nbFeatures Number of features to search.
250
251
* @returns {Array.<ol.Feature> } List of closest features.
251
252
*/
252
- getClosestFeatures ( coordinate , numFeatures ) {
253
- const num = numFeatures || 1 ;
254
- const ext = [ - Infinity , - Infinity , Infinity , Infinity ] ;
255
- const featureDict = { } ;
256
-
257
- const pushSnapFeatures = ( f ) => {
258
- const cCoord = f . getGeometry ( ) . getClosestPoint ( coordinate ) ;
259
- const dx = cCoord [ 0 ] - coordinate [ 0 ] ;
260
- const dy = cCoord [ 1 ] - coordinate [ 1 ] ;
261
- const dist = dx * dx + dy * dy ;
262
- featureDict [ dist ] = f ;
263
- } ;
264
-
265
- this . source . forEachFeatureInExtent ( ext , ( f ) => {
266
- if ( ! this . filter || ( this . filter && this . filter ( f ) ) ) {
267
- pushSnapFeatures ( f ) ;
268
- }
269
- } ) ;
270
-
271
- const dists = Object . keys ( featureDict ) ;
272
- let features = [ ] ;
273
- const count = Math . min ( dists . length , num ) ;
274
-
275
- dists . sort ( ( a , b ) => a - b ) ;
276
-
277
- for ( let i = 0 ; i < count ; i += 1 ) {
278
- features . push ( featureDict [ dists [ i ] ] ) ;
279
- }
280
-
281
- // Remove edit and draw feature for snapping list.
253
+ getClosestFeatures ( coordinate , nbFeatures = 1 ) {
282
254
const editFeature = this . editor . getEditFeature ( ) ;
283
255
const drawFeature = this . editor . getDrawFeature ( ) ;
284
- [ editFeature , drawFeature ] . forEach ( ( feature ) => {
285
- const index = features . indexOf ( feature ) ;
286
- if ( index > - 1 ) {
287
- features . splice ( index , 1 ) ;
256
+ const currentFeatures = [ editFeature , drawFeature ] . filter ( ( f ) => ! ! f ) ;
257
+
258
+ const cacheDist = { } ;
259
+ const dist = ( f ) => {
260
+ const uid = getUid ( f ) ;
261
+ if ( ! cacheDist [ uid ] ) {
262
+ const cCoord = f . getGeometry ( ) . getClosestPoint ( coordinate ) ;
263
+ const dx = cCoord [ 0 ] - coordinate [ 0 ] ;
264
+ const dy = cCoord [ 1 ] - coordinate [ 1 ] ;
265
+ cacheDist [ uid ] = dx * dx + dy * dy ;
288
266
}
289
- } ) ;
267
+ return cacheDist [ uid ] ;
268
+ } ;
269
+ const sortByDistance = ( a , b ) => dist ( a ) - dist ( b ) ;
270
+
271
+ let features = this . source
272
+ . getFeatures ( )
273
+ . filter ( this . filter )
274
+ . filter ( ( f ) => ! currentFeatures . includes ( f ) )
275
+ . sort ( sortByDistance )
276
+ . slice ( 0 , nbFeatures ) ;
290
277
291
278
// When using showSnapPoints, return all features except edit/draw features
292
279
if ( this . properties . showSnapPoints ) {
@@ -295,10 +282,10 @@ class CadControl extends Control {
295
282
296
283
// When using showSnapLines, return all features but edit/draw features are
297
284
// cloned to remove the node at the mouse position.
298
- [ editFeature , drawFeature ]
299
- . filter ( ( f ) => f )
300
- . forEach ( ( feature ) => {
301
- const geom = feature . getGeometry ( ) ;
285
+ currentFeatures . filter ( this . filter ) . forEach ( ( feature ) => {
286
+ const geom = feature . getGeometry ( ) ;
287
+
288
+ if ( ! ( geom instanceof Circle ) && ! ( geom instanceof Point ) ) {
302
289
const snapGeom = getShiftedMultiPoint ( geom , coordinate ) ;
303
290
const isPolygon = geom instanceof Polygon ;
304
291
const snapFeature = feature . clone ( ) ;
@@ -308,7 +295,8 @@ class CadControl extends Control {
308
295
isPolygon ? [ snapGeom . getCoordinates ( ) ] : snapGeom . getCoordinates ( ) ,
309
296
) ;
310
297
features = [ snapFeature , ...features ] ;
311
- } ) ;
298
+ }
299
+ } ) ;
312
300
313
301
return features ;
314
302
}
@@ -615,10 +603,15 @@ class CadControl extends Control {
615
603
616
604
for ( let i = 0 ; i < features . length ; i += 1 ) {
617
605
const geom = features [ i ] . getGeometry ( ) ;
618
- const featureCoord = geom . getCoordinates ( ) ;
606
+ let featureCoord = geom . getCoordinates ( ) ;
607
+
608
+ if ( ! featureCoord && geom instanceof Circle ) {
609
+ featureCoord = geom . getCenter ( ) ;
610
+ }
611
+
619
612
// Polygons initially return a geometry with an empty coordinate array, so we need to catch it
620
- if ( featureCoord . length ) {
621
- if ( geom instanceof Point ) {
613
+ if ( featureCoord ? .length ) {
614
+ if ( geom instanceof Point || geom instanceof Circle ) {
622
615
snapCoordsBefore . push ( ) ;
623
616
snapCoords . push ( featureCoord ) ;
624
617
snapCoordsAfter . push ( ) ;
0 commit comments