Skip to content

Commit 8131970

Browse files
committed
spatialQuery support op
1 parent 0ef02dd commit 8131970

File tree

1 file changed

+58
-24
lines changed

1 file changed

+58
-24
lines changed

index.js

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
import { Util, MicroTask, Layer, Geometry } from 'maptalks';
33

44
let jsts;
5-
let geojsonRender;
5+
let geojsonReader;
66
// const geojsonWriter = new jsts.io.GeoJSONWriter();
77
const JSTS_ISNULL = 'jsts namespace is null, please injectJSTS(jsts)';
88
const FILTER_PAGESIZE = 40000;
99
const SPATIAL_PAGESIZE = 3000;
10+
const OPS = [];
1011

1112
export function injectJSTS(jstsNameSpace) {
1213
jsts = jstsNameSpace;
@@ -16,35 +17,35 @@ export function injectJSTS(jstsNameSpace) {
1617
// return jsts;
1718
// }
1819

19-
function checkJSTS() {
20+
function isJSTSAvailable() {
2021
if (!jsts) {
2122
console.error(JSTS_ISNULL);
2223
return false;
2324
}
24-
if (!geojsonRender) {
25-
geojsonRender = new jsts.io.GeoJSONReader();
25+
if (!geojsonReader) {
26+
geojsonReader = new jsts.io.GeoJSONReader();
2627
}
2728
return true;
2829
}
2930

30-
function flatGeos(layer, result) {
31+
function flatGeos(layer, geos) {
3132
if (layer.getGeometries) {
32-
return result;
33+
return geos;
3334
}
34-
const geos = [];
35-
const tiles = result;
35+
const data = [];
36+
const tiles = geos;
3637
// vt
3738
for (let i = 0, len = tiles.length; i < len; i++) {
3839
const features = tiles[i].features || [];
3940
for (let j = 0, len1 = features.length; j < len1; j++) {
4041
const feature = features[j].feature;
4142
if (feature && feature.geometry) {
42-
geos.push(feature);
43+
data.push(feature);
4344
}
4445
}
4546
// Util.pushIn(geos, features);
4647
}
47-
return geos;
48+
return data;
4849
}
4950

5051
export class Query {
@@ -141,6 +142,9 @@ export class Query {
141142
const list = data.slice(startIndex, endIndex);
142143
for (let i = 0, len = list.length; i < len; i++) {
143144
const { geo, layer } = list[i];
145+
if (!geo) {
146+
continue;
147+
}
144148
if (filter.call(this, geo, layer)) {
145149
result.push(list[i]);
146150
}
@@ -155,21 +159,30 @@ export class Query {
155159
});
156160
}
157161

158-
_spatialFilterGeos(data, geometry) {
162+
_spatialFilterGeos(data, geometry, operation) {
159163
return new Promise((resolve, reject) => {
160-
const geoJSON = geometry.toGeoJSON();
161-
let queryGeo;
164+
let inputGeom;
162165
try {
163-
queryGeo = geojsonRender.read(geoJSON).geometry;
166+
const geoJSON = geometry.toGeoJSON();
167+
inputGeom = geojsonReader.read(geoJSON).geometry;
164168
} catch (error) {
165169
console.error(error);
166170
reject(new Error('geometry.geoJSON() error', geometry));
167171
return;
168172
}
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+
}
169182
const pageSize = SPATIAL_PAGESIZE;
170183
const count = Math.ceil(data.length / pageSize);
171184
let page = 1;
172-
const result = [];
185+
173186
const TEMPFEATURE = {
174187
type: 'Feature',
175188
geometry: null
@@ -180,7 +193,10 @@ export class Query {
180193
const list = data.slice(startIndex, endIndex);
181194
for (let i = 0, len = list.length; i < len; i++) {
182195
const { geo, layer } = list[i];
183-
let feature, jstsGeo;
196+
if (!geo) {
197+
continue;
198+
}
199+
let feature, geom;
184200
try {
185201
if (geo.toGeoJSON) {
186202
feature = geo.toGeoJSON();
@@ -200,21 +216,21 @@ export class Query {
200216
continue;
201217
}
202218
try {
203-
jstsGeo = geojsonRender.read(feature).geometry;
219+
geom = geojsonReader.read(feature).geometry;
204220
} catch (error) {
205221
console.error(error);
206-
console.error('geo to jsts geo error:', geo, layer);
222+
console.error('geometry to jsts geo error:', geo, layer);
207223
}
208-
if (!jstsGeo) {
224+
if (!geom) {
209225
continue;
210226
}
211227
try {
212-
if (queryGeo.intersects(jstsGeo)) {
228+
if (inputGeom[operation] && inputGeom[operation](geom)) {
213229
result.push(list[i]);
214230
}
215231
} catch (error) {
216232
console.error(error);
217-
console.error('geo spatial cal:', geo);
233+
console.error('geo spatial cal:', inputGeom, geom, operation);
218234
}
219235
}
220236
page++;
@@ -270,18 +286,26 @@ export class Query {
270286

271287
spatialQuery(options = {}) {
272288
return new Promise((resolve, reject) => {
273-
const { filter, layers, geometry } = options;
289+
const { filter, layers, geometry, op } = options;
274290
if (!geometry || !(geometry instanceof Geometry)) {
275291
reject(new Error('geometry is not maptalks.Geometry'));
276292
return;
277293
}
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+
}
278302
const filterLayers = this._filterLayers(layers);
279303
this._getLayersGeos(filterLayers, data => {
280304
this._filterGeos(data, filter).then(list => {
281-
if (!checkJSTS()) {
305+
if (!isJSTSAvailable()) {
282306
reject(new Error(JSTS_ISNULL));
283307
} else {
284-
this._spatialFilterGeos(list, geometry).then(filterData => {
308+
this._spatialFilterGeos(list, geometry, operation).then(filterData => {
285309
const result = this._formatResult(filterData);
286310
resolve(result);
287311
}).catch(error => {
@@ -296,3 +320,13 @@ export class Query {
296320
}
297321

298322
}
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

Comments
 (0)