diff --git a/.Rbuildignore b/.Rbuildignore index 30c967a..37b7dba 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -4,3 +4,5 @@ appveyor.yml codecov.yml ^docs$ tic.R +^.*\.Rproj$ +^\.Rproj\.user$ diff --git a/DESCRIPTION b/DESCRIPTION index 46256a7..352af70 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -40,4 +40,5 @@ Collate: perimeter.R clockwise.R geod.R + startpoint.R RoxygenNote: 6.0.1 diff --git a/NAMESPACE b/NAMESPACE index cba8975..0debab0 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -46,6 +46,7 @@ export(st_perimeter) export(st_perimeter_2d) export(st_snap_to_grid) export(st_split) +export(st_startpoint) export(st_subdivide) export(st_transform_proj) import(sf) diff --git a/R/RcppExports.R b/R/RcppExports.R index 1be04ca..20039a1 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -81,6 +81,10 @@ CPL_force_polygon_cw <- function(sfc) { .Call('_lwgeom_CPL_force_polygon_cw', PACKAGE = 'lwgeom', sfc) } +CPL_startpoint <- function(sfc) { + .Call('_lwgeom_CPL_startpoint', PACKAGE = 'lwgeom', sfc) +} + CPL_proj_version <- function(b = FALSE) { .Call('_lwgeom_CPL_proj_version', PACKAGE = 'lwgeom', b) } diff --git a/R/startpoint.R b/R/startpoint.R new file mode 100644 index 0000000..1a1422e --- /dev/null +++ b/R/startpoint.R @@ -0,0 +1,17 @@ +#' Return the start and end points from lines +#' +#' @param x line of class \code{sf}, \code{sfc} or \code{sfg} +#' @export +#' @details see \url{https://postgis.net/docs/ST_StartPoint.html} and \url{https://postgis.net/docs/ST_EndPoint.html}. +#' @return \code{sf} object representing start and end points +#' @examples +#' library(sf) +#' m = matrix(c(0, 1, 2, 0, 1, 4), ncol = 2) +#' l = st_sfc(st_linestring(m)) +#' lwgeom::st_startpoint(l) +#' l2 = st_sfc(st_linestring(m), st_linestring(m[3:1, ])) +#' lwgeom::st_startpoint(l2) +st_startpoint = function(x) { + m <- CPL_startpoint(st_geometry(x)) + st_sfc(lapply(seq_len(nrow(m)), function(i) st_point(m[i,])), crs = st_crs(x)) +} diff --git a/man/st_startpoint.Rd b/man/st_startpoint.Rd new file mode 100644 index 0000000..723db2b --- /dev/null +++ b/man/st_startpoint.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/startpoint.R +\name{st_startpoint} +\alias{st_startpoint} +\title{Return the start and end points from lines} +\usage{ +st_startpoint(x) +} +\arguments{ +\item{x}{line of class \code{sf}, \code{sfc} or \code{sfg}} +} +\value{ +\code{sf} object representing start and end points +} +\description{ +Return the start and end points from lines +} +\details{ +see \url{https://postgis.net/docs/ST_StartPoint.html} and \url{https://postgis.net/docs/ST_EndPoint.html}. +} +\examples{ +library(sf) +m = matrix(c(0, 1, 2, 0, 1, 4), ncol = 2) +l = st_sfc(st_linestring(m)) +lwgeom::st_startpoint(l) +l2 = st_sfc(st_linestring(m), st_linestring(m[3:1, ])) +lwgeom::st_startpoint(l2) +} diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 1076197..c47d663 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -246,6 +246,17 @@ BEGIN_RCPP return rcpp_result_gen; END_RCPP } +// CPL_startpoint +Rcpp::NumericMatrix CPL_startpoint(Rcpp::List sfc); +RcppExport SEXP _lwgeom_CPL_startpoint(SEXP sfcSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP); + rcpp_result_gen = Rcpp::wrap(CPL_startpoint(sfc)); + return rcpp_result_gen; +END_RCPP +} // CPL_proj_version std::string CPL_proj_version(bool b); RcppExport SEXP _lwgeom_CPL_proj_version(SEXP bSEXP) { @@ -293,6 +304,7 @@ static const R_CallMethodDef CallEntries[] = { {"_lwgeom_CPL_perimeter", (DL_FUNC) &_lwgeom_CPL_perimeter, 2}, {"_lwgeom_CPL_is_polygon_cw", (DL_FUNC) &_lwgeom_CPL_is_polygon_cw, 1}, {"_lwgeom_CPL_force_polygon_cw", (DL_FUNC) &_lwgeom_CPL_force_polygon_cw, 1}, + {"_lwgeom_CPL_startpoint", (DL_FUNC) &_lwgeom_CPL_startpoint, 1}, {"_lwgeom_CPL_proj_version", (DL_FUNC) &_lwgeom_CPL_proj_version, 1}, {"_lwgeom_CPL_linesubstring", (DL_FUNC) &_lwgeom_CPL_linesubstring, 4}, {NULL, NULL, 0} diff --git a/src/lwgeom.cpp b/src/lwgeom.cpp index fd45272..696509f 100644 --- a/src/lwgeom.cpp +++ b/src/lwgeom.cpp @@ -244,3 +244,21 @@ Rcpp::List CPL_force_polygon_cw(Rcpp::List sfc) { } return sfc_from_lwgeom(lwgeom_cw); } + +// [[Rcpp::export]] +Rcpp::NumericMatrix CPL_startpoint(Rcpp::List sfc) { + + std::vector lwgeom_cw = lwgeom_from_sfc(sfc); + Rcpp::NumericMatrix m(lwgeom_cw.size(), 2); + + POINT4D p; + for (size_t i = 0; i < lwgeom_cw.size(); i++) { + lwgeom_startpoint(lwgeom_cw[i], &p); + m(i, 0) = p.x; + m(i, 1) = p.y; + } + + return m; + // next step: get it into sf form + // return sfc_from_lwgeom(lwgeom_cw); +}