Splitting line or polygon with sf: st_intersection doesn’t work?

huangapple go评论111阅读模式
英文:

Splitting line or polygon with sf: st_intersection doesn't work?

问题

I'm trying to do the seemingly simple task of split Russia along the Ural mountains, but I must be misunderstanding something basic in sf_intersection. I can't even split the line, much less create two new polygons.

  1. rm(list=ls())
  2. library(rworldmap)
  3. library(tidyverse)
  4. library(sf)
  5. setwd("/Users/mr56267/Documents/UT_web/TLAH_Maps_2023/Mapping_textbook")
  6. world_sp <- fortify(getMap())
  7. world_sf <- world_sp %>%
  8. st_as_sf(coords = c("long", "lat"), crs = 4326, row.names="group") %>%
  9. group_by(group) %>%
  10. summarise(geometry = st_combine(geometry)) %>%
  11. st_cast("POLYGON")
  12. ggplot() +
  13. geom_sf(data = world_sf)
  14. world_robinson <- st_transform(world_sf,
  15. crs = '+proj=robin +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs')
  16. Russia.sf <- world_robinson$geometry[which(world_robinson$group=="Russia.1")]
  17. ### good to here
  18. ### now split Russia on Urals
  19. https://raw.githubusercontent.com/sashatrubetskoy/asia_europe_border/master/asia_europe_border.geojson
  20. Urals.sf <- st_read("https://raw.githubusercontent.com/sashatrubetskoy/asia_europe_border/master/asia_europe_border.geojson")
  21. Urals.sf <- st_transform(Urals.sf, crs = st_crs(world_robinson$geometry[which(world_robinson$group=="Russia.1")]))
  22. Russia_line.sf <- st_cast(Russia.sf,"MULTILINESTRING")
  23. intersection_points <- st_intersection(Russia_line.sf,Urals.sf)
  24. intersection_points
  25. st_intersects(intersection_points,Russia_line.sf)

What's going on here? How can the points created with st_intersection not be points of intersection? Everything looks good:

  1. ggplot() + geom_sf(data=Russia_line.sf) + geom_sf(data=Urals.sf, color="red") +
  2. geom_sf(data=intersection_points, color="green")

How do I split Russia into east and west?

英文:

I'm trying to do the seemingly simple task of split Russia along the Ural mountains, but I must be misunderstanding something basic in sf_intersection. I can't even split the line, much less create two new polygons

  1. rm(list=ls())
  2. library(rworldmap)
  3. library(tidyverse)
  4. library(sf)
  5. setwd(&quot;/Users/mr56267/Documents/UT_web/TLAH_Maps_2023/Mapping_textbook&quot;)
  6. world_sp &lt;- fortify(getMap())
  7. world_sf &lt;- world_sp %&gt;% st_as_sf(coords = c(&quot;long&quot;, &quot;lat&quot;), crs = 4326, row.names=&quot;group&quot;) %&gt;%
  8. group_by(group) %&gt;% summarise(geometry = st_combine(geometry)) %&gt;% st_cast(&quot;POLYGON&quot;)
  9. ggplot() +
  10. geom_sf(data = world_sf)
  11. world_robinson &lt;- st_transform(world_sf,
  12. crs = &#39;+proj=robin +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs&#39;)
  13. Russia.sf &lt;- world_robinson$geometry[which(world_robinson$group==&quot;Russia.1&quot;)]
  14. ### good to here
  15. ### now split Russia on Urals
  16. https://raw.githubusercontent.com/sashatrubetskoy/asia_europe_border/master/asia_europe_border.geojson
  17. Urals.sf &lt;- st_read(&quot;https://raw.githubusercontent.com/sashatrubetskoy/asia_europe_border/master/asia_europe_border.geojson&quot;)
  18. Urals.sf &lt;- st_transform(Urals.sf, crs = st_crs(world_robinson$geometry[which(world_robinson$group==&quot;Russia.1&quot;)]))
  19. Russia_line.sf &lt;- st_cast(Russia.sf,&quot;MULTILINESTRING&quot;)
  20. intersection_points &lt;- st_intersection(Russia_line.sf,Urals.sf)
  21. intersection_points
  22. st_intersects(intersection_points,Russia_line.sf)

What's going on here? How can the points created with st_intersection not be points of intersection? Everything looks good:

  1. ggplot() + geom_sf(data=Russia_line.sf) + geom_sf(data=Urals.sf, color=&quot;red&quot;) +
  2. geom_sf(data=intersection_points, color=&quot;green&quot;)

How do I split Russia into east and west?

答案1

得分: 3

使用建议中提到的lwgeom::st_split()函数,形式为lwgeom::st_split(POLYGON, LINESTRING)。需要注意的一点是,您正在使用的边界相当详细,因此取决于Russia.sf的分辨率(例如边界的详细程度),可能会在里海附近产生不希望出现的伪影,特别是在陆地边界上(这里预期边界应与陆地边界匹配)。

以下是使用giscoR世界地图的完整示例,具有合理的分辨率(我使用了rworldmap进行测试,伪影出现在那里):

  1. library(giscoR)
  2. library(tidyverse)
  3. library(sf)
  4. #&gt; Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1; sf_use_s2() is TRUE
  5. # 使用 giscoR
  6. world_sf &lt;- gisco_get_countries(resolution = 10)
  7. ggplot() +
  8. geom_sf(data = world_sf)

Splitting line or polygon with sf: st_intersection doesn’t work?<!-- -->

  1. world_robinson &lt;- st_transform(world_sf,
  2. crs = &quot;+proj=robin +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs&quot;
  3. )
  4. # 提取俄罗斯并将其分解为所有相邻的陆地区域(POLYGONS)
  5. Russia_exploded &lt;- world_robinson %&gt;%
  6. 翻译部分结束
  7. <details>
  8. <summary>英文:</summary>
  9. Use `lwgeom::st_split()` as suggested in the comments, in the form of `lwgeom::st_split(POLYGON, LINESTRING)`. One thing to bear in mind is that the borders you are using are quite detailed, hence depending on the resolution of `Russia.sf`(e.g. how detailed are the borders) it may produce undesired artifacts, specially in the near the Caspian Sea (where the limits are expected to match the landmass borders).
  10. See a full example using `giscoR` world map with a reasonable good resolution (I tested with `rworldmap` and that&#39;s when artifacts appear):
  11. ``` r
  12. library(giscoR)
  13. library(tidyverse)
  14. library(sf)
  15. #&gt; Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1; sf_use_s2() is TRUE
  16. # Using giscoR instead
  17. world_sf &lt;- gisco_get_countries(resolution = 10)
  18. ggplot() +
  19. geom_sf(data = world_sf)

Splitting line or polygon with sf: st_intersection doesn’t work?<!-- -->

  1. world_robinson &lt;- st_transform(world_sf,
  2. crs = &quot;+proj=robin +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs&quot;
  3. )
  4. # Extract Russia and explode it in all the contiguous landmasses (POLYGONS)
  5. Russia_exploded &lt;- world_robinson %&gt;%
  6. filter(ISO3_CODE == &quot;RUS&quot;) %&gt;%
  7. st_cast(&quot;POLYGON&quot;)
  8. #&gt; Warning in st_cast.sf(., &quot;POLYGON&quot;): repeating attributes for all
  9. #&gt; sub-geometries for which they may not be constant
  10. # Extract mainland as the largest contiguous portion of Russia
  11. # Equivalent to your world_robinson$group==&quot;Russia.1&quot;
  12. Russia.sf &lt;- Russia_exploded[which.max(st_area(Russia_exploded)), ] %&gt;%
  13. st_union() %&gt;%
  14. st_sf(cntry = &quot;Russia&quot;)
  15. ggplot(Russia.sf) +
  16. geom_sf()

Splitting line or polygon with sf: st_intersection doesn’t work?<!-- -->

  1. ### now split Russia on Urals
  2. # https://raw.githubusercontent.com/sashatrubetskoy/asia_europe_border/master/asia_europe_border.geojson
  3. download.file(&quot;https://raw.githubusercontent.com/sashatrubetskoy/asia_europe_border/master/asia_europe_border.geojson&quot;,
  4. &quot;border.geojson&quot;,
  5. mode = &quot;wb&quot;
  6. )
  7. Urals.sf &lt;- read_sf(&quot;border.geojson&quot;) %&gt;%
  8. st_geometry() %&gt;%
  9. st_combine() %&gt;%
  10. st_line_merge() %&gt;%
  11. st_transform(st_crs(world_robinson))
  12. ggplot(Russia.sf) +
  13. geom_sf() +
  14. geom_sf(data = Urals.sf)

Splitting line or polygon with sf: st_intersection doesn’t work?<!-- -->

  1. # Split with lwgeom
  2. Russia_splitted &lt;- lwgeom::st_split(Russia.sf, Urals.sf) %&gt;%
  3. st_collection_extract(&quot;POLYGON&quot;)
  4. Russia_splitted$gr &lt;- factor(seq_len(nrow(Russia_splitted)))
  5. ggplot(Russia_splitted) +
  6. geom_sf(aes(fill = gr))

Splitting line or polygon with sf: st_intersection doesn’t work?<!-- -->

  1. # Done, now identify resulting polygons (visually) and assign continent
  2. Russia_splitted_end &lt;- Russia_splitted %&gt;%
  3. mutate(Continent = ifelse(gr == &quot;1&quot;, &quot;Asia&quot;, &quot;Europe&quot;)) %&gt;%
  4. group_by(Continent) %&gt;%
  5. summarise()
  6. ggplot(Russia_splitted_end) +
  7. geom_sf(aes(fill = Continent))

Splitting line or polygon with sf: st_intersection doesn’t work?<!-- -->

  1. # Same but faceted
  2. ggplot(Russia_splitted_end) +
  3. geom_sf(aes(fill = Continent)) +
  4. facet_wrap(~Continent, ncol = 1)

Splitting line or polygon with sf: st_intersection doesn’t work?<!-- -->

<sup>Created on 2023-06-28 with reprex v2.0.2</sup>

huangapple
  • 本文由 发表于 2023年6月27日 20:16:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76564769.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定