mapcomplete/Logic/Osm/Actions/CreateMultiPolygonWithPointReuseAction.ts

108 lines
3.9 KiB
TypeScript

import { OsmCreateAction } from "./OsmChangeAction"
import { Tag } from "../../Tags/Tag"
import { Changes } from "../Changes"
import { ChangeDescription } from "./ChangeDescription"
import FeaturePipelineState from "../../State/FeaturePipelineState"
import FeatureSource from "../../FeatureSource/FeatureSource"
import CreateNewWayAction from "./CreateNewWayAction"
import CreateWayWithPointReuseAction, { MergePointConfig } from "./CreateWayWithPointReuseAction"
import { And } from "../../Tags/And"
import { TagUtils } from "../../Tags/TagUtils"
/**
* More or less the same as 'CreateNewWay', except that it'll try to reuse already existing points
*/
export default class CreateMultiPolygonWithPointReuseAction extends OsmCreateAction {
public newElementId: string = undefined
public newElementIdNumber: number = undefined
private readonly _tags: Tag[]
private readonly createOuterWay: CreateWayWithPointReuseAction
private readonly createInnerWays: CreateNewWayAction[]
private readonly geojsonPreview: any
private readonly theme: string
private readonly changeType: "import" | "create" | string
constructor(
tags: Tag[],
outerRingCoordinates: [number, number][],
innerRingsCoordinates: [number, number][][],
state: FeaturePipelineState,
config: MergePointConfig[],
changeType: "import" | "create" | string
) {
super(null, true)
this._tags = [...tags, new Tag("type", "multipolygon")]
this.changeType = changeType
this.theme = state?.layoutToUse?.id ?? ""
this.createOuterWay = new CreateWayWithPointReuseAction(
[],
outerRingCoordinates,
state,
config
)
this.createInnerWays = innerRingsCoordinates.map(
(ringCoordinates) =>
new CreateNewWayAction(
[],
ringCoordinates.map(([lon, lat]) => ({ lat, lon })),
{ theme: state?.layoutToUse?.id }
)
)
this.geojsonPreview = {
type: "Feature",
properties: TagUtils.changeAsProperties(new And(this._tags).asChange({})),
geometry: {
type: "Polygon",
coordinates: [outerRingCoordinates, ...innerRingsCoordinates],
},
}
}
public async getPreview(): Promise<FeatureSource> {
const outerPreview = await this.createOuterWay.getPreview()
outerPreview.features.data.push({
freshness: new Date(),
feature: this.geojsonPreview,
})
return outerPreview
}
protected async CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]> {
console.log("Running CMPWPRA")
const descriptions: ChangeDescription[] = []
descriptions.push(...(await this.createOuterWay.CreateChangeDescriptions(changes)))
for (const innerWay of this.createInnerWays) {
descriptions.push(...(await innerWay.CreateChangeDescriptions(changes)))
}
this.newElementIdNumber = changes.getNewID()
this.newElementId = "relation/" + this.newElementIdNumber
descriptions.push({
type: "relation",
id: this.newElementIdNumber,
tags: new And(this._tags).asChange({}),
meta: {
theme: this.theme,
changeType: this.changeType,
},
changes: {
members: [
{
type: "way",
ref: this.createOuterWay.newElementIdNumber,
role: "outer",
},
// @ts-ignore
...this.createInnerWays.map((a) => ({
type: "way",
ref: a.newElementIdNumber,
role: "inner",
})),
],
},
})
return descriptions
}
}