In this Notebook we will use functions from sf that measure geometric properties (area, length, distance).

  • compute the total area of YNP in meters2 and miles2
  • compute the area of watersheds
  • compute the total length of roads
  • compute the distance between campgrounds and cell towers

Setup

Load the packages we’ll need and set tmap mode to ‘plot’:

library(sf)
library(units)
library(tmap)
tmap_mode("plot")
tmap mode set to plotting

Load dplyr and set name conflict preferences:

library(dplyr)

## Load the conflicted package
library(conflicted)

# Set conflict preferences
conflict_prefer("filter", "dplyr", quiet = TRUE)
conflict_prefer("count", "dplyr", quiet = TRUE)
conflict_prefer("select", "dplyr", quiet = TRUE)
conflict_prefer("arrange", "dplyr", quiet = TRUE)

Import the Park Boundary

## Define a convenience variable for UTM Zone 11
epsg_utm11n_nad83 <- 26911

## Import the YNP border
yose_bnd_utm <- st_read(dsn="./data", layer="yose_boundary") %>% 
  st_transform(epsg_utm11n_nad83)
Reading layer `yose_boundary' from data source `D:\Workshops\R-Spatial\rspatial_mod\outputs\rspatial_data\data' using driver `ESRI Shapefile'
Simple feature collection with 1 feature and 11 fields
Geometry type: POLYGON
Dimension:     XY
Bounding box:  xmin: -119.8864 ymin: 37.4947 xmax: -119.1964 ymax: 38.18515
Geodetic CRS:  North_American_Datum_1983

Compute the area of the park

Find area with st_area():

yose_area <- yose_bnd_utm %>% st_area()
yose_area
3019918537 [m^2]

Find the area in miles2.

## View in square miles
set_units(yose_area, mi^2)
1165.997 [mi^2]

Import the Watersheds

Next import the watershed boundaries.

yose_watersheds_utm <- st_read("./data/yose_watersheds.gpkg", layer="calw221") %>% 
  st_transform(epsg_utm11n_nad83) %>% 
  select(CALWNUM, HU, HRNAME, RBNAME, HUNAME, HANAME, CDFSPWNAME, CDFPWSNAME, HUC_8, HUC_8_NAME)
Reading layer `calw221' from data source `D:\Workshops\R-Spatial\rspatial_mod\outputs\rspatial_data\data\yose_watersheds.gpkg' using driver `GPKG'
Simple feature collection with 127 features and 38 fields
Geometry type: POLYGON
Dimension:     XY
Bounding box:  xmin: 1383.82 ymin: -61442.93 xmax: 81596.71 ymax: 26405.66
Projected CRS: unnamed
yose_watersheds_utm %>% slice(1:10) %>% as_tibble()

tm_shape(yose_watersheds_utm) +
  tm_borders() +
tm_shape(yose_bnd_utm) +
  tm_borders(col="red", lwd=3)

CHALLENGE: Compute the watershed areas

Compute the watershed areas, and add them as a new column in the attribute table. Answer

# Your answer here

CHALLENGE: Find the largest watershed

Find the largest watershed, and report the area in acres. Answer

# Your answer here

Import the Roads

yose_roads_utm <- st_read("./data/yose_roads.gdb", "Yosemite_Roads") %>% 
  st_transform(epsg_utm11n_nad83) %>% 
  select(RDNAME, RTENUMBER, YOSE_Surface, YOSE_FIRE_ROAD, YOSE_INPARK, YOSE_Type)
Reading layer `Yosemite_Roads' from data source `D:\Workshops\R-Spatial\rspatial_mod\outputs\rspatial_data\data\yose_roads.gdb' using driver `OpenFileGDB'
Simple feature collection with 823 features and 40 fields
Geometry type: MULTILINESTRING
Dimension:     XY
Bounding box:  xmin: 234658.1 ymin: 4139484 xmax: 324852.6 ymax: 4250252
Projected CRS: NAD83 / UTM zone 11N

Compute the length of roads and save it in the attribute table:

yose_roads_utm <- yose_roads_utm %>% 
  mutate(rd_length = st_length(yose_roads_utm))
yose_roads_utm %>% slice(1:10) %>% as_tibble()

CHALLENGE: Compute Road Lengths

Find the total length for each type of Road (see YOSE_Type) in miles. Answer

# Your answer here

Import the Campgrounds and Cell Towers

yose_campgrounds_utm <- st_read("./data", layer="yose_poi") %>% 
  st_transform(epsg_utm11n_nad83) %>% 
  filter(POITYPE == 'Campground') %>% 
  select(POINAME)
Reading layer `yose_poi' from data source `D:\Workshops\R-Spatial\rspatial_mod\outputs\rspatial_data\data' using driver `ESRI Shapefile'
Simple feature collection with 2720 features and 30 fields
Geometry type: POINT
Dimension:     XY
Bounding box:  xmin: 246416.2 ymin: 4153717 xmax: 301510.7 ymax: 4208419
Projected CRS: NAD83 / UTM zone 11N
  
yose_celltwrs_utm <- st_read("./data/yose_communications.gdb", "Cell_Towers") %>% 
  st_transform(epsg_utm11n_nad83) 
Reading layer `Cell_Towers' from data source `D:\Workshops\R-Spatial\rspatial_mod\outputs\rspatial_data\data\yose_communications.gdb' using driver `OpenFileGDB'
Simple feature collection with 5 features and 6 fields
Geometry type: POINT
Dimension:     XY
Bounding box:  xmin: 251532.4 ymin: 4158756 xmax: 293307.2 ymax: 4194328
Projected CRS: NAD83 / UTM zone 11N

Plot them:

tm_shape(yose_bnd_utm) +
  tm_borders() +
tm_shape(yose_campgrounds_utm) +
  tm_symbols(size = 0.3, col = "blue") +
tm_shape(yose_celltwrs_utm) +
  tm_symbols(size = 0.3, col = "red") 

Compute Distances Between Features - 1 sf data frame

st_distance() can be used to compute distances between features. If you pass it one sf object, it will return a symmetric distance matrix between all pairs of features.

Compute the distance between all pairs of campgrounds:

campgrounds_dist_mat <- st_distance(yose_campgrounds_utm)
campgrounds_dist_mat
Units: [m]
           [,1]      [,2]      [,3]      [,4]      [,5]      [,6]     [,7]      [,8]     [,9]     [,10]      [,11]
 [1,]     0.000  8275.796 12628.738 20897.961 24202.415 26366.307 45699.01 26318.172 32505.98 24022.360 27053.5366
 [2,]  8275.796     0.000  5634.176 19310.626 20243.499 21669.864 41526.22 18231.678 24574.95 17323.278 20522.7859
 [3,] 12628.738  5634.176     0.000 15448.311 15106.794 16243.769 36084.79 14050.939 23230.46 11754.726 14931.6215
 [4,] 20897.961 19310.626 15448.311     0.000  6776.104  9775.471 25681.09 23140.503 36074.82 14860.874 15706.6234
 [5,] 24202.415 20243.499 15106.794  6776.104     0.000  3014.800 21555.06 18297.281 31962.27  9501.164  9443.6883
 [6,] 26366.307 21669.864 16243.769  9775.471  3014.800     0.000 19858.20 16911.114 30774.47  8198.298  7236.6861
 [7,] 45699.014 41526.218 36084.793 25681.086 21555.058 19858.200     0.00 32839.145 45873.18 26134.546 23327.6854
 [8,] 26318.172 18231.678 14050.939 23140.503 18297.281 16911.114 32839.14     0.000 13892.94  8814.694 10183.5588
 [9,] 32505.983 24574.955 23230.456 36074.816 31962.268 30774.468 45873.18 13892.936     0.00 22606.591 24037.3432
[10,] 24022.360 17323.278 11754.726 14860.874  9501.164  8198.298 26134.55  8814.694 22606.59     0.000  3222.2366
[11,] 27053.537 20522.786 14931.621 15706.623  9443.688  7236.686 23327.69 10183.559 24037.34  3222.237     0.0000
[12,] 27174.786 20589.170 15009.085 15972.557  9717.027  7503.431 23439.68  9979.152 23820.38  3268.848   273.4135
[13,] 27088.787 20464.194 14892.172 16067.174  9849.639  7671.851 23645.40  9768.727 23613.03  3140.976   440.3027
[14,] 27616.957 20889.582 15345.375 16750.368 10495.364  8244.331 23684.28  9487.701 23272.44  3604.361  1053.9344
[15,] 22073.083 24539.640 22864.646 11107.445 17786.365 20717.442 32873.41 33489.566 45540.25 25705.918 26791.2639
           [,12]      [,13]      [,14]    [,15]
 [1,] 27174.7857 27088.7873 27616.9569 22073.08
 [2,] 20589.1697 20464.1936 20889.5823 24539.64
 [3,] 15009.0854 14892.1717 15345.3754 22864.65
 [4,] 15972.5573 16067.1742 16750.3676 11107.45
 [5,]  9717.0274  9849.6393 10495.3635 17786.37
 [6,]  7503.4311  7671.8512  8244.3308 20717.44
 [7,] 23439.6793 23645.4050 23684.2839 32873.41
 [8,]  9979.1521  9768.7266  9487.7011 33489.57
 [9,] 23820.3830 23613.0283 23272.4414 45540.25
[10,]  3268.8477  3140.9757  3604.3606 25705.92
[11,]   273.4135   440.3027  1053.9344 26791.26
[12,]     0.0000   212.8079   782.1046 27054.79
[13,]   212.8079     0.0000   692.4943 27142.02
[14,]   782.1046   692.4943     0.0000 27829.09
[15,] 27054.7878 27142.0250 27829.0938     0.00

Compute Distances Between Features - 2 sf data frames

If you pass two sf objects to st_distance(), it will return a n x m matrix containing the distance between all pairs of features.

Compute the distance between all pairs of campgrounds and cell towers:

cgct_dist_mat <- st_distance(yose_campgrounds_utm, yose_celltwrs_utm)
cgct_dist_mat
Units: [m]
            [,1]      [,2]      [,3]      [,4]      [,5]
 [1,] 46219.4109 25884.856 26225.834 33538.244  5903.577
 [2,] 42063.8195 19210.673 19163.004 25491.865  2384.789
 [3,] 36624.3349 13645.182 13737.613 23773.991  7499.216
 [4,] 26168.3039 15613.133 17308.435 36061.840 19627.095
 [5,] 22082.7907  9689.048 11543.363 31666.279 21313.320
 [6,] 20396.4206  7834.371  9723.708 30321.762 22987.367
 [7,]   541.1383 24682.675 25995.385 44830.662 42783.486
 [8,] 33352.8435  9178.442  7376.002 13416.944 20585.520
 [9,] 46361.8785 23070.914 21252.438  1824.674 26769.154
[10,] 26671.4314  1890.457  2646.959 22220.557 19249.627
[11,] 23859.2190  1411.166  2821.810 23427.597 22413.196
[12,] 23970.1116  1403.475  2639.230 23199.118 22497.225
[13,] 24175.5888  1257.224  2426.427 22995.829 22383.935
[14,] 24211.1160  1733.602  2314.224 22611.632 22843.581
[15,] 33272.4448 26622.758 28245.217 45778.512 23754.044

CHALLENGE: Find the closest cell tower

For the first campground (row), which is the closest cell tower? Answer

Hint: use which.min()

# Your answer here

End

Congratulations, you’ve completed the Notebook!

To view your Notebook at HTML, save it (again), then click the ‘Preview’ button in the RStudio toolbar.

LS0tDQp0aXRsZTogIkdlb3Byb2Nlc3NpbmcgMSAtIEdlb21ldHJpYyBNZWFzdXJlbWVudHMiDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCi0tLQ0KDQpJbiB0aGlzIE5vdGVib29rIHdlIHdpbGwgdXNlIGZ1bmN0aW9ucyBmcm9tIGBzZmAgdGhhdCBtZWFzdXJlIGdlb21ldHJpYyBwcm9wZXJ0aWVzIChhcmVhLCBsZW5ndGgsIGRpc3RhbmNlKS4gDQoNCi0gY29tcHV0ZSB0aGUgdG90YWwgYXJlYSBvZiBZTlAgaW4gbWV0ZXJzXjJeIGFuZCBtaWxlc14yXiAgDQotIGNvbXB1dGUgdGhlIGFyZWEgb2Ygd2F0ZXJzaGVkcyAgIA0KLSBjb21wdXRlIHRoZSB0b3RhbCBsZW5ndGggb2Ygcm9hZHMgIA0KLSBjb21wdXRlIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIGNhbXBncm91bmRzIGFuZCBjZWxsIHRvd2VycyAgICANCg0KIyMgU2V0dXANCg0KTG9hZCB0aGUgcGFja2FnZXMgd2UnbGwgbmVlZCBhbmQgc2V0IHRtYXAgbW9kZSB0byAncGxvdCc6DQoNCmBgYHtyIGNodW5rMDF9DQpsaWJyYXJ5KHNmKQ0KbGlicmFyeSh1bml0cykNCmxpYnJhcnkodG1hcCkNCnRtYXBfbW9kZSgicGxvdCIpDQpgYGANCg0KTG9hZCBgZHBseXJgIGFuZCBzZXQgbmFtZSBjb25mbGljdCBwcmVmZXJlbmNlczoNCg0KYGBge3IgY2h1bmswMn0NCmxpYnJhcnkoZHBseXIpDQoNCiMjIExvYWQgdGhlIGNvbmZsaWN0ZWQgcGFja2FnZQ0KbGlicmFyeShjb25mbGljdGVkKQ0KDQojIFNldCBjb25mbGljdCBwcmVmZXJlbmNlcw0KY29uZmxpY3RfcHJlZmVyKCJmaWx0ZXIiLCAiZHBseXIiLCBxdWlldCA9IFRSVUUpDQpjb25mbGljdF9wcmVmZXIoImNvdW50IiwgImRwbHlyIiwgcXVpZXQgPSBUUlVFKQ0KY29uZmxpY3RfcHJlZmVyKCJzZWxlY3QiLCAiZHBseXIiLCBxdWlldCA9IFRSVUUpDQpjb25mbGljdF9wcmVmZXIoImFycmFuZ2UiLCAiZHBseXIiLCBxdWlldCA9IFRSVUUpDQpgYGANCg0KIyMgSW1wb3J0IHRoZSBQYXJrIEJvdW5kYXJ5DQoNCmBgYHtyIGNodW5rMDN9DQojIyBEZWZpbmUgYSBjb252ZW5pZW5jZSB2YXJpYWJsZSBmb3IgVVRNIFpvbmUgMTENCmVwc2dfdXRtMTFuX25hZDgzIDwtIDI2OTExDQoNCiMjIEltcG9ydCB0aGUgWU5QIGJvcmRlcg0KeW9zZV9ibmRfdXRtIDwtIHN0X3JlYWQoZHNuPSIuL2RhdGEiLCBsYXllcj0ieW9zZV9ib3VuZGFyeSIpICU+JSANCiAgc3RfdHJhbnNmb3JtKGVwc2dfdXRtMTFuX25hZDgzKQ0KYGBgDQoNCiMjIENvbXB1dGUgdGhlIGFyZWEgb2YgdGhlIHBhcmsNCg0KRmluZCBhcmVhIHdpdGggYHN0X2FyZWEoKWA6DQoNCmBgYHtyIGNodW5rMDR9DQp5b3NlX2FyZWEgPC0geW9zZV9ibmRfdXRtICU+JSBzdF9hcmVhKCkNCnlvc2VfYXJlYQ0KYGBgDQoNCkZpbmQgdGhlIGFyZWEgaW4gbWlsZXNeMl4uDQoNCmBgYHtyIGNodW5rMDV9DQojIyBWaWV3IGluIHNxdWFyZSBtaWxlcw0Kc2V0X3VuaXRzKHlvc2VfYXJlYSwgbWleMikNCmBgYA0KDQojIyBJbXBvcnQgdGhlIFdhdGVyc2hlZHMNCg0KTmV4dCBpbXBvcnQgdGhlIHdhdGVyc2hlZCBib3VuZGFyaWVzLg0KDQpgYGB7ciBjaHVuazA2fQ0KeW9zZV93YXRlcnNoZWRzX3V0bSA8LSBzdF9yZWFkKCIuL2RhdGEveW9zZV93YXRlcnNoZWRzLmdwa2ciLCBsYXllcj0iY2FsdzIyMSIpICU+JSANCiAgc3RfdHJhbnNmb3JtKGVwc2dfdXRtMTFuX25hZDgzKSAlPiUgDQogIHNlbGVjdChDQUxXTlVNLCBIVSwgSFJOQU1FLCBSQk5BTUUsIEhVTkFNRSwgSEFOQU1FLCBDREZTUFdOQU1FLCBDREZQV1NOQU1FLCBIVUNfOCwgSFVDXzhfTkFNRSkNCg0KeW9zZV93YXRlcnNoZWRzX3V0bSAlPiUgc2xpY2UoMToxMCkgJT4lIGFzX3RpYmJsZSgpDQoNCnRtX3NoYXBlKHlvc2Vfd2F0ZXJzaGVkc191dG0pICsNCiAgdG1fYm9yZGVycygpICsNCnRtX3NoYXBlKHlvc2VfYm5kX3V0bSkgKw0KICB0bV9ib3JkZXJzKGNvbD0icmVkIiwgbHdkPTMpDQpgYGANCg0KIyMgQ0hBTExFTkdFOiBDb21wdXRlIHRoZSB3YXRlcnNoZWQgYXJlYXMNCg0KQ29tcHV0ZSB0aGUgd2F0ZXJzaGVkIGFyZWFzLCBhbmQgYWRkIHRoZW0gYXMgYSBuZXcgY29sdW1uIGluIHRoZSBhdHRyaWJ1dGUgdGFibGUuIFtBbnN3ZXJdKGh0dHBzOi8vYml0Lmx5LzNkb3Y5WncpDQoNCmBgYHtyIGNodW5rMDd9DQojIFlvdXIgYW5zd2VyIGhlcmUNCg0KYGBgDQoNCiMjIENIQUxMRU5HRTogRmluZCB0aGUgbGFyZ2VzdCB3YXRlcnNoZWQNCg0KRmluZCB0aGUgbGFyZ2VzdCB3YXRlcnNoZWQsIGFuZCByZXBvcnQgdGhlIGFyZWEgaW4gYWNyZXMuIFtBbnN3ZXJdKGh0dHBzOi8vYml0Lmx5LzN1YVk0SEUpDQoNCmBgYHtyIGNodW5rMDh9DQojIFlvdXIgYW5zd2VyIGhlcmUNCg0KYGBgDQoNCiMjIEltcG9ydCB0aGUgUm9hZHMNCg0KYGBge3IgY2h1bmswOX0NCnlvc2Vfcm9hZHNfdXRtIDwtIHN0X3JlYWQoIi4vZGF0YS95b3NlX3JvYWRzLmdkYiIsICJZb3NlbWl0ZV9Sb2FkcyIpICU+JSANCiAgc3RfdHJhbnNmb3JtKGVwc2dfdXRtMTFuX25hZDgzKSAlPiUgDQogIHNlbGVjdChSRE5BTUUsIFJURU5VTUJFUiwgWU9TRV9TdXJmYWNlLCBZT1NFX0ZJUkVfUk9BRCwgWU9TRV9JTlBBUkssIFlPU0VfVHlwZSkNCmBgYA0KDQpDb21wdXRlIHRoZSBsZW5ndGggb2Ygcm9hZHMgYW5kIHNhdmUgaXQgaW4gdGhlIGF0dHJpYnV0ZSB0YWJsZToNCg0KYGBge3IgY2h1bmsxMH0NCnlvc2Vfcm9hZHNfdXRtIDwtIHlvc2Vfcm9hZHNfdXRtICU+JSANCiAgbXV0YXRlKHJkX2xlbmd0aCA9IHN0X2xlbmd0aCh5b3NlX3JvYWRzX3V0bSkpDQp5b3NlX3JvYWRzX3V0bSAlPiUgc2xpY2UoMToxMCkgJT4lIGFzX3RpYmJsZSgpDQpgYGANCg0KIyMgQ0hBTExFTkdFOiBDb21wdXRlIFJvYWQgTGVuZ3Rocw0KDQpGaW5kIHRoZSB0b3RhbCBsZW5ndGggZm9yIGVhY2ggdHlwZSBvZiBSb2FkIChzZWUgWU9TRV9UeXBlKSBpbiBtaWxlcy4gW0Fuc3dlcl0oaHR0cHM6Ly9iaXQubHkvM3diYkxiYikNCg0KYGBge3IgY2h1bmsxMX0NCiMgWW91ciBhbnN3ZXIgaGVyZQ0KDQpgYGANCg0KIyMgSW1wb3J0IHRoZSBDYW1wZ3JvdW5kcyBhbmQgQ2VsbCBUb3dlcnMNCg0KYGBge3IgY2h1bmsxMn0NCnlvc2VfY2FtcGdyb3VuZHNfdXRtIDwtIHN0X3JlYWQoIi4vZGF0YSIsIGxheWVyPSJ5b3NlX3BvaSIpICU+JSANCiAgc3RfdHJhbnNmb3JtKGVwc2dfdXRtMTFuX25hZDgzKSAlPiUgDQogIGZpbHRlcihQT0lUWVBFID09ICdDYW1wZ3JvdW5kJykgJT4lIA0KICBzZWxlY3QoUE9JTkFNRSkNCiAgDQp5b3NlX2NlbGx0d3JzX3V0bSA8LSBzdF9yZWFkKCIuL2RhdGEveW9zZV9jb21tdW5pY2F0aW9ucy5nZGIiLCAiQ2VsbF9Ub3dlcnMiKSAlPiUgDQogIHN0X3RyYW5zZm9ybShlcHNnX3V0bTExbl9uYWQ4MykgDQpgYGANCg0KUGxvdCB0aGVtOg0KDQpgYGB7ciBjaHVuazEzfQ0KdG1fc2hhcGUoeW9zZV9ibmRfdXRtKSArDQogIHRtX2JvcmRlcnMoKSArDQp0bV9zaGFwZSh5b3NlX2NhbXBncm91bmRzX3V0bSkgKw0KICB0bV9zeW1ib2xzKHNpemUgPSAwLjMsIGNvbCA9ICJibHVlIikgKw0KdG1fc2hhcGUoeW9zZV9jZWxsdHdyc191dG0pICsNCiAgdG1fc3ltYm9scyhzaXplID0gMC4zLCBjb2wgPSAicmVkIikgDQpgYGANCg0KIyMgQ29tcHV0ZSBEaXN0YW5jZXMgQmV0d2VlbiBGZWF0dXJlcyAtIDEgc2YgZGF0YSBmcmFtZQ0KDQpgc3RfZGlzdGFuY2UoKWAgY2FuIGJlIHVzZWQgdG8gY29tcHV0ZSBkaXN0YW5jZXMgYmV0d2VlbiBmZWF0dXJlcy4gSWYgeW91IHBhc3MgaXQgb25lIHNmIG9iamVjdCwgaXQgd2lsbCByZXR1cm4gYSBzeW1tZXRyaWMgZGlzdGFuY2UgbWF0cml4IGJldHdlZW4gYWxsIHBhaXJzIG9mIGZlYXR1cmVzLiANCg0KQ29tcHV0ZSB0aGUgZGlzdGFuY2UgYmV0d2VlbiBhbGwgcGFpcnMgb2YgY2FtcGdyb3VuZHM6DQoNCmBgYHtyIGNodW5rMTR9DQpjYW1wZ3JvdW5kc19kaXN0X21hdCA8LSBzdF9kaXN0YW5jZSh5b3NlX2NhbXBncm91bmRzX3V0bSkNCmNhbXBncm91bmRzX2Rpc3RfbWF0DQpgYGANCg0KDQojIyBDb21wdXRlIERpc3RhbmNlcyBCZXR3ZWVuIEZlYXR1cmVzIC0gMiBzZiBkYXRhIGZyYW1lcw0KDQpJZiB5b3UgcGFzcyB0d28gc2Ygb2JqZWN0cyB0byBgc3RfZGlzdGFuY2UoKWAsIGl0IHdpbGwgcmV0dXJuIGEgKm4geCBtKiBtYXRyaXggY29udGFpbmluZyB0aGUgZGlzdGFuY2UgYmV0d2VlbiBhbGwgcGFpcnMgb2YgZmVhdHVyZXMuIA0KDQpDb21wdXRlIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIGFsbCBwYWlycyBvZiBjYW1wZ3JvdW5kcyBhbmQgY2VsbCB0b3dlcnM6DQoNCmBgYHtyIGNodW5rMTV9DQpjZ2N0X2Rpc3RfbWF0IDwtIHN0X2Rpc3RhbmNlKHlvc2VfY2FtcGdyb3VuZHNfdXRtLCB5b3NlX2NlbGx0d3JzX3V0bSkNCmNnY3RfZGlzdF9tYXQNCmBgYA0KDQojIyBDSEFMTEVOR0U6IEZpbmQgdGhlIGNsb3Nlc3QgY2VsbCB0b3dlcg0KDQpGb3IgdGhlIGZpcnN0IGNhbXBncm91bmQgKHJvdyksIHdoaWNoIGlzIHRoZSBjbG9zZXN0IGNlbGwgdG93ZXI/IFtBbnN3ZXJdKGh0dHBzOi8vYml0Lmx5LzN3ZWJUWHApDQoNCkhpbnQ6IHVzZSBgd2hpY2gubWluKClgDQoNCmBgYHtyIGNodW5rMTZ9DQojIFlvdXIgYW5zd2VyIGhlcmUNCg0KYGBgDQoNCiMjIEVuZA0KDQpDb25ncmF0dWxhdGlvbnMsIHlvdSd2ZSBjb21wbGV0ZWQgdGhlIE5vdGVib29rISANCg0KVG8gdmlldyB5b3VyIE5vdGVib29rIGF0IEhUTUwsIHNhdmUgaXQgKGFnYWluKSwgdGhlbiBjbGljayB0aGUgJ1ByZXZpZXcnIGJ1dHRvbiBpbiB0aGUgUlN0dWRpbyB0b29sYmFyLg0KDQoNCg0K