Last week, we started talking about spatial operations. This week, we
will work on geometry operations: these are spatial operations that
require us to transform the geometry of our data. As you’ll see, many of
these operations perform similar tasks as the functions we learned last
week. Topic 5 and topic 6 are intended to help you build your toolkit of
spatial operations; next class, we will practice those skills.
#load in packages
library(sf)
library(dplyr)
library(spData)
library(urbnmapr)
library(ggplot2)
#Load in our rivers data
setwd("~/Binghamton/geog380/rivers")
Warning: The working directory was changed to C:/Users/mhaller/Documents/Binghamton/geog380/rivers inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.

#That map is pretty hard to see - let's focus on Broome county
broome <- counties %>% filter(county_name == "Broome County")
broome_hydro <- river_shape[broome,]
ggplot() +
geom_sf(data = broome,
mapping = aes(), color = "lightgray")+
geom_sf(data = broome_hydro,
mapping = aes(), color = "blue")+
theme_minimal()

Our first geometry operation involves simplification - sometimes, we
won’t need a large degree of geographic detail in order to effectively
convey spatial information. Simplified map layers may be easier to
visualize and more efficient to work with than larger, more complex
shape files.
#Let's simplify those lines!
river_simp = st_simplify(broome_hydro, dTolerance = 10000)
ggplot() +
geom_sf(data = broome,
mapping = aes(), color = "lightgray")+
geom_sf(data = river_simp,
mapping = aes(), color = "blue")+
theme_minimal()

Now, let’s compare the two!
a <- ggplot() +
geom_sf(data = broome,
mapping = aes(), color = "lightgray")+
geom_sf(data = broome_hydro,
mapping = aes(), color = "blue")+
theme_minimal()
b <- ggplot() +
geom_sf(data = broome,
mapping = aes(), color = "lightgray")+
geom_sf(data = river_simp,
mapping = aes(), color = "blue")+
theme_minimal()
library(cowplot)
plot_grid(a, b)

Last week, we also learned how to find the centroid of a spatial unit
(e.g. polygon) using st_centroid(). One thing to note is that the most
central point on a polygon doesn’t always fall within that polygon -
here we’ll learn another function that we can use to ensure that our
centroids are within the polygons.
#Create centroids
points <- st_point_on_surface(counties)
Warning: st_point_on_surface assumes attributes are constant over geometries of x
ggplot() +
geom_sf(data = counties,
mapping = aes(), color = "lightgray")+
geom_sf(data = points,
mapping = aes(), color = "blue")+
theme_minimal()

NA
NA
This is what a centroid actually looks like! Again, these become most
useful for calculating distances.
Let’s compare the two methods:
centroids <- st_centroid(counties)
Warning: st_centroid assumes attributes are constant over geometries of x
ggplot() +
geom_sf(data = counties,
mapping = aes(), color = "lightgray")+
geom_sf(data = points,
mapping = aes(color = "Point on Surface"))+
geom_sf(data = centroids, mapping = aes(color = "Centroids"))+
theme_minimal()+
scale_color_manual(labels = c("Point on Surface", "Centroids"),
values = c("blue", "red"))+
labs(color = "Point Type")

Next, we’ll move on to buffers! I’ll show you what it is, and then
we’ll talk about the ways that you might use a buffer. Buffering creates
a new polygon that is within a certain distance of the original, and it
looks like this:
river_buff_500 = st_buffer(broome_hydro, dist = 500)
ggplot() +
geom_sf(data = broome,
mapping = aes(), color = "lightgray")+
geom_sf(data = river_buff_500,
mapping = aes(), color = "yellow")+
geom_sf(data = broome_hydro,
mapping = aes(), color = "blue")+
theme_minimal()

How or why would you use this? Let’s say I am trying to figure out
the location for a new building. I don’t want it to be too close to any
rivers, or flooding would be a risk - I can use a buffer to visualize
locations that are a certain distance (e.g. 1 km) away.
Next, we’ll move on to spatial clipping.

With spatial clipping, I can create a new map layer with its own
geometry based on the intersection of two existing layers. In order to
technically use spatial clipping, we need somewhat complex geometry
types (e.g. lines and polygons - points technically don’t work here). In
this line example, the road lines will be cut off to only retain the
road segments that intersected with rivers.
What makes this a geometry operation? I’m not just selecting features
based on the intersection of two spatial layers - I am creating a new
object with its own unique geometry. That is technically what sets
geometry operations apart from other kinds of spatial operations (don’t
worry though, I won’t quiz you on that).

So, this is helpful, but what if I wanted the actual points where the
bridges are located? This is not technically clipping, but we can do
that, too!


Finally, we’ll look at geometry unions! This will typically involve
aggregating/summarising spatial information at one level (e.g. the
county level) up to a higher scale (e.g. the regional level). For
example, using our NYS data:

Resources
Lovelace, R., Nowosad, J., Muenchow. J. (2019). Geocomputation with
R. Retrieved from: https://geocompr.robinlovelace.net/.
New York State (2022). New York State Statewide Covid-19 Testing.
[Data Set]. Retreived from: https://health.data.ny.gov/Health/New-York-State-Statewide-COVID-19-Testing/xdss-u53e.
NYS GIS Clearinghouse (2022). NYS Streets. [Data Set]. Retrieved
from: http://gis.ny.gov/gisdata/.
NYS GIS Clearinghouse (2022). NYS Hydrography. [Data Set]. Retrieved
from: http://gis.ny.gov/gisdata/.
LS0tDQp0aXRsZTogIkdlb2cgMzgwQSBUb3BpYyA2OiBHZW9tZXRyeSBPcGVyYXRpb25zIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCkxhc3Qgd2Vlaywgd2Ugc3RhcnRlZCB0YWxraW5nIGFib3V0IHNwYXRpYWwgb3BlcmF0aW9ucy4gVGhpcyB3ZWVrLCB3ZSB3aWxsIHdvcmsgb24gZ2VvbWV0cnkgb3BlcmF0aW9uczogdGhlc2UgYXJlIHNwYXRpYWwgb3BlcmF0aW9ucyB0aGF0IHJlcXVpcmUgdXMgdG8gdHJhbnNmb3JtIHRoZSBnZW9tZXRyeSBvZiBvdXIgZGF0YS4gQXMgeW91J2xsIHNlZSwgbWFueSBvZiB0aGVzZSBvcGVyYXRpb25zIHBlcmZvcm0gc2ltaWxhciB0YXNrcyBhcyB0aGUgZnVuY3Rpb25zIHdlIGxlYXJuZWQgbGFzdCB3ZWVrLiBUb3BpYyA1IGFuZCB0b3BpYyA2IGFyZSBpbnRlbmRlZCB0byBoZWxwIHlvdSBidWlsZCB5b3VyIHRvb2xraXQgb2Ygc3BhdGlhbCBvcGVyYXRpb25zOyBuZXh0IGNsYXNzLCB3ZSB3aWxsIHByYWN0aWNlIHRob3NlIHNraWxscy4gDQoNCg0KYGBge3J9DQojbG9hZCBpbiBwYWNrYWdlcw0KbGlicmFyeShzZikgICAgIA0KbGlicmFyeShkcGx5cikgICANCmxpYnJhcnkoc3BEYXRhKSANCmxpYnJhcnkodXJibm1hcHIpDQpsaWJyYXJ5KGdncGxvdDIpDQpgYGANCg0KYGBge3J9DQojTG9hZCBpbiBvdXIgcml2ZXJzIGRhdGENCnNldHdkKCJ+L0JpbmdoYW10b24vZ2VvZzM4MC9yaXZlcnMiKQ0Kcml2ZXJfc2hhcGUgPC0gc3RfcmVhZCgiTGluZWFySHlkcm9ncmFwaHkuc2hwIikNCg0Kcml2ZXJfc2hhcGUgPC0gcml2ZXJfc2hhcGUgJT4lIHN0X3RyYW5zZm9ybSgiRVBTRzozMjExNiIpDQpgYGANCmBgYHtyfQ0KI01hcCBpdCENCg0KI2xvYWQgaW4gTllTIGNvdW50eSBzaGFwZSBmaWxlIGFuZCBzZXQgY3JzDQpjb3VudGllcyA8LSBnZXRfdXJibl9tYXAoImNvdW50aWVzIiwgc2YgPSBUUlVFKQ0KDQojZmlsdGVyIHRoZSBkYXRhIHRvIGdldCBqdXN0IE5ZUw0KY291bnRpZXMgPC0gY291bnRpZXMgJT4lIA0KICBmaWx0ZXIoc3RhdGVfYWJidiA9PSAiTlkiKSAlPiUgDQogIHN0X3RyYW5zZm9ybSgiRVBTRzozMjExNiIpDQoNCiNMZXQncyBtYXAgdGhlbSBub3chDQpnZ3Bsb3QoKSArDQogIGdlb21fc2YoZGF0YSA9IGNvdW50aWVzLA0KICAgIG1hcHBpbmcgPSBhZXMoKSwgY29sb3IgPSAibGlnaHRncmF5IikrDQogIGdlb21fc2YoZGF0YSA9IHJpdmVyX3NoYXBlLA0KICAgICAgICAgIG1hcHBpbmcgPSBhZXMoKSwgY29sb3IgPSAiYmx1ZSIpKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQpgYGB7cn0NCiNUaGF0IG1hcCBpcyBwcmV0dHkgaGFyZCB0byBzZWUgLSBsZXQncyBmb2N1cyBvbiBCcm9vbWUgY291bnR5DQpicm9vbWUgPC0gY291bnRpZXMgJT4lIGZpbHRlcihjb3VudHlfbmFtZSA9PSAiQnJvb21lIENvdW50eSIpDQpicm9vbWVfaHlkcm8gPC0gcml2ZXJfc2hhcGVbYnJvb21lLF0NCg0KZ2dwbG90KCkgKw0KICBnZW9tX3NmKGRhdGEgPSBicm9vbWUsDQogICAgbWFwcGluZyA9IGFlcygpLCBjb2xvciA9ICJsaWdodGdyYXkiKSsNCiAgZ2VvbV9zZihkYXRhID0gYnJvb21lX2h5ZHJvLA0KICAgICAgICAgIG1hcHBpbmcgPSBhZXMoKSwgY29sb3IgPSAiYmx1ZSIpKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQpPdXIgZmlyc3QgZ2VvbWV0cnkgb3BlcmF0aW9uIGludm9sdmVzIHNpbXBsaWZpY2F0aW9uIC0gc29tZXRpbWVzLCB3ZSB3b24ndCBuZWVkIGEgbGFyZ2UgZGVncmVlIG9mIGdlb2dyYXBoaWMgZGV0YWlsIGluIG9yZGVyIHRvIGVmZmVjdGl2ZWx5IGNvbnZleSBzcGF0aWFsIGluZm9ybWF0aW9uLiBTaW1wbGlmaWVkIG1hcCBsYXllcnMgbWF5IGJlIGVhc2llciB0byB2aXN1YWxpemUgYW5kIG1vcmUgZWZmaWNpZW50IHRvIHdvcmsgd2l0aCB0aGFuIGxhcmdlciwgbW9yZSBjb21wbGV4IHNoYXBlIGZpbGVzLiANCmBgYHtyfQ0KI0xldCdzIHNpbXBsaWZ5IHRob3NlIGxpbmVzIQ0KDQpyaXZlcl9zaW1wID0gc3Rfc2ltcGxpZnkoYnJvb21lX2h5ZHJvLCBkVG9sZXJhbmNlID0gMTAwMDApDQoNCmdncGxvdCgpICsNCiAgZ2VvbV9zZihkYXRhID0gYnJvb21lLA0KICAgIG1hcHBpbmcgPSBhZXMoKSwgY29sb3IgPSAibGlnaHRncmF5IikrDQogIGdlb21fc2YoZGF0YSA9IHJpdmVyX3NpbXAsDQogICAgICAgICAgbWFwcGluZyA9IGFlcygpLCBjb2xvciA9ICJibHVlIikrDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCk5vdywgbGV0J3MgY29tcGFyZSB0aGUgdHdvIQ0KDQpgYGB7cn0NCg0KYSA8LSBnZ3Bsb3QoKSArDQogIGdlb21fc2YoZGF0YSA9IGJyb29tZSwNCiAgICBtYXBwaW5nID0gYWVzKCksIGNvbG9yID0gImxpZ2h0Z3JheSIpKw0KICBnZW9tX3NmKGRhdGEgPSBicm9vbWVfaHlkcm8sDQogICAgICAgICAgbWFwcGluZyA9IGFlcygpLCBjb2xvciA9ICJibHVlIikrDQogIHRoZW1lX21pbmltYWwoKQ0KDQpiIDwtIGdncGxvdCgpICsNCiAgZ2VvbV9zZihkYXRhID0gYnJvb21lLA0KICAgIG1hcHBpbmcgPSBhZXMoKSwgY29sb3IgPSAibGlnaHRncmF5IikrDQogIGdlb21fc2YoZGF0YSA9IHJpdmVyX3NpbXAsDQogICAgICAgICAgbWFwcGluZyA9IGFlcygpLCBjb2xvciA9ICJibHVlIikrDQogIHRoZW1lX21pbmltYWwoKQ0KDQpsaWJyYXJ5KGNvd3Bsb3QpDQoNCnBsb3RfZ3JpZChhLCBiKQ0KDQpgYGANCkxhc3Qgd2Vlaywgd2UgYWxzbyBsZWFybmVkIGhvdyB0byBmaW5kIHRoZSBjZW50cm9pZCBvZiBhIHNwYXRpYWwgdW5pdCAoZS5nLiBwb2x5Z29uKSB1c2luZyBzdF9jZW50cm9pZCgpLiBPbmUgdGhpbmcgdG8gbm90ZSBpcyB0aGF0IHRoZSBtb3N0IGNlbnRyYWwgcG9pbnQgb24gYSBwb2x5Z29uIGRvZXNuJ3QgYWx3YXlzIGZhbGwgd2l0aGluIHRoYXQgcG9seWdvbiAtIGhlcmUgd2UnbGwgbGVhcm4gYW5vdGhlciBmdW5jdGlvbiB0aGF0IHdlIGNhbiB1c2UgdG8gZW5zdXJlIHRoYXQgb3VyIGNlbnRyb2lkcyBhcmUgd2l0aGluIHRoZSBwb2x5Z29ucy4NCmBgYHtyfQ0KDQojQ3JlYXRlIGNlbnRyb2lkcw0KcG9pbnRzIDwtIHN0X3BvaW50X29uX3N1cmZhY2UoY291bnRpZXMpDQoNCiBnZ3Bsb3QoKSArDQogIGdlb21fc2YoZGF0YSA9IGNvdW50aWVzLA0KICAgIG1hcHBpbmcgPSBhZXMoKSwgY29sb3IgPSAibGlnaHRncmF5IikrDQogIGdlb21fc2YoZGF0YSA9IHBvaW50cywNCiAgICAgICAgICBtYXBwaW5nID0gYWVzKCksIGNvbG9yID0gImJsdWUiKSsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCg0KYGBgDQpUaGlzIGlzIHdoYXQgYSBjZW50cm9pZCBhY3R1YWxseSBsb29rcyBsaWtlISBBZ2FpbiwgdGhlc2UgYmVjb21lIG1vc3QgdXNlZnVsIGZvciBjYWxjdWxhdGluZyBkaXN0YW5jZXMuIA0KDQpMZXQncyBjb21wYXJlIHRoZSB0d28gbWV0aG9kczoNCg0KYGBge3J9DQoNCmNlbnRyb2lkcyA8LSBzdF9jZW50cm9pZChjb3VudGllcykNCg0KZ2dwbG90KCkgKw0KICBnZW9tX3NmKGRhdGEgPSBjb3VudGllcywNCiAgICBtYXBwaW5nID0gYWVzKCksIGNvbG9yID0gImxpZ2h0Z3JheSIpKw0KICBnZW9tX3NmKGRhdGEgPSBwb2ludHMsDQogICAgICAgICAgbWFwcGluZyA9IGFlcyhjb2xvciA9ICJQb2ludCBvbiBTdXJmYWNlIikpKw0KICBnZW9tX3NmKGRhdGEgPSBjZW50cm9pZHMsIG1hcHBpbmcgPSBhZXMoY29sb3IgPSAiQ2VudHJvaWRzIikpKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHNjYWxlX2NvbG9yX21hbnVhbChsYWJlbHMgPSBjKCJQb2ludCBvbiBTdXJmYWNlIiwgIkNlbnRyb2lkcyIpLA0KICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYygiYmx1ZSIsICJyZWQiKSkrDQogIGxhYnMoY29sb3IgPSAiUG9pbnQgVHlwZSIpDQpgYGANCg0KDQpOZXh0LCB3ZSdsbCBtb3ZlIG9uIHRvIGJ1ZmZlcnMhIEknbGwgc2hvdyB5b3Ugd2hhdCBpdCBpcywgYW5kIHRoZW4gd2UnbGwgdGFsayBhYm91dCB0aGUgd2F5cyB0aGF0IHlvdSBtaWdodCB1c2UgYSBidWZmZXIuIEJ1ZmZlcmluZyBjcmVhdGVzIGEgbmV3IHBvbHlnb24gdGhhdCBpcyB3aXRoaW4gYSBjZXJ0YWluIGRpc3RhbmNlIG9mIHRoZSBvcmlnaW5hbCwgYW5kIGl0IGxvb2tzIGxpa2UgdGhpczoNCg0KYGBge3J9DQpyaXZlcl9idWZmXzUwMCA9IHN0X2J1ZmZlcihicm9vbWVfaHlkcm8sIGRpc3QgPSA1MDApDQoNCg0KZ2dwbG90KCkgKw0KICBnZW9tX3NmKGRhdGEgPSBicm9vbWUsDQogICAgbWFwcGluZyA9IGFlcygpLCBjb2xvciA9ICJsaWdodGdyYXkiKSsNCiAgICBnZW9tX3NmKGRhdGEgPSByaXZlcl9idWZmXzUwMCwNCiAgICAgICAgICBtYXBwaW5nID0gYWVzKCksIGNvbG9yID0gInllbGxvdyIpKw0KICBnZW9tX3NmKGRhdGEgPSBicm9vbWVfaHlkcm8sDQogICAgICAgICAgbWFwcGluZyA9IGFlcygpLCBjb2xvciA9ICJibHVlIikrDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQpIb3cgb3Igd2h5IHdvdWxkIHlvdSB1c2UgdGhpcz8gTGV0J3Mgc2F5IEkgYW0gdHJ5aW5nIHRvIGZpZ3VyZSBvdXQgdGhlIGxvY2F0aW9uIGZvciBhIG5ldyBidWlsZGluZy4gSSBkb24ndCB3YW50IGl0IHRvIGJlIHRvbyBjbG9zZSB0byBhbnkgcml2ZXJzLCBvciBmbG9vZGluZyB3b3VsZCBiZSBhIHJpc2sgLSBJIGNhbiB1c2UgYSBidWZmZXIgdG8gdmlzdWFsaXplIGxvY2F0aW9ucyB0aGF0IGFyZSBhIGNlcnRhaW4gZGlzdGFuY2UgKGUuZy4gMSBrbSkgYXdheS4gDQoNCk5leHQsIHdlJ2xsIG1vdmUgb24gdG8gc3BhdGlhbCBjbGlwcGluZy4gDQoNCmBgYHtyfQ0Kc2V0d2QoIn4vQmluZ2hhbXRvbi9nZW9nMzgwL1NpbXBsaWZpZWRTdHJlZXRzX1NIUCIpDQpzdHJlZXRfc2hhcGUgPC0gc3RfcmVhZCgiU2ltcGxpZmllZFN0cmVldFNlZ21lbnRRcnQuc2hwIikNCg0Kc3RyZWV0X3NoYXBlIDwtIHN0cmVldF9zaGFwZSAlPiUgc3RfdHJhbnNmb3JtKCJFUFNHOjMyMTE2IikNCmJyb29tZV9zdHJlZXRzIDwtIHN0cmVldF9zaGFwZVticm9vbWUsICwgb3AgPSBzdF93aXRoaW5dDQpicm9vbWVfc3RyZWV0czEgPC0gc3RyZWV0X3NoYXBlW2Jyb29tZSwgLCBvcCA9IHN0X2ludGVyc2VjdHNdDQoNCmdncGxvdCgpICsNCiAgZ2VvbV9zZihkYXRhID0gYnJvb21lLA0KICAgIG1hcHBpbmcgPSBhZXMoKSwgY29sb3IgPSAibGlnaHRncmF5IikrDQogIGdlb21fc2YoZGF0YSA9IGJyb29tZV9zdHJlZXRzLA0KICAgICAgICAgIG1hcHBpbmcgPSBhZXMoKSwgY29sb3IgPSAiZ3JheTEwIikrDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQpXaXRoIHNwYXRpYWwgY2xpcHBpbmcsIEkgY2FuIGNyZWF0ZSBhIG5ldyBtYXAgbGF5ZXIgd2l0aCBpdHMgb3duIGdlb21ldHJ5IGJhc2VkIG9uIHRoZSBpbnRlcnNlY3Rpb24gb2YgdHdvIGV4aXN0aW5nIGxheWVycy4gSW4gb3JkZXIgdG8gdGVjaG5pY2FsbHkgdXNlIHNwYXRpYWwgY2xpcHBpbmcsIHdlIG5lZWQgc29tZXdoYXQgY29tcGxleCBnZW9tZXRyeSB0eXBlcyAoZS5nLiBsaW5lcyBhbmQgcG9seWdvbnMgLSBwb2ludHMgdGVjaG5pY2FsbHkgZG9uJ3Qgd29yayBoZXJlKS4gSW4gdGhpcyBsaW5lIGV4YW1wbGUsIHRoZSByb2FkIGxpbmVzIHdpbGwgYmUgY3V0IG9mZiB0byBvbmx5IHJldGFpbiB0aGUgcm9hZCBzZWdtZW50cyB0aGF0IGludGVyc2VjdGVkIHdpdGggcml2ZXJzLg0KDQpXaGF0IG1ha2VzIHRoaXMgYSBnZW9tZXRyeSBvcGVyYXRpb24/IEknbSBub3QganVzdCBzZWxlY3RpbmcgZmVhdHVyZXMgYmFzZWQgb24gdGhlIGludGVyc2VjdGlvbiBvZiB0d28gc3BhdGlhbCBsYXllcnMgLSBJIGFtIGNyZWF0aW5nIGEgbmV3IG9iamVjdCB3aXRoIGl0cyBvd24gdW5pcXVlIGdlb21ldHJ5LiBUaGF0IGlzIHRlY2huaWNhbGx5IHdoYXQgc2V0cyBnZW9tZXRyeSBvcGVyYXRpb25zIGFwYXJ0IGZyb20gb3RoZXIga2luZHMgb2Ygc3BhdGlhbCBvcGVyYXRpb25zIChkb24ndCB3b3JyeSB0aG91Z2gsIEkgd29uJ3QgcXVpeiB5b3Ugb24gdGhhdCkuDQoNCmBgYHtyfQ0KI0xldCdzIGdldCBicmlkZ2VzIGluIEJyb29tZSBjb3VudHkNCmJyaWRnZXMgPSBsZW5ndGhzKHN0X2ludGVyc2VjdHMoYnJvb21lX2h5ZHJvLCBicm9vbWVfc3RyZWV0cykpID4gMA0KDQpicm9vbWVfYnJpZGdlcyA8LSBicm9vbWVfaHlkcm9bYnJpZGdlcyxdDQoNCmdncGxvdCgpICsNCiAgZ2VvbV9zZihkYXRhID0gYnJvb21lLA0KICAgIG1hcHBpbmcgPSBhZXMoKSwgY29sb3IgPSAibGlnaHRncmF5IikrDQogIGdlb21fc2YoZGF0YSA9IGJyb29tZV9zdHJlZXRzLCBtYXBwaW5nID0gYWVzKCksIGNvbG9yID0gImdyYXkiKSsNCiAgICBnZW9tX3NmKGRhdGEgPSBicm9vbWVfaHlkcm8sDQogICAgICAgICAgbWFwcGluZyA9IGFlcygpLCBjb2xvciA9ICJibHVlIikrDQogICAgZ2VvbV9zZihkYXRhID0gYnJvb21lX2JyaWRnZXMsDQogICAgICAgICAgbWFwcGluZyA9IGFlcygpLCBjb2xvciA9ICJicm93biIsIHNpemUgPSAxLjIpKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQpTbywgdGhpcyBpcyBoZWxwZnVsLCBidXQgd2hhdCBpZiBJIHdhbnRlZCB0aGUgYWN0dWFsIHBvaW50cyB3aGVyZSB0aGUgYnJpZGdlcyBhcmUgbG9jYXRlZD8gVGhpcyBpcyBub3QgdGVjaG5pY2FsbHkgY2xpcHBpbmcsIGJ1dCB3ZSBjYW4gZG8gdGhhdCwgdG9vIQ0KDQpgYGB7cn0NCiNGaXJzdCwgSSBuZWVkIHRvIGNvbnZlcnQgbXkgcml2ZXIgbGF5ZXIgZnJvbSBsaW5lcyB0byBwb2ludHMgLSB3ZSdsbCB1c2UgdGhlIGludGVyc2VjdGlvbiBvZiB0aGVzZSBwb2ludHMgdG8gZmluZCBicmlkZ2UgbG9jYXRpb25zDQpyaXZlcl9wb2ludHMgPSBzdF9jYXN0KGJyb29tZV9oeWRybywgIlBPSU5UIikNCg0KZ2dwbG90KCkgKw0KICBnZW9tX3NmKGRhdGEgPSBicm9vbWUsDQogICAgbWFwcGluZyA9IGFlcygpLCBjb2xvciA9ICJsaWdodGdyYXkiKSsNCiAgICBnZW9tX3NmKGRhdGEgPSByaXZlcl9wb2ludHMsDQogICAgICAgICAgbWFwcGluZyA9IGFlcygpLCBjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDAuMikrDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQpgYGB7cn0NCiNDcmVhdGUgYSBsb2dpY2FsIHZlY3RvciB0byBzdWJzZXQgb3VyIHJpdmVyIHBvaW50cyBsYXllciBieSAtIHRoaXMgaXMgZXF1YWwgdG8gVFJVRSBpZiB0aGUgcG9pbnRzIGxheWVyIGFuZCBicm9vbWUgc3RyZWV0cyBpbnRlcnNlY3QsIGFuZCBGQUxTRSBvdGhlcndpc2UNCiNIZXJlIHdlIGFyZSBmaW5kaW5nIGFsbCB0aGUgcG9pbnRzIHRoYXQgaW50ZXJzZWN0IHdpdGggYnJvb21lIHN0cmVldHMgLSBpZiBhIHBvaW50IGludGVyc2VjdHMsIGluIHRoZSByZXN1bHQgaXQgd2lsbCBoYXZlIGEgbGVuZ3RoID4gMA0KI0NyZWF0ZSBhIGxvZ2ljYWwgdmVjdG9yIGJhc2VkIG9uIHdoZXRoZXIgdGhlIGxlbmdodGhzIGFyZSBncmVhdGVyIHRoYW4gMA0KYnJpZGdlcyA9IGxlbmd0aHMoc3RfaW50ZXJzZWN0cyhyaXZlcl9wb2ludHMsIGJyb29tZV9zdHJlZXRzKSkgPiAwDQoNCmJyaWRnZXNfbmV3IDwtIHJpdmVyX3BvaW50c1ticmlkZ2VzLF0NCg0KZ2dwbG90KCkgKw0KICBnZW9tX3NmKGRhdGEgPSBicm9vbWUsDQogICAgbWFwcGluZyA9IGFlcygpLCBjb2xvciA9ICJsaWdodGdyYXkiKSsNCiAgICBnZW9tX3NmKGRhdGEgPSBicmlkZ2VzX25ldywNCiAgICAgICAgICBtYXBwaW5nID0gYWVzKCksIGNvbG9yID0gImJyb3duIiwgc2l6ZSA9IDEuMikrDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCkZpbmFsbHksIHdlJ2xsIGxvb2sgYXQgZ2VvbWV0cnkgdW5pb25zISBUaGlzIHdpbGwgdHlwaWNhbGx5IGludm9sdmUgYWdncmVnYXRpbmcvc3VtbWFyaXNpbmcgc3BhdGlhbCBpbmZvcm1hdGlvbiBhdCBvbmUgbGV2ZWwgKGUuZy4gdGhlIGNvdW50eSBsZXZlbCkgdXAgdG8gYSBoaWdoZXIgc2NhbGUgKGUuZy4gdGhlIHJlZ2lvbmFsIGxldmVsKS4gRm9yIGV4YW1wbGUsIHVzaW5nIG91ciBOWVMgZGF0YToNCg0KYGBge3J9DQojTG9hZCBpbiBDb3ZpZCBkYXRhIHdpdGggcmVnaW9uIGluZm9ybWF0aW9uDQpzZXR3ZCgifi9CaW5naGFtdG9uL2dlb2czODAiKQ0KY292aWQgPC0gcmVhZC5jc3YoImNvdmlkX2RhdGFfbnkuY3N2IikNCg0KbGlicmFyeSh0aWR5cikNCmNvdW50aWVzMSA8LSBjb3VudGllcyAlPiUgDQogIHNlcGFyYXRlKGNvdW50eV9uYW1lLCBjKCJjb3VudHlfbmFtZSIsICJjb3VudHkiKSwgc2VwID0gIiBDb3VudHkiKSAlPiUgDQogIHNlbGVjdCgtY291bnR5KQ0KDQpjb3VudGllczEgPC0gY291bnRpZXMxICU+JQ0KICBsZWZ0X2pvaW4oY292aWQsIGJ5ID0gYygiY291bnR5X25hbWUiID0gIkNvdW50eSIpKQ0KDQojSSBkb24ndCBhY3R1YWxseSBjYXJlIGFib3V0IENvdmlkIGNhc2VzIC0gc3VtbWFyaXNlIGNvdmlkIGNhc2VzIHRvIGdldCBvdXIgc3BhdGlhbCBkYXRhIGdyb3VwZWQgYnkgcmVnaW9uDQpyZWdpb25zIDwtIGNvdW50aWVzMSAlPiUgZ3JvdXBfYnkocmVnaW9uKSAlPiUNCiAgc3VtbWFyaXplKGNhc2VzID0gc3VtKG5ld19wb3NpdGl2ZSwgbmEucm0gPSBUUlVFKSkNCg0KI25vdyB3ZSdsbCBtYXAgaXQhDQpnZ3Bsb3QoKSArDQogIGdlb21fc2YoZGF0YSA9IHJlZ2lvbnMsDQogICAgbWFwcGluZyA9IGFlcyhmaWxsID0gcmVnaW9uKSkrDQogIGdlb21fc2YoZGF0YSA9IGNvdW50aWVzLCBtYXBwaW5nID0gYWVzKCksIGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvciA9ICJ3aGl0ZSIpKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIGxhYnMoZmlsbCA9ICJSZWdpb24iLCB0aXRsZSA9ICJSZWdpb25zIG9mIE5ZUyIpKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkNCg0KYGBgDQpSZXNvdXJjZXMgDQoNCkxvdmVsYWNlLCBSLiwgTm93b3NhZCwgSi4sIE11ZW5jaG93LiBKLiAoMjAxOSkuIEdlb2NvbXB1dGF0aW9uIHdpdGggUi4gUmV0cmlldmVkIGZyb206IGh0dHBzOi8vZ2VvY29tcHIucm9iaW5sb3ZlbGFjZS5uZXQvLg0KDQpOZXcgWW9yayBTdGF0ZSAoMjAyMikuIE5ldyBZb3JrIFN0YXRlIFN0YXRld2lkZSBDb3ZpZC0xOSBUZXN0aW5nLiBbRGF0YSBTZXRdLiBSZXRyZWl2ZWQgZnJvbTogaHR0cHM6Ly9oZWFsdGguZGF0YS5ueS5nb3YvSGVhbHRoL05ldy1Zb3JrLVN0YXRlLVN0YXRld2lkZS1DT1ZJRC0xOS1UZXN0aW5nL3hkc3MtdTUzZS4gDQoNCk5ZUyBHSVMgQ2xlYXJpbmdob3VzZSAoMjAyMikuIE5ZUyBTdHJlZXRzLiBbRGF0YSBTZXRdLiBSZXRyaWV2ZWQgZnJvbTogaHR0cDovL2dpcy5ueS5nb3YvZ2lzZGF0YS8uIA0KDQpOWVMgR0lTIENsZWFyaW5naG91c2UgKDIwMjIpLiBOWVMgSHlkcm9ncmFwaHkuIFtEYXRhIFNldF0uIFJldHJpZXZlZCBmcm9tOiBodHRwOi8vZ2lzLm55Lmdvdi9naXNkYXRhLy4gDQo=