Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] setting up Inst/Include header #18

Merged
merged 7 commits into from
May 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# decido 0.2.0.9

* Created decido.hpp header file for linking from other packages

# decido 0.2.0

* Increased automated test coverage of underlying library code.
Expand Down
4 changes: 4 additions & 0 deletions R/RcppExports.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ earcut_cpp <- function(x, y, holes, numholes) {
.Call(`_decido_earcut_cpp`, x, y, holes, numholes)
}

earcut_sfg <- function(sfg) {
.Call(`_decido_earcut_sfg`, sfg)
}

7 changes: 3 additions & 4 deletions R/decido-package.R
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
#' @keywords internal
"_PACKAGE"


#' @useDynLib 'decido', .registration = TRUE
#' @importFrom Rcpp sourceCpp
NULL

#' @keywords internal
"_PACKAGE"


#' decido
#'
Expand Down
207 changes: 207 additions & 0 deletions inst/include/decido/decido.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
#ifndef R_DECIDO_EARCUT_H
#define R_DECIDO_EARCUT_H

#include <RcppCommon.h>
#include <array>
#include "earcut.h"


namespace Rcpp {

template < typename T > SEXP wrap( std::array< T, 2 >& Point );
template < typename T > SEXP wrap( std::vector< std::array< T, 2 > >& Polygon );
template < typename T > SEXP wrap( std::vector< std::vector< std::array< T, 2 > > >& Polygons );

namespace traits {

template < typename T > class Exporter< std::array< T, 2 > >;
template < typename T > class Exporter< std::vector< std::array< T, 2 > > >;
template < typename T > class Exporter< std::vector< std::vector< std::array< T, 2 > > > >;

} // traits
} // Rcpp

#include <Rcpp.h>

namespace Rcpp {

template <typename T>
SEXP wrap( std::array< T, 2 >& Point ) {
Rcpp::NumericVector v(2);
v[0] = Point[0];
v[1] = Point[1];
return v;
}

template < typename T >
SEXP wrap( std::vector< std::array< T, 2 > >& Polygon ) {
R_xlen_t n = Polygon.size();
Rcpp::NumericMatrix mat( n, 2 );
R_xlen_t i;
for( i = 0; i < n; ++i ) {
std::array< T, 2 > pt = Polygon[ i ];
Rcpp::NumericVector nv = Rcpp::wrap( pt );
mat( i, Rcpp::_ ) = nv;
}
return mat;
}

template < typename T >
SEXP wrap( std::vector< std::vector< std::array< T, 2 > > >& Polygons ) {
R_xlen_t n = Polygons.size();
Rcpp::List lst( n );
R_xlen_t i;
for( i = 0; i < n; ++i ) {
std::vector< std::array< T, 2 > > polygon = Polygons[ i ];
lst[ i ] = Rcpp::wrap( polygon );
}
return lst;
}

namespace traits {

template < typename T > class Exporter< std::array< T, 2 > > {
typedef typename std::array< T, 2 > Point;

const static int RTYPE = Rcpp::traits::r_sexptype_traits< T >::rtype;
Rcpp::Vector< RTYPE > vec;

public:
Exporter( SEXP x ) : vec( x ) {
if( TYPEOF( x ) != RTYPE ) {
throw std::invalid_argument("decido - invalid R object for creating a Point");
}
}

Point get() {
if( vec.length() != 2 ) {
Rcpp::stop("decido - each point in the polygon must have exactly two coordinates");
}
Point x({ vec[0], vec[1] });
return x;
}

};

template < typename T > class Exporter< std::vector< std::array< T, 2 > > > {
typedef typename std::vector< std::array< T, 2 > > Polygon;

const static int RTYPE = Rcpp::traits::r_sexptype_traits< T >::rtype;
Rcpp::Matrix< RTYPE > mat;

public:
Exporter( SEXP x ) : mat( x ) {
if( TYPEOF( x ) != RTYPE ) {
throw std::invalid_argument("decido - invalid R object for creating a Polygon");
}
}

Polygon get() {
R_xlen_t n_row = mat.nrow();
Polygon x( n_row );
R_xlen_t i;
for( i = 0; i < n_row; ++i ) {
Rcpp::Vector< RTYPE > v = mat( i, Rcpp::_);
x[i] = Rcpp::as< std::array< T, 2 > >( v );
}
return x;
}
};

template< typename T > class Exporter< std::vector< std::vector< std::array< T, 2 > > > > {
typedef typename std::vector< std::vector< std::array< T, 2 > > > Polygons;

const static int RTYPE = Rcpp::traits::r_sexptype_traits< T >::rtype;
Rcpp::List lst;

public:
Exporter( SEXP x ) : lst( x ) { }
Polygons get() {
R_xlen_t n = lst.size();
Polygons x( n );
R_xlen_t i;
for( i = 0; i < n; ++i ) {
if( !Rf_isMatrix( lst[ i ] ) ) {
Rcpp::stop("decido - a list must only contain matrices");
}
Rcpp::Matrix< RTYPE > mat = lst[ i ];
x[i] = Rcpp::as< std::vector< std::array< T, 2 > > >( mat );
}
return x;
}
};

} // traits
} // Rcpp

typedef double Coord;
typedef std::array< Coord, 2 > Point;
typedef std::vector< Point > Polygon;
typedef std::vector< Polygon > Polygons;

namespace decido {
namespace api {

inline Rcpp::IntegerVector earcut(
Rcpp::NumericVector& x,
Rcpp::NumericVector& y,
IntegerVector& holes,
IntegerVector& numholes
) {
// The index type. Defaults to uint32_t, but you can also pass uint16_t if you know that your
// data won't have more than 65536 vertices.
using N = uint32_t;
Polygon poly;

int vcount = static_cast <int> (x.length());
Point pt;
Polygons polyrings;
// if (numholes.size())
// Rcout << "numholes[0]:" << numholes[0] << std::endl;
int hole_index = 0;
for (int ipoint = 0; ipoint < vcount; ipoint++) {
pt = {x[ipoint], y[ipoint]};

// don't add the point if we are starting a new ring
if (numholes.size() && numholes[0] > 0) {
if (hole_index < holes.size()) {
// throw std::runtime_error("bounds");
int ihole = holes[hole_index];
if (ipoint == ihole) {
// Rprintf("pushback poly %i\n", ipoint + 1);
polyrings.push_back(poly);
poly.clear();
hole_index++;
}
}
}
// now add the point
poly.push_back(pt);
}

// ensure we catch the last poly ring
polyrings.push_back(poly);

// Run tessellation
// Returns array of indices that refer to the vertices of the input polygon.
// Three subsequent indices form a triangle.
std::vector<N> indices = mapbox::earcut<N>(polyrings);
return Rcpp::wrap( indices );
}

inline Rcpp::IntegerVector earcut(
SEXP& polygon
) {
if( TYPEOF( polygon ) != VECSXP ) {
Rcpp::stop("decido - expecting a list of matrices");
}
Polygons polyrings = Rcpp::as< Polygons >( polygon );
std::vector< uint32_t > indices = mapbox::earcut< uint32_t >( polyrings );
return Rcpp::wrap( indices );
}

} // earcut
} // decido


#endif
1 change: 1 addition & 0 deletions src/earcut.h → inst/include/earcut.h
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,7 @@ void Earcut<N>::removeNode(Node* p) {

template <typename N = uint32_t, typename Polygon>
std::vector<N> earcut(const Polygon& poly) {

mapbox::detail::Earcut<N> earcut;
earcut(poly);
return std::move(earcut.indices);
Expand Down
1 change: 1 addition & 0 deletions src/Makevars
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
CXX_STD = CXX11
PKG_CXXFLAGS = -I../inst/include/
2 changes: 2 additions & 0 deletions src/Makevars.win
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CXX_STD = CXX11
PKG_CXXFLAGS = -I../inst/include/
24 changes: 23 additions & 1 deletion src/RcppExports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using namespace Rcpp;

// earcut_cpp
IntegerVector earcut_cpp(NumericVector x, NumericVector y, IntegerVector holes, IntegerVector numholes);
Rcpp::IntegerVector earcut_cpp(NumericVector x, NumericVector y, IntegerVector holes, IntegerVector numholes);
RcppExport SEXP _decido_earcut_cpp(SEXP xSEXP, SEXP ySEXP, SEXP holesSEXP, SEXP numholesSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Expand All @@ -19,3 +19,25 @@ BEGIN_RCPP
return rcpp_result_gen;
END_RCPP
}
// earcut_sfg
Rcpp::IntegerVector earcut_sfg(SEXP& sfg);
RcppExport SEXP _decido_earcut_sfg(SEXP sfgSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< SEXP& >::type sfg(sfgSEXP);
rcpp_result_gen = Rcpp::wrap(earcut_sfg(sfg));
return rcpp_result_gen;
END_RCPP
}

static const R_CallMethodDef CallEntries[] = {
{"_decido_earcut_cpp", (DL_FUNC) &_decido_earcut_cpp, 4},
{"_decido_earcut_sfg", (DL_FUNC) &_decido_earcut_sfg, 1},
{NULL, NULL, 0}
};

RcppExport void R_init_decido(DllInfo *dll) {
R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
R_useDynamicSymbols(dll, FALSE);
}
60 changes: 12 additions & 48 deletions src/decido.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,21 @@
using namespace Rcpp;
#include "earcut.h"

#include "decido/decido.hpp"

// [[Rcpp::export]]
IntegerVector earcut_cpp(NumericVector x, NumericVector y,
IntegerVector holes,
IntegerVector numholes) {
using Coord = double;
// The index type. Defaults to uint32_t, but you can also pass uint16_t if you know that your
// data won't have more than 65536 vertices.
using N = uint32_t;
// Create array
using Point = std::array<Coord, 2>;
using Polygon = std::vector<Point>;
Polygon poly;
using Polygons = std::vector<Polygon>;

int vcount = static_cast <int> (x.length());
Point pt;
Polygons polyrings;
// if (numholes.size())
// Rcout << "numholes[0]:" << numholes[0] << std::endl;
int hole_index = 0;
for (int ipoint = 0; ipoint < vcount; ipoint++) {
pt = {x[ipoint], y[ipoint]};
// don't add the point if we are starting a new ring
if (numholes.size() && numholes[0] > 0) {
if (hole_index < holes.size()) {
// throw std::runtime_error("bounds");
int ihole = holes[hole_index];
if (ipoint == ihole) {
// Rprintf("pushback poly %i\n", ipoint + 1);
polyrings.push_back(poly);
poly.clear();
hole_index++;
}
}
}
// now add the point
poly.push_back(pt);
}
Rcpp::IntegerVector earcut_cpp(
NumericVector x,
NumericVector y,
IntegerVector holes,
IntegerVector numholes
) {
return decido::api::earcut( x, y, holes, numholes );
}

// ensure we catch the last poly ring
polyrings.push_back(poly);
// Run tessellation
// Returns array of indices that refer to the vertices of the input polygon.
// Three subsequent indices form a triangle.
std::vector<N> indices = mapbox::earcut<N>(polyrings);

IntegerVector out(indices.size());
for (size_t j = 0; j < static_cast <size_t> (out.length()); j++){
out[static_cast <R_xlen_t> (j)] = static_cast <int> (indices[j]);
}
return out;
// [[Rcpp::export]]
Rcpp::IntegerVector earcut_sfg( SEXP& sfg ) {
return decido::api::earcut( sfg );
}

Loading