forked from MapComplete/MapComplete
		
	Fix: snapping now also works if the building it snaps to is a multipolygon/relation
This commit is contained in:
		
							parent
							
								
									d224f1fd39
								
							
						
					
					
						commit
						fc940c8a7e
					
				
					 4 changed files with 123 additions and 65 deletions
				
			
		|  | @ -3,6 +3,8 @@ import { Store, UIEventSource } from "../../UIEventSource" | ||||||
| import { Feature, Point } from "geojson" | import { Feature, Point } from "geojson" | ||||||
| import { GeoOperations } from "../../GeoOperations" | import { GeoOperations } from "../../GeoOperations" | ||||||
| import { BBox } from "../../BBox" | import { BBox } from "../../BBox" | ||||||
|  | import { RelationId } from "../../../Models/OsmFeature" | ||||||
|  | import OsmObjectDownloader from "../../Osm/OsmObjectDownloader" | ||||||
| 
 | 
 | ||||||
| export interface SnappingOptions { | export interface SnappingOptions { | ||||||
|     /** |     /** | ||||||
|  | @ -33,13 +35,15 @@ export interface SnappingOptions { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export default class SnappingFeatureSource | export default class SnappingFeatureSource | ||||||
|     implements FeatureSource<Feature<Point, { "snapped-to": string; dist: number }>> |     implements FeatureSource<Feature<Point, { "snapped-to": string; dist: number }>> { | ||||||
| { |  | ||||||
|     public readonly features: Store<[Feature<Point, { "snapped-to": string; dist: number }>]> |     public readonly features: Store<[Feature<Point, { "snapped-to": string; dist: number }>]> | ||||||
|     /*Contains the id of the way it snapped to*/ |     /*Contains the id of the way it snapped to*/ | ||||||
|     public readonly snappedTo: Store<string> |     public readonly snappedTo: Store<string> | ||||||
|     private readonly _snappedTo: UIEventSource<string> |     private readonly _snappedTo: UIEventSource<string> | ||||||
| 
 | 
 | ||||||
|  |     // private static readonly downloadedRelations: UIEventSource<Map<RelationId, OsmRelation>> = new UIEventSource(new Map())
 | ||||||
|  |     private static readonly downloadedRelationMembers: UIEventSource<Feature[]> = new UIEventSource([]) | ||||||
|  | 
 | ||||||
|     constructor( |     constructor( | ||||||
|         snapTo: FeatureSource, |         snapTo: FeatureSource, | ||||||
|         location: Store<{ lon: number; lat: number }>, |         location: Store<{ lon: number; lat: number }>, | ||||||
|  | @ -50,9 +54,9 @@ export default class SnappingFeatureSource | ||||||
|         this.snappedTo = this._snappedTo |         this.snappedTo = this._snappedTo | ||||||
|         const simplifiedFeatures = snapTo.features |         const simplifiedFeatures = snapTo.features | ||||||
|             .mapD((features) => |             .mapD((features) => | ||||||
|                 features |                 [].concat(...features | ||||||
|                     .filter((feature) => feature.geometry.type !== "Point") |                     .filter((feature) => feature.geometry.type !== "Point") | ||||||
|                     .map((f) => GeoOperations.forceLineString(<any>f)) |                     .map((f) => GeoOperations.forceLineString(<any>f))) | ||||||
|             ) |             ) | ||||||
|             .map( |             .map( | ||||||
|                 (features) => { |                 (features) => { | ||||||
|  | @ -63,9 +67,10 @@ export default class SnappingFeatureSource | ||||||
|                 [location] |                 [location] | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|         this.features = location.mapD( |         this.features = location.mapD( | ||||||
|             ({ lon, lat }) => { |             ({ lon, lat }) => { | ||||||
|                 const features = simplifiedFeatures.data |                 const features = simplifiedFeatures.data.concat(...SnappingFeatureSource.downloadedRelationMembers.data) | ||||||
|                 const loc: [number, number] = [lon, lat] |                 const loc: [number, number] = [lon, lat] | ||||||
|                 const maxDistance = (options?.maxDistance ?? 1000) / 1000 |                 const maxDistance = (options?.maxDistance ?? 1000) / 1000 | ||||||
|                 let bestSnap: Feature<Point, { "snapped-to": string; dist: number }> = undefined |                 let bestSnap: Feature<Point, { "snapped-to": string; dist: number }> = undefined | ||||||
|  | @ -74,7 +79,12 @@ export default class SnappingFeatureSource | ||||||
|                         // TODO handle Polygons with holes
 |                         // TODO handle Polygons with holes
 | ||||||
|                         continue |                         continue | ||||||
|                     } |                     } | ||||||
|                     const snapped = GeoOperations.nearestPoint(<any>feature, loc) |                     const snapped: Feature<Point, { | ||||||
|  |                         dist: number; | ||||||
|  |                         index: number; | ||||||
|  |                         multiFeatureIndex: number; | ||||||
|  |                         location: number | ||||||
|  |                     }> = GeoOperations.nearestPoint(feature, loc) | ||||||
|                     if (snapped.properties.dist > maxDistance) { |                     if (snapped.properties.dist > maxDistance) { | ||||||
|                         continue |                         continue | ||||||
|                     } |                     } | ||||||
|  | @ -82,8 +92,20 @@ export default class SnappingFeatureSource | ||||||
|                         bestSnap === undefined || |                         bestSnap === undefined || | ||||||
|                         bestSnap.properties.dist > snapped.properties.dist |                         bestSnap.properties.dist > snapped.properties.dist | ||||||
|                     ) { |                     ) { | ||||||
|                         snapped.properties["snapped-to"] = feature.properties.id |                         const id = feature.properties.id | ||||||
|                         bestSnap = <any>snapped |                         if (id.startsWith("relation/")) { | ||||||
|  |                             /** | ||||||
|  |                              * This is a bit of dirty code: | ||||||
|  |                              * if we find a relation, we'll start to download it and the members. | ||||||
|  |                              * The downloaded members will then be used to snap against as well upon a following iteration | ||||||
|  |                              */ | ||||||
|  |                             SnappingFeatureSource.download(id) | ||||||
|  |                             continue | ||||||
|  |                         } | ||||||
|  |                         bestSnap = { | ||||||
|  |                             ...snapped, | ||||||
|  |                             properties: { ...snapped.properties, "snapped-to": id } | ||||||
|  |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 this._snappedTo.setData(bestSnap?.properties?.["snapped-to"]) |                 this._snappedTo.setData(bestSnap?.properties?.["snapped-to"]) | ||||||
|  | @ -92,19 +114,47 @@ export default class SnappingFeatureSource | ||||||
|                         type: "Feature", |                         type: "Feature", | ||||||
|                         geometry: { |                         geometry: { | ||||||
|                             type: "Point", |                             type: "Point", | ||||||
|                             coordinates: [lon, lat], |                             coordinates: [lon, lat] | ||||||
|                         }, |                         }, | ||||||
|                         properties: { |                         properties: { | ||||||
|                             "snapped-to": undefined, |                             "snapped-to": undefined, | ||||||
|                             dist: -1, |                             dist: -1 | ||||||
|                         }, |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 const c = bestSnap.geometry.coordinates |                 const c = bestSnap.geometry.coordinates | ||||||
|                 options?.snapLocation?.setData({ lon: c[0], lat: c[1] }) |                 options?.snapLocation?.setData({ lon: c[0], lat: c[1] }) | ||||||
|                 return [bestSnap] |                 return [bestSnap] | ||||||
|             }, |             }, | ||||||
|             [snapTo.features] |             [snapTo.features, SnappingFeatureSource.downloadedRelationMembers] | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     private static _downloader = new OsmObjectDownloader() | ||||||
|  |     private static _downloadedRelations = new Set<string>() | ||||||
|  | 
 | ||||||
|  |     private static async download(id: RelationId) { | ||||||
|  |         if (SnappingFeatureSource._downloadedRelations.has(id)) { | ||||||
|  |             return | ||||||
|  |         } | ||||||
|  |         SnappingFeatureSource._downloadedRelations.add(id) | ||||||
|  |         const rel = await SnappingFeatureSource._downloader.DownloadObjectAsync(id, 60 * 24) | ||||||
|  |         if (rel === "deleted") { | ||||||
|  |             return | ||||||
|  |         } | ||||||
|  |         for (const member of rel.members) { | ||||||
|  |             if (member.type !== "way") { | ||||||
|  |                 continue | ||||||
|  |             } | ||||||
|  |             if (member.role !== "outer" && member.role !== "inner") { | ||||||
|  |                 continue | ||||||
|  |             } | ||||||
|  |             const way = await SnappingFeatureSource._downloader.DownloadObjectAsync(member.type + "/" + member.ref) | ||||||
|  |             if (way === "deleted") { | ||||||
|  |                 continue | ||||||
|  |             } | ||||||
|  |             SnappingFeatureSource.downloadedRelationMembers.data.push(...GeoOperations.forceLineString(way.asGeoJson())) | ||||||
|  |         } | ||||||
|  |         SnappingFeatureSource.downloadedRelationMembers.ping() | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -10,11 +10,12 @@ import { | ||||||
|     MultiPolygon, |     MultiPolygon, | ||||||
|     Point, |     Point, | ||||||
|     Polygon, |     Polygon, | ||||||
|     Position, |     Position | ||||||
| } from "geojson" | } from "geojson" | ||||||
| import { Tiles } from "../Models/TileRange" | import { Tiles } from "../Models/TileRange" | ||||||
| import { Utils } from "../Utils" | import { Utils } from "../Utils" | ||||||
| ;("use strict") | 
 | ||||||
|  | ("use strict") | ||||||
| 
 | 
 | ||||||
| export class GeoOperations { | export class GeoOperations { | ||||||
|     private static readonly _earthRadius = 6378137 |     private static readonly _earthRadius = 6378137 | ||||||
|  | @ -28,7 +29,7 @@ export class GeoOperations { | ||||||
|         "behind", |         "behind", | ||||||
|         "sharp_left", |         "sharp_left", | ||||||
|         "left", |         "left", | ||||||
|         "slight_left", |         "slight_left" | ||||||
|     ] as const |     ] as const | ||||||
|     private static reverseBearing = { |     private static reverseBearing = { | ||||||
|         N: 0, |         N: 0, | ||||||
|  | @ -46,7 +47,7 @@ export class GeoOperations { | ||||||
|         W: 270, |         W: 270, | ||||||
|         WNW: 292.5, |         WNW: 292.5, | ||||||
|         NW: 315, |         NW: 315, | ||||||
|         NNW: 337.5, |         NNW: 337.5 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -308,7 +309,7 @@ export class GeoOperations { | ||||||
|         bufferSizeInMeter: number |         bufferSizeInMeter: number | ||||||
|     ): Feature<Polygon | MultiPolygon> | FeatureCollection<Polygon | MultiPolygon> { |     ): Feature<Polygon | MultiPolygon> | FeatureCollection<Polygon | MultiPolygon> { | ||||||
|         return turf.buffer(feature, bufferSizeInMeter / 1000, { |         return turf.buffer(feature, bufferSizeInMeter / 1000, { | ||||||
|             units: "kilometers", |             units: "kilometers" | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -324,9 +325,9 @@ export class GeoOperations { | ||||||
|                     [lon0, lat], |                     [lon0, lat], | ||||||
|                     [lon0, lat0], |                     [lon0, lat0], | ||||||
|                     [lon, lat0], |                     [lon, lat0], | ||||||
|                     [lon, lat], |                     [lon, lat] | ||||||
|                 ], |                 ] | ||||||
|             }, |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -356,40 +357,47 @@ export class GeoOperations { | ||||||
|      * Mostly used as helper for 'nearestPoint' |      * Mostly used as helper for 'nearestPoint' | ||||||
|      * @param way |      * @param way | ||||||
|      */ |      */ | ||||||
|     public static forceLineString(way: Feature<LineString | Polygon>): Feature<LineString> |     public static forceLineString(way: Feature<LineString | Polygon>): Feature<LineString>[] | ||||||
| 
 | 
 | ||||||
|     public static forceLineString( |     public static forceLineString( | ||||||
|         way: Feature<MultiLineString | MultiPolygon> |         way: Feature<MultiLineString | MultiPolygon> | ||||||
|     ): Feature<MultiLineString> |     ): Feature<MultiLineString>[] | ||||||
| 
 | 
 | ||||||
|     public static forceLineString( |     public static forceLineString( | ||||||
|         way: Feature<LineString | MultiLineString | Polygon | MultiPolygon> |         way: Feature<LineString | MultiLineString | Polygon | MultiPolygon> | ||||||
|     ): Feature<LineString | MultiLineString> { |     ): Feature<LineString | MultiLineString>[] { | ||||||
|         if (way.geometry.type === "Polygon") { |         if (way.geometry.type === "Polygon") { | ||||||
|             return <Feature<LineString>>{ |             const poly: Feature<Polygon> = <Feature<Polygon>>way | ||||||
|                 type: "Feature", |             return poly.geometry.coordinates.map((linestringCoors, i) => { | ||||||
|                 geometry: { |                 return <Feature<LineString>>{ | ||||||
|                     type: "LineString", |                     type: "Feature", | ||||||
|                     coordinates: way.geometry.coordinates[0], |                     geometry: { | ||||||
|                 }, |                         type: "LineString", | ||||||
|                 properties: way.properties, |                         coordinates: linestringCoors | ||||||
|             } |                     }, | ||||||
|  |                     properties: way.properties | ||||||
|  |                 } | ||||||
|  |             }) | ||||||
|         } |         } | ||||||
|         if (way.geometry.type === "MultiPolygon") { |         if (way.geometry.type === "MultiPolygon") { | ||||||
|             return <Feature<MultiLineString>>{ |             const mpoly: Feature<MultiPolygon> = <Feature<MultiPolygon>>way | ||||||
|                 type: "Feature", | 
 | ||||||
|                 geometry: { |             return [].concat(...mpoly.geometry.coordinates.map(linestrings => | ||||||
|                     type: "MultiLineString", |                 [].concat(...linestrings.map(linestring => | ||||||
|                     coordinates: way.geometry.coordinates[0], |                     <Feature<LineString>>{ | ||||||
|                 }, |                         type: "Feature", | ||||||
|                 properties: way.properties, |                         geometry: { | ||||||
|             } |                             type: "LineString", | ||||||
|  |                             coordinates: linestring | ||||||
|  |                         }, | ||||||
|  |                         properties: way.properties | ||||||
|  |                     })))) | ||||||
|         } |         } | ||||||
|         if (way.geometry.type === "LineString") { |         if (way.geometry.type === "LineString") { | ||||||
|             return <Feature<LineString>>way |             return [<Feature<LineString>>way] | ||||||
|         } |         } | ||||||
|         if (way.geometry.type === "MultiLineString") { |         if (way.geometry.type === "MultiLineString") { | ||||||
|             return <Feature<MultiLineString>>way |             return [<Feature<MultiLineString>>way] | ||||||
|         } |         } | ||||||
|         throw "Invalid geometry to create a way from this" |         throw "Invalid geometry to create a way from this" | ||||||
|     } |     } | ||||||
|  | @ -466,7 +474,7 @@ export class GeoOperations { | ||||||
|         const lon = lonLat[0] |         const lon = lonLat[0] | ||||||
|         const lat = lonLat[1] |         const lat = lonLat[1] | ||||||
|         const x = (180 * lon) / GeoOperations._originShift |         const x = (180 * lon) / GeoOperations._originShift | ||||||
|         let y = (180 * lat) / GeoOperations._originShift |         let y = (180 * lat) / GeoOperations._originShiftcons | ||||||
|         y = (180 / Math.PI) * (2 * Math.atan(Math.exp((y * Math.PI) / 180)) - Math.PI / 2) |         y = (180 / Math.PI) * (2 * Math.atan(Math.exp((y * Math.PI) / 180)) - Math.PI / 2) | ||||||
|         return [x, y] |         return [x, y] | ||||||
|     } |     } | ||||||
|  | @ -560,7 +568,7 @@ export class GeoOperations { | ||||||
|                 } |                 } | ||||||
|                 const properties = { |                 const properties = { | ||||||
|                     ...f.properties, |                     ...f.properties, | ||||||
|                     id, |                     id | ||||||
|                 } |                 } | ||||||
|                 intersectionPart.properties = properties |                 intersectionPart.properties = properties | ||||||
|                 newFeatures.push(intersectionPart) |                 newFeatures.push(intersectionPart) | ||||||
|  | @ -592,8 +600,8 @@ export class GeoOperations { | ||||||
|                         properties: {}, |                         properties: {}, | ||||||
|                         geometry: { |                         geometry: { | ||||||
|                             type: "Point", |                             type: "Point", | ||||||
|                             coordinates: p, |                             coordinates: p | ||||||
|                         }, |                         } | ||||||
|                     } |                     } | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
|  | @ -609,7 +617,7 @@ export class GeoOperations { | ||||||
|             trackPoints.push(trkpt) |             trackPoints.push(trkpt) | ||||||
|         } |         } | ||||||
|         const header = |         const header = | ||||||
|             '<gpx version="1.1" creator="mapcomplete.org" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">' |             "<gpx version=\"1.1\" creator=\"mapcomplete.org\" xmlns=\"http://www.topografix.com/GPX/1/1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">" | ||||||
|         return ( |         return ( | ||||||
|             header + |             header + | ||||||
|             "\n<name>" + |             "\n<name>" + | ||||||
|  | @ -648,7 +656,7 @@ export class GeoOperations { | ||||||
|             trackPoints.push(trkpt) |             trackPoints.push(trkpt) | ||||||
|         } |         } | ||||||
|         const header = |         const header = | ||||||
|             '<gpx version="1.1" creator="mapcomplete.org" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">' |             "<gpx version=\"1.1\" creator=\"mapcomplete.org\" xmlns=\"http://www.topografix.com/GPX/1/1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">" | ||||||
|         return ( |         return ( | ||||||
|             header + |             header + | ||||||
|             "\n<name>" + |             "\n<name>" + | ||||||
|  | @ -674,7 +682,7 @@ export class GeoOperations { | ||||||
| 
 | 
 | ||||||
|         const copy = { |         const copy = { | ||||||
|             ...feature, |             ...feature, | ||||||
|             geometry: { ...feature.geometry }, |             geometry: { ...feature.geometry } | ||||||
|         } |         } | ||||||
|         let coordinates: [number, number][] |         let coordinates: [number, number][] | ||||||
|         if (feature.geometry.type === "LineString") { |         if (feature.geometry.type === "LineString") { | ||||||
|  | @ -732,8 +740,8 @@ export class GeoOperations { | ||||||
|                 type: "Feature", |                 type: "Feature", | ||||||
|                 geometry: { |                 geometry: { | ||||||
|                     type: "LineString", |                     type: "LineString", | ||||||
|                     coordinates: [a, b], |                     coordinates: [a, b] | ||||||
|                 }, |                 } | ||||||
|             }, |             }, | ||||||
|             distanceMeter, |             distanceMeter, | ||||||
|             { units: "meters" } |             { units: "meters" } | ||||||
|  | @ -780,8 +788,8 @@ export class GeoOperations { | ||||||
|                         type: "Feature", |                         type: "Feature", | ||||||
|                         geometry: { |                         geometry: { | ||||||
|                             type: "Polygon", |                             type: "Polygon", | ||||||
|                             coordinates, |                             coordinates | ||||||
|                         }, |                         } | ||||||
|                     } |                     } | ||||||
|             ) |             ) | ||||||
|             return !polygons.some((polygon) => !booleanWithin(polygon, possiblyEnclosingFeature)) |             return !polygons.some((polygon) => !booleanWithin(polygon, possiblyEnclosingFeature)) | ||||||
|  | @ -860,8 +868,8 @@ export class GeoOperations { | ||||||
|                             type: "Feature", |                             type: "Feature", | ||||||
|                             properties: { ...toSplit.properties }, |                             properties: { ...toSplit.properties }, | ||||||
|                             geometry: boundary.geometry, |                             geometry: boundary.geometry, | ||||||
|                             bbox: boundary.bbox, |                             bbox: boundary.bbox | ||||||
|                         }, |                         } | ||||||
|                     ] |                     ] | ||||||
|                 } |                 } | ||||||
|                 return [] |                 return [] | ||||||
|  | @ -959,8 +967,8 @@ export class GeoOperations { | ||||||
|             properties: p.properties, |             properties: p.properties, | ||||||
|             geometry: { |             geometry: { | ||||||
|                 type: "LineString", |                 type: "LineString", | ||||||
|                 coordinates: p.geometry.coordinates[0], |                 coordinates: p.geometry.coordinates[0] | ||||||
|             }, |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -988,7 +996,7 @@ export class GeoOperations { | ||||||
|                             console.debug("Splitting way", feature.properties.id) |                             console.debug("Splitting way", feature.properties.id) | ||||||
|                             result.push(<Feature>{ |                             result.push(<Feature>{ | ||||||
|                                 ...feature, |                                 ...feature, | ||||||
|                                 geometry: { ...feature.geometry, coordinates: coors.slice(i + 1) }, |                                 geometry: { ...feature.geometry, coordinates: coors.slice(i + 1) } | ||||||
|                             }) |                             }) | ||||||
|                             coors = coors.slice(0, i + 1) |                             coors = coors.slice(0, i + 1) | ||||||
|                             break |                             break | ||||||
|  | @ -997,7 +1005,7 @@ export class GeoOperations { | ||||||
|                 } |                 } | ||||||
|                 result.push(<Feature>{ |                 result.push(<Feature>{ | ||||||
|                     ...feature, |                     ...feature, | ||||||
|                     geometry: { ...feature.geometry, coordinates: coors }, |                     geometry: { ...feature.geometry, coordinates: coors } | ||||||
|                 }) |                 }) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -1171,8 +1179,8 @@ export class GeoOperations { | ||||||
|                 properties: multiLineStringFeature.properties, |                 properties: multiLineStringFeature.properties, | ||||||
|                 geometry: { |                 geometry: { | ||||||
|                     type: "LineString", |                     type: "LineString", | ||||||
|                     coordinates: coors[0], |                     coordinates: coors[0] | ||||||
|                 }, |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         return { |         return { | ||||||
|  | @ -1180,8 +1188,8 @@ export class GeoOperations { | ||||||
|             properties: multiLineStringFeature.properties, |             properties: multiLineStringFeature.properties, | ||||||
|             geometry: { |             geometry: { | ||||||
|                 type: "MultiLineString", |                 type: "MultiLineString", | ||||||
|                 coordinates: coors, |                 coordinates: coors | ||||||
|             }, |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -1334,7 +1342,7 @@ export class GeoOperations { | ||||||
|                     const intersection = turf.intersect( |                     const intersection = turf.intersect( | ||||||
|                         turf.featureCollection([ |                         turf.featureCollection([ | ||||||
|                             turf.truncate(feature), |                             turf.truncate(feature), | ||||||
|                             turf.truncate(otherFeature), |                             turf.truncate(otherFeature) | ||||||
|                         ]) |                         ]) | ||||||
|                     ) |                     ) | ||||||
|                     if (intersection == null) { |                     if (intersection == null) { | ||||||
|  |  | ||||||
|  | @ -40,7 +40,7 @@ export default class OsmObjectDownloader { | ||||||
|     async DownloadObjectAsync( |     async DownloadObjectAsync( | ||||||
|         id: RelationId, |         id: RelationId, | ||||||
|         maxCacheAgeInSecs?: number |         maxCacheAgeInSecs?: number | ||||||
|     ): Promise<OsmRelation | undefined> |     ): Promise<OsmRelation | "deleted"> | ||||||
| 
 | 
 | ||||||
|     async DownloadObjectAsync(id: OsmId, maxCacheAgeInSecs?: number): Promise<OsmObject | "deleted"> |     async DownloadObjectAsync(id: OsmId, maxCacheAgeInSecs?: number): Promise<OsmObject | "deleted"> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -61,7 +61,7 @@ | ||||||
|   let map: UIEventSource<MlMap> = new UIEventSource<MlMap>(undefined) |   let map: UIEventSource<MlMap> = new UIEventSource<MlMap>(undefined) | ||||||
|   let adaptor = new MapLibreAdaptor(map, mapProperties) |   let adaptor = new MapLibreAdaptor(map, mapProperties) | ||||||
| 
 | 
 | ||||||
|   let wayGeojson: Feature<LineString> = GeoOperations.forceLineString(osmWay.asGeoJson()) |   let wayGeojson: Feature<LineString> = <Feature<LineString>>osmWay.asGeoJson() | ||||||
|   adaptor.location.setData(GeoOperations.centerpointCoordinatesObj(wayGeojson)) |   adaptor.location.setData(GeoOperations.centerpointCoordinatesObj(wayGeojson)) | ||||||
|   adaptor.bounds.setData(BBox.get(wayGeojson).pad(2)) |   adaptor.bounds.setData(BBox.get(wayGeojson).pad(2)) | ||||||
|   adaptor.maxbounds.setData(BBox.get(wayGeojson).pad(2)) |   adaptor.maxbounds.setData(BBox.get(wayGeojson).pad(2)) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue