# How to edit OpenStreetMap

WARNING: This vignette contain examples that can edit the data at OpenStreetMap.org. Please, create a user in the testing server and configure `osmapiR` to use it. You will be responsible for any edition!

    library(osmapiR)
    set_osmapi_connection(server = "testing") # set the testing server

Create some dummy OSM objects.

    d <- data.frame(
      type = c("node", "node", "way", "relation"),
      id = -(1:4),
      lat = c(0, 1, NA, NA),
      lon = c(0, 1, NA, NA),
      name = c(NA, NA, "My way", "Our relation"),
      type.1 = c(NA, NA, NA, "Column clash!")
    )
    d$members <- list(
      NULL, NULL, -(1:2),
      matrix(
        c("node", "-1", "node", "-2", "way", "-3"),
        nrow = 3, ncol = 2, byrow = TRUE, dimnames = list(NULL, c("type", "ref"))
      )
    )
    obj <- osmapi_objects(d, tag_columns = c(name = "name", type = "type.1"))

## Using `OSMChange` format and `osm_diff_upload_changeset()`

    osmcha_crea <- osmchange_create(obj)
    osmcha_crea

    changeset_id <- osm_create_changeset(
      comment = "Add objects for testing editions with osmchange format.",
      hashtags = "#osmapiRvignette;#testing"
    )
    osmcha_diff <- osm_diff_upload_changeset(changeset_id = changeset_id, osmcha = osmcha_crea)

    message("See changeset at:\n\t", paste0(get_osmapi_url(), "/changeset/", changeset_id))

Add a new node:

    new_node <- data.frame(type = "node", id = -1, lat = 0, lon = 1)
    new_node <- osmapi_objects(new_node)
    osmcha_new_node <- osmchange_create(new_node)

Update the `id` of the created objects which we want to modify with the `id` assigned by the server:

    mod_obj <- obj[3:4, ]
    mod_obj$id <- osmcha_diff$new_id[match(mod_obj$id, osmcha_diff$old_id)]

    mod_obj$members[[1]] <- osmcha_diff$new_id[match(mod_obj$members[[1]], osmcha_diff$old_id)]
    mod_obj$members[[2]][, "ref"] <- osmcha_diff$new_id[match(mod_obj$members[[2]][, "ref"], osmcha_diff$old_id)]

Add the new node to the way and the relation

    mod_obj$members[[1]] <- c(mod_obj$members[[1]], new_node$id)
    mod_obj$members[[2]] <- rbind(mod_obj$members[[2]], as.character(new_node[, c("type", "id")]))
    mod_obj <- osmapi_objects(mod_obj)

    osmcha_mod <- osmchange_modify(mod_obj, tag_keys = FALSE, members = TRUE)

Unite modification and new node changes and commit changes

    # Just for the rbind of `osmcha_create` and `osmcha_modify` which have different columns:
    osmcha_new_node <- osmapi_objects(osmcha_new_node)
    osmcha_new_node[, setdiff(names(osmcha_mod), names(osmcha_new_node))] <- NA

    osmcha_2 <- rbind(osmcha_new_node, osmcha_mod)

    osmcha_diff2 <- osm_diff_upload_changeset(changeset_id = changeset_id, osmcha = osmcha_2)

Even if it’s a testing server, better to leave it clean. Let’s remove the created objects and close the changeset:

    osmcha_del <- unique(rbind(osmcha_diff[, c("type", "new_id")], osmcha_diff2[, c("type", "new_id")]))
    names(osmcha_del) <- c("type", "id")
    osmcha_del <- osmchange_delete(osmcha_del)
    osmcha_del

    osmcha_diff_del <- osm_diff_upload_changeset(changeset_id = changeset_id, osmcha = osmcha_del)
    osmcha_diff_del

    osm_close_changeset(changeset_id)

## Using osmapi patterns

To avoid performance issues when uploading multiple objects, the use of transactions with [osm_diff_upload_changeset()] as in the former example is highly recommended.

    changeset_id <- osm_create_changeset(
      comment = "Add objects for testing editions with osmapi.",
      hashtags = "#osmapiRvignette;#testing"
    )

    new_id <- character(nrow(obj))

    # create nodes
    for (i in 1:2) {
      obj$id[i] <- osm_create_object(obj[i, ], changeset_id = changeset_id)
    }

    # create way
    obj$members[[3]] <- obj$id[1:2] # update id of the newly created nodes
    obj$id[3] <- osm_create_object(obj[3, ], changeset_id = changeset_id)

    # create relation
    obj$members[[4]][, "ref"] <- obj$id[1:3] # update id of the newly created objects
    obj$id[4] <- osm_create_object(obj[4, ], changeset_id = changeset_id)

    message("See changeset at:\n\t", paste0(get_osmapi_url(), "/changeset/", changeset_id))

Update object:

    upd_obj <- osm_get_objects(osm_type = obj$type[4], osm_id = obj$id[4])
    new_tags <- upd_obj$tags[[1]]
    new_tags$value[2] <- "test"
    new_tags <- rbind(new_tags, data.frame(key = "name:ca", value = "La nostra relació"))
    upd_obj$tags[[1]] <- new_tags

    osm_update_object(upd_obj, changeset_id = changeset_id)

Delete everything and close the changeset:

    obj$version <- "1"
    obj$version[4] <- "2" # updated object
    for (i in rev(seq_len(nrow(obj)))) { # reverse order to avoid error (Node xxx is still used by ways yyy.)
      osm_delete_object(obj[i, ], changeset_id = changeset_id)
    }

    osm_close_changeset(changeset_id)