forked from MapComplete/MapComplete
Refactoring of import button, various improvements
This commit is contained in:
parent
cabbdf96db
commit
a095af4f18
17 changed files with 527 additions and 328 deletions
|
@ -42,7 +42,6 @@ export class NewGeometryFromChangesFeatureSource implements FeatureSource {
|
|||
feature: feature,
|
||||
freshness: now
|
||||
})
|
||||
console.warn("Added a new feature: ", JSON.stringify(feature))
|
||||
}
|
||||
|
||||
for (const change of changes) {
|
||||
|
|
102
Logic/Osm/Actions/CreateMultiPolygonWithPointReuseAction.ts
Normal file
102
Logic/Osm/Actions/CreateMultiPolygonWithPointReuseAction.ts
Normal file
|
@ -0,0 +1,102 @@
|
|||
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 {
|
||||
private readonly _tags: Tag[];
|
||||
public newElementId: string = undefined;
|
||||
public newElementIdNumber: number = undefined;
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
import {Tag} from "../../Tags/Tag";
|
||||
import OsmChangeAction from "./OsmChangeAction";
|
||||
import OsmChangeAction, {OsmCreateAction} from "./OsmChangeAction";
|
||||
import {Changes} from "../Changes";
|
||||
import {ChangeDescription} from "./ChangeDescription";
|
||||
import {And} from "../../Tags/And";
|
||||
import {OsmWay} from "../OsmObject";
|
||||
import {GeoOperations} from "../../GeoOperations";
|
||||
|
||||
export default class CreateNewNodeAction extends OsmChangeAction {
|
||||
export default class CreateNewNodeAction extends OsmCreateAction {
|
||||
|
||||
/**
|
||||
* Maps previously created points onto their assigned ID, to reuse the point if uplaoded
|
||||
|
@ -121,7 +121,6 @@ export default class CreateNewNodeAction extends OsmChangeAction {
|
|||
reusedPointId = this._snapOnto.nodes[index + 1]
|
||||
}
|
||||
if (reusedPointId !== undefined) {
|
||||
console.log("Reusing an existing point:", reusedPointId)
|
||||
this.setElementId(reusedPointId)
|
||||
return [{
|
||||
tags: new And(this._basicTags).asChange(properties),
|
||||
|
@ -133,7 +132,6 @@ export default class CreateNewNodeAction extends OsmChangeAction {
|
|||
|
||||
const locations = [...this._snapOnto.coordinates]
|
||||
locations.forEach(coor => coor.reverse())
|
||||
console.log("Locations are: ", locations)
|
||||
const ids = [...this._snapOnto.nodes]
|
||||
|
||||
locations.splice(index + 1, 0, [this._lon, this._lat])
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import {ChangeDescription} from "./ChangeDescription";
|
||||
import OsmChangeAction from "./OsmChangeAction";
|
||||
import {OsmCreateAction} from "./OsmChangeAction";
|
||||
import {Changes} from "../Changes";
|
||||
import {Tag} from "../../Tags/Tag";
|
||||
import CreateNewNodeAction from "./CreateNewNodeAction";
|
||||
import {And} from "../../Tags/And";
|
||||
|
||||
export default class CreateNewWayAction extends OsmChangeAction {
|
||||
export default class CreateNewWayAction extends OsmCreateAction {
|
||||
public newElementId: string = undefined
|
||||
public newElementIdNumber: number = undefined;
|
||||
private readonly coordinates: ({ nodeId?: number, lat: number, lon: number })[];
|
||||
private readonly tags: Tag[];
|
||||
private readonly _options: {
|
||||
|
@ -55,7 +56,7 @@ export default class CreateNewWayAction extends OsmChangeAction {
|
|||
|
||||
|
||||
const id = changes.getNewID()
|
||||
|
||||
this.newElementIdNumber = id
|
||||
const newWay = <ChangeDescription>{
|
||||
id,
|
||||
type: "way",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import OsmChangeAction from "./OsmChangeAction";
|
||||
import OsmChangeAction, {OsmCreateAction} from "./OsmChangeAction";
|
||||
import {Tag} from "../../Tags/Tag";
|
||||
import {Changes} from "../Changes";
|
||||
import {ChangeDescription} from "./ChangeDescription";
|
||||
|
@ -31,7 +31,7 @@ interface CoordinateInfo {
|
|||
/**
|
||||
* More or less the same as 'CreateNewWay', except that it'll try to reuse already existing points
|
||||
*/
|
||||
export default class CreateWayWithPointReuseAction extends OsmChangeAction {
|
||||
export default class CreateWayWithPointReuseAction extends OsmCreateAction {
|
||||
private readonly _tags: Tag[];
|
||||
/**
|
||||
* lngLat-coordinates
|
||||
|
@ -40,6 +40,9 @@ export default class CreateWayWithPointReuseAction extends OsmChangeAction {
|
|||
private _coordinateInfo: CoordinateInfo[];
|
||||
private _state: FeaturePipelineState;
|
||||
private _config: MergePointConfig[];
|
||||
|
||||
public newElementId: string = undefined;
|
||||
public newElementIdNumber: number = undefined
|
||||
|
||||
constructor(tags: Tag[],
|
||||
coordinates: [number, number][],
|
||||
|
@ -87,7 +90,8 @@ export default class CreateWayWithPointReuseAction extends OsmChangeAction {
|
|||
properties: {
|
||||
"move": "yes",
|
||||
"osm-id": reusedPoint.node.properties.id,
|
||||
"id": "new-geometry-move-existing" + i
|
||||
"id": "new-geometry-move-existing" + i,
|
||||
"distance":GeoOperations.distanceBetween(coordinateInfo.lngLat, reusedPoint.node.geometry.coordinates)
|
||||
},
|
||||
geometry: {
|
||||
type: "LineString",
|
||||
|
@ -97,8 +101,23 @@ export default class CreateWayWithPointReuseAction extends OsmChangeAction {
|
|||
features.push(moveDescription)
|
||||
|
||||
} else {
|
||||
// The geometry is moved
|
||||
// The geometry is moved, the point is reused
|
||||
geometryMoved = true
|
||||
|
||||
const reuseDescription = {
|
||||
type: "Feature",
|
||||
properties: {
|
||||
"move": "no",
|
||||
"osm-id": reusedPoint.node.properties.id,
|
||||
"id": "new-geometry-reuse-existing" + i,
|
||||
"distance":GeoOperations.distanceBetween(coordinateInfo.lngLat, reusedPoint.node.geometry.coordinates)
|
||||
},
|
||||
geometry: {
|
||||
type: "LineString",
|
||||
coordinates: [coordinateInfo.lngLat, reusedPoint.node.geometry.coordinates]
|
||||
}
|
||||
}
|
||||
features.push(reuseDescription)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,11 +157,10 @@ export default class CreateWayWithPointReuseAction extends OsmChangeAction {
|
|||
features.push(newGeometry)
|
||||
|
||||
}
|
||||
console.log("Preview:", features)
|
||||
return new StaticFeatureSource(features, false)
|
||||
}
|
||||
|
||||
protected async CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]> {
|
||||
public async CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]> {
|
||||
const theme = this._state.layoutToUse.id
|
||||
const allChanges: ChangeDescription[] = []
|
||||
const nodeIdsToUse: { lat: number, lon: number, nodeId?: number }[] = []
|
||||
|
@ -196,6 +214,8 @@ export default class CreateWayWithPointReuseAction extends OsmChangeAction {
|
|||
})
|
||||
|
||||
allChanges.push(...(await newWay.CreateChangeDescriptions(changes)))
|
||||
this.newElementId = newWay.newElementId
|
||||
this.newElementIdNumber = newWay.newElementIdNumber
|
||||
return allChanges
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ export default abstract class OsmChangeAction {
|
|||
public readonly trackStatistics: boolean;
|
||||
/**
|
||||
* The ID of the object that is the center of this change.
|
||||
* Null if the action creates a new object
|
||||
* Null if the action creates a new object (at initialization)
|
||||
* Undefined if such an id does not make sense
|
||||
*/
|
||||
public readonly mainObjectId: string;
|
||||
|
@ -30,4 +30,11 @@ export default abstract class OsmChangeAction {
|
|||
}
|
||||
|
||||
protected abstract CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]>
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class OsmCreateAction extends OsmChangeAction{
|
||||
|
||||
public newElementId : string
|
||||
public newElementIdNumber: number
|
||||
|
||||
}
|
||||
|
|
|
@ -46,6 +46,9 @@ export class Tag extends TagsFilter {
|
|||
if (shorten) {
|
||||
v = Utils.EllipsesAfter(v, 25);
|
||||
}
|
||||
if(v === "" || v === undefined){
|
||||
return "<span class='line-through'>"+this.key+"</span>"
|
||||
}
|
||||
if (linkToWiki) {
|
||||
return `<a href='https://wiki.openstreetmap.org/wiki/Key:${this.key}' target='_blank'>${this.key}</a>` +
|
||||
`=` +
|
||||
|
|
|
@ -8,7 +8,7 @@ export abstract class TagsFilter {
|
|||
|
||||
abstract matchesProperties(properties: any): boolean;
|
||||
|
||||
abstract asHumanString(linkToWiki: boolean, shorten: boolean, properties: any);
|
||||
abstract asHumanString(linkToWiki: boolean, shorten: boolean, properties: any) : string;
|
||||
|
||||
abstract usedKeys(): string[];
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue