2
2
import { Util , MicroTask , Layer , Geometry } from 'maptalks' ;
3
3
4
4
let jsts ;
5
- let geojsonRender ;
5
+ let geojsonReader ;
6
6
// const geojsonWriter = new jsts.io.GeoJSONWriter();
7
7
const JSTS_ISNULL = 'jsts namespace is null, please injectJSTS(jsts)' ;
8
8
const FILTER_PAGESIZE = 40000 ;
9
9
const SPATIAL_PAGESIZE = 3000 ;
10
+ const OPS = [ ] ;
10
11
11
12
export function injectJSTS ( jstsNameSpace ) {
12
13
jsts = jstsNameSpace ;
@@ -16,35 +17,35 @@ export function injectJSTS(jstsNameSpace) {
16
17
// return jsts;
17
18
// }
18
19
19
- function checkJSTS ( ) {
20
+ function isJSTSAvailable ( ) {
20
21
if ( ! jsts ) {
21
22
console . error ( JSTS_ISNULL ) ;
22
23
return false ;
23
24
}
24
- if ( ! geojsonRender ) {
25
- geojsonRender = new jsts . io . GeoJSONReader ( ) ;
25
+ if ( ! geojsonReader ) {
26
+ geojsonReader = new jsts . io . GeoJSONReader ( ) ;
26
27
}
27
28
return true ;
28
29
}
29
30
30
- function flatGeos ( layer , result ) {
31
+ function flatGeos ( layer , geos ) {
31
32
if ( layer . getGeometries ) {
32
- return result ;
33
+ return geos ;
33
34
}
34
- const geos = [ ] ;
35
- const tiles = result ;
35
+ const data = [ ] ;
36
+ const tiles = geos ;
36
37
// vt
37
38
for ( let i = 0 , len = tiles . length ; i < len ; i ++ ) {
38
39
const features = tiles [ i ] . features || [ ] ;
39
40
for ( let j = 0 , len1 = features . length ; j < len1 ; j ++ ) {
40
41
const feature = features [ j ] . feature ;
41
42
if ( feature && feature . geometry ) {
42
- geos . push ( feature ) ;
43
+ data . push ( feature ) ;
43
44
}
44
45
}
45
46
// Util.pushIn(geos, features);
46
47
}
47
- return geos ;
48
+ return data ;
48
49
}
49
50
50
51
export class Query {
@@ -141,6 +142,9 @@ export class Query {
141
142
const list = data . slice ( startIndex , endIndex ) ;
142
143
for ( let i = 0 , len = list . length ; i < len ; i ++ ) {
143
144
const { geo, layer } = list [ i ] ;
145
+ if ( ! geo ) {
146
+ continue ;
147
+ }
144
148
if ( filter . call ( this , geo , layer ) ) {
145
149
result . push ( list [ i ] ) ;
146
150
}
@@ -155,21 +159,30 @@ export class Query {
155
159
} ) ;
156
160
}
157
161
158
- _spatialFilterGeos ( data , geometry ) {
162
+ _spatialFilterGeos ( data , geometry , operation ) {
159
163
return new Promise ( ( resolve , reject ) => {
160
- const geoJSON = geometry . toGeoJSON ( ) ;
161
- let queryGeo ;
164
+ let inputGeom ;
162
165
try {
163
- queryGeo = geojsonRender . read ( geoJSON ) . geometry ;
166
+ const geoJSON = geometry . toGeoJSON ( ) ;
167
+ inputGeom = geojsonReader . read ( geoJSON ) . geometry ;
164
168
} catch ( error ) {
165
169
console . error ( error ) ;
166
170
reject ( new Error ( 'geometry.geoJSON() error' , geometry ) ) ;
167
171
return ;
168
172
}
173
+ const result = [ ] ;
174
+ if ( ! inputGeom ) {
175
+ resolve ( result ) ;
176
+ return ;
177
+ }
178
+ if ( ! inputGeom . isValid ( ) ) {
179
+ reject ( new Error ( 'input geometry is not valide:' , geometry ) ) ;
180
+ return ;
181
+ }
169
182
const pageSize = SPATIAL_PAGESIZE ;
170
183
const count = Math . ceil ( data . length / pageSize ) ;
171
184
let page = 1 ;
172
- const result = [ ] ;
185
+
173
186
const TEMPFEATURE = {
174
187
type : 'Feature' ,
175
188
geometry : null
@@ -180,7 +193,10 @@ export class Query {
180
193
const list = data . slice ( startIndex , endIndex ) ;
181
194
for ( let i = 0 , len = list . length ; i < len ; i ++ ) {
182
195
const { geo, layer } = list [ i ] ;
183
- let feature , jstsGeo ;
196
+ if ( ! geo ) {
197
+ continue ;
198
+ }
199
+ let feature , geom ;
184
200
try {
185
201
if ( geo . toGeoJSON ) {
186
202
feature = geo . toGeoJSON ( ) ;
@@ -200,21 +216,21 @@ export class Query {
200
216
continue ;
201
217
}
202
218
try {
203
- jstsGeo = geojsonRender . read ( feature ) . geometry ;
219
+ geom = geojsonReader . read ( feature ) . geometry ;
204
220
} catch ( error ) {
205
221
console . error ( error ) ;
206
- console . error ( 'geo to jsts geo error:' , geo , layer ) ;
222
+ console . error ( 'geometry to jsts geo error:' , geo , layer ) ;
207
223
}
208
- if ( ! jstsGeo ) {
224
+ if ( ! geom ) {
209
225
continue ;
210
226
}
211
227
try {
212
- if ( queryGeo . intersects ( jstsGeo ) ) {
228
+ if ( inputGeom [ operation ] && inputGeom [ operation ] ( geom ) ) {
213
229
result . push ( list [ i ] ) ;
214
230
}
215
231
} catch ( error ) {
216
232
console . error ( error ) ;
217
- console . error ( 'geo spatial cal:' , geo ) ;
233
+ console . error ( 'geo spatial cal:' , inputGeom , geom , operation ) ;
218
234
}
219
235
}
220
236
page ++ ;
@@ -270,18 +286,26 @@ export class Query {
270
286
271
287
spatialQuery ( options = { } ) {
272
288
return new Promise ( ( resolve , reject ) => {
273
- const { filter, layers, geometry } = options ;
289
+ const { filter, layers, geometry, op } = options ;
274
290
if ( ! geometry || ! ( geometry instanceof Geometry ) ) {
275
291
reject ( new Error ( 'geometry is not maptalks.Geometry' ) ) ;
276
292
return ;
277
293
}
294
+ let operation = op ;
295
+ if ( ! operation ) {
296
+ operation = Query . intersects ;
297
+ }
298
+ if ( OPS . indexOf ( operation ) === - 1 ) {
299
+ reject ( new Error ( 'not support the op:' , operation ) ) ;
300
+ return ;
301
+ }
278
302
const filterLayers = this . _filterLayers ( layers ) ;
279
303
this . _getLayersGeos ( filterLayers , data => {
280
304
this . _filterGeos ( data , filter ) . then ( list => {
281
- if ( ! checkJSTS ( ) ) {
305
+ if ( ! isJSTSAvailable ( ) ) {
282
306
reject ( new Error ( JSTS_ISNULL ) ) ;
283
307
} else {
284
- this . _spatialFilterGeos ( list , geometry ) . then ( filterData => {
308
+ this . _spatialFilterGeos ( list , geometry , operation ) . then ( filterData => {
285
309
const result = this . _formatResult ( filterData ) ;
286
310
resolve ( result ) ;
287
311
} ) . catch ( error => {
@@ -296,3 +320,13 @@ export class Query {
296
320
}
297
321
298
322
}
323
+
324
+ Query . contains = 'contains' ;
325
+ Query . crosses = 'crosses' ;
326
+ Query . disjoint = 'disjoint' ;
327
+ Query . equals = 'equals' ;
328
+ Query . intersects = 'intersects' ;
329
+ Query . overlaps = 'overlaps' ;
330
+ Query . within = 'overlaps' ;
331
+
332
+ OPS . push ( Query . contains , Query . crosses , Query . disjoint , Query . equals , Query . intersects , Query . overlaps , Query . within ) ;
0 commit comments