Angie Alejandra Juyo Buitrago Marzo 24-2020

Este es un cuaderno de R asignado para el curso de geomática básica de la Universidad Nacional de Colombia su objetivo es ilustra las funcionalidades geoespaciales de R con ayuda de las librerias (sf) y (tidyverse)

Lo primero que haremos ser? instalar las librerias mencionadas

#install.packages("tidyverse")
#install.packages("sf")

De forma posterior , debemos cargarlas

library(tidyverse)
Registered S3 method overwritten by 'dplyr':
  method           from
  print.rowwise_df     
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
-- Attaching packages --------------------------------------- tidyverse 1.3.0 --
v ggplot2 3.3.0     v purrr   0.3.3
v tibble  2.1.3     v dplyr   0.8.4
v tidyr   1.0.2     v stringr 1.4.0
v readr   1.3.1     v forcats 0.5.0
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(sf)
Linking to GEOS 3.6.1, GDAL 2.2.3, PROJ 4.9.3

Luego usamos la función “read_sf” esta, nos permite leer un archivo que ha sido previamente descargado de DIVA-GIS de forma que representa a los departamentos colombianos

deptos <-  read_sf("C:/Users/LUISA CARRION/Documents/Geomática/COL_adm1.shp")

Podemos saber cuál es el contenido de las primeras filas del objeto que fue importado

head(deptos)
Simple feature collection with 6 features and 9 fields
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: -77.149 ymin: -4.228429 xmax: -69.36835 ymax: 11.10792
epsg (SRID):    4326
proj4string:    +proj=longlat +datum=WGS84 +no_defs

La función st_crs es muy ?til para saber cuál es el sistema de referencia de coordenadas de los datos vectoriales almacenados en el objeto deptos:

st_crs(deptos)
Coordinate Reference System:
  EPSG: 4326 
  proj4string: "+proj=longlat +datum=WGS84 +no_defs"
  1. Usando el ggplot para visualizar los datos geoespaciales:

Podemos usar las funcionalidades del ggplot para trazar los datos del objeto deptos

ggplot() + geom_sf(data = deptos) 

Aunque podemos utilizar cualquier sistema de referencia de coordenadas para trazar los datos , no deberiamos utilizar un sistema de referencia de coordenadas que haya sido definido explícitamente para otro país o región

#El CRS 3968 es usado en Virginia , Estados Unidos 
ggplot() + geom_sf(data = deptos) + coord_sf(crs=st_crs(3968))

En caso de que necesitemos usar tal SRC, es necesario convertir el objeto espacial de EPSG4326 en EPSG:3968

deptos_utm <- st_transform(deptos, crs = st_crs(3968))
deptos_utm
Simple feature collection with 32 features and 9 fields
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: -280425.6 ymin: -4811689 xmax: 1697588 ymax: -2284762
epsg (SRID):    3968
proj4string:    +proj=lcc +lat_1=37 +lat_2=39.5 +lat_0=36 +lon_0=-79.5 +x_0=0 +y_0=0 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs
ggplot() + geom_sf(data = deptos_utm)

ggplot() + geom_sf(data = deptos_utm)

  1. Filtrar datos geoespaciales en función de los atributos

Esta vez sólo trabajaremos con un departamento,del cual podemos filtrar los datos.

Vichada <-  deptos %>%   filter(NAME_1 == "Vichada")

Y trazamos el nuevo objeto

ggplot() + geom_sf(data = Vichada) 

Podemos repetir los pasos anteriores ,pero esta vez con los municipios correspondientes al departamento de Vichada

munic <-  read_sf("C:/Users/LUISA CARRION/Documents/Geomática/COL_adm2.shp")
mun_Vichada <- munic %>% filter(NAME_1 == "Vichada")
ggplot() + geom_sf(data = mun_Vichada) 

mun_Vichada
Simple feature collection with 6 features and 11 fields
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: -71.0978 ymin: 2.7081 xmax: -67.42111 ymax: 6.301989
epsg (SRID):    4326
proj4string:    +proj=longlat +datum=WGS84 +no_defs
Vichada_points<- st_centroid(mun_Vichada)
st_centroid assumes attributes are constant over geometries of xst_centroid does not give correct centroids for longitude/latitude data
Vichada_points <- cbind(mun_Vichada, st_coordinates(st_centroid(mun_Vichada$geometry)))
st_centroid does not give correct centroids for longitude/latitude data

Podemos mejorar el aspecto de nuestro gráfico a traves del uso de diferentes funciones, como se muestra en el siguiente bloque de código

ggplot(Vichada) +
    geom_sf() +
    geom_sf(data = Vichada_points, fill = "Turquoise", color = "black") + 
    geom_text(data = Vichada_points, aes(x=X, y=Y,label = ID_2), size = 2) +
    coord_sf(xlim = c(-71.5, -67), ylim = c(2.5, 6.5), expand = FALSE)+ggtitle("Municipios de Vichada")

library(scales)

Attaching package: 㤼㸱scales㤼㸲

The following object is masked from 㤼㸱package:purrr㤼㸲:

    discard

The following object is masked from 㤼㸱package:readr㤼㸲:

    col_factor

También,podemos hacer que cada municipio de nuestro departamento se caracterize por un color, en función del código o ID

ggplot(Vichada) + 
  geom_sf(data=Vichada_points, aes(x=X, y=Y, fill =
                                       ID_2), color = "black", size = 0.25) +
  geom_text(data = Vichada_points, aes(x=X, y=Y,label = ID_2), size = 2) +
  theme(aspect.ratio=1)+
  scale_fill_distiller(name="ID_2", palette = "PuBuGn", breaks = pretty_breaks(n = 5))+
  labs(title="Municipios de Vichada")
Ignoring unknown aesthetics: x, y

Aunque, estas representaciones no son mapas reales, podemos exportarlas como PDF o en formato PNG

ggsave("Vichada_municipios.pdf")
Saving 7 x 7 in image
ggsave("map_Vichada.png", width = 6, height = 6, dpi = "screen")

Uso de Leaflet para la visualización de datos

Primero,instalamos el programa requerido para posteriormente cargarlo

library(leaflet)

Luego,para usar la libreria debemos convertir nuestros datos en puntos espaciales

Vichada_points <- as(Vichada_points, 'Spatial')
#head(Vichada_points)
install.packages("lwgeom")
library(lwgeom)
Linking to liblwgeom 3.0.0beta1 r16016, GEOS 3.6.1, PROJ 4.9.3

Podemos obtener el ?rea por municipios de la siguiente manera

mun_Vichada$area <- st_area(mun_Vichada)

Calculamos el área de cada municipio (en metros cuadrados):

mun_Vichada$km2 <- mun_Vichada$area/(1000000)

Creamos un nuevo campo para el area en Kilometros Cuadrados

mun_Vichada$km2
Units: [m^2]
[1] 21531.911 20596.228  9857.561 25241.785 19206.969  4320.376

Finalmente , comprobamos la salida

mun_Vichada$km2
Units: [m^2]
[1] 21531.911 20596.228  9857.561 25241.785 19206.969  4320.376

De nuevo convertimos a poligonos espaciales

Vichada_mun <- as(mun_Vichada, 'Spatial')

Y lo comprobamos

#head(Vichada_mun)

Preparamos nuestra gráfica

bins <- c(0, 50, 100, 200, 300, 500, 1000, 2000, Inf)
pal <- colorBin("YlOrRd", domain = Vichada_mun$km2, bins = bins)


labels <- mun_Vichada$NAME_2

labels
[1] "Cumaribo"          "La Primavera"      "Puerto Carreño"    "San Jose de Ocune" "Santa Rita"       
[6] "Santa Rosalía"    
m <- leaflet(Vichada_mun) %>%
  setView(-70.8, 4, 5)  %>% addPolygons(
  fillColor = ~pal(km2),
  weight = 2,
  opacity = 1,
  color = "white",
  dashArray = "3",
  fillOpacity = 0.7,
  highlight = highlightOptions(
    weight = 5,
    color = "#666",
    dashArray = "",
    fillOpacity = 0.7,
    bringToFront = TRUE),
  label = labels) %>%
  addLegend(pal = pal, values = ~km2, opacity = 0.7, title = NULL,
    position = "bottomright")
m

Otra forma de representar nuestros datos puede ser

leaflet() %>%
  addProviderTiles(providers$Esri.WorldImagery, options= providerTileOptions(opacity = 0.99)) %>%
  addPolygons(data = Vichada_mun, popup= Vichada_mun$NAME_2,
    stroke = TRUE, fillOpacity = 0.25, smoothFactor = 0.25
  )

Ahora usaremos SetView para conocer Puerto Carreño, la capital de nuestro departamento

v <- leaflet() %>% setView(lng = -69.0, lat = 6.15, zoom = 9)
v %>% addTiles()

NA
LS0tDQp0aXRsZTogIkRhdG9zIGRlIHZlY3RvcmVzIGdlb2VzcGFjaWFsZXMgZW4gUiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQpBbmdpZSBBbGVqYW5kcmEgSnV5byBCdWl0cmFnbw0KTWFyem8gMjQtMjAyMA0KDQpFc3RlIGVzIHVuIGN1YWRlcm5vIGRlIFIgYXNpZ25hZG8gcGFyYSBlbCBjdXJzbyBkZSBnZW9tw6F0aWNhIGLDoXNpY2EgZGUgbGEgVW5pdmVyc2lkYWQgTmFjaW9uYWwgZGUgQ29sb21iaWEgc3Ugb2JqZXRpdm8gZXMgaWx1c3RyYSBsYXMgZnVuY2lvbmFsaWRhZGVzIGdlb2VzcGFjaWFsZXMgZGUgUiBjb24gYXl1ZGEgZGUgbGFzIGxpYnJlcmlhcyAoc2YpIHkgKHRpZHl2ZXJzZSkgDQoNCkxvIHByaW1lcm8gcXVlIGhhcmVtb3Mgc2VyPyBpbnN0YWxhciBsYXMgbGlicmVyaWFzIG1lbmNpb25hZGFzDQoNCmBgYHtyfQ0KI2luc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQojaW5zdGFsbC5wYWNrYWdlcygic2YiKQ0KYGBgDQoNCkRlIGZvcm1hIHBvc3RlcmlvciAsIGRlYmVtb3MgY2FyZ2FybGFzIA0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShzZikNCmBgYA0KDQpMdWVnbyB1c2Ftb3MgbGEgZnVuY2nDs24gInJlYWRfc2YiIGVzdGEsIG5vcyBwZXJtaXRlIGxlZXIgdW4gYXJjaGl2byBxdWUgaGEgc2lkbyBwcmV2aWFtZW50ZSBkZXNjYXJnYWRvIGRlIERJVkEtR0lTIGRlIGZvcm1hIHF1ZSByZXByZXNlbnRhIGEgbG9zIGRlcGFydGFtZW50b3MgY29sb21iaWFub3MgDQoNCmBgYHtyfQ0KZGVwdG9zIDwtICByZWFkX3NmKCJDOi9Vc2Vycy9MVUlTQSBDQVJSSU9OL0RvY3VtZW50cy9HZW9tw6F0aWNhL0NPTF9hZG0xLnNocCIpDQpgYGANCg0KUG9kZW1vcyBzYWJlciBjdcOhbCBlcyBlbCBjb250ZW5pZG8gZGUgbGFzIHByaW1lcmFzIGZpbGFzIGRlbCBvYmpldG8gcXVlIGZ1ZSBpbXBvcnRhZG8NCg0KYGBge3J9DQpoZWFkKGRlcHRvcykNCmBgYA0KTGEgZnVuY2nDs24gc3RfY3JzIGVzIG11eSA/dGlsIHBhcmEgc2FiZXIgY3XDoWwgZXMgZWwgc2lzdGVtYSBkZSByZWZlcmVuY2lhIGRlIGNvb3JkZW5hZGFzIGRlIGxvcyBkYXRvcyB2ZWN0b3JpYWxlcyBhbG1hY2VuYWRvcyBlbiBlbCBvYmpldG8gZGVwdG9zOg0KDQoNCmBgYHtyfQ0Kc3RfY3JzKGRlcHRvcykNCmBgYA0KDQozLiBVc2FuZG8gZWwgZ2dwbG90IHBhcmEgdmlzdWFsaXphciBsb3MgZGF0b3MgZ2VvZXNwYWNpYWxlczoNCg0KUG9kZW1vcyB1c2FyIGxhcyBmdW5jaW9uYWxpZGFkZXMgZGVsIGdncGxvdCBwYXJhIHRyYXphciBsb3MgZGF0b3MgZGVsIG9iamV0byBkZXB0b3MNCg0KYGBge3J9DQpnZ3Bsb3QoKSArIGdlb21fc2YoZGF0YSA9IGRlcHRvcykgDQpgYGANCkF1bnF1ZSBwb2RlbW9zIHV0aWxpemFyIGN1YWxxdWllciBzaXN0ZW1hIGRlIHJlZmVyZW5jaWEgZGUgY29vcmRlbmFkYXMgcGFyYSB0cmF6YXIgbG9zIGRhdG9zICwgbm8gZGViZXJpYW1vcyB1dGlsaXphciB1biBzaXN0ZW1hIGRlIHJlZmVyZW5jaWEgZGUgY29vcmRlbmFkYXMgcXVlIGhheWEgc2lkbyBkZWZpbmlkbyBleHBsw61jaXRhbWVudGUgcGFyYSBvdHJvIHBhw61zIG8gcmVnacOzbg0KDQoNCmBgYHtyfQ0KI0VsIENSUyAzOTY4IGVzIHVzYWRvIGVuIFZpcmdpbmlhICwgRXN0YWRvcyBVbmlkb3MgDQpnZ3Bsb3QoKSArIGdlb21fc2YoZGF0YSA9IGRlcHRvcykgKyBjb29yZF9zZihjcnM9c3RfY3JzKDM5NjgpKQ0KYGBgDQpFbiBjYXNvIGRlIHF1ZSBuZWNlc2l0ZW1vcyB1c2FyIHRhbCBTUkMsIGVzIG5lY2VzYXJpbyBjb252ZXJ0aXIgZWwgb2JqZXRvIGVzcGFjaWFsIGRlIEVQU0c0MzI2IGVuIEVQU0c6Mzk2OA0KDQoNCmBgYHtyfQ0KZGVwdG9zX3V0bSA8LSBzdF90cmFuc2Zvcm0oZGVwdG9zLCBjcnMgPSBzdF9jcnMoMzk2OCkpDQpgYGANCg0KDQpgYGB7cn0NCmRlcHRvc191dG0NCmBgYA0KDQoNCmBgYHtyfQ0KZ2dwbG90KCkgKyBnZW9tX3NmKGRhdGEgPSBkZXB0b3NfdXRtKQ0KYGBgDQoNCg0KYGBge3J9DQpnZ3Bsb3QoKSArIGdlb21fc2YoZGF0YSA9IGRlcHRvc191dG0pDQpgYGANCg0KNC4gRmlsdHJhciBkYXRvcyBnZW9lc3BhY2lhbGVzIGVuIGZ1bmNpw7NuIGRlIGxvcyBhdHJpYnV0b3MNCg0KRXN0YSB2ZXogc8OzbG8gdHJhYmFqYXJlbW9zIGNvbiB1biBkZXBhcnRhbWVudG8sZGVsIGN1YWwgcG9kZW1vcyBmaWx0cmFyIGxvcyBkYXRvcy4gDQpgYGB7cn0NClZpY2hhZGEgPC0gIGRlcHRvcyAlPiUgICBmaWx0ZXIoTkFNRV8xID09ICJWaWNoYWRhIikNCmBgYA0KDQpZIHRyYXphbW9zIGVsIG51ZXZvIG9iamV0bw0KDQpgYGB7cn0NCmdncGxvdCgpICsgZ2VvbV9zZihkYXRhID0gVmljaGFkYSkgDQpgYGANClBvZGVtb3MgcmVwZXRpciBsb3MgcGFzb3MgYW50ZXJpb3JlcyAscGVybyBlc3RhIHZleiBjb24gbG9zIG11bmljaXBpb3MgY29ycmVzcG9uZGllbnRlcyBhbCBkZXBhcnRhbWVudG8gZGUgVmljaGFkYSAgDQoNCmBgYHtyfQ0KbXVuaWMgPC0gIHJlYWRfc2YoIkM6L1VzZXJzL0xVSVNBIENBUlJJT04vRG9jdW1lbnRzL0dlb23DoXRpY2EvQ09MX2FkbTIuc2hwIikNCmBgYA0KDQpgYGB7cn0NCm11bl9WaWNoYWRhIDwtIG11bmljICU+JSBmaWx0ZXIoTkFNRV8xID09ICJWaWNoYWRhIikNCmdncGxvdCgpICsgZ2VvbV9zZihkYXRhID0gbXVuX1ZpY2hhZGEpIA0KYGBgDQoNCmBgYHtyfQ0KbXVuX1ZpY2hhZGENCmBgYA0KDQoNCg0KYGBge3J9DQpWaWNoYWRhX3BvaW50czwtIHN0X2NlbnRyb2lkKG11bl9WaWNoYWRhKQ0KDQpgYGANCg0KYGBge3J9DQpWaWNoYWRhX3BvaW50cyA8LSBjYmluZChtdW5fVmljaGFkYSwgc3RfY29vcmRpbmF0ZXMoc3RfY2VudHJvaWQobXVuX1ZpY2hhZGEkZ2VvbWV0cnkpKSkNCmBgYA0KDQpQb2RlbW9zIG1lam9yYXIgZWwgYXNwZWN0byBkZSBudWVzdHJvIGdyw6FmaWNvIGEgdHJhdmVzIGRlbCB1c28gZGUgZGlmZXJlbnRlcyBmdW5jaW9uZXMsIGNvbW8gc2UgbXVlc3RyYSBlbiBlbCBzaWd1aWVudGUgYmxvcXVlIGRlIGPDs2RpZ28NCg0KYGBge3J9DQpnZ3Bsb3QoVmljaGFkYSkgKw0KICAgIGdlb21fc2YoKSArDQogICAgZ2VvbV9zZihkYXRhID0gVmljaGFkYV9wb2ludHMsIGZpbGwgPSAiVHVycXVvaXNlIiwgY29sb3IgPSAiYmxhY2siKSArIA0KICAgIGdlb21fdGV4dChkYXRhID0gVmljaGFkYV9wb2ludHMsIGFlcyh4PVgsIHk9WSxsYWJlbCA9IElEXzIpLCBzaXplID0gMikgKw0KICAgIGNvb3JkX3NmKHhsaW0gPSBjKC03MS41LCAtNjcpLCB5bGltID0gYygyLjUsIDYuNSksIGV4cGFuZCA9IEZBTFNFKStnZ3RpdGxlKCJNdW5pY2lwaW9zIGRlIFZpY2hhZGEiKQ0KDQpgYGANCg0KDQpgYGB7cn0NCmxpYnJhcnkoc2NhbGVzKQ0KYGBgDQoNClRhbWJpw6luLHBvZGVtb3MgaGFjZXIgcXVlIGNhZGEgbXVuaWNpcGlvIGRlIG51ZXN0cm8gZGVwYXJ0YW1lbnRvIHNlIGNhcmFjdGVyaXplIHBvciB1biBjb2xvciwgZW4gZnVuY2nDs24gZGVsIGPDs2RpZ28gbyBJRA0KDQpgYGB7cn0NCmdncGxvdChWaWNoYWRhKSArIA0KICBnZW9tX3NmKGRhdGE9VmljaGFkYV9wb2ludHMsIGFlcyh4PVgsIHk9WSwgZmlsbCA9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJRF8yKSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC4yNSkgKw0KICBnZW9tX3RleHQoZGF0YSA9IFZpY2hhZGFfcG9pbnRzLCBhZXMoeD1YLCB5PVksbGFiZWwgPSBJRF8yKSwgc2l6ZSA9IDIpICsNCiAgdGhlbWUoYXNwZWN0LnJhdGlvPTEpKw0KICBzY2FsZV9maWxsX2Rpc3RpbGxlcihuYW1lPSJJRF8yIiwgcGFsZXR0ZSA9ICJQdUJ1R24iLCBicmVha3MgPSBwcmV0dHlfYnJlYWtzKG4gPSA1KSkrDQogIGxhYnModGl0bGU9Ik11bmljaXBpb3MgZGUgVmljaGFkYSIpDQpgYGANCg0KQXVucXVlLCBlc3RhcyByZXByZXNlbnRhY2lvbmVzIG5vIHNvbiBtYXBhcyByZWFsZXMsIHBvZGVtb3MgZXhwb3J0YXJsYXMgY29tbyBQREYgbyBlbiBmb3JtYXRvIFBORw0KDQpgYGB7cn0NCmdnc2F2ZSgiVmljaGFkYV9tdW5pY2lwaW9zLnBkZiIpDQpgYGANCg0KYGBge3J9DQpnZ3NhdmUoIm1hcF9WaWNoYWRhLnBuZyIsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNiwgZHBpID0gInNjcmVlbiIpDQpgYGANCg0KDQpVc28gZGUgIExlYWZsZXQgcGFyYSBsYSB2aXN1YWxpemFjacOzbiBkZSBkYXRvcyANCg0KUHJpbWVybyxpbnN0YWxhbW9zIGVsIHByb2dyYW1hIHJlcXVlcmlkbyBwYXJhIHBvc3Rlcmlvcm1lbnRlIGNhcmdhcmxvIA0KYGBge3J9DQpsaWJyYXJ5KGxlYWZsZXQpDQpgYGANCg0KTHVlZ28scGFyYSB1c2FyIGxhIGxpYnJlcmlhIGRlYmVtb3MgY29udmVydGlyIG51ZXN0cm9zIGRhdG9zIGVuIHB1bnRvcyBlc3BhY2lhbGVzDQoNCmBgYHtyfQ0KVmljaGFkYV9wb2ludHMgPC0gYXMoVmljaGFkYV9wb2ludHMsICdTcGF0aWFsJykNCmBgYA0KDQpgYGB7cn0NCiNoZWFkKFZpY2hhZGFfcG9pbnRzKQ0KYGBgDQoNCmBgYHtyfQ0KaW5zdGFsbC5wYWNrYWdlcygibHdnZW9tIikNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkobHdnZW9tKQ0KYGBgDQoNClBvZGVtb3Mgb2J0ZW5lciBlbCA/cmVhIHBvciBtdW5pY2lwaW9zIGRlIGxhIHNpZ3VpZW50ZSBtYW5lcmENCg0KYGBge3J9DQptdW5fVmljaGFkYSRhcmVhIDwtIHN0X2FyZWEobXVuX1ZpY2hhZGEpDQpgYGANCg0KQ2FsY3VsYW1vcyBlbCDDoXJlYSBkZSBjYWRhIG11bmljaXBpbyAoZW4gbWV0cm9zIGN1YWRyYWRvcyk6DQoNCmBgYHtyfQ0KbXVuX1ZpY2hhZGEka20yIDwtIG11bl9WaWNoYWRhJGFyZWEvKDEwMDAwMDApDQpgYGANCg0KQ3JlYW1vcyB1biBudWV2byBjYW1wbyBwYXJhIGVsIGFyZWEgZW4gS2lsb21ldHJvcyBDdWFkcmFkb3MNCg0KYGBge3J9DQptdW5fVmljaGFkYSRrbTINCmBgYA0KRmluYWxtZW50ZSAsIGNvbXByb2JhbW9zIGxhIHNhbGlkYQ0KDQpgYGB7cn0NCm11bl9WaWNoYWRhJGttMg0KYGBgDQoNCkRlIG51ZXZvIGNvbnZlcnRpbW9zIGEgcG9saWdvbm9zIGVzcGFjaWFsZXMNCg0KYGBge3J9DQpWaWNoYWRhX211biA8LSBhcyhtdW5fVmljaGFkYSwgJ1NwYXRpYWwnKQ0KYGBgDQoNClkgbG8gY29tcHJvYmFtb3MNCg0KYGBge3J9DQojaGVhZChWaWNoYWRhX211bikNCmBgYA0KDQpQcmVwYXJhbW9zIG51ZXN0cmEgZ3LDoWZpY2ENCg0KYGBge3J9DQpiaW5zIDwtIGMoMCwgNTAsIDEwMCwgMjAwLCAzMDAsIDUwMCwgMTAwMCwgMjAwMCwgSW5mKQ0KcGFsIDwtIGNvbG9yQmluKCJZbE9yUmQiLCBkb21haW4gPSBWaWNoYWRhX211biRrbTIsIGJpbnMgPSBiaW5zKQ0KDQoNCmxhYmVscyA8LSBtdW5fVmljaGFkYSROQU1FXzINCg0KbGFiZWxzDQpgYGANCmBgYHtyfQ0KbSA8LSBsZWFmbGV0KFZpY2hhZGFfbXVuKSAlPiUNCiAgc2V0VmlldygtNzAuOCwgNCwgNSkgICU+JSBhZGRQb2x5Z29ucygNCiAgZmlsbENvbG9yID0gfnBhbChrbTIpLA0KICB3ZWlnaHQgPSAyLA0KICBvcGFjaXR5ID0gMSwNCiAgY29sb3IgPSAid2hpdGUiLA0KICBkYXNoQXJyYXkgPSAiMyIsDQogIGZpbGxPcGFjaXR5ID0gMC43LA0KICBoaWdobGlnaHQgPSBoaWdobGlnaHRPcHRpb25zKA0KICAgIHdlaWdodCA9IDUsDQogICAgY29sb3IgPSAiIzY2NiIsDQogICAgZGFzaEFycmF5ID0gIiIsDQogICAgZmlsbE9wYWNpdHkgPSAwLjcsDQogICAgYnJpbmdUb0Zyb250ID0gVFJVRSksDQogIGxhYmVsID0gbGFiZWxzKSAlPiUNCiAgYWRkTGVnZW5kKHBhbCA9IHBhbCwgdmFsdWVzID0gfmttMiwgb3BhY2l0eSA9IDAuNywgdGl0bGUgPSBOVUxMLA0KICAgIHBvc2l0aW9uID0gImJvdHRvbXJpZ2h0IikNCmBgYA0KDQpgYGB7cn0NCm0NCmBgYA0KT3RyYSBmb3JtYSBkZSByZXByZXNlbnRhciBudWVzdHJvcyBkYXRvcyBwdWVkZSBzZXIgDQoNCmBgYHtyfQ0KbGVhZmxldCgpICU+JQ0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRFc3JpLldvcmxkSW1hZ2VyeSwgb3B0aW9ucz0gcHJvdmlkZXJUaWxlT3B0aW9ucyhvcGFjaXR5ID0gMC45OSkpICU+JQ0KICBhZGRQb2x5Z29ucyhkYXRhID0gVmljaGFkYV9tdW4sIHBvcHVwPSBWaWNoYWRhX211biROQU1FXzIsDQogICAgc3Ryb2tlID0gVFJVRSwgZmlsbE9wYWNpdHkgPSAwLjI1LCBzbW9vdGhGYWN0b3IgPSAwLjI1DQogICkNCmBgYA0KDQoNCkFob3JhIHVzYXJlbW9zIFNldFZpZXcgcGFyYSBjb25vY2VyIFB1ZXJ0byBDYXJyZcOxbywgbGEgY2FwaXRhbCBkZSBudWVzdHJvIGRlcGFydGFtZW50byANCg0KYGBge3J9DQp2IDwtIGxlYWZsZXQoKSAlPiUgc2V0VmlldyhsbmcgPSAtNjkuMCwgbGF0ID0gNi4xNSwgem9vbSA9IDkpDQp2ICU+JSBhZGRUaWxlcygpDQoNCmBgYA0KDQoNCg0K