mapcomplete/Logic/Osm/Actions/CreateMultiPolygonWithPointReuseAction.ts
2022-02-22 14:13:41 +01:00

103 lines
No EOL
3.8 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
}
}