libarea: added OffsetWithClipper function
Also added a few extra setting variables. OffsetWithClipper perform offset operation using ClipperLib::ClipperOffset.
This commit is contained in:
parent
2a67c7f0ae
commit
9cf075a806
|
@ -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;
|
||||||
|
|
|
@ -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());}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user