2022-09-08 21:40:48 +02:00
|
|
|
import { Tag } from "../../Tags/Tag"
|
|
|
|
|
import { OsmCreateAction } from "./OsmChangeAction"
|
|
|
|
|
import { Changes } from "../Changes"
|
|
|
|
|
import { ChangeDescription } from "./ChangeDescription"
|
|
|
|
|
import { And } from "../../Tags/And"
|
|
|
|
|
import { OsmWay } from "../OsmObject"
|
|
|
|
|
import { GeoOperations } from "../../GeoOperations"
|
2024-09-04 00:07:23 +02:00
|
|
|
import InsertPointIntoWayAction from "./InsertPointIntoWayAction"
|
2021-07-15 20:47:28 +02:00
|
|
|
|
2021-12-10 04:00:02 +01:00
|
|
|
export default class CreateNewNodeAction extends OsmCreateAction {
|
2021-10-29 16:38:33 +02:00
|
|
|
/**
|
|
|
|
|
* Maps previously created points onto their assigned ID, to reuse the point if uplaoded
|
|
|
|
|
* "lat,lon" --> id
|
|
|
|
|
*/
|
|
|
|
|
private static readonly previouslyCreatedPoints = new Map<string, number>()
|
2021-09-09 00:05:51 +02:00
|
|
|
public newElementId: string = undefined
|
2021-10-29 16:38:33 +02:00
|
|
|
public newElementIdNumber: number = undefined
|
2022-09-08 21:40:48 +02:00
|
|
|
private readonly _basicTags: Tag[]
|
|
|
|
|
private readonly _lat: number
|
|
|
|
|
private readonly _lon: number
|
|
|
|
|
private readonly _snapOnto: OsmWay
|
|
|
|
|
private readonly _reusePointDistance: number
|
2022-10-27 01:50:41 +02:00
|
|
|
private readonly meta: {
|
|
|
|
|
changeType: "create" | "import"
|
|
|
|
|
theme: string
|
|
|
|
|
specialMotivation?: string
|
|
|
|
|
}
|
2022-09-08 21:40:48 +02:00
|
|
|
private readonly _reusePreviouslyCreatedPoint: boolean
|
|
|
|
|
|
|
|
|
|
constructor(
|
|
|
|
|
basicTags: Tag[],
|
|
|
|
|
lat: number,
|
|
|
|
|
lon: number,
|
|
|
|
|
options: {
|
|
|
|
|
allowReuseOfPreviouslyCreatedPoints?: boolean
|
|
|
|
|
snapOnto?: OsmWay
|
|
|
|
|
reusePointWithinMeters?: number
|
|
|
|
|
theme: string
|
|
|
|
|
changeType: "create" | "import" | null
|
|
|
|
|
specialMotivation?: string
|
2024-09-04 00:07:23 +02:00
|
|
|
},
|
2022-09-08 21:40:48 +02:00
|
|
|
) {
|
2022-01-26 21:40:38 +01:00
|
|
|
super(null, basicTags !== undefined && basicTags.length > 0)
|
2022-09-08 21:40:48 +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!"
|
|
|
|
|
}
|
2022-09-08 21:40:48 +02:00
|
|
|
this._snapOnto = options?.snapOnto
|
2021-09-18 02:34:13 +02:00
|
|
|
this._reusePointDistance = options?.reusePointWithinMeters ?? 1
|
2022-09-08 21:40:48 +02:00
|
|
|
this._reusePreviouslyCreatedPoint =
|
|
|
|
|
options?.allowReuseOfPreviouslyCreatedPoints ?? basicTags.length === 0
|
2021-10-04 03:12:42 +02:00
|
|
|
this.meta = {
|
|
|
|
|
theme: options.theme,
|
2022-01-25 00:48:05 +01:00
|
|
|
changeType: options.changeType,
|
2022-09-08 21:40:48 +02:00
|
|
|
specialMotivation: options.specialMotivation,
|
2021-10-04 03:12:42 +02:00
|
|
|
}
|
2021-07-15 20:47:28 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-22 05:02:09 +02:00
|
|
|
async CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]> {
|
2021-10-29 16:38:33 +02:00
|
|
|
if (this._reusePreviouslyCreatedPoint) {
|
|
|
|
|
const key = this._lat + "," + this._lon
|
|
|
|
|
const prev = CreateNewNodeAction.previouslyCreatedPoints
|
|
|
|
|
if (prev.has(key)) {
|
|
|
|
|
this.newElementIdNumber = prev.get(key)
|
|
|
|
|
this.newElementId = "node/" + this.newElementIdNumber
|
|
|
|
|
return []
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-15 20:47:28 +02:00
|
|
|
const id = changes.getNewID()
|
|
|
|
|
const properties = {
|
2022-09-08 21:40:48 +02:00
|
|
|
id: "node/" + id,
|
2021-07-15 20:47:28 +02:00
|
|
|
}
|
2021-10-29 16:38:33 +02:00
|
|
|
this.setElementId(id)
|
2021-07-15 20:47:28 +02:00
|
|
|
for (const kv of this._basicTags) {
|
|
|
|
|
if (typeof kv.value !== "string") {
|
2022-09-08 21:40:48 +02:00
|
|
|
throw (
|
|
|
|
|
"Invalid value: don't use non-string value in a preset. The tag " +
|
|
|
|
|
kv.key +
|
|
|
|
|
"=" +
|
|
|
|
|
kv.value +
|
|
|
|
|
" is not a string, the value is a " +
|
|
|
|
|
typeof kv.value
|
|
|
|
|
)
|
2021-07-15 20:47:28 +02:00
|
|
|
}
|
2022-09-08 21:40:48 +02:00
|
|
|
properties[kv.key] = kv.value
|
2021-07-15 20:47:28 +02:00
|
|
|
}
|
|
|
|
|
|
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,
|
2022-09-08 21:40:48 +02:00
|
|
|
lon: this._lon,
|
2021-10-04 03:12:42 +02:00
|
|
|
},
|
2022-09-08 21:40:48 +02:00
|
|
|
meta: this.meta,
|
2021-08-07 21:19:01 +02:00
|
|
|
}
|
2023-09-21 14:53:52 +02:00
|
|
|
if (this._snapOnto?.coordinates === undefined) {
|
2021-08-07 21:19:01 +02:00
|
|
|
return [newPointChange]
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-04 00:07:23 +02:00
|
|
|
const change = new InsertPointIntoWayAction(
|
2023-04-06 01:33:08 +02:00
|
|
|
this._lat,
|
2024-09-04 00:07:23 +02:00
|
|
|
this._lon,
|
|
|
|
|
id,
|
|
|
|
|
this._snapOnto,
|
|
|
|
|
{
|
|
|
|
|
reusePointWithinMeters: this._reusePointDistance,
|
|
|
|
|
allowReuseOfPreviouslyCreatedPoints: this._reusePreviouslyCreatedPoint,
|
|
|
|
|
},
|
|
|
|
|
).prepareChangeDescription()
|
2022-09-08 21:40:48 +02:00
|
|
|
|
2021-08-07 21:19:01 +02:00
|
|
|
return [
|
|
|
|
|
newPointChange,
|
2024-09-04 00:07:23 +02:00
|
|
|
{ ...change, meta: this.meta },
|
2021-08-07 21:19:01 +02:00
|
|
|
]
|
2021-07-15 20:47:28 +02:00
|
|
|
}
|
|
|
|
|
|
2021-10-29 16:38:33 +02:00
|
|
|
private setElementId(id: number) {
|
2022-09-08 21:40:48 +02:00
|
|
|
this.newElementIdNumber = id
|
2021-11-07 16:34:51 +01:00
|
|
|
this.newElementId = "node/" + id
|
2021-10-29 16:38:33 +02:00
|
|
|
if (!this._reusePreviouslyCreatedPoint) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const key = this._lat + "," + this._lon
|
|
|
|
|
CreateNewNodeAction.previouslyCreatedPoints.set(key, id)
|
|
|
|
|
}
|
2022-09-08 21:40:48 +02:00
|
|
|
}
|