├── 2020
├── Code
│ ├── 01_points
│ │ ├── 01_points.R
│ │ └── 01_points.png
│ ├── 02_lines
│ │ ├── 02_lines.R
│ │ ├── 02_lines.pdf
│ │ └── 02_lines.png
│ ├── 03_Polygons
│ │ ├── 03_polygons.R
│ │ └── 03_polygons.png
│ ├── 07_green
│ │ ├── 07_green.R
│ │ └── 07_green.png
│ ├── 08_yellow
│ │ ├── 08_yellow.R
│ │ └── 08_yellow.png
│ └── 20_population
│ │ ├── 20_map-img.png
│ │ ├── 20_map.gif
│ │ └── population.R
└── Data
│ ├── 01_chipotle_stores.csv
│ ├── 07_streetlight.csv
│ ├── 20_Israel-pop.csv
│ └── Israel-map
│ ├── 00_Israel_0_sf.rds
│ ├── gadm36_ISR_0_sf.rds
│ ├── gadm36_ISR_0_sp.rds
│ └── gadm36_ISR_1_sf.rds
├── 2021
├── 01_points
│ ├── 01_points.R
│ └── trees.png
├── 02_lines
│ ├── lines.R
│ ├── lines.html
│ ├── lines.png
│ └── lines_files
│ │ ├── Proj4Leaflet-1.0.1
│ │ └── proj4leaflet.js
│ │ ├── htmlwidgets-1.5.4
│ │ └── htmlwidgets.js
│ │ ├── jquery-1.12.4
│ │ └── jquery.min.js
│ │ ├── leaflet-1.3.1
│ │ ├── images
│ │ │ ├── layers-2x.png
│ │ │ ├── layers.png
│ │ │ ├── marker-icon-2x.png
│ │ │ ├── marker-icon.png
│ │ │ └── marker-shadow.png
│ │ ├── leaflet.css
│ │ └── leaflet.js
│ │ ├── leaflet-binding-2.0.4.1
│ │ └── leaflet.js
│ │ ├── leaflet-providers-1.9.0
│ │ └── leaflet-providers_1.9.0.js
│ │ ├── leaflet-providers-plugin-2.0.4.1
│ │ └── leaflet-providers-plugin.js
│ │ ├── leafletfix-1.0.0
│ │ └── leafletfix.css
│ │ ├── proj4-2.6.2
│ │ └── proj4.min.js
│ │ └── rstudio_leaflet-1.3.1
│ │ ├── images
│ │ └── 1px.png
│ │ └── rstudio_leaflet.css
├── 03_polygons
│ ├── trains.R
│ └── trains.png
├── 04_hexagons
│ ├── busstops.R
│ └── stops.png
├── 05_osm
│ ├── street.png
│ └── streets.R
├── 06_red
│ ├── index.html
│ ├── map-screenshot.png
│ └── shelters.geojson
├── 07_green
│ ├── bikelanes.R
│ └── bikelanes.png
├── 08_blue
│ ├── wave.R
│ └── wave.png
├── 09_monochrome
│ ├── israelbw.png
│ └── monochrome.R
├── 10_raster
│ ├── walk_from_dizengof.html
│ ├── walk_from_dizengof_files
│ │ ├── Proj4Leaflet-1.0.1
│ │ │ └── proj4leaflet.js
│ │ ├── htmlwidgets-1.5.4
│ │ │ └── htmlwidgets.js
│ │ ├── jquery-1.12.4
│ │ │ └── jquery.min.js
│ │ ├── leaflet-1.3.1
│ │ │ ├── images
│ │ │ │ ├── layers-2x.png
│ │ │ │ ├── layers.png
│ │ │ │ ├── marker-icon-2x.png
│ │ │ │ ├── marker-icon.png
│ │ │ │ └── marker-shadow.png
│ │ │ ├── leaflet.css
│ │ │ └── leaflet.js
│ │ ├── leaflet-binding-2.0.4.1
│ │ │ └── leaflet.js
│ │ ├── leafletfix-1.0.0
│ │ │ └── leafletfix.css
│ │ ├── proj4-2.6.2
│ │ │ └── proj4.min.js
│ │ └── rstudio_leaflet-1.3.1
│ │ │ ├── images
│ │ │ └── 1px.png
│ │ │ └── rstudio_leaflet.css
│ ├── walking.R
│ └── walking.png
├── 11_3d
│ ├── 3d.R
│ └── ramon.png
├── 13_natural-earth
│ ├── visited.R
│ └── visited.png
├── 17_land
│ ├── land.R
│ └── ta_area.png
├── 2021.Rproj
├── 20_movement
│ ├── ice-cream.html
│ ├── ice-cream_farthest.png
│ ├── ice-cream_files
│ │ ├── Proj4Leaflet-1.0.1
│ │ │ └── proj4leaflet.js
│ │ ├── htmlwidgets-1.5.4
│ │ │ └── htmlwidgets.js
│ │ ├── jquery-1.12.4
│ │ │ └── jquery.min.js
│ │ ├── leaflet-1.3.1
│ │ │ ├── images
│ │ │ │ ├── layers-2x.png
│ │ │ │ ├── layers.png
│ │ │ │ ├── marker-icon-2x.png
│ │ │ │ ├── marker-icon.png
│ │ │ │ └── marker-shadow.png
│ │ │ ├── leaflet.css
│ │ │ └── leaflet.js
│ │ ├── leaflet-binding-2.0.4.1
│ │ │ └── leaflet.js
│ │ ├── leaflet-providers-1.9.0
│ │ │ └── leaflet-providers_1.9.0.js
│ │ ├── leaflet-providers-plugin-2.0.4.1
│ │ │ └── leaflet-providers-plugin.js
│ │ ├── leafletfix-1.0.0
│ │ │ └── leafletfix.css
│ │ ├── proj4-2.6.2
│ │ │ └── proj4.min.js
│ │ └── rstudio_leaflet-1.3.1
│ │ │ ├── images
│ │ │ └── 1px.png
│ │ │ └── rstudio_leaflet.css
│ ├── ice-cream_two_opt.png
│ └── icecream.R
├── 22_borders
│ ├── borders.R
│ └── borders.png
├── 25_interactive
│ ├── elderly.html
│ ├── elderly.png
│ ├── elderly_files
│ │ ├── Proj4Leaflet-1.0.1
│ │ │ └── proj4leaflet.js
│ │ ├── htmlwidgets-1.5.4
│ │ │ └── htmlwidgets.js
│ │ ├── jquery-1.12.4
│ │ │ └── jquery.min.js
│ │ ├── leaflet-1.3.1
│ │ │ ├── images
│ │ │ │ ├── layers-2x.png
│ │ │ │ ├── layers.png
│ │ │ │ ├── marker-icon-2x.png
│ │ │ │ ├── marker-icon.png
│ │ │ │ └── marker-shadow.png
│ │ │ ├── leaflet.css
│ │ │ └── leaflet.js
│ │ ├── leaflet-binding-2.0.4.1
│ │ │ └── leaflet.js
│ │ ├── leaflet-providers-1.9.0
│ │ │ └── leaflet-providers_1.9.0.js
│ │ ├── leaflet-providers-plugin-2.0.4.1
│ │ │ └── leaflet-providers-plugin.js
│ │ ├── leafletfix-1.0.0
│ │ │ └── leafletfix.css
│ │ ├── proj4-2.6.2
│ │ │ └── proj4.min.js
│ │ └── rstudio_leaflet-1.3.1
│ │ │ ├── images
│ │ │ └── 1px.png
│ │ │ └── rstudio_leaflet.css
│ └── src.R
├── data
│ ├── Crime-map-2016_2021.xlsx
│ ├── golda_locations.xlsx
│ ├── ta-shapefile
│ │ ├── gv_Tel_Aviv-Yafo_27.10.14.dbf
│ │ ├── gv_Tel_Aviv-Yafo_27.10.14.jgw
│ │ ├── gv_Tel_Aviv-Yafo_27.10.14.shp
│ │ └── gv_Tel_Aviv-Yafo_27.10.14.shx
│ ├── tatrees
│ │ ├── %D7%A2%D7%A6%D7%99_%D7%9E%D7%95%D7%A8%D7%A9%D7%AA.cpg
│ │ ├── %D7%A2%D7%A6%D7%99_%D7%9E%D7%95%D7%A8%D7%A9%D7%AA.dbf
│ │ ├── %D7%A2%D7%A6%D7%99_%D7%9E%D7%95%D7%A8%D7%A9%D7%AA.prj
│ │ ├── %D7%A2%D7%A6%D7%99_%D7%9E%D7%95%D7%A8%D7%A9%D7%AA.shp
│ │ ├── %D7%A2%D7%A6%D7%99_%D7%9E%D7%95%D7%A8%D7%A9%D7%AA.shx
│ │ ├── %D7%A2%D7%A6%D7%99_%D7%9E%D7%95%D7%A8%D7%A9%D7%AA.xml
│ │ └── trees.csv
│ └── wave
│ │ ├── export.kml
│ │ ├── export.xlsx
│ │ ├── tsunami 5 meter line.cpg
│ │ ├── tsunami 5 meter line.dbf
│ │ ├── tsunami 5 meter line.prj
│ │ ├── tsunami 5 meter line.shp
│ │ └── tsunami 5 meter line.shx
└── messing-around
│ ├── ggmap.png
│ ├── ggmap_polygon.png
│ ├── ggmap_polygon_clean.png
│ ├── israel.png
│ ├── israelpre67.png
│ ├── leaflet.png
│ ├── leaflet_files
│ ├── Proj4Leaflet-1.0.1
│ │ └── proj4leaflet.js
│ ├── htmlwidgets-1.5.4
│ │ └── htmlwidgets.js
│ ├── jquery-1.12.4
│ │ └── jquery.min.js
│ ├── leaflet-1.3.1
│ │ ├── images
│ │ │ ├── layers-2x.png
│ │ │ ├── layers.png
│ │ │ ├── marker-icon-2x.png
│ │ │ ├── marker-icon.png
│ │ │ └── marker-shadow.png
│ │ ├── leaflet.css
│ │ └── leaflet.js
│ ├── leaflet-binding-2.0.4.1
│ │ └── leaflet.js
│ ├── leafletfix-1.0.0
│ │ └── leafletfix.css
│ ├── proj4-2.6.2
│ │ └── proj4.min.js
│ └── rstudio_leaflet-1.3.1
│ │ ├── images
│ │ └── 1px.png
│ │ └── rstudio_leaflet.css
│ ├── telaviv_tmap.png
│ └── warmup.R
├── 2022
├── 01_points
│ ├── .ipynb_checkpoints
│ │ ├── Polling address to Geolocation-checkpoint.ipynb
│ │ └── polling_address_to_geo-checkpoint.ipynb
│ ├── 01_points.R
│ ├── 01_polling_locations.png
│ ├── map.png
│ ├── polling_address_to_geo.html
│ ├── polling_address_to_geo.ipynb
│ ├── polling_address_to_geo_files
│ │ └── libs
│ │ │ ├── bootstrap
│ │ │ ├── bootstrap-icons.css
│ │ │ ├── bootstrap-icons.woff
│ │ │ ├── bootstrap.min.css
│ │ │ └── bootstrap.min.js
│ │ │ ├── clipboard
│ │ │ └── clipboard.min.js
│ │ │ └── quarto-html
│ │ │ ├── anchor.min.js
│ │ │ ├── popper.min.js
│ │ │ ├── quarto-syntax-highlighting.css
│ │ │ ├── quarto.js
│ │ │ ├── tippy.css
│ │ │ └── tippy.umd.min.js
│ ├── polling_station_rehovot.csv
│ └── rehovot_polls.xlsx
├── 02_lines
│ ├── lines.html
│ ├── lines.png
│ ├── lines_files
│ │ ├── Proj4Leaflet-1.0.1
│ │ │ └── proj4leaflet.js
│ │ ├── htmlwidgets-1.5.4
│ │ │ └── htmlwidgets.js
│ │ ├── jquery-1.12.4
│ │ │ └── jquery.min.js
│ │ ├── leaflet-1.3.1
│ │ │ ├── images
│ │ │ │ ├── layers-2x.png
│ │ │ │ ├── layers.png
│ │ │ │ ├── marker-icon-2x.png
│ │ │ │ ├── marker-icon.png
│ │ │ │ └── marker-shadow.png
│ │ │ ├── leaflet.css
│ │ │ └── leaflet.js
│ │ ├── leaflet-binding-2.1.1
│ │ │ └── leaflet.js
│ │ ├── leaflet-providers-1.9.0
│ │ │ └── leaflet-providers_1.9.0.js
│ │ ├── leaflet-providers-plugin-2.1.1
│ │ │ └── leaflet-providers-plugin.js
│ │ ├── leafletfix-1.0.0
│ │ │ └── leafletfix.css
│ │ ├── proj4-2.6.2
│ │ │ └── proj4.min.js
│ │ └── rstudio_leaflet-1.3.1
│ │ │ ├── images
│ │ │ └── 1px.png
│ │ │ └── rstudio_leaflet.css
│ └── routes.R
├── 03_polygons
│ ├── 03_polygons.R
│ ├── all_rides.rds
│ ├── area_distribution.png
│ ├── area_distribution_updated.png
│ ├── bus_stops.png
│ ├── bus_stops_updated.png
│ └── stops_in_rehovot.rds
├── 07_raster
│ ├── 07_raster.R
│ ├── elevation.png
│ └── elevation_high_res.png
├── 08_osm
│ ├── .ipynb_checkpoints
│ │ └── 08_osm-checkpoint.ipynb
│ ├── 08_osm.ipynb
│ ├── rehovot.png
│ └── rehovot_sf
│ │ ├── gv_Rehovot_2016_plt.dbf
│ │ ├── gv_Rehovot_2016_plt.prj
│ │ ├── gv_Rehovot_2016_plt.shp
│ │ └── gv_Rehovot_2016_plt.shx
└── 14_hexagons
│ ├── 14_hexagons.R
│ ├── 14_hexagons_accidents.R
│ ├── accidents.png
│ ├── biking.rds
│ └── driving.rds
├── .gitignore
├── 30daymapchallenge.Rproj
├── README.md
├── data
└── maps
│ ├── 00_Israel_0_sf.rds
│ ├── gadm36_ISR_0_sf.rds
│ ├── gadm36_ISR_0_sp.rds
│ ├── gadm36_ISR_1_sf.rds
│ └── isr-full
│ ├── israel_borders.dbf
│ ├── israel_borders.prj
│ ├── israel_borders.sbn
│ ├── israel_borders.sbx
│ ├── israel_borders.shp
│ ├── israel_borders.shp.xml
│ └── israel_borders.shx
└── expc.csv
/.gitignore:
--------------------------------------------------------------------------------
1 | .Rproj.user
2 | .Rhistory
3 | .RData
4 | .Ruserdata
5 |
6 | data/maps/judicial
7 |
8 | *.pptx
--------------------------------------------------------------------------------
/2020/Code/01_points/01_points.R:
--------------------------------------------------------------------------------
1 | library(ggplot2)
2 | library(readr)
3 | library(maps)
4 | library(cowplot)
5 | library(ggforce)
6 | library(extrafont)
7 | library(emoGG)
8 |
9 | us_states <- map_data("state")
10 | dat <- read_csv("data/01_chipotle_stores.csv")
11 |
12 | # Highlight specific point
13 | point <- data.frame(lon = -77.1378, lat = 39.07526, label = "My most frequently visited location throughout my stay in the US", title = "865 Rockville Pike, Rockville, MD")
14 |
15 | ggplot(data = us_states, mapping = aes(x = long, y = lat, group = group))+
16 | geom_polygon(fill = "grey85",color = "white", size = 0.5)+
17 | geom_point(data = dat, aes(x = longitude, y = latitude, group = 1), color = "#451400", size = 0.3)+
18 | coord_map(projection = 'albers', lat0 = 39, lat1 = 45)+
19 | theme_map()+
20 | labs(title = "Chipotle locations across the US", caption = "#30DayMapChallenge | Day: 01\nData: Kaggle | @Amit_Levinson")+
21 | geom_mark_circle(data = point, mapping = aes(x = lon, y= lat, label = title, description = label, group = 1), radius = unit(0.01, "mm"),
22 | label.family = c("Segoe UI Black", "Segoe UI"), label.fontsize = c(10,9), label.colour = c("#451400", "#451400"), con.border = "none",
23 | con.colour = "grey55", expand = unit(0.01, "mm"), label.buffer = unit(30, "mm"), label.fill = "transparent", color = "white")+
24 | geom_emoji(data = point, aes(x = lon, y = lat, group = 1), emoji = "1f4cd", size = 0.02)+
25 | theme(
26 | plot.title = element_text(color = "#451400", hjust = 0.5, size = 24, family = "Segoe UI Black"),
27 | plot.caption = element_text(color = "#451400", hjust = 1, size = 8, family = "Segoe UI Light")
28 | )
29 |
30 | ggsave("01_points/01_points.png", width = 10, height = 8)
31 |
32 | #Data set from:
33 | # https://www.kaggle.com/navneethc/chipotle
--------------------------------------------------------------------------------
/2020/Code/01_points/01_points.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2020/Code/01_points/01_points.png
--------------------------------------------------------------------------------
/2020/Code/02_lines/02_lines.R:
--------------------------------------------------------------------------------
1 | library(tidyverse)
2 | library(osmdata)
3 | library(sf)
4 | library(extrafont)
5 | library(pdftools)
6 |
7 | # This gets us the long and lat min and max suitable for Tel-Aviv.
8 | # See link at the bottom of the script for a blog to create your own.
9 | tv_coordinates <- getbb("Tel Aviv Israel")
10 |
11 | # Start by getting the lines and point for the main streets
12 | streets <- tv_coordinates %>%
13 | opq() %>%
14 | add_osm_feature(key = "highway",
15 | value = c("motorway","primary",
16 | "secondary", "tertiary")) %>%
17 | osmdata_sf()
18 |
19 | small_streets <- tv_coordinates %>%
20 | opq() %>%
21 | add_osm_feature(key = "highway",
22 | value = c("residential", "living_street",
23 | "unclassified", "service", "footway")) %>%
24 | osmdata_sf()
25 |
26 | # PDF output --------------------------------------------------------------
27 |
28 | # I deliberately add it to an object since the direct outputting is extremely slow.
29 | # I then render it to pdf and convert that to png which is much faster:
30 | plot_pdf <- ggplot()+
31 | geom_sf(data = streets$osm_lines,
32 | inherit.aes = FALSE,
33 | color = "black",
34 | size = .6,
35 | alpha = .8)+
36 | geom_sf(data = small_streets$osm_lines,
37 | inherit.aes = FALSE,
38 | color = "black",
39 | size = .4,
40 | alpha = .6)+
41 | coord_sf(xlim = c(34.73900 , 34.85400),
42 | ylim = c(32.01650, 32.14750),
43 | expand = FALSE)+
44 | theme_void()+
45 | geom_text(aes(x= 34.80200, y = 32.02020, label = "Tel-Aviv, IL"),
46 | color = "grey15", family = "IBM Plex Sans Light", size = 14)+
47 | labs(caption = "\n#30daymapchallenge | Day: 02\nData: OSM | @Amit_Levinson")+
48 | theme(
49 | plot.caption = element_text(family = "IBM Plex Sans Light", size = 11, color = "gray25", face = "italic"),
50 | plot.caption.position = "plot",
51 | plot.margin = unit(c(2,4,2,2), "mm"))
52 |
53 | # Used pdf method from Cédric Scherer's tidytuesday outputs
54 | ggsave(plot = plot_pdf, filename = "Code/02_lines/02_lines2.pdf", width = 10, height = 18, device = cairo_pdf)
55 |
56 | pdf_convert(pdf = "Code/02_lines/02_lines.pdf",
57 | filenames = "Code/02_lines/02_lines.png",
58 | format = "png", dpi = 400)
59 |
60 | #Thanks to Chris' blog post on introducing us the plot:
61 | #https://ggplot2tutor.com/streetmaps/streetmaps/
--------------------------------------------------------------------------------
/2020/Code/02_lines/02_lines.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2020/Code/02_lines/02_lines.pdf
--------------------------------------------------------------------------------
/2020/Code/02_lines/02_lines.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2020/Code/02_lines/02_lines.png
--------------------------------------------------------------------------------
/2020/Code/03_Polygons/03_polygons.R:
--------------------------------------------------------------------------------
1 | library(ggplot2)
2 | library(dplyr)
3 | library(sf)
4 | library(ggrepel)
5 | library(jsonlite)
6 | library(httr)
7 | library(extrafont)
8 | library(ggtext)
9 |
10 | # Polygon data from https://gadm.org/download_country_v3.html
11 | shp <- readRDS("Data/00_Israel_0_sf.rds")
12 |
13 | # GET data from data.gov.il
14 | hotels <- GET("https://data.gov.il/api/3/action/datastore_search?resource_id=073b0370-dd72-4fbb-ab0e-bc2f8e85699f&limit=400")
15 | hotels <- fromJSON(rawToChar(hotels$content))
16 | hotels <- hotels$result$records
17 |
18 | # Plot
19 | ggplot()+
20 | geom_sf(data = shp, size = 1, color = "black", fill = "grey95")+
21 | geom_point(data = hotels, aes(x = X, y = Y, label = Name), color = "#8A2BE2")+
22 | theme_void()+
23 | labs(title = "Hotels in Israel", subtitle = "Labeled hotels are over the the green line",
24 | caption = "#30DayMapChallenge | Day: 03\nData: data.gov.il | @Amit_Levinson")+
25 | geom_text_repel(data = filter(hotels, Name %in% c("Kalya", "Almog")), mapping = aes(x = X, y= Y, label = Name), point.padding = 0.4 ,box.padding = 1, family = "IBM Plex Sans", color = "gray15", size = 3)+
26 | xlim(c(34, 36.5))+
27 | theme(text = element_text(family = "IBM Plex Sans"),
28 | plot.title = element_markdown(hjust = 0, size = 28, family = "IBM Plex Sans Medium"),
29 | plot.subtitle = element_text(size = 12),
30 | plot.caption = element_text(size = 8,family = "IBM Plex Sans Light", hjust = 0, color = "gray15"),
31 | plot.margin = unit(c(4,4,4,4), "mm"))
32 |
33 | ggsave(filename = "Code/03_polygons/03_polygons.png", height = 8, width = 6, dpi = 450)
34 |
--------------------------------------------------------------------------------
/2020/Code/03_Polygons/03_polygons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2020/Code/03_Polygons/03_polygons.png
--------------------------------------------------------------------------------
/2020/Code/07_green/07_green.R:
--------------------------------------------------------------------------------
1 | library(readr)
2 | library(dplyr)
3 | library(ggplot2)
4 | library(osmdata)
5 | library(sf)
6 | library(pdftools)
7 | library(ggtext)
8 | library(extrafont)
9 |
10 |
11 | sf_trees <- read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-01-28/sf_trees.csv')
12 |
13 | # Get coordinates
14 | sf_coordinates <- getbb("San Francisco USA")
15 |
16 | # Get data from osm
17 | sf_roads_raw <- sf_coordinates %>%
18 | opq() %>%
19 | add_osm_feature("highway") %>%
20 | osmdata_sf()
21 |
22 | label_df <- data.frame(
23 | x = -122.44,
24 | y = 37.82,
25 | label = "**Trees** of San Francisco")
26 |
27 | plot_pdf <- ggplot()+
28 | geom_sf(data = sf_roads_raw$osm_lines,
29 | color = "grey35",
30 | inherit.aes = FALSE,
31 | size = .6,
32 | alpha = .4)+
33 | geom_point(data = sf_trees, aes(x = longitude, y = latitude), color = "#919c4c", size = 0.05)+
34 | coord_sf(xlim = c(-122.51490, -122.35698),
35 | ylim = c(37.70809, 37.83240),
36 | expand = FALSE)+
37 | geom_richtext(data = label_df,aes(x =x , y = y, label = label), inherit.aes = FALSE, fill = NA, label.color =NA, label.padding = unit(c(0,0,0,0), "pt"), size = 24, family = "Kaushan Script")+
38 | geom_text(aes(x = -122.358, y = 37.711, label = "#30DayMapChallenge Day 07\nSource: DataSF | @Amit_Levinson"), size = 6, hjust = 1, family = "Kaushan Script", color = "grey25")+
39 | theme_void()+
40 | theme(
41 | panel.background = element_rect(fill = "#f8eed1"),
42 | panel.border = element_blank(),
43 | plot.title = element_markdown(size = 32),
44 | plot.margin = unit(c(4,4,4,4), "mm")
45 | )
46 |
47 | # See Cédric Scherer on saving as pdf:
48 | # https://github.com/Z3tt/TidyTuesday/blob/master/R/2020_05_TreesSF.Rmd
49 | ggsave(plot = plot_pdf, filename = "Code/07_green/07_green.pdf", width = 19, height = 18.94, device = cairo_pdf)
50 |
51 | pdf_convert(pdf = "Code/07_green/07_green.pdf",
52 | filenames = "Code/07_green/07_green.png",
53 | format = "png")
54 |
--------------------------------------------------------------------------------
/2020/Code/07_green/07_green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2020/Code/07_green/07_green.png
--------------------------------------------------------------------------------
/2020/Code/08_yellow/08_yellow.R:
--------------------------------------------------------------------------------
1 | library(snapbox)
2 | library(sf)
3 | library(ggplot2)
4 | library(readr)
5 | library(dplyr)
6 | library(extrafont)
7 |
8 | # List available shape files of Israel's municipality
9 | list.files("גבולות שיפוט", recursive = TRUE, pattern = "\\.shp$")
10 | # Read Be'er sheva
11 | b7 <- read_sf("גבולות שיפוט/���� ����/�� ����/����� ���� (Arc View)/gv_beer_sheva3.7.07.shp")
12 |
13 |
14 | # Read street light data
15 | # data from: https://www.beer-sheva.muni.il/OpenData/Pages/Data.aspx (seems to be broken now)
16 | b7_lights <- read_csv("Data/07_streetlight.csv")
17 |
18 | # Convert lights to sf and add title as a row
19 | b7_lights <- b7_lights %>%
20 | select(lat, lon) %>%
21 | mutate(label = "") %>%
22 | add_row(lat = 31.31, lon = 34.76, label = "Light posts in\nBe'er Sheva, IL")
23 |
24 | # Convert to sf
25 | lights_sf <- b7_lights %>%
26 | st_as_sf(coords = c("lon", "lat"), crs=4326)
27 |
28 | # Get boundaries of Be'er Sheva
29 | b7_area <- st_bbox(b7)
30 |
31 | # Retrieve mapbox, see link below for Jose Maria's code
32 | map_base <- ggplot()+
33 | layer_mapbox(b7_area,
34 | mapbox_api_access_token = keyring::key_get("mapbox"))
35 |
36 | # Plot
37 | map_base +
38 | geom_sf(data = filter(lights_sf, label ==""), fill = NA, color = "#ffff00", size = 0.01, alpha = 0.6)+
39 | geom_sf_text(data = lights_sf, aes(label = label),color = "#ffff00", size = 7, family = "Roboto Condensed", fontface = "italic")+
40 | theme_void()
41 |
42 | # Save:
43 | ggsave("Code/08_yellow/08_yellow.png",width = 13.5,height = 17.5,units = c("cm"), dpi = 400,bg = "transparent")
44 |
45 | # Code I followed:
46 | # https://gist.github.com/JoseEchave/672df001307c7f4344418fc4edb999cc
--------------------------------------------------------------------------------
/2020/Code/08_yellow/08_yellow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2020/Code/08_yellow/08_yellow.png
--------------------------------------------------------------------------------
/2020/Code/20_population/20_map-img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2020/Code/20_population/20_map-img.png
--------------------------------------------------------------------------------
/2020/Code/20_population/20_map.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2020/Code/20_population/20_map.gif
--------------------------------------------------------------------------------
/2020/Code/20_population/population.R:
--------------------------------------------------------------------------------
1 | library(dplyr)
2 | library(sf)
3 | library(ggplot2)
4 | library(sp)
5 | library(cartogram)
6 | library(readr)
7 | library(gganimate)
8 | library(tweenr)
9 | library(broom)
10 | library(extrafont)
11 |
12 | # See R-graph gallery for original blog post on how to do it (minor change since to the {gganimate} API):
13 | # https://www.r-graph-gallery.com/a-smooth-transition-between-chloropleth-and-cartogram.html
14 |
15 | israel_sf <- readRDS("Data/Israel-map/gadm36_ISR_1_sf.Rds")
16 |
17 | # Convert Golan + North into one since we'll need it aligned with the population:
18 | israel_sf_joined <- israel_sf %>%
19 | mutate(group_agg = NAME_1,
20 | group_agg = case_when(
21 | group_agg %in% c("Golan", "HaZafon") ~ "North",
22 | group_agg == "HaDarom" ~ "South",
23 | group_agg == "HaMerkaz" ~ "Center",
24 | TRUE ~ NAME_1)) %>%
25 | group_by(group_agg) %>%
26 | summarise()
27 |
28 | # Alternatively, join using aggregate. Thanks to Michael Dorman for the help!
29 | # israel_sf_joined <- aggregate(israel_sf_joined["geometry"], st_drop_geometry(israel_sf_joined["group_agg"]), sum)
30 |
31 | # Israel population for 2017 from
32 | # https://data.gov.il/dataset/localauthorities2018
33 | pop <- read_csv("Data/20_Israel-pop.csv")
34 |
35 |
36 | pop_dat <- pop %>%
37 | group_by(district) %>%
38 | # Convert to by million
39 | summarise(pop_sum = sum(population_thousands)/ 1000) %>%
40 | # Change names to match the sf object
41 | mutate(name = case_when(
42 | district == "הדרום" ~ "South",
43 | district == "המרכז" ~ "Center",
44 | district == "הצפון" ~ "North",
45 | district == "חיפה" ~ "Haifa",
46 | district == "ירושלים" ~ "Jerusalem",
47 | district == "תל אביב" ~ "Tel Aviv"
48 | ))
49 |
50 | israel_sf_joined <- left_join(israel_sf_joined, pop_dat, by = c("group_agg" = "name")) %>%
51 | # For a cartogram transform coordinates
52 | st_transform(crs = 23038)
53 |
54 | # Make the cartogram
55 | cartogram <- cartogram_cont(israel_sf_joined, "pop_sum", itermax = 7)
56 |
57 | isr_carto <- as(st_geometry(cartogram), "Spatial") %>%
58 | tidy()
59 |
60 | israel <- as(st_geometry(israel_sf_joined), "Spatial") %>%
61 | tidy()
62 |
63 | isr_carto$id <- seq(1,nrow(isr_carto))
64 | israel$id <- seq(1,nrow(israel))
65 |
66 | israel_combined <- rbind(israel, isr_carto,israel)
67 |
68 | israel_combined$ease <- "cubic-in-out"
69 | israel_combined$time <- rep(c(1:3), each=nrow(israel))
70 |
71 | israel_combined <- tween_elements(israel_combined, time='time', group='id', ease='ease', nframes = 40)
72 |
73 | # the geographical regions are saved as ID once we use the tween_elements. I imagine
74 | # you can solve this beforehand if you save the data as a dataframe in the spatial object
75 | israel_combined <- israel_combined %>%
76 | mutate(group = as.character(group),
77 | group = case_when(
78 | group == "ID1.1" ~ "Center",
79 | group == "ID2.1" ~ "Haifa",
80 | group == "ID3.1" ~ "Jerusalem",
81 | group == "ID4.1" ~ "North",
82 | group == "ID5.1" ~ "South",
83 | group == "ID6.1" ~ "Tel Aviv",
84 | TRUE ~ group
85 | ))
86 |
87 | israel_combined <- israel_combined %>%
88 | left_join(pop_dat, by = c("group" = "name"))
89 |
90 | # Start with exploring the plot on only 1 frame, adjust any aesthetics and
91 | # then explore with the animation
92 | p <- ggplot() +
93 | geom_polygon(data = israel_combined %>% arrange(order), aes(fill = pop_sum, x = long, y = lat, group = group) , size=0, alpha=0.9, color = "gray35") +
94 | scale_fill_continuous(trans = "reverse",name="Population (Millions)", guide = guide_legend(keyheight = unit(1, units = "mm"), keywidth=unit(6, units = "mm"), label.position = "bottom", title.position = 'top', ncol=1))+
95 | labs(title = "Israel's population", subtitle = "Map transitions between a regular map to a cartogram, a map where\nthe geographic size is proportional to the population in that area.\nData is from Israel's CBS 2017 report and is aggregated at the district level", caption = "Data: data.gov.il\n@Amit_Levinson")+
96 | theme_void() +
97 | theme(text = element_text(family = "IBM Plex Sans"),
98 | plot.margin = unit(c(3,3,3,5), "mm"),
99 | plot.title = element_text(size = 14, face = "bold"),
100 | plot.subtitle = element_text(size = 8, color = "gray15"),
101 | legend.title=element_text(size= 7),
102 | legend.text = element_text(size = 6),
103 | plot.caption = element_text(size = 6, face = "italic", color = "gray45"))+
104 | transition_states(.frame)+
105 | enter_fade() +
106 | exit_fade()
107 |
108 | # The rendering takes some time, so tweak and do any aesthetics on a filtered
109 | # version of the data. Just add %>% filter(.frame == 1) in the data argument above
110 | animate(p, start_pause = 3, width = 4, height = 7, units = "in", res = 150)
111 |
112 | anim_save("Code/20_population/20_map.gif")
113 |
114 |
115 | # Or make both plots just not animated -----------------------------------
116 |
117 | library(patchwork)
118 |
119 | p1 <- ggplot() +
120 | geom_sf(data = israel_sf_joined, aes(fill = pop_sum) , size=0, alpha=0.9, color = "gray35") +
121 | scale_fill_gradient(trans = "reverse",name="Population (Millions)", guide = guide_legend(keyheight = unit(3, units = "mm"), keywidth=unit(8, units = "mm"), label.position = "bottom", title.position = 'top', nrow=1))+
122 | labs(title = "Regular")+
123 | theme_void() +
124 | theme(plot.title = element_text(size = 14),
125 | legend.title=element_text(size= 12),
126 | legend.text = element_text(size = 10),
127 | legend.spacing.x = unit(3, 'mm'))
128 |
129 | p2 <- ggplot() +
130 | geom_sf(data = cartogram, aes(fill = pop_sum) , size=0, alpha=0.9, color = "gray35") +
131 | scale_fill_continuous(trans = "reverse",name="Population (Millions)", guide = NULL)+
132 | ggtitle("Cartogram")+
133 | labs(title = "Cartogram", caption = "Data: data.gov.il\n@Amit_Levinson")+
134 | theme_void() +
135 | theme(plot.title = element_text(size = 14),
136 | plot.caption = element_text(size = 10, face = "italic", color = "gray45"))
137 |
138 | # Stick plots together
139 | p <- p1+p2+
140 | plot_layout(guides = 'collect')+
141 | plot_annotation(title = "Israel's Population", subtitle = "A regular map and a cartogram, a map where the geographic size is proportional\nto the population in that area. Data is from Israel's CBS 2017 report and is\naggregated at the district level",
142 | theme = theme(plot.title = element_text(size = 18, face = "bold"),
143 | plot.subtitle = element_text(size = 14, color = "gray35"))) &
144 | theme(text = element_text('IBM Plex Sans'),
145 | plot.title = element_text(face = "bold"),
146 | legend.position = "bottom",
147 | plot.margin = unit(c(2,2,4,2), "mm"))
148 |
149 | ggsave("Code/20_population/20_map-img.png", p, height = 13, width = 8, units = "in", dpi = 300)
--------------------------------------------------------------------------------
/2020/Data/20_Israel-pop.csv:
--------------------------------------------------------------------------------
1 | name,district,population_thousands
2 | אום אל-פחם,חיפה,54.2
3 | אופקים,הדרום,27.8
4 | אור יהודה,תל אביב,36.7
5 | אור עקיבא,חיפה,17.8
6 | אילת,הדרום,50.7
7 | אלעד,המרכז,46.9
8 | אריאל,אזור יהודה והשומרון,19.6
9 | אשדוד,הדרום,222.9
10 | אשקלון,הדרום,137.9
11 | באקה אל-גרביה,חיפה,29.0
12 | באר שבע,הדרום,207.6
13 | בית שאן,הצפון,17.7
14 | בית שמש,ירושלים,114.4
15 | ביתר עילית,אזור יהודה והשומרון,54.6
16 | בני ברק,תל אביב,193.8
17 | בת ים,תל אביב,128.7
18 | גבעת שמואל,המרכז,25.8
19 | גבעתיים,תל אביב,59.5
20 | דימונה,הדרום,33.7
21 | הוד השרון,המרכז,61.1
22 | הרצלייה,תל אביב,94.0
23 | חדרה,חיפה,94.0
24 | חולון,תל אביב,192.6
25 | חיפה,חיפה,281.1
26 | טבריה,הצפון,43.7
27 | טייבה,המרכז,42.4
28 | טירה,המרכז,25.7
29 | טירת כרמל,חיפה,21.3
30 | טמרה,הצפון,33.4
31 | יבנה,המרכז,45.5
32 | יהוד,המרכז,29.7
33 | יקנעם עילית,הצפון,22.7
34 | ירושלים,ירושלים,901.3
35 | כפר יונה,המרכז,22.5
36 | כפר סבא,המרכז,100.0
37 | כפר קאסם,המרכז,22.7
38 | כרמיאל,הצפון,45.9
39 | לוד,המרכז,74.6
40 | מגדל העמק,הצפון,25.4
41 | מודיעין עילית,אזור יהודה והשומרון,70.1
42 | מודיעין-מכבים-רעות*,המרכז,91.3
43 | מעלה אדומים,אזור יהודה והשומרון,37.8
44 | מעלות-תרשיחא,הצפון,21.3
45 | נהרייה,הצפון,56.1
46 | נס ציונה,המרכז,49.1
47 | נצרת,הצפון,76.6
48 | נצרת עילית,הצפון,40.6
49 | נשר,חיפה,23.7
50 | נתיבות,הדרום,33.8
51 | נתניה,המרכז,214.1
52 | סח'נין,הצפון,30.5
53 | עכו,הצפון,48.3
54 | עפולה,הצפון,49.2
55 | עראבה,הצפון,25.0
56 | ערד,הדרום,25.5
57 | פתח תקווה,המרכז,240.4
58 | צפת,הצפון,35.3
59 | קלנסווה,המרכז,22.4
60 | קריית אונו,תל אביב,39.4
61 | קריית אתא,חיפה,57.5
62 | קריית ביאליק,חיפה,39.6
63 | קריית גת,הדרום,53.5
64 | קריית ים,חיפה,39.7
65 | קריית מוצקין,חיפה,41.4
66 | קריית מלאכי,הדרום,22.3
67 | קריית שמונה,הצפון,22.8
68 | ראש העין,המרכז,50.5
69 | ראשון לציון,המרכז,249.9
70 | רהט,הדרום,66.8
71 | רחובות,המרכז,138.4
72 | רמלה,המרכז,75.7
73 | רמת גן,תל אביב,156.3
74 | רמת השרון,תל אביב,46.0
75 | רעננה,המרכז,72.8
76 | שדרות,הדרום,25.1
77 | שפרעם,הצפון,41.0
78 | תל אביב -יפו,תל אביב,443.9
79 | אבו גוש,ירושלים,7.3
80 | אבו סנאן,הצפון,13.7
81 | אבן יהודה,המרכז,13.7
82 | אורנית,אזור יהודה והשומרון,8.7
83 | אזור,תל אביב,12.7
84 | אכסאל,הצפון,14.2
85 | אליכין,המרכז,3.5
86 | אלפי מנשה,אזור יהודה והשומרון,7.8
87 | אלקנה,אזור יהודה והשומרון,3.9
88 | אעבלין,הצפון,13.0
89 | אפרת,אזור יהודה והשומרון,9.1
90 | באר יעקב,המרכז,22.9
91 | בועיינה-נוג'ידאת,הצפון,9.5
92 | בוקעאתא,הצפון,6.5
93 | ביר אל-מכסור,הצפון,9.1
94 | בית אל,אזור יהודה והשומרון,6.1
95 | בית אריה,אזור יהודה והשומרון,5.0
96 | בית ג'ן,הצפון,11.7
97 | בית דגן,המרכז,7.1
98 | "בני עי""ש",המרכז,7.0
99 | בנימינה-גבעת עדה*,חיפה,15.6
100 | "בסמ""ה",חיפה,9.5
101 | בסמת טבעון,הצפון,7.7
102 | בענה,הצפון,8.1
103 | גבעת זאב,אזור יהודה והשומרון,17.3
104 | ג'דיידה-מכר,הצפון,20.6
105 | גדרה,המרכז,27.5
106 | ג'ולס,הצפון,6.3
107 | ג'לג'וליה,המרכז,9.8
108 | גן יבנה,המרכז,23.5
109 | גני תקווה,המרכז,18.2
110 | ג'סר א-זרקא,חיפה,14.4
111 | ג'ש (גוש חלב),הצפון,3.1
112 | ג'ת,חיפה,11.6
113 | דאלית אל-כרמל,חיפה,17.2
114 | דבורייה,הצפון,10.2
115 | דייר אל-אסד,הצפון,12.1
116 | דייר חנא,הצפון,10.1
117 | הר אדר,אזור יהודה והשומרון,4.1
118 | זכרון יעקב,חיפה,23.0
119 | זמר,המרכז,6.8
120 | זרזיר,הצפון,7.8
121 | חורה,הדרום,20.8
122 | חורפיש,הצפון,6.2
123 | חצור הגלילית,הצפון,9.1
124 | חריש,חיפה,3.6
125 | טובא-זנגרייה,הצפון,6.5
126 | טורעאן,הצפון,13.7
127 | יאנוח-ג'ת,הצפון,6.5
128 | יבנאל,הצפון,4.3
129 | יסוד המעלה,הצפון,1.7
130 | יפיע,הצפון,18.7
131 | ירוחם,הדרום,9.5
132 | ירכא,הצפון,16.7
133 | כאבול,הצפון,13.6
134 | כאוכב אבו אל-היג'א,הצפון,3.5
135 | כוכב יאיר,המרכז,8.9
136 | כסיפה,הדרום,20.3
137 | כסרא-סמיע,הצפון,8.5
138 | כעביה-טבאש-חג'אג'רה,הצפון,5.2
139 | כפר ברא,המרכז,3.5
140 | כפר ורדים,הצפון,5.5
141 | כפר יאסיף,הצפון,9.9
142 | כפר כמא,הצפון,3.3
143 | כפר כנא,הצפון,22.0
144 | כפר מנדא,הצפון,19.3
145 | כפר קרע,חיפה,18.3
146 | כפר שמריהו,תל אביב,1.9
147 | כפר תבור,הצפון,4.1
148 | להבים,הדרום,6.4
149 | לקיה,הדרום,12.9
150 | מבשרת ציון,ירושלים,24.4
151 | מגאר,הצפון,22.3
152 | מג'ד אל-כרום,הצפון,15.1
153 | מגדל,הצפון,1.9
154 | מג'דל שמס,הצפון,10.9
155 | מזכרת בתיה,המרכז,14.2
156 | מזרעה,הצפון,3.8
157 | מטולה,הצפון,1.6
158 | מיתר,הדרום,7.7
159 | מסעדה,הצפון,3.6
160 | מעיליא,הצפון,3.2
161 | מעלה אפרים,אזור יהודה והשומרון,1.2
162 | מעלה עירון,חיפה,14.6
163 | מצפה רמון,הדרום,5.2
164 | משהד,הצפון,8.1
165 | נחף,הצפון,12.6
166 | סאג'ור,הצפון,4.1
167 | סביון*,המרכז,3.9
168 | ע'ג'ר,הצפון,2.6
169 | עומר,הדרום,7.6
170 | עיילבון,הצפון,5.6
171 | עילוט,הצפון,7.9
172 | עין מאהל,הצפון,12.8
173 | עין קנייא,הצפון,2.0
174 | עמנואל,אזור יהודה והשומרון,3.4
175 | עספיא,חיפה,12.1
176 | ערערה,חיפה,24.5
177 | ערערה-בנגב,הדרום,17.0
178 | פוריידיס,חיפה,12.9
179 | פסוטה,הצפון,3.1
180 | פקיעין (בוקייעה),הצפון,5.8
181 | פרדס חנה-כרכור,חיפה,41.1
182 | פרדסייה,המרכז,5.8
183 | קדומים,אזור יהודה והשומרון,4.5
184 | קדימה-צורן,המרכז,22.0
185 | קצרין,הצפון,7.1
186 | קריית ארבע,אזור יהודה והשומרון,7.3
187 | קריית טבעון,חיפה,17.7
188 | קריית יערים,ירושלים,4.8
189 | קריית עקרון,המרכז,10.9
190 | קרני שומרון,אזור יהודה והשומרון,7.4
191 | ראמה,הצפון,7.6
192 | ראש פינה,הצפון,3.1
193 | ריינה,הצפון,18.7
194 | רכסים,חיפה,11.8
195 | רמת ישי,הצפון,7.7
196 | שבלי - אום אל-גנם,הצפון,5.9
197 | שגב-שלום,הדרום,9.9
198 | שוהם,המרכז,20.9
199 | שלומי,הצפון,6.2
200 | שעב,הצפון,6.8
201 | תל מונד,המרכז,12.6
202 | תל שבע,הדרום,19.7
203 | אל קסום,הדרום,10.0
204 | אל-בטוף,הצפון,7.8
205 | אלונה,חיפה,2.3
206 | אשכול,הדרום,13.9
207 | באר טוביה,הדרום,23.1
208 | בוסתן אל-מרג',הצפון,7.7
209 | בני שמעון,הדרום,10.0
210 | ברנר,המרכז,7.9
211 | גדרות,המרכז,5.2
212 | גולן,הצפון,17.0
213 | גוש עציון,אזור יהודה והשומרון,23.5
214 | גזר,המרכז,26.5
215 | גן רווה,המרכז,6.1
216 | דרום השרון,המרכז,32.7
217 | הגלבוע,הצפון,29.9
218 | הגליל העליון,הצפון,17.8
219 | הגליל התחתון,הצפון,12.1
220 | הערבה התיכונה,הדרום,3.3
221 | הר חברון,אזור יהודה והשומרון,8.3
222 | זבולון,חיפה,13.4
223 | חבל אילות,הדרום,4.1
224 | חבל יבנה,המרכז,7.0
225 | חבל מודיעין,המרכז,23.4
226 | חוף אשקלון,הדרום,17.1
227 | חוף הכרמל,חיפה,30.8
228 | חוף השרון,המרכז,15.1
229 | יואב,הדרום,8.6
230 | לב השרון,המרכז,23.6
231 | לכיש,הדרום,11.4
232 | מבואות החרמון,הצפון,7.2
233 | מגידו,הצפון,11.6
234 | מגילות ים המלח,אזור יהודה והשומרון,1.6
235 | מטה אשר,הצפון,28.7
236 | מטה בנימין,אזור יהודה והשומרון,65.4
237 | מטה יהודה,ירושלים,56.6
238 | מנשה,חיפה,19.8
239 | מעלה יוסף,הצפון,10.5
240 | מרום הגליל,הצפון,15.4
241 | מרחבים,הדרום,13.7
242 | משגב,הצפון,28.0
243 | נווה מדבר,הדרום,9.1
244 | נחל שורק,המרכז,9.2
245 | עמק הירדן,הצפון,13.5
246 | עמק המעיינות,הצפון,13.1
247 | עמק חפר,המרכז,42.2
248 | עמק יזרעאל,הצפון,38.0
249 | עמק לוד,המרכז,15.0
250 | ערבות הירדן,אזור יהודה והשומרון,4.9
251 | רמת נגב,הדרום,7.6
252 | שדות נגב,הדרום,10.3
253 | שומרון,אזור יהודה והשומרון,41.1
254 | שער הנגב,הדרום,8.0
255 | שפיר,הדרום,11.0
256 | תמר,הדרום,1.5
257 |
--------------------------------------------------------------------------------
/2020/Data/Israel-map/00_Israel_0_sf.rds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2020/Data/Israel-map/00_Israel_0_sf.rds
--------------------------------------------------------------------------------
/2020/Data/Israel-map/gadm36_ISR_0_sf.rds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2020/Data/Israel-map/gadm36_ISR_0_sf.rds
--------------------------------------------------------------------------------
/2020/Data/Israel-map/gadm36_ISR_0_sp.rds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2020/Data/Israel-map/gadm36_ISR_0_sp.rds
--------------------------------------------------------------------------------
/2020/Data/Israel-map/gadm36_ISR_1_sf.rds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2020/Data/Israel-map/gadm36_ISR_1_sf.rds
--------------------------------------------------------------------------------
/2021/01_points/01_points.R:
--------------------------------------------------------------------------------
1 | library(sf)
2 | library(ggplot2)
3 | library(geojsonio)
4 | library(ggmap)
5 | library(dplyr)
6 | library(stringr)
7 | library(RColorBrewer)
8 |
9 | dat <- st_as_sf(geojson_read("https://opendata.arcgis.com/datasets/feec119124874c70994fa13a365bebf9_0.geojson", what = "sp"))
10 |
11 | Sys.setlocale("LC_ALL", "Hebrew")
12 |
13 |
14 | clean_data <- dat %>%
15 | mutate(
16 | # Extract years
17 | TreeEstimateAge = str_extract(TreeEstimateAge, "\\d+(-)?\\d*"),
18 | TreeEstimateAge = ifelse(TreeEstimateAge == "60-100", "60", TreeEstimateAge),
19 | TreeAge = factor(TreeEstimateAge, levels = c(NA, "10-20", "20-40", "40-60", "60", "100"), labels = c("10-20","20-40", "40-60", "60+", "100+"))
20 | )
21 |
22 | telavivggmap <- get_googlemap(center = "tel aviv, israel", zoom = 13,style=c(feature="all",element="labels",visibility="off"))
23 |
24 |
25 | ggmap(telavivggmap)+
26 | geom_sf(data = clean_data, aes(color = TreeAge), inherit.aes = FALSE, size = 1.5)+
27 | scale_color_brewer(palette = "YlOrBr", na.value="grey", name = "Tree age (Years)")+
28 | guides(color = guide_legend(nrow = 1, byrow = TRUE,override.aes = list(size=3)))+
29 | labs(title = "Historical and preserved trees across Tel-Aviv",
30 | subtitle = "",
31 | caption = "Data: Israel's Ministry of Agriculture | Visualization: @Amit_Levinson")+
32 | theme(
33 | text = element_text(family = "Segoe UI"),
34 | plot.title = element_text(size = 22, family = "Alegreya", hjust = 0.5, face = "bold"),
35 | plot.subtitle = element_text(size = 8),
36 | legend.position = "top",
37 | legend.direction = "horizontal",
38 | legend.key.size = unit(3,"mm"),
39 | legend.key.width = unit(5,"mm"),
40 | legend.title = element_text(size = 11, color = "gray10"),
41 | legend.text = element_text(size = 10, color = "gray25"),
42 | plot.caption = element_text(hjust = 0.5, color = "gray45", size = 10),
43 | plot.margin = margin(6,2,6,2,"mm"),
44 | panel.background = element_rect(fill = "white", color = NA),
45 | axis.text = element_blank(),
46 | axis.ticks = element_blank(),
47 | axis.title = element_blank(),
48 | legend.key=element_blank()
49 | )
50 |
51 | ggsave("2021/01_points/trees.png",height = 8, width = 7, dpi = 500)
52 |
--------------------------------------------------------------------------------
/2021/01_points/trees.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/01_points/trees.png
--------------------------------------------------------------------------------
/2021/02_lines/lines.R:
--------------------------------------------------------------------------------
1 |
2 | # Code from Alexandra Kapp day 9: https://alexandrakapp.github.io/30daymapchallenge/index.html
3 | # Check it out^^
4 |
5 | library(sf)
6 | library(dplyr)
7 | library(osrm)
8 | library(stplanr)
9 | library(leaflet)
10 | library(htmltools)
11 | library(htmlwidgets)
12 | library(webshot)
13 |
14 | # Get Tel Aviv shapefile to extract points for routes
15 | tel_aviv_file_name <- list.files(pattern =".Aviv.+\\.shp$", recursive = TRUE)
16 | tel_aviv_file <- read_sf(paste0(tel_aviv_file_name))
17 |
18 | # Provide relevant crs to Tel-Aviv
19 | tel_aviv_file <- st_transform(st_set_crs(tel_aviv_file, 2039), 4326)
20 |
21 | routes <- route(from = st_coordinates(st_sample(tel_aviv_file, size = 1000)),
22 | to = st_coordinates(st_sample(tel_aviv_file, size = 1000)),
23 | route_fun = osrmRoute,
24 | returnclass = "sf")
25 |
26 | routes["count"] <- 1
27 |
28 | overlapping_segments <- overline(routes, attrib = "count")
29 |
30 |
31 | p <- leaflet(overlapping_segments) %>%
32 | addProviderTiles(providers$CartoDB.DarkMatter) %>%
33 | addPolylines(weight = overlapping_segments$count / 6, color = "white") %>%
34 | addControl(html = paste(tags$h1(HTML("Streets traveled
in Tel-Aviv"), style = "color:white; font-family:Merriweather; font-size: 28pt; padding-left: 12px; line-height: 1.2em;"),
35 | tags$div(HTML("Most commonly traveled streets
from a sample of 1000 routes."), style = "color:white; font-family:Segoe UI; font-size: 15pt; padding-left: 15px; margin-top:-20px"))
36 | , className = "fieldset {
37 | border: 0;
38 | }", position = "topleft") %>%
39 | addControl(html = tags$div(HTML("Adapted from Alexandra Kapp • Data: {stplanr} package • Amit Levinson"), style = "color:#BEBEBE; font-family:Segoe UI; font-size: 10pt; padding-left: 15px;"), className = "fieldset {border: 0;}", position = "bottomleft")
40 |
41 | # Saving a snapshot
42 | saveWidget(p, "2021/02_lines/lines.html")
43 | webshot("2021/02_lines/lines.html", file = "2021/02_lines/lines.png", zoom = 3, vwidth = 900, vheight = 700)
44 |
--------------------------------------------------------------------------------
/2021/02_lines/lines.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/02_lines/lines.png
--------------------------------------------------------------------------------
/2021/02_lines/lines_files/Proj4Leaflet-1.0.1/proj4leaflet.js:
--------------------------------------------------------------------------------
1 | (function (factory) {
2 | var L, proj4;
3 | if (typeof define === 'function' && define.amd) {
4 | // AMD
5 | define(['leaflet', 'proj4'], factory);
6 | } else if (typeof module === 'object' && typeof module.exports === "object") {
7 | // Node/CommonJS
8 | L = require('leaflet');
9 | proj4 = require('proj4');
10 | module.exports = factory(L, proj4);
11 | } else {
12 | // Browser globals
13 | if (typeof window.L === 'undefined' || typeof window.proj4 === 'undefined')
14 | throw 'Leaflet and proj4 must be loaded first';
15 | factory(window.L, window.proj4);
16 | }
17 | }(function (L, proj4) {
18 | if (proj4.__esModule && proj4.default) {
19 | // If proj4 was bundled as an ES6 module, unwrap it to get
20 | // to the actual main proj4 object.
21 | // See discussion in https://github.com/kartena/Proj4Leaflet/pull/147
22 | proj4 = proj4.default;
23 | }
24 |
25 | L.Proj = {};
26 |
27 | L.Proj._isProj4Obj = function(a) {
28 | return (typeof a.inverse !== 'undefined' &&
29 | typeof a.forward !== 'undefined');
30 | };
31 |
32 | L.Proj.Projection = L.Class.extend({
33 | initialize: function(code, def, bounds) {
34 | var isP4 = L.Proj._isProj4Obj(code);
35 | this._proj = isP4 ? code : this._projFromCodeDef(code, def);
36 | this.bounds = isP4 ? def : bounds;
37 | },
38 |
39 | project: function (latlng) {
40 | var point = this._proj.forward([latlng.lng, latlng.lat]);
41 | return new L.Point(point[0], point[1]);
42 | },
43 |
44 | unproject: function (point, unbounded) {
45 | var point2 = this._proj.inverse([point.x, point.y]);
46 | return new L.LatLng(point2[1], point2[0], unbounded);
47 | },
48 |
49 | _projFromCodeDef: function(code, def) {
50 | if (def) {
51 | proj4.defs(code, def);
52 | } else if (proj4.defs[code] === undefined) {
53 | var urn = code.split(':');
54 | if (urn.length > 3) {
55 | code = urn[urn.length - 3] + ':' + urn[urn.length - 1];
56 | }
57 | if (proj4.defs[code] === undefined) {
58 | throw 'No projection definition for code ' + code;
59 | }
60 | }
61 |
62 | return proj4(code);
63 | }
64 | });
65 |
66 | L.Proj.CRS = L.Class.extend({
67 | includes: L.CRS,
68 |
69 | options: {
70 | transformation: new L.Transformation(1, 0, -1, 0)
71 | },
72 |
73 | initialize: function(a, b, c) {
74 | var code,
75 | proj,
76 | def,
77 | options;
78 |
79 | if (L.Proj._isProj4Obj(a)) {
80 | proj = a;
81 | code = proj.srsCode;
82 | options = b || {};
83 |
84 | this.projection = new L.Proj.Projection(proj, options.bounds);
85 | } else {
86 | code = a;
87 | def = b;
88 | options = c || {};
89 | this.projection = new L.Proj.Projection(code, def, options.bounds);
90 | }
91 |
92 | L.Util.setOptions(this, options);
93 | this.code = code;
94 | this.transformation = this.options.transformation;
95 |
96 | if (this.options.origin) {
97 | this.transformation =
98 | new L.Transformation(1, -this.options.origin[0],
99 | -1, this.options.origin[1]);
100 | }
101 |
102 | if (this.options.scales) {
103 | this._scales = this.options.scales;
104 | } else if (this.options.resolutions) {
105 | this._scales = [];
106 | for (var i = this.options.resolutions.length - 1; i >= 0; i--) {
107 | if (this.options.resolutions[i]) {
108 | this._scales[i] = 1 / this.options.resolutions[i];
109 | }
110 | }
111 | }
112 |
113 | this.infinite = !this.options.bounds;
114 |
115 | },
116 |
117 | scale: function(zoom) {
118 | var iZoom = Math.floor(zoom),
119 | baseScale,
120 | nextScale,
121 | scaleDiff,
122 | zDiff;
123 | if (zoom === iZoom) {
124 | return this._scales[zoom];
125 | } else {
126 | // Non-integer zoom, interpolate
127 | baseScale = this._scales[iZoom];
128 | nextScale = this._scales[iZoom + 1];
129 | scaleDiff = nextScale - baseScale;
130 | zDiff = (zoom - iZoom);
131 | return baseScale + scaleDiff * zDiff;
132 | }
133 | },
134 |
135 | zoom: function(scale) {
136 | // Find closest number in this._scales, down
137 | var downScale = this._closestElement(this._scales, scale),
138 | downZoom = this._scales.indexOf(downScale),
139 | nextScale,
140 | nextZoom,
141 | scaleDiff;
142 | // Check if scale is downScale => return array index
143 | if (scale === downScale) {
144 | return downZoom;
145 | }
146 | if (downScale === undefined) {
147 | return -Infinity;
148 | }
149 | // Interpolate
150 | nextZoom = downZoom + 1;
151 | nextScale = this._scales[nextZoom];
152 | if (nextScale === undefined) {
153 | return Infinity;
154 | }
155 | scaleDiff = nextScale - downScale;
156 | return (scale - downScale) / scaleDiff + downZoom;
157 | },
158 |
159 | distance: L.CRS.Earth.distance,
160 |
161 | R: L.CRS.Earth.R,
162 |
163 | /* Get the closest lowest element in an array */
164 | _closestElement: function(array, element) {
165 | var low;
166 | for (var i = array.length; i--;) {
167 | if (array[i] <= element && (low === undefined || low < array[i])) {
168 | low = array[i];
169 | }
170 | }
171 | return low;
172 | }
173 | });
174 |
175 | L.Proj.GeoJSON = L.GeoJSON.extend({
176 | initialize: function(geojson, options) {
177 | this._callLevel = 0;
178 | L.GeoJSON.prototype.initialize.call(this, geojson, options);
179 | },
180 |
181 | addData: function(geojson) {
182 | var crs;
183 |
184 | if (geojson) {
185 | if (geojson.crs && geojson.crs.type === 'name') {
186 | crs = new L.Proj.CRS(geojson.crs.properties.name);
187 | } else if (geojson.crs && geojson.crs.type) {
188 | crs = new L.Proj.CRS(geojson.crs.type + ':' + geojson.crs.properties.code);
189 | }
190 |
191 | if (crs !== undefined) {
192 | this.options.coordsToLatLng = function(coords) {
193 | var point = L.point(coords[0], coords[1]);
194 | return crs.projection.unproject(point);
195 | };
196 | }
197 | }
198 |
199 | // Base class' addData might call us recursively, but
200 | // CRS shouldn't be cleared in that case, since CRS applies
201 | // to the whole GeoJSON, inluding sub-features.
202 | this._callLevel++;
203 | try {
204 | L.GeoJSON.prototype.addData.call(this, geojson);
205 | } finally {
206 | this._callLevel--;
207 | if (this._callLevel === 0) {
208 | delete this.options.coordsToLatLng;
209 | }
210 | }
211 | }
212 | });
213 |
214 | L.Proj.geoJson = function(geojson, options) {
215 | return new L.Proj.GeoJSON(geojson, options);
216 | };
217 |
218 | L.Proj.ImageOverlay = L.ImageOverlay.extend({
219 | initialize: function (url, bounds, options) {
220 | L.ImageOverlay.prototype.initialize.call(this, url, null, options);
221 | this._projectedBounds = bounds;
222 | },
223 |
224 | // Danger ahead: Overriding internal methods in Leaflet.
225 | // Decided to do this rather than making a copy of L.ImageOverlay
226 | // and doing very tiny modifications to it.
227 | // Future will tell if this was wise or not.
228 | _animateZoom: function (event) {
229 | var scale = this._map.getZoomScale(event.zoom);
230 | var northWest = L.point(this._projectedBounds.min.x, this._projectedBounds.max.y);
231 | var offset = this._projectedToNewLayerPoint(northWest, event.zoom, event.center);
232 |
233 | L.DomUtil.setTransform(this._image, offset, scale);
234 | },
235 |
236 | _reset: function () {
237 | var zoom = this._map.getZoom();
238 | var pixelOrigin = this._map.getPixelOrigin();
239 | var bounds = L.bounds(
240 | this._transform(this._projectedBounds.min, zoom)._subtract(pixelOrigin),
241 | this._transform(this._projectedBounds.max, zoom)._subtract(pixelOrigin)
242 | );
243 | var size = bounds.getSize();
244 |
245 | L.DomUtil.setPosition(this._image, bounds.min);
246 | this._image.style.width = size.x + 'px';
247 | this._image.style.height = size.y + 'px';
248 | },
249 |
250 | _projectedToNewLayerPoint: function (point, zoom, center) {
251 | var viewHalf = this._map.getSize()._divideBy(2);
252 | var newTopLeft = this._map.project(center, zoom)._subtract(viewHalf)._round();
253 | var topLeft = newTopLeft.add(this._map._getMapPanePos());
254 |
255 | return this._transform(point, zoom)._subtract(topLeft);
256 | },
257 |
258 | _transform: function (point, zoom) {
259 | var crs = this._map.options.crs;
260 | var transformation = crs.transformation;
261 | var scale = crs.scale(zoom);
262 |
263 | return transformation.transform(point, scale);
264 | }
265 | });
266 |
267 | L.Proj.imageOverlay = function (url, bounds, options) {
268 | return new L.Proj.ImageOverlay(url, bounds, options);
269 | };
270 |
271 | return L.Proj;
272 | }));
273 |
--------------------------------------------------------------------------------
/2021/02_lines/lines_files/leaflet-1.3.1/images/layers-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/02_lines/lines_files/leaflet-1.3.1/images/layers-2x.png
--------------------------------------------------------------------------------
/2021/02_lines/lines_files/leaflet-1.3.1/images/layers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/02_lines/lines_files/leaflet-1.3.1/images/layers.png
--------------------------------------------------------------------------------
/2021/02_lines/lines_files/leaflet-1.3.1/images/marker-icon-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/02_lines/lines_files/leaflet-1.3.1/images/marker-icon-2x.png
--------------------------------------------------------------------------------
/2021/02_lines/lines_files/leaflet-1.3.1/images/marker-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/02_lines/lines_files/leaflet-1.3.1/images/marker-icon.png
--------------------------------------------------------------------------------
/2021/02_lines/lines_files/leaflet-1.3.1/images/marker-shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/02_lines/lines_files/leaflet-1.3.1/images/marker-shadow.png
--------------------------------------------------------------------------------
/2021/02_lines/lines_files/leaflet-providers-plugin-2.0.4.1/leaflet-providers-plugin.js:
--------------------------------------------------------------------------------
1 | LeafletWidget.methods.addProviderTiles = function(provider, layerId, group, options) {
2 | this.layerManager.addLayer(L.tileLayer.provider(provider, options), "tile", layerId, group);
3 | };
4 |
--------------------------------------------------------------------------------
/2021/02_lines/lines_files/leafletfix-1.0.0/leafletfix.css:
--------------------------------------------------------------------------------
1 | /* Work around CSS properties introduced on img by bootstrap */
2 | img.leaflet-tile {
3 | padding: 0;
4 | margin: 0;
5 | border-radius: 0;
6 | border: none;
7 | }
8 | .info {
9 | padding: 6px 8px;
10 | font: 14px/16px Arial, Helvetica, sans-serif;
11 | background: white;
12 | background: rgba(255,255,255,0.8);
13 | box-shadow: 0 0 15px rgba(0,0,0,0.2);
14 | border-radius: 5px;
15 | }
16 | .legend {
17 | line-height: 18px;
18 | color: #555;
19 | }
20 | .legend svg text {
21 | fill: #555;
22 | }
23 | .legend svg line {
24 | stroke: #555;
25 | }
26 | .legend i {
27 | width: 18px;
28 | height: 18px;
29 | margin-right: 4px;
30 | opacity: 0.7;
31 | display: inline-block;
32 | vertical-align: top;
33 | /*For IE 7*/
34 | zoom: 1;
35 | *display: inline;
36 | }
37 |
--------------------------------------------------------------------------------
/2021/02_lines/lines_files/rstudio_leaflet-1.3.1/images/1px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/02_lines/lines_files/rstudio_leaflet-1.3.1/images/1px.png
--------------------------------------------------------------------------------
/2021/02_lines/lines_files/rstudio_leaflet-1.3.1/rstudio_leaflet.css:
--------------------------------------------------------------------------------
1 | .leaflet-tooltip.leaflet-tooltip-text-only,
2 | .leaflet-tooltip.leaflet-tooltip-text-only:before,
3 | .leaflet-tooltip.leaflet-tooltip-text-only:after {
4 | background: none;
5 | border: none;
6 | box-shadow: none;
7 | }
8 |
9 | .leaflet-tooltip.leaflet-tooltip-text-only.leaflet-tooltip-left {
10 | margin-left: 5px;
11 | }
12 |
13 | .leaflet-tooltip.leaflet-tooltip-text-only.leaflet-tooltip-right {
14 | margin-left: -5px;
15 | }
16 |
17 | .leaflet-tooltip:after {
18 | border-right: 6px solid transparent;
19 | /* right: -16px; */
20 | }
21 |
22 | .leaflet-popup-pane .leaflet-popup-tip-container {
23 | /* when the tooltip container is clicked, it is closed */
24 | pointer-events: all;
25 | /* tooltips should display the "hand" icon, just like .leaflet-interactive*/
26 | cursor: pointer;
27 | }
28 |
29 | /* have the widget be displayed in the right 'layer' */
30 | .leaflet-map-pane {
31 | z-index: auto;
32 | }
33 |
--------------------------------------------------------------------------------
/2021/03_polygons/trains.R:
--------------------------------------------------------------------------------
1 | library(sf)
2 | library(janitor)
3 | library(ggplot2)
4 | library(units)
5 | library(ggvoronoi)
6 | library(dplyr)
7 | library(ggtext)
8 |
9 | # Get Israel map, unnest to coordinates as polygons.
10 | isrfull <- read_sf("data/maps/isr-full/israel_borders.shp")
11 | isrfull <- st_transform(isrfull, 4326)
12 | isr_points <- as.data.frame(st_coordinates(isrfull))
13 |
14 | # Similarly with the train station data
15 | dat <- read_sf("2021/data/rail_stat_onoff_month/RAIL_STAT_ONOFF_MONTH.shp") %>%
16 | clean_names()
17 |
18 | dat <- st_transform(dat, 4326)
19 |
20 | dat <- dat %>%
21 | st_coordinates(geometry) %>%
22 | as.data.frame()
23 |
24 | # Create Voronoi data
25 | isr_voronoi <- voronoi_polygon(data=dat,
26 | x="X",y="Y",
27 | outline=isr_points)
28 |
29 | # Converts output of voronoi_polygon to be plotted, but we'll move it to sfc_polygon for area calculation
30 | isr_voronoi <- fortify_voronoi(isr_voronoi)
31 |
32 |
33 | isr_voronoi_poloygon <- isr_voronoi %>%
34 | # Convert the coordinats of polygon to a sfc_polygon
35 | st_as_sf(coords = c("x", "y"), crs = 4326) %>%
36 | group_by(id) %>%
37 | # collect them together, keep only distinct point for train
38 | summarise(geometry = st_combine(geometry),
39 | train.y = max(point.x),
40 | train.x = max(point.x)) %>%
41 | st_cast("POLYGON")
42 |
43 | # Calculate area each train station comprises
44 | isr_voronoi_poloygon <- isr_voronoi_poloygon %>%
45 | st_transform(.,crs = 2039) %>%
46 | mutate(area = st_area(geometry),
47 | area = as.numeric(set_units(area, km^2))) %>%
48 | st_transform(crs = 4326)
49 |
50 | # Finally, plot
51 | ggplot(isr_voronoi_poloygon) +
52 | geom_sf(aes(fill = area), color = NA) +
53 | geom_point(data = dat, aes(x = X, y = Y), inherit.aes = FALSE, size = 0.05, alpha = 0.7)+
54 | # Ignore the limits; played a little with adding white spice but removed for now
55 | coord_sf(xlim = c(min(isr_voronoi$x), max(isr_voronoi$x)))+
56 | scale_fill_gradientn("Area (km2)",
57 | colors=viridis::plasma(10), trans = "log", breaks = c(10,100,1000,8000), labels = scales::comma)+
58 | labs(title = "Nearest Train Station",
59 | subtitle = "The nearest train station for land areas in Israel.\nAll locations in an area are closer to that train\nstation (dot) than to any other",
60 | caption = "Data: Ministry of Transport | @Amit_Levinson")+
61 | theme_minimal()+
62 | theme(
63 | text = element_text(family = "Raleway"),
64 | plot.title = element_text(size = 18, "Playfair Display"),
65 | plot.title.position = "plot",
66 | plot.subtitle = element_text(size = 12),
67 | axis.text = element_blank(),
68 | axis.title = element_blank(),
69 | panel.grid = element_blank(),
70 | legend.title = element_markdown(size = 10),
71 | plot.caption = element_text(hjust = 0.5, size = 8, color = "gray15"),
72 | legend.text = element_text(size = 8),
73 | plot.margin = margin(6,2,6,2,"mm"),
74 | panel.background = element_rect(fill = "white", color = NA),
75 | plot.background = element_rect(fill = "white", color = NA)
76 |
77 | )
78 |
79 | ggsave("2021/03_polygons/trains.png", width = 8, height = 7)
80 |
--------------------------------------------------------------------------------
/2021/03_polygons/trains.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/03_polygons/trains.png
--------------------------------------------------------------------------------
/2021/04_hexagons/busstops.R:
--------------------------------------------------------------------------------
1 | library(dplyr)
2 | library(sf)
3 | library(ggplot2)
4 | library(viridis)
5 | library(ggtext)
6 | library(data.table)
7 |
8 | # Get Israel map, unnest to coordinates as polygons.
9 | isrfull <- read_sf("data/maps/isr-full/israel_borders.shp") %>%
10 | st_transform(crs = 2039)
11 |
12 | # read data for Novemeber 3
13 | dat <- fread("https://openmobilitydata-data.s3-us-west-1.amazonaws.com/public/feeds/ministry-of-transport-and-road-safety/820/20211103/original/stops.txt")
14 |
15 | dat_clean <- dat %>%
16 | distinct(stop_lon, stop_lat, stop_id)
17 |
18 | # filter to dsitinct stop_id (which it should be)
19 | datsf <- dat_clean %>%
20 | select(stop_lon, stop_lat,stop_id, stop_id) %>%
21 | st_as_sf(coords = c("stop_lon", "stop_lat")) %>%
22 | st_set_crs(4326) %>%
23 | st_transform(crs = 2039)
24 |
25 | # Make grids
26 | isrfull_grid <- st_make_grid(isrfull, cellsize = 5000 , square = FALSE)
27 | # Get only intersecting grids
28 | grid_rds <- st_as_sf(st_intersection(isrfull_grid, isrfull))
29 |
30 | # Add a unique id
31 | grid_rds <- st_as_sf(grid_rds) %>%
32 | mutate(id = 1:nrow(.))
33 |
34 |
35 | # Join grid and stops
36 | gridpoint_joined <- st_join(grid_rds, datsf, left = TRUE) %>%
37 | mutate(stops = ifelse(is.na(stop_id), 0,1))
38 |
39 | # for some reason I can't aggregate in the geometry object level, so use id instead:
40 | stops_per_grid <- gridpoint_joined %>%
41 | st_drop_geometry() %>%
42 | group_by(id) %>%
43 | summarise(stops = sum(stops)) %>%
44 | mutate(stops = na_if(stops, 0))
45 |
46 | # Join back to grid object
47 | full_grid_stops <- grid_rds %>%
48 | left_join(stops_per_grid) %>%
49 | st_transform(crs = 4326)
50 |
51 |
52 | ggplot(full_grid_stops)+
53 | geom_sf(aes(fill = stops), size = 0.1, color = "gray15")+
54 | scale_fill_viridis(name = "Bus stops", trans = "log", breaks = c(1,10,100,500))+
55 | labs(title = "Bus stops per 5km^2",
56 | caption = "Data: OpenMobilityData (11/3/2021) | Visualization: Amit_Levinson")+
57 | coord_sf(xlim = c(33.5,36))+
58 |
59 | theme(
60 | panel.background = element_rect(fill = "white", color = NA),
61 | plot.background = element_rect(fill = "white", color = NA),
62 | text = element_text(family = "Roboto"),
63 | plot.title = element_markdown(size = 18, "Merriweather", hjust = 1, face = "bold"),
64 | plot.title.position = "plot",
65 | plot.subtitle = element_text(size = 12),
66 | axis.text = element_blank(),
67 | axis.title = element_blank(),
68 | axis.ticks = element_blank(),
69 | panel.grid = element_blank(),
70 | legend.title = element_markdown(size = 10, color = "gray15", hjust = 0),
71 | plot.caption = element_text(hjust = 0.5, size = 8, color = "gray35"),
72 | legend.text = element_text(size = 8, hjust = 0, color = "gray15"),
73 | legend.position=c(0.3,0.75),
74 | legend.background = element_blank(),
75 | plot.margin = margin(6,2,6,2,"mm")
76 | )
77 |
78 | ggsave("2021/04_hexagons/stops.png", width= 8, height= 7)
79 |
--------------------------------------------------------------------------------
/2021/04_hexagons/stops.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/04_hexagons/stops.png
--------------------------------------------------------------------------------
/2021/05_osm/street.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/05_osm/street.png
--------------------------------------------------------------------------------
/2021/05_osm/streets.R:
--------------------------------------------------------------------------------
1 | library(osmdata)
2 | library(sf)
3 | library(dplyr)
4 | library(ggplot2)
5 | library(patchwork)
6 | junebug::font_hoist("Alegreya") # Hoist Alegreya to enjoy its various weights
7 |
8 |
9 | # Data collections & setup ------------------------------------------------
10 |
11 | # Wrap the street collection info into a function:
12 |
13 | large_features <- c("motorway","primary","secondary", "tertiary")
14 | small_features <- c("residential", "living_street", "unclassified", "service", "footway")
15 |
16 | get_osm_data <- function (city, features) {
17 | getbb(city)%>%
18 | opq()%>%
19 | add_osm_feature(key = "highway",
20 | value = features) %>%
21 | osmdata_sf()
22 |
23 | }
24 |
25 |
26 | jlm_large <- get_osm_data("Jerusalem, IL", features = large_features)
27 | jlm_small <- get_osm_data("Jerusalem, IL", features = small_features)
28 |
29 | ny_large <- get_osm_data("Manhattan, NY", features = large_features)
30 | ny_small <- get_osm_data("Manhattan, NY", features = small_features)
31 |
32 |
33 |
34 | # Plot --------------------------------------------------------------------
35 |
36 | theme_set(theme_void())
37 |
38 |
39 | generate_plot <- function(large, small, title, glowsigma, glowexpand) {
40 | ggplot(data = small$osm_lines)+
41 | geom_sf(color = "gray15", size = 0.2)+
42 | with_outer_glow(
43 | geom_sf(data =large$osm_lines, inherit.aes = FALSE),
44 | colour = "yellow",
45 | sigma = glowsigma,
46 | expand = glowexpand
47 | )+
48 |
49 | labs(title = title) +
50 | theme (
51 | plot.title = element_text(size = 25, hjust = 0.5, family = "Alegreya Bold"),
52 | # For some reason I add this to solve FaceBook issues :(
53 | panel.background = element_rect(fill = "white", color = NA),
54 | plot.background = element_rect(fill = "white", color = NA)
55 | )
56 | }
57 |
58 |
59 | # Combine -----------------------------------------------------------------
60 |
61 | pny <- generate_plot(ny_large, ny_small, title = "Manhattan", glowsigma = 0.5, glowexpand = 1)
62 | pjlm <- generate_plot(jlm_large, jlm_small, title = "Jerusalem", glowsigma = 0.75, glowexpand = 1.5)
63 |
64 | combined <- pny + pjlm +
65 | plot_annotation(
66 | caption = "Data: OSM | Amit_Levinson",
67 | theme = theme(
68 | plot.caption = element_text(size = 11, family = "Alegreya", color = "gray25", hjust = 0),
69 | plot.margin = margin(4,0,4,0,"mm")
70 | ))
71 |
72 | ggsave("2021/05_osm/street.png" ,plot = combined, width = 13, height = 8)
73 |
--------------------------------------------------------------------------------
/2021/06_red/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
13 |
14 |
15 |
16 |
17 |
43 |
44 |
--------------------------------------------------------------------------------
/2021/06_red/map-screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/06_red/map-screenshot.png
--------------------------------------------------------------------------------
/2021/07_green/bikelanes.R:
--------------------------------------------------------------------------------
1 | library(sf)
2 | library(dplyr)
3 | library(ggplot2)
4 |
5 | # Get Tel Aviv shapefile to extract points for routes
6 | tel_aviv_file_name <- list.files(pattern =".Aviv.+\\.shp$", recursive = TRUE)
7 | tel_aviv_file <- read_sf(paste0(tel_aviv_file_name))
8 |
9 | # Provide relevant crs to Tel-Aviv
10 | tel_aviv_file <- st_transform(st_set_crs(tel_aviv_file, 2039), 4326)
11 |
12 | biketrail <- read_sf("2021/data/biketrail/Bicycle Routes.shp")
13 |
14 |
15 | # Calculate length of routes ------------------------------------------------------------
16 |
17 | trail_length <- st_transform(biketrail, 2039)
18 |
19 | trail_length %>%
20 | filter(!is.na(direction)) %>%
21 | st_length() %>%
22 | sum()
23 |
24 | # plot
25 | ggplot(tel_aviv_file)+
26 | geom_sf(fill = "white", color = "black", size = 0.25)+
27 | geom_sf(data = biketrail, inherit.aes = FALSE, color = '#50C878')+
28 | theme_void()+
29 | coord_sf()+
30 | labs(title = "Bike Lanes in Tel-Aviv",
31 | caption = "Data: Tel-Aviv Open Data | Amit_Levinson")+
32 | theme(
33 | text = element_text(family = 'Playfair Display'),
34 | plot.title = element_text(hjust = 0.5, family = 'Playfair Display', face="bold", size = 19),
35 | plot.caption = element_text(hjust = 0.5, size = 8, color = "gray20"),
36 | plot.background = element_rect(fill = '#E9E9E9', color = NA),
37 | panel.background = element_rect(fill = '#E9E9E9', color = NA),
38 | plot.margin = margin(4,2,2,4,"mm")
39 | )
40 |
41 | ggsave("2021/07_green/bikelanes.png", width = 5, height = 6)
42 |
--------------------------------------------------------------------------------
/2021/07_green/bikelanes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/07_green/bikelanes.png
--------------------------------------------------------------------------------
/2021/08_blue/wave.R:
--------------------------------------------------------------------------------
1 | library(sf)
2 | library(ggmap)
3 | library(ggtext)
4 |
5 | tel_aviv_file_name <- list.files(pattern =".Aviv.+\\.shp$", recursive = TRUE)
6 | tel_aviv_file <- read_sf(paste0(tel_aviv_file_name))
7 |
8 | # Provide relevant crs to Tel-Aviv
9 | tel_aviv_file <- st_transform(st_set_crs(tel_aviv_file, 2039), 4326)
10 |
11 | wave <- read_sf("2021/data/wave/tsunami 5 meter line.shp") %>%
12 | st_transform(., crs = 4326) %>%
13 | st_intersection(., tel_aviv_file)
14 |
15 | telavivggmap <- get_googlemap(center = "tel aviv, israel", zoom = 13,style=c(feature="all",element="labels",visibility="off"))
16 |
17 | ggmap(telavivggmap)+
18 | geom_sf(data = wave, inherit.aes = FALSE, fill = NA, color = "#1f73b7", size =1.25)+
19 | labs(title = "Area covered by a 5 meter tsunami wave in Tel-Aviv",
20 | caption = "Data: Tel-Aviv Open Data | Amit_Levinson")+
21 | theme_void()+
22 | theme(
23 | text = element_text(family = "Roboto Condensed"),
24 | plot.title = element_markdown(hjust = 0.5, size = 18, face = "bold"),
25 | panel.background = element_rect(fill = "white", color = NA),
26 | plot.background = element_rect(fill = "white", color = NA),
27 | plot.caption = element_text(size = 10, color = "gray15")
28 | )
29 |
30 | ggsave("2021/08_blue/wave.png", width = 7, height = 8)
31 |
32 |
--------------------------------------------------------------------------------
/2021/08_blue/wave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/08_blue/wave.png
--------------------------------------------------------------------------------
/2021/09_monochrome/israelbw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/09_monochrome/israelbw.png
--------------------------------------------------------------------------------
/2021/09_monochrome/monochrome.R:
--------------------------------------------------------------------------------
1 | library(elevatr)
2 | library(rayshader)
3 | library(sf)
4 |
5 | # Get Israel map for extracting raster layer below, you can also use the {rgeoboundaries} instead
6 | # to get boundaries of a country you're interested in.
7 | isrfull <- read_sf("data/maps/isr-full/israel_borders.shp")
8 | isrfull <- st_transform(isrfull, 4326)
9 |
10 | # Get elevation data
11 | isrraster <- get_elev_raster(locations = isrfull, z = 9, clip = "locations")
12 |
13 | # Convert to matrix for rayshader plotting
14 | isrrayshader = raster_to_matrix(isrraster)
15 |
16 | isrrayshader %>%
17 | sphere_shade(texture = "bw") %>%
18 | plot_3d(isrrayshader, zscale = 10, fov = 0, theta = 0, zoom = 0.9, phi = 45, windowsize = c(1000, 800))
19 |
20 | render_snapshot("2021/09_monochrome/israelbw",
21 | title_text = "Israel's\nElevation",
22 | title_offset = c(60,50),
23 | title_color = "black",
24 | title_size = 40,
25 | title_font = "PT Serif",
26 | vignette = 0.1)
27 |
--------------------------------------------------------------------------------
/2021/10_raster/walk_from_dizengof_files/Proj4Leaflet-1.0.1/proj4leaflet.js:
--------------------------------------------------------------------------------
1 | (function (factory) {
2 | var L, proj4;
3 | if (typeof define === 'function' && define.amd) {
4 | // AMD
5 | define(['leaflet', 'proj4'], factory);
6 | } else if (typeof module === 'object' && typeof module.exports === "object") {
7 | // Node/CommonJS
8 | L = require('leaflet');
9 | proj4 = require('proj4');
10 | module.exports = factory(L, proj4);
11 | } else {
12 | // Browser globals
13 | if (typeof window.L === 'undefined' || typeof window.proj4 === 'undefined')
14 | throw 'Leaflet and proj4 must be loaded first';
15 | factory(window.L, window.proj4);
16 | }
17 | }(function (L, proj4) {
18 | if (proj4.__esModule && proj4.default) {
19 | // If proj4 was bundled as an ES6 module, unwrap it to get
20 | // to the actual main proj4 object.
21 | // See discussion in https://github.com/kartena/Proj4Leaflet/pull/147
22 | proj4 = proj4.default;
23 | }
24 |
25 | L.Proj = {};
26 |
27 | L.Proj._isProj4Obj = function(a) {
28 | return (typeof a.inverse !== 'undefined' &&
29 | typeof a.forward !== 'undefined');
30 | };
31 |
32 | L.Proj.Projection = L.Class.extend({
33 | initialize: function(code, def, bounds) {
34 | var isP4 = L.Proj._isProj4Obj(code);
35 | this._proj = isP4 ? code : this._projFromCodeDef(code, def);
36 | this.bounds = isP4 ? def : bounds;
37 | },
38 |
39 | project: function (latlng) {
40 | var point = this._proj.forward([latlng.lng, latlng.lat]);
41 | return new L.Point(point[0], point[1]);
42 | },
43 |
44 | unproject: function (point, unbounded) {
45 | var point2 = this._proj.inverse([point.x, point.y]);
46 | return new L.LatLng(point2[1], point2[0], unbounded);
47 | },
48 |
49 | _projFromCodeDef: function(code, def) {
50 | if (def) {
51 | proj4.defs(code, def);
52 | } else if (proj4.defs[code] === undefined) {
53 | var urn = code.split(':');
54 | if (urn.length > 3) {
55 | code = urn[urn.length - 3] + ':' + urn[urn.length - 1];
56 | }
57 | if (proj4.defs[code] === undefined) {
58 | throw 'No projection definition for code ' + code;
59 | }
60 | }
61 |
62 | return proj4(code);
63 | }
64 | });
65 |
66 | L.Proj.CRS = L.Class.extend({
67 | includes: L.CRS,
68 |
69 | options: {
70 | transformation: new L.Transformation(1, 0, -1, 0)
71 | },
72 |
73 | initialize: function(a, b, c) {
74 | var code,
75 | proj,
76 | def,
77 | options;
78 |
79 | if (L.Proj._isProj4Obj(a)) {
80 | proj = a;
81 | code = proj.srsCode;
82 | options = b || {};
83 |
84 | this.projection = new L.Proj.Projection(proj, options.bounds);
85 | } else {
86 | code = a;
87 | def = b;
88 | options = c || {};
89 | this.projection = new L.Proj.Projection(code, def, options.bounds);
90 | }
91 |
92 | L.Util.setOptions(this, options);
93 | this.code = code;
94 | this.transformation = this.options.transformation;
95 |
96 | if (this.options.origin) {
97 | this.transformation =
98 | new L.Transformation(1, -this.options.origin[0],
99 | -1, this.options.origin[1]);
100 | }
101 |
102 | if (this.options.scales) {
103 | this._scales = this.options.scales;
104 | } else if (this.options.resolutions) {
105 | this._scales = [];
106 | for (var i = this.options.resolutions.length - 1; i >= 0; i--) {
107 | if (this.options.resolutions[i]) {
108 | this._scales[i] = 1 / this.options.resolutions[i];
109 | }
110 | }
111 | }
112 |
113 | this.infinite = !this.options.bounds;
114 |
115 | },
116 |
117 | scale: function(zoom) {
118 | var iZoom = Math.floor(zoom),
119 | baseScale,
120 | nextScale,
121 | scaleDiff,
122 | zDiff;
123 | if (zoom === iZoom) {
124 | return this._scales[zoom];
125 | } else {
126 | // Non-integer zoom, interpolate
127 | baseScale = this._scales[iZoom];
128 | nextScale = this._scales[iZoom + 1];
129 | scaleDiff = nextScale - baseScale;
130 | zDiff = (zoom - iZoom);
131 | return baseScale + scaleDiff * zDiff;
132 | }
133 | },
134 |
135 | zoom: function(scale) {
136 | // Find closest number in this._scales, down
137 | var downScale = this._closestElement(this._scales, scale),
138 | downZoom = this._scales.indexOf(downScale),
139 | nextScale,
140 | nextZoom,
141 | scaleDiff;
142 | // Check if scale is downScale => return array index
143 | if (scale === downScale) {
144 | return downZoom;
145 | }
146 | if (downScale === undefined) {
147 | return -Infinity;
148 | }
149 | // Interpolate
150 | nextZoom = downZoom + 1;
151 | nextScale = this._scales[nextZoom];
152 | if (nextScale === undefined) {
153 | return Infinity;
154 | }
155 | scaleDiff = nextScale - downScale;
156 | return (scale - downScale) / scaleDiff + downZoom;
157 | },
158 |
159 | distance: L.CRS.Earth.distance,
160 |
161 | R: L.CRS.Earth.R,
162 |
163 | /* Get the closest lowest element in an array */
164 | _closestElement: function(array, element) {
165 | var low;
166 | for (var i = array.length; i--;) {
167 | if (array[i] <= element && (low === undefined || low < array[i])) {
168 | low = array[i];
169 | }
170 | }
171 | return low;
172 | }
173 | });
174 |
175 | L.Proj.GeoJSON = L.GeoJSON.extend({
176 | initialize: function(geojson, options) {
177 | this._callLevel = 0;
178 | L.GeoJSON.prototype.initialize.call(this, geojson, options);
179 | },
180 |
181 | addData: function(geojson) {
182 | var crs;
183 |
184 | if (geojson) {
185 | if (geojson.crs && geojson.crs.type === 'name') {
186 | crs = new L.Proj.CRS(geojson.crs.properties.name);
187 | } else if (geojson.crs && geojson.crs.type) {
188 | crs = new L.Proj.CRS(geojson.crs.type + ':' + geojson.crs.properties.code);
189 | }
190 |
191 | if (crs !== undefined) {
192 | this.options.coordsToLatLng = function(coords) {
193 | var point = L.point(coords[0], coords[1]);
194 | return crs.projection.unproject(point);
195 | };
196 | }
197 | }
198 |
199 | // Base class' addData might call us recursively, but
200 | // CRS shouldn't be cleared in that case, since CRS applies
201 | // to the whole GeoJSON, inluding sub-features.
202 | this._callLevel++;
203 | try {
204 | L.GeoJSON.prototype.addData.call(this, geojson);
205 | } finally {
206 | this._callLevel--;
207 | if (this._callLevel === 0) {
208 | delete this.options.coordsToLatLng;
209 | }
210 | }
211 | }
212 | });
213 |
214 | L.Proj.geoJson = function(geojson, options) {
215 | return new L.Proj.GeoJSON(geojson, options);
216 | };
217 |
218 | L.Proj.ImageOverlay = L.ImageOverlay.extend({
219 | initialize: function (url, bounds, options) {
220 | L.ImageOverlay.prototype.initialize.call(this, url, null, options);
221 | this._projectedBounds = bounds;
222 | },
223 |
224 | // Danger ahead: Overriding internal methods in Leaflet.
225 | // Decided to do this rather than making a copy of L.ImageOverlay
226 | // and doing very tiny modifications to it.
227 | // Future will tell if this was wise or not.
228 | _animateZoom: function (event) {
229 | var scale = this._map.getZoomScale(event.zoom);
230 | var northWest = L.point(this._projectedBounds.min.x, this._projectedBounds.max.y);
231 | var offset = this._projectedToNewLayerPoint(northWest, event.zoom, event.center);
232 |
233 | L.DomUtil.setTransform(this._image, offset, scale);
234 | },
235 |
236 | _reset: function () {
237 | var zoom = this._map.getZoom();
238 | var pixelOrigin = this._map.getPixelOrigin();
239 | var bounds = L.bounds(
240 | this._transform(this._projectedBounds.min, zoom)._subtract(pixelOrigin),
241 | this._transform(this._projectedBounds.max, zoom)._subtract(pixelOrigin)
242 | );
243 | var size = bounds.getSize();
244 |
245 | L.DomUtil.setPosition(this._image, bounds.min);
246 | this._image.style.width = size.x + 'px';
247 | this._image.style.height = size.y + 'px';
248 | },
249 |
250 | _projectedToNewLayerPoint: function (point, zoom, center) {
251 | var viewHalf = this._map.getSize()._divideBy(2);
252 | var newTopLeft = this._map.project(center, zoom)._subtract(viewHalf)._round();
253 | var topLeft = newTopLeft.add(this._map._getMapPanePos());
254 |
255 | return this._transform(point, zoom)._subtract(topLeft);
256 | },
257 |
258 | _transform: function (point, zoom) {
259 | var crs = this._map.options.crs;
260 | var transformation = crs.transformation;
261 | var scale = crs.scale(zoom);
262 |
263 | return transformation.transform(point, scale);
264 | }
265 | });
266 |
267 | L.Proj.imageOverlay = function (url, bounds, options) {
268 | return new L.Proj.ImageOverlay(url, bounds, options);
269 | };
270 |
271 | return L.Proj;
272 | }));
273 |
--------------------------------------------------------------------------------
/2021/10_raster/walk_from_dizengof_files/leaflet-1.3.1/images/layers-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/10_raster/walk_from_dizengof_files/leaflet-1.3.1/images/layers-2x.png
--------------------------------------------------------------------------------
/2021/10_raster/walk_from_dizengof_files/leaflet-1.3.1/images/layers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/10_raster/walk_from_dizengof_files/leaflet-1.3.1/images/layers.png
--------------------------------------------------------------------------------
/2021/10_raster/walk_from_dizengof_files/leaflet-1.3.1/images/marker-icon-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/10_raster/walk_from_dizengof_files/leaflet-1.3.1/images/marker-icon-2x.png
--------------------------------------------------------------------------------
/2021/10_raster/walk_from_dizengof_files/leaflet-1.3.1/images/marker-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/10_raster/walk_from_dizengof_files/leaflet-1.3.1/images/marker-icon.png
--------------------------------------------------------------------------------
/2021/10_raster/walk_from_dizengof_files/leaflet-1.3.1/images/marker-shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/10_raster/walk_from_dizengof_files/leaflet-1.3.1/images/marker-shadow.png
--------------------------------------------------------------------------------
/2021/10_raster/walk_from_dizengof_files/leafletfix-1.0.0/leafletfix.css:
--------------------------------------------------------------------------------
1 | /* Work around CSS properties introduced on img by bootstrap */
2 | img.leaflet-tile {
3 | padding: 0;
4 | margin: 0;
5 | border-radius: 0;
6 | border: none;
7 | }
8 | .info {
9 | padding: 6px 8px;
10 | font: 14px/16px Arial, Helvetica, sans-serif;
11 | background: white;
12 | background: rgba(255,255,255,0.8);
13 | box-shadow: 0 0 15px rgba(0,0,0,0.2);
14 | border-radius: 5px;
15 | }
16 | .legend {
17 | line-height: 18px;
18 | color: #555;
19 | }
20 | .legend svg text {
21 | fill: #555;
22 | }
23 | .legend svg line {
24 | stroke: #555;
25 | }
26 | .legend i {
27 | width: 18px;
28 | height: 18px;
29 | margin-right: 4px;
30 | opacity: 0.7;
31 | display: inline-block;
32 | vertical-align: top;
33 | /*For IE 7*/
34 | zoom: 1;
35 | *display: inline;
36 | }
37 |
--------------------------------------------------------------------------------
/2021/10_raster/walk_from_dizengof_files/rstudio_leaflet-1.3.1/images/1px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/10_raster/walk_from_dizengof_files/rstudio_leaflet-1.3.1/images/1px.png
--------------------------------------------------------------------------------
/2021/10_raster/walk_from_dizengof_files/rstudio_leaflet-1.3.1/rstudio_leaflet.css:
--------------------------------------------------------------------------------
1 | .leaflet-tooltip.leaflet-tooltip-text-only,
2 | .leaflet-tooltip.leaflet-tooltip-text-only:before,
3 | .leaflet-tooltip.leaflet-tooltip-text-only:after {
4 | background: none;
5 | border: none;
6 | box-shadow: none;
7 | }
8 |
9 | .leaflet-tooltip.leaflet-tooltip-text-only.leaflet-tooltip-left {
10 | margin-left: 5px;
11 | }
12 |
13 | .leaflet-tooltip.leaflet-tooltip-text-only.leaflet-tooltip-right {
14 | margin-left: -5px;
15 | }
16 |
17 | .leaflet-tooltip:after {
18 | border-right: 6px solid transparent;
19 | /* right: -16px; */
20 | }
21 |
22 | .leaflet-popup-pane .leaflet-popup-tip-container {
23 | /* when the tooltip container is clicked, it is closed */
24 | pointer-events: all;
25 | /* tooltips should display the "hand" icon, just like .leaflet-interactive*/
26 | cursor: pointer;
27 | }
28 |
29 | /* have the widget be displayed in the right 'layer' */
30 | .leaflet-map-pane {
31 | z-index: auto;
32 | }
33 |
--------------------------------------------------------------------------------
/2021/10_raster/walking.R:
--------------------------------------------------------------------------------
1 | library(stars)
2 | library(sf)
3 | library(htmltools)
4 | library(leaflet)
5 | library(raster)
6 | # remotes::install_github("GIScience/openrouteservice-r")
7 | library(openrouteservice)
8 | library(htmlwidgets)
9 | library(webshot)
10 |
11 | ta_iso <- ors_isochrones(locations = data.frame(x= 34.774225,y = 32.077915),
12 | profile = "foot-walking",
13 | range = 1800,
14 | interval = 300,
15 | output = "sf")
16 |
17 | ta_iso_min <- ta_iso %>%
18 | mutate(value = value / 60)
19 |
20 |
21 | # rasterize
22 | ta_raster <- raster(nrow = 270 , ncols = 450, ext = extent(ta_iso_min[,1:2]))
23 | ta_raster <- rasterize(ta_iso_min[,1:2], ta_raster, field = "value", fun = min)
24 |
25 | # Add crs to raster
26 | crs(ta_raster) <- CRS("+init=epsg:4326")
27 |
28 | bins <- seq(0,30,5)
29 |
30 | # Create color scale
31 | s <- colorRampPalette(c( "#FFFFCC", "#41B6C4"))
32 | palcolors <- s(6)
33 |
34 | pal <- colorBin(palcolors, domain = ta_raster, bins = seq(0,30,5), na.color = NA)
35 |
36 |
37 | p <- leaflet() %>%
38 | addTiles() %>%
39 | addRasterImage(ta_raster, colors = palcolors, opacity = 0.8) %>%
40 | addLegend(pal = pal, values = values(ta_raster), title = "Minutes walking", position = "bottomright", opacity = 0.8) %>%
41 | addControl(html = paste(tags$h1(HTML("Walking from
Dizengoff square"), style = "color:black; font-family:Merriweather; font-size: 26pt; padding-left: 8px; line-height: 1.2em;"),
42 | tags$div(HTML("How far can you reach when
walking away from Dizengoff
square, Tel-Aviv, IL."), style = "color:black; font-family:Segoe UI; font-size: 15pt; padding-left: 8px; margin-top:-20px")), className = "fieldset {
43 | border: 0;
44 | }", position = "topleft") %>%
45 | addControl(html = tags$div(HTML("Data: openrouteservice • Amit_Levinson"), style = "color:black; font-family:Segoe UI; font-size: 12pt; padding-left: 15px;"), className = "fieldset {border: 0;}", position = "bottomleft")
46 |
47 | # Save widget
48 | saveWidget(p, "2021/10_raster/walk_from_dizengof.html")
49 | # Save snapshot
50 | webshot("2021/10_raster/walk_from_dizengof.html", file = "2021/10_raster/walking.png", zoom = 3, vwidth = 900, vheight = 700)
51 |
--------------------------------------------------------------------------------
/2021/10_raster/walking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/10_raster/walking.png
--------------------------------------------------------------------------------
/2021/11_3d/3d.R:
--------------------------------------------------------------------------------
1 | library(rayshader)
2 | library(rayvista)
3 | # devtools::install_github("h-a-graham/rayvista", dependencies=TRUE)
4 | library(rayrender)
5 |
6 | lat <- 30.609379
7 | long <- 34.884477
8 |
9 |
10 | ramon <- plot_3d_vista(lat = lat, long = long, radius= 9000, overlay_detail = 14,
11 | cache_dir = '2021/11_3d/cache',theta=25, phi=25,
12 | windowsize = 800)
13 |
14 |
15 | render_snapshot("2021/11_3d/ramon",
16 | title_text = "Ramon Crater",
17 | title_offset = c(60,50),
18 | title_color = "black",
19 | title_size = 40,
20 | title_font = "Playfair Display",
21 | vignette = 0.1,
22 | clear = TRUE)
23 |
--------------------------------------------------------------------------------
/2021/11_3d/ramon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/11_3d/ramon.png
--------------------------------------------------------------------------------
/2021/13_natural-earth/visited.R:
--------------------------------------------------------------------------------
1 |
2 | ## Code credited to gist from below and the d6berlin R package!
3 | ## Also thanks to Georgios for pointing it out @geokaramanis
4 |
5 | library(sf)
6 | library(rnaturalearth)
7 | library(ggplot2)
8 | library(dplyr)
9 | library(patchwork)
10 |
11 | # Process -----------------------------------------------------------------
12 |
13 | ## code to preserve orthpgraphic view from this gist:
14 | ## https://gist.github.com/fzenoni/ef23faf6d1ada5e4a91c9ef23b0ba2c1
15 | ## via this issue: https://github.com/r-spatial/sf/issues/1050
16 |
17 |
18 | ## Load country data
19 | mini_world <- rnaturalearth::ne_countries(scale = "medium", returnclass = "sf")
20 |
21 |
22 | ## Define the orthographic projection ........................................
23 | lat <- 20
24 | lon <- 40
25 |
26 | ortho <- paste0('+proj=ortho +lat_0=', lat, ' +lon_0=', lon,
27 | ' +x_0=0 +y_0=0 +a=6371000 +b=6371000 +units=m +no_defs')
28 |
29 | ## Define the polygon to split what lies within and without your projection ..
30 | circle <-
31 | suppressMessages(
32 | sf::st_point(x = c(0, 0)) %>%
33 | sf::st_buffer(dist = 6371000) %>%
34 | sf::st_sfc(crs = ortho)
35 | )
36 | ## Project this polygon in lat-lon ...........................................
37 | circle_longlat <-
38 | circle %>%
39 | sf::st_transform(crs = 4326)
40 |
41 | ## You must decompose it into a string with ordered longitudes
42 | ## Then complete the polygon definition to cover the hemisphere ..............
43 | if(lat != 0) {
44 | circle_longlat <- sf::st_boundary(circle_longlat)
45 |
46 | circle_coords <- sf::st_coordinates(circle_longlat)[, c(1,2)]
47 | circle_coords <- circle_coords[order(circle_coords[, 1]),]
48 | circle_coords <- circle_coords[!duplicated(circle_coords),]
49 |
50 | ## Rebuild line ............................................................
51 | circle_longlat <-
52 | sf::st_linestring(circle_coords) %>%
53 | sf::st_sfc(crs = 4326)
54 |
55 | if(lat > 0) {
56 | rectangle <- list(rbind(circle_coords,
57 | c(X = 180, circle_coords[nrow(circle_coords), 'Y']),
58 | c(X = 180, Y = 90),
59 | c(X = -180, Y = 90),
60 | c(X = -180, circle_coords[1, 'Y']),
61 | circle_coords[1, c('X','Y')])) %>%
62 | sf::st_polygon() %>%
63 | sf::st_sfc(crs = 4326)
64 | } else {
65 | rectangle <- list(rbind(circle_coords,
66 | c(X = 180, circle_coords[nrow(circle_coords), 'Y']),
67 | c(X = 180, Y = -90),
68 | c(X = -180, Y = -90),
69 | c(X = -180, circle_coords[1, 'Y']),
70 | circle_coords[1, c('X','Y')])) %>%
71 | sf::st_polygon() %>%
72 | sf::st_sfc(crs = 4326)
73 | }
74 |
75 | circle_longlat <- suppressMessages(sf::st_union(
76 | sf::st_make_valid(circle_longlat),
77 | sf::st_make_valid(rectangle))
78 | )
79 | }
80 |
81 | ## A small negative buffer is necessary to avoid polygons still disappearing
82 | ## in a few pathological cases ...............................................
83 | ## Comment Cédric: Doesn't work with -.09 anymore, returns empty object.
84 | ## But works also without the buffer, so using 0 here to
85 | ## return the same type of object.
86 | visible <- suppressMessages(suppressWarnings(
87 | sf::st_intersection(sf::st_make_valid(mini_world),
88 | sf::st_buffer(circle_longlat, 0)) %>%
89 | sf::st_transform(crs = ortho)
90 | ))
91 |
92 | ## Get reason why polygons are broken ........................................
93 | broken_reason <- sf::st_is_valid(visible, reason = TRUE)
94 |
95 | ## First fix NA's by decomposing them ........................................
96 | na_visible <- visible[is.na(broken_reason),]
97 | visible <- visible[!is.na(broken_reason),]
98 |
99 | ## Open and close polygons ...................................................
100 | na_visible <- sf::st_cast(na_visible, 'MULTILINESTRING') %>%
101 | sf::st_cast('LINESTRING', do_split=TRUE)
102 | na_visible <- na_visible %>%
103 | dplyr::mutate(npts = mapview::npts(geometry, by_feature = TRUE))
104 |
105 | ## Exclude polygons with less than 4 points ..................................
106 | na_visible <- na_visible %>%
107 | dplyr::filter(npts >= 4) %>%
108 | dplyr::select(-npts) %>%
109 | sf::st_cast('POLYGON')
110 |
111 | ## Fix other broken polygons .................................................
112 | broken <- which(!sf::st_is_valid(visible))
113 | for(land in broken) {
114 | result = suppressWarnings(tryCatch({
115 | visible[land,] <-
116 | sf::st_make_valid(visible[land,]) %>%
117 | sf::st_collection_extract()
118 | }, error = function(e) {
119 | visible[land,] <<- sf::st_buffer(visible[land,], 0)
120 | }))
121 | }
122 |
123 | ## Bind together the two tables ..............................................
124 | visible <- suppressMessages(rbind(visible, na_visible))
125 |
126 |
127 |
128 | # ## Inset line -----------------------------------------------------------
129 |
130 |
131 | israel_center <- filter(visible, name_long == "Israel") %>%
132 | st_centroid() %>%
133 | st_geometry() %>%
134 | st_coordinates()
135 |
136 | line_loc <- rbind(israel_center, israel_center + c(4e6, 4e6))
137 |
138 | inset_line <- st_sfc(st_linestring(line_loc), crs = ortho)
139 |
140 |
141 | # # Create globe as ggplot ....................................................
142 | p_globe <- ggplot2::ggplot()+
143 | ggplot2::geom_sf(data = circle, fill = "white") +
144 | ggplot2::geom_sf(data = circle, alpha = .5) +
145 | ggplot2::geom_sf(data = sf::st_collection_extract(visible),
146 | fill = "gray45", color = "gray55") +
147 | ggplot2::geom_sf(data = filter(visible, name_long == "Israel"), fill = "#4B0082", color = NA) +
148 | ggplot2::geom_sf(data = circle, color = "grey60", fill = NA, size = .5) +
149 | geom_sf(data = inset_line, color = "gray75", size = 0.3, linetype = "dashed")+
150 | ggplot2::coord_sf(crs = ortho) +
151 | # labs(
152 | # title = "Countries I visited in the past two years"
153 | # ) +
154 | ggplot2::theme_void() +
155 | ggplot2::theme(
156 | panel.grid.major = element_blank()
157 | )
158 |
159 |
160 |
161 | # Inset Israel ------------------------------------------------------------
162 |
163 | circle <- st_point(x = c(35, 31)) %>%
164 | st_buffer(dist = 7) %>%
165 | st_sfc(crs = ortho)
166 |
167 | israel_zoomed <- st_intersection(circle, st_set_crs(mini_world, ortho))
168 |
169 | p_small <- ggplot() +
170 | geom_sf(data = circle, color = "gray45",fill = "white")+
171 | geom_sf(data = israel_zoomed, fill = "gray55")+
172 | # Highlight Israel
173 | geom_sf(data = israel_zoomed[5], fill = "#4B0082", color = NA)+
174 | coord_sf(xlim = c(27,43), ylim = c(22, 38))+
175 | theme_void()+
176 | theme(
177 | plot.background = element_rect(fill = "transparent", color = NA)
178 | )
179 |
180 |
181 | p_globe + inset_element(p_small, left = 0.6, bottom = 0.7, right = 0.8, top = 1)+
182 | plot_annotation(
183 | title = "Countries I visited in the past year",
184 | caption = "@Amit_Levinson",
185 | theme = theme(
186 | title = element_text(size = 16, family = "Playfair Display", face = "bold", hjust = 0),
187 | plot.caption = element_text(size = 8, family = "Playfair Display", color = "gray35", hjust = 0.5),
188 | plot.margin = margin(4,8,4,8,"mm")
189 | ))
190 |
191 | ggsave("2021/13_natural-earth/visited.png", width = 8, height = 8)
192 |
193 |
--------------------------------------------------------------------------------
/2021/13_natural-earth/visited.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/13_natural-earth/visited.png
--------------------------------------------------------------------------------
/2021/17_land/land.R:
--------------------------------------------------------------------------------
1 | library(ggplot2)
2 | library(sf)
3 | library(raster)
4 | library(dplyr)
5 | library(patchwork)
6 |
7 | tel_aviv_file_name <- list.files(path = "~/isr_maps", pattern =".Aviv.+\\.shp$", recursive = TRUE)
8 | # I use the file for different projects and reference it several times from a specific folder
9 | tel_aviv_file <- read_sf(paste0("C:/Users/amitl/R_code/isr_maps/", tel_aviv_file_name))
10 |
11 | # Convert to raster
12 | r <- raster(tel_aviv_file,res =10)
13 | ras_ta <- rasterize(tel_aviv_file, r, field = 1)
14 |
15 |
16 | draw_plot <- function(ras_ta, direction) {
17 |
18 |
19 | # Turn raster object to data.frame
20 | ta_tiles <- ras_ta %>%
21 | as.data.frame(xy = TRUE) %>%
22 | filter(!is.na(layer)) %>%
23 | arrange({{direction}}) %>%
24 | # Split the raster object into deciles by id, giving us 10 equal sized groups of points.
25 | mutate(id = 1:nrow(.)) %>%
26 | mutate(point_to_labels = as.numeric(cut(id, breaks = quantile(id,probs = 0:10/10), labels = seq(10, 100, 10), include.lowest = TRUE)),
27 | # Not sure but we need to convert to numeric
28 | point_to_labels = point_to_labels * 10,
29 | # give a different color to each adjacent area
30 | fillcolor = ifelse( (point_to_labels / 10) %% 2 == 1, "#5E7893", "#2F4169"))
31 |
32 | p <- ggplot(ta_tiles)+
33 | geom_sf(data = tel_aviv_file, inherit.aes = FALSE, fill = NA, color = 'gray55')+
34 | geom_tile(aes(x = x,y = y,fill = fillcolor, color = fillcolor), size =.3, show.legend = FALSE, alpha = 0.3)+
35 | theme_void()+
36 | theme(
37 | panel.background = element_rect(fill = "white", color =NA)
38 | )+
39 | scale_fill_identity() +
40 | scale_color_identity()
41 |
42 | return (p)
43 |
44 | }
45 |
46 | # vertical and horizontal map
47 | p_hor <- draw_plot(ras_ta, direction = y)
48 | p_ver <- draw_plot(ras_ta, direction = x)
49 |
50 |
51 | p_hor + p_ver+
52 | plot_annotation(
53 | title = "Tel Aviv Split to Ten Equal Areas\n",
54 | caption = "@Amit_Levinson",
55 | theme = theme(
56 | text = element_text(family = "Lora"),
57 | plot.title = element_text(size = 24),
58 | plot.caption = element_text(size = 11, color = "gray25", hjust = 0.5),
59 | plot.margin = margin(5,3,5,3,"mm")
60 | ))
61 |
62 | ggsave("2021/17_land/ta_area.png", width= 13, height = 8)
63 |
--------------------------------------------------------------------------------
/2021/17_land/ta_area.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/17_land/ta_area.png
--------------------------------------------------------------------------------
/2021/2021.Rproj:
--------------------------------------------------------------------------------
1 | Version: 1.0
2 |
3 | RestoreWorkspace: Default
4 | SaveWorkspace: Default
5 | AlwaysSaveHistory: Default
6 |
7 | EnableCodeIndexing: Yes
8 | UseSpacesForTab: Yes
9 | NumSpacesForTab: 2
10 | Encoding: UTF-8
11 |
12 | RnwWeave: Sweave
13 | LaTeX: pdfLaTeX
14 |
--------------------------------------------------------------------------------
/2021/20_movement/ice-cream_farthest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/20_movement/ice-cream_farthest.png
--------------------------------------------------------------------------------
/2021/20_movement/ice-cream_files/Proj4Leaflet-1.0.1/proj4leaflet.js:
--------------------------------------------------------------------------------
1 | (function (factory) {
2 | var L, proj4;
3 | if (typeof define === 'function' && define.amd) {
4 | // AMD
5 | define(['leaflet', 'proj4'], factory);
6 | } else if (typeof module === 'object' && typeof module.exports === "object") {
7 | // Node/CommonJS
8 | L = require('leaflet');
9 | proj4 = require('proj4');
10 | module.exports = factory(L, proj4);
11 | } else {
12 | // Browser globals
13 | if (typeof window.L === 'undefined' || typeof window.proj4 === 'undefined')
14 | throw 'Leaflet and proj4 must be loaded first';
15 | factory(window.L, window.proj4);
16 | }
17 | }(function (L, proj4) {
18 | if (proj4.__esModule && proj4.default) {
19 | // If proj4 was bundled as an ES6 module, unwrap it to get
20 | // to the actual main proj4 object.
21 | // See discussion in https://github.com/kartena/Proj4Leaflet/pull/147
22 | proj4 = proj4.default;
23 | }
24 |
25 | L.Proj = {};
26 |
27 | L.Proj._isProj4Obj = function(a) {
28 | return (typeof a.inverse !== 'undefined' &&
29 | typeof a.forward !== 'undefined');
30 | };
31 |
32 | L.Proj.Projection = L.Class.extend({
33 | initialize: function(code, def, bounds) {
34 | var isP4 = L.Proj._isProj4Obj(code);
35 | this._proj = isP4 ? code : this._projFromCodeDef(code, def);
36 | this.bounds = isP4 ? def : bounds;
37 | },
38 |
39 | project: function (latlng) {
40 | var point = this._proj.forward([latlng.lng, latlng.lat]);
41 | return new L.Point(point[0], point[1]);
42 | },
43 |
44 | unproject: function (point, unbounded) {
45 | var point2 = this._proj.inverse([point.x, point.y]);
46 | return new L.LatLng(point2[1], point2[0], unbounded);
47 | },
48 |
49 | _projFromCodeDef: function(code, def) {
50 | if (def) {
51 | proj4.defs(code, def);
52 | } else if (proj4.defs[code] === undefined) {
53 | var urn = code.split(':');
54 | if (urn.length > 3) {
55 | code = urn[urn.length - 3] + ':' + urn[urn.length - 1];
56 | }
57 | if (proj4.defs[code] === undefined) {
58 | throw 'No projection definition for code ' + code;
59 | }
60 | }
61 |
62 | return proj4(code);
63 | }
64 | });
65 |
66 | L.Proj.CRS = L.Class.extend({
67 | includes: L.CRS,
68 |
69 | options: {
70 | transformation: new L.Transformation(1, 0, -1, 0)
71 | },
72 |
73 | initialize: function(a, b, c) {
74 | var code,
75 | proj,
76 | def,
77 | options;
78 |
79 | if (L.Proj._isProj4Obj(a)) {
80 | proj = a;
81 | code = proj.srsCode;
82 | options = b || {};
83 |
84 | this.projection = new L.Proj.Projection(proj, options.bounds);
85 | } else {
86 | code = a;
87 | def = b;
88 | options = c || {};
89 | this.projection = new L.Proj.Projection(code, def, options.bounds);
90 | }
91 |
92 | L.Util.setOptions(this, options);
93 | this.code = code;
94 | this.transformation = this.options.transformation;
95 |
96 | if (this.options.origin) {
97 | this.transformation =
98 | new L.Transformation(1, -this.options.origin[0],
99 | -1, this.options.origin[1]);
100 | }
101 |
102 | if (this.options.scales) {
103 | this._scales = this.options.scales;
104 | } else if (this.options.resolutions) {
105 | this._scales = [];
106 | for (var i = this.options.resolutions.length - 1; i >= 0; i--) {
107 | if (this.options.resolutions[i]) {
108 | this._scales[i] = 1 / this.options.resolutions[i];
109 | }
110 | }
111 | }
112 |
113 | this.infinite = !this.options.bounds;
114 |
115 | },
116 |
117 | scale: function(zoom) {
118 | var iZoom = Math.floor(zoom),
119 | baseScale,
120 | nextScale,
121 | scaleDiff,
122 | zDiff;
123 | if (zoom === iZoom) {
124 | return this._scales[zoom];
125 | } else {
126 | // Non-integer zoom, interpolate
127 | baseScale = this._scales[iZoom];
128 | nextScale = this._scales[iZoom + 1];
129 | scaleDiff = nextScale - baseScale;
130 | zDiff = (zoom - iZoom);
131 | return baseScale + scaleDiff * zDiff;
132 | }
133 | },
134 |
135 | zoom: function(scale) {
136 | // Find closest number in this._scales, down
137 | var downScale = this._closestElement(this._scales, scale),
138 | downZoom = this._scales.indexOf(downScale),
139 | nextScale,
140 | nextZoom,
141 | scaleDiff;
142 | // Check if scale is downScale => return array index
143 | if (scale === downScale) {
144 | return downZoom;
145 | }
146 | if (downScale === undefined) {
147 | return -Infinity;
148 | }
149 | // Interpolate
150 | nextZoom = downZoom + 1;
151 | nextScale = this._scales[nextZoom];
152 | if (nextScale === undefined) {
153 | return Infinity;
154 | }
155 | scaleDiff = nextScale - downScale;
156 | return (scale - downScale) / scaleDiff + downZoom;
157 | },
158 |
159 | distance: L.CRS.Earth.distance,
160 |
161 | R: L.CRS.Earth.R,
162 |
163 | /* Get the closest lowest element in an array */
164 | _closestElement: function(array, element) {
165 | var low;
166 | for (var i = array.length; i--;) {
167 | if (array[i] <= element && (low === undefined || low < array[i])) {
168 | low = array[i];
169 | }
170 | }
171 | return low;
172 | }
173 | });
174 |
175 | L.Proj.GeoJSON = L.GeoJSON.extend({
176 | initialize: function(geojson, options) {
177 | this._callLevel = 0;
178 | L.GeoJSON.prototype.initialize.call(this, geojson, options);
179 | },
180 |
181 | addData: function(geojson) {
182 | var crs;
183 |
184 | if (geojson) {
185 | if (geojson.crs && geojson.crs.type === 'name') {
186 | crs = new L.Proj.CRS(geojson.crs.properties.name);
187 | } else if (geojson.crs && geojson.crs.type) {
188 | crs = new L.Proj.CRS(geojson.crs.type + ':' + geojson.crs.properties.code);
189 | }
190 |
191 | if (crs !== undefined) {
192 | this.options.coordsToLatLng = function(coords) {
193 | var point = L.point(coords[0], coords[1]);
194 | return crs.projection.unproject(point);
195 | };
196 | }
197 | }
198 |
199 | // Base class' addData might call us recursively, but
200 | // CRS shouldn't be cleared in that case, since CRS applies
201 | // to the whole GeoJSON, inluding sub-features.
202 | this._callLevel++;
203 | try {
204 | L.GeoJSON.prototype.addData.call(this, geojson);
205 | } finally {
206 | this._callLevel--;
207 | if (this._callLevel === 0) {
208 | delete this.options.coordsToLatLng;
209 | }
210 | }
211 | }
212 | });
213 |
214 | L.Proj.geoJson = function(geojson, options) {
215 | return new L.Proj.GeoJSON(geojson, options);
216 | };
217 |
218 | L.Proj.ImageOverlay = L.ImageOverlay.extend({
219 | initialize: function (url, bounds, options) {
220 | L.ImageOverlay.prototype.initialize.call(this, url, null, options);
221 | this._projectedBounds = bounds;
222 | },
223 |
224 | // Danger ahead: Overriding internal methods in Leaflet.
225 | // Decided to do this rather than making a copy of L.ImageOverlay
226 | // and doing very tiny modifications to it.
227 | // Future will tell if this was wise or not.
228 | _animateZoom: function (event) {
229 | var scale = this._map.getZoomScale(event.zoom);
230 | var northWest = L.point(this._projectedBounds.min.x, this._projectedBounds.max.y);
231 | var offset = this._projectedToNewLayerPoint(northWest, event.zoom, event.center);
232 |
233 | L.DomUtil.setTransform(this._image, offset, scale);
234 | },
235 |
236 | _reset: function () {
237 | var zoom = this._map.getZoom();
238 | var pixelOrigin = this._map.getPixelOrigin();
239 | var bounds = L.bounds(
240 | this._transform(this._projectedBounds.min, zoom)._subtract(pixelOrigin),
241 | this._transform(this._projectedBounds.max, zoom)._subtract(pixelOrigin)
242 | );
243 | var size = bounds.getSize();
244 |
245 | L.DomUtil.setPosition(this._image, bounds.min);
246 | this._image.style.width = size.x + 'px';
247 | this._image.style.height = size.y + 'px';
248 | },
249 |
250 | _projectedToNewLayerPoint: function (point, zoom, center) {
251 | var viewHalf = this._map.getSize()._divideBy(2);
252 | var newTopLeft = this._map.project(center, zoom)._subtract(viewHalf)._round();
253 | var topLeft = newTopLeft.add(this._map._getMapPanePos());
254 |
255 | return this._transform(point, zoom)._subtract(topLeft);
256 | },
257 |
258 | _transform: function (point, zoom) {
259 | var crs = this._map.options.crs;
260 | var transformation = crs.transformation;
261 | var scale = crs.scale(zoom);
262 |
263 | return transformation.transform(point, scale);
264 | }
265 | });
266 |
267 | L.Proj.imageOverlay = function (url, bounds, options) {
268 | return new L.Proj.ImageOverlay(url, bounds, options);
269 | };
270 |
271 | return L.Proj;
272 | }));
273 |
--------------------------------------------------------------------------------
/2021/20_movement/ice-cream_files/leaflet-1.3.1/images/layers-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/20_movement/ice-cream_files/leaflet-1.3.1/images/layers-2x.png
--------------------------------------------------------------------------------
/2021/20_movement/ice-cream_files/leaflet-1.3.1/images/layers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/20_movement/ice-cream_files/leaflet-1.3.1/images/layers.png
--------------------------------------------------------------------------------
/2021/20_movement/ice-cream_files/leaflet-1.3.1/images/marker-icon-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/20_movement/ice-cream_files/leaflet-1.3.1/images/marker-icon-2x.png
--------------------------------------------------------------------------------
/2021/20_movement/ice-cream_files/leaflet-1.3.1/images/marker-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/20_movement/ice-cream_files/leaflet-1.3.1/images/marker-icon.png
--------------------------------------------------------------------------------
/2021/20_movement/ice-cream_files/leaflet-1.3.1/images/marker-shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/20_movement/ice-cream_files/leaflet-1.3.1/images/marker-shadow.png
--------------------------------------------------------------------------------
/2021/20_movement/ice-cream_files/leaflet-providers-plugin-2.0.4.1/leaflet-providers-plugin.js:
--------------------------------------------------------------------------------
1 | LeafletWidget.methods.addProviderTiles = function(provider, layerId, group, options) {
2 | this.layerManager.addLayer(L.tileLayer.provider(provider, options), "tile", layerId, group);
3 | };
4 |
--------------------------------------------------------------------------------
/2021/20_movement/ice-cream_files/leafletfix-1.0.0/leafletfix.css:
--------------------------------------------------------------------------------
1 | /* Work around CSS properties introduced on img by bootstrap */
2 | img.leaflet-tile {
3 | padding: 0;
4 | margin: 0;
5 | border-radius: 0;
6 | border: none;
7 | }
8 | .info {
9 | padding: 6px 8px;
10 | font: 14px/16px Arial, Helvetica, sans-serif;
11 | background: white;
12 | background: rgba(255,255,255,0.8);
13 | box-shadow: 0 0 15px rgba(0,0,0,0.2);
14 | border-radius: 5px;
15 | }
16 | .legend {
17 | line-height: 18px;
18 | color: #555;
19 | }
20 | .legend svg text {
21 | fill: #555;
22 | }
23 | .legend svg line {
24 | stroke: #555;
25 | }
26 | .legend i {
27 | width: 18px;
28 | height: 18px;
29 | margin-right: 4px;
30 | opacity: 0.7;
31 | display: inline-block;
32 | vertical-align: top;
33 | /*For IE 7*/
34 | zoom: 1;
35 | *display: inline;
36 | }
37 |
--------------------------------------------------------------------------------
/2021/20_movement/ice-cream_files/rstudio_leaflet-1.3.1/images/1px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/20_movement/ice-cream_files/rstudio_leaflet-1.3.1/images/1px.png
--------------------------------------------------------------------------------
/2021/20_movement/ice-cream_files/rstudio_leaflet-1.3.1/rstudio_leaflet.css:
--------------------------------------------------------------------------------
1 | .leaflet-tooltip.leaflet-tooltip-text-only,
2 | .leaflet-tooltip.leaflet-tooltip-text-only:before,
3 | .leaflet-tooltip.leaflet-tooltip-text-only:after {
4 | background: none;
5 | border: none;
6 | box-shadow: none;
7 | }
8 |
9 | .leaflet-tooltip.leaflet-tooltip-text-only.leaflet-tooltip-left {
10 | margin-left: 5px;
11 | }
12 |
13 | .leaflet-tooltip.leaflet-tooltip-text-only.leaflet-tooltip-right {
14 | margin-left: -5px;
15 | }
16 |
17 | .leaflet-tooltip:after {
18 | border-right: 6px solid transparent;
19 | /* right: -16px; */
20 | }
21 |
22 | .leaflet-popup-pane .leaflet-popup-tip-container {
23 | /* when the tooltip container is clicked, it is closed */
24 | pointer-events: all;
25 | /* tooltips should display the "hand" icon, just like .leaflet-interactive*/
26 | cursor: pointer;
27 | }
28 |
29 | /* have the widget be displayed in the right 'layer' */
30 | .leaflet-map-pane {
31 | z-index: auto;
32 | }
33 |
--------------------------------------------------------------------------------
/2021/20_movement/ice-cream_two_opt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/20_movement/ice-cream_two_opt.png
--------------------------------------------------------------------------------
/2021/20_movement/icecream.R:
--------------------------------------------------------------------------------
1 | library(sf)
2 | library(readr)
3 | library(sf)
4 | library(dplyr)
5 | library(osrm)
6 | library(stplanr)
7 | library(ggplot2)
8 | library(htmltools)
9 | library(glue)
10 | library(htmlwidgets)
11 | library(webshot)
12 | library(purrr)
13 |
14 | Sys.setlocale("LC_ALL", "Hebrew")
15 |
16 | # Get Tel Aviv shapefile to extract points for routes
17 | tel_aviv_file_name <- list.files(pattern =".Aviv.+\\.shp$", recursive = TRUE)
18 | tel_aviv_file <- read_sf(paste0(tel_aviv_file_name))
19 |
20 | # Provide relevant crs to Tel-Aviv
21 | tel_aviv_file <- st_transform(st_set_crs(tel_aviv_file, 2039), 4326)
22 |
23 | # Incomplete data (specific locations for this analysis were added manually)
24 | golda <- readxl::read_xlsx("2021/data/golda_locations.xlsx") %>%
25 | mutate(id = 1:nrow(.))
26 |
27 | golda_sf <- golda %>%
28 | st_as_sf(coords = c("long", "lat"), crs = 4326, remove = FALSE) %>%
29 | # Get only what's in Tel-Aviv
30 | filter(lengths(st_intersects(., tel_aviv_file)) > 0)
31 |
32 | # TSP analysis based on Jerry Shannon's piece:
33 | # https://twitter.com/jerry_shannon/status/1455525819066028037/photo/1
34 |
35 | distance <- st_distance(golda_sf, golda_sf)
36 | distance <- as.matrix(distance) / 1000
37 |
38 | colnames(distance) <- golda_sf$id
39 | rownames(distance) <- golda_sf$id
40 |
41 | # covert to distance matrix of upper/lower
42 | distance <- as.dist(distance)
43 |
44 | # TSP prob & solving ------------------------------------------------------
45 | tsp <- TSP(distance)
46 |
47 | # Playing around with different methods
48 | methods <- c(
49 | "nearest_insertion",
50 | "farthest_insertion",
51 | "cheapest_insertion",
52 | "arbitrary_insertion",
53 | "nn",
54 | "repetitive_nn",
55 | "two_opt"
56 | )
57 |
58 |
59 | tours <- methods %>% map(function(method) {
60 | solve_TSP(tsp, method)
61 | })
62 |
63 | # Find the optimal method (Though also I want it to be intuitive for me)
64 | dotchart(sort(c(sapply(tours, tour_length), optimal = 30)),
65 | xlab = "tour length", xlim = c(0, 35))
66 |
67 |
68 |
69 | # Go with insertion algorithm, specifically farthest, read more here:
70 | # https://cran.r-project.org/web/packages/TSP/vignettes/TSP.pdf
71 | tour <- solve_TSP(tsp, method = "farthest_insertion")
72 |
73 | # Order of locations in tour
74 | tour_order <- as.integer(tour)
75 |
76 | # get order of addresses
77 | addresses <- golda_sf[tour_order,]
78 |
79 |
80 | # Build route
81 | golda_route <- map_dfr(seq(nrow(addresses)-1), function (n){
82 | route(
83 | from = addresses[n,],
84 | to = addresses[n + 1,],
85 | route_fun = osrmRoute,
86 | returnclass = "sf") %>%
87 | mutate(section = n)
88 | })
89 |
90 | # Add location labels
91 | make_label <- function(street ){
92 | glue("{street}
") %>%
93 | HTML()}
94 |
95 | # Map map
96 | p <- leaflet() %>%
97 | addProviderTiles("CartoDB.Positron",options = providerTileOptions(minZoom = 12)) %>%
98 | addPolylines(data = golda_route, weight = 2, color = "#080E46") %>%
99 | # Add emoji as points
100 | addLabelOnlyMarkers(data = golda_sf, label = HTML("🍦"),
101 | labelOptions = labelOptions(noHide = T, textOnly = T,
102 | "font-size" = "6px")) %>%
103 | # Add a start label
104 | addLabelOnlyMarkers(data = golda_route[1,], ~fx, ~fy, label = HTML("Start
↓"),
105 | labelOptions = labelOptions(noHide = T, direction = "top", textOnly = TRUE,
106 | style = list(
107 | "color" = "#080E46",
108 | "text-align" = "center",
109 | "font-size" = "10px",
110 | "font-face" = "bold",
111 | "border-color" = "rgba(0,0,0,0.5)"))) %>%
112 | addControl(html = paste(tags$h1(HTML("Golda locations
in Tel-Aviv 🍦"), style = "color:black; font-family:Rockwell; font-size: 26pt; padding-left: 8px; line-height: 1.2em;"),
113 | tags$div(HTML("Fastest route between all
Golda ice-cream locations
in Tel-Aviv."), style = "color:black; font-family:Segoe UI; font-size: 15pt; padding-left: 8px; margin-top:-20px")), className = "fieldset {
114 | border: 0;
115 | }", position = "topleft") %>%
116 | addControl(html = tags$div(HTML("Data: Golda • Amit_Levinson • Code"), style = "color:black; font-family:Segoe UI; font-size: 12pt; padding-left: 15px;"), className = "fieldset {border: 0;}", position = "bottomleft")
117 |
118 |
119 | # Save widget
120 | saveWidget(p, "2021/20_movement/ice-cream.html")
121 | # Save snapshot
122 | webshot("2021/20_movement/ice-cream.html", file = "2021/20_movement/ice-cream_farthest.png", zoom = 3, vwidth = 900, vheight = 700, delay = 2)
123 |
124 |
--------------------------------------------------------------------------------
/2021/22_borders/borders.R:
--------------------------------------------------------------------------------
1 | library(sf)
2 | library(purrr)
3 | library(viridis)
4 | library(ggplot2)
5 | library(dplyr)
6 | library(ggtext)
7 |
8 | # Sys.setlocale("LC_ALL", "Hebrew")
9 |
10 | tel_aviv_neighborhoods_path <- list.files(pattern ="Neighbourhoods\\.shp$", recursive = TRUE)
11 | tel_aviv_neighborhoods <- read_sf(tel_aviv_neighborhoods_path) %>%
12 | st_transform(crs = 4326)
13 |
14 | # Function to count number of bordering neighbourhoods
15 | count_borders <- function (rownumber) {
16 | tel_aviv_neighborhoods[rownumber,] %>%
17 | st_touches(tel_aviv_neighborhoods) %>%
18 | unlist() %>%
19 | length()
20 | }
21 |
22 | ta <- tel_aviv_neighborhoods %>%
23 | mutate(
24 | # Wrap in purrr::possibly as it might result in NA's and throw an error if your sf is messy:(
25 | n_borders = map_dbl(seq(nrow(.)), possibly(count_borders, NA_real_))
26 | )
27 |
28 | yarkon_arrow <- ta %>%
29 | filter(n_borders == max(n_borders)) %>%
30 | st_centroid() %>%
31 | st_coordinates()
32 |
33 |
34 | ta %>%
35 | ggplot()+
36 | geom_sf(aes(fill = n_borders), color = "gray5", size = 0.1)+
37 | annotate(geom = "curve", x = yarkon_arrow[1] -0.003, xend = yarkon_arrow[1] , y = yarkon_arrow[2] - 0.015, yend = yarkon_arrow[2]-0.003,
38 | curvature =.1, color = "gray25", size = 0.5, arrow = arrow(length = unit(2, "mm")))+
39 | geom_richtext(aes(x = yarkon_arrow[1] -0.003, y = yarkon_arrow[2] - 0.0155, label = "The *Yarkon*, bordering
15 other neighborhoods", hjust = 0, vjust = 1),label.color = NA, fill = NA, size = 6, family = "Mukta", color = "gray35")+
40 | labs(title = "Bordering Neighborhoods in Tel-Aviv",
41 | subtitle = "Number of neighborhoods each neighborhood borders in Tel-Aviv",
42 | caption = "@Amit_Levinson"
43 | )+
44 | scale_fill_viridis(name = "# borders",option="magma")+
45 | guides(fill = guide_colorbar(barheight = unit(2.2, units = "mm"), barwidth = unit(45, units = "mm"),
46 | ticks.colour = "gray25", title.position = "top", label.position = "bottom",
47 | title.hjust = 0.5))+
48 | theme_void()+
49 | theme(
50 | text = element_text(family = "Mukta"),
51 | plot.title = element_text(size = 24, face = "bold", family = "Lora"),
52 | plot.subtitle = element_text(size = 19),
53 | plot.caption = element_text(size = 14, color = "gray35", hjust = 1),
54 | plot.title.position = "plot",
55 | legend.position = "bottom",
56 | legend.title = element_text(size = 18),
57 | legend.text = element_text(size = 14),
58 | plot.background = element_rect(fill = "white", color = NA),
59 | panel.background = element_rect(fill = "white", color = NA),
60 | plot.margin = margin(4,2,4,2,"mm")
61 | )
62 |
63 | ggsave("2021/22_borders/borders.png", height = 11, width = 9)
64 |
--------------------------------------------------------------------------------
/2021/22_borders/borders.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/22_borders/borders.png
--------------------------------------------------------------------------------
/2021/25_interactive/elderly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/25_interactive/elderly.png
--------------------------------------------------------------------------------
/2021/25_interactive/elderly_files/Proj4Leaflet-1.0.1/proj4leaflet.js:
--------------------------------------------------------------------------------
1 | (function (factory) {
2 | var L, proj4;
3 | if (typeof define === 'function' && define.amd) {
4 | // AMD
5 | define(['leaflet', 'proj4'], factory);
6 | } else if (typeof module === 'object' && typeof module.exports === "object") {
7 | // Node/CommonJS
8 | L = require('leaflet');
9 | proj4 = require('proj4');
10 | module.exports = factory(L, proj4);
11 | } else {
12 | // Browser globals
13 | if (typeof window.L === 'undefined' || typeof window.proj4 === 'undefined')
14 | throw 'Leaflet and proj4 must be loaded first';
15 | factory(window.L, window.proj4);
16 | }
17 | }(function (L, proj4) {
18 | if (proj4.__esModule && proj4.default) {
19 | // If proj4 was bundled as an ES6 module, unwrap it to get
20 | // to the actual main proj4 object.
21 | // See discussion in https://github.com/kartena/Proj4Leaflet/pull/147
22 | proj4 = proj4.default;
23 | }
24 |
25 | L.Proj = {};
26 |
27 | L.Proj._isProj4Obj = function(a) {
28 | return (typeof a.inverse !== 'undefined' &&
29 | typeof a.forward !== 'undefined');
30 | };
31 |
32 | L.Proj.Projection = L.Class.extend({
33 | initialize: function(code, def, bounds) {
34 | var isP4 = L.Proj._isProj4Obj(code);
35 | this._proj = isP4 ? code : this._projFromCodeDef(code, def);
36 | this.bounds = isP4 ? def : bounds;
37 | },
38 |
39 | project: function (latlng) {
40 | var point = this._proj.forward([latlng.lng, latlng.lat]);
41 | return new L.Point(point[0], point[1]);
42 | },
43 |
44 | unproject: function (point, unbounded) {
45 | var point2 = this._proj.inverse([point.x, point.y]);
46 | return new L.LatLng(point2[1], point2[0], unbounded);
47 | },
48 |
49 | _projFromCodeDef: function(code, def) {
50 | if (def) {
51 | proj4.defs(code, def);
52 | } else if (proj4.defs[code] === undefined) {
53 | var urn = code.split(':');
54 | if (urn.length > 3) {
55 | code = urn[urn.length - 3] + ':' + urn[urn.length - 1];
56 | }
57 | if (proj4.defs[code] === undefined) {
58 | throw 'No projection definition for code ' + code;
59 | }
60 | }
61 |
62 | return proj4(code);
63 | }
64 | });
65 |
66 | L.Proj.CRS = L.Class.extend({
67 | includes: L.CRS,
68 |
69 | options: {
70 | transformation: new L.Transformation(1, 0, -1, 0)
71 | },
72 |
73 | initialize: function(a, b, c) {
74 | var code,
75 | proj,
76 | def,
77 | options;
78 |
79 | if (L.Proj._isProj4Obj(a)) {
80 | proj = a;
81 | code = proj.srsCode;
82 | options = b || {};
83 |
84 | this.projection = new L.Proj.Projection(proj, options.bounds);
85 | } else {
86 | code = a;
87 | def = b;
88 | options = c || {};
89 | this.projection = new L.Proj.Projection(code, def, options.bounds);
90 | }
91 |
92 | L.Util.setOptions(this, options);
93 | this.code = code;
94 | this.transformation = this.options.transformation;
95 |
96 | if (this.options.origin) {
97 | this.transformation =
98 | new L.Transformation(1, -this.options.origin[0],
99 | -1, this.options.origin[1]);
100 | }
101 |
102 | if (this.options.scales) {
103 | this._scales = this.options.scales;
104 | } else if (this.options.resolutions) {
105 | this._scales = [];
106 | for (var i = this.options.resolutions.length - 1; i >= 0; i--) {
107 | if (this.options.resolutions[i]) {
108 | this._scales[i] = 1 / this.options.resolutions[i];
109 | }
110 | }
111 | }
112 |
113 | this.infinite = !this.options.bounds;
114 |
115 | },
116 |
117 | scale: function(zoom) {
118 | var iZoom = Math.floor(zoom),
119 | baseScale,
120 | nextScale,
121 | scaleDiff,
122 | zDiff;
123 | if (zoom === iZoom) {
124 | return this._scales[zoom];
125 | } else {
126 | // Non-integer zoom, interpolate
127 | baseScale = this._scales[iZoom];
128 | nextScale = this._scales[iZoom + 1];
129 | scaleDiff = nextScale - baseScale;
130 | zDiff = (zoom - iZoom);
131 | return baseScale + scaleDiff * zDiff;
132 | }
133 | },
134 |
135 | zoom: function(scale) {
136 | // Find closest number in this._scales, down
137 | var downScale = this._closestElement(this._scales, scale),
138 | downZoom = this._scales.indexOf(downScale),
139 | nextScale,
140 | nextZoom,
141 | scaleDiff;
142 | // Check if scale is downScale => return array index
143 | if (scale === downScale) {
144 | return downZoom;
145 | }
146 | if (downScale === undefined) {
147 | return -Infinity;
148 | }
149 | // Interpolate
150 | nextZoom = downZoom + 1;
151 | nextScale = this._scales[nextZoom];
152 | if (nextScale === undefined) {
153 | return Infinity;
154 | }
155 | scaleDiff = nextScale - downScale;
156 | return (scale - downScale) / scaleDiff + downZoom;
157 | },
158 |
159 | distance: L.CRS.Earth.distance,
160 |
161 | R: L.CRS.Earth.R,
162 |
163 | /* Get the closest lowest element in an array */
164 | _closestElement: function(array, element) {
165 | var low;
166 | for (var i = array.length; i--;) {
167 | if (array[i] <= element && (low === undefined || low < array[i])) {
168 | low = array[i];
169 | }
170 | }
171 | return low;
172 | }
173 | });
174 |
175 | L.Proj.GeoJSON = L.GeoJSON.extend({
176 | initialize: function(geojson, options) {
177 | this._callLevel = 0;
178 | L.GeoJSON.prototype.initialize.call(this, geojson, options);
179 | },
180 |
181 | addData: function(geojson) {
182 | var crs;
183 |
184 | if (geojson) {
185 | if (geojson.crs && geojson.crs.type === 'name') {
186 | crs = new L.Proj.CRS(geojson.crs.properties.name);
187 | } else if (geojson.crs && geojson.crs.type) {
188 | crs = new L.Proj.CRS(geojson.crs.type + ':' + geojson.crs.properties.code);
189 | }
190 |
191 | if (crs !== undefined) {
192 | this.options.coordsToLatLng = function(coords) {
193 | var point = L.point(coords[0], coords[1]);
194 | return crs.projection.unproject(point);
195 | };
196 | }
197 | }
198 |
199 | // Base class' addData might call us recursively, but
200 | // CRS shouldn't be cleared in that case, since CRS applies
201 | // to the whole GeoJSON, inluding sub-features.
202 | this._callLevel++;
203 | try {
204 | L.GeoJSON.prototype.addData.call(this, geojson);
205 | } finally {
206 | this._callLevel--;
207 | if (this._callLevel === 0) {
208 | delete this.options.coordsToLatLng;
209 | }
210 | }
211 | }
212 | });
213 |
214 | L.Proj.geoJson = function(geojson, options) {
215 | return new L.Proj.GeoJSON(geojson, options);
216 | };
217 |
218 | L.Proj.ImageOverlay = L.ImageOverlay.extend({
219 | initialize: function (url, bounds, options) {
220 | L.ImageOverlay.prototype.initialize.call(this, url, null, options);
221 | this._projectedBounds = bounds;
222 | },
223 |
224 | // Danger ahead: Overriding internal methods in Leaflet.
225 | // Decided to do this rather than making a copy of L.ImageOverlay
226 | // and doing very tiny modifications to it.
227 | // Future will tell if this was wise or not.
228 | _animateZoom: function (event) {
229 | var scale = this._map.getZoomScale(event.zoom);
230 | var northWest = L.point(this._projectedBounds.min.x, this._projectedBounds.max.y);
231 | var offset = this._projectedToNewLayerPoint(northWest, event.zoom, event.center);
232 |
233 | L.DomUtil.setTransform(this._image, offset, scale);
234 | },
235 |
236 | _reset: function () {
237 | var zoom = this._map.getZoom();
238 | var pixelOrigin = this._map.getPixelOrigin();
239 | var bounds = L.bounds(
240 | this._transform(this._projectedBounds.min, zoom)._subtract(pixelOrigin),
241 | this._transform(this._projectedBounds.max, zoom)._subtract(pixelOrigin)
242 | );
243 | var size = bounds.getSize();
244 |
245 | L.DomUtil.setPosition(this._image, bounds.min);
246 | this._image.style.width = size.x + 'px';
247 | this._image.style.height = size.y + 'px';
248 | },
249 |
250 | _projectedToNewLayerPoint: function (point, zoom, center) {
251 | var viewHalf = this._map.getSize()._divideBy(2);
252 | var newTopLeft = this._map.project(center, zoom)._subtract(viewHalf)._round();
253 | var topLeft = newTopLeft.add(this._map._getMapPanePos());
254 |
255 | return this._transform(point, zoom)._subtract(topLeft);
256 | },
257 |
258 | _transform: function (point, zoom) {
259 | var crs = this._map.options.crs;
260 | var transformation = crs.transformation;
261 | var scale = crs.scale(zoom);
262 |
263 | return transformation.transform(point, scale);
264 | }
265 | });
266 |
267 | L.Proj.imageOverlay = function (url, bounds, options) {
268 | return new L.Proj.ImageOverlay(url, bounds, options);
269 | };
270 |
271 | return L.Proj;
272 | }));
273 |
--------------------------------------------------------------------------------
/2021/25_interactive/elderly_files/leaflet-1.3.1/images/layers-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/25_interactive/elderly_files/leaflet-1.3.1/images/layers-2x.png
--------------------------------------------------------------------------------
/2021/25_interactive/elderly_files/leaflet-1.3.1/images/layers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/25_interactive/elderly_files/leaflet-1.3.1/images/layers.png
--------------------------------------------------------------------------------
/2021/25_interactive/elderly_files/leaflet-1.3.1/images/marker-icon-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/25_interactive/elderly_files/leaflet-1.3.1/images/marker-icon-2x.png
--------------------------------------------------------------------------------
/2021/25_interactive/elderly_files/leaflet-1.3.1/images/marker-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/25_interactive/elderly_files/leaflet-1.3.1/images/marker-icon.png
--------------------------------------------------------------------------------
/2021/25_interactive/elderly_files/leaflet-1.3.1/images/marker-shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/25_interactive/elderly_files/leaflet-1.3.1/images/marker-shadow.png
--------------------------------------------------------------------------------
/2021/25_interactive/elderly_files/leaflet-providers-plugin-2.0.4.1/leaflet-providers-plugin.js:
--------------------------------------------------------------------------------
1 | LeafletWidget.methods.addProviderTiles = function(provider, layerId, group, options) {
2 | this.layerManager.addLayer(L.tileLayer.provider(provider, options), "tile", layerId, group);
3 | };
4 |
--------------------------------------------------------------------------------
/2021/25_interactive/elderly_files/leafletfix-1.0.0/leafletfix.css:
--------------------------------------------------------------------------------
1 | /* Work around CSS properties introduced on img by bootstrap */
2 | img.leaflet-tile {
3 | padding: 0;
4 | margin: 0;
5 | border-radius: 0;
6 | border: none;
7 | }
8 | .info {
9 | padding: 6px 8px;
10 | font: 14px/16px Arial, Helvetica, sans-serif;
11 | background: white;
12 | background: rgba(255,255,255,0.8);
13 | box-shadow: 0 0 15px rgba(0,0,0,0.2);
14 | border-radius: 5px;
15 | }
16 | .legend {
17 | line-height: 18px;
18 | color: #555;
19 | }
20 | .legend svg text {
21 | fill: #555;
22 | }
23 | .legend svg line {
24 | stroke: #555;
25 | }
26 | .legend i {
27 | width: 18px;
28 | height: 18px;
29 | margin-right: 4px;
30 | opacity: 0.7;
31 | display: inline-block;
32 | vertical-align: top;
33 | /*For IE 7*/
34 | zoom: 1;
35 | *display: inline;
36 | }
37 |
--------------------------------------------------------------------------------
/2021/25_interactive/elderly_files/rstudio_leaflet-1.3.1/images/1px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/25_interactive/elderly_files/rstudio_leaflet-1.3.1/images/1px.png
--------------------------------------------------------------------------------
/2021/25_interactive/elderly_files/rstudio_leaflet-1.3.1/rstudio_leaflet.css:
--------------------------------------------------------------------------------
1 | .leaflet-tooltip.leaflet-tooltip-text-only,
2 | .leaflet-tooltip.leaflet-tooltip-text-only:before,
3 | .leaflet-tooltip.leaflet-tooltip-text-only:after {
4 | background: none;
5 | border: none;
6 | box-shadow: none;
7 | }
8 |
9 | .leaflet-tooltip.leaflet-tooltip-text-only.leaflet-tooltip-left {
10 | margin-left: 5px;
11 | }
12 |
13 | .leaflet-tooltip.leaflet-tooltip-text-only.leaflet-tooltip-right {
14 | margin-left: -5px;
15 | }
16 |
17 | .leaflet-tooltip:after {
18 | border-right: 6px solid transparent;
19 | /* right: -16px; */
20 | }
21 |
22 | .leaflet-popup-pane .leaflet-popup-tip-container {
23 | /* when the tooltip container is clicked, it is closed */
24 | pointer-events: all;
25 | /* tooltips should display the "hand" icon, just like .leaflet-interactive*/
26 | cursor: pointer;
27 | }
28 |
29 | /* have the widget be displayed in the right 'layer' */
30 | .leaflet-map-pane {
31 | z-index: auto;
32 | }
33 |
--------------------------------------------------------------------------------
/2021/25_interactive/src.R:
--------------------------------------------------------------------------------
1 | library(sf)
2 | library(jsonlite)
3 | library(httr)
4 | library(purrr)
5 | library(dplyr)
6 | library(ggplot2)
7 | library(leaflet)
8 | library(glue)
9 | library(htmlwidgets)
10 | library(webshot)
11 |
12 | # Set for Hebrew characters
13 | # Sys.setlocale("LC_ALL", "Hebrew")
14 |
15 | # Bus stops from TA api
16 | bus_stopsapiraw <- GET("https://gisn.tel-aviv.gov.il/arcgis/rest/services/IView2/MapServer/956/query?where=1%3D1&outFields=*&f=json")
17 | bus_apilist <- fromJSON(content(bus_stopsapiraw, "text"), simplifyVector = FALSE)
18 | bus_stops <- map_dfr(bus_apilist$features, pluck("attributes")) %>%
19 | st_as_sf(coords = c("stop_lon", "stop_lat"), crs = 4326) %>%
20 | st_transform(crs = 2039) %>%
21 | mutate(id = 1:nrow(.))
22 |
23 | # Get the API information from Tel-Aviv municipality website for elderly locations
24 | elderly_info <- data.frame(
25 | apiurl = c(
26 | "https://gisn.tel-aviv.gov.il/arcgis/rest/services/IView2/MapServer/600/query?where=1%3D1&outFields=*&f=json",
27 | "https://gisn.tel-aviv.gov.il/arcgis/rest/services/IView2/MapServer/581/query?where=1%3D1&outFields=*&f=json",
28 | "https://gisn.tel-aviv.gov.il/arcgis/rest/services/IView2/MapServer/855/query?where=1%3D1&outFields=*&f=json"
29 | ),
30 | apiname = c("elderly_clubs","geriatric_day_center", "programs_for_elderly" )
31 | )
32 |
33 |
34 | # Function to extract, clean and transform to sf the api call of elderly program locations
35 | clean_ta_api <- function(apiurl, apiname) {
36 | apiraw <- GET(apiurl)
37 |
38 | apilist <- fromJSON(content(apiraw, "text"), simplifyVector = FALSE)
39 |
40 | sf_data <- map_dfr(apilist$features, pluck("geometry")) %>%
41 | mutate(
42 | shem = map_chr(apilist$features, pluck, "attributes", "shem", .default = NA),
43 | location_name = apiname
44 | ) %>%
45 | st_as_sf(coords = c("x", "y"), crs = 2039)
46 |
47 | return(sf_data)
48 | }
49 |
50 | # Get the data
51 | elderly <- map2_dfr(elderly_info$apiurl, elderly_info$apiname, clean_ta_api) %>%
52 | distinct(shem, location_name, geometry)
53 |
54 | # Calculate distances from each elderly center to the nearest bus stop
55 | distances <- st_distance(bus_stops, elderly) %>%
56 | as_tibble()
57 |
58 | # Get the minimum distance, i.e. the nearest bus stop
59 | elderly_with_info <- elderly %>%
60 | mutate(distance_to_bus = map_dbl(distances, function(x) min(x))) %>%
61 | st_transform(crs = 4326)
62 |
63 | bus_stops_wgs <- bus_stops %>%
64 | st_transform(crs = 4326)
65 |
66 | distance_label <- glue("{round(elderly_with_info$distance_to_bus, 1)}m") %>%
67 | map(., htmltools::HTML)
68 |
69 | pal <- colorNumeric(
70 | palette = RColorBrewer::brewer.pal(9, "Blues"),
71 | domain = elderly_with_info$distance_to_bus)
72 |
73 | open_labels <- elderly_with_info %>%
74 | arrange(-distance_to_bus) %>%
75 | slice(c(1,3)) %>%
76 | mutate(distance_label_open = glue("{round(distance_to_bus, 1)}m"),
77 | distance_label_open = lapply(distance_label_open, HTML))
78 |
79 |
80 | p <- leaflet() %>%
81 | addProviderTiles("CartoDB.Positron",options = providerTileOptions(minZoom = 12)) %>%
82 | addCircles(data = bus_stops_wgs, weight =1, color = "#696969", radius = 1, opacity = 0.5) %>%
83 | addCircleMarkers(data = elderly_with_info, weight = 4, radius = 2, color = ~pal(distance_to_bus), fillColor = ~pal(distance_to_bus), label = distance_label, opacity = 1, labelOptions = labelOptions(
84 | style = list(
85 | "font-size" = "14px",
86 | "border-color" = "rgba(0,0,0,0.5)"))) %>%
87 | addLabelOnlyMarkers(data = open_labels, label = open_labels$distance_label_open,
88 | labelOptions = labelOptions(noHide = T, direction = "top",
89 | style = list(
90 | "font-size" = "11px",
91 | "border-color" = "rgba(0,0,0,0.5)"))) %>%
92 | addControl(html = paste(tags$h1(HTML("Distance from elderly
program locations to
the nearest bus stop"), style = "color:black; font-family:Alegreya; font-size: 24pt; padding-left: 8px; line-height: 1.1em;")), className = "fieldset {
93 | border: 0;
94 | }", position = "topleft") %>%
95 | addLegend(
96 | title = "Distance (m)",
97 | data = elderly_with_info,
98 | position = "bottomright",
99 | pal = pal, values = ~ elderly_with_info$distance_to_bus,
100 | bins = c(100,200,300))
101 |
102 |
103 | # Save widget
104 | saveWidget(p, "2021/25_interactive/elderly.html")
105 | # Save snapshot
106 | webshot("2021/25_interactive/elderly.html", file = "2021/25_interactive/elderly.png", vwidth = 700, vheight = 800, delay = 2)
107 |
--------------------------------------------------------------------------------
/2021/data/Crime-map-2016_2021.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/data/Crime-map-2016_2021.xlsx
--------------------------------------------------------------------------------
/2021/data/golda_locations.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/data/golda_locations.xlsx
--------------------------------------------------------------------------------
/2021/data/ta-shapefile/gv_Tel_Aviv-Yafo_27.10.14.dbf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/data/ta-shapefile/gv_Tel_Aviv-Yafo_27.10.14.dbf
--------------------------------------------------------------------------------
/2021/data/ta-shapefile/gv_Tel_Aviv-Yafo_27.10.14.jgw:
--------------------------------------------------------------------------------
1 | 3.03925388213476
2 | -0.00088827221119
3 | -0.00088845076055
4 | -3.03986479491399
5 | 174915.71561200556000
6 | 680001.49658626493000
7 |
--------------------------------------------------------------------------------
/2021/data/ta-shapefile/gv_Tel_Aviv-Yafo_27.10.14.shp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/data/ta-shapefile/gv_Tel_Aviv-Yafo_27.10.14.shp
--------------------------------------------------------------------------------
/2021/data/ta-shapefile/gv_Tel_Aviv-Yafo_27.10.14.shx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/data/ta-shapefile/gv_Tel_Aviv-Yafo_27.10.14.shx
--------------------------------------------------------------------------------
/2021/data/tatrees/%D7%A2%D7%A6%D7%99_%D7%9E%D7%95%D7%A8%D7%A9%D7%AA.cpg:
--------------------------------------------------------------------------------
1 | UTF-8
--------------------------------------------------------------------------------
/2021/data/tatrees/%D7%A2%D7%A6%D7%99_%D7%9E%D7%95%D7%A8%D7%A9%D7%AA.dbf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/data/tatrees/%D7%A2%D7%A6%D7%99_%D7%9E%D7%95%D7%A8%D7%A9%D7%AA.dbf
--------------------------------------------------------------------------------
/2021/data/tatrees/%D7%A2%D7%A6%D7%99_%D7%9E%D7%95%D7%A8%D7%A9%D7%AA.prj:
--------------------------------------------------------------------------------
1 | PROJCS["WGS_1984_Web_Mercator_Auxiliary_Sphere",GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Mercator_Auxiliary_Sphere"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",0.0],PARAMETER["Standard_Parallel_1",0.0],PARAMETER["Auxiliary_Sphere_Type",0.0],UNIT["Meter",1.0]]
--------------------------------------------------------------------------------
/2021/data/tatrees/%D7%A2%D7%A6%D7%99_%D7%9E%D7%95%D7%A8%D7%A9%D7%AA.shp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/data/tatrees/%D7%A2%D7%A6%D7%99_%D7%9E%D7%95%D7%A8%D7%A9%D7%AA.shp
--------------------------------------------------------------------------------
/2021/data/tatrees/%D7%A2%D7%A6%D7%99_%D7%9E%D7%95%D7%A8%D7%A9%D7%AA.shx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/data/tatrees/%D7%A2%D7%A6%D7%99_%D7%9E%D7%95%D7%A8%D7%A9%D7%AA.shx
--------------------------------------------------------------------------------
/2021/data/wave/export.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/data/wave/export.xlsx
--------------------------------------------------------------------------------
/2021/data/wave/tsunami 5 meter line.cpg:
--------------------------------------------------------------------------------
1 | utf-8
--------------------------------------------------------------------------------
/2021/data/wave/tsunami 5 meter line.dbf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/data/wave/tsunami 5 meter line.dbf
--------------------------------------------------------------------------------
/2021/data/wave/tsunami 5 meter line.prj:
--------------------------------------------------------------------------------
1 | PROJCS["WGS_1984_UTM_Zone_36N",GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",33.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]]
--------------------------------------------------------------------------------
/2021/data/wave/tsunami 5 meter line.shp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/data/wave/tsunami 5 meter line.shp
--------------------------------------------------------------------------------
/2021/data/wave/tsunami 5 meter line.shx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/data/wave/tsunami 5 meter line.shx
--------------------------------------------------------------------------------
/2021/messing-around/ggmap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/messing-around/ggmap.png
--------------------------------------------------------------------------------
/2021/messing-around/ggmap_polygon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/messing-around/ggmap_polygon.png
--------------------------------------------------------------------------------
/2021/messing-around/ggmap_polygon_clean.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/messing-around/ggmap_polygon_clean.png
--------------------------------------------------------------------------------
/2021/messing-around/israel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/messing-around/israel.png
--------------------------------------------------------------------------------
/2021/messing-around/israelpre67.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/messing-around/israelpre67.png
--------------------------------------------------------------------------------
/2021/messing-around/leaflet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/messing-around/leaflet.png
--------------------------------------------------------------------------------
/2021/messing-around/leaflet_files/Proj4Leaflet-1.0.1/proj4leaflet.js:
--------------------------------------------------------------------------------
1 | (function (factory) {
2 | var L, proj4;
3 | if (typeof define === 'function' && define.amd) {
4 | // AMD
5 | define(['leaflet', 'proj4'], factory);
6 | } else if (typeof module === 'object' && typeof module.exports === "object") {
7 | // Node/CommonJS
8 | L = require('leaflet');
9 | proj4 = require('proj4');
10 | module.exports = factory(L, proj4);
11 | } else {
12 | // Browser globals
13 | if (typeof window.L === 'undefined' || typeof window.proj4 === 'undefined')
14 | throw 'Leaflet and proj4 must be loaded first';
15 | factory(window.L, window.proj4);
16 | }
17 | }(function (L, proj4) {
18 | if (proj4.__esModule && proj4.default) {
19 | // If proj4 was bundled as an ES6 module, unwrap it to get
20 | // to the actual main proj4 object.
21 | // See discussion in https://github.com/kartena/Proj4Leaflet/pull/147
22 | proj4 = proj4.default;
23 | }
24 |
25 | L.Proj = {};
26 |
27 | L.Proj._isProj4Obj = function(a) {
28 | return (typeof a.inverse !== 'undefined' &&
29 | typeof a.forward !== 'undefined');
30 | };
31 |
32 | L.Proj.Projection = L.Class.extend({
33 | initialize: function(code, def, bounds) {
34 | var isP4 = L.Proj._isProj4Obj(code);
35 | this._proj = isP4 ? code : this._projFromCodeDef(code, def);
36 | this.bounds = isP4 ? def : bounds;
37 | },
38 |
39 | project: function (latlng) {
40 | var point = this._proj.forward([latlng.lng, latlng.lat]);
41 | return new L.Point(point[0], point[1]);
42 | },
43 |
44 | unproject: function (point, unbounded) {
45 | var point2 = this._proj.inverse([point.x, point.y]);
46 | return new L.LatLng(point2[1], point2[0], unbounded);
47 | },
48 |
49 | _projFromCodeDef: function(code, def) {
50 | if (def) {
51 | proj4.defs(code, def);
52 | } else if (proj4.defs[code] === undefined) {
53 | var urn = code.split(':');
54 | if (urn.length > 3) {
55 | code = urn[urn.length - 3] + ':' + urn[urn.length - 1];
56 | }
57 | if (proj4.defs[code] === undefined) {
58 | throw 'No projection definition for code ' + code;
59 | }
60 | }
61 |
62 | return proj4(code);
63 | }
64 | });
65 |
66 | L.Proj.CRS = L.Class.extend({
67 | includes: L.CRS,
68 |
69 | options: {
70 | transformation: new L.Transformation(1, 0, -1, 0)
71 | },
72 |
73 | initialize: function(a, b, c) {
74 | var code,
75 | proj,
76 | def,
77 | options;
78 |
79 | if (L.Proj._isProj4Obj(a)) {
80 | proj = a;
81 | code = proj.srsCode;
82 | options = b || {};
83 |
84 | this.projection = new L.Proj.Projection(proj, options.bounds);
85 | } else {
86 | code = a;
87 | def = b;
88 | options = c || {};
89 | this.projection = new L.Proj.Projection(code, def, options.bounds);
90 | }
91 |
92 | L.Util.setOptions(this, options);
93 | this.code = code;
94 | this.transformation = this.options.transformation;
95 |
96 | if (this.options.origin) {
97 | this.transformation =
98 | new L.Transformation(1, -this.options.origin[0],
99 | -1, this.options.origin[1]);
100 | }
101 |
102 | if (this.options.scales) {
103 | this._scales = this.options.scales;
104 | } else if (this.options.resolutions) {
105 | this._scales = [];
106 | for (var i = this.options.resolutions.length - 1; i >= 0; i--) {
107 | if (this.options.resolutions[i]) {
108 | this._scales[i] = 1 / this.options.resolutions[i];
109 | }
110 | }
111 | }
112 |
113 | this.infinite = !this.options.bounds;
114 |
115 | },
116 |
117 | scale: function(zoom) {
118 | var iZoom = Math.floor(zoom),
119 | baseScale,
120 | nextScale,
121 | scaleDiff,
122 | zDiff;
123 | if (zoom === iZoom) {
124 | return this._scales[zoom];
125 | } else {
126 | // Non-integer zoom, interpolate
127 | baseScale = this._scales[iZoom];
128 | nextScale = this._scales[iZoom + 1];
129 | scaleDiff = nextScale - baseScale;
130 | zDiff = (zoom - iZoom);
131 | return baseScale + scaleDiff * zDiff;
132 | }
133 | },
134 |
135 | zoom: function(scale) {
136 | // Find closest number in this._scales, down
137 | var downScale = this._closestElement(this._scales, scale),
138 | downZoom = this._scales.indexOf(downScale),
139 | nextScale,
140 | nextZoom,
141 | scaleDiff;
142 | // Check if scale is downScale => return array index
143 | if (scale === downScale) {
144 | return downZoom;
145 | }
146 | if (downScale === undefined) {
147 | return -Infinity;
148 | }
149 | // Interpolate
150 | nextZoom = downZoom + 1;
151 | nextScale = this._scales[nextZoom];
152 | if (nextScale === undefined) {
153 | return Infinity;
154 | }
155 | scaleDiff = nextScale - downScale;
156 | return (scale - downScale) / scaleDiff + downZoom;
157 | },
158 |
159 | distance: L.CRS.Earth.distance,
160 |
161 | R: L.CRS.Earth.R,
162 |
163 | /* Get the closest lowest element in an array */
164 | _closestElement: function(array, element) {
165 | var low;
166 | for (var i = array.length; i--;) {
167 | if (array[i] <= element && (low === undefined || low < array[i])) {
168 | low = array[i];
169 | }
170 | }
171 | return low;
172 | }
173 | });
174 |
175 | L.Proj.GeoJSON = L.GeoJSON.extend({
176 | initialize: function(geojson, options) {
177 | this._callLevel = 0;
178 | L.GeoJSON.prototype.initialize.call(this, geojson, options);
179 | },
180 |
181 | addData: function(geojson) {
182 | var crs;
183 |
184 | if (geojson) {
185 | if (geojson.crs && geojson.crs.type === 'name') {
186 | crs = new L.Proj.CRS(geojson.crs.properties.name);
187 | } else if (geojson.crs && geojson.crs.type) {
188 | crs = new L.Proj.CRS(geojson.crs.type + ':' + geojson.crs.properties.code);
189 | }
190 |
191 | if (crs !== undefined) {
192 | this.options.coordsToLatLng = function(coords) {
193 | var point = L.point(coords[0], coords[1]);
194 | return crs.projection.unproject(point);
195 | };
196 | }
197 | }
198 |
199 | // Base class' addData might call us recursively, but
200 | // CRS shouldn't be cleared in that case, since CRS applies
201 | // to the whole GeoJSON, inluding sub-features.
202 | this._callLevel++;
203 | try {
204 | L.GeoJSON.prototype.addData.call(this, geojson);
205 | } finally {
206 | this._callLevel--;
207 | if (this._callLevel === 0) {
208 | delete this.options.coordsToLatLng;
209 | }
210 | }
211 | }
212 | });
213 |
214 | L.Proj.geoJson = function(geojson, options) {
215 | return new L.Proj.GeoJSON(geojson, options);
216 | };
217 |
218 | L.Proj.ImageOverlay = L.ImageOverlay.extend({
219 | initialize: function (url, bounds, options) {
220 | L.ImageOverlay.prototype.initialize.call(this, url, null, options);
221 | this._projectedBounds = bounds;
222 | },
223 |
224 | // Danger ahead: Overriding internal methods in Leaflet.
225 | // Decided to do this rather than making a copy of L.ImageOverlay
226 | // and doing very tiny modifications to it.
227 | // Future will tell if this was wise or not.
228 | _animateZoom: function (event) {
229 | var scale = this._map.getZoomScale(event.zoom);
230 | var northWest = L.point(this._projectedBounds.min.x, this._projectedBounds.max.y);
231 | var offset = this._projectedToNewLayerPoint(northWest, event.zoom, event.center);
232 |
233 | L.DomUtil.setTransform(this._image, offset, scale);
234 | },
235 |
236 | _reset: function () {
237 | var zoom = this._map.getZoom();
238 | var pixelOrigin = this._map.getPixelOrigin();
239 | var bounds = L.bounds(
240 | this._transform(this._projectedBounds.min, zoom)._subtract(pixelOrigin),
241 | this._transform(this._projectedBounds.max, zoom)._subtract(pixelOrigin)
242 | );
243 | var size = bounds.getSize();
244 |
245 | L.DomUtil.setPosition(this._image, bounds.min);
246 | this._image.style.width = size.x + 'px';
247 | this._image.style.height = size.y + 'px';
248 | },
249 |
250 | _projectedToNewLayerPoint: function (point, zoom, center) {
251 | var viewHalf = this._map.getSize()._divideBy(2);
252 | var newTopLeft = this._map.project(center, zoom)._subtract(viewHalf)._round();
253 | var topLeft = newTopLeft.add(this._map._getMapPanePos());
254 |
255 | return this._transform(point, zoom)._subtract(topLeft);
256 | },
257 |
258 | _transform: function (point, zoom) {
259 | var crs = this._map.options.crs;
260 | var transformation = crs.transformation;
261 | var scale = crs.scale(zoom);
262 |
263 | return transformation.transform(point, scale);
264 | }
265 | });
266 |
267 | L.Proj.imageOverlay = function (url, bounds, options) {
268 | return new L.Proj.ImageOverlay(url, bounds, options);
269 | };
270 |
271 | return L.Proj;
272 | }));
273 |
--------------------------------------------------------------------------------
/2021/messing-around/leaflet_files/leaflet-1.3.1/images/layers-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/messing-around/leaflet_files/leaflet-1.3.1/images/layers-2x.png
--------------------------------------------------------------------------------
/2021/messing-around/leaflet_files/leaflet-1.3.1/images/layers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/messing-around/leaflet_files/leaflet-1.3.1/images/layers.png
--------------------------------------------------------------------------------
/2021/messing-around/leaflet_files/leaflet-1.3.1/images/marker-icon-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/messing-around/leaflet_files/leaflet-1.3.1/images/marker-icon-2x.png
--------------------------------------------------------------------------------
/2021/messing-around/leaflet_files/leaflet-1.3.1/images/marker-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/messing-around/leaflet_files/leaflet-1.3.1/images/marker-icon.png
--------------------------------------------------------------------------------
/2021/messing-around/leaflet_files/leaflet-1.3.1/images/marker-shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/messing-around/leaflet_files/leaflet-1.3.1/images/marker-shadow.png
--------------------------------------------------------------------------------
/2021/messing-around/leaflet_files/leafletfix-1.0.0/leafletfix.css:
--------------------------------------------------------------------------------
1 | /* Work around CSS properties introduced on img by bootstrap */
2 | img.leaflet-tile {
3 | padding: 0;
4 | margin: 0;
5 | border-radius: 0;
6 | border: none;
7 | }
8 | .info {
9 | padding: 6px 8px;
10 | font: 14px/16px Arial, Helvetica, sans-serif;
11 | background: white;
12 | background: rgba(255,255,255,0.8);
13 | box-shadow: 0 0 15px rgba(0,0,0,0.2);
14 | border-radius: 5px;
15 | }
16 | .legend {
17 | line-height: 18px;
18 | color: #555;
19 | }
20 | .legend svg text {
21 | fill: #555;
22 | }
23 | .legend svg line {
24 | stroke: #555;
25 | }
26 | .legend i {
27 | width: 18px;
28 | height: 18px;
29 | margin-right: 4px;
30 | opacity: 0.7;
31 | display: inline-block;
32 | vertical-align: top;
33 | /*For IE 7*/
34 | zoom: 1;
35 | *display: inline;
36 | }
37 |
--------------------------------------------------------------------------------
/2021/messing-around/leaflet_files/rstudio_leaflet-1.3.1/images/1px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/messing-around/leaflet_files/rstudio_leaflet-1.3.1/images/1px.png
--------------------------------------------------------------------------------
/2021/messing-around/leaflet_files/rstudio_leaflet-1.3.1/rstudio_leaflet.css:
--------------------------------------------------------------------------------
1 | .leaflet-tooltip.leaflet-tooltip-text-only,
2 | .leaflet-tooltip.leaflet-tooltip-text-only:before,
3 | .leaflet-tooltip.leaflet-tooltip-text-only:after {
4 | background: none;
5 | border: none;
6 | box-shadow: none;
7 | }
8 |
9 | .leaflet-tooltip.leaflet-tooltip-text-only.leaflet-tooltip-left {
10 | margin-left: 5px;
11 | }
12 |
13 | .leaflet-tooltip.leaflet-tooltip-text-only.leaflet-tooltip-right {
14 | margin-left: -5px;
15 | }
16 |
17 | .leaflet-tooltip:after {
18 | border-right: 6px solid transparent;
19 | /* right: -16px; */
20 | }
21 |
22 | .leaflet-popup-pane .leaflet-popup-tip-container {
23 | /* when the tooltip container is clicked, it is closed */
24 | pointer-events: all;
25 | /* tooltips should display the "hand" icon, just like .leaflet-interactive*/
26 | cursor: pointer;
27 | }
28 |
29 | /* have the widget be displayed in the right 'layer' */
30 | .leaflet-map-pane {
31 | z-index: auto;
32 | }
33 |
--------------------------------------------------------------------------------
/2021/messing-around/telaviv_tmap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2021/messing-around/telaviv_tmap.png
--------------------------------------------------------------------------------
/2021/messing-around/warmup.R:
--------------------------------------------------------------------------------
1 |
2 | # Just some sf objects and mapping ----------------------------------------
3 |
4 | library(sf)
5 | library(ggplot2)
6 |
7 | # Pre 67 borders
8 | isr <- readRDS("data/maps/00_israel_0_sf.rds")
9 |
10 | # Error requesting to set crs from old version
11 | isr <- st_set_crs(isr, st_crs(isr))
12 |
13 | ggplot()+
14 | geom_sf(data = st_as_sf(isr))
15 |
16 | # ggsave("2021/messing-around/israelpre67.png")
17 |
18 | # Full map
19 | isrfull <- read_sf("data/maps/isr-full/israel_borders.shp")
20 |
21 | ggplot(isrfull)+
22 | geom_sf()
23 |
24 | # ggsave("2021/messing-around/israel.png")
25 |
26 | # Tel Aviv
27 | tel_aviv_file_name <- list.files(pattern =".Aviv.+\\.shp$", recursive = TRUE)
28 | # I use the file for different projects and reference it several times from a specific folder
29 | tel_aviv_file <- read_sf(paste0(tel_aviv_file_name))
30 |
31 |
32 | # So Tel-aviv didn't have any crs, but we can see it's in ITM:
33 | tel_aviv_file <- st_set_crs(tel_aviv_file, 2039)
34 |
35 | # Now convert to WGS 84:
36 | tel_aviv_file <- st_transform(tel_aviv_file, 4326)
37 |
38 |
39 | # tmap attempt ------------------------------------------------------------
40 |
41 | library(tmap)
42 |
43 | t <- qtm(tel_aviv_file, fill = NA, borders = NULL, title = "Just a quick tmap of Tel-Aviv", style = "cobalt")
44 |
45 | tmap_save(t,"2021/messing-around/telaviv_tmap.png")
46 |
47 | # ggmap -------------------------------------------------------------------
48 | library(ggmap)
49 |
50 | telavivggmap <- get_googlemap(center = "tel aviv, israel", zoom = 12)
51 |
52 | ggmap(telavivggmap)
53 |
54 | # ggsave("2021/messing-around/ggmap.png")
55 |
56 | # Again, this time add an sf object
57 | ggmap(telavivggmap)+
58 | # Adding sf to ggmap, inherift.aes = FALSE
59 | geom_sf(data = tel_aviv_file, inherit.aes = FALSE, fill = NA)
60 |
61 | # ggsave("2021/messing-around/ggmap_polygon.png")
62 |
63 |
64 | # And again, this time removing labels
65 | telavivggmapclean <- get_googlemap(center = "tel aviv, israel", zoom = 12, style=c(feature="all",element="labels",visibility="off"))
66 |
67 | ggmap(telavivggmapclean)+
68 | # Adding sf to ggmap, inherift.aes = FALSE
69 | geom_sf(data = tel_aviv_file, inherit.aes = FALSE, fill = NA)+
70 | theme_void()
71 |
72 | # ggsave("2021/messing-around/ggmap_polygon_clean.png")
73 |
74 |
75 | # Leaflet -----------------------------------------------------------------
76 |
77 |
78 | library(leaflet)
79 | library(magrittr)
80 | m <- leaflet() %>%
81 | addTiles() %>%
82 | addPolygons(data = tel_aviv_file)
83 |
84 | # mapview::mapshot(m, file = "2021/messing-around/leaflet.png")
85 |
86 |
87 | # Osm data ----------------------------------------------------------------
88 | library(osmdata)
89 |
90 | opq(st_bbox(tel_aviv_file))
91 |
92 | dat <- opq(bbox = st_bbox(tel_aviv_file)) %>%
93 | # add_osm_feature(key = 'height') %>%
94 | add_osm_feature(key = "busway") %>%
95 | osmdata_sf()
96 |
97 | q <- opq(st_bbox(tel_aviv_file)) %>%
98 | add_osm_feature(key = 'highway') %>%
99 | osmdata_sf()
100 |
101 | ggplot()+
102 | # geom_sf(data = st_geometry(q$osm_lines), color = "red")+
103 | geom_sf(data = st_geometry(q$osm_points), alpha = 0.1)
104 |
105 | ?overline
106 | library(ggplot2)
107 | plot(dat)
108 | available_features()
109 |
110 |
111 |
112 | # stplanr and osrm --------------------------------------------------------
113 | library(stplanr)
114 | library(osrm)
115 |
116 | trip <- route(
117 | from = st_coordinates(st_sample(tel_aviv_file, size = 1)),
118 | to = st_coordinates(st_sample(tel_aviv_file, size = 1)),
119 | route_fun = osrmRoute,
120 | returnclass = "sf",
121 | osrm.profile = "car"
122 | )
123 |
124 | mapview::mapview(trip, color = "cyan")
125 |
126 |
127 |
128 | # Buffer zone -------------------------------------------------------------
129 |
130 | # Dizingof center as a point
131 | # dizcenter <- st_transform(st_sfc(st_point(c(34.774225, 32.077915)), crs = 4326), crs = 2039)
132 |
133 | # 1 Km radius around it
134 | # dizcenter1km <- st_transform(st_buffer(dizcenter, dist = units::set_units(2, "km")), crs = 4326)
135 |
136 |
137 | # st_transform(st_buffer(st_transform(st_as_sf(loc, coords = c("longitude", "latitude"), crs = 4326), 2039), dist = set_units(8, "km")), crs = 4326)
138 |
139 | # lines intersecting within our buffer
140 | # datcomplete <- st_intersection(tel_aviv_file, dat)
141 |
142 | # So Tel-aviv didn't have any crs, but we can see it's in ITM:
143 | tel_aviv_file <- st_set_crs(tel_aviv_file, 2039)
144 |
145 | # Now convert to WGS 84:
146 | tel_aviv_file <- st_transform(tel_aviv_file, 4326)
147 |
148 |
149 | # Extract streets in Tel-Aviv near the Diz center
150 | # streets <- opq(bbox = st_bbox(dizcenter1km)) %>%
151 | # add_osm_feature(key = "highway", value = c("motorway","primary",
152 | # "secondary", "tertiary", "residential",
153 | # "service")) %>%
154 | # osmdata_sf()
155 |
156 |
157 |
158 | # Bus routes --------------------------------------------------------------
159 |
160 |
161 | # Check out more at
162 | # https://transitfeeds.com/p/ministry-of-transport-and-road-safety/820
163 |
164 | routes
165 | routes <- fread("2021/data/stop_times.txt")
166 | setkey(routes, "stop_id")
167 | setkey(dat, "stop_id")
168 |
169 | dat[routes, on = "stop_id", nomatch=0][trip_id == "44092626_041121",.(mean(arrival_time)), by = trip_id]
170 |
171 |
172 | # elevater ----------------------------------------------------------------
173 |
174 |
175 |
176 |
177 | isrraster <- get_elev_raster(locations = isrfull, z = 9, clip = "locations")
178 |
179 | elevation_data <- as.data.frame(isrraster, xy = TRUE)
180 |
181 |
182 | colnames(elevation_data)[3] <- "elevation"
183 | # remove rows of data frame with one or more NA's,using complete.cases
184 | elevation_data <- elevation_data[complete.cases(elevation_data), ]
185 |
186 | ggplot() +
187 | geom_point(data = elevation_data, aes(x = x, y = y, color = elevation)) +
188 | scale_color_gradient(low = "white", high = "black")+
189 | coord_sf() +
190 | theme_void()
191 |
192 |
--------------------------------------------------------------------------------
/2022/01_points/01_points.R:
--------------------------------------------------------------------------------
1 | library(readr)
2 | library(sf)
3 | library(dplyr)
4 | library(systemfonts)
5 | library(snapbox)
6 | library(ggplot2)
7 | library(ggsflabel)
8 |
9 | rehovot_path <- list.files('../data/maps/judicial/', recursive = T, pattern = 'gv_Rehovot_2016_plt\\.shp$')
10 |
11 | # taken from June Choe's blog
12 | fa_solid_path <- system_fonts() %>%
13 | filter(family == "Font Awesome 6 Free", style == "Solid") %>%
14 | pull(path)
15 |
16 | systemfonts::register_font(
17 | name = "Font Awesome 6 Free Solid",
18 | plain = fa_solid_path
19 | )
20 |
21 | rehovot_sf <- st_read(paste0('../data/maps/judicial/', rehovot_path)) %>%
22 | st_transform(crs = 4326) # %>%
23 | # remove the holes (combine Gibton)
24 | # sfheaders::sf_remove_holes()
25 |
26 |
27 | polling_stations <- read_csv('01_points/polling_station_rehovot.csv') %>%
28 | filter(lon <= 34.85) %>%
29 | select(address:lon) %>%
30 | mutate(is_voting_location = ifelse(lat == 31.89650869, 'Yes', 'no')) %>%
31 | st_as_sf(coords = c('lon', 'lat'), crs = 4326) %>%
32 | mutate(label = 'vote-yea')
33 |
34 | # Great tip to cutout part of the map, I just used it as a mask:
35 | # https://stackoverflow.com/questions/69126928/hide-area-outside-of-area-of-interest-in-ggspatial
36 | rehovot_mask <- st_buffer(rehovot_sf, units::as_units(5.5, "km")) %>%
37 | st_difference(rehovot_sf)
38 |
39 | # Plot --------------------------------------------------------------------
40 | p <- ggplot() +
41 | (layer_mapbox(st_bbox(rehovot_sf, crs = 4326) + c(-0.01,-0.01,0.01, 0.01),
42 | scale_ratio = 0.6, map_style = mapbox_gallery_frank()))
43 |
44 | p +
45 | geom_sf(data = rehovot_sf, inherit.aes = F,fill = NA, color = 'black', lwd = 1) +
46 | geom_sf(data = rehovot_mask, inherit.aes = F,fill = 'white', color = NA, alpha = 0.65) +
47 | geom_sf_text(data = polling_stations, aes(label = label, color = is_voting_location ),
48 | inherit.aes = F, family = 'Font Awesome 6 Free Solid', size = 3, show.legend = FALSE)+
49 | scale_color_manual(values = c('Yes' = '#00008b', 'no' = 'gray55'))+
50 | coord_sf()+
51 | theme_void() +
52 | theme(
53 | panel.background =element_rect(fill = 'white', color = NA),
54 | plot.background =element_rect(fill = 'white', color = NA)
55 | )
56 |
57 | ggsave('test.png',width = 13, height = 13, dpi = 500)
58 |
59 |
60 | img = magick::image_read('test.png')
61 | img_cropped = magick::image_trim(img) # cutout extra white space
62 |
63 | # img2 = magick::image_crop(img, '5000x3500+750+1250')
64 |
65 | magick::image_write(img_cropped, '01_points/map.png')
66 |
--------------------------------------------------------------------------------
/2022/01_points/01_polling_locations.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/01_points/01_polling_locations.png
--------------------------------------------------------------------------------
/2022/01_points/map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/01_points/map.png
--------------------------------------------------------------------------------
/2022/01_points/polling_address_to_geo_files/libs/bootstrap/bootstrap-icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/01_points/polling_address_to_geo_files/libs/bootstrap/bootstrap-icons.woff
--------------------------------------------------------------------------------
/2022/01_points/polling_address_to_geo_files/libs/clipboard/clipboard.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * clipboard.js v2.0.10
3 | * https://clipboardjs.com/
4 | *
5 | * Licensed MIT © Zeno Rocha
6 | */
7 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1.anchorjs-link,.anchorjs-link:focus{opacity:1}",u.sheet.cssRules.length),u.sheet.insertRule("[data-anchorjs-icon]::after{content:attr(data-anchorjs-icon)}",u.sheet.cssRules.length),u.sheet.insertRule('@font-face{font-family:anchorjs-icons;src:url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype")}',u.sheet.cssRules.length)),u=document.querySelectorAll("[id]"),t=[].map.call(u,function(A){return A.id}),i=0;i\]./()*\\\n\t\b\v\u00A0]/g,"-").replace(/-{2,}/g,"-").substring(0,this.options.truncate).replace(/^-+|-+$/gm,"").toLowerCase()},this.hasAnchorJSLink=function(A){var e=A.firstChild&&-1<(" "+A.firstChild.className+" ").indexOf(" anchorjs-link "),A=A.lastChild&&-1<(" "+A.lastChild.className+" ").indexOf(" anchorjs-link ");return e||A||!1}}});
9 | // @license-end
--------------------------------------------------------------------------------
/2022/01_points/polling_address_to_geo_files/libs/quarto-html/quarto-syntax-highlighting.css:
--------------------------------------------------------------------------------
1 | /* quarto syntax highlight colors */
2 | :root {
3 | --quarto-hl-ot-color: #003B4F;
4 | --quarto-hl-at-color: #657422;
5 | --quarto-hl-ss-color: #20794D;
6 | --quarto-hl-an-color: #5E5E5E;
7 | --quarto-hl-fu-color: #4758AB;
8 | --quarto-hl-st-color: #20794D;
9 | --quarto-hl-cf-color: #003B4F;
10 | --quarto-hl-op-color: #5E5E5E;
11 | --quarto-hl-er-color: #AD0000;
12 | --quarto-hl-bn-color: #AD0000;
13 | --quarto-hl-al-color: #AD0000;
14 | --quarto-hl-va-color: #111111;
15 | --quarto-hl-bu-color: inherit;
16 | --quarto-hl-ex-color: inherit;
17 | --quarto-hl-pp-color: #AD0000;
18 | --quarto-hl-in-color: #5E5E5E;
19 | --quarto-hl-vs-color: #20794D;
20 | --quarto-hl-wa-color: #5E5E5E;
21 | --quarto-hl-do-color: #5E5E5E;
22 | --quarto-hl-im-color: #00769E;
23 | --quarto-hl-ch-color: #20794D;
24 | --quarto-hl-dt-color: #AD0000;
25 | --quarto-hl-fl-color: #AD0000;
26 | --quarto-hl-co-color: #5E5E5E;
27 | --quarto-hl-cv-color: #5E5E5E;
28 | --quarto-hl-cn-color: #8f5902;
29 | --quarto-hl-sc-color: #5E5E5E;
30 | --quarto-hl-dv-color: #AD0000;
31 | --quarto-hl-kw-color: #003B4F;
32 | }
33 |
34 | /* other quarto variables */
35 | :root {
36 | --quarto-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
37 | }
38 |
39 | pre > code.sourceCode > span {
40 | color: #003B4F;
41 | }
42 |
43 | code span {
44 | color: #003B4F;
45 | }
46 |
47 | code.sourceCode > span {
48 | color: #003B4F;
49 | }
50 |
51 | div.sourceCode,
52 | div.sourceCode pre.sourceCode {
53 | color: #003B4F;
54 | }
55 |
56 | code span.ot {
57 | color: #003B4F;
58 | }
59 |
60 | code span.at {
61 | color: #657422;
62 | }
63 |
64 | code span.ss {
65 | color: #20794D;
66 | }
67 |
68 | code span.an {
69 | color: #5E5E5E;
70 | }
71 |
72 | code span.fu {
73 | color: #4758AB;
74 | }
75 |
76 | code span.st {
77 | color: #20794D;
78 | }
79 |
80 | code span.cf {
81 | color: #003B4F;
82 | }
83 |
84 | code span.op {
85 | color: #5E5E5E;
86 | }
87 |
88 | code span.er {
89 | color: #AD0000;
90 | }
91 |
92 | code span.bn {
93 | color: #AD0000;
94 | }
95 |
96 | code span.al {
97 | color: #AD0000;
98 | }
99 |
100 | code span.va {
101 | color: #111111;
102 | }
103 |
104 | code span.pp {
105 | color: #AD0000;
106 | }
107 |
108 | code span.in {
109 | color: #5E5E5E;
110 | }
111 |
112 | code span.vs {
113 | color: #20794D;
114 | }
115 |
116 | code span.wa {
117 | color: #5E5E5E;
118 | font-style: italic;
119 | }
120 |
121 | code span.do {
122 | color: #5E5E5E;
123 | font-style: italic;
124 | }
125 |
126 | code span.im {
127 | color: #00769E;
128 | }
129 |
130 | code span.ch {
131 | color: #20794D;
132 | }
133 |
134 | code span.dt {
135 | color: #AD0000;
136 | }
137 |
138 | code span.fl {
139 | color: #AD0000;
140 | }
141 |
142 | code span.co {
143 | color: #5E5E5E;
144 | }
145 |
146 | code span.cv {
147 | color: #5E5E5E;
148 | font-style: italic;
149 | }
150 |
151 | code span.cn {
152 | color: #8f5902;
153 | }
154 |
155 | code span.sc {
156 | color: #5E5E5E;
157 | }
158 |
159 | code span.dv {
160 | color: #AD0000;
161 | }
162 |
163 | code span.kw {
164 | color: #003B4F;
165 | }
166 |
167 | .prevent-inlining {
168 | content: "";
169 | }
170 |
171 | /*# sourceMappingURL=debc5d5d77c3f9108843748ff7464032.css.map */
172 |
--------------------------------------------------------------------------------
/2022/01_points/polling_address_to_geo_files/libs/quarto-html/tippy.css:
--------------------------------------------------------------------------------
1 | .tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1}
--------------------------------------------------------------------------------
/2022/01_points/polling_station_rehovot.csv:
--------------------------------------------------------------------------------
1 | ,address,lat,lon
2 | ?,"??""? ????",31.8927303,34.7769436
3 | 0,"???""? ??? ?????? ??? (??? ????",31.8945265,34.7770918
4 | 0,"??""? ?""? ????",31.9021923,34.8252074
5 | 0,"??""? ?? ????",31.8852272,34.7862129
6 | 0,"????? ???? ??? ????""? (?????)",31.88723196,34.78589572
7 | 0,"???""? ?????? - ???? ?????",31.899885,34.799526
8 | 0,"??""? ???????",31.9006595,34.7997207
9 | 0,"???""? ??""? ????",31.9229061,34.8663035
10 | 0,"??""? ???? ?'",31.8917685,34.7995722
11 | 0,"??""? ???? ?",31.8917685,34.7995722
12 | 0,"??""? ???",31.89704658,34.80304551
13 | 0,"??""? ????? ???",31.8941148,34.805065
14 | 0,????? ??????? ????? ??????,31.8921107,34.80779
15 | 0,"??""? ?? ???",31.8895092,34.8089408
16 | 0,"????? ???? ""????""",31.8953369,34.8148519
17 | 0,"??""? ????",31.8981053,34.8154966
18 | 0,"??""? ???? ???",31.9034937,34.8153708
19 | 0,"??""? ????????",31.8964965,34.8154448
20 | 0,"??""? ??""? ???????",31.9002367,34.818781
21 | 0,??? ?????? ??? ??????,31.89650869,34.82489543
22 | 0,"??""? ????? ???? ??""? ??????",31.8920581,34.8190983
23 | 0,"???""? ???? ????",31.8905515,34.8249087
24 | 0,"??""? ???????",31.8816982,34.8196295
25 | 0,"??""? ???? ????-????",31.8839238,34.8172026
26 | 0,"??? ?""? ????-????? ???? ??????",31.8824356,34.8156686
27 | 0,"??""? ?????",31.8767152,34.8141885
28 | 0,"??""? ?? ??????",31.8785607,34.8159989
29 | 0,"???""? ???? ??? (??????)",31.90068024,34.81997323
30 | 0,"???""? ????????",31.885044,34.8026166
31 | 0,???? ??????,31.883297,34.808894
32 | 0,"??""? ?????? ???",31.8833207,34.8089712
33 | 0,?????? ???????? ???? - ??????,31.8822529,34.8287707
34 | 0,???? ??????-???? ????,31.8825048,34.8193654
35 | 0,"??""? ???""?",31.88924898,34.8239414
36 | 0,???? ????? ?????? (???),31.8896029,34.8308089
37 | 0,"??""? ???? ??????",31.8864741,34.8063198
38 | 0,"??""? ??""? ????? ?????",31.8895773,34.8236509
39 | 0,"??""? ???",31.88671967,34.8272474
40 | 0,"???""? ?????? ?????",31.8927419,34.7821437
41 | 0,??? ???? ????,31.87892544,34.81209852
42 | 0,??? ???? ????,31.9048138,34.8242721
43 | 0,"??""? ????? ????",31.9012034,34.8223669
44 | 0,"??""? ????",31.88354574,34.7912934
45 | 0,???? ?????? ????????,31.8918645,34.7825402
46 |
--------------------------------------------------------------------------------
/2022/01_points/rehovot_polls.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/01_points/rehovot_polls.xlsx
--------------------------------------------------------------------------------
/2022/02_lines/lines.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/02_lines/lines.png
--------------------------------------------------------------------------------
/2022/02_lines/lines_files/Proj4Leaflet-1.0.1/proj4leaflet.js:
--------------------------------------------------------------------------------
1 | (function (factory) {
2 | var L, proj4;
3 | if (typeof define === 'function' && define.amd) {
4 | // AMD
5 | define(['leaflet', 'proj4'], factory);
6 | } else if (typeof module === 'object' && typeof module.exports === "object") {
7 | // Node/CommonJS
8 | L = require('leaflet');
9 | proj4 = require('proj4');
10 | module.exports = factory(L, proj4);
11 | } else {
12 | // Browser globals
13 | if (typeof window.L === 'undefined' || typeof window.proj4 === 'undefined')
14 | throw 'Leaflet and proj4 must be loaded first';
15 | factory(window.L, window.proj4);
16 | }
17 | }(function (L, proj4) {
18 | if (proj4.__esModule && proj4.default) {
19 | // If proj4 was bundled as an ES6 module, unwrap it to get
20 | // to the actual main proj4 object.
21 | // See discussion in https://github.com/kartena/Proj4Leaflet/pull/147
22 | proj4 = proj4.default;
23 | }
24 |
25 | L.Proj = {};
26 |
27 | L.Proj._isProj4Obj = function(a) {
28 | return (typeof a.inverse !== 'undefined' &&
29 | typeof a.forward !== 'undefined');
30 | };
31 |
32 | L.Proj.Projection = L.Class.extend({
33 | initialize: function(code, def, bounds) {
34 | var isP4 = L.Proj._isProj4Obj(code);
35 | this._proj = isP4 ? code : this._projFromCodeDef(code, def);
36 | this.bounds = isP4 ? def : bounds;
37 | },
38 |
39 | project: function (latlng) {
40 | var point = this._proj.forward([latlng.lng, latlng.lat]);
41 | return new L.Point(point[0], point[1]);
42 | },
43 |
44 | unproject: function (point, unbounded) {
45 | var point2 = this._proj.inverse([point.x, point.y]);
46 | return new L.LatLng(point2[1], point2[0], unbounded);
47 | },
48 |
49 | _projFromCodeDef: function(code, def) {
50 | if (def) {
51 | proj4.defs(code, def);
52 | } else if (proj4.defs[code] === undefined) {
53 | var urn = code.split(':');
54 | if (urn.length > 3) {
55 | code = urn[urn.length - 3] + ':' + urn[urn.length - 1];
56 | }
57 | if (proj4.defs[code] === undefined) {
58 | throw 'No projection definition for code ' + code;
59 | }
60 | }
61 |
62 | return proj4(code);
63 | }
64 | });
65 |
66 | L.Proj.CRS = L.Class.extend({
67 | includes: L.CRS,
68 |
69 | options: {
70 | transformation: new L.Transformation(1, 0, -1, 0)
71 | },
72 |
73 | initialize: function(a, b, c) {
74 | var code,
75 | proj,
76 | def,
77 | options;
78 |
79 | if (L.Proj._isProj4Obj(a)) {
80 | proj = a;
81 | code = proj.srsCode;
82 | options = b || {};
83 |
84 | this.projection = new L.Proj.Projection(proj, options.bounds);
85 | } else {
86 | code = a;
87 | def = b;
88 | options = c || {};
89 | this.projection = new L.Proj.Projection(code, def, options.bounds);
90 | }
91 |
92 | L.Util.setOptions(this, options);
93 | this.code = code;
94 | this.transformation = this.options.transformation;
95 |
96 | if (this.options.origin) {
97 | this.transformation =
98 | new L.Transformation(1, -this.options.origin[0],
99 | -1, this.options.origin[1]);
100 | }
101 |
102 | if (this.options.scales) {
103 | this._scales = this.options.scales;
104 | } else if (this.options.resolutions) {
105 | this._scales = [];
106 | for (var i = this.options.resolutions.length - 1; i >= 0; i--) {
107 | if (this.options.resolutions[i]) {
108 | this._scales[i] = 1 / this.options.resolutions[i];
109 | }
110 | }
111 | }
112 |
113 | this.infinite = !this.options.bounds;
114 |
115 | },
116 |
117 | scale: function(zoom) {
118 | var iZoom = Math.floor(zoom),
119 | baseScale,
120 | nextScale,
121 | scaleDiff,
122 | zDiff;
123 | if (zoom === iZoom) {
124 | return this._scales[zoom];
125 | } else {
126 | // Non-integer zoom, interpolate
127 | baseScale = this._scales[iZoom];
128 | nextScale = this._scales[iZoom + 1];
129 | scaleDiff = nextScale - baseScale;
130 | zDiff = (zoom - iZoom);
131 | return baseScale + scaleDiff * zDiff;
132 | }
133 | },
134 |
135 | zoom: function(scale) {
136 | // Find closest number in this._scales, down
137 | var downScale = this._closestElement(this._scales, scale),
138 | downZoom = this._scales.indexOf(downScale),
139 | nextScale,
140 | nextZoom,
141 | scaleDiff;
142 | // Check if scale is downScale => return array index
143 | if (scale === downScale) {
144 | return downZoom;
145 | }
146 | if (downScale === undefined) {
147 | return -Infinity;
148 | }
149 | // Interpolate
150 | nextZoom = downZoom + 1;
151 | nextScale = this._scales[nextZoom];
152 | if (nextScale === undefined) {
153 | return Infinity;
154 | }
155 | scaleDiff = nextScale - downScale;
156 | return (scale - downScale) / scaleDiff + downZoom;
157 | },
158 |
159 | distance: L.CRS.Earth.distance,
160 |
161 | R: L.CRS.Earth.R,
162 |
163 | /* Get the closest lowest element in an array */
164 | _closestElement: function(array, element) {
165 | var low;
166 | for (var i = array.length; i--;) {
167 | if (array[i] <= element && (low === undefined || low < array[i])) {
168 | low = array[i];
169 | }
170 | }
171 | return low;
172 | }
173 | });
174 |
175 | L.Proj.GeoJSON = L.GeoJSON.extend({
176 | initialize: function(geojson, options) {
177 | this._callLevel = 0;
178 | L.GeoJSON.prototype.initialize.call(this, geojson, options);
179 | },
180 |
181 | addData: function(geojson) {
182 | var crs;
183 |
184 | if (geojson) {
185 | if (geojson.crs && geojson.crs.type === 'name') {
186 | crs = new L.Proj.CRS(geojson.crs.properties.name);
187 | } else if (geojson.crs && geojson.crs.type) {
188 | crs = new L.Proj.CRS(geojson.crs.type + ':' + geojson.crs.properties.code);
189 | }
190 |
191 | if (crs !== undefined) {
192 | this.options.coordsToLatLng = function(coords) {
193 | var point = L.point(coords[0], coords[1]);
194 | return crs.projection.unproject(point);
195 | };
196 | }
197 | }
198 |
199 | // Base class' addData might call us recursively, but
200 | // CRS shouldn't be cleared in that case, since CRS applies
201 | // to the whole GeoJSON, inluding sub-features.
202 | this._callLevel++;
203 | try {
204 | L.GeoJSON.prototype.addData.call(this, geojson);
205 | } finally {
206 | this._callLevel--;
207 | if (this._callLevel === 0) {
208 | delete this.options.coordsToLatLng;
209 | }
210 | }
211 | }
212 | });
213 |
214 | L.Proj.geoJson = function(geojson, options) {
215 | return new L.Proj.GeoJSON(geojson, options);
216 | };
217 |
218 | L.Proj.ImageOverlay = L.ImageOverlay.extend({
219 | initialize: function (url, bounds, options) {
220 | L.ImageOverlay.prototype.initialize.call(this, url, null, options);
221 | this._projectedBounds = bounds;
222 | },
223 |
224 | // Danger ahead: Overriding internal methods in Leaflet.
225 | // Decided to do this rather than making a copy of L.ImageOverlay
226 | // and doing very tiny modifications to it.
227 | // Future will tell if this was wise or not.
228 | _animateZoom: function (event) {
229 | var scale = this._map.getZoomScale(event.zoom);
230 | var northWest = L.point(this._projectedBounds.min.x, this._projectedBounds.max.y);
231 | var offset = this._projectedToNewLayerPoint(northWest, event.zoom, event.center);
232 |
233 | L.DomUtil.setTransform(this._image, offset, scale);
234 | },
235 |
236 | _reset: function () {
237 | var zoom = this._map.getZoom();
238 | var pixelOrigin = this._map.getPixelOrigin();
239 | var bounds = L.bounds(
240 | this._transform(this._projectedBounds.min, zoom)._subtract(pixelOrigin),
241 | this._transform(this._projectedBounds.max, zoom)._subtract(pixelOrigin)
242 | );
243 | var size = bounds.getSize();
244 |
245 | L.DomUtil.setPosition(this._image, bounds.min);
246 | this._image.style.width = size.x + 'px';
247 | this._image.style.height = size.y + 'px';
248 | },
249 |
250 | _projectedToNewLayerPoint: function (point, zoom, center) {
251 | var viewHalf = this._map.getSize()._divideBy(2);
252 | var newTopLeft = this._map.project(center, zoom)._subtract(viewHalf)._round();
253 | var topLeft = newTopLeft.add(this._map._getMapPanePos());
254 |
255 | return this._transform(point, zoom)._subtract(topLeft);
256 | },
257 |
258 | _transform: function (point, zoom) {
259 | var crs = this._map.options.crs;
260 | var transformation = crs.transformation;
261 | var scale = crs.scale(zoom);
262 |
263 | return transformation.transform(point, scale);
264 | }
265 | });
266 |
267 | L.Proj.imageOverlay = function (url, bounds, options) {
268 | return new L.Proj.ImageOverlay(url, bounds, options);
269 | };
270 |
271 | return L.Proj;
272 | }));
273 |
--------------------------------------------------------------------------------
/2022/02_lines/lines_files/leaflet-1.3.1/images/layers-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/02_lines/lines_files/leaflet-1.3.1/images/layers-2x.png
--------------------------------------------------------------------------------
/2022/02_lines/lines_files/leaflet-1.3.1/images/layers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/02_lines/lines_files/leaflet-1.3.1/images/layers.png
--------------------------------------------------------------------------------
/2022/02_lines/lines_files/leaflet-1.3.1/images/marker-icon-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/02_lines/lines_files/leaflet-1.3.1/images/marker-icon-2x.png
--------------------------------------------------------------------------------
/2022/02_lines/lines_files/leaflet-1.3.1/images/marker-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/02_lines/lines_files/leaflet-1.3.1/images/marker-icon.png
--------------------------------------------------------------------------------
/2022/02_lines/lines_files/leaflet-1.3.1/images/marker-shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/02_lines/lines_files/leaflet-1.3.1/images/marker-shadow.png
--------------------------------------------------------------------------------
/2022/02_lines/lines_files/leaflet-providers-plugin-2.1.1/leaflet-providers-plugin.js:
--------------------------------------------------------------------------------
1 | LeafletWidget.methods.addProviderTiles = function(provider, layerId, group, options) {
2 | this.layerManager.addLayer(L.tileLayer.provider(provider, options), "tile", layerId, group);
3 | };
4 |
--------------------------------------------------------------------------------
/2022/02_lines/lines_files/leafletfix-1.0.0/leafletfix.css:
--------------------------------------------------------------------------------
1 | /* Work around CSS properties introduced on img by bootstrap */
2 | img.leaflet-tile {
3 | padding: 0;
4 | margin: 0;
5 | border-radius: 0;
6 | border: none;
7 | }
8 | .info {
9 | padding: 6px 8px;
10 | font: 14px/16px Arial, Helvetica, sans-serif;
11 | background: white;
12 | background: rgba(255,255,255,0.8);
13 | box-shadow: 0 0 15px rgba(0,0,0,0.2);
14 | border-radius: 5px;
15 | }
16 | .legend {
17 | line-height: 18px;
18 | color: #555;
19 | }
20 | .legend svg text {
21 | fill: #555;
22 | }
23 | .legend svg line {
24 | stroke: #555;
25 | }
26 | .legend i {
27 | width: 18px;
28 | height: 18px;
29 | margin-right: 4px;
30 | opacity: 0.7;
31 | display: inline-block;
32 | vertical-align: top;
33 | /*For IE 7*/
34 | zoom: 1;
35 | *display: inline;
36 | }
37 |
--------------------------------------------------------------------------------
/2022/02_lines/lines_files/rstudio_leaflet-1.3.1/images/1px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/02_lines/lines_files/rstudio_leaflet-1.3.1/images/1px.png
--------------------------------------------------------------------------------
/2022/02_lines/lines_files/rstudio_leaflet-1.3.1/rstudio_leaflet.css:
--------------------------------------------------------------------------------
1 | .leaflet-tooltip.leaflet-tooltip-text-only,
2 | .leaflet-tooltip.leaflet-tooltip-text-only:before,
3 | .leaflet-tooltip.leaflet-tooltip-text-only:after {
4 | background: none;
5 | border: none;
6 | box-shadow: none;
7 | }
8 |
9 | .leaflet-tooltip.leaflet-tooltip-text-only.leaflet-tooltip-left {
10 | margin-left: 5px;
11 | }
12 |
13 | .leaflet-tooltip.leaflet-tooltip-text-only.leaflet-tooltip-right {
14 | margin-left: -5px;
15 | }
16 |
17 | .leaflet-tooltip:after {
18 | border-right: 6px solid transparent;
19 | /* right: -16px; */
20 | }
21 |
22 | .leaflet-popup-pane .leaflet-popup-tip-container {
23 | /* when the tooltip container is clicked, it is closed */
24 | pointer-events: all;
25 | /* tooltips should display the "hand" icon, just like .leaflet-interactive*/
26 | cursor: pointer;
27 | }
28 |
29 | /* have the widget be displayed in the right 'layer' */
30 | .leaflet-map-pane {
31 | z-index: auto;
32 | }
33 |
34 | /* Add missing rule from leaflet for img.
35 | This complete existing leaflet.css.
36 | Fix for https://github.com/rstudio/rmarkdown/issues/1949 */
37 | .leaflet-container .leaflet-right-pane img,
38 | .leaflet-container .leaflet-left-pane img {
39 | max-width: none !important;
40 | max-height: none !important;
41 | }
42 |
--------------------------------------------------------------------------------
/2022/02_lines/routes.R:
--------------------------------------------------------------------------------
1 | # Code from Alexandra Kapp day 9: https://alexandrakapp.github.io/30daymapchallenge/index.html
2 | # Check it out^^
3 |
4 | library(sf)
5 | library(dplyr)
6 | library(osrm)
7 | library(stplanr)
8 | library(leaflet)
9 | library(htmltools)
10 | library(htmlwidgets)
11 | library(webshot)
12 |
13 | rehovot_path <- list.files('../data/maps/judicial/', recursive = T, pattern = 'gv_Rehovot_2016_plt\\.shp$')
14 |
15 | rehovot_sf <- st_read(paste0('../data/maps/judicial/', rehovot_path)) %>%
16 | st_transform(crs = 4326)# %>%
17 | # remove the holes (combine Gibton)
18 | # sfheaders::sf_remove_holes()
19 |
20 |
21 | routes <- route(from = st_coordinates(st_sample(rehovot_sf, size = 1000)),
22 | to = st_coordinates(st_sample(rehovot_sf, size = 1000)),
23 | route_fun = osrmRoute,
24 | returnclass = "sf")
25 |
26 | routes["count"] <- 1
27 |
28 | overlapping_segments <- overline(routes, attrib = "count")
29 |
30 | p <- leaflet(overlapping_segments) %>%
31 | addProviderTiles(providers$CartoDB.DarkMatter) %>%
32 | addPolylines(weight = overlapping_segments$count / 6, color = "white") %>%
33 | addControl(html = paste(tags$h1(HTML("Major routes
in Rehovot, Israel"), style = "color:white; font-family:Merriweather; font-size: 30pt; padding-left: 12px; line-height: 1.2em;"),
34 | tags$div(HTML("Most commonly traveled roads
from a sample of 1000 routes."), style = "color:white; font-family:Segoe UI; font-size: 15pt; padding-left: 15px; margin-top:-20px"))
35 | , className = "fieldset {
36 | border: 0;
37 | }", position = "topleft") %>%
38 | addControl(html = tags$div(HTML("Adapted from Alexandra Kapp • Data: {stplanr} package • Amit Levinson"), style = "color:#BEBEBE; font-family:Segoe UI; font-size: 10pt; padding-left: 15px;"), className = "fieldset {border: 0;}", position = "bottomleft")
39 |
40 | # Saving a snapshot
41 | saveWidget(p, "02_lines/lines.html")
42 | webshot("02_lines/lines.html", file = "02_lines/lines.png", zoom = 3, vwidth = 1000, vheight = 700, delay = 2)
43 |
--------------------------------------------------------------------------------
/2022/03_polygons/all_rides.rds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/03_polygons/all_rides.rds
--------------------------------------------------------------------------------
/2022/03_polygons/area_distribution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/03_polygons/area_distribution.png
--------------------------------------------------------------------------------
/2022/03_polygons/area_distribution_updated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/03_polygons/area_distribution_updated.png
--------------------------------------------------------------------------------
/2022/03_polygons/bus_stops.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/03_polygons/bus_stops.png
--------------------------------------------------------------------------------
/2022/03_polygons/bus_stops_updated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/03_polygons/bus_stops_updated.png
--------------------------------------------------------------------------------
/2022/03_polygons/stops_in_rehovot.rds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/03_polygons/stops_in_rehovot.rds
--------------------------------------------------------------------------------
/2022/07_raster/07_raster.R:
--------------------------------------------------------------------------------
1 | # https://rspatialdata.github.io/elevation.html
2 |
3 | library(elevatr)
4 | library(sf)
5 | library(raster)
6 | library(ggplot2)
7 | library(ggtext)
8 |
9 | # Get Israel map for extracting raster layer below, you can also use the {rgeoboundaries} instead
10 | # to get boundaries of a country you're interested in.
11 | isr_map <- readRDS(paste0('../data/maps/00_Israel_0_sf.rds'))
12 |
13 |
14 | # Get elevation data
15 | isrraster <- get_elev_raster(locations = isr_map, z = 10, clip = "locations")
16 |
17 | elevation_data <- as.data.frame(isrraster, xy = TRUE)
18 | colnames(elevation_data)[3] <- "elevation"
19 | elevation_data <- elevation_data[complete.cases(elevation_data), ]
20 |
21 | ggplot() +
22 | geom_raster(data = elevation_data, aes(x = x, y = y, fill = elevation)) +
23 | coord_sf() +
24 | scale_fill_viridis_c(name = "Elevation (meters)" ,option = 'E', labels = scales::comma) +
25 | labs(title = "Elevation in Israel",
26 | x = "Longitude",
27 | y = "Latitude",
28 | caption = 'Data: {elvatar} package & AWS Tiles • Visualization: Amit Grinson') +
29 | theme(
30 | text = element_text(family = "Quicksand", lineheight = 1),
31 | plot.title = element_text(size = 28, family = "Roboto Slab", face = 'bold', hjust = 1),
32 | plot.subtitle = element_text(size = 18, lineheight = 1.1),
33 | plot.caption = element_markdown(hjust = 0, size = 12, color = "gray25"),
34 | axis.text = element_blank(),
35 | axis.title = element_blank(),
36 | legend.title = element_text(size = 12),
37 | legend.text = element_text(size = 10),
38 | # legend.position = 'horizontal',
39 | panel.background = element_rect(fill = "white", color = NA),
40 | plot.background = element_rect(fill = "white", color = NA),
41 | panel.grid = element_blank(),
42 | plot.margin = margin(6,2,6,2,"mm"),
43 | axis.ticks = element_blank()
44 | )
45 |
46 | ggsave('07_raster/elevation_high_res.png', width = 7, height = 11)
47 |
--------------------------------------------------------------------------------
/2022/07_raster/elevation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/07_raster/elevation.png
--------------------------------------------------------------------------------
/2022/07_raster/elevation_high_res.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/07_raster/elevation_high_res.png
--------------------------------------------------------------------------------
/2022/08_osm/rehovot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/08_osm/rehovot.png
--------------------------------------------------------------------------------
/2022/08_osm/rehovot_sf/gv_Rehovot_2016_plt.dbf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/08_osm/rehovot_sf/gv_Rehovot_2016_plt.dbf
--------------------------------------------------------------------------------
/2022/08_osm/rehovot_sf/gv_Rehovot_2016_plt.prj:
--------------------------------------------------------------------------------
1 | PROJCS["Israel_TM_Grid",GEOGCS["GCS_Israel",DATUM["D_Israel",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",219529.584],PARAMETER["False_Northing",626907.39],PARAMETER["Central_Meridian",35.20451694444445],PARAMETER["Scale_Factor",1.0000067],PARAMETER["Latitude_Of_Origin",31.73439361111111],UNIT["Meter",1.0]]
--------------------------------------------------------------------------------
/2022/08_osm/rehovot_sf/gv_Rehovot_2016_plt.shp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/08_osm/rehovot_sf/gv_Rehovot_2016_plt.shp
--------------------------------------------------------------------------------
/2022/08_osm/rehovot_sf/gv_Rehovot_2016_plt.shx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/08_osm/rehovot_sf/gv_Rehovot_2016_plt.shx
--------------------------------------------------------------------------------
/2022/14_hexagons/14_hexagons.R:
--------------------------------------------------------------------------------
1 | library(sf)
2 | library(dplyr)
3 | library(ggplot2)
4 | library(googleway)
5 | library(purrr)
6 | library(tidyr)
7 |
8 | rehovot_path <- list.files('data/maps/judicial/', recursive = T, pattern = 'gv_Rehovot_2016_plt\\.shp$')
9 |
10 | rehovot_sf <- st_read(paste0('data/maps/judicial/', rehovot_path)) %>%
11 | # st_transform(crs = 4326) %>%
12 | sfheaders::sf_remove_holes()
13 |
14 | home <- st_geometry(st_point(c(34.809366, 31.898025))) %>%
15 | st_set_crs(4326)
16 |
17 | grid_square <- st_make_grid(rehovot_sf, cellsize = 250,square = FALSE)
18 |
19 |
20 | rehovot_grid <- grid_square[st_intersects(grid_square, rehovot_sf, sparse = F) %>%
21 | as.vector()] %>%
22 | st_transform(crs = 4326) %>%
23 | st_as_sf()
24 |
25 | hexagons_to_measure <- rehovot_grid[!st_within(home, rehovot_grid, sparse = F) %>% as.vector(),]
26 |
27 |
28 |
29 | hexagons_centroids <- rehovot_grid %>%
30 | st_centroid() %>%
31 | st_coordinates() %>%
32 | as_tibble() %>%
33 | select(lat = Y, long = X)
34 |
35 | get_distance_info <- function(lat, long, way) {
36 | Sys.sleep(1)
37 | travel_info <- googleway::google_distance(origins = c(31.89803, 34.80937),
38 | destinations = c(lat, long),
39 | mode = way,
40 | key = keyring::key_get('google-key'))
41 |
42 | dat <- travel_info$rows$elements[[1]] %>%
43 | as_tibble() %>%
44 | unnest() %>%
45 | mutate(mode = way,
46 | address = travel_info$destination_addresses,
47 | lat = lat,
48 | long = long)
49 |
50 | return(dat)
51 | }
52 | #
53 | # get_distance_info(31.8975, 34.76228, 'transit')
54 |
55 |
56 | safe_info <- safely(get_distance_info)
57 |
58 | # queried 21:00
59 | # driving_info <- pmap_dfr(list(hexagons_centroids$lat, hexagons_centroids$long, 'driving'), safe_info)
60 | # saveRDS(driving_info, '2022/14_hexagons/driving.rds')
61 | driving <- readRDS('2022/14_hexagons/driving.rds')
62 | ?google_distance
63 |
64 | # biking_info <- pmap_dfr(list(hexagons_centroids$lat, hexagons_centroids$long, 'bicycling'), safe_info)
65 | # saveRDS(biking_info, '2022/14_hexagons/biking.rds')
66 | biking <- readRDS('2022/14_hexagons/biking.rds')
67 |
68 | hexagons_distance <- rbind(biking, driving) %>%
69 | rename(travel_seconds = value1, travel_m = value) %>%
70 | # group_by(lat,long) %>%
71 | pivot_wider(id_cols = c('long', 'lat'),
72 | values_from = c(travel_seconds,travel_m),names_from = 'mode') %>%
73 | mutate(ratio = travel_seconds_bicycling - travel_seconds_driving) %>%
74 | st_as_sf(coords = c('long', 'lat'), crs = 4326) %>%
75 | st_join(x= hexagons_to_measure, y = .)
76 |
77 | limit <- max(abs(hexagons_distance$ratio)) * c(-1, 1)
78 |
79 | ggplot(hexagons_distance) +
80 | geom_sf(aes(fill = ratio))+
81 | scale_fill_distiller(palette = 'RdBu', limit =limit )
82 |
83 | hexagons_distance %>%
84 | arrange(ratio)
85 |
86 | pal <- colorNumeric('RdBu',hexagons_distance$ratio)
87 |
88 | library(leaflet)
89 | leaflet(hexagons_distance) %>%
90 | addTiles() %>%
91 | addPolygons(stroke = FALSE, fillOpacity = 0.8,
92 | fillColor = pal(hexagons_distance$ratio)) %>%
93 | addLegend(pal = pal, values = ~ratio)
94 |
95 |
96 | ?colorNumeric
97 | ggplot(aes(fill = ratio)) +
98 | geom_sf(color = NA)
99 |
100 | rehovot_grid %>%
101 | st_as_sf
102 |
103 | rbind(biking, driving) %>%
104 | count(address, sort = T)
105 | rename(travel_seconds = value1, travel_m = value) %>%
106 | st_as_sf(coords = c('long', 'lat'), crs = 4326) %>%
107 |
108 | st_as_sf(coordinates = c('$long', '$lat'))
109 |
110 | driving_info$result$duration %>% as_tibble()
111 |
112 | ?google_distance
113 |
114 | keyring::key_set('google-key')
115 |
116 | test$rows$elements %>%
117 | as.data.frame()
118 |
119 |
120 |
121 | ggmap::has_google_key()
122 | test <- route(from = home,
123 | to = hexagons_centroids[1:3], mode = 'bicycling')
124 |
125 |
126 |
127 |
128 |
129 | grid_centroid <- tibble(
130 | grid = st_geometry(rehovot_grid),
131 | centroid = rehovot_grid %>% st_centroid()
132 | )
133 |
134 |
135 | tes <- rbind(home, hexagons_centroids %>% head(1)) %>%
136 | as.data.frame() %>%
137 | st_as_sf(crs = 4326)
138 |
139 | routes <- osrm::osrmTrip(
140 | loc = tes,
141 | osrm.profile = 'bike')
142 |
143 | install.packages('googleway')
144 |
145 | bike_route <- osrm::osrmTable(src = home, dst = hexagons_dist %>% filter(is.na(duration)) %>% st_centroid(),
146 | osrm.profile = 'bike' )
147 |
148 |
149 | test_plot <- data.frame(st_geometry(hexagons_to_measure)) %>%
150 | mutate(
151 | duration = bike_route$durations %>% as.vector()
152 | ) %>%
153 | st_as_sf()
154 |
155 | hexagons_dist %>% filter(is.na(duration)) %>% st_centroid() %>%
156 | ggplot() +
157 | geom_sf()
158 |
159 | dat <- bike_route$destinations %>%
160 | st_as_sf(coords = c('lon', 'lat'), crs = 4326) %>%
161 | mutate(duration = bike_route$durations %>% as.vector())
162 |
163 | hexagons_dist <- st_join(hexagons_to_measure %>% st_as_sf(), dat)
164 | hexagons_dist%>%
165 | ggplot() +
166 | geom_sf(aes(fill = duration))
167 |
168 |
169 | class(dat)
170 | class()
171 | ?st_coordinates()
172 | st_
173 | bike_route$destinations
174 |
175 | plot(hexagons_to_measure)
176 | test_plot
177 |
178 | ggplot(test_plot) +
179 | geom_sf(aes(color = duration))
180 |
181 | plot(test_plot)
182 |
183 | ggplot()
184 |
185 | ?osrm::osrmTable
186 | routes[[1]][[1]]
187 |
188 | routes
189 | plot(routes)
190 |
191 | ggplot()+
192 | geom_sf(hexagons_to_measure,mapping = aes(), fill ='red')
193 | geom_sf(home, inherit.aes = F, mapping = aes())
194 |
195 | pharmacy <- st_read(system.file("gpkg/apotheke.gpkg", package = "osrm"),
196 | quiet = TRUE)
197 | travel_time <- osrmTable(loc = pharmacy)
198 | travel_time$durations[1:5,1:5]
199 |
200 |
--------------------------------------------------------------------------------
/2022/14_hexagons/14_hexagons_accidents.R:
--------------------------------------------------------------------------------
1 | library(sf)
2 | library(dplyr)
3 | library(ggplot2)
4 | library(readr)
5 | library(ggtext)
6 |
7 | rehovot_path <- list.files('data/maps/judicial/', recursive = T, pattern = 'gv_Rehovot_2016_plt\\.shp$')
8 | rehovot_sf <- st_read(paste0('data/maps/judicial/', rehovot_path)) %>%
9 | sfheaders::sf_remove_holes()
10 |
11 | grid_square <- st_make_grid(rehovot_sf, cellsize = 500,square = FALSE)
12 |
13 | rehovot_grid <- grid_square[st_intersects(grid_square, rehovot_sf, sparse = F) %>%
14 | as.vector()] %>%
15 | st_transform(crs = 4326) %>%
16 | st_as_sf() %>%
17 | mutate(id = 1:nrow(.)) %>%
18 | rename(geometry = x)
19 |
20 | loc <- read_csv('-2019.csv')
21 |
22 | loc_clean <- loc %>%
23 | filter(!is.na(X) | !is.na(Y)) %>%
24 | st_as_sf(coords = c('X', 'Y'), crs = 2039)
25 |
26 | rehovot_accidents <- loc_clean[st_within(loc_clean, rehovot_sf, sparse = F),] %>%
27 | st_transform(crs = 4326)
28 |
29 |
30 |
31 |
32 | hexagons_with_accidents <- rehovot_grid %>%
33 | mutate(total = lengths(st_intersects(., rehovot_accidents)),
34 | total = ifelse(total == 0, NA, total))
35 |
36 | ggplot(hexagons_with_accidents) +
37 | geom_sf(aes(fill = total), color = 'gray45', lwd = 0.25) +
38 | scale_fill_gradient(name = '# Accidents', low = '#000000', high = '#FF0000', na.value = 'gray85',
39 | breaks = seq(2,12,4))+
40 | guides(fill = guide_colorbar(title.position="top", title.hjust = 0.5))+
41 | labs(title = 'Car Accidents in Rehovot, IL',
42 | subtitle = 'Number of car accidents occurring in 2019 per 500m2',
43 | caption = 'Data: gov.il • Amit Grinson')+
44 | theme_minimal()+
45 | theme(
46 | text = element_text(family = "Public Sans"),
47 | plot.title = element_text(size = 28, face = 'bold'),
48 | plot.title.position = "plot",
49 | plot.subtitle = element_markdown(size = 18),
50 | plot.caption = element_markdown(hjust = 1, size = 12, color = "gray35"),
51 | axis.text = element_blank(),
52 | axis.title = element_blank(),
53 | legend.title = element_text(size = 15),
54 | legend.text = element_text(size = 12),
55 | legend.position = 'bottom',
56 | legend.key.height = unit(4, 'mm'),
57 | panel.grid = element_blank(),
58 | plot.margin = margin(6,2,6,2,"mm"),
59 | plot.background = element_rect(fill = 'white', color = NA),
60 | panel.background = element_rect(fill = 'white', color = NA)
61 | )
62 |
63 |
64 | ggsave('2022/14_hexagons/accidents.png', width = 10, height = 8)
65 |
66 |
--------------------------------------------------------------------------------
/2022/14_hexagons/accidents.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/14_hexagons/accidents.png
--------------------------------------------------------------------------------
/2022/14_hexagons/biking.rds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/14_hexagons/biking.rds
--------------------------------------------------------------------------------
/2022/14_hexagons/driving.rds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/2022/14_hexagons/driving.rds
--------------------------------------------------------------------------------
/30daymapchallenge.Rproj:
--------------------------------------------------------------------------------
1 | Version: 1.0
2 |
3 | RestoreWorkspace: Default
4 | SaveWorkspace: Default
5 | AlwaysSaveHistory: Default
6 |
7 | EnableCodeIndexing: Yes
8 | UseSpacesForTab: Yes
9 | NumSpacesForTab: 2
10 | Encoding: UTF-8
11 |
12 | RnwWeave: Sweave
13 | LaTeX: pdfLaTeX
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 30daymapchallenge
2 |
3 | ### What's this project all about?
4 |
5 | Taken from the [GitHub page](https://github.com/tjukanovt/30DayMapChallenge) of the project:
6 |
7 | > "The idea is to create (and publish) maps based on different themes on each day of the month using the hashtag #30DayMapChallenge, You can prepare the maps beforehand, but the main idea is to publish maps from specific topics on specific days listed below. Just include a picture of the map when you post to Twitter with the hashtag. You don't have to sign up anywhere to participate. There are no restrictions on the tools, technologies and the data you use in your maps. Doing less than 30 is also fine (and actually doing all 30 is really hard!)..."
8 |
9 | #### How do I see it?
10 |
11 | **I don't get to plot maps that often in my daily work, so I find this challenge a great opportunity in doing so.** I'll try to do as many as possible, and you can find below all of the attempts including links to the code for you to explore.
12 |
13 | Enjoy!
14 |
15 | ## 2020
16 |
17 | ### Day 20 - Population (Animated + static)
18 |
19 | [Link to code](https://github.com/AmitLevinson/30daymapchallenge/blob/main/2020/Code/20_population/population.R)
20 |
21 |
22 | 
23 |
24 |
25 |
26 |
27 |
28 | ### Day 08 - Yellow
29 |
30 | [Link to code](https://github.com/AmitLevinson/30daymapchallenge/blob/main/2020/Code/08_yellow/08_yellow.R)
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | ### Day 07 - Green
40 |
41 | [Link to code](https://github.com/AmitLevinson/30daymapchallenge/blob/main/2020/Code/07_green/07_green.R)
42 |
43 |
44 |
45 |
46 |
47 |
48 | ### Day 03 - Polygon
49 |
50 | [Link to code](https://github.com/AmitLevinson/30daymapchallenge/blob/main/2020/Code/03_Polygons/03_polygons.R)
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | ### Day 02 - Lines
60 |
61 | [Link to code](https://github.com/AmitLevinson/30daymapchallenge/blob/main/2020/Code/02_lines/02_lines.R)
62 |
63 |
64 |
65 |
66 |
67 |
68 | ### Day 01 - Points
69 |
70 | [Link to code](https://github.com/AmitLevinson/30daymapchallenge/blob/main/2020/Code/01_points/01_points.R)
71 |
72 |
73 |
74 |
75 |
76 | Back to top
--------------------------------------------------------------------------------
/data/maps/00_Israel_0_sf.rds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/data/maps/00_Israel_0_sf.rds
--------------------------------------------------------------------------------
/data/maps/gadm36_ISR_0_sf.rds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/data/maps/gadm36_ISR_0_sf.rds
--------------------------------------------------------------------------------
/data/maps/gadm36_ISR_0_sp.rds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/data/maps/gadm36_ISR_0_sp.rds
--------------------------------------------------------------------------------
/data/maps/gadm36_ISR_1_sf.rds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/data/maps/gadm36_ISR_1_sf.rds
--------------------------------------------------------------------------------
/data/maps/isr-full/israel_borders.dbf:
--------------------------------------------------------------------------------
1 | o
2 | A W Id N
0
--------------------------------------------------------------------------------
/data/maps/isr-full/israel_borders.prj:
--------------------------------------------------------------------------------
1 | PROJCS["WGS_1984_UTM_Zone_36N",GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",33.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]]
--------------------------------------------------------------------------------
/data/maps/isr-full/israel_borders.sbn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/data/maps/isr-full/israel_borders.sbn
--------------------------------------------------------------------------------
/data/maps/isr-full/israel_borders.sbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/data/maps/isr-full/israel_borders.sbx
--------------------------------------------------------------------------------
/data/maps/isr-full/israel_borders.shp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/data/maps/isr-full/israel_borders.shp
--------------------------------------------------------------------------------
/data/maps/isr-full/israel_borders.shx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/data/maps/isr-full/israel_borders.shx
--------------------------------------------------------------------------------
/expc.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AmitLevinson/30daymapchallenge/2b65006b1b68ef6364028fe72b324c62ffe8cfe0/expc.csv
--------------------------------------------------------------------------------