1
#' HERE Routing API: Calculate Isoline
2
#'
3
#' Calcuates isolines (\code{POLYGON} or \code{MULTIPOLYGON}) using the HERE 'Routing' API
4
#' that connect the end points of all routes leaving from defined centers (POIs) with either
5
#' a specified length, a specified travel time or consumption.
6
#'
7
#' @references
8
#' \href{https://developer.here.com/documentation/routing/topics/resource-calculate-isoline.html}{HERE Routing API: Calculate Isoline}
9
#'
10
#' @param poi \code{sf} object, Points of Interest (POIs) of geometry type \code{POINT}.
11
#' @param datetime \code{POSIXct} object, datetime for the departure (or arrival if \code{arrival = TRUE}).
12
#' @param arrival boolean, are the provided Points of Interest (POIs) the origin or destination locations (\code{default = FALSE})?
13
#' @param range numeric, a vector of type \code{integer} containing the breaks for the generation of the isolines: (1) time in seconds; (2) distance in meters; (3) consumption in costfactor.
14
#' @param range_type character, unit of the isolines: \code{"distance"}, \code{"time"} or \code{"consumption"}.
15
#' @param type character, set the routing type: \code{"fastest"} or \code{"shortest"}.
16
#' @param mode character, set the transport mode: \code{"car"}, \code{"pedestrian"} or \code{"truck"}.
17
#' @param traffic boolean, use real-time traffic or prediction in routing (\code{default = FALSE})? If no \code{datetime} is set, the current timestamp at the moment of the request is used for \code{datetime}.
18
#' @param aggregate boolean, aggregate (with function \code{min}) and intersect the isolines from geometry type \code{POLYGON} to geometry type \code{MULTIPOLYGON} (\code{default = TRUE})?
19
#' @param url_only boolean, only return the generated URLs (\code{default = FALSE})?
20
#'
21
#' @return
22
#' An \code{sf} object containing the requested isolines.
23
#' @export
24
#'
25
#' @examples
26
#' # Provide an API Key for a HERE project
27
#' set_key("<YOUR API KEY>")
28
#'
29
#' # Isochrone for 5, 10, 15, 20, 25 and 30 minutes driving time
30
#' isolines <- isoline(
31
#'   poi = poi,
32
#'   range = seq(5, 30, 5) * 60,
33
#'   url_only = TRUE
34
#' )
35
isoline <- function(poi, datetime = Sys.time(), arrival = FALSE,
36
                    range = seq(5, 30, 5) * 60, range_type = "time",
37
                    type = "fastest", mode = "car", traffic = FALSE,
38
                    aggregate = TRUE, url_only = FALSE) {
39

40
  # Checks
41 1
  .check_points(poi)
42 1
  .check_datetime(datetime)
43 1
  .check_range_type(range_type)
44 1
  .check_type(type = type, request = "calculateisoline")
45 1
  .check_mode(mode = mode, request = "calculateisoline")
46 1
  .check_boolean(traffic)
47 1
  .check_boolean(arrival)
48 1
  .check_boolean(aggregate)
49 1
  .check_boolean(url_only)
50

51
  # Add API key
52 1
  url <- .add_key(
53 1
    url = "https://isoline.route.ls.hereapi.com/routing/7.2/calculateisoline.json?"
54
  )
55

56
  # Add point coords
57 1
  poi <- sf::st_coordinates(
58 1
    sf::st_transform(poi, 4326)
59
  )
60 1
  poi <- paste0(
61 1
    "geo!", poi[, 2], ",", poi[, 1]
62
  )
63 1
  url = paste0(
64 1
    url,
65 0
    if (!arrival) {"&start="} else {"&destination="},
66 1
    poi
67
  )
68

69
  # Add range and range type
70 1
  url = paste0(
71 1
    url,
72 1
    "&range=",
73 1
    paste0(range, collapse = ","),
74 1
    "&rangetype=",
75 1
    range_type
76
  )
77

78
  # Add consumption details
79 1
  if (range_type == "consumption") {
80 0
    url <- paste0(
81 0
      url,
82 0
      "&consumptionmodel=",
83 0
      "standard",
84 0
      "&customconsumptiondetails=",
85 0
      "speed,0,1.7,10,1.4,30,1.1,50,1.0,70,1.1,100,1.2,120,1.4,140,1.8;ascent,30.0;descent,10.0"
86
    )
87
  }
88
  # Add mode
89 1
  url <- .add_mode(
90 1
    url = url,
91 1
    type = type,
92 1
    mode = mode,
93 1
    traffic = traffic
94
  )
95

96
  # Add departure time
97 1
  url <- .add_datetime(
98 1
    url,
99 1
    datetime,
100 1
    if (arrival) "arrival" else "departure"
101
  )
102

103
  # Return urls if chosen
104 0
  if (url_only) return(url)
105

106
  # Request and get content
107 1
  data <- .get_content(
108 1
    url = url
109
  )
110 0
  if (length(data) == 0) return(NULL)
111

112
  # Extract information
113 1
  ids <- .get_ids(data)
114 1
  count <- 0
115 1
  isolines <-  sf::st_as_sf(
116 1
    as.data.frame(data.table::rbindlist(
117 1
      lapply(data, function(con) {
118 1
        count <<- count + 1
119 1
        df <- jsonlite::fromJSON(con)
120 1
        geometry <- lapply(df$response$isoline$component, function(iso){
121 1
          .polygon_from_pointList(iso$shape[[1]])
122
        })
123 1
        sf::st_as_sf(
124 1
          data.table::data.table(
125 1
            id = ids[count],
126 1
            departure = if(arrival) (datetime - df$response$isoline$range) else datetime,
127 1
            arrival = if(arrival) datetime else (datetime + df$response$isoline$range),
128 1
            range =  df$response$isoline$range,
129 1
            lng = df$response$center$longitude,
130 1
            lat = df$response$center$latitude
131
          ),
132 1
          geometry = sf::st_as_sfc(geometry, crs = 4326)
133
        )
134
      })
135 1
    )), check_ring_dir = TRUE
136
  )
137

138
  # Aggregate
139 1
  if (aggregate) {
140 1
    tz <- attr(isolines$departure, "tzone")
141 1
    isolines <- sf::st_set_precision(isolines, 1e5)
142 1
    isolines <- sf::st_make_valid(isolines)
143 1
    isolines <- stats::aggregate(isolines, by = list(isolines$range),
144 1
                                 FUN = min, do_union = TRUE, simplify = TRUE,
145 1
                                 join = sf::st_intersects)
146 1
    isolines <- sf::st_make_valid(isolines)
147 1
    suppressMessages(
148 1
      isolines <- sf::st_difference(isolines)
149
    )
150 1
    isolines$Group.1 <- NULL
151 1
    isolines$id <- NA
152 1
    attr(isolines$departure, "tzone") <- tz
153 1
    attr(isolines$arrival, "tzone") <- tz
154

155
    # Fix geometry collections
156 1
    suppressWarnings(
157 1
      isolines <- sf::st_collection_extract(
158 1
        isolines, type = c("POLYGON")
159
      )
160
    )
161
  }
162

163 1
  rownames(isolines) <- NULL
164 1
  return(isolines)
165
}

Read our documentation on viewing source code .

Loading