libarea: fixed memory leak in CAreaOrderer

This commit is contained in:
Zheng, Lei 2017-01-20 18:32:30 +08:00
parent 2c249e8356
commit 298ad1eb26
3 changed files with 41 additions and 62 deletions

View File

@ -92,33 +92,22 @@ void CArea::Reorder()
// returns 1, if the curves are overlapping // returns 1, if the curves are overlapping
CAreaOrderer ao; CAreaOrderer ao;
std::list<CCurve>::iterator ItLast = m_curves.end(); for(std::list<CCurve>::iterator It = m_curves.begin(), ItNext=It; It != m_curves.end(); It=ItNext)
for(std::list<CCurve>::iterator It = m_curves.begin(); It != m_curves.end(); ++It)
{ {
++ItNext;
CCurve& curve = *It; CCurve& curve = *It;
if(!It->IsClosed()) if(!It->IsClosed())
continue; continue;
ItLast = It; ao.Insert(make_shared<CCurve>(curve));
ao.Insert(&curve);
if(m_set_processing_length_in_split) if(m_set_processing_length_in_split)
{ {
CArea::m_processing_done += (m_split_processing_length / m_curves.size()); CArea::m_processing_done += (m_split_processing_length / m_curves.size());
} }
m_curves.erase(It);
} }
if(ItLast == m_curves.end())
return;
if(ao.m_top_level) if(ao.m_top_level)
ao.m_top_level->GetArea(*this); ao.m_top_level->GetArea(*this);
++ItLast;
for(std::list<CCurve>::iterator It=m_curves.begin(), ItNext=It; It!=ItLast; It=ItNext)
{
++ItNext;
if(It->IsClosed())
m_curves.erase(It);
}
} }
class ZigZag class ZigZag

View File

@ -30,29 +30,27 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "AreaOrderer.h" #include "AreaOrderer.h"
#include "Area.h" #include "Area.h"
using namespace std;
CAreaOrderer* CInnerCurves::area_orderer = NULL; CAreaOrderer* CInnerCurves::area_orderer = NULL;
CInnerCurves::CInnerCurves(CInnerCurves* pOuter, const CCurve* curve) CInnerCurves::CInnerCurves(shared_ptr<CInnerCurves> pOuter, shared_ptr<CCurve> curve)
:m_pOuter(pOuter)
,m_curve(curve)
{ {
m_pOuter = pOuter;
m_curve = curve;
m_unite_area = NULL;
} }
CInnerCurves::~CInnerCurves() CInnerCurves::~CInnerCurves()
{ {
delete m_unite_area;
} }
void CInnerCurves::Insert(const CCurve* pcurve) void CInnerCurves::Insert(shared_ptr<CCurve> pcurve)
{ {
std::list<CInnerCurves*> outside_of_these; std::list<shared_ptr<CInnerCurves> > outside_of_these;
std::list<CInnerCurves*> crossing_these; std::list<shared_ptr<CInnerCurves> > crossing_these;
// check all inner curves // check all inner curves
for(std::set<CInnerCurves*>::iterator It = m_inner_curves.begin(); It != m_inner_curves.end(); It++) for(shared_ptr<CInnerCurves> c : m_inner_curves) {
{
CInnerCurves* c = *It;
switch(GetOverlapType(*pcurve, *(c->m_curve))) switch(GetOverlapType(*pcurve, *(c->m_curve)))
{ {
@ -75,28 +73,24 @@ void CInnerCurves::Insert(const CCurve* pcurve)
} }
// add as a new inner // add as a new inner
CInnerCurves* new_item = new CInnerCurves(this, pcurve); shared_ptr<CInnerCurves> new_item(new CInnerCurves(shared_from_this(), pcurve));
this->m_inner_curves.insert(new_item); this->m_inner_curves.insert(new_item);
for(std::list<CInnerCurves*>::iterator It = outside_of_these.begin(); It != outside_of_these.end(); It++) for(shared_ptr<CInnerCurves> c : outside_of_these) {
{
// move items // move items
CInnerCurves* c = *It;
c->m_pOuter = new_item; c->m_pOuter = new_item;
new_item->m_inner_curves.insert(c); new_item->m_inner_curves.insert(c);
this->m_inner_curves.erase(c); this->m_inner_curves.erase(c);
} }
for(std::list<CInnerCurves*>::iterator It = crossing_these.begin(); It != crossing_these.end(); It++) for(shared_ptr<CInnerCurves> c : crossing_these) {
{
// unite these // unite these
CInnerCurves* c = *It;
new_item->Unite(c); new_item->Unite(c);
this->m_inner_curves.erase(c); this->m_inner_curves.erase(c);
} }
} }
void CInnerCurves::GetArea(CArea &area, bool outside, bool use_curve)const void CInnerCurves::GetArea(CArea &area, bool outside, bool use_curve)
{ {
if(use_curve && m_curve) if(use_curve && m_curve)
{ {
@ -104,11 +98,9 @@ void CInnerCurves::GetArea(CArea &area, bool outside, bool use_curve)const
outside = !outside; outside = !outside;
} }
std::list<const CInnerCurves*> do_after; std::list<shared_ptr<CInnerCurves> > do_after;
for(std::set<CInnerCurves*>::const_iterator It = m_inner_curves.begin(); It != m_inner_curves.end(); It++) for(shared_ptr<CInnerCurves> c: m_inner_curves) {
{
const CInnerCurves* c = *It;
area.m_curves.push_back(*c->m_curve); area.m_curves.push_back(*c->m_curve);
if(!outside)area.m_curves.back().Reverse(); if(!outside)area.m_curves.back().Reverse();
@ -116,19 +108,15 @@ void CInnerCurves::GetArea(CArea &area, bool outside, bool use_curve)const
else do_after.push_back(c); else do_after.push_back(c);
} }
for(std::list<const CInnerCurves*>::iterator It = do_after.begin(); It != do_after.end(); It++) for(shared_ptr<CInnerCurves> c : do_after)
{
const CInnerCurves* c = *It;
c->GetArea(area, !outside, false); c->GetArea(area, !outside, false);
}
} }
void CInnerCurves::Unite(const CInnerCurves* c) void CInnerCurves::Unite(shared_ptr<CInnerCurves> c)
{ {
// unite all the curves in c, with this one // unite all the curves in c, with this one
CArea* new_area = new CArea(); shared_ptr<CArea> new_area(new CArea());
new_area->m_curves.push_back(*m_curve); new_area->m_curves.push_back(*m_curve);
delete m_unite_area;
m_unite_area = new_area; m_unite_area = new_area;
CArea a2; CArea a2;
@ -140,21 +128,21 @@ void CInnerCurves::Unite(const CInnerCurves* c)
{ {
CCurve &curve = *It; CCurve &curve = *It;
if(It == m_unite_area->m_curves.begin()) if(It == m_unite_area->m_curves.begin())
m_curve = &curve; m_curve = make_shared<CCurve>(curve);
else else
{ {
if(curve.IsClockwise())curve.Reverse(); if(curve.IsClockwise())curve.Reverse();
Insert(&curve); Insert(shared_ptr<CCurve>(new CCurve(curve)));
} }
} }
} }
CAreaOrderer::CAreaOrderer() CAreaOrderer::CAreaOrderer()
:m_top_level(make_shared<CInnerCurves>())
{ {
m_top_level = new CInnerCurves(NULL, NULL);
} }
void CAreaOrderer::Insert(CCurve* pcurve) void CAreaOrderer::Insert(shared_ptr<CCurve> pcurve)
{ {
CInnerCurves::area_orderer = this; CInnerCurves::area_orderer = this;

View File

@ -28,6 +28,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once #pragma once
#include <memory>
#include <list> #include <list>
#include <set> #include <set>
@ -36,30 +37,31 @@ class CCurve;
class CAreaOrderer; class CAreaOrderer;
class CInnerCurves class CInnerCurves: public std::enable_shared_from_this<CInnerCurves>
{ {
CInnerCurves* m_pOuter; std::shared_ptr<CInnerCurves> m_pOuter;
const CCurve* m_curve; // always empty if top level std::shared_ptr<CCurve> m_curve; // always empty if top level
std::set<CInnerCurves*> m_inner_curves; std::set<std::shared_ptr<CInnerCurves> > m_inner_curves;
CArea *m_unite_area; // new curves made by uniting are stored here std::shared_ptr<CArea> m_unite_area; // new curves made by uniting are stored here
public: public:
static CAreaOrderer* area_orderer; static CAreaOrderer* area_orderer;
CInnerCurves(CInnerCurves* pOuter, const CCurve* curve); CInnerCurves(std::shared_ptr<CInnerCurves> pOuter, std::shared_ptr<CCurve> curve);
CInnerCurves(){}
~CInnerCurves(); ~CInnerCurves();
void Insert(const CCurve* pcurve); void Insert(std::shared_ptr<CCurve> pcurve);
void GetArea(CArea &area, bool outside = true, bool use_curve = true)const; void GetArea(CArea &area, bool outside = true, bool use_curve = true);
void Unite(const CInnerCurves* c); void Unite(std::shared_ptr<CInnerCurves> c);
}; };
class CAreaOrderer class CAreaOrderer
{ {
public: public:
CInnerCurves* m_top_level; std::shared_ptr<CInnerCurves> m_top_level;
CAreaOrderer(); CAreaOrderer();
void Insert(CCurve* pcurve); void Insert(std::shared_ptr<CCurve> pcurve);
CArea ResultArea()const; CArea ResultArea()const;
}; };