Skip to content

Commit

Permalink
Add flag gj2008 to allow reverse polygon winding order (#168)
Browse files Browse the repository at this point in the history
* Add gj2008 flag to allow reverse winding order

* Expose gj2008 flag in dots arguments

* Ensure all -o flags are passed together

* Add test for #167

* Update NEWS for #167, #168

* Add gj2008 to sf and sp methods

* Remove spurious argument to fc_command()

* Add gj2008 to clip and erase

* Ensure quiet flag is passed through appropriately

* Update documenation for gj2008 flag

* Update snapshot

* quiet flag only apply when sys = TRUE

* Test gj2008 with sf
  • Loading branch information
ateucher authored Oct 23, 2023
1 parent 807a4e7 commit 576f6b4
Show file tree
Hide file tree
Showing 23 changed files with 432 additions and 199 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
* Setting `force_FC = TRUE` no longer adds a `rmapshaperid` id column. `force_FC`
is also better respected across functions and methods; previously it was
somewhat inconsistent (#151).
* Added new argument `gj2008`, which if `TRUE` outputs geojson following the old
(2008) specification. Polygon rings are CW and holes are CCW, which is the
opposite of the default RFC 7946-compatible output. This is required by D3, and
packages that depend on it, like plotly (#167, #168).

# rmapshaper 0.5.0

Expand Down
62 changes: 48 additions & 14 deletions R/clip_erase.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#' @param bbox supply a bounding box instead of a clipping layer to extract from
#' the target layer. Supply as a numeric vector: \code{c(minX, minY, maxX, maxY)}.
#' @param remove_slivers Remove tiny sliver polygons created by clipping. (Default \code{FALSE})
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet gj2008
#'
#' @return clipped target in the same class as the input target
#'
Expand Down Expand Up @@ -138,7 +138,7 @@ ms_clip.sfc <- function(target, clip = NULL, bbox = NULL,
#' @param bbox supply a bounding box instead of an erasing layer to remove from
#' the target layer. Supply as a numeric vector: \code{c(minX, minY, maxX, maxY)}.
#' @param remove_slivers Remove tiny sliver polygons created by erasing. (Default \code{FALSE})
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet gj2008
#'
#' @return erased target in the same format as the input target
#' @examples
Expand Down Expand Up @@ -249,7 +249,8 @@ ms_erase.sfc <- function(target, erase = NULL, bbox = NULL,
clip_erase_json <- function(target, overlay_layer, bbox, remove_slivers, type,
force_FC = TRUE, sys = FALSE,
sys_mem = getOption("mapshaper.sys_mem", default = 8),
quiet = getOption("mapshaper.sys_quiet", default = FALSE)) {
quiet = getOption("mapshaper.sys_quiet", default = FALSE),
gj2008 = FALSE) {

check_overlay_bbox(overlay_layer = overlay_layer, bbox = bbox, type = type)

Expand All @@ -259,13 +260,15 @@ clip_erase_json <- function(target, overlay_layer, bbox, remove_slivers, type,

mapshaper_clip_erase(target_layer = target, overlay_layer = overlay_layer, type = type,
remove_slivers = remove_slivers, bbox = bbox,
force_FC = force_FC, sys = sys, sys_mem = sys_mem, quiet = quiet)
force_FC = force_FC, sys = sys, sys_mem = sys_mem, quiet = quiet,
gj2008 = gj2008)
}

clip_erase_sp <- function(target, overlay_layer, bbox, type, remove_slivers,
force_FC = TRUE, sys = FALSE,
sys_mem = getOption("mapshaper.sys_mem", default = 8),
quiet = getOption("mapshaper.sys_quiet", default = FALSE)) {
quiet = getOption("mapshaper.sys_quiet", default = FALSE),
gj2008 = FALSE) {

check_overlay_bbox(overlay_layer = overlay_layer, bbox = bbox, type = type)

Expand All @@ -284,7 +287,8 @@ clip_erase_sp <- function(target, overlay_layer, bbox, type, remove_slivers,
result <- mapshaper_clip_erase(target_layer = target_geojson,
overlay_layer = overlay_geojson,
type = type, remove_slivers = remove_slivers,
bbox = bbox, force_FC = TRUE, sys = sys, sys_mem = sys_mem)
bbox = bbox, force_FC = TRUE, sys = sys,
sys_mem = sys_mem, quiet = quiet, gj2008 = gj2008)

ret <- GeoJSON_to_sp(result, target_proj)

Expand All @@ -299,7 +303,8 @@ clip_erase_sp <- function(target, overlay_layer, bbox, type, remove_slivers,
clip_erase_sf <- function(target, overlay_layer, bbox, type, remove_slivers,
force_FC = TRUE, sys = FALSE,
sys_mem = getOption("mapshaper.sys_mem", default = 8),
quiet = getOption("mapshaper.sys_quiet", default = FALSE)) {
quiet = getOption("mapshaper.sys_quiet", default = FALSE),
gj2008 = FALSE) {

check_overlay_bbox(overlay_layer = overlay_layer, bbox = bbox, type = type)

Expand All @@ -323,10 +328,18 @@ clip_erase_sf <- function(target, overlay_layer, bbox, type, remove_slivers,

target_geojson <- sf_to_GeoJSON(target, file = sys)

result <- mapshaper_clip_erase(target_layer = target_geojson,
overlay_layer = overlay_geojson,
type = type, remove_slivers = remove_slivers,
bbox = bbox, force_FC = TRUE, sys = sys, sys_mem = sys_mem)
result <- mapshaper_clip_erase(
target_layer = target_geojson,
overlay_layer = overlay_geojson,
bbox = bbox,
type = type,
remove_slivers = remove_slivers,
force_FC = TRUE,
sys = sys,
sys_mem = sys_mem,
quiet = quiet,
gj2008 = gj2008
)

ret <- GeoJSON_to_sf(result, target_proj)

Expand Down Expand Up @@ -361,21 +374,38 @@ check_overlay_bbox <- function(overlay_layer, bbox, type) {
mapshaper_clip_erase <- function(target_layer, overlay_layer, bbox, type,
remove_slivers, force_FC = TRUE, sys = FALSE,
sys_mem = getOption("mapshaper.sys_mem", default = 8),
quiet = getOption("mapshaper.sys_quiet", default = FALSE)) {
quiet = getOption("mapshaper.sys_quiet", default = FALSE),
gj2008 = FALSE) {


remove_slivers <- ifelse(remove_slivers, "remove-slivers", "")

if (!is.null(bbox)) {
cmd <- paste0("-", type, " bbox=",paste0(bbox, collapse = ","), " ",
remove_slivers)
out <- apply_mapshaper_commands(target_layer, cmd, force_FC = force_FC, sys = sys, sys_mem = sys_mem, quiet = quiet)
out <- apply_mapshaper_commands(
target_layer,
cmd,
force_FC = force_FC,
sys = sys,
sys_mem = sys_mem,
quiet = quiet,
gj2008 = gj2008
)
} else if (!is.null(overlay_layer)) {

if (sys) {
on.exit(unlink(c(target_layer, overlay_layer)), add = TRUE)
cmd <- paste0("-", type)
out <- sys_mapshaper(data = target_layer, data2 = overlay_layer, command = cmd, force_FC = force_FC, sys_mem = sys_mem, quiet = quiet)
out <- sys_mapshaper(
data = target_layer,
data2 = overlay_layer,
command = cmd,
force_FC = force_FC,
sys_mem = sys_mem,
quiet = quiet,
gj2008 = gj2008
)
} else {

ms <- ms_make_ctx()
Expand All @@ -400,6 +430,10 @@ mapshaper_clip_erase <- function(target_layer, overlay_layer, bbox, type,
command <- paste(command, fc_command())
}

if (isTRUE(gj2008)) {
command <- paste(command, "gj2008")
}

# Create an object to hold the return value
ms$eval("var return_data;")

Expand Down
2 changes: 1 addition & 1 deletion R/dissolve.R
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#' @param copy_fields fields to copy. The first instance of each field will be
#' copied to the aggregated feature.
#' @param weight Name of an attribute field for generating weighted centroids (points only).
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet gj2008
#'
#' @return the same class as the input
#'
Expand Down
2 changes: 1 addition & 1 deletion R/explode.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#' \item multipart \code{SpatialPolygons}, \code{SpatialLines};
#' \item \code{sf} or \code{sfc} multipart lines, or polygons object
#' }
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet gj2008
#'
#' @return same class as input
#'
Expand Down
2 changes: 1 addition & 1 deletion R/filter_islands.R
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#' @param drop_null_geometries should features with empty geometries be dropped?
#' Default \code{TRUE}. Ignored for \code{SpatialPolyons*}, as it is always
#' \code{TRUE}.
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet gj2008
#'
#' @return object with only specified features retained, in the same class as
#' the input
Expand Down
2 changes: 1 addition & 1 deletion R/inner_lines.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#' \item \code{SpatialPolygons*};
#' \item \code{sf} or \code{sfc} polygons object
#' }
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet gj2008
#'
#' @return lines in the same class as the input layer, but without attributes
#'
Expand Down
2 changes: 1 addition & 1 deletion R/lines.R
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#' intermediate level of hierarchy at TYPE 1, with the lowest-level internal
#' boundaries set to TYPE 2. Supplying a character vector of field names adds
#' additional levels of hierarchy.
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet gj2008
#'
#' @return topological boundaries as lines, in the same class as the input
#'
Expand Down
2 changes: 1 addition & 1 deletion R/points.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#' \code{location} is specified.
#' @param y name of field containing y coordinate values. Must be \code{NULL} if
#' \code{location} is specified.
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet gj2008
#'
#' @return points in the same class as the input.
#'
Expand Down
2 changes: 1 addition & 1 deletion R/simplify.R
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#' Ignored for \code{Spatial*} objects, as it is always \code{TRUE}.
#' @param snap_interval Specify snapping distance in source units, must be a
#' numeric. Default \code{NULL}
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet
#' @inheritDotParams apply_mapshaper_commands force_FC sys sys_mem quiet gj2008
#'
#' @return a simplified representation of the geometry in the same class as the
#' input
Expand Down
Loading

0 comments on commit 576f6b4

Please sign in to comment.