Я пытаюсь использовать 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
};
Предполагая, что вы не хотите изменять (очевидно, плохо спроектированную) библиотеку 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...
Тем не менее, я бы предложил открыть тикет (если есть трекер ошибок) или связаться с автором библиотеки по этому вопросу.
Прежде чем что-либо делать, убедитесь, что следующая программа работает правильно:
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.
Так что либо вы можете исправить класс для безопасного копирования, либо забыть об этом и жить с классом, с которым вам нужно обращаться очень осторожно и в ограниченных ситуациях (то есть вы не можете надежно вернуть его копии, как делаете сейчас).
Для записи и объединения всех ответов в длительной дискуссии на вопрос.
Проблемы:
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)
Ваша проблема в третьей строке снизу треугольников ToPolyTreeUnion. Дерево, которое вы создаете, создается в стеке и находится только в области действия внутри функции.
Вы должны динамически распределять память и возвращать указатель на дерево или делать объект вашего дерева членом класса, чтобы он оставался в области видимости после возврата из функции.