Refactoring of metatagging and extrafunctions to splice out the relation memberships, add calculatedTags and metatags into cache
This commit is contained in:
parent
362abbf079
commit
0dec1d0f75
10 changed files with 98 additions and 54 deletions
|
@ -2,6 +2,7 @@ import {GeoOperations} from "./GeoOperations";
|
||||||
import {UIElement} from "../UI/UIElement";
|
import {UIElement} from "../UI/UIElement";
|
||||||
import Combine from "../UI/Base/Combine";
|
import Combine from "../UI/Base/Combine";
|
||||||
import State from "../State";
|
import State from "../State";
|
||||||
|
import {Relation} from "./Osm/ExtractRelations";
|
||||||
|
|
||||||
export class ExtraFunction {
|
export class ExtraFunction {
|
||||||
|
|
||||||
|
@ -40,11 +41,11 @@ Some advanced functions are available on <b>feat</b> as well:
|
||||||
"overlapWith",
|
"overlapWith",
|
||||||
"Gives a list of features from the specified layer which this feature overlaps with, the amount of overlap in m². The returned value is <b>{ feat: GeoJSONFeature, overlap: number}</b>",
|
"Gives a list of features from the specified layer which this feature overlaps with, the amount of overlap in m². The returned value is <b>{ feat: GeoJSONFeature, overlap: number}</b>",
|
||||||
["...layerIds - one or more layer ids of the layer from which every feature is checked for overlap)"],
|
["...layerIds - one or more layer ids of the layer from which every feature is checked for overlap)"],
|
||||||
(featuresPerLayer, feat) => {
|
(params, feat) => {
|
||||||
return (...layerIds: string[]) => {
|
return (...layerIds: string[]) => {
|
||||||
const result = []
|
const result = []
|
||||||
for (const layerId of layerIds) {
|
for (const layerId of layerIds) {
|
||||||
const otherLayer = featuresPerLayer.get(layerId);
|
const otherLayer = params.featuresPerLayer.get(layerId);
|
||||||
if (otherLayer === undefined) {
|
if (otherLayer === undefined) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -80,10 +81,10 @@ Some advanced functions are available on <b>feat</b> as well:
|
||||||
"closest",
|
"closest",
|
||||||
"Given either a list of geojson features or a single layer name, gives the single object which is nearest to the feature. In the case of ways/polygons, only the centerpoint is considered.",
|
"Given either a list of geojson features or a single layer name, gives the single object which is nearest to the feature. In the case of ways/polygons, only the centerpoint is considered.",
|
||||||
["list of features"],
|
["list of features"],
|
||||||
(featuresPerLayer, feature) => {
|
(params, feature) => {
|
||||||
return (features) => {
|
return (features) => {
|
||||||
if (typeof features === "string") {
|
if (typeof features === "string") {
|
||||||
features = featuresPerLayer.get(features)
|
features = params.featuresPerLayer.get(features)
|
||||||
}
|
}
|
||||||
let closestFeature = undefined;
|
let closestFeature = undefined;
|
||||||
let closestDistance = undefined;
|
let closestDistance = undefined;
|
||||||
|
@ -118,11 +119,8 @@ Some advanced functions are available on <b>feat</b> as well:
|
||||||
"memberships",
|
"memberships",
|
||||||
"Gives a list of {role: string, relation: Relation}-objects, containing all the relations that this feature is part of. \n\nFor example: `_part_of_walking_routes=feat.memberships().map(r => r.relation.tags.name).join(';')`",
|
"Gives a list of {role: string, relation: Relation}-objects, containing all the relations that this feature is part of. \n\nFor example: `_part_of_walking_routes=feat.memberships().map(r => r.relation.tags.name).join(';')`",
|
||||||
[],
|
[],
|
||||||
(featuresPerLayer, feature) => {
|
(params, feature) => {
|
||||||
return () => {
|
return () => params.relations ?? [];
|
||||||
return State.state.knownRelations.data?.get(feature.id) ?? [];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -130,9 +128,9 @@ Some advanced functions are available on <b>feat</b> as well:
|
||||||
private readonly _name: string;
|
private readonly _name: string;
|
||||||
private readonly _args: string[];
|
private readonly _args: string[];
|
||||||
private readonly _doc: string;
|
private readonly _doc: string;
|
||||||
private readonly _f: (featuresPerLayer: Map<string, any[]>, feat: any) => any;
|
private readonly _f: (params: {featuresPerLayer: Map<string, any[]>, relations: {role: string, relation: Relation}[]}, feat: any) => any;
|
||||||
|
|
||||||
constructor(name: string, doc: string, args: string[], f: ((featuresPerLayer: Map<string, any[]>, feat: any) => any)) {
|
constructor(name: string, doc: string, args: string[], f: ((params: {featuresPerLayer: Map<string, any[]>, relations: {role: string, relation: Relation}[]}, feat: any) => any)) {
|
||||||
this._name = name;
|
this._name = name;
|
||||||
this._doc = doc;
|
this._doc = doc;
|
||||||
this._args = args;
|
this._args = args;
|
||||||
|
@ -140,9 +138,9 @@ Some advanced functions are available on <b>feat</b> as well:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FullPatchFeature(featuresPerLayer: Map<string, any[]>, feature) {
|
public static FullPatchFeature(featuresPerLayer: Map<string, any[]>,relations: {role: string, relation: Relation}[], feature) {
|
||||||
for (const func of ExtraFunction.allFuncs) {
|
for (const func of ExtraFunction.allFuncs) {
|
||||||
func.PatchFeature(featuresPerLayer, feature);
|
func.PatchFeature(featuresPerLayer, relations, feature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +166,8 @@ Some advanced functions are available on <b>feat</b> as well:
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PatchFeature(featuresPerLayer: Map<string, any[]>, feature: any) {
|
public PatchFeature(featuresPerLayer: Map<string, any[]>, relations: {role: string, relation: Relation}[], feature: any) {
|
||||||
feature[this._name] = this._f(featuresPerLayer, feature);
|
|
||||||
|
feature[this._name] = this._f({featuresPerLayer: featuresPerLayer, relations: relations}, feature);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,6 +11,10 @@ import LayerConfig from "../../Customizations/JSON/LayerConfig";
|
||||||
export default class FeatureDuplicatorPerLayer implements FeatureSource {
|
export default class FeatureDuplicatorPerLayer implements FeatureSource {
|
||||||
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>;
|
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>;
|
||||||
|
|
||||||
|
|
||||||
|
public static GetMatchingLayerId(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
constructor(layers: UIEventSource<{ layerDef: LayerConfig }[]>, upstream: FeatureSource) {
|
constructor(layers: UIEventSource<{ layerDef: LayerConfig }[]>, upstream: FeatureSource) {
|
||||||
this.features = upstream.features.map(features => {
|
this.features = upstream.features.map(features => {
|
||||||
|
|
|
@ -35,7 +35,7 @@ export default class FeaturePipeline implements FeatureSource {
|
||||||
|
|
||||||
const geojsonSources: FeatureSource [] = GeoJsonSource
|
const geojsonSources: FeatureSource [] = GeoJsonSource
|
||||||
.ConstructMultiSource(flayers.data, locationControl)
|
.ConstructMultiSource(flayers.data, locationControl)
|
||||||
.map(geojsonSource => new RegisteringFeatureSource(new FeatureDuplicatorPerLayer(flayers, geojsonSource)));
|
.map(geojsonSource => new RegisteringFeatureSource(new FeatureDuplicatorPerLayer(flayers, geojsonSource)));
|
||||||
|
|
||||||
const amendedLocalStorageSource =
|
const amendedLocalStorageSource =
|
||||||
new RememberingSource(new RegisteringFeatureSource(new FeatureDuplicatorPerLayer(flayers, new LocalStorageSource(layout))
|
new RememberingSource(new RegisteringFeatureSource(new FeatureDuplicatorPerLayer(flayers, new LocalStorageSource(layout))
|
||||||
|
|
|
@ -3,6 +3,7 @@ import {UIEventSource} from "../UIEventSource";
|
||||||
import State from "../../State";
|
import State from "../../State";
|
||||||
import Hash from "../Web/Hash";
|
import Hash from "../Web/Hash";
|
||||||
import MetaTagging from "../MetaTagging";
|
import MetaTagging from "../MetaTagging";
|
||||||
|
import ExtractRelations from "../Osm/ExtractRelations";
|
||||||
|
|
||||||
export default class MetaTaggingFeatureSource implements FeatureSource {
|
export default class MetaTaggingFeatureSource implements FeatureSource {
|
||||||
features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource<{feature: any; freshness: Date}[]>(undefined);
|
features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource<{feature: any; freshness: Date}[]>(undefined);
|
||||||
|
@ -21,7 +22,7 @@ export default class MetaTaggingFeatureSource implements FeatureSource {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
MetaTagging.addMetatags(featuresFreshness, State.state.layoutToUse.data.layers);
|
MetaTagging.addMetatags(featuresFreshness, State.state.knownRelations.data, State.state.layoutToUse.data.layers);
|
||||||
self.features.setData(featuresFreshness);
|
self.features.setData(featuresFreshness);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
import LayerConfig from "../Customizations/JSON/LayerConfig";
|
import LayerConfig from "../Customizations/JSON/LayerConfig";
|
||||||
import SimpleMetaTagger from "./SimpleMetaTagger";
|
import SimpleMetaTagger from "./SimpleMetaTagger";
|
||||||
import {ExtraFunction} from "./ExtraFunction";
|
import {ExtraFunction} from "./ExtraFunction";
|
||||||
|
import State from "../State";
|
||||||
|
import {Relation} from "./Osm/ExtractRelations";
|
||||||
|
|
||||||
|
|
||||||
|
interface Params {
|
||||||
|
featuresPerLayer: Map<string, any[]>,
|
||||||
|
memberships: Map<string, { role: string, relation: Relation }[]>
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metatagging adds various tags to the elements, e.g. lat, lon, surface area, ...
|
* Metatagging adds various tags to the elements, e.g. lat, lon, surface area, ...
|
||||||
|
@ -14,7 +22,8 @@ export default class MetaTagging {
|
||||||
* An actor which adds metatags on every feature in the given object
|
* An actor which adds metatags on every feature in the given object
|
||||||
* The features are a list of geojson-features, with a "properties"-field and geometry
|
* The features are a list of geojson-features, with a "properties"-field and geometry
|
||||||
*/
|
*/
|
||||||
static addMetatags(features: { feature: any; freshness: Date }[], layers: LayerConfig[]) {
|
static addMetatags(features: { feature: any; freshness: Date }[],
|
||||||
|
relations: Map<string, { role: string, relation: Relation }[]>, layers: LayerConfig[]) {
|
||||||
|
|
||||||
for (const metatag of SimpleMetaTagger.metatags) {
|
for (const metatag of SimpleMetaTagger.metatags) {
|
||||||
try {
|
try {
|
||||||
|
@ -26,7 +35,7 @@ export default class MetaTagging {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The functions - per layer - which add the new keys
|
// The functions - per layer - which add the new keys
|
||||||
const layerFuncs = new Map<string, ((featursPerLayer: Map<string, any[]>, feature: any) => void)>();
|
const layerFuncs = new Map<string, ((params: Params, feature: any) => void)>();
|
||||||
for (const layer of layers) {
|
for (const layer of layers) {
|
||||||
layerFuncs.set(layer.id, this.createRetaggingFunc(layer));
|
layerFuncs.set(layer.id, this.createRetaggingFunc(layer));
|
||||||
}
|
}
|
||||||
|
@ -48,27 +57,26 @@ export default class MetaTagging {
|
||||||
if (f === undefined) {
|
if (f === undefined) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
f({featuresPerLayer: featuresPerLayer, memberships: relations}, feature.feature)
|
||||||
f(featuresPerLayer, feature.feature)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static createRetaggingFunc(layer: LayerConfig): ((featuresPerLayer: Map<string, any[]>, feature: any) => void) {
|
private static createRetaggingFunc(layer: LayerConfig):
|
||||||
|
((params: Params, feature: any) => void) {
|
||||||
const calculatedTags: [string, string][] = layer.calculatedTags;
|
const calculatedTags: [string, string][] = layer.calculatedTags;
|
||||||
if (calculatedTags === undefined) {
|
if (calculatedTags === undefined) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const functions: ((featuresPerLayer: Map<string, any[]>, feature: any) => void)[] = [];
|
const functions: ((params: Params, feature: any) => void)[] = [];
|
||||||
for (const entry of calculatedTags) {
|
for (const entry of calculatedTags) {
|
||||||
const key = entry[0]
|
const key = entry[0]
|
||||||
const code = entry[1];
|
const code = entry[1];
|
||||||
if (code === undefined) {
|
if (code === undefined) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const func = new Function("feat", "return " + code + ";");
|
const func = new Function("feat", "return " + code + ";");
|
||||||
|
|
||||||
const f = (featuresPerLayer, feature: any) => {
|
const f = (featuresPerLayer, feature: any) => {
|
||||||
|
@ -76,16 +84,17 @@ export default class MetaTagging {
|
||||||
}
|
}
|
||||||
functions.push(f)
|
functions.push(f)
|
||||||
}
|
}
|
||||||
return (featuresPerLayer: Map<string, any[]>, feature) => {
|
return (params: Params, feature) => {
|
||||||
const tags = feature.properties
|
const tags = feature.properties
|
||||||
if (tags === undefined) {
|
if (tags === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtraFunction.FullPatchFeature(featuresPerLayer, feature);
|
const relations = params.memberships.get(feature.properties.id)
|
||||||
|
ExtraFunction.FullPatchFeature(params.featuresPerLayer, relations, feature);
|
||||||
try {
|
try {
|
||||||
for (const f of functions) {
|
for (const f of functions) {
|
||||||
f(featuresPerLayer, feature);
|
f(params, feature);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("While calculating a tag value: ", e)
|
console.error("While calculating a tag value: ", e)
|
||||||
|
|
|
@ -17,7 +17,6 @@ export default class ExtractRelations {
|
||||||
|
|
||||||
public static RegisterRelations(overpassJson: any) : void{
|
public static RegisterRelations(overpassJson: any) : void{
|
||||||
const memberships = ExtractRelations.BuildMembershipTable(ExtractRelations.GetRelationElements(overpassJson))
|
const memberships = ExtractRelations.BuildMembershipTable(ExtractRelations.GetRelationElements(overpassJson))
|
||||||
console.log("Assigned memberships: ", memberships)
|
|
||||||
State.state.knownRelations.setData(memberships)
|
State.state.knownRelations.setData(memberships)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +39,7 @@ export default class ExtractRelations {
|
||||||
* @param relations
|
* @param relations
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
private static BuildMembershipTable(relations: Relation[]): Map<string, { role: string, relation: Relation, }[]> {
|
public static BuildMembershipTable(relations: Relation[]): Map<string, { role: string, relation: Relation }[]> {
|
||||||
const memberships = new Map<string, { role: string, relation: Relation }[]>()
|
const memberships = new Map<string, { role: string, relation: Relation }[]>()
|
||||||
|
|
||||||
for (const relation of relations) {
|
for (const relation of relations) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {UIElement} from "../UI/UIElement";
|
||||||
import Combine from "../UI/Base/Combine";
|
import Combine from "../UI/Base/Combine";
|
||||||
import UpdateTagsFromOsmAPI from "./Actors/UpdateTagsFromOsmAPI";
|
import UpdateTagsFromOsmAPI from "./Actors/UpdateTagsFromOsmAPI";
|
||||||
|
|
||||||
|
|
||||||
export default class SimpleMetaTagger {
|
export default class SimpleMetaTagger {
|
||||||
public readonly keys: string[];
|
public readonly keys: string[];
|
||||||
public readonly doc: string;
|
public readonly doc: string;
|
||||||
|
@ -89,7 +90,12 @@ export default class SimpleMetaTagger {
|
||||||
["_isOpen", "_isOpen:description"],
|
["_isOpen", "_isOpen:description"],
|
||||||
"If 'opening_hours' is present, it will add the current state of the feature (being 'yes' or 'no')",
|
"If 'opening_hours' is present, it will add the current state of the feature (being 'yes' or 'no')",
|
||||||
(feature => {
|
(feature => {
|
||||||
|
if(Utils.runningFromConsole){
|
||||||
|
// We are running from console, thus probably creating a cache
|
||||||
|
// isOpen is irrelevant
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const tagsSource = State.state.allElements.getEventSourceById(feature.properties.id);
|
const tagsSource = State.state.allElements.getEventSourceById(feature.properties.id);
|
||||||
tagsSource.addCallbackAndRun(tags => {
|
tagsSource.addCallbackAndRun(tags => {
|
||||||
if (tags.opening_hours === undefined || tags._country === undefined) {
|
if (tags.opening_hours === undefined || tags._country === undefined) {
|
||||||
|
@ -317,7 +323,7 @@ export default class SimpleMetaTagger {
|
||||||
];
|
];
|
||||||
|
|
||||||
static GetCountryCodeFor(lon: number, lat: number, callback: (country: string) => void) {
|
static GetCountryCodeFor(lon: number, lat: number, callback: (country: string) => void) {
|
||||||
SimpleMetaTagger.coder.GetCountryCodeFor(lon, lat, callback)
|
SimpleMetaTagger.coder?.GetCountryCodeFor(lon, lat, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
static HelpText(): UIElement {
|
static HelpText(): UIElement {
|
||||||
|
|
|
@ -159,32 +159,34 @@
|
||||||
"width": {
|
"width": {
|
||||||
"render": "4"
|
"render": "4"
|
||||||
},
|
},
|
||||||
"dashArray": "2 10 6 10",
|
"dashArray": {
|
||||||
"color": {
|
"render": "",
|
||||||
"render": "#bb2",
|
|
||||||
"mappings": [
|
"mappings": [
|
||||||
{
|
{
|
||||||
"if": "highway=cycleway",
|
"if": "highway=cycleway",
|
||||||
"then": "#00c"
|
"then": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"if": "highway=path",
|
"if": "highway=path",
|
||||||
"then": "#bb2"
|
"then": "10 3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"if": "highway=footway",
|
"if": "highway=footway",
|
||||||
"then": "#c30"
|
"then": "10 10"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"if": "highway=pedestrian",
|
"if": "highway=pedestrian",
|
||||||
"then": "#3c3"
|
"then": "10 10"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"if": "highway=living_street",
|
"if": "highway=living_street",
|
||||||
"then": "#ccc"
|
"then": "10 5 3 5"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"color": {
|
||||||
|
"render": "#eaba2a"
|
||||||
|
},
|
||||||
"presets": [
|
"presets": [
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
"generate:translations": "ts-node scripts/generateTranslations.ts",
|
"generate:translations": "ts-node scripts/generateTranslations.ts",
|
||||||
"generate:layouts": "ts-node scripts/generateLayouts.ts",
|
"generate:layouts": "ts-node scripts/generateLayouts.ts",
|
||||||
"generate:docs": "ts-node scripts/generateDocs.ts && ts-node scripts/generateTaginfoProjectFiles.ts",
|
"generate:docs": "ts-node scripts/generateDocs.ts && ts-node scripts/generateTaginfoProjectFiles.ts",
|
||||||
"generate:cache:speelplekken": "ts-node scripts/generateCache.ts speelplekken 14 ./cache/speelplekken 51.2003 4.3925 51.1058 4.5087",
|
"generate:cache:speelplekken": "ts-node scripts/generateCache.ts speelplekken 14 ../pietervdvn.github.io/speelplekken_cache/ 51.20 4.37 51.11 4.51",
|
||||||
"generate:layeroverview": "ts-node scripts/generateLayerOverview.ts --no-fail",
|
"generate:layeroverview": "ts-node scripts/generateLayerOverview.ts --no-fail",
|
||||||
"generate:licenses": "ts-node scripts/generateLicenseInfo.ts --no-fail",
|
"generate:licenses": "ts-node scripts/generateLicenseInfo.ts --no-fail",
|
||||||
"validate:layeroverview": "ts-node scripts/generateLayerOverview.ts --report",
|
"validate:layeroverview": "ts-node scripts/generateLayerOverview.ts --report",
|
||||||
|
|
|
@ -14,6 +14,8 @@ import ScriptUtils from "./ScriptUtils";
|
||||||
import ExtractRelations from "../Logic/Osm/ExtractRelations";
|
import ExtractRelations from "../Logic/Osm/ExtractRelations";
|
||||||
import * as OsmToGeoJson from "osmtogeojson";
|
import * as OsmToGeoJson from "osmtogeojson";
|
||||||
import {Script} from "vm";
|
import {Script} from "vm";
|
||||||
|
import MetaTagging from "../Logic/MetaTagging";
|
||||||
|
import State from "../State";
|
||||||
|
|
||||||
function createOverpassObject(theme: LayoutConfig) {
|
function createOverpassObject(theme: LayoutConfig) {
|
||||||
let filters: TagsFilter[] = [];
|
let filters: TagsFilter[] = [];
|
||||||
|
@ -26,8 +28,8 @@ function createOverpassObject(theme: LayoutConfig) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (layer.source.geojsonSource !== undefined) {
|
if (layer.source.geojsonSource !== undefined) {
|
||||||
// Not our responsibility to download this layer!
|
// We download these anyway - we are building the cache after all!
|
||||||
continue;
|
//continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,17 +70,17 @@ function metaJsonName(targetDir: string, x: number, y: number, z: number): strin
|
||||||
return targetDir + "_" + z + "_" + x + "_" + y + ".meta.json"
|
return targetDir + "_" + z + "_" + x + "_" + y + ".meta.json"
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadRaw(targetdir: string, r: TileRange, overpass: Overpass) {
|
async function downloadRaw(targetdir: string, r: TileRange, overpass: Overpass) {
|
||||||
let downloaded = 0
|
let downloaded = 0
|
||||||
for (let x = r.xstart; x <= r.xend; x++) {
|
for (let x = r.xstart; x <= r.xend; x++) {
|
||||||
for (let y = r.ystart; y <= r.yend; y++) {
|
for (let y = r.ystart; y <= r.yend; y++) {
|
||||||
console.log("x:", (x - r.xstart), "/", (r.xend - r.xstart), "; y:", (y - r.ystart), "/", (r.yend - r.ystart), "; total: ", downloaded, "/", r.total)
|
|
||||||
downloaded++;
|
downloaded++;
|
||||||
const filename = rawJsonName(targetdir, x, y, r.zoomlevel)
|
const filename = rawJsonName(targetdir, x, y, r.zoomlevel)
|
||||||
if (existsSync(filename)) {
|
if (existsSync(filename)) {
|
||||||
console.log("Already exists: ", filename)
|
console.log("Already exists: ", filename)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
console.log("x:", (x - r.xstart), "/", (r.xend - r.xstart), "; y:", (y - r.ystart), "/", (r.yend - r.ystart), "; total: ", downloaded, "/", r.total)
|
||||||
|
|
||||||
const boundsArr = Utils.tile_bounds(r.zoomlevel, x, y)
|
const boundsArr = Utils.tile_bounds(r.zoomlevel, x, y)
|
||||||
const bounds = {
|
const bounds = {
|
||||||
|
@ -87,28 +89,35 @@ async function downloadRaw(targetdir: string, r: TileRange, overpass: Overpass)
|
||||||
east: Math.max(boundsArr[0][1], boundsArr[1][1]),
|
east: Math.max(boundsArr[0][1], boundsArr[1][1]),
|
||||||
west: Math.min(boundsArr[0][1], boundsArr[1][1])
|
west: Math.min(boundsArr[0][1], boundsArr[1][1])
|
||||||
}
|
}
|
||||||
console.log("Downloading tile", r.zoomlevel, x, y, "with bounds", bounds)
|
|
||||||
const url = overpass.buildQuery("[bbox:" + bounds.south + "," + bounds.west + "," + bounds.north + "," + bounds.east + "]")
|
const url = overpass.buildQuery("[bbox:" + bounds.south + "," + bounds.west + "," + bounds.north + "," + bounds.east + "]")
|
||||||
|
|
||||||
|
let gotResponse = false
|
||||||
ScriptUtils.DownloadJSON(url,
|
ScriptUtils.DownloadJSON(url,
|
||||||
chunks => {
|
chunks => {
|
||||||
|
gotResponse = true;
|
||||||
saveResponse(chunks, filename)
|
saveResponse(chunks, filename)
|
||||||
})
|
})
|
||||||
|
|
||||||
await ScriptUtils.sleep(10000)
|
while (!gotResponse) {
|
||||||
console.debug("Waking up")
|
await ScriptUtils.sleep(10000)
|
||||||
|
console.debug("Waking up")
|
||||||
|
if (!gotResponse) {
|
||||||
|
console.log("Didn't get an answer yet - waiting more")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function postProcess(targetdir: string, r: TileRange) {
|
async function postProcess(targetdir: string, r: TileRange, theme: LayoutConfig) {
|
||||||
let processed = 0;
|
let processed = 0;
|
||||||
for (let x = r.xstart; x <= r.xend; x++) {
|
for (let x = r.xstart; x <= r.xend; x++) {
|
||||||
for (let y = r.ystart; y <= r.yend; y++) {
|
for (let y = r.ystart; y <= r.yend; y++) {
|
||||||
processed++;
|
processed++;
|
||||||
const filename = rawJsonName(targetdir, x, y, r.zoomlevel)
|
const filename = rawJsonName(targetdir, x, y, r.zoomlevel)
|
||||||
console.log(" Post processing", processed, "/",r. total, filename)
|
console.log(" Post processing", processed, "/", r.total, filename)
|
||||||
if (!existsSync(filename)) {
|
if (!existsSync(filename)) {
|
||||||
throw "Not found - and not downloaded. Run this script again!: " + filename
|
throw "Not found - and not downloaded. Run this script again!: " + filename
|
||||||
}
|
}
|
||||||
|
@ -118,11 +127,26 @@ async function postProcess(targetdir: string, r: TileRange) {
|
||||||
|
|
||||||
// Create and save the geojson file - which is the main chunk of the data
|
// Create and save the geojson file - which is the main chunk of the data
|
||||||
const geojson = OsmToGeoJson.default(rawOsm);
|
const geojson = OsmToGeoJson.default(rawOsm);
|
||||||
|
const osmTime = new Date(rawOsm.osm3s.timestamp_osm_base);
|
||||||
|
|
||||||
|
for (const feature of geojson.features) {
|
||||||
|
|
||||||
|
for (const layer of theme.layers) {
|
||||||
|
if (layer.source.osmTags.matchesProperties(feature.properties)) {
|
||||||
|
feature["_matching_layer_id"] = layer.id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const featuresFreshness = geojson.features.map(feature => ({
|
||||||
|
freshness: osmTime,
|
||||||
|
feature: feature
|
||||||
|
}));
|
||||||
|
// Extract the relationship information
|
||||||
|
const relations = ExtractRelations.BuildMembershipTable(ExtractRelations.GetRelationElements(rawOsm))
|
||||||
|
MetaTagging.addMetatags(featuresFreshness, relations, theme.layers);
|
||||||
writeFileSync(geoJsonName(targetdir, x, y, r.zoomlevel), JSON.stringify(geojson))
|
writeFileSync(geoJsonName(targetdir, x, y, r.zoomlevel), JSON.stringify(geojson))
|
||||||
|
|
||||||
// Extract the relationship information
|
|
||||||
const relations = ExtractRelations.GetRelationElements(rawOsm)
|
|
||||||
const osmTime = new Date(rawOsm.osm3s.timestamp_osm_base);
|
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
freshness: osmTime,
|
freshness: osmTime,
|
||||||
|
@ -145,7 +169,7 @@ async function main(args: string[]) {
|
||||||
}
|
}
|
||||||
const themeName = args[0]
|
const themeName = args[0]
|
||||||
const zoomlevel = Number(args[1])
|
const zoomlevel = Number(args[1])
|
||||||
const targetdir = args[2]
|
const targetdir = args[2] + "/" + themeName
|
||||||
const lat0 = Number(args[3])
|
const lat0 = Number(args[3])
|
||||||
const lon0 = Number(args[4])
|
const lon0 = Number(args[4])
|
||||||
const lat1 = Number(args[5])
|
const lat1 = Number(args[5])
|
||||||
|
@ -167,7 +191,7 @@ async function main(args: string[]) {
|
||||||
|
|
||||||
|
|
||||||
await downloadRaw(targetdir, tileRange, overpass)
|
await downloadRaw(targetdir, tileRange, overpass)
|
||||||
await postProcess(targetdir, tileRange)
|
await postProcess(targetdir, tileRange, theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue