Skip to content

Commit

Permalink
libarea: added OffsetWithClipper function
Browse files Browse the repository at this point in the history
Also added a few extra setting variables.

OffsetWithClipper perform offset operation using
ClipperLib::ClipperOffset.
  • Loading branch information
realthunder committed Jan 19, 2017
1 parent 2a67c7f commit 9cf075a
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 10 deletions.
4 changes: 4 additions & 0 deletions src/Mod/Path/libarea/Area.cpp
Expand Up @@ -10,7 +10,11 @@

double CArea::m_accuracy = 0.01;
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;
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_processing_done = 0.0;
bool CArea::m_please_abort = false;
Expand Down
11 changes: 11 additions & 0 deletions src/Mod/Path/libarea/Area.h
Expand Up @@ -7,6 +7,7 @@
#define AREA_HEADER

#include "Curve.h"
#include "clipper.hpp"

enum PocketMode
{
Expand Down Expand Up @@ -42,14 +43,19 @@ class CArea
std::list<CCurve> m_curves;
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 bool m_clipper_simple;
static double m_clipper_clean_distance;
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_single_area_processing_length;
static double m_after_MakeOffsets_length;
static double m_MakeOffsets_increment;
static double m_split_processing_length;
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 double m_clipper_scale;

void append(const CCurve& curve);
void Subtract(const CArea& a2);
Expand All @@ -58,6 +64,11 @@ class CArea
static CArea UniteCurves(std::list<CCurve> &curves);
void Xor(const CArea& a2);
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 FitArcs();
unsigned int num_curves(){return static_cast<int>(m_curves.size());}
Expand Down
61 changes: 51 additions & 10 deletions src/Mod/Path/libarea/AreaClipper.cpp
Expand Up @@ -12,16 +12,16 @@ using namespace ClipperLib;
bool CArea::HolesLinked(){ return false; }

//static const double PI = 3.1415926535897932;
static double Clipper4Factor = 10000.0;
double CArea::m_clipper_scale = 10000.0;

class DoubleAreaPoint
{
public:
double X, Y;

DoubleAreaPoint(double x, double y){X = x; Y = y;}
DoubleAreaPoint(const IntPoint& p){X = (double)(p.X) / Clipper4Factor; Y = (double)(p.Y) / Clipper4Factor;}
IntPoint int_point(){return IntPoint((long64)(X * Clipper4Factor), (long64)(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 * CArea::m_clipper_scale), (long64)(Y * CArea::m_clipper_scale));}
};

static std::list<DoubleAreaPoint> pts_for_AddVertex;
Expand Down Expand Up @@ -81,10 +81,10 @@ static void AddVertex(const CVertex& vertex, const CVertex* prev_vertex)
else
Segments=(int)ceil(-phit/dphi);

if (Segments < 1)
Segments=1;
if (Segments > 100)
Segments=100;
if (Segments < CArea::m_min_arc_points)
Segments = CArea::m_min_arc_points;
if (Segments > CArea::m_max_arc_points)
Segments=CArea::m_max_arc_points;

dphi=phit/(Segments);

Expand Down Expand Up @@ -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)
{
Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);

bool inwards = (inwards_value > 0);
bool reverse = false;
Expand Down Expand Up @@ -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)
{
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++)
Expand Down Expand Up @@ -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++)
{
const IntPoint &pt = p[j];
Expand All @@ -372,14 +377,14 @@ static void SetFromResult( CCurve& curve, const TPolygon& p, bool reverse = true
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
area.m_curves.clear();

for(unsigned int i = 0; i < pp.size(); i++)
{
const TPolygon& p = pp[i];
TPolygon& p = pp[i];

area.m_curves.push_back(CCurve());
CCurve &curve = area.m_curves.back();
Expand All @@ -390,6 +395,7 @@ static void SetFromResult( CArea& area, const TPolyPolygon& pp, bool reverse = t
void CArea::Subtract(const CArea& a2)
{
Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
TPolyPolygon pp1, pp2;
MakePolyPoly(*this, pp1);
MakePolyPoly(a2, pp2);
Expand All @@ -403,6 +409,7 @@ void CArea::Subtract(const CArea& a2)
void CArea::Intersect(const CArea& a2)
{
Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
TPolyPolygon pp1, pp2;
MakePolyPoly(*this, pp1);
MakePolyPoly(a2, pp2);
Expand All @@ -416,6 +423,7 @@ void CArea::Intersect(const CArea& a2)
void CArea::Union(const CArea& a2)
{
Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
TPolyPolygon pp1, pp2;
MakePolyPoly(*this, pp1);
MakePolyPoly(a2, pp2);
Expand All @@ -430,6 +438,7 @@ void CArea::Union(const CArea& a2)
CArea CArea::UniteCurves(std::list<CCurve> &curves)
{
Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);

TPolyPolygon pp;

Expand All @@ -452,6 +461,7 @@ CArea CArea::UniteCurves(std::list<CCurve> &curves)
void CArea::Xor(const CArea& a2)
{
Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
TPolyPolygon pp1, pp2;
MakePolyPoly(*this, pp1);
MakePolyPoly(a2, pp2);
Expand All @@ -471,6 +481,37 @@ void CArea::Offset(double inwards_value)
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)
{
TPolyPolygon pp;
Expand Down

0 comments on commit 9cf075a

Please sign in to comment.