|
1 | 1 | import type { LatLngTuple } from "leaflet"; |
2 | 2 | import osmtogeojson from "osmtogeojson"; |
3 | 3 | import * as turf from "@turf/turf"; |
4 | | -import { mapGeoLocation, polyGeoJSON } from "@/lib/context"; |
| 4 | +import { |
| 5 | + additionalMapGeoLocations, |
| 6 | + mapGeoLocation, |
| 7 | + polyGeoJSON, |
| 8 | +} from "@/lib/context"; |
5 | 9 | import type { |
6 | 10 | EncompassingTentacleQuestionSchema, |
7 | 11 | Question, |
|
374 | 378 | out ${outType}; |
375 | 379 | `; |
376 | 380 | } else { |
377 | | - const geoLocation = mapGeoLocation.get(); |
| 381 | + const primaryLocation = mapGeoLocation.get(); |
| 382 | + |
| 383 | + const additionalLocations = additionalMapGeoLocations |
| 384 | + .get() |
| 385 | + .filter((entry) => entry.added) |
| 386 | + .map((entry) => entry.location); |
| 387 | + |
| 388 | + const allLocations = [primaryLocation, ...additionalLocations]; |
| 389 | + |
| 390 | + const relationToAreaBlocks = allLocations |
| 391 | + .map((loc, idx) => { |
| 392 | + const regionVar = `.region${idx}`; |
| 393 | + return `relation(${loc.properties.osm_id});map_to_area->${regionVar};`; |
| 394 | + }) |
| 395 | + .join("\n"); |
| 396 | + |
| 397 | + const searchBlocks = allLocations |
| 398 | + .map((_, idx) => { |
| 399 | + const regionVar = `area.region${idx}`; |
| 400 | + const altQueries = |
| 401 | + alternatives.length > 0 |
| 402 | + ? alternatives |
| 403 | + .map( |
| 404 | + (alt) => `${searchType}${alt}(${regionVar});`, |
| 405 | + ) |
| 406 | + .join("\n") |
| 407 | + : ""; |
| 408 | + |
| 409 | + return ` |
| 410 | + ${searchType}${filter}(${regionVar}); |
| 411 | + ${altQueries} |
| 412 | + `; |
| 413 | + }) |
| 414 | + .join("\n"); |
378 | 415 |
|
379 | 416 | query = ` |
380 | | -[out:json]${timeoutDuration != 0 ? `[timeout:${timeoutDuration}]` : ""}; |
381 | | -relation(${geoLocation.properties.osm_id});map_to_area->.region; |
382 | | -( |
383 | | -${searchType}${filter}(area.region); |
384 | | -${alternatives.length > 0 ? alternatives.map((alternative) => `${searchType}${alternative}(area.region);`).join("\n") : ""} |
385 | | -); |
386 | | -out ${outType}; |
387 | | -`; |
| 417 | + [out:json]${timeoutDuration !== 0 ? `[timeout:${timeoutDuration}]` : ""}; |
| 418 | + ${relationToAreaBlocks} |
| 419 | + ( |
| 420 | + ${searchBlocks} |
| 421 | + ); |
| 422 | + out ${outType}; |
| 423 | + `; |
| 424 | + } |
| 425 | + |
| 426 | + const data = await getOverpassData( |
| 427 | + query, |
| 428 | + loadingText, |
| 429 | + CacheType.ZONE_CACHE, |
| 430 | + ); |
| 431 | + |
| 432 | + const subtractedEntries = additionalMapGeoLocations |
| 433 | + .get() |
| 434 | + .filter((e) => !e.added); |
| 435 | + const subtractedPolygons = subtractedEntries.map((entry) => entry.location); |
| 436 | + |
| 437 | + if (subtractedPolygons.length > 0 && data && data.elements) { |
| 438 | + const turfPolys = await Promise.all( |
| 439 | + subtractedPolygons.map( |
| 440 | + async (location) => |
| 441 | + turf.combine( |
| 442 | + await determineGeoJSON( |
| 443 | + location.properties.osm_id.toString(), |
| 444 | + location.properties.osm_type, |
| 445 | + ), |
| 446 | + ).features[0], |
| 447 | + ), |
| 448 | + ); |
| 449 | + |
| 450 | + data.elements = data.elements.filter((el: any) => { |
| 451 | + const lon = el.center ? el.center.lon : el.lon; |
| 452 | + const lat = el.center ? el.center.lat : el.lat; |
| 453 | + if (typeof lon !== "number" || typeof lat !== "number") |
| 454 | + return false; |
| 455 | + const pt = turf.point([lon, lat]); |
| 456 | + |
| 457 | + return !turfPolys.some((poly) => |
| 458 | + turf.booleanPointInPolygon(pt, poly as any), |
| 459 | + ); |
| 460 | + }); |
388 | 461 | } |
389 | 462 |
|
390 | | - return await getOverpassData(query, loadingText, CacheType.ZONE_CACHE); |
| 463 | + return data; |
391 | 464 | }; |
392 | 465 |
|
393 | 466 | export const findPlacesSpecificInZone = async ( |
|
0 commit comments