Skip to contents

[Experimental]

Tests whether points are inside a polygon using Cartesian coordinates. Distinguishes between points that are inside, outside, or on the polygon boundary.

Usage

point_in_polygon(point_x = NULL, point_y = NULL, poly_x = NULL, poly_y = NULL)

Arguments

point_x

Numeric vector of x coordinates for points to test

point_y

Numeric vector of y coordinates for points to test

poly_x

Numeric vector of x coordinates defining polygon vertices

poly_y

Numeric vector of y coordinates defining polygon vertices

Value

Integer vector: 0 = outside polygon, 1 = inside polygon -OR- on polygon boundary

Details

The function uses the sf package's geometry operations with Cartesian coordinates. If the provided polygon's first and last vertices are different, it is not considered to be a closed polygon. If this occurs, it will be automatically closed. All input vectors must be numeric, and point_x/point_y must have matching lengths, as must poly_x/poly_y.

Examples

# point_in_polygon can be used with basic vectors#
# X points we want to check the position of relevant to the polygon
point_x <- c(0.5, 1.5, 2.5, 1.0, 3.0)
# Y points we want to check the position of relevant to the polygon
point_y <- c(0.5, 1.5, 2.5, 0.0, 1.0)
# X points of the polygon we want to test against
poly_x <- c(0, 2, 2, 0, 0)
# Y points of the polygon we want to test against
poly_y <- c(0, 0, 2, 2, 0)

# 0 = outside polygon, 1 = inside polygon or on boundary
point_in_polygon(point_x, point_y, poly_x, poly_y)
#> [1] 1 1 0 1 0

# point_in_polygon can also be used within a data frame#
library(dplyr)

test_data <- data.frame(px = c(0.5, 1.5, 2.5), py = c(0.5, 1.5, 2.5))
polygon_x <- c(0, 2, 2, 0, 0)
polygon_y <- c(0, 0, 2, 2, 0)

test_data |>
  mutate(logic = point_in_polygon(px, py, polygon_x, polygon_y))
#>    px  py logic
#> 1 0.5 0.5     1
#> 2 1.5 1.5     1
#> 3 2.5 2.5     0

# You can also see the results of the function visualized on a ggplot#
library(ggplot2)

# Create test points and polygon for visualization
df_points_prep <-
  tibble(
    x = c(0.5, 1.5, 2.5, 1.0, 0.0, 3.0),
    y = c(0.5, 1.5, 2.5, 0.0, 1.0, 1.0)
  )
df_polygon <-
  tibble(
    x = c(0, 2, 2, 0, 0),
    y = c(0, 0, 2, 2, 0)
  )

# Test the points and add labels for the plot
df_points <-
  df_points_prep |>
  mutate(
    position = point_in_polygon(x, y, df_polygon$x, df_polygon$y),
    position_string = case_match(position,
                                 0 ~ "Outside",
                                 1 ~ "Inside/On Boundary"
                                 ) |> factor(),
    color = case_match(position,
                       0 ~ "#e31a1c",
                       1 ~ "#33a02c"
                       )
  )

# Pull out the colors for the plot points
unique_df <- unique(df_points[c("position_string", "color")])
vec_colors <- setNames(unique_df$color, unique_df$position_string)

# Plot it
ggplot() +
  geom_polygon(data = df_polygon, aes(x = x, y = y),
               fill = "#104d70", alpha = 0.3, color = "black", linewidth = 1) +
  geom_point(data = df_points, aes(x = x, y = y, color = position_string), size = 4) +
  scale_color_manual(values = vec_colors) +
  labs(color = "Position:") +
  coord_equal()