选择多边形最长边上的一个随机点。

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

Select a random point along the longest edges of a polygon

问题

我有一个形状文件,其中包含许多表示农场上田地的多边形。在现实生活中进行田间采样时,我需要沿着每个田地(多边形)的2个最长边之一行走50米的横切线。我的最初目标是创建一个脚本,将在多边形的最长边上的某个位置放置一个随机的50米线(类似于st_sample,但是是线而不是点),但这似乎比仅仅找到多边形边缘上的一个点要困难得多。

我尝试过的方法:
我还没有想到一种选择沿多边形边缘的50米线段的方法,所以我的下一个想法是使用sf包中的st_segmentize,然后也许尝试使用st_buffer来筛选间距为50米的点,并使用这两个点作为横切线的起点/终点。然而,并不能保证这些点位于多边形的最长边上,也不能保证它们之间恰好相隔50米(考虑到st_buffer的性质,它们可能相隔超过50米)。这是我到目前为止所做的:

library(sf)
library(tidyverse)

field <- st_polygon(x=list(cbind(x=c(8.069730,  8.069209, 8.069521, 8.070026, 8.069730),
                             y=c(46.94751, 46.94925, 46.94922, 46.94754, 46.94751)))) %>%
  st_sfc(crs = 4326)

edge_pts <- st_segmentize(field, dfMaxLength = 50) %>%
    st_coordinates() %>%
    as.data.frame() %>%
    dplyr::select(X, Y) %>%
    st_as_sf(coords = c("X", "Y")) %>%
    st_set_crs(4326)

plot(field, reset = FALSE)
plot(edge_pts, reset = FALSE, add = TRUE)

老实说,在这一点上,如果我能找到一种方法,即使只是在多边形的两个最长边中间附近获取一个单一点(而不是在田地的顶点),我会满意的。

英文:

I have a shapefile that consists of many polygons representing fields on a farm. For field sampling in real life, I need to walk a 50m transect along one of the 2 longest sides of each field (polygon). My original goal was to create a script that would place a random 50m line somewhere along the longest side of the polygon (like st_sample, but with a line instead of a point), but that seems to be much more difficult than just finding a point on the edge of a polygon.

What I have attempted:
I haven't thought of a way to select a 50m line segment along the edge of the polygon, so my next thought was to use st_segmentize from the sf package, and then maybe try to filter for points that are 50m apart using st_buffer and use the two points as starting/ending points for the transect line. However, there is no guarantee that the points are on the longest sides of the polygon, nor that there will be any that are exactly 50m apart (given the nature of st_buffer, they could be more than 50m apart). This is what I've gotten so far:

library(sf)
library(tidyverse)

field &lt;- st_polygon(x=list(cbind(x=c(8.069730,  8.069209, 8.069521, 8.070026, 8.069730),
                                 y=c(46.94751, 46.94925, 46.94922, 46.94754, 46.94751)))) %&gt;% 
  st_sfc(crs = 4326)

edge_pts &lt;- st_segmentize(field, dfMaxLength = 50) %&gt;% 
    st_coordinates() %&gt;% 
    as.data.frame() %&gt;% 
    dplyr::select(X, Y) %&gt;% 
    st_as_sf(coords = c(&quot;X&quot;, &quot;Y&quot;)) %&gt;% 
    st_set_crs(4326)

plot(field, reset = FALSE)
plot(edge_pts, reset = FALSE, add = TRUE)

选择多边形最长边上的一个随机点。

Honestly, at this point, if I could even find a way to just get a single point near the middle of the two longest sides of the polygon (and not on the vertices of the field), I would be fine with that.

答案1

得分: 1

The commented example below should split a polygon into segments, select the two longest segments, and return a point along each of the two segments.

library(sf)
library(tidyverse)
library(nngeo)

set.seed(6)                      # for reproducibility due to st_sample

field &lt;- st_polygon(x=list(cbind(x=c(8.069730,  8.069209, 8.069521, 8.070026, 8.069730),
                                 y=c(46.94751, 46.94925, 46.94922, 46.94754, 46.94751)))) %&gt;% 
  st_sfc(crs = 4326)

points &lt;- 
field %&gt;%
  st_as_sf() %&gt;%
  st_segments() %&gt;%                 # from nngeo package, splits polygon into lines
  mutate(len = st_length(.)) %&gt;%    # length of each edge
  top_n(n = 2, wt = len) %&gt;%        # select two longest sides from polygon
  st_sample(size = c(1,1)) 

#plotting:
ggplot() + 
  geom_sf(data = field) +
  geom_sf(data = points, color = 'red')

选择多边形最长边上的一个随机点。

创建于2023年5月25日,由reprex包 (v2.0.1)创建

英文:

The commented example below should split a polygon into segments, select the two longest segments, and return a point along each of the two segments.

library(sf)
library(tidyverse)
library(nngeo)

set.seed(6)                      # for reproducibility due to st_sample

field &lt;- st_polygon(x=list(cbind(x=c(8.069730,  8.069209, 8.069521, 8.070026, 8.069730),
                                 y=c(46.94751, 46.94925, 46.94922, 46.94754, 46.94751)))) %&gt;% 
  st_sfc(crs = 4326)

points &lt;- 
field %&gt;%
  st_as_sf() %&gt;%
  st_segments() %&gt;%                 # from nngeo package, splits polygon into lines
  mutate(len = st_length(.)) %&gt;%    # length of each edge
  top_n(n = 2, wt = len) %&gt;%        # select two longest sides from polygon
  st_sample(size = c(1,1)) 

#plotting:
ggplot() + 
  geom_sf(data = field) +
  geom_sf(data = points, color = &#39;red&#39;)

选择多边形最长边上的一个随机点。

<sup>Created on 2023-05-25 by the reprex package (v2.0.1)</sup>

答案2

得分: 0

以下是翻译好的部分:

找到最长的边,通过计算 Li:= (Xi+1 - Xi)² + (Yi+1 - Yi)² 对所有边进行计算(对于最后一条边,索引会循环),并保留产生最大值的 i

要获得这条边的长度,取平方根(所以将 Li -> √Li)。

如果 Li < 50,则没有解决方案。否则,坐标为

X = Xi + 50/Li (Xi+1 - Xi)
Y = Yi + 50/Li (Yi+1 - Yi)

附录:

如果您的多边形是3D的,只需在 Z 上进行插值

Z = Zi + 50/Li (Zi+1 - Zi)

这假定50米是水平长度。如果您需要斜向长度,请使用

Li:= (Xi+1 - Xi)² + (Yi+1 - Yi)² + (Zi+1 - Zi)²;

代替。

英文:

As I am not R-speaking, I will just give you the maths.

Find the longest edge by computing Li:= (Xi+1 - Xi)&#178; + (Yi+1 - Yi)&#178; for all edges (the index wraps around for the last edge), and keeping the i that gives the largest value.

To get the length of this side, take the square root (so replace Li -&gt; √Li).

If Li &lt; 50, there is no solution. Otherwise, the coordinates are

X = Xi + 50/Li (Xi+1 - Xi)
Y = Yi + 50/Li (Yi+1 - Yi)

Addendum:

If your polygons are 3D, you simply add the interpolation on Z

Z = Zi + 50/Li (Zi+1 - Zi)

This assumes that the 50 m is an horizontal length. If you need the oblique length, use

Li:= (Xi+1 - Xi)&#178; + (Yi+1 - Yi)&#178; + (Zi+1 - Zi)&#178;

instead.

huangapple
  • 本文由 发表于 2023年5月25日 16:08:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76330150.html
匿名

发表评论

匿名网友

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

确定