我是新手,以提升和“沉重”的模板。我已经玩了几天,并试图将数组传递给惊人的boost::geometry::convex_hull函数。没有运气。
我准备了以下示例:
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/adapted/boost_tuple.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <iostream>
using namespace std;
namespace bg = boost::geometry;
BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
int main()
{
typedef boost::tuple<float, float> point;
typedef bg::model::polygon<point> polygon;
polygon poly, hull;
// define rectangle, this will become also our convex hull
bg::append( poly, point( 0.0, 0.0 ) );
bg::append( poly, point( 1.0, 0.0 ) );
bg::append( poly, point( 1.0, 1.0 ) );
// bg::append( poly, point( 2.0, 2.0 ) );
bg::append( poly, point( 1.0, 0.0 ) );
// mid point, which should not be part of the hull
bg::append( poly, point( 0.5, 0.5 ) );
// The above poly would ideally constructed with:
// float myInputData[] = { 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 2.0, 2.0, 1.0, 0.0 };
// and then used like: bg::convex_hull( myInputData, hull );
bg::convex_hull( poly, hull );
cout << "convex hull is:\n";
vector<boost::tuples::tuple<float, float> >::iterator it;
for( it = hull.outer().begin(); it != hull.outer().end(); ++it )
cout << "(" << bg::get<0>(*it) << "/" << bg::get<1>(*it) << ")\n";
}
附加bg :: append的点应该是一个简单的c数组,如:
float mydataArray[ 20 ];
其中数据布局的格式为[x1,y1,x2,y2 ...] 所以理想的函数是:bg :: append_points(arrayOfAlternating_X_Y_coordinates)
我还想将结果(hull)作为数组指针传递给OpenGL,而不是迭代并通过float读出浮点数(因此,目标是:摆脱bg :: get&lt; 0&gt;(* it ))。
结果也应该来自[x1,y1,x2,y2 ...]
我有种感觉,这种提升并不能提供我想要的功能。那么,我摆脱循环的想法有什么问题吗?我如何编写一个可以被bg :: convex_hull函数使用的智能访问类?
答案 0 :(得分:1)
除the other answer中显示的polygon<>
模型的机制外,您可以将polygon<>
替换为ring<>
模型,因为似乎没有内环涉及?
这样,你可以直接初始化到你的戒指中:
typedef bg::model::ring<point> ring;
ring poly {
{ 0.0, 0.0 },
//{ 0.5, 0.5 }, // mid point, which should not be part of the hull
{ 1.0, 0.0 },
{ 1.0, 1.0 },
{ 2.0, 2.0 },
{ 1.0, 0.0 },
};
API调用可以是:
point const* hull_array_ptr = &hull.front();
call_API(hull_array_ptr, hull.size());
<强> Live On Coliru 强>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/ring.hpp>
#include <boost/geometry/io/io.hpp>
#include <boost/geometry/geometries/adapted/boost_tuple.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <iostream>
using namespace std;
namespace bg = boost::geometry;
BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
typedef boost::tuple<float, float> point;
void dump(point const& p) { cout << get<0>(p) << " " << get<1>(p) << ","; }
void call_API(point const* arr, size_t n) {
cout << "hull (API):";
for_each(arr, arr+n, dump);
cout << "\n";
}
int main()
{
typedef bg::model::ring<point> ring;
ring poly {
{ 0.0, 0.0 },
//{ 0.5, 0.5 }, // mid point, which should not be part of the hull
{ 1.0, 0.0 },
{ 1.0, 1.0 },
{ 2.0, 2.0 },
{ 1.0, 0.0 },
};
cout << "raw: " << bg::wkt(poly) << "\n";
bg::correct(poly);
cout << "corrected: " << bg::wkt(poly) << "\n";
ring hull;
bg::convex_hull(poly, hull);
cout << "hull: " << bg::wkt(hull) << "\n";
point const* hull_array_ptr = &hull.front();
call_API(hull_array_ptr, hull.size());
}
再次打印:
raw: POLYGON((0 0,1 0,1 1,2 2,1 0))
corrected: POLYGON((0 0,1 0,1 1,2 2,1 0,0 0))
hull: POLYGON((0 0,2 2,1 0,0 0))
hull (API):0 0,2 2,1 0,0 0,
答案 1 :(得分:1)
好的,第三次是魅力,对吧
OP:感谢您的努力,但这不是您想要的解决方案。我澄清了这个问题。目标是为输入和输出提供一个扁平的c型浮子阵列。打印出来的数据应该是这样的:
float[]
我: 花车意味着什么?
OP:交替的x和y坐标,[...]
如果你做了必要的事情
您可以在原始template<typename T> using compact_point = boost::tuple<T, T>;
template<typename T> using compact_ring = boost::iterator_range<T*>;
static_assert(sizeof(compact_point<float>) == 2*sizeof(float), "");
static_assert(alignof(compact_point<float>) >= alignof(float), "");
BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
BOOST_GEOMETRY_REGISTER_RING_TEMPLATED(compact_ring)
using point = compact_point<float>;
using ring = compact_ring<point>;
上创建一个环形作为一系列类型惩罚点:
template <typename T, size_t N>
compact_ring<compact_point<T> > as_compact_ring(T (&arr)[N]) {
auto f = reinterpret_cast<point*>(+arr);
return { f, f + N/2 };
}
template <typename T>
boost::iterator_range<T const*> as_compact_points(std::vector<compact_point<T> > const& r) {
auto f = reinterpret_cast<T const*>(&r[0]);
return { f, f + r.size()*2 };
}
注意请注意,这仅适用于只读环
int main() {
alignas(compact_point<float>) float ringdata[] {
0.0, 0.0, // clockwise rect
0.0, 2.0,
//
1.0, 1.0, // dent...
//
2.0, 2.0,
2.0, 0.0,
0.0, 0.0,
};
ring poly = as_compact_ring(ringdata);
cout << "raw: " << bg::wkt(poly) << "\n";
std::string reason;
if (!bg::is_valid(poly, reason)) {
std::cout << "NOT VALID: " << reason << "\n";
return 255;
}
bg::model::ring<point> hull; // not a range proxy though
bg::convex_hull(poly, hull);
cout << "hull:" << bg::wkt(hull) << "\n";
// force back:
auto view = as_compact_points(hull);
float const* rawhull = &*view.begin();
call_API(rawhull, 2*hull.size());
}
你去了,你现在可以申请:
raw: POLYGON((0 0,0 2,1 1,2 2,2 0,0 0))
hull:POLYGON((0 0,0 2,2 2,2 0,0 0))
hull (API):0 0 0 2 2 2 2 0 0 0
打印
class ThisFails {
func foo() -> PA {
return X().test() // error: generic parameter 'U' could not be inferred
}
}
X().test() as PA // error: generic parameter 'U' could not be inferred
答案 2 :(得分:0)
问。附加bg :: append的点应该在一个数组中,这样理想的函数就是:
bg::append_points(arrayOf_X_Y_coordinates)
您可以一次指定多边形的外环:
point raw[] = {
{ 0.0, 0.0 },
//{ 0.5, 0.5 }, // mid point, which should not be part of the hull
{ 1.0, 0.0 },
{ 1.0, 1.0 },
// { 2.0, 2.0 },
{ 1.0, 0.0 },
};
// define rectangle, this will become also our convex hull
poly.outer().assign(begin(raw), end(raw));
Q。我还希望将结果(hull)作为数组指针传递给OpenGL,而不是迭代并通过float读取坐标float(使用bg :: get&lt; 0&gt;(*它))。
您可以传递初始矢量元素的地址:
point const* hull_array_ptr = &hull.outer().front();
call_API(hull_array_ptr, hull.outer().size());
注意确保您的多边形有效,满足convex_hull
算法的前提条件! correct
在此处执行必要的修复:
<强> Live On Coliru 强>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/io/io.hpp>
#include <boost/geometry/geometries/adapted/boost_tuple.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <iostream>
using namespace std;
namespace bg = boost::geometry;
BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
typedef boost::tuple<float, float> point;
void dump(point const& p) { cout << get<0>(p) << " " << get<1>(p) << ","; }
void call_API(point const* arr, size_t n) {
cout << "hull (API):";
for_each(arr, arr+n, dump);
cout << "\n";
}
int main()
{
typedef bg::model::polygon<point> polygon;
polygon poly, hull;
point raw[] = {
{ 0.0, 0.0 },
//{ 0.5, 0.5 }, // mid point, which should not be part of the hull
{ 1.0, 0.0 },
{ 1.0, 1.0 },
{ 2.0, 2.0 },
{ 1.0, 0.0 },
};
poly.outer().assign(begin(raw), end(raw));
cout << "raw: " << bg::wkt(poly) << "\n";
bg::correct(poly);
cout << "corrected: " << bg::wkt(poly) << "\n";
bg::convex_hull(poly, hull);
cout << "hull: " << bg::wkt(hull) << "\n";
point const* hull_array_ptr = &hull.outer().front();
call_API(hull_array_ptr, hull.outer().size());
}
输出:
raw: POLYGON((0 0,1 0,1 1,2 2,1 0,0 0))
corrected: POLYGON((0 0,1 0,1 1,2 2,1 0,0 0))
hull: POLYGON((0 0,2 2,1 0,0 0))
hull (API):0 0,2 2,1 0,0 0,