First draft of loading 'notes'

This commit is contained in:
pietervdvn 2022-01-07 04:14:53 +01:00
parent bafaba7011
commit ebb510da04
20 changed files with 580 additions and 199 deletions

View file

@ -93,7 +93,7 @@ export default class GeoJsonSource implements FeatureSourceForLayer, Tiled {
for (const key in props) {
if (typeof props[key] !== "string") {
// Make sure all the values are string, it crashes stuff otherwise
props[key] = "" + props[key]
props[key] = JSON.stringify(props[key])
}
}

View file

@ -104,8 +104,8 @@ export default class MetaTagging {
}
return atLeastOneFeatureChanged
}
public static createFunctionsForFeature(layerId: string, calculatedTags: [string, string, boolean][]): ((feature: any) => boolean)[] {
const functions: ((feature: any) => boolean)[] = [];
public static createFunctionsForFeature(layerId: string, calculatedTags: [string, string, boolean][]): ((feature: any) => void)[] {
const functions: ((feature: any) => any)[] = [];
for (const entry of calculatedTags) {
const key = entry[0]
@ -115,9 +115,8 @@ export default class MetaTagging {
continue;
}
const calculateAndAssign: ((feat: any) => boolean) = (feat) => {
const calculateAndAssign: ((feat: any) => any) = (feat) => {
try {
let oldValue = isStrict ? feat.properties[key] : undefined
let result = new Function("feat", "return " + code + ";")(feat);
if (result === "") {
result === undefined
@ -128,7 +127,7 @@ export default class MetaTagging {
}
delete feat.properties[key]
feat.properties[key] = result;
return result === oldValue;
return result
}catch(e){
if (MetaTagging.errorPrintCount < MetaTagging.stopErrorOutputAt) {
console.warn("Could not calculate a " + (isStrict ? "strict " : "") + " calculated tag for key " + key + " defined by " + code + " (in layer" + layerId + ") due to \n" + e + "\n. Are you the theme creator? Doublecheck your code. Note that the metatags might not be stable on new features", e, e.stack)
@ -137,7 +136,7 @@ export default class MetaTagging {
console.error("Got ", MetaTagging.stopErrorOutputAt, " errors calculating this metatagging - stopping output now")
}
}
return false;
return undefined;
}
}
@ -154,11 +153,10 @@ export default class MetaTagging {
configurable: true,
enumerable: false, // By setting this as not enumerable, the localTileSaver will _not_ calculate this
get: function () {
calculateAndAssign(feature)
return feature.properties[key]
return calculateAndAssign(feature)
}
})
return true
return undefined
}
@ -167,7 +165,7 @@ export default class MetaTagging {
return functions;
}
private static retaggingFuncCache = new Map<string, ((feature: any) => boolean)[]>()
private static retaggingFuncCache = new Map<string, ((feature: any) => void)[]>()
/**
* Creates the function which adds all the calculated tags to a feature. Called once per layer
@ -183,7 +181,7 @@ export default class MetaTagging {
return undefined;
}
let functions :((feature: any) => boolean)[] = MetaTagging.retaggingFuncCache.get(layer.id);
let functions :((feature: any) => void)[] = MetaTagging.retaggingFuncCache.get(layer.id);
if (functions === undefined) {
functions = MetaTagging.createFunctionsForFeature(layer.id, calculatedTags)
MetaTagging.retaggingFuncCache.set(layer.id, functions)

View file

@ -218,6 +218,24 @@ export class OsmConnection {
});
}
public closeNote(id: number | string): Promise<any> {
return new Promise((ok, error) => {
this.auth.xhr({
method: 'POST',
path: `/api/0.6/notes/${id}/close`
}, function (err, response) {
console.log("Closing note gave:", err, response)
if (err !== null) {
error(err)
} else {
ok()
}
})
})
}
private updateAuthObject() {
let pwaStandAloneMode = false;
try {
@ -260,6 +278,4 @@ export class OsmConnection {
});
}
}

View file

@ -16,7 +16,7 @@ export class Tiles {
const result: T[] = []
const total = tileRange.total
if (total > 100000) {
throw "Tilerange too big"
throw "Tilerange too big (z is "+tileRange.zoomlevel+")"
}
for (let x = tileRange.xstart; x <= tileRange.xend; x++) {
for (let y = tileRange.ystart; y <= tileRange.yend; y++) {

View file

@ -43,7 +43,7 @@ export default class UserBadge extends Toggle {
if (home === undefined) {
return;
}
state.leafletMap.data.setView([home.lat, home.lon], 16);
state.leafletMap.data?.setView([home.lat, home.lon], 16);
});
const linkStyle = "flex items-baseline"

View file

@ -298,12 +298,16 @@ export class OH {
}
}
static Parse(rules: string) {
public static simplify(str: string): string{
return OH.ToString(OH.MergeTimes(OH.Parse(str)))
}
public static Parse(rules: string) : OpeningHour[] {
if (rules === undefined || rules === "") {
return []
}
const ohs = []
const ohs : OpeningHour[] = []
const split = rules.split(";");

View file

@ -44,7 +44,7 @@ export default class FeatureInfoBox extends ScrollableFullScreen {
.SetClass("break-words font-bold sm:p-0.5 md:p-1 sm:p-1.5 md:p-2");
const titleIcons = new Combine(
layerConfig.titleIcons.map(icon => new TagRenderingAnswer(tags, icon,
"block w-8 h-8 align-baseline box-content sm:p-0.5", "width: 2rem;")
"block w-8 h-8 max-h-8 align-baseline box-content sm:p-0.5", "width: 2rem;")
))
.SetClass("flex flex-row flex-wrap pt-0.5 sm:pt-1 items-center mr-2")
@ -193,9 +193,9 @@ export default class FeatureInfoBox extends ScrollableFullScreen {
const config_download: TagRenderingConfig = new TagRenderingConfig({render: "{export_as_geojson()}"}, "");
const config_id: TagRenderingConfig = new TagRenderingConfig({render: "{open_in_iD()}"}, "");
return new Combine([new TagRenderingAnswer(tags, config_all_tags, "all_tags"),
new TagRenderingAnswer(tags, config_download, ""),
new TagRenderingAnswer(tags, config_id, "")])
return new Combine([new TagRenderingAnswer(tags, config_all_tags, State.state),
new TagRenderingAnswer(tags, config_download, State.state),
new TagRenderingAnswer(tags, config_id, State.state)])
}
})
)

View file

@ -38,6 +38,7 @@ import TagApplyButton from "./Popup/TagApplyButton";
import AutoApplyButton from "./Popup/AutoApplyButton";
import * as left_right_style_json from "../assets/layers/left_right_style/left_right_style.json";
import {OpenIdEditor} from "./BigComponents/CopyrightPanel";
import Toggle from "./Input/Toggle";
export interface SpecialVisualization {
funcName: string,
@ -607,6 +608,39 @@ export default class SpecialVisualizations {
Hash.hash.setData(undefined)
})
}
},
{
funcName: "close_note",
docs: "Button to close a note",
args:[
{
name:"text",
doc: "Text to show on this button",
},
{
name:"Id-key",
doc: "The property name where the ID of the note to close can be found",
defaultValue: "id"
}
],
constr: (state, tags, args, guiState) => {
const t = Translations.t.notes;
const closeButton = new SubtleButton( Svg.checkmark_svg(), t.closeNote)
const isClosed = new UIEventSource(false);
closeButton.onClick(() => {
const id = tags.data[args[1] ?? "id"]
if(state.featureSwitchIsTesting.data){
console.log("Not actually closing note...")
return;
}
state.osmConnection.closeNote(id).then(_ => isClosed.setData(true))
})
return new Toggle(
t.isClosed.SetClass("thanks"),
closeButton,
isClosed
)
}
}
]

View file

@ -0,0 +1,18 @@
[
{
"path": "note.svg",
"license": "CC0",
"authors": [
"Pieter Vander Vennet"
],
"sources": []
},
{
"path": "resolved.svg",
"license": "CC0",
"authors": [
"Pieter Vander Vennet"
],
"sources": []
}
]

View file

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="275px"
height="374px"
viewBox="0 0 275 374"
version="1.1"
id="svg7"
sodipodi:docname="teardrop.svg"
inkscape:version="1.1.1 (1:1.1+202109281949+c3084ef5ed)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs11" />
<sodipodi:namedview
id="namedview9"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-global="false"
inkscape:zoom="1.8073494"
inkscape:cx="80.227983"
inkscape:cy="144.13372"
inkscape:current-layer="svg7">
<sodipodi:guide
position="137.32093,125.42369"
orientation="1,0"
id="guide2177" />
</sodipodi:namedview>
<path
id="path2"
style="fill:#c60000;fill-opacity:1;fill-rule:nonzero;stroke:#950000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 135.55664 1.9765625 C 74.593645 2.1922681 20.084472 43.910648 7.2773438 104.37109 C 4.936895 115.41704 4.1435422 126.42334 4.7265625 137.18555 C 2.5821353 205.89923 56.815085 269.30423 107.08203 335.96094 C 119.40234 351.22656 136.60547 368.02734 137.43359 370.03516 L 165.07812 337.42188 C 227.98632 255.40992 319.84389 135.74148 238.04492 49.080078 C 219.42005 26.853995 193.07863 10.556457 161.97656 4.4921875 C 153.10693 2.7626953 144.26564 1.9457474 135.55664 1.9765625 z " />
<path
id="path5936"
style="color:#000000;fill:#fffffd;stroke:#000000;stroke-width:5;stroke-linecap:round;stroke-opacity:1;fill-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
d="m 202.54602,49.933374 a 19.846225,19.846225 0 0 0 -14.03347,5.812789 L 137.36365,106.89506 86.838795,56.370195 a 19.845967,19.845967 0 0 0 -14.033473,-5.812787 19.845967,19.845967 0 0 0 -14.033471,5.812787 19.845967,19.845967 0 0 0 0,28.066944 l 50.524859,50.524871 -50.328371,50.32837 a 19.846225,19.846225 0 0 0 0,28.06695 19.846225,19.846225 0 0 0 28.066944,0 l 50.328367,-50.32838 50.95423,50.95424 a 19.845967,19.845967 0 0 0 28.06694,0 19.845967,19.845967 0 0 0 0,-28.06695 L 165.4306,134.96201 216.57949,83.813106 a 19.846225,19.846225 0 0 0 0,-28.066943 19.846225,19.846225 0 0 0 -14.03347,-5.812789 z" />
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,93 @@
{
"id": "notes",
"language": [
"en"
],
"maintainer": "MapComplete",
"startLat": 0,
"startLon": 0,
"startZoom": 0,
"title": "Notes on OpenStreetMap",
"version": "0.1",
"description": "Notes from OpenStreetMap",
"icon": "./assets/themes/notes/resolved.svg",
"clustering": false,
"layers": [
{
"id": "notes",
"name": {
"en": "OpenStreetMap notes"
},
"description": "Notes on OpenStreetMap.org",
"source": {
"osmTags": "id~*",
"geoJson": "https://api.openstreetmap.org/api/0.6/notes.json?closed=7&bbox={x_min},{y_min},{x_max},{y_max}",
"geoJsonZoomLevel": 12,
"maxCacheAge": 0
},
"minzoom": 10,
"title": {
"render": {
"en": "Note"
},
"mappings": [{
"if": "closed_at~*",
"then": {
"en": "Closed note"
}
}]
},
"calculatedTags": [
"_first_comment:=feat.get('comments')[0].text",
"_conversation=feat.get('comments').map(c => {if(c.user_url == undefined) {return 'anonymous user, '+c.date;} return c.html+'<div class=\"subtle flex justify-end border-b border-gray-500\"><a href=\"'+c.user_url+'\" target=\"_blank\">'+c.user+'</a> &nbsp;'+c.date+'</div>'}).join('')"
],
"titleIcons": [{
"render": "<a href='https://openstreetmap.org/note/{id}' target='_blank'><img src='./assets/svg/osm-logo-us.svg'></a>"
}],
"tagRenderings": [
{
"id": "conversation",
"render": "{_conversation}"
},
{
"id": "date_created",
"render": {
"en": "Opened on {date_created}"
}
},
{
"id": "close",
"render": "{close_note()}",
"condition": "closed_at="
}
],
"mapRendering": [
{
"location": [
"point",
"centroid"
],
"icon": {
"render": "./assets/themes/notes/note.svg",
"mappings": [
{
"if": "closed_at~*",
"then": "./assets/themes/notes/resolved.svg"
}
]
},
"iconSize": "40,40,bottom"
}
],
"filter": [{
"id": "bookcases",
"options": [
{
"osmTags": "_first_comment~.*bookcase.*",
"question": "Should mention 'bookcase' in the first comment"
}]
}]
}
]
}

View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="275px"
height="374px"
viewBox="0 0 275 374"
version="1.1"
id="svg7"
sodipodi:docname="resolved.svg"
inkscape:version="1.1.1 (1:1.1+202109281949+c3084ef5ed)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs11" />
<sodipodi:namedview
id="namedview9"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-global="false"
inkscape:zoom="2.2793262"
inkscape:cx="68.44128"
inkscape:cy="162.54804"
inkscape:current-layer="svg7">
<sodipodi:guide
position="137.32093,125.42369"
orientation="1,0"
id="guide2177" />
</sodipodi:namedview>
<path
id="path2"
style="fill:#00c82e;fill-opacity:1;fill-rule:nonzero;stroke:#40ff00;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 135.55664 1.9765625 C 74.593645 2.1922681 20.084472 43.910648 7.2773438 104.37109 C 4.936895 115.41704 4.1435422 126.42334 4.7265625 137.18555 C 2.5821353 205.89923 56.815085 269.30423 107.08203 335.96094 C 119.40234 351.22656 136.60547 368.02734 137.43359 370.03516 L 165.07812 337.42188 C 227.98632 255.40992 319.84389 135.74148 238.04492 49.080078 C 219.42005 26.853995 193.07863 10.556457 161.97656 4.4921875 C 153.10693 2.7626953 144.26564 1.9457474 135.55664 1.9765625 z " />
<path
style="color:#000000;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3.52437;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 216.35763,81.457377 c -6.31364,-1.014444 -12.65279,1.657101 -16.62944,7.00824 L 117.3564,199.32492 69.393978,152.33285 c -7.532586,-9.1813 -20.4662,-9.07329 -27.311559,-1.91781 -7.087039,7.56459 -8.507731,17.24412 -0.648456,25.76692 l 61.942427,65.80658 c 7.15464,9.62634 20.80539,9.62634 27.96003,0 l 96.3518,-129.67383 c 6.14683,-8.27231 4.87072,-20.317183 -2.85026,-26.902908 -2.45389,-2.092661 -5.37864,-3.456485 -8.48033,-3.954425 z"
id="path3639"
sodipodi:nodetypes="ccccccccccc" />
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -716,18 +716,6 @@ video {
left: 0px;
}
.bottom-3 {
bottom: 0.75rem;
}
.left-3 {
left: 0.75rem;
}
.right-2 {
right: 0.5rem;
}
.left-24 {
left: 6rem;
}
@ -740,6 +728,18 @@ video {
top: 14rem;
}
.bottom-3 {
bottom: 0.75rem;
}
.left-3 {
left: 0.75rem;
}
.right-2 {
right: 0.5rem;
}
.top-2 {
top: 0.5rem;
}
@ -800,10 +800,6 @@ video {
margin: 2rem;
}
.m-11 {
margin: 2.75rem;
}
.m-1 {
margin: 0.25rem;
}
@ -812,6 +808,10 @@ video {
margin: 1.25rem;
}
.m-4 {
margin: 1rem;
}
.m-0\.5 {
margin: 0.125rem;
}
@ -824,10 +824,6 @@ video {
margin: 0.75rem;
}
.m-4 {
margin: 1rem;
}
.m-2 {
margin: 0.5rem;
}
@ -1080,6 +1076,10 @@ video {
width: 2.75rem;
}
.w-6 {
width: 1.5rem;
}
.w-16 {
width: 4rem;
}
@ -1090,10 +1090,6 @@ video {
width: min-content;
}
.w-6 {
width: 1.5rem;
}
.w-max {
width: -webkit-max-content;
width: -moz-max-content;
@ -1565,6 +1561,10 @@ video {
text-transform: lowercase;
}
.capitalize {
text-transform: capitalize;
}
.italic {
font-style: italic;
}

View file

@ -62,5 +62,9 @@
"sizes": "513x513",
"type": "image/svg"
}
],
"categories": [
"map",
"navigation"
]
}

View file

@ -422,5 +422,10 @@
}
}
}
},
"notes": {
"isClosed": "This note is resolved",
"closeNote":
"Close this note"
}
}

View file

@ -944,6 +944,18 @@
"shortDescription": "This map shows the nature reserves of Natuurpunt",
"title": "The map of Natuurpunt"
},
"notes": {
"layers": {
"0": {
"name": "OpenStreetMap notes",
"tagRenderings": {
"date_created": {
"render": "Opened on {date_created}"
}
}
}
}
},
"observation_towers": {
"description": "Publicly accessible towers to enjoy the view",
"shortDescription": "Publicly accessible towers to enjoy the view",

View file

@ -42,7 +42,8 @@
"gittag": "ts-node scripts/printVersion.ts | bash",
"lint": "tslint --project . -c tslint.json '**.ts' ",
"clean": "rm -rf .cache/ && (find *.html | grep -v \"\\(404\\|index\\|land\\|test\\|preferences\\|customGenerator\\|professional\\|automaton\\|theme\\).html\" | xargs rm) && (ls | grep \"^index_[a-zA-Z_]\\+\\.ts$\" | xargs rm) && (ls | grep \".*.webmanifest$\" | xargs rm)",
"generate:dependency-graph": "node_modules/.bin/depcruise --exclude \"^node_modules\" --output-type dot Logic/State/MapState.ts > dependencies.dot && dot dependencies.dot -T svg -o dependencies.svg && rm dependencies.dot"
"generate:dependency-graph": "node_modules/.bin/depcruise --exclude \"^node_modules\" --output-type dot Logic/State/MapState.ts > dependencies.dot && dot dependencies.dot -T svg -o dependencies.svg && rm dependencies.dot",
"bicycle_rental": "ts-node ./scripts/extractBikeRental.ts"
},
"keywords": [
"OpenStreetMap",

View file

@ -0,0 +1,211 @@
import * as fs from "fs";
import {OH} from "../UI/OpeningHours/OpeningHours";
function extractValue(vs: { __value }[]) {
if(vs === undefined){
return undefined
}
for (const v of vs) {
if ((v.__value ?? "") === "") {
continue
}
return v.__value;
}
return undefined
}
function extract_oh_block (days) : string{
const oh = []
for (const day of days.day) {
const abbr = day.name.substr(0,2)
const block = day.time_block[0]
const from = block.time_from.substr(0,5)
const to = block.time_until.substr(0,5)
const by_appointment = block.by_appointment ? " \"by appointment\"" : ""
oh.push(`${abbr} ${from}-${to}${by_appointment}`)
}
return oh.join("; ")
}
function extract_oh(opening_periods){
const rules = []
if(opening_periods === undefined){
return undefined;
}
for (const openingPeriod of opening_periods.opening_period ?? []) {
let rule = extract_oh_block(openingPeriod.days)
if(openingPeriod.name.toLowerCase().indexOf("schoolvakantie") >= 0){
rule = "SH "+rule
}
rules.push(rule)
}
return OH.simplify( rules.join(";"))
}
function rewrite(obj, key) {
if (obj[key] === undefined) {
return
}
obj[key] = extractValue(obj[key]["value"])
}
const stuff = fs.readFileSync("/home/pietervdvn/Documents/Freelance/ToerismeVlaanderen 2021-09/TeImporteren/allchannels-bike_rental.json", "UTF8")
const data: any[] = JSON.parse(stuff)
const results: {
geometry: {
type: "Point",
coordinates: [number, number]
},
type: "Feature",
properties: any
}[] = []
const skipped = []
console.log("[")
for (const item of data) {
const metadata = item["metadata"]
if (metadata.name === "Jommekeroute") {
continue
}
const addr = item.location_info?.address
if (addr === undefined) {
skipped.push(item)
continue
}
const toDelete = ["id", "uuid", "update_date", "creation_date",
"deleted",
"aborted",
"partner_id",
"business_product_id",
"winref",
"winref_uuid",
"root_product_type",
"parent"
]
for (const key of toDelete) {
delete metadata[key]
}
delete item["meeting_rooms_count"]
delete item["facilities"]
item.properties = metadata
delete item["metadata"]
const metadata_values = ["touristic_product_type", "root_product_type"]
for (const key of metadata_values) {
rewrite(metadata, key)
}
rewrite(item.contact_info, "commercial_name")
const gl = addr.geolocation
item.coordinates = [gl.lon, gl.lat]
metadata["addr:street"] = addr.street
metadata["addr:housenumber"] = addr.number
metadata["phone"] = item.contact_info["telephone"] ?? item.contact_info["mobile"]
metadata["email"] = item.contact_info["email_address"]
const links = item.links?.link?.map(l => l.url) ?? []
metadata["website"] = item.contact_info["website"] ?? links[0]
delete item["links"]
delete item.location_info
delete item.contact_info
delete item.promotional_info
if (metadata["touristic_product_type"] === "Fietsverhuur") {
metadata["amenity"] = "bicycle_rental"
delete metadata["touristic_product_type"]
} else {
console.error("Unkown product type: ", metadata["touristic_product_type"])
}
const descriptions = item.descriptions?.description?.map(d => extractValue(d?.text?.value)) ?? []
delete item.descriptions
metadata["description"] = metadata["description"] ?? descriptions[0]
if (item.price_info?.prices?.free == true) {
metadata.fee = "no"
delete item.price_info
} else if (item.price_info?.prices?.free == false) {
metadata.fee = "yes"
metadata.charge = extractValue(item.price_info?.extra_information?.value)
const methods = item.price_info?.payment_methods?.payment_method
if(methods !== undefined){
methods.map(v => extractValue(v.value)).forEach(method => {
metadata["payment:" + method.toLowerCase()] = "yes"
})
}
delete item.price_info
}else if(item.price_info?.prices?.length === 0){
delete item.price_info
}
try{
if(item.labels_info?.labels_own?.label[0]?.code === "Billenkar"){
metadata.rental = "quadricycle"
delete item.labels_info
}
}catch(e){
}
delete item["publishing_channels"]
try {
metadata["image"] = item.media.file[0].url[0]
} catch (e) {
// No image!
}
delete item.media
const time_info = item.time_info?.time_info_regular
if(time_info?.permantly_open === true){
metadata.opening_hours = "24/7"
}else{
metadata.opening_hours = extract_oh(time_info?.opening_periods)
}
delete item.time_info
const properties = {}
for (const key in metadata) {
const v = metadata[key]
if(v === null || v === undefined || v === ""){
delete metadata[key]
continue
}
properties[key] = v
}
results.push({
geometry: {
type: "Point",
coordinates: item.coordinates
},
type: "Feature",
properties
})
delete item.coordinates
delete item.properties
console.log(JSON.stringify(item, null, " ") + ",")
}
console.log("]")
fs.writeFileSync("west-vlaanderen.geojson", JSON.stringify(
{
type: "FeatureCollection",
features: results
}
, null, " "
))

45
scripts/perProperty.ts Normal file
View file

@ -0,0 +1,45 @@
import * as fs from "fs";
function main(args){
if(args.length < 2){
console.log("Given a single geojson file, generates the partitions for every found property")
console.log("USAGE: perProperty `file.geojson` `property-key`")
return
}
const path = args[0]
const key = args[1]
const data= JSON.parse(fs.readFileSync(path, "UTF8"))
const perProperty = new Map<string, any[]>()
console.log("Partitioning",data.features.length, "features")
for (const feature of data.features) {
const v = feature.properties[key]
if(!perProperty.has(v)){
console.log("Found a new category:", v)
perProperty.set(v, [])
}
perProperty.get(v).push(feature)
}
const stripped = path.substr(0, path.length - ".geojson".length)
perProperty.forEach((features, v) => {
fs.writeFileSync(stripped+"."+v.replace(/[^a-zA-Z0-9_]/g, "_")+".geojson",
JSON.stringify({
type:"FeatureCollection",
features
}))
})
}
let args = [...process.argv]
args.splice(0, 2)
try {
main(args)
} catch (e) {
console.error("Error building cache:", e)
}
console.log("All done!")

153
test.ts
View file

@ -1,152 +1 @@
import State from "./State";
import AllKnownLayers from "./Customizations/AllKnownLayers";
import AvailableBaseLayersImplementation from "./Logic/Actors/AvailableBaseLayersImplementation";
import AvailableBaseLayers from "./Logic/Actors/AvailableBaseLayers";
import MinimapImplementation from "./UI/Base/MinimapImplementation";
import {Utils} from "./Utils";
import * as grb from "./assets/themes/grb_import/grb.json";
import ReplaceGeometryAction from "./Logic/Osm/Actions/ReplaceGeometryAction";
import Minimap from "./UI/Base/Minimap";
import ShowDataLayer from "./UI/ShowDataLayer/ShowDataLayer";
import {AllKnownLayouts} from "./Customizations/AllKnownLayouts";
import {BBox} from "./Logic/BBox";
AvailableBaseLayers.implement(new AvailableBaseLayersImplementation())
MinimapImplementation.initialize()
async function test() {
const wayId = "way/323230330";
const targetFeature = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
4.483118100000016,
51.028366499999706
],
[
4.483135099999986,
51.028325800000005
],
[
4.483137700000021,
51.02831960000019
],
[
4.4831429000000025,
51.0283205
],
[
4.483262199999987,
51.02834059999982
],
[
4.483276700000019,
51.028299999999746
],
[
4.483342100000037,
51.02830730000009
],
[
4.483340700000012,
51.028331299999934
],
[
4.483346499999953,
51.02833189999984
],
[
4.483290600000001,
51.028500699999846
],
[
4.4833335999999635,
51.02851150000015
],
[
4.4833433000000475,
51.028513999999944
],
[
4.483312899999958,
51.02857759999998
],
[
4.483141100000033,
51.02851780000015
],
[
4.483193100000022,
51.028409999999894
],
[
4.483206100000019,
51.02838310000014
],
[
4.483118100000016,
51.028366499999706
]
]
]
},
"id": "https://betadata.grbosm.site/grb?bbox=498980.9206456306,6626173.107985358,499133.7947022009,6626325.98204193/30",
"bbox": {
"maxLat": 51.02857759999998,
"maxLon": 4.483346499999953,
"minLat": 51.028299999999746,
"minLon": 4.483118100000016
},
"_lon": 4.483232299999985,
"_lat": 51.02843879999986
}
const layout = AllKnownLayouts.allKnownLayouts.get("grb")
const state = new State(layout)
State.state = state;
const bbox = new BBox(
[[
4.482952281832695,
51.02828527958197
],
[
4.483400881290436,
51.028578384406984
]
])
const url = `https://www.openstreetmap.org/api/0.6/map.json?bbox=${bbox.minLon},${bbox.minLat},${bbox.maxLon},${bbox.maxLat}`
const data = await Utils.downloadJson(url)
state.featurePipeline.fullNodeDatabase.handleOsmJson(data, 0)
const action = new ReplaceGeometryAction(state, targetFeature, wayId, {
theme: "test"
}
)
console.log(">>>>> ", action.GetClosestIds())
const map = Minimap.createMiniMap({
attribution: false,
})
const preview = await action.getPreview()
new ShowDataLayer({
layerToShow: AllKnownLayers.sharedLayers.get("conflation"),
features: preview,
leafletMap: map.leafletMap,
zoomToFeatures: true
})
map
.SetStyle("height: 75vh;")
.AttachTo("maindiv")
}
test()
console.log("Hello world")