libarea: added CArea::Clip to handle open wires

CArea::Clip enables ClipperLib open wire boolean operation as well as
other settings (PolyFillType) for closed wires.
This commit is contained in:
Zheng, Lei 2017-01-19 19:03:59 +08:00
parent b58e45a04c
commit a79013e7f3
3 changed files with 61 additions and 40 deletions

View File

@ -99,6 +99,13 @@ public:
CAREA_PARAM_DECLARE(short,min_arc_points);
CAREA_PARAM_DECLARE(short,max_arc_points);
CAREA_PARAM_DECLARE(double,clipper_scale);
// Following functions is add to operate on possible open curves
void PopulateClipper(ClipperLib::Clipper &c, ClipperLib::PolyType type) const;
void Clip(ClipperLib::ClipType op,
const CArea *a,
ClipperLib::PolyFillType subjFillType = ClipperLib::pftEvenOdd,
ClipperLib::PolyFillType clipFillType = ClipperLib::pftEvenOdd);
};
enum eOverlapType

View File

@ -298,48 +298,14 @@ static void OffsetSpansWithObrounds(const CArea& area, TPolyPolygon &pp_new, dou
}
}
static void MakePolyPoly( const CArea& area, TPolyPolygon &pp, bool reverse = true ){
pp.clear();
for(std::list<CCurve>::const_iterator It = area.m_curves.begin(); It != area.m_curves.end(); It++)
{
pts_for_AddVertex.clear();
const CCurve& curve = *It;
const CVertex* prev_vertex = NULL;
for(std::list<CVertex>::const_iterator It2 = curve.m_vertices.begin(); It2 != curve.m_vertices.end(); It2++)
{
const CVertex& vertex = *It2;
if(prev_vertex)AddVertex(vertex, prev_vertex);
prev_vertex = &vertex;
}
TPolygon p;
p.resize(pts_for_AddVertex.size());
if(reverse)
{
std::size_t i = pts_for_AddVertex.size() - 1;// clipper wants them the opposite way to CArea
for(std::list<DoubleAreaPoint>::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++, i--)
{
p[i] = It->int_point();
}
}
else
{
unsigned int i = 0;
for(std::list<DoubleAreaPoint>::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++, i++)
{
p[i] = It->int_point();
}
}
pp.push_back(p);
}
}
static void MakePoly(const CCurve& curve, TPolygon &p)
static void MakePoly(const CCurve& curve, TPolygon &p, bool reverse = false)
{
pts_for_AddVertex.clear();
const CVertex* prev_vertex = NULL;
if(!curve.m_vertices.size()) return;
if(!curve.IsClosed()) AddVertex(curve.m_vertices.front(),NULL);
for (std::list<CVertex>::const_iterator It2 = curve.m_vertices.begin(); It2 != curve.m_vertices.end(); It2++)
{
const CVertex& vertex = *It2;
@ -348,6 +314,15 @@ static void MakePoly(const CCurve& curve, TPolygon &p)
}
p.resize(pts_for_AddVertex.size());
if(reverse)
{
std::size_t i = pts_for_AddVertex.size() - 1;// clipper wants them the opposite way to CArea
for(std::list<DoubleAreaPoint>::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++, i--)
{
p[i] = It->int_point();
}
}
else
{
unsigned int i = 0;
for (std::list<DoubleAreaPoint>::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++, i++)
@ -357,6 +332,16 @@ static void MakePoly(const CCurve& curve, TPolygon &p)
}
}
static void MakePolyPoly( const CArea& area, TPolyPolygon &pp, bool reverse = true ){
pp.clear();
for(std::list<CCurve>::const_iterator It = area.m_curves.begin(); It != area.m_curves.end(); It++)
{
pp.push_back(TPolygon());
MakePoly(*It,pp.back(),reverse);
}
}
static void SetFromResult( CCurve& curve, TPolygon& p, bool reverse = true )
{
if(CArea::m_clipper_clean_distance >= Point::tolerance)
@ -481,6 +466,35 @@ void CArea::Offset(double inwards_value)
this->Reorder();
}
void CArea::PopulateClipper(Clipper &c, PolyType type) const
{
for (std::list<CCurve>::const_iterator It = m_curves.begin(); It != m_curves.end(); It++)
{
const CCurve &curve = *It;
bool closed = curve.IsClosed();
if(type == ptClip && !closed)
continue;
TPolygon p;
MakePoly(curve, p, false);
c.AddPath(p, type, closed);
}
}
void CArea::Clip(ClipType op, const CArea *a,
PolyFillType subjFillType,
PolyFillType clipFillType)
{
Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
PopulateClipper(c,ptSubject);
if(a) a->PopulateClipper(c,ptClip);
PolyTree tree;
c.Execute(op, tree, subjFillType,clipFillType);
TPolyPolygon solution;
PolyTreeToPaths(tree,solution);
SetFromResult(*this, solution);
}
void CArea::OffsetWithClipper(double offset,
JoinType joinType/* =jtRound */,
EndType endType/* =etOpenRound */,

View File

@ -44,7 +44,7 @@
//#define use_xyz
//use_lines: Enables line clipping. Adds a very minor cost to performance.
//#define use_lines
#define use_lines
//use_deprecated: Enables temporary support for the obsolete functions
//#define use_deprecated