clipperlib — C ++ не может вернуть объект из функции

Я пытаюсь использовать C ++ «Clipper Library» (http://www.angusj.com/delphi/clipper.php), но когда я пытаюсь вернуть один из объектов из библиотеки клиперов из функции, он, кажется, становится нулевым или изменяется каким-либо образом

Вот функция, которую я написал. Единственные соответствующие строки должны быть последними 3.

ClipperLib::PolyTree MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles)
{
// Make all of the triangles CW
for (auto& triangle : triangles)
{
triangle.makeClockwise();
}
// Set up the Clipper
ClipperLib::Clipper clipper;
// To take a union, add all the paths as "subject" paths
for (auto& triangle : triangles)
{
ClipperLib::Path triContour(3);
triContour[0] = convertGLMToClipperPoint(triangle.getVertex(0));
triContour[1] = convertGLMToClipperPoint(triangle.getVertex(1));
triContour[2] = convertGLMToClipperPoint(triangle.getVertex(2));
clipper.AddPath(triContour, ClipperLib::PolyType::ptSubject, true);
}
// Now get the PolyTree representing the contours
ClipperLib::PolyTree tree;
clipper.Execute(ClipperLib::ClipType::ctUnion, tree);
return tree;
}

Когда я вызываю clipper.execute, он записывает в древовидную структуру некоторую информацию о контуре. Он пишет правильную информацию, и я проверил, что это правильно. Однако, когда я возвращаю дерево, оно, кажется, ничего не копирует, и PolyTree, полученное из этой функции, пусто.

Я уверен, что с библиотекой все в порядке, и я просто делаю здесь ошибку для начинающего c ++. Надеюсь, у кого-то есть представление о том, что это может быть.

Спасибо!

редактировать: для справки, вот страница документации для политре (http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/PolyTree/_Body.htm)

редактировать: я думал, что библиотека Clipper не с открытым исходным кодом, но это так. Вот код

typedef std::vector< IntPoint > Path;
typedef std::vector< Path > Paths;
class PolyNode;
typedef std::vector< PolyNode* > PolyNodes;

class PolyNode
{
public:
PolyNode();
Path Contour;
PolyNodes Childs;
PolyNode* Parent;
PolyNode* GetNext() const;
bool IsHole() const;
bool IsOpen() const;
int ChildCount() const;
private:
unsigned Index; //node index in Parent.Childs
bool m_IsOpen;
JoinType m_jointype;
EndType m_endtype;
PolyNode* GetNextSiblingUp() const;
void AddChild(PolyNode& child);
friend class Clipper; //to access Index
friend class ClipperOffset;
};

class PolyTree: public PolyNode
{
public:
~PolyTree(){Clear();};
PolyNode* GetFirst() const;
void Clear();
int Total() const;
private:
PolyNodes AllNodes;
friend class Clipper; //to access AllNodes
};

1

Решение

Предполагая, что вы не хотите изменять (очевидно, плохо спроектированную) библиотеку Clipper, вы можете сделать это так, как я предложил в своем комментарии:

// Make sure to have this at the top of your header file:
#include <memory>

std::unique_ptr<ClipperLib::PolyTree> MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles)
{
// Rest of your code...

std::unique_ptr<ClipperLib::PolyTree> tree(new ClipperLib::PolyTree);
clipper.Execute(ClipperLib::ClipType::ctUnion, *tree);
return tree;
}

Затем при вызове вашей функции:

std::unique_ptr<ClipperLib::PolyTree> tree(yourMeshHandler.trianglesToPolyTreeUnion(/*...*/);

// make use of tree...

Тем не менее, я бы предложил открыть тикет (если есть трекер ошибок) или связаться с автором библиотеки по этому вопросу.

2

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

Прежде чем что-либо делать, убедитесь, что следующая программа работает правильно:

int main()
{
PolyTree p1;
// fill PolyTree with some values that make sense (please add code to do this)
//...
PolyTree p2 = p1;
PolyTree p3;
p3 = p1;
}

Это в основном то, что мы хотим проверить. Если вы можете заставить этот код работать (добавьте соответствующие заголовки и необходимые инициализации), тогда вы можете вернуться к функции. Если приведенный выше код не работает, то есть ваш ответ.

Вы должны получить приведенный выше код для получения правильной семантики копирования, и даже просто важно, что при выходе из main () не происходит повреждения памяти при уничтожении p1, p2 и p3.

Так что либо вы можете исправить класс для безопасного копирования, либо забыть об этом и жить с классом, с которым вам нужно обращаться очень осторожно и в ограниченных ситуациях (то есть вы не можете надежно вернуть его копии, как делаете сейчас).

3

Для записи и объединения всех ответов в длительной дискуссии на вопрос.
Проблемы:

  1. Возвращаемое значение является локальной переменной, которая выходит из области видимости. Это вызывает деструктор PolyTree
  2. PolyTree содержит вектор указателей PolyNode *. Они выделяются при вызове clipper.Execute ().
  3. Однако PolyTree :: Clear () действительно удаляет узлы … и Clear () вызывается деструктором.
  4. Таким образом, внутри функции содержимое корректно (выделяется Execute ()), когда передается наружу, в отсутствие конструкторов копирования и operator=, деструктор локальной переменной вызывается и узлы очищаются, результат, полученный вне функции, пуст.

Код для PolyTree :: Clear ()

void PolyTree::Clear()
{
for (PolyNodes::size_type i = 0; i < AllNodes.size(); ++i)
delete AllNodes[i];
AllNodes.resize(0);
Childs.resize(0);
}

Вероятно, вы должны следовать шаблону Execute и определить свою функцию как:

void MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles,ClipperLib::PolyTree &tree)
3

Ваша проблема в третьей строке снизу треугольников ToPolyTreeUnion. Дерево, которое вы создаете, создается в стеке и находится только в области действия внутри функции.

Вы должны динамически распределять память и возвращать указатель на дерево или делать объект вашего дерева членом класса, чтобы он оставался в области видимости после возврата из функции.

-1