Получение координат точек из многоугольника Boost Geometry - PullRequest
9 голосов
/ 11 октября 2011

У меня есть простая DLL, выполняющая некоторые вычисления с полигонами Boost Geometry. (В основном пересечения и различия.) Поскольку DLL, скорее всего, будет вызываться из кода C #, а также из Delphi и кто знает откуда, я должен преобразовать результат в массивы, с которыми может справиться все.

UPDATE: Я упростил и несколько исправил свой код. Новый код выглядит совершенно по-другому, использует совершенно другой подход (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;
        }       
    }
}

Текущие ошибки компиляции:

  1. ошибка C2039: «тип»: не является членом «boost :: mpl :: eval_if_c» iterator.hpp 63
  2. ошибка C3203: «тип»: шаблон неспециализированного класса не может использоваться в качестве аргумента шаблона для параметра шаблона «Итератор», ожидается реальный тип diff_type.hpp 25
  3. ошибка C2955: 'boost :: type': использование шаблона класса требует списка аргументов шаблона diff_type.hpp 25
  4. ошибка C2955: 'boost :: iterator_difference': использование шаблона класса требует списка аргументов шаблона diff_type.hpp 26

Какие из них не имеют отношения к этой части кода (мое имя файла - geometry.cpp), но все остальное, использующее Boost Geometry, закомментировано, и я все еще получаю эти ошибки, так что ...

Вот мой плохой код, который у меня был ранее (отредактированный sehe)

(Я новичок в C ++ и Boost, поэтому, возможно, пропустил некоторую базовую концепцию, когда собирал код из Интернета.) Я предполагаю, что я просто не могу перебрать многоугольник, который легко пропустил, и я пропустил нетривиальную часть, или что многоугольник нельзя использовать в качестве кольца, или итерации просто не такие, как я думал, или у меня нет Идея, что еще может быть не так. Что я сделал не так?

Ответы [ 2 ]

5 голосов
/ 13 октября 2011

Хорошо, я думаю, у меня есть то, что вы ищете здесь.Я до сих пор не совсем понимаю, почему вы ищете этот диапазон, который, как я предполагаю, равен точкам, большим или равным 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

, значение является моделью :: многоугольника.

boost :: model :: polygon НЕ является само по себе Boost.Rangeсовместимы.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 (то есть, модель :: 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;
      }
    }
}
4 голосов
/ 13 октября 2011

Я нашел несколько вещей, которые нужно исправить:

  1. Одна проблема, которую я вижу, в ваших шаблонах.Обязательно ставьте пробелы!
  2. Boost range работает с контейнерами или диапазонами, которые содержат начало, конечные пары
  3. Итераторы представляют собой нечто вроде указателя на объект.Получение размера итератора не будет делать то, что вы хотите.Вам нужно использовать 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;
        }       
    }
}
...