R/otp-geocode.R

Defines functions otp_geocode

Documented in otp_geocode

#'  Use OTP Geo-coder to find a location
#'
#'  Geo-coding converts a named place, such as a street name into a
#'      lng/lat pair.
#'
#' @param otpcon OTP connection object produced by otp_connect()
#' @param query Character, The query string we want to geocode
#' @param autocomplete logical Whether we should use the query
#'     string to do a prefix match, default FALSE
#' @param stops Logical, Search for stops, either by name or
#'     stop code, default TRUE
#' @param clusters Logical, Search for clusters by their name,
#'     default FALSE
#' @param corners Logical, Search for street corners using at
#'     least one of the street names, default TRUE
#' @param type Character, How should results be returned can
#'     be "SF" or "Coordinates" or "Both", Default "SF"
#' @family routing
#' @return
#' Returns a data.frame of SF POINTS or Coordinates of all
#'     the locations that match `query`
#' @examples
#' \dontrun{
#' locations <- otp_geocode(otpcon, "High Street")
#' }
#' @details
#' OTP will return a maximum of 10 results
#'
#' @export
otp_geocode <- function(otpcon = NULL,
                        query = NULL,
                        autocomplete = FALSE,
                        stops = TRUE,
                        clusters = FALSE,
                        corners = TRUE,
                        type = "SF") {
  # Check for OTP2
  if (!is.null(otpcon$otp_version)) {
    if (otpcon$otp_version >= 2) {
      stop("Geocoding is not supported by OTP v2.X")
    }
  }

  # Validate Inputs
  checkmate::assert_class(otpcon, "otpconnect", null.ok = FALSE)
  checkmate::assert_character(query,
    null.ok = FALSE, len = 1,
    min.chars = 1, any.missing = FALSE
  )
  checkmate::assert_logical(autocomplete, null.ok = FALSE)
  checkmate::assert_logical(stops, null.ok = FALSE)
  checkmate::assert_logical(clusters, null.ok = FALSE)
  checkmate::assert_logical(corners, null.ok = FALSE)
  checkmate::assert_choice(type,
    choices = c("SF", "Coordinates", "Both"),
    null.ok = FALSE
  )


  autocomplete <- tolower(as.character(autocomplete))
  stops <- tolower(as.character(stops))
  clusters <- tolower(as.character(clusters))
  corners <- tolower(as.character(corners))

  # Construct URL
  routerUrl <- make_url(otpcon)
  routerUrl <- paste0(routerUrl, "/geocode")

  querylist <- list(
    query = query,
    autocomplete = autocomplete,
    stops = stops,
    clusters = clusters,
    corners = corners
  )

  # convert response content into text
  url <- build_url(routerUrl, querylist)
  text <- curl::curl_fetch_memory(url)
  text <- rawToChar(text$content)


  if (nchar(text) == 2) {
    warning(paste0("Failed to find '", query, "'"))
    return(NA)
  } else {
    # parse text to json
    # asjson <- jsonlite::fromJSON(text)
    asjson <- rjson::fromJSON(text)
    asjson <- data.table::rbindlist(asjson)
    # parse to sf
    if (type %in% c("SF", "Both")) {
      if (type == "SF") {
        remove <- TRUE
      } else {
        remove <- FALSE
      }
      response <- sf::st_as_sf(asjson,
        coords = c("lng", "lat"),
        remove = remove,
        crs = 4326
      )
      return(response)
    } else {
      return(asjson)
    }
  }
}
ropensci/opentripplanner documentation built on Aug. 5, 2024, 9:58 p.m.