| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  | import {Tag} from "../../Tags/Tag"; | 
					
						
							|  |  |  | import OsmChangeAction from "./OsmChangeAction"; | 
					
						
							|  |  |  | import {Changes} from "../Changes"; | 
					
						
							|  |  |  | import {ChangeDescription} from "./ChangeDescription"; | 
					
						
							|  |  |  | import {And} from "../../Tags/And"; | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  | import {OsmWay} from "../OsmObject"; | 
					
						
							|  |  |  | import {GeoOperations} from "../../GeoOperations"; | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-18 14:52:09 +02:00
										 |  |  | export default class CreateNewNodeAction extends OsmChangeAction { | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |     public newElementId: string = undefined | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |     private readonly _basicTags: Tag[]; | 
					
						
							|  |  |  |     private readonly _lat: number; | 
					
						
							|  |  |  |     private readonly _lon: number; | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |     private readonly _snapOnto: OsmWay; | 
					
						
							|  |  |  |     private readonly _reusePointDistance: number; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     constructor(basicTags: Tag[], lat: number, lon: number, options?: { snapOnto: OsmWay, reusePointWithinMeters?: number }) { | 
					
						
							| 
									
										
										
										
											2021-07-18 14:52:09 +02:00
										 |  |  |         super() | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |         this._basicTags = basicTags; | 
					
						
							|  |  |  |         this._lat = lat; | 
					
						
							|  |  |  |         this._lon = lon; | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |         if (lat === undefined || lon === undefined) { | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |             throw "Lat or lon are undefined!" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         this._snapOnto = options?.snapOnto; | 
					
						
							|  |  |  |         this._reusePointDistance = options.reusePointWithinMeters ?? 1 | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-18 14:52:09 +02:00
										 |  |  |     CreateChangeDescriptions(changes: Changes): ChangeDescription[] { | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |         const id = changes.getNewID() | 
					
						
							|  |  |  |         const properties = { | 
					
						
							|  |  |  |             id: "node/" + id | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |         this.newElementId = "node/" + id | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |         for (const kv of this._basicTags) { | 
					
						
							|  |  |  |             if (typeof kv.value !== "string") { | 
					
						
							|  |  |  |                 throw "Invalid value: don't use a regex in a preset" | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             properties[kv.key] = kv.value; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |         const newPointChange: ChangeDescription = { | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |             tags: new And(this._basicTags).asChange(properties), | 
					
						
							|  |  |  |             type: "node", | 
					
						
							|  |  |  |             id: id, | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |             changes: { | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                 lat: this._lat, | 
					
						
							|  |  |  |                 lon: this._lon | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (this._snapOnto === undefined) { | 
					
						
							|  |  |  |             return [newPointChange] | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Project the point onto the way
 | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |         const geojson = this._snapOnto.asGeoJson() | 
					
						
							|  |  |  |         const projected = GeoOperations.nearestPoint(geojson, [this._lon, this._lat]) | 
					
						
							|  |  |  |         const index = projected.properties.index | 
					
						
							|  |  |  |         // We check that it isn't close to an already existing point
 | 
					
						
							|  |  |  |         let reusedPointId = undefined; | 
					
						
							|  |  |  |         const prev = <[number, number]>geojson.geometry.coordinates[index] | 
					
						
							|  |  |  |         if (GeoOperations.distanceBetween(prev, <[number, number]>projected.geometry.coordinates) * 1000 < this._reusePointDistance) { | 
					
						
							|  |  |  |             // We reuse this point instead!
 | 
					
						
							|  |  |  |             reusedPointId = this._snapOnto.nodes[index] | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const next = <[number, number]>geojson.geometry.coordinates[index + 1] | 
					
						
							|  |  |  |         if (GeoOperations.distanceBetween(next, <[number, number]>projected.geometry.coordinates) * 1000 < this._reusePointDistance) { | 
					
						
							|  |  |  |             // We reuse this point instead!
 | 
					
						
							|  |  |  |             reusedPointId = this._snapOnto.nodes[index + 1] | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (reusedPointId !== undefined) { | 
					
						
							|  |  |  |             console.log("Reusing an existing point:", reusedPointId) | 
					
						
							|  |  |  |             this.newElementId = "node/" + reusedPointId | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return [{ | 
					
						
							|  |  |  |                 tags: new And(this._basicTags).asChange(properties), | 
					
						
							|  |  |  |                 type: "node", | 
					
						
							|  |  |  |                 id: reusedPointId | 
					
						
							|  |  |  |             }] | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |         const locations = [...this._snapOnto.coordinates] | 
					
						
							|  |  |  |         locations.forEach(coor => coor.reverse()) | 
					
						
							|  |  |  |         console.log("Locations are: ", locations) | 
					
						
							|  |  |  |         const ids = [...this._snapOnto.nodes] | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |         locations.splice(index + 1, 0, [this._lon, this._lat]) | 
					
						
							|  |  |  |         ids.splice(index + 1, 0, id) | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |         // Allright, we have to insert a new point in the way
 | 
					
						
							|  |  |  |         return [ | 
					
						
							|  |  |  |             newPointChange, | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |                 type: "way", | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |                 id: this._snapOnto.id, | 
					
						
							|  |  |  |                 changes: { | 
					
						
							|  |  |  |                     locations: locations, | 
					
						
							|  |  |  |                     nodes: ids | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ] | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |