libarea: added OffsetWithClipper function

Also added a few extra setting variables.

OffsetWithClipper perform offset operation using
ClipperLib::ClipperOffset.
This commit is contained in:
Zheng, Lei 2017-01-19 18:58:09 +08:00
parent 2a67c7f0ae
commit 9cf075a806
3 changed files with 66 additions and 10 deletions

View File

@ -10,7 +10,11 @@
double CArea::m_accuracy = 0.01; double CArea::m_accuracy = 0.01;
double CArea::m_units = 1.0; double CArea::m_units = 1.0;
bool CArea::m_clipper_simple = false;
double CArea::m_clipper_clean_distance = 0.0;
bool CArea::m_fit_arcs = true; bool CArea::m_fit_arcs = true;
int CArea::m_min_arc_points = 4;
int CArea::m_max_arc_points = 100;
double CArea::m_single_area_processing_length = 0.0; double CArea::m_single_area_processing_length = 0.0;
double CArea::m_processing_done = 0.0; double CArea::m_processing_done = 0.0;
bool CArea::m_please_abort = false; bool CArea::m_please_abort = false;

View File

@ -7,6 +7,7 @@
#define AREA_HEADER #define AREA_HEADER
#include "Curve.h" #include "Curve.h"
#include "clipper.hpp"
enum PocketMode enum PocketMode
{ {
@ -42,7 +43,11 @@ public:
std::list<CCurve> m_curves; std::list<CCurve> m_curves;
static double m_accuracy; static double m_accuracy;
static double m_units; // 1.0 for mm, 25.4 for inches. All points are multiplied by this before going to the engine static double m_units; // 1.0 for mm, 25.4 for inches. All points are multiplied by this before going to the engine
static bool m_clipper_simple;
static double m_clipper_clean_distance;
static bool m_fit_arcs; static bool m_fit_arcs;
static int m_min_arc_points;
static int m_max_arc_points;
static double m_processing_done; // 0.0 to 100.0, set inside MakeOnePocketCurve static double m_processing_done; // 0.0 to 100.0, set inside MakeOnePocketCurve
static double m_single_area_processing_length; static double m_single_area_processing_length;
static double m_after_MakeOffsets_length; static double m_after_MakeOffsets_length;
@ -50,6 +55,7 @@ public:
static double m_split_processing_length; static double m_split_processing_length;
static bool m_set_processing_length_in_split; static bool m_set_processing_length_in_split;
static bool m_please_abort; // the user sets this from another thread, to tell MakeOnePocketCurve to finish with no result. static bool m_please_abort; // the user sets this from another thread, to tell MakeOnePocketCurve to finish with no result.
static double m_clipper_scale;
void append(const CCurve& curve); void append(const CCurve& curve);
void Subtract(const CArea& a2); void Subtract(const CArea& a2);
@ -58,6 +64,11 @@ public:
static CArea UniteCurves(std::list<CCurve> &curves); static CArea UniteCurves(std::list<CCurve> &curves);
void Xor(const CArea& a2); void Xor(const CArea& a2);
void Offset(double inwards_value); void Offset(double inwards_value);
void OffsetWithClipper(double offset,
ClipperLib::JoinType joinType=ClipperLib::jtRound,
ClipperLib::EndType endType=ClipperLib::etOpenRound,
double miterLimit = 5.0,
double roundPrecision = 0.0);
void Thicken(double value); void Thicken(double value);
void FitArcs(); void FitArcs();
unsigned int num_curves(){return static_cast<int>(m_curves.size());} unsigned int num_curves(){return static_cast<int>(m_curves.size());}

View File

@ -12,7 +12,7 @@ using namespace ClipperLib;
bool CArea::HolesLinked(){ return false; } bool CArea::HolesLinked(){ return false; }
//static const double PI = 3.1415926535897932; //static const double PI = 3.1415926535897932;
static double Clipper4Factor = 10000.0; double CArea::m_clipper_scale = 10000.0;
class DoubleAreaPoint class DoubleAreaPoint
{ {
@ -20,8 +20,8 @@ public:
double X, Y; double X, Y;
DoubleAreaPoint(double x, double y){X = x; Y = y;} DoubleAreaPoint(double x, double y){X = x; Y = y;}
DoubleAreaPoint(const IntPoint& p){X = (double)(p.X) / Clipper4Factor; Y = (double)(p.Y) / Clipper4Factor;} DoubleAreaPoint(const IntPoint& p){X = (double)(p.X) / CArea::m_clipper_scale; Y = (double)(p.Y) / CArea::m_clipper_scale;}
IntPoint int_point(){return IntPoint((long64)(X * Clipper4Factor), (long64)(Y * Clipper4Factor));} IntPoint int_point(){return IntPoint((long64)(X * CArea::m_clipper_scale), (long64)(Y * CArea::m_clipper_scale));}
}; };
static std::list<DoubleAreaPoint> pts_for_AddVertex; static std::list<DoubleAreaPoint> pts_for_AddVertex;
@ -81,10 +81,10 @@ static void AddVertex(const CVertex& vertex, const CVertex* prev_vertex)
else else
Segments=(int)ceil(-phit/dphi); Segments=(int)ceil(-phit/dphi);
if (Segments < 1) if (Segments < CArea::m_min_arc_points)
Segments=1; Segments = CArea::m_min_arc_points;
if (Segments > 100) if (Segments > CArea::m_max_arc_points)
Segments=100; Segments=CArea::m_max_arc_points;
dphi=phit/(Segments); dphi=phit/(Segments);
@ -139,6 +139,7 @@ static void MakeLoop(const DoubleAreaPoint &pt0, const DoubleAreaPoint &pt1, con
static void OffsetWithLoops(const TPolyPolygon &pp, TPolyPolygon &pp_new, double inwards_value) static void OffsetWithLoops(const TPolyPolygon &pp, TPolyPolygon &pp_new, double inwards_value)
{ {
Clipper c; Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
bool inwards = (inwards_value > 0); bool inwards = (inwards_value > 0);
bool reverse = false; bool reverse = false;
@ -251,6 +252,7 @@ static void MakeObround(const Point &pt0, const CVertex &vt1, double radius)
static void OffsetSpansWithObrounds(const CArea& area, TPolyPolygon &pp_new, double radius) static void OffsetSpansWithObrounds(const CArea& area, TPolyPolygon &pp_new, double radius)
{ {
Clipper c; Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
for(std::list<CCurve>::const_iterator It = area.m_curves.begin(); It != area.m_curves.end(); It++) for(std::list<CCurve>::const_iterator It = area.m_curves.begin(); It != area.m_curves.end(); It++)
@ -355,8 +357,11 @@ static void MakePoly(const CCurve& curve, TPolygon &p)
} }
} }
static void SetFromResult( CCurve& curve, const TPolygon& p, bool reverse = true ) static void SetFromResult( CCurve& curve, TPolygon& p, bool reverse = true )
{ {
if(CArea::m_clipper_clean_distance >= Point::tolerance)
CleanPolygon(p,CArea::m_clipper_clean_distance);
for(unsigned int j = 0; j < p.size(); j++) for(unsigned int j = 0; j < p.size(); j++)
{ {
const IntPoint &pt = p[j]; const IntPoint &pt = p[j];
@ -372,14 +377,14 @@ static void SetFromResult( CCurve& curve, const TPolygon& p, bool reverse = true
if(CArea::m_fit_arcs)curve.FitArcs(); if(CArea::m_fit_arcs)curve.FitArcs();
} }
static void SetFromResult( CArea& area, const TPolyPolygon& pp, bool reverse = true ) static void SetFromResult( CArea& area, TPolyPolygon& pp, bool reverse = true )
{ {
// delete existing geometry // delete existing geometry
area.m_curves.clear(); area.m_curves.clear();
for(unsigned int i = 0; i < pp.size(); i++) for(unsigned int i = 0; i < pp.size(); i++)
{ {
const TPolygon& p = pp[i]; TPolygon& p = pp[i];
area.m_curves.push_back(CCurve()); area.m_curves.push_back(CCurve());
CCurve &curve = area.m_curves.back(); CCurve &curve = area.m_curves.back();
@ -390,6 +395,7 @@ static void SetFromResult( CArea& area, const TPolyPolygon& pp, bool reverse = t
void CArea::Subtract(const CArea& a2) void CArea::Subtract(const CArea& a2)
{ {
Clipper c; Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
TPolyPolygon pp1, pp2; TPolyPolygon pp1, pp2;
MakePolyPoly(*this, pp1); MakePolyPoly(*this, pp1);
MakePolyPoly(a2, pp2); MakePolyPoly(a2, pp2);
@ -403,6 +409,7 @@ void CArea::Subtract(const CArea& a2)
void CArea::Intersect(const CArea& a2) void CArea::Intersect(const CArea& a2)
{ {
Clipper c; Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
TPolyPolygon pp1, pp2; TPolyPolygon pp1, pp2;
MakePolyPoly(*this, pp1); MakePolyPoly(*this, pp1);
MakePolyPoly(a2, pp2); MakePolyPoly(a2, pp2);
@ -416,6 +423,7 @@ void CArea::Intersect(const CArea& a2)
void CArea::Union(const CArea& a2) void CArea::Union(const CArea& a2)
{ {
Clipper c; Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
TPolyPolygon pp1, pp2; TPolyPolygon pp1, pp2;
MakePolyPoly(*this, pp1); MakePolyPoly(*this, pp1);
MakePolyPoly(a2, pp2); MakePolyPoly(a2, pp2);
@ -430,6 +438,7 @@ void CArea::Union(const CArea& a2)
CArea CArea::UniteCurves(std::list<CCurve> &curves) CArea CArea::UniteCurves(std::list<CCurve> &curves)
{ {
Clipper c; Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
TPolyPolygon pp; TPolyPolygon pp;
@ -452,6 +461,7 @@ CArea CArea::UniteCurves(std::list<CCurve> &curves)
void CArea::Xor(const CArea& a2) void CArea::Xor(const CArea& a2)
{ {
Clipper c; Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
TPolyPolygon pp1, pp2; TPolyPolygon pp1, pp2;
MakePolyPoly(*this, pp1); MakePolyPoly(*this, pp1);
MakePolyPoly(a2, pp2); MakePolyPoly(a2, pp2);
@ -471,6 +481,37 @@ void CArea::Offset(double inwards_value)
this->Reorder(); this->Reorder();
} }
void CArea::OffsetWithClipper(double offset,
JoinType joinType/* =jtRound */,
EndType endType/* =etOpenRound */,
double miterLimit/* = 5.0 */,
double roundPrecision/* = 0.0 */)
{
offset *= m_units*m_clipper_scale;
if(roundPrecision == 0.0) {
// Clipper roundPrecision definition: https://goo.gl/4odfQh
double dphi=acos(1.0-m_accuracy*m_clipper_scale/fabs(offset));
int Segments=(int)ceil(PI/dphi);
if (Segments < 2*CArea::m_min_arc_points)
Segments = 2*CArea::m_min_arc_points;
if (Segments > CArea::m_max_arc_points)
Segments=CArea::m_max_arc_points;
dphi = PI/Segments;
roundPrecision = (1.0-cos(dphi))*fabs(offset);
}else
roundPrecision *= m_clipper_scale;
ClipperOffset clipper(miterLimit,roundPrecision);
TPolyPolygon pp, pp2;
MakePolyPoly(*this, pp, false);
int i=0;
for(const CCurve &c : m_curves)
clipper.AddPath(pp[i++],joinType,c.IsClosed()?etClosedPolygon:endType);
clipper.Execute(pp2,(long64)(offset));
SetFromResult(*this, pp2, false);
this->Reorder();
}
void CArea::Thicken(double value) void CArea::Thicken(double value)
{ {
TPolyPolygon pp; TPolyPolygon pp;