Получение координат точек из многоугольника Boost Geometry
у меня есть простая DLL, выполняющая некоторые вычисления с полигонами геометрии Boost. (В основном, пересечения и различия.) Поскольку DLL, скорее всего, будет вызвана из кода C#, а также из Delphi и кто знает, откуда еще, я должен преобразовать результат в массивы, с которыми все может справиться.
обновление:
Я упростил и несколько исправил свой код. Новый код выглядит совершенно иначе, использует совершенно другой подход (for_each_point
), и как-то еще не компилируется.
мой новый код:
#include <vector>
#include <boost/range.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/polygon.hpp>
using namespace boost::geometry;
typedef boost::geometry::model::point
<
double, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree>
> spherical_point;
class PointAggregator {
private :
double *x, *y;
int count;
public :
PointAggregator(int size) {
x = (double*) malloc(sizeof(double) * size);
y = (double*) malloc(sizeof(double) * size);
count = 0;
}
~PointAggregator() {
free(x);
free(y);
}
inline void operator()(spherical_point& p) {
x[count] = get<0>(p);
y[count] = get<1>(p);
count++;
}
void GetResult(double *resultX, double *resultY) {
resultX = x;
resultY = y;
}
};
void VectorToArray(std::vector<model::polygon<spherical_point>> resultVector, double x[], double y[], int *count) {
int i = 0;
for (std::vector<model::polygon<spherical_point>>::iterator it = resultVector.begin(); it != resultVector.end(); ++it) {
if (boost::size(*it) >= 2) {
*count = boost::size(*it);
PointAggregator* pa = new PointAggregator(*count);
boost::geometry::for_each_point(*it, *pa);
pa->GetResult(x, y);
delete(pa);
break;
}
}
}
текущие ошибки компиляции:
- ошибка C2039:' type': не является членом итератора' boost:: mpl:: eval_if_c'.ГЭС 63
- ошибка C3203: "тип": шаблон неспециализированного класса не может использоваться в качестве аргумента шаблона для параметра шаблона "итератор", ожидается реальный тип difference_type.ГЭС 25
- ошибка C2955: 'boost:: type': Использование шаблона класса требует шаблона список аргументов difference_type.ГЭС 25
- ошибка C2955:' boost:: iterator_difference': для использования шаблона класса требуется список аргументов шаблона difference_type.ГЭС 26
какие из них не выглядят так, как будто они имеют какое-либо отношение к этой части кода (мое имя файла-геометрия.cpp), но все остальное, что использует геометрию Boost, комментируется, и я все еще получаю эти ошибки, поэтому...
вот мой плохой код, который я имел ранее (отредактировано sehe)
(Я новичок в C++ и Boost, поэтому я, возможно, пропустил некоторую базовую концепцию, собирая код из интернета.) Я предполагаю, что я просто не могу перебирать многоугольник, который легко и я пропустил нетривиальную часть, или что многоугольник нельзя использовать в качестве кольца, или итерации просто не так, как я думал, или я понятия не имею, что еще может быть неправильно. Что я сделал не так?
2 ответов
Я нашел несколько вещей, которые нужно исправить:
- одна проблема, которую я вижу в ваших шаблонах. Обязательно поставьте пробелы!
- boost range работает на контейнерах или диапазонах, которые держат begin, end pairs
- итераторы представляют собой что-то вроде указателя на объект. Получение размер итератора не будет делать то, что вы хотите. Вам нужно либо использовать boost::size всего контейнера, либо std:: distance(begin_iterator,end_iterator).
здесь это версия, которая компилирует:
#include <vector>
#include <boost/range.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/polygon.hpp>
using namespace boost::geometry;
typedef boost::geometry::model::point
<
double, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree>
> spherical_point;
class PointAggregator {
private :
double *x, *y;
int count;
public :
PointAggregator(int size) {
x = (double*) malloc(sizeof(double) * size);
y = (double*) malloc(sizeof(double) * size);
count = 0;
}
~PointAggregator() {
free(x);
free(y);
}
inline void operator()(spherical_point& p) {
x[count] = get<0>(p);
y[count] = get<1>(p);
count++;
}
void GetResult(double *resultX, double *resultY) {
resultX = x;
resultY = y;
}
};
// added spaces to the close brackets >> becomes > >
void VectorToArray(std::vector<model::polygon<spherical_point> > resultVector, double x[], double y[], int *count) {
for (std::vector<model::polygon<spherical_point> >::iterator it = resultVector.begin(); it != resultVector.end(); ++it) {
if (boost::size(resultVector) >= 2) {
// getting the size of the whole container
*count = boost::size(resultVector);
PointAggregator* pa = new PointAggregator(*count);
boost::geometry::for_each_point(*it, *pa);
pa->GetResult(x, y);
delete(pa);
break;
}
}
}
хорошо, я думаю, что у меня есть то, что вы ищете здесь. Я все еще не совсем понимаю, почему вы ищете этот диапазон того, что я предполагаю, больше или равно 2, но я понял, как заставить его компилироваться при использовании boost::size() по крайней мере.
во-первых, поймите, что первый параметр функции
void VectorToArray(std::vector<model::polygon<spherical_point> > resultVector, double x[], double y[], int *count)
{
...
}
- это std:: vector, содержащий экземпляры типа model:: polygon.
это означает, что при разыменовании итератора ...определяется как
std::vector<model::polygon<spherical_point> >::iterator it
rvalue является моделью:: polygon.
boost::model:: polygon сам по себе не является Boost.Диапазон совместим. boost::model:: polygon-это тип, содержащий 5 функций-членов ....
inline ring_type const& outer() const { return m_outer; }
inline inner_container_type const& inners() const { return m_inners; }
inline ring_type& outer() { return m_outer; }
inline inner_container_type & inners() { return m_inners; }
inline void clear()
{
m_outer.clear();
m_inners.clear();
}
это означает, что ваш *it (т. е. model::polygon) ограничен вызовом только этих функций.
похоже, что вы хотите сделать, это захватить либо внешнее кольцо, либо одно из внутренних колец каждого многоугольника в векторе (не уверен, что , внутренний или внешний), и посмотреть, если диапазон того, что в этом кольце больше или равно 2.
чтобы сделать это, мы должны сделать еще несколько mpl и typedef.
typedef boost::geometry::model::point<double, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > spherical_point; // your definition of a spherical_point
typedef boost::geometry::model::polygon<spherical_point> polygon; //consolidation of template args for a polygon
typedef boost::geometry::ring_type<polygon>::type ring_type; // define a ring_type that can handle your spherical_point by way of the polygon typedef.
typedef boost::geometry::interior_type<polygon>::type int_type; //define a interior_type that can handle your spherical_point
чтобы завершить это и просто и заставить его "работать", я решил предположить, что вы хотите" внешнее " кольцо для условного предела диапазона.
вот, ко мне, компиляция кода, на gcc 4.1.1 с boost 1.48. Я оставляю вопрос о том, правильна ли логика, на усмотрение кого-то другого.
using namespace boost::geometry;
typedef boost::geometry::model::point<double, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > spherical_point;
typedef boost::geometry::model::polygon<spherical_point> polygon;
typedef boost::geometry::ring_type<polygon>::type ring_type;
typedef boost::geometry::interior_type<polygon>::type int_type;
class PointAggregator
{
private :
double *x, *y;
int count;
public :
PointAggregator(int size)
{
x = (double*) malloc(sizeof(double) * size);
y = (double*) malloc(sizeof(double) * size);
count = 0;
}
~PointAggregator()
{
free(x);
free(y);
}
inline void operator()(spherical_point& p)
{
x[count] = get<0>(p);
y[count] = get<1>(p);
count++;
}
void GetResult(double *resultX, double *resultY)
{
resultX = x;
resultY = y;
}
};
void VectorToArray(std::vector<model::polygon<spherical_point> > resultVector, double x[], double y[], int *count)
{
for (std::vector<model::polygon<spherical_point> >::iterator it = resultVector.begin(); it != resultVector.end(); ++it)
{
model::polygon<spherical_point> tmpPoly;
tmpPoly = (*it);
boost::geometry::ring_type<polygon>::type somering = tmpPoly.outer(); //typed it all out again instead of using ring_type since the complier was complaining and i didn't wanna get into it.
int ringsize = boost::size(somering);
if(ringsize >= 2)
{
*count = ringsize;
PointAggregator* pa = new PointAggregator(*count);
boost::geometry::for_each_point(*it, *pa);
pa->GetResult(x, y);
delete(pa);
break;
}
}
}