Преобразование Rcpp NumericMatrix для использования с Boost Geometry

Я обнаружил, что я потерялся без хорошего <as> а также <wrap> команды, которые Rcpp и связанные с ними пакеты обеспечивают для преобразования между различными типами объектов.

У меня есть матрица точек, для которых строки представляют точки в двумерном декартовом пространстве:

 pointsMatrix <- matrix(runif(100,-1,1),50,50)

Затем я хочу использовать Алгоритм выпуклый_халл от геометрии наддува найти выпуклую оболочку из точек.

Однако я не уверен, как конвертировать NumericMatrix в один из типов данных, которые convex_hull понимает. Кроме того, я не уверен, как преобразовать выходные данные Boost Geometry во что-то, что Rcpp может передать обратно R.

 #include <Rcpp.h>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/polygon.hpp>
using namespace Rcpp;

BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)

// [[Rcpp::export]]
NumericMatrix convexHullRcpp(NumericMatrix pointsMatrix){

typedef boost::tuple<double, double> point;
typedef boost::geometry::model::polygon<point> polygon;

// Some sort of conversion of pointsMatrix here to pointsMatrixBG//

polygon hull;
boost::geometry::convex_hull(pointsMatrixBG, hull);

//Now to convert hull into something that Rcpp can hand back to R.//

return hullToR;
}

Похоже, boost.tuple может быть лучшим выбором

1

Решение

Вот небольшой файл test.cpp

#include <Rcpp.h>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/point_xy.hpp>

using namespace Rcpp;

typedef boost::geometry::model::d2::point_xy<double, boost::geometry::cs::cartesian> Point;
typedef boost::geometry::model::polygon<Point, true, true> Polygon;

namespace Rcpp {
template <> Polygon as(SEXP pointsMatrixSEXP) {
NumericMatrix pointsMatrix(pointsMatrixSEXP);
Polygon pointsMatrixBG;
for (int i = 0; i < pointsMatrix.nrow(); ++i) {
double x = pointsMatrix(i,0);
double y = pointsMatrix(i,1);
Point p(x,y);
pointsMatrixBG.outer().push_back(p);
}
return (pointsMatrixBG);
}

template <> SEXP wrap(const Polygon& poly) {
const std::vector<Point>& points = poly.outer();
NumericMatrix rmat(points.size(), 2);
for(int i = 0; i < points.size(); ++i) {
const Point& p = points[i];
rmat(i,0) = p.x();
rmat(i,1) = p.y();
}
return Rcpp::wrap(rmat);
}
}

// [[Rcpp::export]]
NumericMatrix convexHullRcpp(SEXP pointsMatrixSEXP){

// Conversion of pointsMatrix here to pointsMatrixBG
Polygon pointsMatrixBG = as<Polygon>(pointsMatrixSEXP);

Polygon hull;
boost::geometry::convex_hull(pointsMatrixBG, hull);

//Now to convert hull into something that Rcpp can hand back to R.//
return wrap(hull);
}

Тогда вы можете проверить это в R.

library(Rcpp)
sourceCpp("test.cpp")
points <- c(2.0, 1.3, 2.4, 1.7, 2.8, 1.8, 3.4, 1.2, 3.7, 1.6,3.4, 2.0, 4.1, 3.0, 5.3, 2.6, 5.4, 1.2, 4.9, 0.8, 2.9, 0.7,2.0, 1.3)
points.matrix <- matrix(points, ncol=2, byrow=TRUE)
> convexHullRcpp(points.matrix)
[,1] [,2]
[1,]  2.0  1.3
[2,]  2.4  1.7
[3,]  4.1  3.0
[4,]  5.3  2.6
[5,]  5.4  1.2
[6,]  4.9  0.8
[7,]  2.9  0.7
[8,]  2.0  1.3
5

Другие решения

В общем, как только вы переходите к типам, не известным R, вам нужно создавать свои собственные функции конвертера. as<>() а также wrap(),

Как отмечается в комментарии, этому посвящена целая виньетка. Есть также примеры в пакетах, а также, например, эта статья в Rcpp Gallery о таможне as<>() а также wrap(), Я бы начал с примеров Boost Geometry в C ++, чтобы понять, как заполняются их структуры данных, а затем заполнил их из моего C ++. Там нет ярлыка. Нет бесплатного обеда Теорема все еще верна.

0